📄 rtp.c
字号:
else
last_pframe = sh->PictureID;
//! need to set the following for EC:
img->tr = sh->PictureID;
}
else if(sh->PictureID == last_pframe + b_interval*bframe_to_code && InfoSet.NumberBFrames) //! we received a B-Frame
{
//! This B-Frame is the one we expected but maybe parts of it are lost!
bframe_to_code ++;
if(bframe_to_code > InfoSet.NumberBFrames) //! last B-Frame before next P-Frame
last_pframe = (last_pframe+(InfoSet.FrameSkip +1))%256;
//! need to set the following for EC:
img->tr = sh->PictureID;
}
else //! we lost at least one whole frame
{
back=p->packlen+8; // Unread the packet
fseek (bits, -back, SEEK_CUR);
currSlice->ei_flag = 1;
currSlice->dp_mode = PAR_DP_1;
currSlice->start_mb_nr = ExpectedMBNr;
currSlice->next_header = RTPGetFollowingSliceHeader (img, nextp, nextsh);
assert (currSlice->start_mb_nr == img->current_mb_nr);
#if _ERROR_CONCEALMENT_
currSlice->last_mb_nr = img->max_mb_nr-1;
#else
currSlice->last_mb_nr = img->max_mb_nr;
#endif
currSlice->partArr[0].bitstream->bitstream_length=0;
currSlice->partArr[0].bitstream->read_len=0;
currSlice->partArr[0].bitstream->code_len=0;
//TO should be OK like this
img->pn++;
if(!InfoSet.NumberBFrames || (bframe_to_code > InfoSet.NumberBFrames)) //! we expect a P-Frame
{
img->tr = currSlice->picture_id = (last_pframe + InfoSet.FrameSkip +1)%256;
img->type = INTER_IMG_1;
if(InfoSet.NumberBFrames)
{
bframe_to_code = 1;
//! do not change last_pframe here
}
else
last_pframe = img->tr;
}
else //! we expect a B-Frame
{
img->tr = currSlice->picture_id = (last_pframe + b_interval*bframe_to_code)%256;
img->type = B_IMG_1;
bframe_to_code ++;
if(bframe_to_code > InfoSet.NumberBFrames)
last_pframe += (InfoSet.FrameSkip +1);
}
if(first)
{
img->pn = 0;
img->tr = 0;
}
first = FALSE;
return 0;
}
if(FirstMacroblockInSlice == 0)
{
currSlice->partArr[0].bitstream->ei_flag = 0; // everything seems to be ok.
}
else //! slice loss from the begining of the frame
{
// printf ("SLICE LOSS 2: Slice loss at PicID %d, beginning of picture to macroblock %d\n", LastPicID, FirstMacroblockInSlice);
back=p->packlen+8; // Unread the packet
fseek (bits, -back, SEEK_CUR);
currSlice->ei_flag = 1;
currSlice->dp_mode = PAR_DP_1;
currSlice->start_mb_nr = ExpectedMBNr;
currSlice->next_header = RTPGetFollowingSliceHeader (img, nextp, nextsh);
assert (currSlice->start_mb_nr == img->current_mb_nr);
#if _ERROR_CONCEALMENT_
currSlice->last_mb_nr = FirstMacroblockInSlice-1;
#else
currSlice->last_mb_nr = FirstMacroblockInSlice;
#endif
currSlice->partArr[0].bitstream->bitstream_length=0;
currSlice->partArr[0].bitstream->read_len=0;
currSlice->partArr[0].bitstream->code_len=0;
if(!InfoSet.NumberBFrames || (bframe_to_code > InfoSet.NumberBFrames)) //! we expect a P-Frame
{
img->type = INTER_IMG_1;
}
else //! we expect a B-Frame
{
img->type = B_IMG_1;
}
return 0;
}
}
else //we did not finish the old frame
{
// printf ("SLICE LOSS 3: Slice loss at PicID %d, macroblocks %d to end of picture\n", LastPicID, ExpectedMBNr);
back=p->packlen+8; // Unread the packet
fseek (bits, -back, SEEK_CUR);
ei_flag = 1;
currSlice->ei_flag = 1;
currSlice->dp_mode = PAR_DP_1;
currSlice->start_mb_nr = ExpectedMBNr;
currSlice->next_header = RTPGetFollowingSliceHeader (img, nextp, nextsh);
assert (currSlice->start_mb_nr == img->current_mb_nr);
#if _ERROR_CONCEALMENT_
currSlice->last_mb_nr = img->max_mb_nr-1;
#else
currSlice->last_mb_nr = img->max_mb_nr;
#endif
currSlice->partArr[0].bitstream->bitstream_length=0;
currSlice->partArr[0].bitstream->read_len=0;
currSlice->partArr[0].bitstream->code_len=0;
img->tr = currSlice->picture_id = LastPicID;
return 0;
}
}
// Here, all concealment is done and we have either a type A partition
// packet or a full slice packet, which need to be worked on
RTPUseParameterSet (sh->ParameterSet, img, inp);
RTPSetImgInp(img, inp, sh);
free_Partition (currSlice->partArr[0].bitstream);
assert (p->paylen-MBDataIndex > 0);
currSlice->partArr[0].bitstream->read_len = 0;
currSlice->partArr[0].bitstream->code_len = p->paylen-MBDataIndex; // neu
currSlice->partArr[0].bitstream->bitstream_length = p->paylen-MBDataIndex;
memcpy (currSlice->partArr[0].bitstream->streamBuffer, &p->payload[MBDataIndex],p->paylen-MBDataIndex);
buf = currSlice->partArr[0].bitstream->streamBuffer;
if(inp->symbol_mode == CABAC)
{
dep = &((currSlice->partArr[0]).de_cabac);
arideco_start_decoding(dep, buf, 0, &currSlice->partArr[0].bitstream->read_len);
}
currSlice->next_header = RTPGetFollowingSliceHeader (img, nextp, nextsh); // no use for the info in nextp, nextsh yet.
if ((p->payload[0]&0xf) == 0) // Full Slice Packet
{
currSlice->dp_mode = PAR_DP_1;
currSlice->max_part_nr=1;
return 1;
}
else
{
currSlice->dp_mode = PAR_DP_3;
currSlice->max_part_nr = 3;
printf ("Found A-Partition: PicId %d, SliceID %d \n",sh->PictureID, sh->SliceID);
RTPProcessDataPartitionedSlice (img, inp, bits, p, sh->SliceID);
return 3;
}
return FALSE;
}
/*!
*****************************************************************************
*
* \brief
* DecomposeRTPpacket interprets the RTP packet and writes the various
* structure members of the RTPpacket_t structure
*
* \return
* 0 in case of success
* negative error code in case of failure
*
* \para Parameters
* Caller is responsible to allocate enough memory for the generated payload
* in parameter->payload. Typically a malloc of paclen-12 bytes is sufficient
*
* \para Side effects
* none
*
* \para Other Notes
* Function contains assert() tests for debug purposes (consistency checks
* for RTP header fields)
*
* \date
* 30 Spetember 2001
*
* \author
* Stephan Wenger stewe@cs.tu-berlin.de
*****************************************************************************/
int DecomposeRTPpacket (RTPpacket_t *p)
{
// consistency check
assert (p->packlen < 65536 - 28); // IP, UDP headers
assert (p->packlen >= 12); // at least a complete RTP header
assert (p->payload != NULL);
assert (p->packet != NULL);
// Extract header information
p->v = p->packet[0] & 0x3;
p->p = (p->packet[0] & 0x4) >> 2;
p->x = (p->packet[0] & 0x8) >> 3;
p->cc = (p->packet[0] & 0xf0) >> 4;
p->m = p->packet[1] & 0x1;
p->pt = (p->packet[1] & 0xfe) >> 1;
p->seq = p->packet[2] | (p->packet[3] << 8);
memcpy (&p->timestamp, &p->packet[4], 4);// change to shifts for unified byte sex
memcpy (&p->ssrc, &p->packet[8], 4);// change to shifts for unified byte sex
// header consistency checks
if ( (p->v != 2)
|| (p->p != 0)
|| (p->x != 0)
|| (p->cc != 0) )
{
printf ("DecomposeRTPpacket, RTP header consistency problem, header follows\n");
DumpRTPHeader (p);
return -1;
}
p->paylen = p->packlen-12;
memcpy (p->payload, &p->packet[12], p->paylen);
return 0;
}
/*!
*****************************************************************************
*
* \brief
* DumpRTPHeader is a debug tool that dumps a human-readable interpretation
* of the RTP header
*
* \return
* n.a.
* \para Parameters
* the RTP packet to be dumped, after DecompositeRTPpacket()
*
* \para Side effects
* Debug output to stdout
*
* \date
* 30 Spetember 2001
*
* \author
* Stephan Wenger stewe@cs.tu-berlin.de
*****************************************************************************/
void DumpRTPHeader (RTPpacket_t *p)
{
int i;
for (i=0; i< 30; i++)
printf ("%02x ", p->packet[i]);
printf ("Version (V): %d\n", p->v);
printf ("Padding (P): %d\n", p->p);
printf ("Extension (X): %d\n", p->x);
printf ("CSRC count (CC): %d\n", p->cc);
printf ("Marker bit (M): %d\n", p->m);
printf ("Payload Type (PT): %d\n", p->pt);
printf ("Sequence Number: %d\n", p->seq);
printf ("Timestamp: %d\n", p->timestamp);
printf ("SSRC: %d\n", p->ssrc);
}
/*!
*****************************************************************************
*
* \brief
* Parses and interprets the UVLC-coded slice header
*
* \return
* negative in case of errors, the byte-index where the UVLC/CABAC MB data
* starts otherwise
*
* \date
* 27 October, 2001
*
* \author
* Stephan Wenger stewe@cs.tu-berlin.de
*****************************************************************************/
int RTPInterpretSliceHeader (byte *buf, int bufsize, int ReadSliceId, RTPSliceHeader_t *sh)
{
int len, info, bytes, dummy, bitptr=0;
int temp, tmp1;
RMPNIbuffer_t *tmp_rmpni,*tmp_rmpni2;
MMCObuffer_t *tmp_mmco,*tmp_mmco2;
int done;
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->ParameterSet, &dummy);
bitptr+=len;
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->PictureID, &dummy);
bitptr+=len;
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->SliceType, &dummy);
bitptr+=len;
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->FirstMBInSliceX, &dummy);
bitptr+=len;
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->FirstMBInSliceY, &dummy);
bitptr+=len;
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->InitialQP, &dummy);
bitptr+=len;
sh->InitialQP = 31-sh->InitialQP;
if (sh->SliceType==2) // SP Picture
{
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->InitialSPQP, &dummy);
bitptr+=len;
sh->InitialSPQP = 31-sh->InitialSPQP;
}
assert (sh->ParameterSet == 0); // only for testing, should be deleted as soon as more than one parameter set is generated by trhe encoder
assert (sh->SliceType > 0 || sh->SliceType < 5);
assert (sh->InitialQP >=0 && sh->InitialQP < 32);
assert (sh->InitialSPQP >=0 && sh->InitialSPQP < 32);
if (ReadSliceId)
{
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->SliceID, &dummy);
bitptr+=len;
}
/* KS: Multi-Picture Buffering Syntax */
/* Reference Picture Selection Flags */
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &temp, &dummy);
bitptr+=len;
/* Picture Number */
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->PictureNum, &dummy);
bitptr+=len;
/* Reference picture selection layer */
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &temp, &dummy);
bitptr+=len;
if (temp)
{
/* read Reference Picture Selection Layer */
// free old buffer content
while (sh->RMPNIbuffer)
{
tmp_rmpni=sh->RMPNIbuffer;
sh->RMPNIbuffer=tmp_rmpni->Next;
free (tmp_rmpni);
}
done=0;
/* if P or B frame RMPNI */
if ((sh->SliceType>=0)&&(sh->SliceType<=2))
{
do
{
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &tmp1, &dummy);
bitptr+=len;
// check for illegal values
if ((tmp1<0)||(tmp1>3))
error ("Invalid RMPNI operation specified",400);
if (tmp1!=3)
{
printf ("got RMPNI = %d\n",tmp1);
tmp_rmpni=(RMPNIbuffer_t*)calloc (1,sizeof (RMPNIbuffer_t));
tmp_rmpni->Next=NULL;
tmp_rmpni->RMPNI=tmp1;
// get the additional parameter
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &tmp_rmpni->Data, &dummy);
bitptr+=len;
// add RMPNI to list
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -