日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法

發布時間:2023/12/9 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

From:?http://www.cnweblog.com/fly2700/archive/2012/02/23/319718.html

RFC3984是H.264的baseline碼流在RTP方式下傳輸的規范,這里只討論FU-A分包方式,以及從RTP包里面得到H.264數據和AAC數據的方法。

1、單個NAL包單元

12字節的RTP頭后面的就是音視頻數據,比較簡單。一個封裝單個NAL單元包到RTP的NAL單元流的RTP序號必須符合NAL單元的解碼順序。

2、FU-A的分片格式
數據比較大的H264視頻包,被RTP分片發送。12字節的RTP頭后面跟隨的就是FU-A分片:
FU indicator有以下格式:
????? +---------------+
????? |0|1|2|3|4|5|6|7|
????? +-+-+-+-+-+-+-+-+
????? |F|NRI|? Type?? |
????? +---------------+
?? FU指示字節的類型域 Type=28表示FU-A。。NRI域的值必須根據分片NAL單元的NRI域的值設置。
?
?? FU header的格式如下:
????? +---------------+
????? |0|1|2|3|4|5|6|7|
????? +-+-+-+-+-+-+-+-+
????? |S|E|R|? Type?? |
????? +---------------+
?? S: 1 bit
?? 當設置成1,開始位指示分片NAL單元的開始。當跟隨的FU荷載不是分片NAL單元荷載的開始,開始位設為0。
?? E: 1 bit
?? 當設置成1, 結束位指示分片NAL單元的結束,即, 荷載的最后字節也是分片NAL單元的最后一個字節。當跟隨的FU荷載不是分片NAL單元的最后分片,結束位設置為0。
?? R: 1 bit
?? 保留位必須設置為0,接收者必須忽略該位。
?? Type: 5 bits
?? NAL單元荷載類型定義見下表


表1.? 單元類型以及荷載結構總結
????? Type?? Packet????? Type name???????????????????????
????? ---------------------------------------------------------
????? 0????? undefined??????????????????????????????????? -
????? 1-23?? NAL unit??? Single NAL unit packet per H.264??
????? 24???? STAP-A???? Single-time aggregation packet????
????? 25???? STAP-B???? Single-time aggregation packet????
????? 26???? MTAP16??? Multi-time aggregation packet?????
????? 27???? MTAP24??? Multi-time aggregation packet?????
????? 28???? FU-A????? Fragmentation unit????????????????
????? 29???? FU-B????? Fragmentation unit?????????????????
????? 30-31? undefined??????????????????????????????????? -
3、拆包和解包

拆包:當編碼器在編碼時需要將原有一個NAL按照FU-A進行分片,原有的NAL的單元頭與分片后的FU-A的單元頭有如下關系:
原始的NAL頭的前三位為FU indicator的前三位,原始的NAL頭的后五位為FU header的后五位,FU indicator與FU header的剩余位數根據實際情況決定。
?
解包:當接收端收到FU-A的分片數據,需要將所有的分片包組合還原成原始的NAl包時,FU-A的單元頭與還原后的NAL的關系如下:
還原后的NAL頭的八位是由FU indicator的前三位加FU header的后五位組成,即:
nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f)

4、代碼實現

從RTP包里面得到H264視頻數據的方法:

?
?//?功能:解碼RTP?H.264視頻
?//?參數:1.RTP包緩沖地址?2.RTP包數據大小?3.H264輸出地址?4.輸出數據大小
?//?返回:true:表示一幀結束??false:FU-A分片未結束或幀未結束?
?
#define??RTP_HEADLEN?12?
?bool??UnpackRTPH264(?void???*??bufIn,??int??len,???void?**??pBufOut,???int???*??pOutLen)
?{
?????*?pOutLen??=???0?;
?????if??(len??<??RTP_HEADLEN)
?????{
?????????return???false?;
????}?

?
????unsigned??char?*??src??=??(unsigned??char?*?)bufIn??+??RTP_HEADLEN;
????unsigned??char??head1??=???*?src;?//?獲取第一個字節?
?
????unsigned??char??head2??=???*?(src?+?1?);?//?獲取第二個字節?
?
????unsigned??char??nal??=??head1??&???0x1f?;?//?獲取FU?indicator的類型域,?
?
????unsigned??char??flag??=??head2??&???0xe0?;?//?獲取FU?header的前三位,判斷當前是分包的開始、中間或結束?
?
????unsigned??char??nal_fua??=??(head1??&???0xe0?)??|??(head2??&???0x1f?);?//?FU_A?nal?
?
?????bool??bFinishFrame??=???false?;
?????if??(nal?==?0x1c?)?//?判斷NAL的類型為0x1c=28,說明是FU-A分片?
?
?????{?//?fu-a?
?
?????????if??(flag?==?0x80?)?//?開始?
?
?????????{
?????????????*?pBufOut??=??src?-?3?;
?????????????*?((?int?*?)(?*?pBufOut))??=???0x01000000??;?//?zyf:大模式會有問題?
?
?????????????*?((?char?*?)(?*?pBufOut)?+?4?)??=??nal_fua;
?????????????*??pOutLen??=??len??-??RTP_HEADLEN??+???3?;
????????}?

?????????else???if?(flag?==?0x40?)?//?結束?
?
?????????{
?????????????*?pBufOut??=??src?+?2?;
?????????????*??pOutLen??=??len??-??RTP_HEADLEN??-???2?;
????????}?

?????????else?//?中間?
?
?????????{
?????????????*?pBufOut??=??src?+?2?;
?????????????*??pOutLen??=??len??-??RTP_HEADLEN??-???2?;
????????}?

????}?

?????else?//?單包數據?
?
?????{
?????????*?pBufOut??=??src?-?4?;
?????????*?((?int?*?)(?*?pBufOut))??=???0x01000000?;?//?zyf:大模式會有問題?
?
?????????*??pOutLen??=??len??-??RTP_HEADLEN??+???4?;
????}?

?
????unsigned??char?*??bufTmp??=??(unsigned??char?*?)bufIn;
?????if??(bufTmp[?1?]??&???0x80?)
?????{
????????bFinishFrame??=???true?;?//?rtp?mark?
?
????}?

?????else?
??????{
????????bFinishFrame??=???false?;
????}?

?????return??bFinishFrame;
}?
??


從RTP包里面得到AAC音頻數據的方法:

//功能:解RTP?AAC音頻包,聲道和采樣頻率必須知道。
//參數:1.RTP包緩沖地址?2.RTP包數據大小?3.H264輸出地址?4.輸出數據大小
//返回:true:表示一幀結束??false:幀未結束?一般AAC音頻包比較小,沒有分片。
bool?UnpackRTPAAC(void?*?bufIn,?int?recvLen,?void**?pBufOut,??int*?pOutLen)
{
????unsigned?char*??bufRecv?=?(unsigned?char*)bufIn;
????//char?strFileName[20];
????
????unsigned?char?ADTS[]?=?{0xFF,?0xF1,?0x00,?0x00,?0x00,?0x00,?0xFC};?
????int?audioSamprate?=?32000;//音頻采樣率
????int?audioChannel?=?2;//音頻聲道?1或2
????int?audioBit?=?16;//16位?固定
????switch(audioSamprate)
????{
????case??16000:
????????ADTS[2]?=?0x60;
????????break;
????case??32000:
????????ADTS[2]?=?0x54;
????????break;
????case??44100:
????????ADTS[2]?=?0x50;
????????break;
????case??48000:
????????ADTS[2]?=?0x4C;
????????break;
????case??96000:
????????ADTS[2]?=?0x40;
????????break;
????default:
????????break;
????}

????ADTS[3]?=?(audioChannel==2)?0x80:0x40;

????int?len?=?recvLen?-?16?+?7;
????len?<<=?5;//8bit?*?2?-?11?=?5(headerSize?11bit)
????len?|=?0x1F;//5?bit????1????????????
????ADTS[4]?=?len>>8;
????ADTS[5]?=?len?&?0xFF;
????*pBufOut?=?(char*)bufIn+16-7;
????memcpy(*pBufOut,?ADTS,?sizeof(ADTS));
????*pOutLen?=?recvLen?-?16?+?7;

????unsigned?char*?bufTmp?=?(unsigned?char*)bufIn;
????bool?bFinishFrame?=?false;
????if?(bufTmp[1]?&?0x80)
????{
????????//DebugTrace::D("Marker");
????????bFinishFrame?=?true;
????}

????else
????{
????????bFinishFrame?=?false;
????}

????return?true;
}

總結

以上是生活随笔為你收集整理的FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。