视频处理学习笔记1:YUYV422、NV12和h264

最近因为工作关系在恶补视频相关知识点,在此做一记录便于日后复习。
以下均是个人学习经验总结,可能存在错误和坑,欢迎大佬指教。

工作中用到的是YUYV422存储格式。存储的就是裸流YUYV422格式文件。

YUYV422是两个像素点共用一个UV分量,每个像素点2byte,两个像素点也就是Y00 U00 Y01 V00,4byte,也就是Y、U、V每个分量各1byte。存储结构大致如下:

Y00 U00 Y01 V00   Y02 U01 Y03 V01   Y04 U02 Y05 V02   Y06 U03 Y07 V03   .......

Y10 U10 Y11 V10   Y12 U11 Y13 V11   Y14 U12 Y15 V02   Y16 U13 Y17 V13   .......

Y20 U20 Y21 V20   Y22 U21 Y23 V21   Y24 U22 Y25 V22   Y26 U23 Y27 V23   .......

Y30 U30 Y31 V30   Y32 U31 Y33 V31   Y34 U32 Y35 V02   Y36 U33 Y37 V33   .......

......

NV12是四个像素点共用一个UV分量,每个分量1byte。YUYV422转NV12后,存储结构大致如下:

Y00 Y01 Y02 Y03 Y04 Y05 Y06 Y07    .......

Y10 Y11 Y12 Y13 Y14 Y15 Y16 Y17    .......

Y20 Y21 Y22 Y23 Y24 Y25 Y26 Y27    .......

Y30 Y31 Y32 Y33 Y34 Y35 Y36 Y37    .......

U01 V01 U03 V03 U21 V21 U23 V23    .......

.......

以下是对应代码:

#include <stdio.h>

void yuyv422_to_nv12(char * image_in, char* image_out, int width, int height, unsigned long int filesize)
{
    /* 计算循环次数,YUYV 一个像素点占2个字节*/
    int pixNUM = width * height;
    unsigned int cycleNum = filesize /pixNUM/2;
    printf("cycleNUM = %d\n",cycleNum);
    
    /*单帧图像中 NV12格式的输出图像 Y分量 和 UV 分量的起始地址,并初始化*/
    char *y = image_out;
    char *uv = image_out + pixNUM ;

    char *start = image_in;
    unsigned int i =0; 
    int j =0,k =0;

    /*处理Y分量*/
    for(i= 0; i<cycleNum ;i++)
    {
        int index =0;
        for(j =0; j< pixNUM*2; j=j+2) //YUYV单行中每两个字节一个Y分量
        {
            *(y+index) = *(start + j);
            index ++;
        }
        start = image_in + pixNUM*2*i;
        y= y + pixNUM*3/2;
    }
      
    /**处理UV分量**/
    start = image_in;
    for(i= 0; i<cycleNum ;i++)
    {
        int uv_index = 0;
        for(j=0; j< height; j =j+2)  // 隔行, 我选择保留偶数行
        {
            for(k = j*width*2+1; k< width*2*(j+1); k=k+4) //YUYV单行中每四个字节含有一对UV分量
            {
                *(uv+ uv_index) = *(start + k);
                *(uv +uv_index+1) = *(start +k +2);
                uv_index += 2;
            }
        }
        start = image_in + pixNUM*2*i;
        uv =uv + pixNUM*3/2;
    }
}

int main(int argc, char **argv) {
    if (argc < 4) {
        printf("useage: %s [src] [width]x[height] [dst]\n", argv[0]);
        return -1;
    }

    int width;
    int height;
    sscanf(argv[2], "%dx%d", &width, &height);
    printf("width:%d height:%d \n",width, height);

    // int col = width;
    // int row = height;
    FILE* inFile = NULL;
    FILE* outFile = NULL;
    inFile = fopen(argv[1],"rb");
    if (inFile == NULL) {
        printf("open src error\n");
        return -1;
    }
    outFile = fopen(argv[3], "wb");
    if (outFile == NULL) {
        printf("open dst error\n");
        fclose(inFile);
        return -1;
    }

    char nv12Buf[height*width*3/2]={0};
    char yuyvBuf[width*height*2]={0};
    int frames = 0;
    while (!feof(inFile))
    {
        fread(yuyvBuf, sizeof(yuyvBuf), 1, inFile);
        yuyv422_to_nv12(yuyvBuf,nv12Buf, width, height, sizeof(yuyvBuf));
        fwrite(nv12Buf, width*height*3/2, 1, outFile);
        fflush(outFile);
        printf("frame:%d\n",++frames);
    }
    fclose(outFile);
    fclose(inFile);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值