h264解碼時的AVCDecoderConfigurationRecord 與 CodecPrivateData

原文:http://www.cnblogs.com/k1988/archive/2010/06/08/2165642.html


  1. 計算 AVCDecoderConfigurationRecord  得到 CodecPrivateData 數據(只有第一幀需要);
  2. 計算 NALUs 得到幀數據。

 

計算 AVCDecoderConfigurationRecord  得到 CodecPrivateData 數據

H.264 視頻流的 CodecPrivateData 實際上就是 AVCDecoderConfigurationRecord 中 SequenceParameterSets(SPS)和 PictureParameterSets(PPS)使用 byte[] {00, 00, 01} 連接的字節數組。

注意!FLV 文件中第一個 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 總是 AVCDecoderConfigurationRecord(在 ISO/IEC 14496-15 中定義),解碼的時候注意跳過這個 VIDOETAG。

 

AVCDecoderConfigurationRecord 結構的定義:

aligned(8) class AVCDecoderConfigurationRecord {
unsigned int(8) configurationVersion = 1;
unsigned int(8) AVCProfileIndication;
unsigned int(8) profile_compatibility;
unsigned int(8) AVCLevelIndication;
bit(6) reserved = ‘111111’b;
unsigned int(2) lengthSizeMinusOne;
bit(3) reserved = ‘111’b;
unsigned int(5) numOfSequenceParameterSets;
for (i=0; i< numOfSequenceParameterSets; i++) {
unsigned int(16) sequenceParameterSetLength ;
bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
}
unsigned int(8) numOfPictureParameterSets;
for (i=0; i< numOfPictureParameterSets; i++) {
unsigned int(16) pictureParameterSetLength;
bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
}
}

 

下面藍色的部分就是 FLV 文件中的 AVCDecoderConfigurationRecord 部分。

00000130h: 00 00 00 17 00 00 00 00 01 4D 40 15 FF E1 00 0A ; .........M@.?.
00000140h: 67 4D 40 15 96 53 01 00 4A 20 01 00 05 68 E9 23 ; gM@.朣..J ...h?
00000150h: 88 00 00 00 00 2A 08 00 00 52 00 00 00 00 00 00 ; ?...*...R......

 

根據 AVCDecoderConfigurationRecord 結構的定義:

  • configurationVersion = 01
  • AVCProfileIndication = 4D
  • profile_compatibility = 40
  • AVCLevelIndication = 15
  • lengthSizeMinusOne = FF <- 非常重要,是 H.264 視頻中 NALU 的長度,計算方法是 1 + (lengthSizeMinusOne & 3)
  • numOfSequenceParameterSets = E1 <- SPS 的個數,計算方法是 numOfSequenceParameterSets & 0x1F
  • sequenceParameterSetLength = 00 0A <- SPS 的長度
  • sequenceParameterSetNALUnits = 67 4D 40 15 96 53 01 00 4A 20 <- SPS
  • numOfPictureParameterSets = 01 <- PPS 的個數
  • pictureParameterSetLength = 00 05 <- PPS 的長度
  • pictureParameterSetNALUnits = 68 E9 23 88 00 <- PPS

 

因此 CodecPrivateData 的字符串表示就是 000001674D4015965301004A2000000168E9238800

 

但是設置 MediaStreamAttributeKeys.CodecPrivateData 是沒用的(只有 H.264 是這樣,其他類型的視頻流仍然需要設置),只有將 CodecPrivateData 寫入 H.264 視頻流第一幀數據的前面 Silverlight 才能正常解碼。

也就是說,Silverlight 的 H.264 解碼器會讀取第一幀前面的 CodecPrivateData 數據來進行配置。

因爲 CodecPrivateData 數據已經包含視頻流的解碼器參數(包括視頻的寬高),所以就不需要設置 MediaStreamAttributeKeys.CodecPrivateData、MediaStreamAttributeKeys.Width 和 MediaStreamAttributeKeys.Height 了。

 

計算 NALU 得到幀數據

FLV 文件中 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 不是原始視頻幀數據,而是一個或更多個 NALU 數據片段。在這篇文章中,你認爲 H.264 視頻幀數據是由多個 NALU 組成的。當然實際上並不是這樣,關於這部分的概念請自行 Google,本文將不做討論。

 

下面是 FLV 文件中 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 屬性的數據(第一幀數據)。

  • 紅色的部分是 NALU 數據的長度,而紅色部分的長度則由 lengthSizeMinusOne 決定。
  • 藍色的部分是 NALU 數據部分。
  • 刪除的部分是廢棄的數據。

00000300h: 00 00 00 00 00 17 01 00 00 22 00 00 00 31 65 88 ; ........."...1e?
00000310h: 80 40 05 B7 95 53 67 FF 84 6C 07 EB 00 F8 45 FB ; €@.窌Sg刲.?鳨?
00000320h: F9 15 71 0D A4 C5 2C 00 00 03 00 00 03 00 3F 2B ; ?q.づ,.......?+
00000330h: 5B 06 57 48 29 F4 08 00 00 0A 10 02 D0 7A FE 00 ; [.WH)?.....衵?
00000340h: 00 00 38 65 01 22 22 01 00 17 B7 95 53 67 FF 84 ; ..8e.""...窌Sg?
00000350h: 6C 07 EB 00 F8 45 FB F9 15 71 0D A4 C5 2C 00 E8 ; l.?鳨.q.づ,.?
00000360h: F3 37 75 43 90 00 00 03 00 15 EF AA A8 53 86 01 ; ?uC?....錸⊿?
00000370h: DD 57 60 00 00 03 01 59 0C F4 3C 00 00 00 33 65 ; 軼`....Y.?...3e
00000380h: 00 90 88 80 40 05 B7 95 53 67 FF 84 6C 07 EB 00 ; .悎€@.窌Sg刲.?
00000390h: F8 45 FB F9 15 71 0D A4 C5 2C 00 00 03 00 00 03 ; 鳨.q.づ,......
000003a0h: 00 3F 2B 5B 06 57 48 29 F4 08 00 00 0A 10 02 D0 ; .?+[.WH)?.....?
000003b0h: 7A FE 00 00 00 38 65 00 D8 88 80 40 05 B7 95 53 ; z?..8e.貓€@.窌S
000003c0h: 67 FF 84 6C 07 EB 00 F8 45 FB F9 15 71 0D A4 C5 ; g刲.?鳨.q.づ
000003d0h: 2C 00 E8 F3 37 75 43 90 00 00 03 00 15 EF AA A8 ; ,.梵7uC?....錸?
000003e0h: 53 86 01 DD 57 60 00 00 03 01 59 0C F4 3C 00 00 ; S?軼`....Y.?..
000003f0h: 00 F4 08 00 01 33 00 00 17 00 00 00 00 AF 01 27 ; .?..3.......?'

 

幀數據是將多個 NALU 使用 byte[] {00, 00, 01} 連接的字節數組。

 

byte[] = {

00,00,01,65,88,
80,40,05,B7,95,53,67,FF,84,6C,07,EB,00,F8,45,FB,
F9,15,71,0D,A4,C5,2C,00,00,03,00,00,03,00,3F,2B,
5B,06,57,48,29,F4,08,00,00,0A,10,02,D0,7A,FE,

00,00,01,65,01,22,22,01,00,17,B7,95,53,67,FF,84,
6C,07,EB,00,F8,45,FB,F9,15,71,0D,A4,C5,2C,00,E8,
F3,37,75,43,90,00,00,03,00,15,EF,AA,A8,53,86,01,
DD,57,60,00,00,03,01,59,0C,F4,3C,

00,00,01,65,
00,90,88,80,40,05,B7,95,53,67,FF,84,6C,07,EB,00,
F8,45,FB,F9,15,71,0D,A4,C5,2C,00,00,03,00,00,03,
00,3F,2B,5B,06,57,48,29,F4,08,00,00,0A,10,02,D0,
7A,FE,

00,00,01,65,00,D8,88,80,40,05,B7,95,53,
67,FF,84,6C,07,EB,00,F8,45,FB,F9,15,71,0D,A4,C5,
2C,00,E8,F3,37,75,43,90,00,00,03,00,15,EF,AA,A8,
53,86,01,DD,57,60,00,00,03,01,59,0C,F4,3C

};


如果是第一幀數據,那麼前面還要加上 CodecPrivateData 數據。

 

byte[] = {

00,00,01,67,4D,40,15,96,53,01,00,4A,20,

00,00,01,68,E9,23,88,00,

00,00,01,65,88,
80,40,05,B7,95,53,67,FF,84,6C,07,EB,00,F8,45,FB,
F9,15,71,0D,A4,C5,2C,00,00,03,00,00,03,00,3F,2B,
5B,06,57,48,29,F4,08,00,00,0A,10,02,D0,7A,FE,

00,00,01,65,01,22,22,01,00,17,B7,95,53,67,FF,84,
6C,07,EB,00,F8,45,FB,F9,15,71,0D,A4,C5,2C,00,E8,
F3,37,75,43,90,00,00,03,00,15,EF,AA,A8,53,86,01,
DD,57,60,00,00,03,01,59,0C,F4,3C,

00,00,01,65,
00,90,88,80,40,05,B7,95,53,67,FF,84,6C,07,EB,00,
F8,45,FB,F9,15,71,0D,A4,C5,2C,00,00,03,00,00,03,
00,3F,2B,5B,06,57,48,29,F4,08,00,00,0A,10,02,D0,
7A,FE,

00,00,01,65,00,D8,88,80,40,05,B7,95,53,
67,FF,84,6C,07,EB,00,F8,45,FB,F9,15,71,0D,A4,C5,
2C,00,E8,F3,37,75,43,90,00,00,03,00,15,EF,AA,A8,
53,86,01,DD,57,60,00,00,03,01,59,0C,F4,3C

};


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