h264碼流rtp打包(一)
阿新 • • 發佈:2019-01-03
一幀image編碼完的資料儲存在h264buffer中,編碼後的h264碼流的大小為nH264Size
因為對於NALU,並不是一幀對應一個NALU,而是對於SLICE而言,一個slice就封裝層一個nal,所以一幀可以有多個slice,即一幀有多個nal。
具體一幀中有幾個nalu則是可以再pps中引數中進行設定的,每遇到一個IDR,則此時就將對應的SPS,PPS進行一個更新,NAL的生成過程:先是對header裡面的8個bits進行設定,然後是Payload。
對於位元組流編碼的碼流編碼,去掉每個slice前面的4個字首碼,就是nal的內容了。而對於rtp封裝打包不需要字首碼,所以在進行
為了讓處理流程看起來比較順暢,我把幾個處理流程都寫在同一函式裡頭。
//return value: number of the slice static int Frame_Slice_Nal_Pro(unsigned char *h264buffer, int nH264Size) { int i; int nSliceCount = -1; unsigned char *pcSliceBuffer[SLICE_NUM]; //儲存slice,去掉每個slice前面的4個字首碼,就是nal的內 容了。 int pnSliceSize[SLICE_NUM]; //每個slice的size,即每個nal的大小+4 for(i=0; i<nH264Size-4; i++) { unsigned char *src = h264buffer + i; //這裡是進行位元組流格式的碼流編碼,有開始4個字首碼,對於RTP封裝則不需要字首碼。 if( (*src == 0x00) && (*(src+1) == 0x00) && (*(src+2) == 0x00) && (*(src+3) == 0x01)) { nSliceCount++; pcSliceBuffer[nSliceCount] = src; pnSliceSize[nSliceCount] = 1; } else { if (nSliceCount >= 0) { pnSliceSize[nSliceCount]++; } } } if (nSliceCount >= 0) { pnSliceSize[nSliceCount] += 4; } //提取nal mblk_t *m; MSQueue *nalus; int i; int nNalNum = nSliceCount + 1; for(i=0; i<nNalNum; i++) { m = allocb(pnSliceSize[i] + 10, 0); //拷貝nal到mblk中,然後將mblk存於nalus佇列裡頭 memcpy(m->b_wptr, pcSliceBuffer[i] + 4, (pnSliceSize[i] - 4)); m->b_wptr += pnSliceSize[i] - 4; ms_queue_put(nalus,m); } .................. //rtp打包傳送出去 if(!ms_queue_empty(nalus)) rfc3984_pack(d->packer,nalus,f->outputs[0],ts); ............ return (nSliceCount + 1); }