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

轉自:http://blog.csdn.net/leixiaohua1020/article/details/11800877


在使用FFMPEG的類庫進行編程的過程中,可以直接輸出解複用之後的的視頻數據碼流。只需要在每次調用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);  

經過以上兩步處理之後,我們就得到了可以正常播放的H.264碼流


還可以參考雷神另一篇文章

http://blog.csdn.net/leixiaohua1020/article/details/39767055


發佈了41 篇原創文章 · 獲贊 17 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章