libavcodec/libx264不生成B帧 我正在编写一个C++应用程序,它使用LIVACODEC与LIBX264编码视频。然而,编码后的数据比我预期的要大得多。我分析了结果,发现我的编码从未产生B帧,只有I帧和P帧
我基于ffmpeg源代码和示例创建了一个独立的实用程序来测试我的编码器设置。它读入H.264文件,对解码帧进行重新编码,并使用ITU H.264附录B格式将结果输出到文件。我还使用ffmpeg执行相同的操作,以便与已知的良好实现进行比较。我的实用程序从不输出B帧,而ffmpeg则会输出 此后,我一直试图弄清楚ffmpeg做了什么,而我的代码没有。我首先尝试手动指定与B帧相关的编码器设置。这没有效果 然后,我尝试在gdb下运行ffmpeg和我的实用程序,并在打开编码器和手动设置任何看起来不同的字段之前比较AVStream、AVCODECTCONTEXT和X264Context的内容。即使使用相同的设置,我仍然只生成I帧和P帧 最后,我想可能是时间戳处理的问题。我修改了我的测试工具,以模拟ffmpeg使用的管道,并像ffmpeg那样输出时间戳调试输出。即使我的时间戳与ffmpeg相同,我仍然没有得到B帧 在这一点上,我不知道还有什么可以尝试。当我运行ffmpeg时,我使用下面的命令行运行它。请注意,除了“superfast”预设之外,我几乎使用默认值libavcodec/libx264不生成B帧 我正在编写一个C++应用程序,它使用LIVACODEC与LIBX264编码视频。然而,编码后的数据比我预期的要大得多。我分析了结果,发现我的编码从未产生B帧,只有I帧和P帧,c++,encoding,ffmpeg,libavcodec,libx264,C++,Encoding,Ffmpeg,Libavcodec,Libx264,我基于ffmpeg源代码和示例创建了一个独立的实用程序来测试我的编码器设置。它读入H.264文件,对解码帧进行重新编码,并使用ITU H.264附录B格式将结果输出到文件。我还使用ffmpeg执行相同的操作,以便与已知的良好实现进行比较。我的实用程序从不输出B帧,而ffmpeg则会输出 此后,我一直试图弄清楚ffmpeg做了什么,而我的代码没有。我首先尝试手动指定与B帧相关的编码器设置。这没有效果 然后,我尝试在gdb下运行ffmpeg和我的实用程序,并在打开编码器和手动设置任何看起来不同的字段
ffmpeg -v debug -i ~/annexb.264 -codec:v libx264 -preset superfast -g 30 -f h264 ./out.264
下面列出了配置编码器的代码。它还指定了“超高速”预设
static AVStream *add_video_stream(AVFormatContext *output_ctx, AVCodec **output_codec, enum AVCodecID codec_id)
{
*output_codec = avcodec_find_encoder(codec_id);
if (*output_codec == NULL) {
printf("Could not find encoder for '%s' (%d)\n", avcodec_get_name(codec_id), codec_id);
return NULL;
}
AVStream *output_stream = avformat_new_stream(output_ctx, *output_codec);
if (output_stream == NULL) {
printf("Could not create video stream.\n");
return NULL;
}
output_stream->id = output_ctx->nb_streams - 1;
AVCodecContext *codec_ctx = output_stream->codec;
avcodec_get_context_defaults3(codec_ctx, *output_codec);
codec_ctx->width = 1280;
codec_ctx->height = 720;
codec_ctx->time_base.den = 15000;
codec_ctx->time_base.num = 1001;
/* codec_ctx->gop_size = 30;*/
codec_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
// try to force B-frame output
/* codec_ctx->max_b_frames = 3;*/
/* codec_ctx->b_frame_strategy = 2;*/
output_stream->sample_aspect_ratio.num = 1;
output_stream->sample_aspect_ratio.den = 1;
codec_ctx->sample_aspect_ratio.num = 1;
codec_ctx->sample_aspect_ratio.den = 1;
codec_ctx->chroma_sample_location = AVCHROMA_LOC_LEFT;
codec_ctx->bits_per_raw_sample = 8;
if ((output_ctx->oformat->flags & AVFMT_GLOBALHEADER) != 0) {
codec_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
return output_stream;
}
int main(int argc, char **argv)
{
// ... open input file
avformat_alloc_output_context2(&output_ctx, NULL, "h264", output_path);
if (output_ctx == NULL) {
fprintf(stderr, "Unable to allocate output context.\n");
return 1;
}
AVCodec *output_codec = NULL;
output_stream = add_video_stream(output_ctx, &output_codec, output_ctx->oformat->video_codec);
if (output_stream == NULL) {
fprintf(stderr, "Error adding video stream to output context.\n");
return 1;
}
encode_ctx = output_stream->codec;
// seems to have no effect
#if 0
if (decode_ctx->extradata_size != 0) {
size_t extradata_size = decode_ctx->extradata_size;
printf("extradata_size: %zu\n", extradata_size);
encode_ctx->extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(encode_ctx->extradata, decode_ctx->extradata, extradata_size);
encode_ctx->extradata_size = extradata_size;
}
#endif // 0
AVDictionary *opts = NULL;
av_dict_set(&opts, "preset", "superfast", 0);
// av_dict_set(&opts, "threads", "auto", 0); // seems to have no effect
ret = avcodec_open2(encode_ctx, output_codec, &opts);
if (ret < 0) {
fprintf(stderr, "Unable to open output video cocec: %s\n", av_err2str(ret));
return 1;
}
// ... decoding/encoding loop, clean up, etc.
return 0;
}
静态AVStream*添加视频流(AVFormatContext*输出ctx、AVCodec**输出codec、枚举AVCodecID codecid)
{
*输出\u编解码器=avcodec\u查找\u编码器(编解码器\u id);
if(*output_codec==NULL){
printf(“找不到“%s”(%d)\n)、avcodec\u get\u名称(codec\u id)、codec\u id的编码器”;
返回NULL;
}
AVStream*output\U stream=avformat\U new\U stream(输出ctx,*输出编解码器);
if(输出_流==NULL){
printf(“无法创建视频流。\n”);
返回NULL;
}
output\u stream->id=output\u ctx->nb\u streams-1;
AVCodecContext*codec\u ctx=输出\u流->编解码器;
avcodec_get_context_defaults3(codec_ctx,*输出_codec);
编解码器ctx->宽度=1280;
编解码器ctx->高度=720;
编解码器\u ctx->time\u base.den=15000;
编解码器\u ctx->time\u base.num=1001;
/*codec_ctx->gop_size=30*/
codec_ctx->pix_fmt=AV_pix_fmt_YUVJ420P;
//尝试强制B帧输出
/*codec_ctx->max_b_帧=3*/
/*编解码器\u ctx->b\u帧\u策略=2*/
输出\u流->样本\u纵横比\u ratio.num=1;
输出流->样本长宽比.den=1;
codec\u ctx->sample\u aspect\u ratio.num=1;
codec\u ctx->sample\u aspect\u ratio.den=1;
编解码器\u ctx->色度\u采样\u位置=AVCHROMA\u LOC\u左;
编解码器ctx->每原始样本的比特数=8;
如果((输出ctx->oformat->flags&AVFMT\U GLOBALHEADER)!=0){
codec_ctx->flags |=codec_FLAG_GLOBAL_头;
}
返回输出流;
}
int main(int argc,字符**argv)
{
//…打开输入文件
avformat_alloc_output_context2(&output_ctx,NULL,“h264”,output_path);
如果(输出_ctx==NULL){
fprintf(stderr,“无法分配输出上下文。\n”);
返回1;
}
AVCodec*输出_codec=NULL;
输出流=添加视频流(输出ctx和输出编解码器,输出ctx->oformat->视频编解码器);
if(输出_流==NULL){
fprintf(stderr,“将视频流添加到输出上下文时出错。\n”);
返回1;
}
encode_ctx=输出_流->编解码器;
//似乎没有效果
#如果0
如果(解码\u ctx->外部数据\u大小!=0){
size\u t extradata\u size=解码\u ctx->extradata\u size;
printf(“外部数据大小:%zu\n”,外部数据大小);
encode_ctx->extradata=av_mallocz(extradata_size+FF_INPUT_BUFFER_PADDING_size);
memcpy(编码\u ctx->extradata,解码\u ctx->extradata,extradata\u size);
encode_ctx->extradata_size=extradata_size;
}
#endif//0
AVDictionary*opts=NULL;
视听记录集(&opts,“预设”、“超高速”,0);
//av_dict_set(&opts,“threads”,“auto”,0);//似乎没有效果
ret=avcodec_open2(编码、输出、编解码器和选项);
如果(ret<0){
fprintf(stderr,“无法打开输出视频coec:%s\n”,av_err2str(ret));
返回1;
}
//…解码/编码循环、清理等。
返回0;
}
我的测试实用程序生成以下调试输出,您可以在其中看到没有生成B帧:
[libx264 @ 0x1b8c9c0] using mv_range_thread = 56
[libx264 @ 0x1b8c9c0] using SAR=1/1
[libx264 @ 0x1b8c9c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[libx264 @ 0x1b8c9c0] profile High, level 3.1
Output #0, h264, to './out.264':
Stream #0:0, 0, 1/90000: Video: h264, yuvj420p, 1280x720 [SAR 1:1 DAR 16:9], 1001/15000, q=-1--1, 90k tbn, 14.99 tbc
<SNIP>
[libx264 @ 0x1b8c9c0] frame= 0 QP=17.22 NAL=3 Slice:I Poc:0 I:3600 P:0 SKIP:0 size=122837 bytes
[libx264 @ 0x1b8c9c0] frame= 1 QP=18.03 NAL=2 Slice:P Poc:2 I:411 P:1825 SKIP:1364 size=25863 bytes
[libx264 @ 0x1b8c9c0] frame= 2 QP=17.03 NAL=2 Slice:P Poc:4 I:369 P:2159 SKIP:1072 size=37880 bytes
[libx264 @ 0x1b8c9c0] frame= 3 QP=16.90 NAL=2 Slice:P Poc:6 I:498 P:2330 SKIP:772 size=50509 bytes
[libx264 @ 0x1b8c9c0] frame= 4 QP=16.68 NAL=2 Slice:P Poc:8 I:504 P:2233 SKIP:863 size=50791 bytes
[libx264 @ 0x1b8c9c0] frame= 5 QP=16.52 NAL=2 Slice:P Poc:10 I:513 P:2286 SKIP:801 size=51820 bytes
[libx264 @ 0x1b8c9c0] frame= 6 QP=16.49 NAL=2 Slice:P Poc:12 I:461 P:2293 SKIP:846 size=51311 bytes
[libx264 @ 0x1b8c9c0] frame= 7 QP=16.65 NAL=2 Slice:P Poc:14 I:476 P:2287 SKIP:837 size=51196 bytes
[libx264 @ 0x1b8c9c0] frame= 8 QP=16.66 NAL=2 Slice:P Poc:16 I:508 P:2240 SKIP:852 size=51577 bytes
[libx264 @ 0x1b8c9c0] frame= 9 QP=16.55 NAL=2 Slice:P Poc:18 I:477 P:2278 SKIP:845 size=51531 bytes
[libx264 @ 0x1b8c9c0] frame= 10 QP=16.67 NAL=2 Slice:P Poc:20 I:517 P:2233 SKIP:850 size=51946 bytes
<SNIP>
[libx264 @ 0x1b8c9c0] frame I:7 Avg QP:13.71 size:152207
[libx264 @ 0x1b8c9c0] frame P:190 Avg QP:16.66 size: 50949
[libx264 @ 0x1b8c9c0] mb I I16..4: 27.1% 30.8% 42.1%
[libx264 @ 0x1b8c9c0] mb P I16..4: 6.8% 6.0% 0.8% P16..4: 61.8% 0.0% 0.0% 0.0% 0.0% skip:24.7%
[libx264 @ 0x1b8c9c0] 8x8 transform intra:41.2% inter:86.9%
[libx264 @ 0x1b8c9c0] coded y,uvDC,uvAC intra: 92.2% 28.3% 5.4% inter: 50.3% 1.9% 0.0%
[libx264 @ 0x1b8c9c0] i16 v,h,dc,p: 7% 7% 77% 8%
[libx264 @ 0x1b8c9c0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 7% 15% 49% 6% 4% 3% 5% 3% 8%
[libx264 @ 0x1b8c9c0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 19% 25% 24% 6% 7% 4% 6% 3% 6%
[libx264 @ 0x1b8c9c0] i8c dc,h,v,p: 72% 14% 10% 4%
[libx264 @ 0x1b8c9c0] Weighted P-Frames: Y:0.0% UV:0.0%
[libx264 @ 0x1b8c9c0] kb/s:6539.11
[libx264@0x1b8c9c0]使用mv_range_thread=56
[libx264@0x1b8c9c0]使用SAR=1/1
[libx264@0x1b8c9c0]使用cpu功能:MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[libx264@0x1b8c9c0]配置文件高,级别3.1
输出#0,h264,到“./out.264”:
流#0:0,0,1/90000:视频:h264,yuvj420p,1280x720[SAR 1:1 DAR 16:9],1001/15000,q=-1--190K tbn,14.99 tbc
[libx264@0x1b8c9c0]帧=0 QP=17.22 NAL=3片:I Poc:0 I:3600 P:0跳过:0大小=122837字节
[libx264@0x1b8c9c0]帧=1 QP=18.03 NAL=2片:P Poc:2 I:411 P:1825跳过:1364大小=25863字节
[libx264@0x1b8c9c0]帧=2 QP=17.03 NAL=2片:P Poc:4 I:369 P:2159跳过:1072大小=37880字节
[libx264@0x1b8c9c0]帧=3 QP=16.90 NAL=2片:P Poc:6 I:498 P:2330跳过:772大小=50509字节
[libx264@0x1b8c9c0]帧=4 QP=16.68 NAL=2片:P Poc:8 I:504 P:2233跳过:863大小=50791字节
[libx264@0x1b8c9c0]帧=5 QP=16.52 NAL=2片:P Poc:10 I:513 P:2286跳过:801大小=51820字节
[libx264@0x1b8c9c0]帧=6 QP=16.49 NAL=2片:P Poc:12 I:461 P:2293跳过:846大小=51311字节
[libx264@0x1b8c9c0]frame=7 QP=16.65 NAL=2 Slice:P Poc:14 I:476 P:2287 SKIP:837 size=51196字节
[libx264@0x1b8c9c0]帧=8 QP=16.66 NAL=2片:P Poc:1
[libx264 @ 0x20b9c40] using mv_range_thread = 56
[libx264 @ 0x20b9c40] using SAR=1/1
[libx264 @ 0x20b9c40] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[libx264 @ 0x20b9c40] profile High, level 3.1
[h264 @ 0x20b8160] detected 4 logical cores
Output #0, h264, to './out.264':
Metadata:
encoder : Lavf54.63.104
Stream #0:0, 0, 1/90000: Video: h264, yuvj420p, 1280x720 [SAR 1:1 DAR 16:9], 1001/15000, q=-1--1, 90k tbn, 14.99 tbc
Stream mapping:
Stream #0:0 -> #0:0 (h264 -> libx264)
<SNIP>
[libx264 @ 0x20b9c40] frame= 0 QP=17.22 NAL=3 Slice:I Poc:0 I:3600 P:0 SKIP:0 size=122835 bytes
[libx264 @ 0x20b9c40] frame= 1 QP=18.75 NAL=2 Slice:P Poc:8 I:984 P:2045 SKIP:571 size=54208 bytes
[libx264 @ 0x20b9c40] frame= 2 QP=19.40 NAL=2 Slice:B Poc:4 I:447 P:1581 SKIP:1572 size=24930 bytes
[libx264 @ 0x20b9c40] frame= 3 QP=19.78 NAL=0 Slice:B Poc:2 I:199 P:1002 SKIP:2399 size=10717 bytes
[libx264 @ 0x20b9c40] frame= 4 QP=20.19 NAL=0 Slice:B Poc:6 I:204 P:1155 SKIP:2241 size=15937 bytes
[libx264 @ 0x20b9c40] frame= 5 QP=18.11 NAL=2 Slice:P Poc:16 I:990 P:2221 SKIP:389 size=64240 bytes
[libx264 @ 0x20b9c40] frame= 6 QP=19.35 NAL=2 Slice:B Poc:12 I:439 P:1784 SKIP:1377 size=34048 bytes
[libx264 @ 0x20b9c40] frame= 7 QP=19.88 NAL=0 Slice:B Poc:10 I:275 P:1035 SKIP:2290 size=16911 bytes
[libx264 @ 0x20b9c40] frame= 8 QP=19.91 NAL=0 Slice:B Poc:14 I:257 P:1270 SKIP:2073 size=19172 bytes
[libx264 @ 0x20b9c40] frame= 9 QP=17.90 NAL=2 Slice:P Poc:24 I:962 P:2204 SKIP:434 size=67439 bytes
[libx264 @ 0x20b9c40] frame= 10 QP=18.84 NAL=2 Slice:B Poc:20 I:474 P:1911 SKIP:1215 size=37742 bytes
<SNIP>
[libx264 @ 0x20b9c40] frame I:7 Avg QP:15.95 size:130124
[libx264 @ 0x20b9c40] frame P:52 Avg QP:17.78 size: 64787
[libx264 @ 0x20b9c40] frame B:138 Avg QP:19.32 size: 26231
[libx264 @ 0x20b9c40] consecutive B-frames: 6.6% 0.0% 0.0% 93.4%
[libx264 @ 0x20b9c40] mb I I16..4: 30.2% 35.2% 34.6%
[libx264 @ 0x20b9c40] mb P I16..4: 13.9% 11.4% 0.3% P16..4: 60.4% 0.0% 0.0% 0.0% 0.0% skip:13.9%
[libx264 @ 0x20b9c40] mb B I16..4: 5.7% 3.3% 0.0% B16..8: 15.8% 0.0% 0.0% direct:25.7% skip:49.5% L0:43.2% L1:37.3% BI:19.5%
[libx264 @ 0x20b9c40] 8x8 transform intra:39.4% inter:77.2%
[libx264 @ 0x20b9c40] coded y,uvDC,uvAC intra: 90.7% 26.6% 3.0% inter: 34.0% 4.1% 0.0%
[libx264 @ 0x20b9c40] i16 v,h,dc,p: 7% 7% 77% 9%
[libx264 @ 0x20b9c40] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 7% 16% 51% 5% 4% 3% 5% 3% 7%
[libx264 @ 0x20b9c40] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 22% 27% 20% 6% 6% 3% 6% 3% 6%
[libx264 @ 0x20b9c40] i8c dc,h,v,p: 71% 15% 11% 3%
[libx264 @ 0x20b9c40] Weighted P-Frames: Y:0.0% UV:0.0%
[libx264 @ 0x20b9c40] kb/s:4807.16