H.264中的SPS和PPS


參考http://blog.csdn.net/leixiaohua1020/article/details/11800877


H.264碼流第一個 NALU是 SPS(序列參數集Sequence Parameter Set)
對應H264標准文檔 7.3.2.1 序列參數集的語法進行解析

H.264碼流第二個 NALU是 PPS(圖像參數集Picture Parameter Set)
對應H264標准文檔 7.3.2.2 序列參數集的語法進行解析

H.264碼流第三個 NALU 是 IDR(即時解碼器刷新)
對應H264標准文檔 7.3.3 序列參數集的語法進行解析
H2.64中I幀和IDR幀的區別
   I和IDR幀都是使用幀內預測的它們都是同一個東西而已,在編碼和解碼中為了方便,要首個I幀和其他I幀區別開,所以才把第一個首個I幀叫IDR,這樣就方便控制編碼和解碼流程IDR幀的作用是立刻刷新,使錯誤不致傳播,從IDR幀開始,重新算一個新的序列開始編碼。而I幀不具有隨機訪問的能力,這個功能是由IDR承擔,IDR會導致DPB(參考幀列表——這是關鍵所在)清空,而I不會。IDR圖像一定是I圖像,但I圖像不一定是IDR圖像。一個序列中可以有很多的I圖像,I圖像之后的圖像可以引用I圖像之間的圖像做運動參考。一個序列中可以有很多的I圖像,I圖像之后的圖象可以引用I圖像之間的圖像做運動參考。
  對於IDR幀來說,在IDR幀之后的所有幀都不能引用任何IDR幀之前的幀的內容,與此相反,對於普通的I-幀來說,位於其之后的B-和P-幀可以引用位於普通I-幀之前的I-幀。從隨機存取的視頻流中,播放器永遠可以從一個IDR幀播放,因為在它之后沒有任何幀引用之前的幀。但是,不能在一個沒有IDR幀的視頻中從任意點開始播放,因為后面的幀總是會引用前面的幀。

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

如果視音頻復用格式是TS(MPEG2 Transport Stream),直接存儲后的文件是可以播放的。

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

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

1.分離某些封裝格式(例如MP4/FLV/MKV等)中的H.264的時候,需要首先寫入SPS和PPS,否則會導致分離出來的數據沒有SPS、PPS而無法播放。H.264碼流的SPS和PPS信息存儲在AVCodecContext結構體的extradata中。需要使用ffmpeg中名稱為“h264_mp4toannexb”的bitstream filter(比特流過濾器)處理。有兩種處理方式:

(1)使用bitstream filter處理每個AVPacket(簡單)

把每個AVPacket中的數據(data字段)經過bitstream filter“過濾”一遍。關鍵函數是av_bitstream_filter_filter()。示例代碼如下


上述代碼中,把av_bitstream_filter_filter()的輸入數據和輸出數據(分別對應第4,5,6,7個參數)都設置成AVPacket的data字段就可以了。

需要注意的是bitstream filter需要初始化和銷毀,分別通過函數av_bitstream_filter_init()和av_bitstream_filter_close()。

經過上述代碼處理之后,AVPacket中的數據有如下變化:

*每個AVPacket的data添加了H.264的NALU的起始碼{0,0,0,1}

*每個IDR幀數據前面添加了SPS和PPS

(2)手工添加SPS,PPS(稍微復雜)

將AVCodecContext的extradata數據經過bitstream filter處理之后得到SPS、PPS,拷貝至每個IDR幀之前。下面代碼示例了寫入SPS、PPS的過程。通過查看FFMPEG源代碼我們發現,AVPacket中的數據起始處沒有分隔符(0x00000001), 也不是0x65、0x67、0x68、0x41等字節,所以可以AVPacket肯定這不是標准的nalu。其實,AVPacket前4個字表示的是nalu的長度,從第5個字節開始才是nalu的數據。所以直接將AVPacket前4個字節替換為0x00000001即可得到標准的nalu數據。

具體代碼如下:



拷貝4個字節(0x00000001

當封裝格式為MPEG2TS的時候,不存在上述問題。

2、SPS和PPS

SDP中的H.264的SPS和PPS串,包含了初始化H.264解碼器所需要的信息參數,包括編碼所用的profile,level,圖像的寬和高,deblock濾波器等。
3、相關函數介紹
(1)av_bitstream_filter_init
輸入參數: 比特流過濾器的名字
輸出參數:根據比特流過濾器的創建並初始化一個比特流過濾器的上下文。

(2)av_bitstream_filter_filter
參數1:比特流過濾器的上下文
參數2:avcodeccontext輸出流的編碼器上下文.。
參數3:指定篩選器配置的參數,可能為空. 
參數4:指針被更新以指向過濾緩沖區. 
參數5:指針以字節形式更新到已過濾的緩沖區大小. 
參數6:包含數據到過濾器的緩沖區 
參數7:在字節緩沖區大小 
參數8:設置為非零,如果緩沖區對應於一個關鍵幀數據包




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM