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

📄 encode.c

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 C
📖 第 1 页 / 共 4 页
字号:
  }
  cpi->MinImprovementForFourMV = cpi->MinImprovementForNewMV * 4;

  if(cpi->MinImprovementForFourMV < (40<<12))
    cpi->MinImprovementForFourMV = (40<<12);

  cpi->FourMvChangeFactor = 8; /* cpi->MVChangeFactor - 0.05;  */

  /* decide what block type and motion vectors to use on all of the frames */
  for ( SBrow=0; SBrow<SBRows; SBrow++ ) {
    for ( SBcol=0; SBcol<SBCols; SBcol++ ) {
      /* Check its four Macro-Blocks */
      for ( MB=0; MB<4; MB++ ) {
	/* There may be MB's lying out of frame which must be
	   ignored. For these MB's Top left block will have a negative
	   Fragment Index. */
	if ( QuadMapToMBTopLeft(cpi->pb.BlockMap,SB,MB) < 0 ) continue;

	/* Is the current macro block coded (in part or in whole) */
	MBCodedFlag = 0;
	for ( B=0; B<4; B++ ) {
	  YFragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B );

	  /* Does Block lie in frame: */
	  if ( YFragIndex >= 0 ) {
	    /* In Frame: Is it coded: */
	    if ( cpi->pb.display_fragments[YFragIndex] ) {
	      MBCodedFlag = 1;
	      break;
	    }
	  } else
	    MBCodedFlag = 0;
	}

	/* This one isn't coded go to the next one */
	if(!MBCodedFlag) continue;

	/* Calculate U and V FragIndex from YFragIndex */
	YFragIndex = QuadMapToMBTopLeft(cpi->pb.BlockMap, SB,MB);
	UVRow = (YFragIndex / (cpi->pb.HFragments * 2));
	UVColumn = (YFragIndex % cpi->pb.HFragments) / 2;
	UVFragOffset = (UVRow * (cpi->pb.HFragments / 2)) + UVColumn;
	UFragIndex = cpi->pb.YPlaneFragments + UVFragOffset;
	VFragIndex = cpi->pb.YPlaneFragments + cpi->pb.UVPlaneFragments +
	  UVFragOffset;


	/**************************************************************
	 Find the block choice with the lowest error

	 NOTE THAT if U or V is coded but no Y from a macro block then
	 the mode will be CODE_INTER_NO_MV as this is the default
	 state to which the mode data structure is initialised in
	 encoder and decoder at the start of each frame. */

	BestError = HUGE_ERROR;


	/* Look at the intra coding error. */
	MBIntraError = GetMBIntraError( cpi, YFragIndex, PixelsPerLine );
	BestError = (BestError > MBIntraError) ? MBIntraError : BestError;

	/* Get the golden frame error */
	MBGFError = GetMBInterError( cpi, cpi->ConvDestBuffer,
				     cpi->pb.GoldenFrame, YFragIndex,
				     0, 0, PixelsPerLine );
	BestError = (BestError > MBGFError) ? MBGFError : BestError;

	/* Calculate the 0,0 case. */
	MBInterError = GetMBInterError( cpi, cpi->ConvDestBuffer,
					cpi->pb.LastFrameRecon,
					YFragIndex, 0, 0, PixelsPerLine );
	BestError = (BestError > MBInterError) ? MBInterError : BestError;

	/* Measure error for last MV */
	MBLastInterError =  GetMBInterError( cpi, cpi->ConvDestBuffer,
					     cpi->pb.LastFrameRecon,
					     YFragIndex, LastInterMVect.x,
					     LastInterMVect.y, PixelsPerLine );
	BestError = (BestError > MBLastInterError) ?
	  MBLastInterError : BestError;

	/* Measure error for prior last MV */
	MBPriorLastInterError =  GetMBInterError( cpi, cpi->ConvDestBuffer,
						  cpi->pb.LastFrameRecon,
						  YFragIndex,
						  PriorLastInterMVect.x,
						  PriorLastInterMVect.y,
						  PixelsPerLine );
	BestError = (BestError > MBPriorLastInterError) ?
	  MBPriorLastInterError : BestError;

	/* Temporarily force usage of no motionvector blocks */
	MBInterMVError = HUGE_ERROR;
	InterMVect.x = 0;  /* Set 0,0 motion vector */
	InterMVect.y = 0;

	/* If the best error is above the required threshold search
           for a new inter MV */
	if ( BestError > cpi->MinImprovementForNewMV ) {
	  /* Use a mix of heirachical and exhaustive searches for
             quick mode. */
	  if ( cpi->pb.info.quick_p ) {
	    MBInterMVError = GetMBMVInterError( cpi, cpi->pb.LastFrameRecon,
						YFragIndex, PixelsPerLine,
						cpi->MVPixelOffsetY,
						&InterMVect );

	    /* If we still do not have a good match try an exhaustive
               MBMV search */
	    if ( (MBInterMVError > cpi->ExhaustiveSearchThresh) &&
		 (BestError > cpi->ExhaustiveSearchThresh) ) {

	      MBInterMVExError =
		GetMBMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon,
					 YFragIndex, PixelsPerLine,
					 &InterMVectEx );

	      /* Is the Variance measure for the EX search
                 better... If so then use it. */
	      if ( MBInterMVExError < MBInterMVError ) {
		MBInterMVError = MBInterMVExError;
		InterMVect.x = InterMVectEx.x;
		InterMVect.y = InterMVectEx.y;
	      }
	    }
	  }else{
	    /* Use an exhaustive search */
	    MBInterMVError =
	      GetMBMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon,
				       YFragIndex, PixelsPerLine,
				       &InterMVect );
	  }


	  /* Is the improvement, if any, good enough to justify a new MV */
	  if ( (16 * MBInterMVError < (BestError * cpi->MVChangeFactor)) &&
	       ((MBInterMVError + cpi->MinImprovementForNewMV) < BestError) ){
	    BestError = MBInterMVError;
	  }

	}

	/* If the best error is still above the required threshold
           search for a golden frame MV */
	MBGF_MVError = HUGE_ERROR;
	GFMVect.x = 0; /* Set 0,0 motion vector */
	GFMVect.y = 0;
	if ( BestError > cpi->MinImprovementForNewMV ) {
	  /* Do an MV search in the golden reference frame */
	  MBGF_MVError = GetMBMVInterError( cpi, cpi->pb.GoldenFrame,
					    YFragIndex, PixelsPerLine,
					    cpi->MVPixelOffsetY, &GFMVect );

	  /* Measure error for last GFMV */
	  LastMBGF_MVError =  GetMBInterError( cpi, cpi->ConvDestBuffer,
					       cpi->pb.GoldenFrame,
					       YFragIndex, LastGFMVect.x,
					       LastGFMVect.y, PixelsPerLine );

	  /* Check against last GF motion vector and reset if the
             search has thrown a worse result. */
	  if ( LastMBGF_MVError < MBGF_MVError ) {
	    GFMVect.x = LastGFMVect.x;
	    GFMVect.y = LastGFMVect.y;
	    MBGF_MVError = LastMBGF_MVError;
	  }else{
	    LastGFMVect.x = GFMVect.x;
	    LastGFMVect.y = GFMVect.y;
	  }

	  /* Is the improvement, if any, good enough to justify a new MV */
	  if ( (16 * MBGF_MVError < (BestError * cpi->MVChangeFactor)) &&
	       ((MBGF_MVError + cpi->MinImprovementForNewMV) < BestError) ) {
	    BestError = MBGF_MVError;
	  }
	}

	/* Finally... If the best error is still to high then consider
           the 4MV mode */
	MBInterFOURMVError = HUGE_ERROR;
	if ( BestError > cpi->FourMVThreshold ) {
	  /* Get the 4MV error. */
	  MBInterFOURMVError =
	    GetFOURMVExhaustiveSearch( cpi, cpi->pb.LastFrameRecon,
				       YFragIndex, PixelsPerLine, FourMVect );

	  /* If the improvement is great enough then use the four MV mode */
	  if ( ((MBInterFOURMVError + cpi->MinImprovementForFourMV) <
		BestError) && (16 * MBInterFOURMVError <
			       (BestError * cpi->FourMvChangeFactor))) {
	    BestError = MBInterFOURMVError;
	  }
	}

        /********************************************************
	 end finding the best error
	 *******************************************************

         Figure out what to do with the block we chose

	 Over-ride and force intra if error high and Intra error similar
	 Now choose a mode based on lowest error (with bias towards no MV) */

	if ( (BestError > cpi->InterTripOutThresh) &&
	     (10 * BestError > MBIntraError * 7 ) ) {
	  cpi->MBCodingMode = CODE_INTRA;
	  SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
				    VFragIndex,&ZeroVect);
	} else if ( BestError == MBInterError ) {
	  cpi->MBCodingMode = CODE_INTER_NO_MV;
	  SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
				    VFragIndex,&ZeroVect);
	} else if ( BestError == MBGFError ) {
	  cpi->MBCodingMode = CODE_USING_GOLDEN;
	  SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
				    VFragIndex,&ZeroVect);
	} else if ( BestError == MBLastInterError ) {
	  cpi->MBCodingMode = CODE_INTER_LAST_MV;
	  SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
				    VFragIndex,&LastInterMVect);
	} else if ( BestError == MBPriorLastInterError ) {
	  cpi->MBCodingMode = CODE_INTER_PRIOR_LAST;
	  SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
				    VFragIndex,&PriorLastInterMVect);

	  /* Swap the prior and last MV cases over */
	  TmpMVect.x = PriorLastInterMVect.x;
	  TmpMVect.y = PriorLastInterMVect.y;
	  PriorLastInterMVect.x = LastInterMVect.x;
	  PriorLastInterMVect.y = LastInterMVect.y;
	  LastInterMVect.x = TmpMVect.x;
	  LastInterMVect.y = TmpMVect.y;

	} else if ( BestError == MBInterMVError ) {

	  cpi->MBCodingMode = CODE_INTER_PLUS_MV;
	  SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
				    VFragIndex,&InterMVect);

	  /* Update Prior last mv with last mv */
	  PriorLastInterMVect.x = LastInterMVect.x;
	  PriorLastInterMVect.y = LastInterMVect.y;

	  /* Note last inter MV for future use */
	  LastInterMVect.x = InterMVect.x;
	  LastInterMVect.y = InterMVect.y;

	  AddMotionVector( cpi, &InterMVect);

	} else if ( BestError == MBGF_MVError ) {

	  cpi->MBCodingMode = CODE_GOLDEN_MV;
	  SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
				    VFragIndex,&GFMVect);

	  /* Note last inter GF MV for future use */
	  LastGFMVect.x = GFMVect.x;
	  LastGFMVect.y = GFMVect.y;

	  AddMotionVector( cpi, &GFMVect);
	} else if ( BestError == MBInterFOURMVError ) {
	  cpi->MBCodingMode = CODE_INTER_FOURMV;

	  /* Calculate the UV vectors as the average of the Y plane ones. */
	  /* First .x component */
	  FourMVect[4].x = FourMVect[0].x + FourMVect[1].x +
	    FourMVect[2].x + FourMVect[3].x;
	  if ( FourMVect[4].x >= 0 )
	    FourMVect[4].x = (FourMVect[4].x + 2) / 4;
	  else
	    FourMVect[4].x = (FourMVect[4].x - 2) / 4;
	  FourMVect[5].x = FourMVect[4].x;

	  /* Then .y component */
	  FourMVect[4].y = FourMVect[0].y + FourMVect[1].y +
	    FourMVect[2].y + FourMVect[3].y;
	  if ( FourMVect[4].y >= 0 )
	    FourMVect[4].y = (FourMVect[4].y + 2) / 4;
	  else
	    FourMVect[4].y = (FourMVect[4].y - 2) / 4;
	  FourMVect[5].y = FourMVect[4].y;

	  SetFragMotionVectorAndMode(cpi, YFragIndex, &FourMVect[0]);
	  SetFragMotionVectorAndMode(cpi, YFragIndex + 1, &FourMVect[1]);
	  SetFragMotionVectorAndMode(cpi, YFragIndex + cpi->pb.HFragments,
				     &FourMVect[2]);
	  SetFragMotionVectorAndMode(cpi, YFragIndex + cpi->pb.HFragments + 1,
				     &FourMVect[3]);
	  SetFragMotionVectorAndMode(cpi, UFragIndex, &FourMVect[4]);
	  SetFragMotionVectorAndMode(cpi, VFragIndex, &FourMVect[5]);

	  /* Note the four MVs values for current macro-block. */
	  AddMotionVector( cpi, &FourMVect[0]);
	  AddMotionVector( cpi, &FourMVect[1]);
	  AddMotionVector( cpi, &FourMVect[2]);
	  AddMotionVector( cpi, &FourMVect[3]);

	  /* Update Prior last mv with last mv */
	  PriorLastInterMVect.x = LastInterMVect.x;
	  PriorLastInterMVect.y = LastInterMVect.y;

	  /* Note last inter MV for future use */
	  LastInterMVect.x = FourMVect[3].x;
	  LastInterMVect.y = FourMVect[3].y;

	} else {

	  cpi->MBCodingMode = CODE_INTRA;
	  SetMBMotionVectorsAndMode(cpi,YFragIndex,UFragIndex,
				    VFragIndex,&ZeroVect);
	}


	/* setting up mode specific block types
           *******************************************************/

	*InterError += (BestError>>8);
	*IntraError += (MBIntraError>>8);


      }
      SB++;

    }
  }

  /* Return number of pixels coded */
  return 0;
}

void WriteFrameHeader( CP_INSTANCE *cpi) {
  ogg_uint32_t i;
  oggpack_buffer *opb=cpi->oggbuffer;

  /* Output the frame type (base/key frame or inter frame) */
  oggpackB_write( opb, cpi->pb.FrameType, 1 );

  /* Write out details of the current value of Q... variable resolution. */
  for ( i = 0; i < Q_TABLE_SIZE; i++ ) {
    if ( cpi->pb.ThisFrameQualityValue == cpi->pb.QThreshTable[i] ) {
      oggpackB_write( opb, i, 6 );
      break;
    }
  }

  if ( i == Q_TABLE_SIZE ) {
    /* An invalid DCT value was specified.  */
    /*IssueWarning( "Invalid Q Multiplier" );*/
    oggpackB_write( opb, 31, 6 );
  }

  /* we only support one Q index per frame */
  oggpackB_write( opb, 0, 1 );

  /* If the frame was a base frame then write out the frame dimensions. */
  if ( cpi->pb.FrameType == KEY_FRAME ) {
    /* Key frame type / method */
    oggpackB_write( opb, cpi->pb.KeyFrameType, 1 );

    /* Spare configuration bits */
    oggpackB_write( opb, 0, 2 );
  }
}





⌨️ 快捷键说明

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