- 計算 AVCDecoderConfigurationRecord 得到 CodecPrivateData 數(shù)據(jù)(只有第一幀需要);
- 計算 NALUs 得到幀數(shù)據(jù)。
計算 AVCDecoderConfigurationRecord 得到 CodecPrivateData 數(shù)據(jù) H.264 視頻流的 CodecPrivateData 實際上就是 AVCDecoderConfigurationRecord 中 SequenceParameterSets(SPS)和 PictureParameterSets(PPS)使用 byte[] {00, 00, 01} 連接的字節(jié)數(shù)組。 注意!FLV 文件中第一個 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 總是 AVCDecoderConfigurationRecord(在 ISO/IEC 14496-15 中定義),解碼的時候注意跳過這個 VIDOETAG。 AVCDecoderConfigurationRecord 結(jié)構(gòu)的定義: 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; } } 下面藍(lán)色的部分就是 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...... 根據(jù) AVCDecoderConfigurationRecord 結(jié)構(gòu)的定義: - configurationVersion = 01
- AVCProfileIndication = 4D
- profile_compatibility = 40
- AVCLevelIndication = 15
- lengthSizeMinusOne = FF <- 非常重要,是 H.264 視頻中 NALU 的長度,計算方法是 1 + (lengthSizeMinusOne & 3)
- numOfSequenceParameterSets = E1 <- SPS 的個數(shù),計算方法是 numOfSequenceParameterSets & 0x1F
- sequenceParameterSetLength = 00 0A <- SPS 的長度
- sequenceParameterSetNALUnits = 67 4D 40 15 96 53 01 00 4A 20 <- SPS
- numOfPictureParameterSets = 01 <- PPS 的個數(shù)
- pictureParameterSetLength = 00 05 <- PPS 的長度
- pictureParameterSetNALUnits = 68 E9 23 88 00 <- PPS
因此 CodecPrivateData 的字符串表示就是 000001674D4015965301004A2000000168E9238800 但是設(shè)置 MediaStreamAttributeKeys.CodecPrivateData 是沒用的(只有 H.264 是這樣,其他類型的視頻流仍然需要設(shè)置),只有將 CodecPrivateData 寫入 H.264 視頻流第一幀數(shù)據(jù)的前面 Silverlight 才能正常解碼。 也就是說,Silverlight 的 H.264 解碼器會讀取第一幀前面的 CodecPrivateData 數(shù)據(jù)來進(jìn)行配置。 因為 CodecPrivateData 數(shù)據(jù)已經(jīng)包含視頻流的解碼器參數(shù)(包括視頻的寬高),所以就不需要設(shè)置 MediaStreamAttributeKeys.CodecPrivateData、MediaStreamAttributeKeys.Width 和 MediaStreamAttributeKeys.Height 了。 計算 NALU 得到幀數(shù)據(jù) FLV 文件中 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 不是原始視頻幀數(shù)據(jù),而是一個或更多個 NALU 數(shù)據(jù)片段。在這篇文章中,你認(rèn)為 H.264 視頻幀數(shù)據(jù)是由多個 NALU 組成的。當(dāng)然實際上并不是這樣,關(guān)于這部分的概念請自行 Google,本文將不做討論。 下面是 FLV 文件中 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 屬性的數(shù)據(jù)(第一幀數(shù)據(jù))。 - 紅色的部分是 NALU 數(shù)據(jù)的長度,而紅色部分的長度則由 lengthSizeMinusOne 決定。
- 藍(lán)色的部分是 NALU 數(shù)據(jù)部分。
- 刪除的部分是廢棄的數(shù)據(jù)。
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.......?' 幀數(shù)據(jù)是將多個 NALU 使用 byte[] {00, 00, 01} 連接的字節(jié)數(shù)組。 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 }; 如果是第一幀數(shù)據(jù),那么前面還要加上 CodecPrivateData 數(shù)據(jù)。
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 };
|