MP4文件两种格式AVC1和H264的区别及利用FFMPEG demux为h264码流事项

(一)首先,从原理上了解一下这2种格式的区别:
AVC1 描述:H.264 bitstream without start codes.一般通过ffmpeg转码生成的视频,是不带起始码0×00000001的。
H264 描述:H.264 bitstream with start codes.一般对于一下HDVD等电影的压制格式,是带有起始码0×00000001的。
来源文档:http://msdn.microsoft.com/zh-cn/library/dd757808(v=vs.85).aspx
(二)其次,通过VLC播放器,可以查看到具体的格式。打开视频后,通过菜单【工具】/【编解码信息】可以查看到【编解码器】具体格式,举例如下,编解码器信息:
编码: H264 – MPEG-4 AVC (part 10) (avc1)
编码: H264 – MPEG-4 AVC (part 10) (h264)

(三)最后,分享一下ffmpeg demux MP4文件后,转换视频流为live555可直接使用的h264 ES流的经验和方法:

针对(avc1),av_read_frame后,取前四个字节为长度,把前四字节直接替换为0×00,0×00,0×00,0×01即可,但注意每个frame可以有多个NAUL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
AVPacket pkt;
AVPacket* packet = &pkt;
av_init_packet(packet);
av_read_frame(ctx, packet);

if(packet->stream_index == 0)
{//is video stream

const char start_code[4] = { 0, 0, 0, 1 };
if(is_avc_ || memcmp(start_code, packet->data, 4) != 0)
{//is avc1 code, have no start code of H264
int len = 0;
uint8_t *p = packet->data;

is_avc_ = True;
do
{//add start_code for each NAL, one frame may have multi NALs.

len = ntohl(*((long*)p));
memcpy(p, start_code, 4);

p += 4;
p += len;
if(p >= packet->data + packet->size)
{
break;
}
} while (1);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
bsfc_ = av_bitstream_filter_init("h264_mp4toannexb");

if(pkt->stream_index == 0)
{//is video stream

AVBitStreamFilterContext* bsfc = bsfc_;
int a;
while (bsfc) {
AVPacket new_pkt = *pkt;
a = av_bitstream_filter_filter(bsfc, encode_ctx_, NULL,
&new_pkt.data, &new_pkt.size,
pkt->data, pkt->size,
pkt->flags & AV_PKT_FLAG_KEY);
if(a == 0 && new_pkt.data != pkt->data && new_pkt.destruct) {
uint8_t *t = (uint8_t*)(new_pkt.size + FF_INPUT_BUFFER_PADDING_SIZE); //the new should be a subset of the old so cannot overflow
if(t) {
memcpy(t, new_pkt.data, new_pkt.size);
memset(t + new_pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
new_pkt.data = t;
a = 1;
} else
a = AVERROR(ENOMEM);
}
if (a > 0 && pkt->data != new_pkt.data) {
av_free_packet(pkt);
new_pkt.destruct = av_destruct_packet;
} else if (a < 0) {
envir() << "!!!!!!!!!!av_bitstream_filter_filter failed" << ",res=" << a << "\n";
}
*pkt = new_pkt;

bsfc = bsfc->next;
}
}