4412移植x264并且yuv422转x264(代码片段)

ch122633 ch122633     2023-01-10     474

关键词:

转自http://blog.sina.com.cn/s/blog_af9acfc60101alxx.html

一、YUV422转换规律 

  做视频采集与处理,自然少不了要学会分析YUV数据。因为从采集的角度来说,一般的视频采集芯片输出的码流一般都是YUV数据流的形式,而从视频处理(例如H.264、MPEG视频编解码)的角度来说,也是在原始YUV码流进行编码和解析,所以,了解如何分析YUV数据流对于做视频领域的人而言,至关重要。本文就是根据我的学习和了解,简单地介绍如何分析YUV数据流。

         YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。

        与我们熟知的RGB类似,YUV也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且,YUV不像RGB那样要求三个独立的视频信号同时传输,所以用YUV方式传送占用极少的频宽。

        好了,言归正传,谈谈如何分析YUV码流吧。YUV码流有多种不同的格式,要分析YUV码流,就必须搞清楚你面对的到底是哪一种格式,并且必须搞清楚这种格式的YUV采样和分布情况。下面我将介绍几种常用的YUV码流格式,供大家参考。

        YUV码流的存储格式其实与其采样的方式密切相关,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0,关于其详细原理,可以通过网上其它文章了解,这里我想强调的是如何根据其采样格式来从码流中还原每个像素点的YUV值,因为只有正确地还原了每个像素点的YUV值,才能通过YUV与RGB的转换公式提取出每个像素点的RGB值,然后显示出来。

1.1 YUV格式

为了方便后面叙述,图片的大小定 义为:w * h,宽高分别为w和h

YUV420格式

Y,后V,中间是U。其中的Y是w * h,U和V是w/2 * (h/2)

如果w = 4,h = 2,则:

yyyy

yyyy

uu

vv

内存则是:yyyyyyyyuuvv

需要占用的内存:w * h * 3 / 2

采样规律是:每个像素点都采样Y,寄数行采样1/2个U,不采样V,偶数行采样1/2个V,不采样U

YUV422格式

本格式使用较为广泛

每两个点为一组,共占用4个字节

YUYVYUYV…

对于每一组YUYV,前面一个Y和本组中的UV组成第一个点,第二个Y和本组中的UV组成第二个点

所以,在内存中,宽高分别为w * 2、h。

如果w = 4,h = 2,则:

YUYVYUYV

YUYVYUYV

需要占用的内存:w * h * 2

UYUY422格式

本格式和YUYV422一样,只是YUV的位置不一样罢了

每组中YUV的排列顺序为:UYUV

需要占用的内存:w * h * 2

 

YUV的采样格式及每种格式中单像素所占内 存大小

YUV主要的采样格式有YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和 YCbCr 4:4:4。

 

 采样格式       单像素所占内存大小        存放的码流

 

 YCbCr 4:4:4    3byte       Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3(4像素为例)

 

 YCbCr 4:2:2    2byte              Y0 U0 Y1 V1 Y2 U2 Y3 V3(4像素为例)

 

 YCbCr 4:2:0    1.5byte     Y0 U0 Y1 Y2 U2 Y3 Y5 V5 Y6 Y7 V7 Y8(8像素为例)

 

 YCbCr 4:1:1    1.5byte              Y0 U0 Y1 Y2 V2 Y3(4像素为例)

 

1.2  存储方式

    下面我用图的形式给出常见的YUV码流的存储方式,并在存储方式后面附有取样每个像素点的YUV数据的方法,其中,Cb、Cr的含义等同于U、V。

(1) YUVY 格式 (属于YUV422)
 
技术分享图片

   YUYV为YUV422采样的存储格式中的一种,相邻的两个Y共用其相邻的两个Cb、Cr,分析,对于像素点Y‘00、Y‘01 而言,其Cb、Cr的值均为 Cb00、Cr00,其他的像素点的YUV取值依次类推。

(2) UYVY 格式 (属于YUV422)

 技术分享图片

    UYVY格式也是YUV422采样的存储格式中的一种,只不过与YUYV不同的是UV的排列顺序不一样而已,还原其每个像素点的YUV值的方法与上面一样。

 (3) YUV422P(属于YUV422)

   YUV422P也属于YUV422的一种,它是一种Plane模式,即打包模式,并不是将YUV数据交错存储,而是先存放所有的Y分量,然后存储所有的U(Cb)分量,最后存储所有的V(Cr)分量,如上图所示。其每一个像素点的YUV值提取方法也是遵循YUV422格式的最基本提取方法,即两个Y共用一个UV。比如,对于像素点Y‘00、Y‘01 而言,其Cb、Cr的值均为 Cb00、Cr00。

 

二、移植x264

首先下载对应的源文件http://ftp.videolan.org/pub/videolan/x264/snapshots/

我选择了x264-snapshot-20181021-2245-stable.tar.bz2

tar jxvf x264-snapshot-20181021-2245-stable.tar.bz

./configure --host=arm-linux --prefix=/opt/wecam/ffmpeg --enable-shared --disable-asm

host:是要使用的平台
prefix:是make install的目录
enable-shared:是使能动态链接库
disable-asm:是关闭汇编命令

然后需要修改config.mak文件

技术分享图片

然后运行指令:

make
make install

然后在/opt/wecam/ffmpeg目录下就有了对应的文件:

技术分享图片

然后把libx264.so.155和pkgconfig目录放到4412开发板的/lib目录,再用指令创建软链接

ln -s libx264.so.155 libx264.so

而头文件x264.h是编译程序时需要使用的头文件

三、使用库编写YUV422转x264应用

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

#include "stdint.h"

#include "include/x264.h"

int main(int argc, char *argv[])

    int ret;
    int y_size;
    int i, j;

    if(argc != 3) 
        printf("usage: %s [source file] [dest file] 
", argv[0]);
        return -1;
    

    //source file
    FILE *fp_src = fopen(argv[1], "rb");
    FILE *fp_dst = fopen(argv[2], "wb");

    //Encode 0 frame
    int frame_num = 50;
    int csp = X264_CSP_I422;                //YUYV
    int width=640,height=480;               //640*480

    int iNal = 0;
    x264_nal_t *pNals = NULL;
    x264_t *pHandle = NULL;
    x264_picture_t *pPic_in = (x264_picture_t *)malloc(sizeof(x264_picture_t));
    x264_picture_t *pPic_out = (x264_picture_t *)malloc(sizeof(x264_picture_t));
    x264_param_t *pParam = (x264_param_t *)malloc(sizeof(x264_param_t));

    if(fp_src == NULL || fp_dst == NULL) 
        printf("Error open files.
");
        return -1;
    

    x264_param_default(pParam);
    pParam->i_width = width;
    pParam->i_height = height;
    pParam->i_csp = csp;
    x264_param_apply_profile(pParam, x264_profile_names[4]);
    pHandle = x264_encoder_open(pParam);

    x264_picture_init(pPic_out);
    x264_picture_alloc(pPic_in, csp, pParam->i_width, pParam->i_height);
    y_size = pParam->i_width * pParam->i_height;
    printf("w:%d h:%d
",pParam->i_width,pParam->i_height);

    //detect frame number
    if(frame_num == 0) 
        fseek(fp_src, 0, SEEK_END);
        switch(csp) 
            case X264_CSP_I444:
                frame_num = ftell(fp_src)/(y_size*3);
                break;
            case X264_CSP_I420:
                frame_num = ftell(fp_src)/(y_size*3/2);
                break;
            case X264_CSP_I422:
                frame_num = ftell(fp_src)/(y_size*2);
                break;
            default:
                printf("Colorspace Not Support.
");
                return -1;
        
        fseek(fp_src, 0, SEEK_SET);
    

    printf("frame_num:%d y_size:%d
",frame_num,y_size);
    //Loop to Encode
    for(i=0;i<frame_num;i++) 
        switch(csp) 
        case X264_CSP_I444:
            fread(pPic_in->img.plane[0], y_size, 1, fp_src);
            fread(pPic_in->img.plane[1], y_size, 1, fp_src);
            fread(pPic_in->img.plane[2], y_size, 1, fp_src);
            break;
        case X264_CSP_I420:
            fread(pPic_in->img.plane[0], y_size, 1, fp_src);
            fread(pPic_in->img.plane[1], y_size/4, 1, fp_src);
            fread(pPic_in->img.plane[2], y_size/4, 1, fp_src);
            break;
        case X264_CSP_I422:
            
                int index = 0;
                int y_i = 0, u_i = 0, v_i = 0;
                for(index = 0; index < y_size*2; ) 
                    fread(&pPic_in->img.plane[0][y_i++], 1, 1, fp_src);         //Y
                    index++;
                    fread(&pPic_in->img.plane[1][u_i++], 1, 1, fp_src);         //U
                    index++;
                    fread(&pPic_in->img.plane[0][y_i++], 1, 1, fp_src);         //Y
                    index++;
                    fread(&pPic_in->img.plane[2][v_i++], 1, 1, fp_src);         //V
                    index++;
                
                break;
            
        default:
            printf("Colorspace Not Support.
");
            return -1;
        

        pPic_in->i_pts = i;
        ret = x264_encoder_encode(pHandle, &pNals, &iNal, pPic_in, pPic_out);
        if(ret < 0) 
            printf("Error.
");
            return -1;
        

        printf("Succeed encode frame: %5d
", i);

        for(j=0;j<iNal;j++) 
            fwrite(pNals[j].p_payload, 1, pNals[j].i_payload, fp_dst);
            
    

    //flush encoder
    while(1) 
        ret = x264_encoder_encode(pHandle, &pNals, &iNal, NULL, pPic_out);
        if(ret == 0)
            break;
        printf("Flush 1 frame.
");
        for(j=0;j<iNal;j++)
            fwrite(pNals[j].p_payload, 1, pNals[j].i_payload, fp_dst);
    
    x264_picture_clean(pPic_in);
    x264_encoder_close(pHandle);
    pHandle = NULL;

    free(pPic_in);
    free(pPic_out);
    free(pParam);

    fclose(fp_src);
    fclose(fp_dst);

    return 0;

然后是Makefile文件

encode_h264:
        arm-none-linux-gnueabi-gcc encode_h264.c -o encode_h264 -L./lib/ -lx264
        cp encode_h264 /home/topeet/linux/camera/x264_code
clean:
        rm -f encode_h264

打完收工!







ffmpeg视频编解码demo初探(包含下载指定windows版本ffmpeg)将yuv图片序列作为流读入,编码封装成x264mp4视频(代码片段)

...个项目:将YUV图片序列作为流读入,编码封装成x264MP4视频将YUV图片序列编码成.h264文件将YUV图片序列编码成mp4文件第二个项目:将YUV图片序列作为流读入,编码封装成x264MP4视频将Y 查看详情

图解yuv444、yuv422、yuv420

参考技术A前段时间搞x264编码测试,传参的时候需要告诉编码器我的原始数据格式是什么,其中在x264.h头文件中定义了如下一堆类型。/*Colorspace``type*/#defineX264_CSP_MASK0x00ff/**/#defineX264_CSP_NONE0x0000/*Invalidmode*/#defineX264_CSP_I4000x0001/*monoc... 查看详情

YUV 422 转 PNG/JPG/

】YUV422转PNG/JPG/【英文标题】:YUV422toPNG/JPG/【发布时间】:2021-06-2913:42:51【问题描述】:在互联网上搜索了几天后,我正在寻找一种方法或程序来将YUV422格式拍摄的图片转换为可用的东西。PNG/BMP或JPG都可以。有人知道这样的工... 查看详情

vscode搭建x264源码调试环境(代码片段)

本节用到了上节Win10环境下编译和运行x264搭建的msys和mingw的环境使用的MSYS2MINGW64、gcc.exe、gdb.exe都是上一节搭建好的环境文章目录1.下载x2642.使用上一节介绍的方法为x264生成支持debug的x264.exe3.在VSCode中打开x264源码文件夹4.创建并... 查看详情

x264代码剖析:主函数main()解析函数parse()与编码函数encode()

x264代码剖析(三):主函数main()、解析函数parse()与编码函数encode()         x264的入口函数为main()。main()函数首先调用parse()解析输入的参数,然后调用encode()编码YUV数据。parse()首先调用x264_param_defa... 查看详情

如何等待 x264enc 在流尾编码缓冲帧

...题在于,尽管为x264enc指定了tune=zerolatency,但存在延迟,并且在将eos发送到管道时会截断输出视频。根 查看详情

blurayx264hd蓝光中的x264是啥意思呢?

BluRayx264HD蓝光中的X264是什么意思呢?在网络上搜索的高清资源经常有这种表示希望达人来解释一下==x264是一个开源库视频文件有很多种编码方式。比如说rmh264不同的格式同样画质大小不一样。目前比较小的有rm和h264。x264就是将y... 查看详情

02使用ffmpeg库,yuv420转h264编码

演示环境:CentOS7FFmpeg的H264编码,需要x264库支持[[email protected] ~]# wget ftp://ftp.videolan.org/pub/x264/snapshots/last_x264.tar.bz2[[email protected] ~]# tar xf las 查看详情

x264项目编译

】x264项目编译【英文标题】:Compilationofx264project【发布时间】:2016-06-1100:28:20【问题描述】:我已经下载了sourceofx264library。x264的版本是148。对于共享dll的编译,我使用以下命令MSYS环境:./configure--disable-cli--enable-shared--prefix=.结... 查看详情

ffmpeg与x264有什么区别?

ffmpeg是一个编解码库,功能丰富,其自带H.264解码功能,但是要实现H.264编码需要集成X264将其作为编码器参考文章:ffmpeg与x264差异? 查看详情

ffmpeg支持x264插件

1ffmpeg安装x264插件2要安装x264模块首先要先装nasm3安装脚本如下【复制即可使用】#!/bin/bashyum-yinstallepel-release &&yum-yinstallgitwget             &nb 查看详情

使用x264编码视频(代码片段)

使用X264编码视频环境准备使用gitclone下载x264源码https://www.videolan.org/developers/x264.html如果电脑之前没有安装过yasm,nasm可以使用brew安装一下brewinstallyasmbrewinstallnasm进入到工程根目录下编译//配置开启动态库,也可以不开启,... 查看详情

x264的版本号

0X264官方地扯  http://www.videolan.org/developers/x264.html1X264官方编译的二进制程序命名格式  官方编译出了LINUX,Win32,Win64等不同OS平台下可运行的版本,每个程序(举例x264-r2694-3b70645.exe)的名称以"-"分成三部分,第一部分为x264,第... 查看详情

如何阅读x264代码

...://www.cnblogs.com/xkfz007/articles/2616057.html 最近我也开始看X264的代码了,于是想到把我读代码的过程记录下来,因为总有很多新手问如何读代码,我这个帖子就是专为这些人写的。至于会读代码的人就完全没有必要看了。下面当... 查看详情

使用 x264 为 Android 构建 FFMPEG

】使用x264为Android构建FFMPEG【英文标题】:BuildFFMPEGwithx264forAndroid【发布时间】:2012-02-0710:17:06【问题描述】:我正在尝试使用libx264forAndroid构建FFMPEG。我可以成功构建和使用适用于Android的FFMPEG,但我意识到我需要编码能力,因... 查看详情

高清格式x264和h264有啥区别

分辨率都是1080P但是X264同样时长的片子体积都要小于H264不知两者有何区别1、意思不一X264:是ITU和MPEG联合制定的视频编码器。H264:是MPEG-4第十部分,是由高度压缩数字视频编解码格式。2、功能不一X264:包含有一些心理视觉增... 查看详情

vscode搭建x264源码调试环境(代码片段)

本节用到了上节Win10环境下编译和运行x264搭建的msys和mingw的环境使用的MSYS2MINGW64、gcc.exe、gdb.exe都是上一节搭建好的环境文章目录1.下载x2642.使用上一节介绍的方法为x264生成支持debug的x264.exe3.在VSCode中打开x264源码文件夹4.创建并... 查看详情

vscode搭建x264源码调试环境(代码片段)

本节用到了上节Win10环境下编译和运行x264搭建的msys和mingw的环境使用的MSYS2MINGW64、gcc.exe、gdb.exe都是上一节搭建好的环境文章目录1.下载x2642.使用上一节介绍的方法为x264生成支持debug的x264.exe3.在VSCode中打开x264源码文件夹4.创建并... 查看详情