Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Video S920(I420平面)格式的组织_Video_Webcam_Yuv - Fatal编程技术网

Video S920(I420平面)格式的组织

Video S920(I420平面)格式的组织,video,webcam,yuv,Video,Webcam,Yuv,目前,我正在使用一款支持3种格式的网络摄像头,该摄像头符合v4l2 ctl--list格式的要求: Index : 0 Type : Video Capture Pixel Format: 'S920' Name : GSPCA SN9C20X I420 Index : 1 Type : Video Capture Pixel Format: 'BA81' Name : 8-bit Bayer BGBG/GRGR

目前,我正在使用一款支持3种格式的网络摄像头,该摄像头符合
v4l2 ctl--list格式的要求

Index       : 0
Type        : Video Capture
Pixel Format: 'S920'
Name        : GSPCA SN9C20X I420

Index       : 1
Type        : Video Capture
Pixel Format: 'BA81'
Name        : 8-bit Bayer BGBG/GRGR

Index       : 2
Type        : Video Capture
Pixel Format: 'JPEG' (compressed)
Name        : JFIF JPEG
JPEG格式工作正常。 当我想使用I420原始数据时,问题就出现了。 我在做640x480。它确实返回正确的字节数。这是460800(640x480x1.5)。但经过一整天的实验,我仍然不知道它是如何组织的

看起来它以像素块的形式返回,即128(192字节)。 如果我覆盖cam,我可以看到前128(y分量)字节很小,然后是64个较大的字节。因此我假设它是128y,然后是32u和32v

下面是我在介绍网络摄像头时的一个示例
hextump-n200

0000000 2b2b 2c2b 2e2b 2e2d 2b2b 2c2b 2c2b 2d2c 
0000010 2b2b 2b2b 2b2a 2c2b 2b2b 2b2c 2b2a 2b2c 
0000020 2b2a 2c2b 2b2b 2b2b 2a2a 2b2b 2b2b 2b2c 
0000030 2a2a 2c2b 2b2b 2c2b 2b2c 2c2b 2b2b 2b2b 
0000040 2d2d 2c2c 2c2c 2d2c 2c2d 2c2d 2c2d 2c2c 
0000050 2c2c 2b2b 2c2c 2c2c 2c2c 2b2c 2c2c 2c2c 
0000060 2b2b 2b2b 2b2b 2c2b 2b2c 2c2c 2b2c 2c2c 
0000070 2c2b 2c2b 2c2b 2c2b 2b2b 2c2c 2c2d 2c2b 
0000080 7a7a 7b79 7c79 7a7a 7979 797a 797a 787a
0000090 7a7a 797a 7a77 797a 797a 797a 7978 797a 
00000a0 7e7e 7d7e 7f7e 7f7f 7e7e 7e7f 7e7f 7e7f 
00000b0 7d7e 7e7d 7e7e 7e7e 7e7f 7e7e 7e7e 7e7e
00000c0 2d2c 2c2c 2d2c 2f2d  
然而,经过反复试验,我仍然无法找到这些组件如何映射到整个640x480中。 我尝试将其转换为yuy2,如下所示:

y0 u0 y1 v0 y2 u0 y3 v0,y4 u1 y5 v1 y6 u1 y7 v1

但看起来不是。。 我在谷歌上搜索过,但没有看到很多人使用这种格式。有人有使用这种yuv格式的经验吗

更新: 我能得到的最接近的图像是使用16x8像素/块,因为S920输出128像素/块(我假设,基于我看到的模式)。经过反复试验,我认为16x8是最接近的。

嗯,这很有趣:-) 事实证明,GSPCA SN9C20X I42格式只是yuv420的一些变体,实际上是yuv420,但框架被分成了瓦片

我发现这是我正确的方向

输出图像如下所示

这是用于将其转换为IYUV的C代码,我从中获得,并使用一个主函数对其进行了轻微修改:

/*
 * Sonix SN9C20X decoder
 * Vasily Khoruzhick, (C) 2008-2009
 * Algorithm based on Java code written by Jens on microdia google group
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Note this code was originally licensed under the GNU GPL instead of the
 * GNU LGPL, its license has been changed by its author.
 */

//#include "libv4lconvert-priv.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>



#define DO_SANITY_CHECKS 0

static const int UVTranslate[32] = {0, 1, 2, 3,
            8, 9, 10, 11,
            16, 17, 18, 19,
            24, 25, 26, 27,
            4, 5, 6, 7,
            12, 13, 14, 15,
            20, 21, 22, 23,
            28, 29, 30, 31};

static const int Y_coords_624x[128][2] = {
{ 0,  0}, { 1,  0}, { 2,  0}, { 3,  0}, { 4,  0}, { 5,  0}, { 6,  0}, { 7,  0},
{ 0,  1}, { 1,  1}, { 2,  1}, { 3,  1}, { 4,  1}, { 5,  1}, { 6,  1}, { 7,  1},
{ 0,  2}, { 1,  2}, { 2,  2}, { 3,  2}, { 4,  2}, { 5,  2}, { 6,  2}, { 7,  2},
{ 0,  3}, { 1,  3}, { 2,  3}, { 3,  3}, { 4,  3}, { 5,  3}, { 6,  3}, { 7,  3},

{ 0,  4}, { 1,  4}, { 2,  4}, { 3,  4}, { 4,  4}, { 5,  4}, { 6,  4}, { 7,  4},
{ 0,  5}, { 1,  5}, { 2,  5}, { 3,  5}, { 4,  5}, { 5,  5}, { 6,  5}, { 7,  5},
{ 0,  6}, { 1,  6}, { 2,  6}, { 3,  6}, { 4,  6}, { 5,  6}, { 6,  6}, { 7,  6},
{ 0,  7}, { 1,  7}, { 2,  7}, { 3,  7}, { 4,  7}, { 5,  7}, { 6,  7}, { 7,  7},

{ 8,  0}, { 9,  0}, {10,  0}, {11,  0}, {12,  0}, {13,  0}, {14,  0}, {15,  0},
{ 8,  1}, { 9,  1}, {10,  1}, {11,  1}, {12,  1}, {13,  1}, {14,  1}, {15,  1},
{ 8,  2}, { 9,  2}, {10,  2}, {11,  2}, {12,  2}, {13,  2}, {14,  2}, {15,  2},
{ 8,  3}, { 9,  3}, {10,  3}, {11,  3}, {12,  3}, {13,  3}, {14,  3}, {15,  3},

{ 8,  4}, { 9,  4}, {10,  4}, {11,  4}, {12,  4}, {13,  4}, {14,  4}, {15,  4},
{ 8,  5}, { 9,  5}, {10,  5}, {11,  5}, {12,  5}, {13,  5}, {14,  5}, {15,  5},
{ 8,  6}, { 9,  6}, {10,  6}, {11,  6}, {12,  6}, {13,  6}, {14,  6}, {15,  6},
{ 8,  7}, { 9,  7}, {10,  7}, {11,  7}, {12,  7}, {13,  7}, {14,  7}, {15,  7}
};

static void do_write_u(const unsigned char *buf, unsigned char *ptr,
    int i, int j)
{
    *ptr = buf[i + 128 + j];
}

static void do_write_v(const unsigned char *buf, unsigned char *ptr,
    int i, int j)
{
    *ptr = buf[i + 160 + j];
}

void v4lconvert_sn9c20x_to_yuv420(const unsigned char *raw, unsigned char *i420,
  int width, int height, int yvu)
{
    int i = 0, x = 0, y = 0, j, relX, relY, x_div2, y_div2;
    const unsigned char *buf = raw;
    unsigned char *ptr;
    int frame_size = width * height;
    int frame_size_div2 = frame_size >> 1;
    int frame_size_div4 = frame_size >> 2;
    int width_div2 = width >> 1;
    int height_div2 = height >> 1;
    void (*do_write_uv1)(const unsigned char *buf, unsigned char *ptr, int i,
    int j) = NULL;
    void (*do_write_uv2)(const unsigned char *buf, unsigned char *ptr, int i,
    int j) = NULL;

    if (yvu) {
        do_write_uv1 = do_write_v;
        do_write_uv2 = do_write_u;
    }
    else {
        do_write_uv1 = do_write_u;
        do_write_uv2 = do_write_v;
    }

    while (i < (frame_size + frame_size_div2)) {
        for (j = 0; j < 128; j++) {
            relX = x + Y_coords_624x[j][0];
            relY = y + Y_coords_624x[j][1];

#if (DO_SANITY_CHECKS==1)
            if ((relX < width) && (relY < height)) {
#endif
                ptr = i420 + relY * width + relX;
                *ptr = buf[i + j];
#if (DO_SANITY_CHECKS==1)
            }
#endif

        }
        x_div2 = x >> 1;
        y_div2 = y >> 1;
        for (j = 0; j < 32; j++) {
            relX = (x_div2) + (j & 0x07);
            relY = (y_div2) + (j >> 3);

#if (DO_SANITY_CHECKS==1)
            if ((relX < width_div2) && (relY < height_div2)) {
#endif
                ptr = i420 + frame_size +
                    relY * width_div2 + relX;
                do_write_uv1(buf, ptr, i, j);
                ptr += frame_size_div4;
                do_write_uv2(buf, ptr, i, j);
#if (DO_SANITY_CHECKS==1)
            }
#endif
        }

        i += 192;
        x += 16;
        if (x >= width) {
            x = 0;
            y += 8;
        }
    }
}

int main(int argc, char** argv)
{
    int cnt;
    FILE* fd;
    size_t size = 640*480*3/2;

    fd = fopen(argv[1], "rb");
    if (!fd) {
        fprintf(stderr, "Error opening %s\n", argv[1]);
        return EXIT_FAILURE;
    }

    uint8_t* raw = malloc(size*sizeof(uint8_t));
    uint8_t* out = malloc(size*sizeof(uint8_t));

    if (!raw || !out) {
        goto cleanup;
    }

    fread(raw, sizeof(uint8_t), size, fd);
    fclose(fd);

    v4lconvert_sn9c20x_to_yuv420(raw, out, 640, 480, 0);

    fd = fopen("out_640x480.yuv", "wb");
    if (!fd) {
        fprintf(stderr, "Error opening %s\n", argv[1]);
        goto cleanup;
    }
    fwrite(out, sizeof(uint8_t), size, fd);

cleanup:
    free(raw);
    free(out);

    return EXIT_SUCCESS;
}
/*
*Sonix SN9C20X解码器
*瓦西里·霍鲁日克(C)2008-2009
*基于Jens在microdia google group上编写的Java代码的算法
*
*这个程序是自由软件;您可以重新分发和/或修改它
*它是根据GNU Lesser General Public License的条款发布的
*自由软件基金会;许可证的2.1版,或
*(由您选择)任何更高版本。
*
*这个节目的发布是希望它会有用,
*但无任何保证;甚至没有任何关于
*适销性或适合某一特定目的。见
*GNU Lesser通用公共许可证了解更多详细信息。
*
*您应该已经收到GNU Lesser通用公共许可证的副本
*与此同时,;如果没有,请写信给自由软件
*基金会,59寺庙广场,套房330,波士顿,MA 02111-1307美国
*
*注意:此代码最初是根据GNU GPL而不是
*GNU LGPL,其许可证已由其作者更改。
*/
//#包括“libv4lconvert-priv.h”
#包括
#包括
#包括
#定义DO_健全性检查0
静态常量int UVTranslate[32]={0,1,2,3,
8, 9, 10, 11,
16, 17, 18, 19,
24, 25, 26, 27,
4, 5, 6, 7,
12, 13, 14, 15,
20, 21, 22, 23,
28, 29, 30, 31};
静态常数int Y_coords_624x[128][2]={
{ 0,  0}, { 1,  0}, { 2,  0}, { 3,  0}, { 4,  0}, { 5,  0}, { 6,  0}, { 7,  0},
{ 0,  1}, { 1,  1}, { 2,  1}, { 3,  1}, { 4,  1}, { 5,  1}, { 6,  1}, { 7,  1},
{ 0,  2}, { 1,  2}, { 2,  2}, { 3,  2}, { 4,  2}, { 5,  2}, { 6,  2}, { 7,  2},
{ 0,  3}, { 1,  3}, { 2,  3}, { 3,  3}, { 4,  3}, { 5,  3}, { 6,  3}, { 7,  3},
{ 0,  4}, { 1,  4}, { 2,  4}, { 3,  4}, { 4,  4}, { 5,  4}, { 6,  4}, { 7,  4},
{ 0,  5}, { 1,  5}, { 2,  5}, { 3,  5}, { 4,  5}, { 5,  5}, { 6,  5}, { 7,  5},
{ 0,  6}, { 1,  6}, { 2,  6}, { 3,  6}, { 4,  6}, { 5,  6}, { 6,  6}, { 7,  6},
{ 0,  7}, { 1,  7}, { 2,  7}, { 3,  7}, { 4,  7}, { 5,  7}, { 6,  7}, { 7,  7},
{ 8,  0}, { 9,  0}, {10,  0}, {11,  0}, {12,  0}, {13,  0}, {14,  0}, {15,  0},
{ 8,  1}, { 9,  1}, {10,  1}, {11,  1}, {12,  1}, {13,  1}, {14,  1}, {15,  1},
{ 8,  2}, { 9,  2}, {10,  2}, {11,  2}, {12,  2}, {13,  2}, {14,  2}, {15,  2},
{ 8,  3}, { 9,  3}, {10,  3}, {11,  3}, {12,  3}, {13,  3}, {14,  3}, {15,  3},
{ 8,  4}, { 9,  4}, {10,  4}, {11,  4}, {12,  4}, {13,  4}, {14,  4}, {15,  4},
{ 8,  5}, { 9,  5}, {10,  5}, {11,  5}, {12,  5}, {13,  5}, {14,  5}, {15,  5},
{ 8,  6}, { 9,  6}, {10,  6}, {11,  6}, {12,  6}, {13,  6}, {14,  6}, {15,  6},
{ 8,  7}, { 9,  7}, {10,  7}, {11,  7}, {12,  7}, {13,  7}, {14,  7}, {15,  7}
};
静态void do_write_(常量unsigned char*buf,unsigned char*ptr,
int i,int j)
{
*ptr=buf[i+128+j];
}
静态void do_write_v(常量unsigned char*buf,unsigned char*ptr,
int i,int j)
{
*ptr=buf[i+160+j];
}
void v4l将\u sn9c20x\u转换为\u yuv420(常量无符号字符*原始,无符号字符*i420,
整数宽度、整数高度、整数yvu)
{
int i=0,x=0,y=0,j,relX,relY,x_div2,y_div2;
常量无符号字符*buf=raw;
无符号字符*ptr;
int frame_size=宽度*高度;
int frame\u size\u div2=frame\u size>>1;
int frame\u size\u div4=frame\u size>>2;
int width_div2=宽度>>1;
int height_div2=高度>>1;
void(*do_write_uv1)(常量无符号字符*buf,无符号字符*ptr,int i,
int j)=NULL;
void(*do_write_uv2)(常量无符号字符*buf,无符号字符*ptr,int i,
int j)=NULL;
如果(yvu){
do_write_uv1=do_write_v;
do_write_uv2=do_write_;
}
否则{
do_write_uv1=do_write_;
do_write_uv2=do_write_v;
}
而(i<(帧大小+帧大小2)){
对于(j=0;j<128;j++){
relX=x+Y_坐标系624x[j][0];
依赖=y+y_坐标系624x[j][1];
#如果(是否正常检查==1)
如果((相对高度<宽度)和((相对高度<高度)){
#恩迪夫
ptr=i420+RELN*宽度+relX;
*ptr=buf[i+j];
#如果(是否正常检查==1)
}
#恩迪夫
}
x_div2=x>>1;
y_div2=y>>1;
对于(j=0;j<32;j++){
relX=(x_div2)+(j&0x07);
依赖=(y_div2)+(j>>3);
#如果(