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

📄 fame_profile_mpeg.c

📁 一个很好用的MPEG1/4的开源编码器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*                                                                           *//*  Description:                                                             *//*    Encode a single slice.                                                 *//*                                                                           *//*  Arguments:                                                               *//*    fame_profile_t * profile: the profile handle returned by fame_open     *//*                                                                           *//*  Return value:                                                            *//*    int : the number of bytes written to buffer                            */static int profile_mpeg_encode(fame_profile_t *profile){  fame_profile_mpeg_t *profile_mpeg = FAME_PROFILE_MPEG(profile);  int x, y;  int slice_end;  /* the 4 Y and 2 C blocks in a macroblock */  short * blocks[6];   /* the binary alpha block */  unsigned char *bab;  fame_bab_t bab_type;  fame_motion_coding_t motion_coding;  fame_motion_vector_t forward[6];  unsigned char pattern;  int dquant;  int mv_count = 0;  int mv_norm = 0;  int quant_sum = 0;  /* Test for end of frame */  if(profile_mpeg->slice_start >= (profile_mpeg->height >> 4))    return(0);  /* Clear syntax buffer */  if(profile_mpeg->slice_start != 0) {    if(profile_mpeg->syntax && profile_mpeg->syntax->use)      profile_mpeg->syntax->use(profile_mpeg->syntax,				profile_mpeg->buffer,				profile_mpeg->dirty);    profile_mpeg->dirty = 0;  }  bab_type = bab_all_coded;  motion_coding = motion_intra;  pattern = 0x0f; /* all blocks coded */  /* Generate slice */  if(profile_mpeg->syntax && profile_mpeg->syntax->start_slice)    profile_mpeg->syntax->start_slice(profile_mpeg->syntax,				      profile_mpeg->slice_start,				      profile_mpeg->lines_per_slice*				      (profile_mpeg->width>>4),				      profile_mpeg->quant_scale);  slice_end = fame_min(profile_mpeg->height >> 4,		       profile_mpeg->slice_start+profile_mpeg->lines_per_slice);  /* Encode macroblocks */  for (y = profile_mpeg->slice_start; y < slice_end; y++)     for (x = 0; x < (profile_mpeg->width >> 4); x++)    {      /* code shape */      if(profile_mpeg->shape && profile_mpeg->shape->encode_intra_shape)	bab_type = profile_mpeg->shape->encode_intra_shape(profile_mpeg->shape,							    x, y, &bab, &pattern);      /* compensate motion */      if(profile_mpeg->current_coding == 'P') {	if(profile_mpeg->syntax && profile_mpeg->syntax->predict_vector)	  profile_mpeg->syntax->predict_vector(profile_mpeg->syntax,						x, y, 0, forward);	if(profile_mpeg->motion && profile_mpeg->motion->estimation)	  motion_coding = profile_mpeg->motion->estimation(profile_mpeg->motion, x, y, forward, profile_mpeg->quant_scale);	/* U and V vectors */	if(profile_mpeg->syntax && profile_mpeg->syntax->compute_chrominance_vectors)	  profile_mpeg->syntax->compute_chrominance_vectors(profile_mpeg->syntax, forward, pattern);      } else	motion_coding = motion_intra;      /* adaptive quantization */      if(profile_mpeg->rate && profile_mpeg->rate->local_estimation)        dquant = profile_mpeg->rate->local_estimation(profile_mpeg->rate,                                                      x, y, blocks,                                                      motion_coding);      else        dquant = 0;      if(motion_coding == motion_intra) {	profile_mpeg->intra++;	/* Code intra macroblock */	if(profile_mpeg->encoder &&	   profile_mpeg->encoder->encode_intra_mb &&	   bab_type != bab_not_coded)	  profile_mpeg->encoder->encode_intra_mb(profile_mpeg->encoder,						 x, y, blocks,						 profile_mpeg->quant_scale,						 bab_type);	if(profile_mpeg->next_coding != 'I')	  if(profile_mpeg->decoder && 	     profile_mpeg->decoder->reconstruct_intra_mb &&	     bab_type != bab_not_coded)	    profile_mpeg->decoder->reconstruct_intra_mb(profile_mpeg->decoder,							x, y, blocks,							profile_mpeg->quant_scale,							bab_type);	/* Write macroblock */	if(profile_mpeg->syntax &&	   profile_mpeg->syntax->write_intra_mb)          profile_mpeg->quant_scale -= /* dquant may be cancelled */            profile_mpeg->syntax->write_intra_mb(profile_mpeg->syntax,                                                 x, y, blocks,                                                 bab, profile_mpeg->bab_map,                                                 bab_type, dquant, pattern);      } else {	profile_mpeg->inter++;	/* TODO: check for coded in syntax macroblock depending on error   */	/* of motion estimation, for inter blocks only.                    */	if(profile_mpeg->search_range_adaptive) {          if(motion_coding == motion_inter4v) {	    mv_count += 4;	    mv_norm += forward[0].dx*forward[0].dx + forward[0].dy*forward[0].dy;	    mv_norm += forward[1].dx*forward[1].dx + forward[1].dy*forward[1].dy;	    mv_norm += forward[2].dx*forward[2].dx + forward[2].dy*forward[2].dy;	    mv_norm += forward[3].dx*forward[3].dx + forward[3].dy*forward[3].dy;          } else {            mv_count++;	    mv_norm += forward[0].dx*forward[0].dx + forward[0].dy*forward[0].dy;	  } 	}	/* Code inter macroblock */	if(profile_mpeg->encoder &&	   profile_mpeg->encoder->encode_inter_mb &&	   bab_type != bab_not_coded)          profile_mpeg->encoder->encode_inter_mb(profile_mpeg->encoder,                                                 x, y, blocks,                                                 forward, NULL, motion_coding,                                                 profile_mpeg->quant_scale,                                                 bab_type);	if(profile_mpeg->next_coding != 'I')	  if(profile_mpeg->decoder &&	     profile_mpeg->decoder->reconstruct_inter_mb &&	     bab_type != bab_not_coded)	    profile_mpeg->decoder->reconstruct_inter_mb(profile_mpeg->decoder, 							x, y, blocks,							forward, NULL, motion_coding,							profile_mpeg->quant_scale,							bab_type);	/* Write macroblock */	if(profile_mpeg->syntax &&	   profile_mpeg->syntax->write_inter_mb)          profile_mpeg->quant_scale -= /* dquant may be cancelled */            profile_mpeg->syntax->write_inter_mb(profile_mpeg->syntax,                                                 x, y, blocks,                                                 bab, profile_mpeg->bab_map,                                                 bab_type, dquant, pattern,                                                 forward, NULL, motion_coding);      }      quant_sum += profile_mpeg->quant_scale;    }  #ifdef HAS_MMX  asm("emms");#endif  if(mv_count) {    /* adapt search range according to MV standard deviation */    mv_norm /= mv_count;    mv_norm = (int) sqrt(mv_norm);    if(profile_mpeg->search_range < 3*mv_norm &&        profile_mpeg->search_range < 1024) {      profile_mpeg->search_range <<= 1;    } else if(profile_mpeg->search_range > 6*mv_norm &&	      profile_mpeg->search_range > 16) {      profile_mpeg->search_range >>= 1;    }  }  /* End of slice */  if(profile_mpeg->syntax && profile_mpeg->syntax->end_slice)    profile_mpeg->syntax->end_slice(profile_mpeg->syntax);  profile_mpeg->quant_avg = (float) quant_sum /     ((slice_end - profile_mpeg->slice_start) * (profile_mpeg->width >> 4));    /* Return the number of bytes encoded */  if(profile_mpeg->syntax && profile_mpeg->syntax->flush)    profile_mpeg->dirty = profile_mpeg->syntax->flush(profile_mpeg->syntax);  else    profile_mpeg->dirty = 0;  profile_mpeg->total += profile_mpeg->dirty;  profile_mpeg->slice_start = slice_end;  return(profile_mpeg->dirty);}/*  profile_mpeg_leave                                                       *//*                                                                           *//*  Description:                                                             *//*    Finish encoding a picture.                                             *//*                                                                           *//*  Arguments:                                                               *//*    fame_profile_t * profile: the profile handle returned by fame_open     *//*    fame_frame_statistics_t * stats: information about the encoding        *//*                                                                           *//*  Return value:                                                            *//*    None.                                                                  */static void profile_mpeg_leave(fame_profile_t *profile,			       fame_frame_statistics_t *stats){  fame_profile_mpeg_t *profile_mpeg = FAME_PROFILE_MPEG(profile);  /* Pad and interpolate for half-pel estimation/compensation */  if(profile_mpeg->motion->flags & FAME_MOTION_FLIP_ROUNDING)    profile_mpeg->rounding ^= 1;  if(profile_mpeg->next_coding != 'I' &&     (profile_mpeg->motion->flags & FAME_MOTION_SUBPEL_SEARCH))    if(profile_mpeg->decoder && profile_mpeg->decoder->interpolate)      profile_mpeg->decoder->interpolate(profile_mpeg->decoder, profile_mpeg->rounding);    if(profile_mpeg->next_coding != 'I' &&     (profile_mpeg->shape ||      (profile_mpeg->motion->flags & FAME_MOTION_UNRESTRICTED_SEARCH)))    if(profile_mpeg->decoder && profile_mpeg->decoder->pad)      profile_mpeg->decoder->pad(profile_mpeg->decoder,				 profile_mpeg->bab_map,				 &profile_mpeg->bounding_box);#undef DEBUG_WRITE_RECONSTRUCTED_FRAMES#ifdef DEBUG_WRITE_RECONSTRUCTED_FRAMES  /* Write reconstructed frame to standard output */  fwrite(profile_mpeg->ref[profile_mpeg->current][1]->y -	 (16*(profile_mpeg->width+32)+16),	 (profile_mpeg->width+32)*(profile_mpeg->height+32),	 1, stdout);  fwrite(profile_mpeg->ref[profile_mpeg->current][1]->u -	 (8*(profile_mpeg->width+32)/2+8),	 (profile_mpeg->width+32)*(profile_mpeg->height+32)/4,	 1, stdout);  fwrite(profile_mpeg->ref[profile_mpeg->current][1]->v -	 (8*(profile_mpeg->width+32)/2+8),	 (profile_mpeg->width+32)*(profile_mpeg->height+32)/4,	 1, stdout);#endif  /* Leave the encoder */  if(profile_mpeg->encoder && profile_mpeg->encoder->leave)    profile_mpeg->encoder->leave(profile_mpeg->encoder);  /* Leave the decoder */  if(profile_mpeg->decoder && profile_mpeg->decoder->leave)    profile_mpeg->decoder->leave(profile_mpeg->decoder);  /* Leave the motion */  if(profile_mpeg->motion && profile_mpeg->motion->leave)    profile_mpeg->motion->leave(profile_mpeg->motion);  /* Rotate reference ring */  switch(profile_mpeg->current_coding) {    case 'I':    case 'P':      profile_mpeg->past = profile_mpeg->future;      profile_mpeg->future = profile_mpeg->current;      profile_mpeg->current = !profile_mpeg->current;    break;    case 'B':    break;    default:    break;  }  /* Increment frame number */  profile_mpeg->frame_number++;  /* Update rate control */  if(profile_mpeg->rate && profile_mpeg->rate->leave)    profile_mpeg->rate->leave(profile_mpeg->rate, profile_mpeg->total * 8);  /* Show picture info */  if(profile_mpeg->verbose) {    if(profile_mpeg->intra+profile_mpeg->inter) {      FAME_INFO("inter/intra %3d%% ",		100*profile_mpeg->inter/		(profile_mpeg->intra+profile_mpeg->inter));    }    FAME_INFO("%dkbits/s quality %.02f%% range %d %c frame #%d\033[K\r",	      (profile_mpeg->total * profile_mpeg->fps_num * 8) / 	      (profile_mpeg->fps_den * 1000),	      (31 - profile_mpeg->quant_avg) * 100 / 30,	      profile_mpeg->search_range,	      profile_mpeg->current_coding,	      profile_mpeg->frame_number);  }  if(profile_mpeg->monitor && profile_mpeg->monitor->leave)    profile_mpeg->monitor->leave(profile_mpeg->monitor, 				 profile_mpeg->total * 8,				 profile_mpeg->quant_avg);  if(stats)    *stats = *profile_mpeg->frame_stats;}/*  profile_mpeg_close                                                       *//*                                                                           *//*  Description:                                                             *//*    Flush remaining encoded data and cleanup everything.                   *//*                                                                           *//*  Arguments:                                                               *//*    fame_profile_t * profile: the profile handle returned by fame_open     *//*                                                                           *//*  Return value:                                                            *//*    int : the number of bytes written to buffer                            */static int profile_mpeg_close(fame_profile_t *profile){  fame_profile_mpeg_t *profile_mpeg = FAME_PROFILE_MPEG(profile);  int i, j;  int bytes_written;  /* Initialize syntax buffer */  if(profile_mpeg->syntax && profile_mpeg->syntax->use)    profile_mpeg->syntax->use(profile_mpeg->syntax, profile_mpeg->buffer, profile_mpeg->dirty);  /* Generate the sequence ender code */  if(profile_mpeg->syntax && profile_mpeg->syntax->end_sequence)    profile_mpeg->syntax->end_sequence(profile_mpeg->syntax);  /* Flush the syntax buffer */  if(profile_mpeg->syntax && profile_mpeg->syntax->flush)    bytes_written = profile_mpeg->syntax->flush(profile_mpeg->syntax);  else    bytes_written = 0;  /* Release the decoder */  if(profile_mpeg->decoder && profile_mpeg->decoder->close)    profile_mpeg->decoder->close(profile_mpeg->decoder);  /* Release the encoder */  if(profile_mpeg->encoder && profile_mpeg->encoder->close)    profile_mpeg->encoder->close(profile_mpeg->encoder);  /* Release the syntax */  if(profile_mpeg->syntax && profile_mpeg->syntax->close)    profile_mpeg->syntax->close(profile_mpeg->syntax);  /* Release the motion estimation  */  if(profile_mpeg->motion && profile_mpeg->motion->close)    profile_mpeg->motion->close(profile_mpeg->motion);  /* Release the shape coder  */  if(profile_mpeg->shape && profile_mpeg->shape->close)    profile_mpeg->shape->close(profile_mpeg->shape);  /* Release the rate controller */  if(profile_mpeg->rate && profile_mpeg->rate->close)    profile_mpeg->rate->close(profile_mpeg->rate); /* Release statistics monitoring */  if(profile_mpeg->monitor && profile_mpeg->monitor->close)    profile_mpeg->monitor->close(profile_mpeg->monitor);  /* Free reference shape */  if(profile_mpeg->ref_shape)    fame_free(profile_mpeg->ref_shape);  /* Free BAB map */  if(profile_mpeg->bab_map)    fame_free(profile_mpeg->bab_map);  /* Free reference ring */  for(j = 0; j < 2; j++) /* 2 references */    for(i = 0; i < 4; i++) { /* 4 planes per reference (interpolation) */      /* remove offset */      profile_mpeg->ref[j][i]->y -= 16*(profile_mpeg->width+32)+16;      fame_free(profile_mpeg->ref[j][i]->y);    }  /* Print newline for picture codes */  if(profile_mpeg->verbose)    FAME_INFO("\n");  /* Return the number of bytes written to buffer */  return(bytes_written);}

⌨️ 快捷键说明

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