=====================================================
FFmpeg簡單使用:過濾器 ---- h264_mp4toannexb
FFmpeg簡單使用:解封裝h264 ---- 提取SPS PPS
=====================================================
H264有兩種封裝方式:字節流AnnexB格式 AVCC格式。
1. AnnexB格式 ---- 用於實時播放
開始前綴(00000001或000001)+NALU數據 絕大部分編碼器的默認輸出格式
一共有兩種起始碼start_code
①3字節0x000001 單幀多slice(即單幀多個NALU)之間間隔
②4字節0x00000001 幀之間,或者SPS等之前
4字節類型的開始碼在在連續的數據傳輸中非常有用,因為用字節來對齊、分割流數據,比如:用連續的31個bit0后接一個bit1來分割流數據,是很容易的。
AnnexB格式每個NALU都包含起始碼,且通常會周期性的在關鍵幀之前重復SPS和PPS
👉👉👉所以解碼器可以從視頻流隨機點開始進行解碼,實時的流格式
2. AVCC格式 ---- 用於存儲
AVCC格式不使用起始碼作為NALU的分界,這種格式在每個NALU前都加上一個大端格式的前綴(1、2、4字節,代表NALU長度)
所以在解析AVCC格式的時候需要將指定的前綴字節數的值保存在一個頭部對象中,這個都通常稱為extradata或者sequence header。同時,SPS和PPS數據也需要保存在extradata或者叫’sequence header’中。
3.AVPacket數據格式
AVPacket中的data格式是:size(4個字節)+ nalu + size(4個字節)+ nalu,一個packet可能會存在多個nalu,前面size表示nalu的大小(不包含自身)
圖1.
如圖1所示,前4個字節表示:第一個nalu大小是0x52d = 1325, 總的pkt的大小是66736。表示存在多個nalu。下一個nalu位置:0x7dc0 + 0x025d + 4 = 0x8021,如圖2所示
圖2.
4.AVPacket轉換為 AnnexB,使用h264_mp4toannexb
編碼:
// 1 獲取相應的比特流過濾器 // FLV/MP4/MKV等結構中,h264需要h264_mp4toannexb處理。添加SPS/PPS等信息。 // FLV封裝時,可以把多個NALU放在一個VIDEO TAG中,結構為4B NALU長度+NALU1+4B NALU長度+NALU2+..., // 需要做的處理把4B長度換成00000001或者000001 // annexb模式: startcode 00000001 AVCC模式: 無startcode (mp4 flv mkv) const AVBitStreamFilter *bsfilter = av_bsf_get_by_name("h264_mp4toannexb"); AVBSFContext *bsf_ctx = NULL; // 2 初始化過濾器上下文 av_bsf_alloc(bsfilter, &bsf_ctx); //AVBSFContext; // 3 添加解碼器屬性 avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->codecpar); av_bsf_init(bsf_ctx);
// 4 發送和接受if (av_bsf_send_packet(bsf_ctx, pkt) != 0) // bitstreamfilter內部去維護內存空間 { av_packet_unref(pkt); // 你不用了就把資源釋放掉 continue; // 繼續送 } av_packet_unref(pkt); // 釋放資源 while(av_bsf_receive_packet(bsf_ctx, pkt) == 0) { out_pkt_count++; // printf("fwrite size:%d\n", pkt->size); av_packet_unref(pkt); }
我們看看filter之后的數據:
圖3.
我們可以看到,和圖1相比size變為00 00 00 01.下面我們看下一幀
圖4.
我們可以看到,下一個並不是簡單變為00 00 00 01,而是插入了一個nalu,再下一個nalu(f885位置),才是之前的nalu。我們分析一下中間插入的nalu,看第一下第一個字節表示nalu header.
NALU header格式:
0x67:
F:0 默認為0
R :11 表示這個幀很重要
T:7 表示SPS,到這里可以看出,插入了一個filter