📄 rtp.c
字号:
else
{
if (LastPicID == sh->PictureID) // we are in the same picture
{
if (ExpectedMBNr == FirstMacroblockInSlice)
{
currSlice->partArr[0].bitstream->ei_flag = 0; // everything seems to be ok.
}
else
{
if (FirstMacroblockInSlice == 0)
{
assert ("weird! PicID wrap around? Should not happen\n");
}
else
{
//printf ("SLICE LOSS 1: Slice loss at PicID %d, macoblocks %d to %d\n",LastPicID, ExpectedMBNr, FirstMacroblockInSlice-1);
back=p->packlen+8;
fseek (bits, -back, SEEK_CUR);
//FirstMacroblockInSlice = (img->width*img->height)/(16*16);
currSlice->ei_flag = 1;
currSlice->dp_mode = PAR_DP_1;
currSlice->start_mb_nr = ExpectedMBNr;
//! just the same slice we just read!
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;
currSlice->partArr[0].bitstream->ei_flag=1;
img->tr = currSlice->picture_id = LastPicID;
return 0;
}
}
}
else // we are in a different picture
{
b_interval = (int)((float)(InfoSet.FrameSkip +1)/(float)(InfoSet.NumberBFrames +1) + 0.49999);
if (ExpectedMBNr == 0) // the old picture was finished
{
if (((last_pframe + InfoSet.FrameSkip +1)%256) == sh->PictureID &&
(bframe_to_code > InfoSet.NumberBFrames)) //! we received a new P-Frame and coded all B-Frames
{
if(InfoSet.NumberBFrames)
{
bframe_to_code = 1;
last_pframe = sh->PictureID-(InfoSet.FrameSkip +1);
}
else
last_pframe = sh->PictureID;
if(last_pframe < 0)
last_pframe += 256;
b_frame = FALSE;
}
else if(sh->PictureID == ((last_pframe + b_interval*bframe_to_code)%256) && InfoSet.NumberBFrames) //! we received a B-Frame
{
bframe_to_code ++;
b_frame = TRUE;
if(bframe_to_code > InfoSet.NumberBFrames)
last_pframe += (InfoSet.FrameSkip +1);
}
else //! we lost at least one whole frame
{
//printf ("SLICE LOSS 4: Slice loss at PicID %d containing the whole frame\n", LastPicID + InfoSet.FrameSkip +1);
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);
currSlice->partArr[0].readSyntaxElement = readSyntaxElement_RTP;
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;
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)
{
last_pframe = img->tr-(InfoSet.FrameSkip +1);
bframe_to_code = 1;
}
else
last_pframe = img->tr;
if(last_pframe < 0)
last_pframe += 256;
b_frame = FALSE;
img->pn++;
}
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);
}
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;
currSlice->partArr[0].readSyntaxElement = readSyntaxElement_RTP;
img->tr = currSlice->picture_id = sh->PictureID;
if(b_frame == FALSE) //! we expect a P-Frame
{
img->type = INTER_IMG_1;
img->pn++;
}
else
img->type = B_IMG_1;
return 0;
}
}
else //we did not finish the old frame
{
//upprintf ("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);
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;
currSlice->partArr[0].readSyntaxElement = readSyntaxElement_RTP;
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 || b_frame) // Full Slice Packet or B-Frame
{
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;
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 = MAX_QP-sh->InitialQP;
if (sh->SliceType==2) // SP Picture
{
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->InitialSPQP, &dummy);
bitptr+=len;
sh->InitialSPQP = MAX_QP-sh->InitialSPQP;
assert (sh->InitialSPQP >=MIN_QP && sh->InitialSPQP <= MAX_QP);
}
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 >=MIN_QP && sh->InitialQP <= MAX_QP);
if (ReadSliceId)
{
len = GetVLCSymbol(buf, bitptr, &info, bufsize);
linfo (len, info, &sh->SliceID, &dummy);
bitptr+=len;
}
/* KS: Multi-Picture Buffering Syntax */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -