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

📄 decodeiff.c

📁 h.264/avc 视频编码程序,实现分数像素匹配功能,非原创.
💻 C
📖 第 1 页 / 共 3 页
字号:
 *      input file pointer
 * \param size
 *      size of the box
 ************************************************************************
 */
int parse_one_segment( struct img_par* img, struct inp_par* inp, struct snr_par *snr, FILE* fp, size_t size )
{
  unsigned long limited, storedpos;

  limited = ftell( fp );
  limited += (size - SIZEOF_BOXTYPE);

  if ( -1 == readfile( &box_s.fileSize, 8, 1, fp ) ) return -1;
  if ( -1 == readfile( &box_s.startTick, 8, 1, fp ) ) return -1;
  if ( -1 == readfile( &box_s.segmentDuration, 8, 1, fp ) ) return -1;
  // storedpos will save the file pointer to point to the current track header
  storedpos = ftell( fp );
  if ( -1 == find_track_meta( fp, limited, &box_ath.storedpos, ThisAlternateTrack ) ) return -1;
  if ( 0 != fseek( fp, storedpos, SEEK_SET ) ) return -1;
  if ( -1 == find_track_media( fp, limited, &box_atm.storedpos, ThisAlternateTrack ) ) return -1;

  if ( -1 == rdOneTrack( img, inp, snr, fp ) ) return -1;

  return 0;
}

/*!
 ************************************************************************
 * \brief
 *      Free all the resources allocated for the segment
 * \return
 *      None
 ************************************************************************
 */
void freeSegmentBox()
{
  freeAlternateTrackHeaderBox();
  freeAlternateTrackMediaBox();
}

/*!
 ************************************************************************
 * \brief
 *      read and decode all the frames in one track of a segment
 * \return
 *      0, if success
 *      -1, otherwise
 * \param img
 *      image pointer
 * \param inp
 *      input parameter pointer
 * \param snr
 *      snr pointer
 * \param fp
 *      input file pointer
 ************************************************************************
 */
int rdOneTrack( struct img_par* img, struct inp_par* inp, struct snr_par *snr, FILE *fp )
{
  unsigned long numPictures;
  int ret = EOS + 100;
//  FILE *f;

//  f = fopen("dummy2.txt", "at");

  if ( 0 != fseek( fp, box_ath.storedpos, SEEK_SET ) ) return -1;
  if ( -1 == readfile( &numPictures, box_fh.numBytesInPictureCountMinusOne+1, 1, fp ) ) return -1;
  currPictureInfo.storedpos = ftell( fp );

  while ( numPictures-- > 0 && ret != EOS )
    ret = decode_one_frame( img, inp, snr );
/*  {
    rdPictureInfo( fp );
    fprintf( f, "picture payload, total %d:\n", currPictureInfo.numPayloads );
    i=9;
    while (i-- > 0)
    {
      ret = readSliceIFF( img, inp );
      fprintf( f, "picture %d payload nr %d 's payloadsize: %d\n", currPayloadInfo.pictureID, currPayloadInfo.payloadnr, currPayloadInfo.payloadSize);
    }
  }
  fclose( f ); */
  return 0;
}

/*!
 ************************************************************************
 * \brief
 *      try to find the ATRH box from the input file
 * \return
 *      0, if success
 *      -1, otherwise
 * \param fp
 *      input file pointer
 * \param limited
 *      how far will go to find it
 * \param storedpos
 *      if found, save the position 
 * \param tracknr
 *      which track to find
 ************************************************************************
 */
int find_track_meta( FILE *fp, unsigned long limited, unsigned long* storedpos, int tracknr )
{
  int nr = -1;
  unsigned long size, type, pos;

  *storedpos = 0;

  assert( fp != NULL );
  assert( tracknr < box_fh.numAlternateTracks );

  pos = 0;
  while ( tracknr > nr && pos < limited && pos != (unsigned long)-1 )
  {
    if ( -1 == readfile( &size, 4, 1, fp ) ) return -1;     // in 32 bits mode
    if ( -1 == readfile( &type, 4, 1, fp ) ) return -1;
    pos = (unsigned)ftell(fp);
    if ( type == BOX_ATRH ) nr++;
    if ( tracknr > nr )
    { if ( 0 != fseek( fp, size - SIZEOF_BOXTYPE, SEEK_CUR ) ) return -1; }
  }

  if ( tracknr != nr ) return -1;     // have not found the track needed

  *storedpos = ftell( fp );           // save the file pointer to the track header
  return 0;
}

/*!
 ************************************************************************
 * \brief
 *      try to find the ATRM box from the input file
 * \return
 *      0, if success
 *      -1, otherwise
 * \param fp
 *      input file pointer
 * \param limited
 *      how far will go to find it
 * \param storedpos
 *      if found, save the position 
 * \param tracknr
 *      which track to find
 ************************************************************************
 */
int find_track_media( FILE *fp, unsigned long limited, unsigned long* storedpos, int tracknr )
{
  int nr = -1;
  unsigned long size, type, pos;

  *storedpos = 0;

  assert( fp != NULL );
  assert( tracknr < box_fh.numAlternateTracks );

  pos = 0;
  while ( tracknr > nr && pos < limited && pos != (unsigned long)-1 )
  {
    if ( -1 == readfile( &size, 4, 1, fp ) ) return -1;     // in 32 bits mode
    if ( -1 == readfile( &type, 4, 1, fp ) ) return -1;
    pos = (unsigned)ftell(fp);
    if ( type == BOX_ATRM ) nr++;
    if ( tracknr > nr )
    { if ( 0 != fseek( fp, size - SIZEOF_BOXTYPE, SEEK_CUR ) ) return -1; }
  }

  if ( tracknr != nr ) return -1;     // have not found the track needed

  *storedpos = ftell( fp );           // save the file pointer to the track header
  box_atm.currPictureOffset = *storedpos;   // maintain the media data pointer
  box_atm.currPayloadOffset = *storedpos;
  return 0;
}

/*!
 ************************************************************************
 * \brief
 *      Do nothing
 * \return
 *      None
 ************************************************************************
 */
void freeAlternateTrackHeaderBox()
{
}

/*!
 ************************************************************************
 * \brief
 *      Read the picture info before it is decoded
 * \return
 *      0, if success
 *      -1, otherwise
 * \param fp
 *      input file pointer
 ************************************************************************
 */
int rdPictureInfo( FILE* fp )
{
  byte cd;
  size_t num = 0;
  
  assert( fp != NULL );

  fseek( fp, currPictureInfo.storedpos, SEEK_SET );

  num += readfile( &cd, 1, 1, fp );
  if ( cd == 0x80 ) currPictureInfo.intraPictureFlag = 1;
  else currPictureInfo.intraPictureFlag = 0;

  num += readfile( &currPictureInfo.pictureOffset, box_fh.numBytesInPictureOffsetMinusTwo + 2, 1, fp );
  num += readfile( &currPictureInfo.pictureDisplayTime, box_fh.numBytesInPictureDisplayTimeMinusOne+1, 1, fp );
  num += readfile( &currPictureInfo.numPayloads, box_fh.numBytesInPayloadCountMinusOne+1, 1, fp );

  if ( num != (unsigned)(1+box_fh.numBytesInPictureOffsetMinusTwo + 2 +
    box_fh.numBytesInPictureDisplayTimeMinusOne+1 +
    box_fh.numBytesInPayloadCountMinusOne+1) ) 
    return -1;

  currPayloadInfo.storedpos = ftell( fp );  // update the pointer, it will be increased when read one payload info
  currPayloadInfo.payloadnr = 0;
  BeginOfPictureOrSlice = SOP;
  return 0;
}

/*!
 ************************************************************************
 * \brief
 *      read the payloadinfo data and set the decoder parameter
 * \return
 *      0, if success
 *      -1, otherwise
 * \param img
 *      image pointer
 * \param inp
 *      input parameter pointer
 * \param pp
 *      read the data to pp
 * \param fp
 *      input file pointer
 ************************************************************************
 */
int rdPayloadInfo( struct img_par *img, struct inp_par* inp, PayloadInfo* pp, FILE *fp )
{
  byte cd;

  assert( fp != NULL );

  fseek( fp, pp->storedpos, SEEK_SET );

  if ( -1 == readfile( &pp->payloadSize, box_fh.numBytesInPayloadSizeMinusOne+1, 1, fp ) ) return -1;
  if ( -1 == readfile( &pp->headerSize, 1, 1, fp ) ) return -1;
  if ( -1 == readfile( &cd, 1, 1, fp ) ) return -1;
  pp->payloadType = (cd >> 4);
  pp->errorIndication = ((cd&0x0F) >> 3);
  pp->reserved = (cd & 0x07);

  switch ( pp->payloadType )
  {
  case 0:
    pp->buffer.bitstream_length = pp->headerSize - (box_fh.numBytesInPayloadSizeMinusOne+1 + 2);
    pp->buffer.streamBuffer = alloca( pp->buffer.bitstream_length );
    assert( pp->buffer.streamBuffer != NULL );
    if ( fread( pp->buffer.streamBuffer, 1, pp->buffer.bitstream_length, fp ) != (unsigned)pp->buffer.bitstream_length )
      return -1;
    pp->buffer.frame_bitoffset = 0;

    decomposeSliceHeader( img, inp, pp );
    break;
  default:
    // not supported now.
    assert( 0 == 1 );
    break;
  }

  pp->payloadnr++;
  if ( currPictureInfo.numPayloads == pp->payloadnr ) // the last payloadinfo is read, set the position of next pic
    currPictureInfo.storedpos = ftell( fp );
  else // next payloadinfo 
    pp->storedpos = ftell( fp );

  return 0;
}

/*!
 ************************************************************************
 * \brief
 *      set the decoder parameter according to a payloadinfo
 * \return
 *      None
 * \param img
 *      image pointer
 * \param inp
 *      input parameter pointer
 * \param pp
 *      read the data to pp
 ************************************************************************
 */
void decomposeSliceHeader( struct img_par *img, struct inp_par* inp, PayloadInfo* pp )
{
  SyntaxElement sym;
  Bitstream* buf;
  Slice *currSlice = img->currentSlice;
  int bitptr = 0;
  int tmp1;
  RMPNIbuffer_t *tmp_rmpni,*tmp_rmpni2;
  MMCObuffer_t *tmp_mmco,*tmp_mmco2;
  int done;

  buf = &(pp->buffer);

  sym.type = SE_HEADER;       // This will be true for all symbols generated here
  sym.mapping = linfo;        // Mapping rule: Simple code number to len/info
  
  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &sym.inf, buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  pp->parameterSet = sym.value1;
  IFFUseParameterSet( pp->parameterSet, img, inp );
  buf->frame_bitoffset += sym.len;
  bitptr += sym.len;

  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &sym.inf, buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  pp->pictureID = sym.value1;
  currSlice->picture_id = img->tr = sym.value1;
  buf->frame_bitoffset += sym.len;
  bitptr += sym.len;

  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &sym.inf, buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  pp->sliceType = sym.value1;
  switch (sym.value1)
  {
  //! Potential BUG: do we need to distinguish between INTER_IMG_MULT and INTER_IMG?
  //!    similar with B_IMG_! and B_IMG_MULT
  //! also: need to define Slice types for SP images
  //! see VCEG-N72r1 for the Slice types, which are mapped here to img->type
  case 0:
    img->type = currSlice->picture_type = (inp->buf_cycle > 1)?INTER_IMG_MULT:INTER_IMG_1;
    break;
  case 1:
    img->type = currSlice->picture_type = (inp->buf_cycle > 1)?B_IMG_MULT:B_IMG_1;
    break;
  case 2:
    img->type = currSlice->picture_type = (inp->buf_cycle > 1)?SP_IMG_MULT:SP_IMG_1;
    break;
  case 3:
    img->type = currSlice->picture_type = INTRA_IMG;
    break;
  default:
    printf ("Panic: unknown Slice type %d, conceal by loosing slice\n", pp->sliceType);
    currSlice->ei_flag = 1;
  }  
  buf->frame_bitoffset += sym.len;
  bitptr += sym.len;

  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &sym.inf, buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  pp->firstMBInSliceX = sym.value1;
  buf->frame_bitoffset += sym.len;
  bitptr += sym.len;

  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &sym.inf, buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  pp->firstMBInSliceY = sym.value1;
  buf->frame_bitoffset += sym.len;
  bitptr += sym.len;

  currSlice->start_mb_nr = pp->firstMBInSliceY * box_ps.pictureWidthInMBs + pp->firstMBInSliceX;

  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &sym.inf, buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  pp->initialQP = MAX_QP - sym.value1;
  currSlice->qp = img->qp = pp->initialQP;
  buf->frame_bitoffset += sym.len;
  bitptr += sym.len;

  if ( inp->symbol_mode == CABAC )
  {
    sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &sym.inf, buf->bitstream_length );
    sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
    pp->lastMBnr = sym.value1;
    currSlice->last_mb_nr = sym.value1;
    buf->frame_bitoffset += sym.len;
    bitptr += sym.len;
  }
  if ( img->type == SP_IMG_1 || img->type == SP_IMG_MULT )
  {
    sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &sym.inf, buf->bitstream_length );
    sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
    img->qpsp = MAX_QP - sym.value1;
    buf->frame_bitoffset += sym.len;
    bitptr += sym.len;
  }


  // Multi-Picture Buffering Syntax, Feb 27, 2002
  // RPSF: Reference Picture Selection Flags
  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &(sym.inf), buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  buf->frame_bitoffset += sym.len;
  bitptr+=sym.len;

  // PN: Picture Number
  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &(sym.inf), buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  buf->frame_bitoffset += sym.len;
  bitptr+=sym.len;
  img->pn=sym.value1;

  // RPSL: Reference picture selection layer
  sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &(sym.inf), buf->bitstream_length );
  sym.mapping(sym.len, sym.inf, &(sym.value1), &(sym.value2));
  buf->frame_bitoffset += sym.len;
  bitptr+=sym.len;

  if (sym.value1)
  {
    // read Reference Picture Selection Layer
    // free old buffer content
    while (img->currentSlice->rmpni_buffer)
    { 
      tmp_rmpni=img->currentSlice->rmpni_buffer;
 
      img->currentSlice->rmpni_buffer=tmp_rmpni->Next;
      free (tmp_rmpni);
    } 
    done=0;
    // if P or B frame RMPNI

    if ((img->type==INTER_IMG_1)||(img->type==INTER_IMG_MULT)||(img->type==B_IMG_1)||
        (img->type==B_IMG_MULT)||(img->type==SP_IMG_1)||(img->type==SP_IMG_MULT))
    {
      do
      {
    
        sym.len = GetVLCSymbol( buf->streamBuffer, buf->frame_bitoffset, &(sym.inf), buf->bitstream_length );
        sym.mapping(sym.len, sym.inf, &tmp1, &(sym.value2));
        buf->frame_bitoffset += sym.len;
        bitptr+=sym.len;


        // check for illegal values
        if ((tmp1<0)||(tmp1>3))
          error ("Invalid RMPNI operation specified",400);

⌨️ 快捷键说明

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