FFmpeg跬步浅析——雷神《YUV编码为H.264》

    首先致敬雷神!这篇博客是基于雷神的《最简单的基于FFMPEG的视频编码器(YUV编码为H.264)ide

编写的,本身研究了两天终于算是明白了雷神的这个例子。如今分析给你们,若是有不对的地方但愿你们能函数

指正出来。学习

你们能够根据这个图中显示的object的关系来理解雷神的代码,下面说几处不太好理解的地方:编码

1)AVDictionary 结构体,这个结构体是用来设置ffmpeg中一些上下文的选项用的,key对应value,雷神的代码中有以下:spa

AVDictionary *param = 0;
    //H.264
    if(pCodecCtx->codec_id == AV_CODEC_ID_H264) {
        av_dict_set(param, "preset", "slow", 0);
        av_dict_set(param, "tune", "zerolatency", 0);
        //av_dict_set(param, "profile", "main", 0);
    }

       接着下面用param设置:.net

if (avcodec_open2(pCodecCtx, pCodec,param) < 0){
        printf("Failed to open encoder! \n");
        return -1;
    }

    ffmpeg中采用H264,H265标准编码时,可能须要设置preset、tune和profile,ffmpeg中须要采用额外参数AVDictionary传入avcodec_open2()函数中实现。avcodec_open2是用于初始化AVCodecContext的。能够在《X264.h》文件中 找到以下声明:code

static const char * const x264_tune_names[] = { "film", "animation",\
 "grain", "stillimage", "psnr", "ssim", "fastdecode", "zerolatency", 0 };

static const char * const x264_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", \
"fast", "medium", "slow", "slower", "veryslow", "placebo", 0 };

2)雷神的代码中故意体现出了ffmpeg中结构体的关系。orm

int flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index){
   ...
    if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
        CODEC_CAP_DELAY))
        return 0;
 
    }

    贯穿整个程序中的AVFormatContext 结构体与相关编码器的对应关系,AVFormatContext ->AVStream **streams[index]->AVCodecContext *codec->const struct AVCodec  *codec->。AVFormatContext 和AVCodecContext的对应关系是:AVFormatContext ->AVStream **streams[index]->AVCodecContext codec。视频

3)代码中有两处调用了avcodec_encode_video2,一处是在Main中,另一处是在flush_encoder中。我把flush_encoder调用注释掉了以后获得的文件《dsbk.h264》和不注释获得的文件《ds.h264》进行比较,如图:blog


    很显然注释掉的执行结果会比不注释的要小不少,紧接着对文件作了对比能够看到《ds.h264》结尾处比《dsbk.h264》多了不少数据,结合flush_encoder(冲刷编码)和对( capabilites & CODEC_CAP_DELAY )的理解得知,编码器在不断输入原始帧 输出编码包的过程当中是有延时的,即不是当即得出输出包的,因此在原始帧输入编码器结束后,须要将编码器内剩余的数据冲刷出来。


    结尾处想说点和本文无关的。首先雷神的精神值得咱们全部人学习,我如今只是一个小白,连入门都不算。但往往想要放弃的时候都会想到雷神那种不求回报、无私奉献的精神,还有那颗对技术和知识热爱、痴迷的初心,往往想到这些个人灵魂都在震撼,咱们生活在一个和平的年代和平的国家,对于咱们每一个工程师来说可能都有着不错的生活条件,在这样的状况下可能还会被生活或者工做的杂事烦心,为了一时的平衡、待遇影响着所思所想,这样是否是很好笑,善待身边的人,也善待本身,不要忘记那颗由于技术知识而欢乐的初心。