標籤:
出自:http://www.mworkbox.com/wp/work/314.html2013-05-04
MP4的視頻H264封裝有2種格式:h264和avc1,對於這個細節,很容易被忽略。筆者也是在改編LIVE555流媒體時,增加mp4檔案類型支援時遇到了該問題。
(一)首先,從原理上瞭解一下這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:
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);
}
}
對於另外一種格式,(h264), 則直接對每個packet調用av_bitstream_filter_filter處理每個packet即可:
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;
}
}
(轉)MP4檔案兩種格式AVC1和H264的區別及利用FFMPEG demux為h264碼流事項