⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtp.c

📁 包含了从MPEG4的视频解码到H.264的视频编码部分的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:

//! The following two variables are used to calculate the size of a lost slice.
//! The NAL conveyes this "lost" slice to the VCL with the ei_flag set in order
//! to trigger concealment

static int LastPicID;       //! PicID of the last packet (current state of the decoder 
                            //! before reading the next packet      
static int ExpectedMBNr;    //! MB Nr of the last decoded MB


/*!
 ************************************************************************
 * \brief
 *    read all Partitions of one Slice from RTP packets
 * \return
 *    SOS if this is not a new frame                                    \n
 *    SOP if this is a new frame                                        \n
 *    EOS if end of sequence reached
 ************************************************************************
 */
int readSliceRTP (struct img_par *img, struct inp_par *inp)
{
  Slice *currSlice = img->currentSlice;
  int PartitionMask;
  static int CurrentPictureId = -1;

  assert (currSlice != NULL);

  PartitionMask = ReadRTPPacket (img, inp, bits);
/*
{
int i;
for (i=0; i<25; i++)
printf ("%02x ", currSlice->partArr[0].bitstream->streamBuffer[i]);
printf ("\n");
for (i=0; i<25; i++)
printf ("%02x ", currSlice->partArr[1].bitstream->streamBuffer[i]);
printf ("\n");
for (i=0; i<25; i++)
printf ("%02x ", currSlice->partArr[2].bitstream->streamBuffer[i]);
printf ("\n");
}
*/
  if(PartitionMask == -4711)
    return EOS;

  if(CurrentPictureId == currSlice->picture_id)
    return SOS;
  else
  {
    CurrentPictureId = currSlice->picture_id;
    return SOP;
  }
}

/*!
 ************************************************************************
 * \brief
 *    read all partitions of one slice from RTP packet stream, also handle
 *    any Parameter Update packets and SuUPP-Packets
 * \return
 *    -1 for EOF                                              \n
 *    Partition-Bitmask otherwise:
 *    Partition Bitmask: 0x1: Full Slice, 0x2: type A, 0x4: Type B 
 *                       0x8: Type C
 ************************************************************************
 */

// Note: this is the unchanged code from the FMO implementation in C092.
// Needs serious testing w/DP and stuff.

int ReadRTPPacket (struct img_par *img, struct inp_par *inp, FILE *bits)
{
  Slice *currSlice = img->currentSlice;
  DecodingEnvironmentPtr dep;
  byte *buf;
  RTPpacket_t *p, *nextp;
  RTPSliceHeader_t *sh, *nextsh;
  int MBDataIndex;
  int done = 0;
  int err;//, back=0; // avoid warnings. mwi
  int FirstMacroblockInSlice;
  static int b_frame = FALSE;

  // JVT-D101
  int done0 = 0; 
  static int first = 1; 
  // End JVT-D101

  assert (currSlice != NULL);
  assert (bits != 0);

  // Temporal storage for this function only

  p=alloca (sizeof (RTPpacket_t));      // the RTP packet
  p->packet=alloca (MAXRTPPACKETSIZE);
  p->payload=alloca (MAXRTPPAYLOADLEN);
  nextp=alloca (sizeof (RTPpacket_t));  
  sh=alloca(sizeof (RTPSliceHeader_t));
  sh->RMPNIbuffer=NULL;
  sh->MMCObuffer=NULL;

  nextsh=alloca(sizeof (RTPSliceHeader_t));
  nextsh->RMPNIbuffer=NULL;
  nextsh->MMCObuffer=NULL;

  ExpectedMBNr = img->current_mb_nr;
  LastPicID = img->tr;

  // JVT-D101
  done0 = 0;
  do
  {
  // End JVT-D101
    done = 0;
    do  
    {
      if (RTPReadPacket (p, bits) < 0)    // Read and decompose
        return -4711;

      if (p->payload[0] == (PAYLOAD_TYPE_IDERP<<4) && fb != NULL && frm != NULL )  // Tian Dong: IDERP, JVT-C083
      {
        reset_buffers();
        frm->picbuf_short[0]->used=0;
        frm->picbuf_short[0]->picID=-1;
        frm->picbuf_short[0]->lt_picID=-1;
        frm->short_used=0;
      }

      switch (p->payload[0] & 0xf)
      {
      case 0:       // Full Slice packet
      case 1:       // Partition type A packet
        done = 1;
        break;
 
      case 2:       // Partition B
      case 3:       // Partition C
        // Do nothing.  this results in discarding the unexpected Partition B, C
        // packet, which will later be concealed "automatically", because when
        // interpreting the next Partition A or full slice packet a range of
        // lost blocks is found which will be concealed in the usual manner.
        //
        // If anyonme comes up with an idea how to use coefficients without the
        // header information then this code has to be changed
        printf ("found unexpected Partition %c packet, skipping\n", (p->payload[0]&0xf)==2?'B':'C'); // avoid warnings. mwi
        break;
      case 4:
        // Tian Dong (Sept 2002)
        // The spare picture SEI messages are packetized in compound packet (known as aggregation packet now),
        // I will only deal with the compound packet composed by sei message and slice data.
        ProcessAggregationPacket(p, img);
        done = 1;
        break;
      case 5:
        //! Add implementation of SUPP packets here
        printf ("SUPP packets not yet implemented, skipped\n");
        break;
      case 6:
        printf ("Found header packet\n");

        if ((err = RTPInterpretParameterSetPacket (&p->payload[1], p->paylen-1)) < 0)
        {
          printf ("RTPInterpretParameterSetPacket returns error %d\n", err);
        }
        break;
      default:
        printf ("Undefined packet type %d found, skipped\n", p->payload[0] & 0xf);
        assert (0==1);
        break;
      }
    } while (!done);

    // Here, all the non-video data packets and lonely type B, C partitions
    // are handled.  Now work on the expected type A and full slice packets

    assert ((p->payload[0] & 0xf) < 2);

    if ((p->payload[0] & 0xf) == 0)       // Full Slice packet
    {
      currSlice->ei_flag = 0;
      MBDataIndex = 1;                    // Skip First Byte
      MBDataIndex += RTPInterpretSliceHeader (&p->payload[1], p->paylen-1, 0, sh, img);
    }
    else                                  // Partition A packet
    {
      currSlice->ei_flag = 0;
      MBDataIndex = 1;                    // Skip First Byte
      MBDataIndex += RTPInterpretSliceHeader (&p->payload[1], p->paylen-1, 1, sh, img);
    }

    FirstMacroblockInSlice = sh->FirstMBInSliceY * (img->width/16) + 
                                 sh->FirstMBInSliceX;   //! assumes picture sizes divisble by 16
    //JVT-D101
    if(first) // just to let the decoding of the first slice in the session
    {
      done0 = 1;
      first = 0;
    }
    else 
    {
      if(sh->PictureID == currSlice->picture_id) // in same picture currSlice->picture_id
      {
        if(sh->PictureID == img->last_decoded_pic_id) // a redundant slice/picture
          ;
        else if(FirstMacroblockInSlice >= img->current_mb_nr) // note here img->current_mb_nr = -4711 if the first slice of picture comes
          done0 = 1; // if FirstMacroblockInSlice < img->current_mb_nr, the slice just read is a redundant slice
      }
      else
        done0 = 1;
    }
    // End JVT-D101

  } while (!done0); // JVT-D101

  // Here used to be the if() cascade.  It is deleted for two reasons:  First,
  // error concealment for non data-partitioned slices (Nokia concealment) is
  // now triggered after decoding based on the map of decoded macroblocks, see
  // file image.c.  The DP errror concealment (Teles concealment) is triggered
  // in ProcessDataPartitionedSlice().  Second, the old code made assumptions
  // such as in-order slices and non-FMO macroblock ordering which are no more
  // appropriate.
  //! I believe I have included all relevant code regarding the IDERP handling
  //! and the emu-prevention code.  However, this would be the first place to
  //! look if any of the two are broken (in the RTP file format only).  StW, 06.07.02

// printf ("ReadRTPPacket: FirstMacroblockInSlice = %d\n", FirstMacroblockInSlice);
  // 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);

  p->paylen = MBDataIndex + EBSPtoRBSP(currSlice->partArr[0].bitstream->streamBuffer, p->paylen - MBDataIndex, 0);
  p->paylen = MBDataIndex + RBSPtoSODB(currSlice->partArr[0].bitstream->streamBuffer, p->paylen - MBDataIndex);
  currSlice->partArr[0].bitstream->bitstream_length = p->paylen-MBDataIndex;
  
  buf = currSlice->partArr[0].bitstream->streamBuffer;

  if(active_pps->entropy_coding_mode == CABAC)
  {
    dep = &((currSlice->partArr[0]).de_cabac);
    arideco_start_decoding(dep, buf, 0, &currSlice->partArr[0].bitstream->read_len, img->type);
  }
      
  currSlice->next_header = RTPGetFollowingSliceHeader (img, nextp, nextsh); // no use for the info in nextp, nextsh yet. 
// printf ("ReadRTPPacket: currSlice->next_header %d  RTPSequence %d\n", currSlice->next_header, p->seq);
assert (b_frame == 0);  
  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 
 *    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, struct img_par *img)
{
  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->structure, &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->disposable_flag, &dummy);
  bitptr+=len;
  sh->num_ref_pic_active_fwd = 0;
  sh->num_ref_pic_active_bwd = 0;
  if(sh->SliceType==0 || sh->SliceType==2) // P or SP Picture
  {
    len = GetVLCSymbol(buf, bitptr, &info, bufsize);
    linfo (len, info, &sh->num_ref_pic_active_fwd, &dummy);
    bitptr+=len;
    sh->num_ref_pic_active_fwd++;
  }
  else if(sh->SliceType==1) // B Picture
  {

    len = GetVLCSymbol(buf, bitptr, &info, bufsize);
    linfo (len, info, &sh->num_ref_pic_active_fwd, &dummy);
    bitptr+=len;
    sh->num_ref_pic_active_fwd++;

    len = GetVLCSymbol(buf, bitptr, &info, bufsize);
    linfo (len, info, &sh->num_ref_pic_active_bwd, &dummy);
    bitptr+=len;
    sh->num_ref_pic_active_bwd++;
  }

  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;
  
  // JVT-D101
  if(img->redundant_slice_flag)
  {
    len = GetfixedSymbol(buf, bitptr, &info, bufsize,1);   
    sh->redundant_pic_cnt = info;
    bitptr+=len;
  } 
  // End JVT-D101

  if(sh->SliceType==1)
  {
    len = GetfixedSymbol(buf, bitptr, &info, bufsize,1);   
    sh->Direct_type = info;
    bitptr+=len;
  } 

  len = GetVLCSymbol(buf, bitptr, &info, bufsize);
  linfo_dquant (len, info, &sh->InitialQP, &dummy);
  bitptr+=len;
  sh->InitialQP = sh->InitialQP + (MAX_QP - MIN_QP +1)/2;

  if (sh->SliceType==2 || sh->SliceType==4) // SP Picture & SI Pictures
  {
    if(sh->SliceType==2) // Do not read for SI PICTURES
    {
    len = GetfixedSymbol(buf, bitptr, &info, bufsize,1);   
    sh->SwitchSP = info;
    bitptr+=1;
    } 
    len = GetVLCSymbol(buf, bitptr, &info, bufsize);
    linfo_dquant (len, info, &sh->InitialSPQP, &dummy);
    bitptr+=len;
    sh->InitialSPQP = sh->InitialSPQP + (MAX_QP - MIN_QP +1)/2;
    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 (ParSet[CurrentParameterSet].FilterParametersFlag)
  {
    len = GetfixedSymbol(buf, bitptr, &info, bufsize,1);   
    sh->LFDisable = info;
    bitptr+=1;
    if (!sh->LFDisable)
    {
      len = GetVLCSymbol(buf, bitptr, &info, bufsize);
      linfo_dquant (len, info, &sh->LFAlphaC0OffsetDiv2, &dummy);
      bitptr+=len;

      len = GetVLCSymbol(buf, bitptr, &info, bufsize);
      linfo_dquant (len, info, &sh->LFBetaOffsetDiv2, &dummy);
      bitptr+=len;
    }
  }


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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -