1. 程式人生 > >h264碼流rtp打包(一)

h264碼流rtp打包(一)

  一幀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封裝打包不需要字首碼,所以在進行

rfc3984_pack進行打包之前需提取nal

為了讓處理流程看起來比較順暢,我把幾個處理流程都寫在同一函式裡頭。

//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);
}