FU-A分包方式,,以及從RTP包里面得到H.264數(shù)據(jù)和AAC數(shù)據(jù)的方法轉(zhuǎn)載自:http://www./fly2700/archive/2012/02/23/319718.html【原創(chuàng)】 1、單個NAL包單元 12字節(jié)的RTP頭后面的就是音視頻數(shù)據(jù),,比較簡單,。一個封裝單個NAL單元包到RTP的NAL單元流的RTP序號必須符合NAL單元的解碼順序。
拆包:當(dāng)編碼器在編碼時需要將原有一個NAL按照FU-A進(jìn)行分片,原有的NAL的單元頭與分片后的FU-A的單元頭有如下關(guān)系: 4,、代碼實現(xiàn) 從RTP包里面得到H264視頻數(shù)據(jù)的方法: // 功能:解碼RTP H.264視頻 // 參數(shù):1.RTP包緩沖地址 2.RTP包數(shù)據(jù)大小 3.H264輸出地址 4.輸出數(shù)據(jù)大小 // 返回:true:表示一幀結(jié)束 false:FU-A分片未結(jié)束或幀未結(jié)束 #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; // 獲取第一個字節(jié) unsigned char head2 = * (src + 1 ); // 獲取第二個字節(jié) unsigned char nal = head1 & 0x1f ; // 獲取FU indicator的類型域,, unsigned char flag = head2 & 0xe0 ; // 獲取FU header的前三位,,判斷當(dāng)前是分包的開始,、中間或結(jié)束 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 ) // 結(jié)束 { * pBufOut = src + 2 ; * pOutLen = len - RTP_HEADLEN - 2 ; } else // 中間 { * pBufOut = src + 2 ; * pOutLen = len - RTP_HEADLEN - 2 ; } } else // 單包數(shù)據(jù) { * 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音頻數(shù)據(jù)的方法: //功能:解RTP AAC音頻包,,聲道和采樣頻率必須知道,。 //參數(shù):1.RTP包緩沖地址 2.RTP包數(shù)據(jù)大小 3.H264輸出地址 4.輸出數(shù)據(jù)大小 //返回:true:表示一幀結(jié)束 false:幀未結(jié)束 一般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; } |
|