天天看點

使用FFMPEG類庫分離出多媒體檔案中的H.264碼流

av_read_frame()之後将得到的視訊的AVPacket存為本地檔案即可。

經試驗,在分離MPEG2碼流的時候,直接存儲AVPacket即可。

在分離H.264碼流的時候,直接存儲AVPacket後的檔案可能是不能播放的。

如果視音頻複用格式是TS(MPEG2 Transport Stream),直接存儲後的檔案是可以播放的。

複用格式是FLV,MP4則不行。

經過長時間資料搜尋發現,FLV,MP4這些屬于“特殊容器”,需要經過以下處理才能得到可播放的H.264碼流:

1.第一次存儲AVPacket之前需要在前面加上H.264的SPS和PPS。這些資訊存儲在AVCodecContext的extradata裡面。

并且需要使用FFMPEG中的名為"h264_mp4toannexb"的bitstream filter 進行處理。

然後将處理後的extradata存入檔案

具體代碼如下:

1. FILE *fp=fopen("test.264","ab");
2. AVCodecContext *pCodecCtx=...      
1. unsigned char *dummy=NULL;   //輸入的指針  
2. int dummy_len;  
3. AVBitStreamFilterContext* bsfc =  av_bitstream_filter_init("h264_mp4toannexb");    
4. av_bitstream_filter_filter(bsfc, pCodecCtx, NULL, &dummy, &dummy_len, NULL, 0, 0);  
5. fwrite(pCodecCtx->extradata,pCodecCtx-->extradata_size,1,fp);  
6. av_bitstream_filter_close(bsfc);    
7. free(dummy);      

2.通過檢視FFMPEG源代碼我們發現,AVPacket中的資料起始處沒有分隔符(0x00000001), 也不是0x65、0x67、0x68、0x41等位元組,是以可以AVPacket肯定這不是标準的nalu。其實,AVPacket前4個字表示的是nalu的長度,從第5個位元組開始才是nalu的資料。是以直接将AVPacket前4個位元組替換為0x00000001即可得到标準的nalu資料。

具體代碼如下:

1. char nal_start[]={0,0,0,1};  
2. fwrite(nal_start,4,1,fp);  
3. fwrite(pkt->data+4,pkt->size-4,1,fp);  
4. fclose(fp);