使用Intel media SDK寫死H264資料然後儲存成264檔案,用vlc播放失敗。
預設編碼是第一幀有IDR幀,後續都沒有I幀,這裡打開儲存的264檔案分析資料幀時發現其資料幀如下

從上圖中可以看到,第一個00 00 00 01 09可以判斷出是分界符的類型,第二個00 00 00 01 27是SPS,第三個00 00 00 01 28是PPS,第四個00 00 00 01 06是SEI,第五個00 00 01 25才是IDR。判斷類型補充如下,參考https://blog.csdn.net/jefry_xdz/article/details/8461343
我們還是接着看最上面圖的碼流對應的資料來層層分析,以00 00 00 01分割之後的下一個位元組就是NALU類型,将其轉為二進制資料後,解讀順序為從左往右算,如下:
(1)第1位禁止位,值為1表示文法出錯
(2)第2~3位為參考級别
(3)第4~8為是nal單元類型
例如上面00000001後有67,68以及65
其中0x67的二進制碼為:
0110 0111
4-8為00111,轉為十進制7,參考第二幅圖:7對應序列參數集SPS
其中0x68的二進制碼為:
0110 1000
4-8為01000,轉為十進制8,參考第二幅圖:8對應圖像參數集PPS
其中0x65的二進制碼為:
0110 0101
4-8為00101,轉為十進制5,參考第二幅圖:5對應IDR圖像中的片(I幀)
接着是後面的非IDR幀資料,如下圖
依次分别是0x00 00 00 01 09(分隔符)|| 0x00 00 00 01 28(PPS)|| 0x00 00 00 01 06(SEI)|| 0x00 00 01 21(非IDR)。
是以用vlc播放失敗的原因就在于這個分隔符,必須去掉這個分隔符才行。
Intel media SDK裡有個sample_encode指令行程式,在執行sample_encode.exe h264 -i out.yuv -o out.264 -w 544 -h 960 -PicTimingSEI:off的時候,發現仍然沒有去掉這個0x00 00 00 01 09(分隔符),通過參考https://blog.jianchihu.net/intel-media-sdk-remove-unused.html,發現在代碼裡pipeline_encode.cpp檔案裡添加m_CodingOption.AUDelimiter = MFX_CODINGOPTION_OFF;能去掉分隔符,如下:
//-PicTimingSEI:off添加這個選項pInParams->nPicTimingSEI就會為true
if (pInParams->nPicTimingSEI || pInParams->nNalHrdConformance || pInParams->nVuiNalHrdParameters)
{
//隻有進入到這裡通過設定bCodingOption為true,m_CodingOption的配置才能生效
m_CodingOption.PicTimingSEI = pInParams->nPicTimingSEI;
m_CodingOption.NalHrdConformance = pInParams->nNalHrdConformance;
m_CodingOption.VuiNalHrdParameters = pInParams->nVuiNalHrdParameters;
//這行代碼才是關鍵,很奇怪的是在inter media sdk說明文檔裡對這個測試程式的附加選項中沒有這個值的對應選項,目前隻能在代碼裡設定,不能通過指令行來設定
m_CodingOption.AUDelimiter = MFX_CODINGOPTION_OFF;
bCodingOption = true;
}
if (bCodingOption)
{
m_EncExtParams.push_back((mfxExtBuffer *)&m_CodingOption);
}