背景
====
我使用旧版的ffmpeg做转码, 但是apiexample.c不能解最新版ffmpeg的生成的mpeg1video, 虽然其他工具生成的可以。于是我想搞清楚是啥回事。
另一工具生成正常的可以解码:
$ ./apiexample.exe aaa.mpeg
Video decoding
fill_buffer 31505
code 1b3 code 1b8 code 100 code 101 code 1b7 mb 44/45 32/33 code 1b7
fill_buffer 0
xxsaving frame 0 linesze 752 376 376
ffmpeg 生成的不能解:
$ ./apiexample.exe huo.mpg
Video decoding
fill_buffer 30673
code 1b3 code 1b8 code 100 code 101 code 10e mb 49/50 12/38 code 11a mb 49/50 24/38 code ffffffff
fill_buffer 0
1. "code ffffffff" 表示code=-1没有找到形如0x00 00 01 xx的起始码。xx=
b3 -- sequence header, b8 -- group start, 00 -- picture start, 01-af slice start, b7 -- sequence end
2. 注意到slice多一个,我以为slice不能多,ffmpeg 我加上-slices 1 也不行,也试过 -g 0 都不行。
3. 观察上面的执行序列,第一个slice start 并没有立即mb, 而是接着遇到起始码才mb。
即每个slice start 的mb解码在该slice内容结束(即再次遇到起始码时)才开始。
仔细阅读代码,发现libavcodec 对于输入, 内部缓存,只有找到下一个起始码才开始:
input_size = s->buf_ptr - s->buffer;
mpeg_decode_slice(avctx, picture, start_code, s->buffer, input_size);
ffmpeg 追加结束码可以解码:
$ ./apiexample.exe huo.mpg
Video decoding
fill_buffer 30677
code 1b3 code 1b8 code 100 code 101 code 10e mb 49/50 12/38 code 11a mb 49/50 24/38 code 1b7 mb 49/50 37/38
fill_buffer 0
xxsaving frame 0 linesze 832 416 416
旧版移植代码加上:
{/*a raw mpeg1 video frame generated by: ffmpeg -i dragon.jpg -f mpeg1video -y dragon.mpg has no sequence end code, which will cause decode fail, so we append one here. --ludi 2014.08 */ unsigned char seq_end_code[] = {0x00, 0x00, 0x01, 0xb7}; memcpy(mpgbuf + mpglen, seq_end_code, sizeof(seq_end_code)); mpglen += sizeof(seq_end_code); }
特此纪念!