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

📄 fame_profile_mpeg.c

📁 一个很好用的MPEG1/4的开源编码器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    libfame - Fast Assembly MPEG Encoder Library    Copyright (C) 2000-2001 Vivien Chappelier    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public    License along with this library; if not, write to the Free    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include "fame.h"#include "fame_malloc.h"#include "fame_profile.h"#include "fame_profile_mpeg.h"#include "fame_encoder.h"#include "fame_decoder.h"#include "fame_motion.h"#include "fame_syntax.h"#include "fame_shape.h"#include "fame_monitor.h"static void profile_mpeg_init(fame_profile_t *profile,			      fame_context_t *context,			      fame_parameters_t *params,			      unsigned char *buffer,			      unsigned int size);static void profile_mpeg_enter(fame_profile_t *profile,			       fame_yuv_t *yuv,			       unsigned char *shape);static int profile_mpeg_encode(fame_profile_t *profile);static void profile_mpeg_leave(fame_profile_t *profile,			       fame_frame_statistics_t *stats);static int profile_mpeg_close(fame_profile_t *profile);FAME_CONSTRUCTOR(fame_profile_mpeg_t){  FAME_OBJECT(this)->name = "MPEG profile";  FAME_PROFILE(this)->init = profile_mpeg_init;  FAME_PROFILE(this)->enter = profile_mpeg_enter;  FAME_PROFILE(this)->encode = profile_mpeg_encode;  FAME_PROFILE(this)->leave = profile_mpeg_leave;  FAME_PROFILE(this)->close = profile_mpeg_close;  this->encoder_flags = 0;  this->decoder_flags = 0;  this->motion_flags = 0;  this->syntax_flags = 0;  this->shape_flags = 0;  this->rate_flags = 0;  this->monitor_flags = 0;  return(this);}/*  profile_mpeg_init                                                        *//*                                                                           *//*  Description:                                                             *//*    Initialize the profile.                                                *//*                                                                           *//*  Arguments:                                                               *//*    fame_profile_t *profile: the profile to initialize                     *//*    fame_parameters_t *params: the parameters for initialization           *//*    unsigned char *buffer: the buffer to output data                       *//*    unsigned int size: the size of the output buffer                       *//*                                                                           *//*  Return value:                                                            *//*    None.                                                                  */static void profile_mpeg_init(fame_profile_t *profile,			      fame_context_t *context,			      fame_parameters_t *params,			      unsigned char *buffer,			      unsigned int size){  fame_profile_mpeg_t *profile_mpeg = FAME_PROFILE_MPEG(profile);  int i, j;  profile_mpeg->width = params->width;  profile_mpeg->height = params->height;  profile_mpeg->coding = strdup(params->coding);  profile_mpeg->quant_scale = 1 + (30*(100-params->quality)+50)/100;  profile_mpeg->bitrate = params->bitrate;  profile_mpeg->slices_per_frame = params->slices_per_frame;  profile_mpeg->frames_per_gop = strlen(profile_mpeg->coding);  profile_mpeg->frames_per_sequence = params->frames_per_sequence;  profile_mpeg->total_frames = params->total_frames;  profile_mpeg->lines_per_slice = ((((params->height + 15) >> 4) + 				    profile_mpeg->slices_per_frame - 1) / 				   profile_mpeg->slices_per_frame);  profile_mpeg->slice_number = 0;  profile_mpeg->frame_number = 0;  profile_mpeg->gop_number = 0;  profile_mpeg->fps_num = params->frame_rate_num;  profile_mpeg->fps_den = params->frame_rate_den;  profile_mpeg->alpha_th = 255*(100 - params->shape_quality)/100;  if(params->search_range) {    profile_mpeg->search_range = params->search_range;    profile_mpeg->search_range_adaptive = 0;  } else {    profile_mpeg->search_range = 32;    profile_mpeg->search_range_adaptive = 1;  }  profile_mpeg->intra_matrix = NULL;  profile_mpeg->inter_matrix = NULL;  profile_mpeg->verbose = params->verbose;  profile_mpeg->rounding = 0;  /* Get the components */  profile_mpeg->decoder =     (fame_decoder_t *) fame_get_object(context, "decoder");  profile_mpeg->encoder =     (fame_encoder_t *) fame_get_object(context, "encoder");  profile_mpeg->motion =    (fame_motion_t *) fame_get_object(context, "motion");  profile_mpeg->syntax =     (fame_syntax_t *) fame_get_object(context, "syntax");  profile_mpeg->shape =     (fame_shape_t *) fame_get_object(context, "shape");  profile_mpeg->rate =     (fame_rate_t *) fame_get_object(context, "rate");  profile_mpeg->monitor =    (fame_monitor_t *) fame_get_object(context, "monitor");  /* VBR/CBR coding */  if(profile_mpeg->bitrate == 0)    profile_mpeg->rate = NULL; /* don't need rate control */  /* Initialize buffer */  memset(buffer, 0, size);  profile_mpeg->buffer = buffer;  profile_mpeg->size = size;  profile_mpeg->dirty = 0;  /* Allocate reference frame ring */  for(j = 0; j < 2; j++) /* 2 references */    for(i = 0; i < 4; i++) { /* 4 planes per reference (interpolation) */      profile_mpeg->ref[j][i] = 	(fame_yuv_t *) fame_malloc(sizeof(fame_yuv_t));      profile_mpeg->ref[j][i]->w = profile_mpeg->width;      profile_mpeg->ref[j][i]->h = profile_mpeg->height;      profile_mpeg->ref[j][i]->p = profile_mpeg->width+32;      profile_mpeg->ref[j][i]->y = 	(unsigned char *) fame_malloc((profile_mpeg->width+32)*				      (profile_mpeg->height+32)*12/8);      profile_mpeg->ref[j][i]->u = 	profile_mpeg->ref[j][i]->y +	(profile_mpeg->width+32)*(profile_mpeg->height+32);      profile_mpeg->ref[j][i]->v = 	profile_mpeg->ref[j][i]->u +	(profile_mpeg->width+32)*(profile_mpeg->height+32)/4;      /* add offset to beggining of picture (padding) */      profile_mpeg->ref[j][i]->y += 16*(profile_mpeg->width+32)+16;      profile_mpeg->ref[j][i]->u += 8*(profile_mpeg->width+32)/2+8;      profile_mpeg->ref[j][i]->v += 8*(profile_mpeg->width+32)/2+8;    }    /* Allocate reconstructed shape and BAB map */  if(profile_mpeg->shape) {    profile_mpeg->ref_shape =       (unsigned char *) fame_malloc(profile_mpeg->width*profile_mpeg->height);    profile_mpeg->bab_map =       (unsigned char *) fame_malloc(((profile_mpeg->width >> 4) + 2)*				    ((profile_mpeg->height >> 4) + 2));  } else {    profile_mpeg->ref_shape = NULL;    profile_mpeg->bab_map = NULL;  }  /* Initialize reference pointers */  profile_mpeg->past = 1;  profile_mpeg->future = 0;  profile_mpeg->current = 1;  /* Initialize motion estimation */  if(profile_mpeg->motion && profile_mpeg->motion->init)    profile_mpeg->motion->init(profile_mpeg->motion, 			       (profile_mpeg->width >> 4),			       (profile_mpeg->height >> 4),			       FAME_PROFILE_MPEG(profile)->motion_flags);    /* Initialize the syntax */  if(profile_mpeg->syntax && profile_mpeg->syntax->init)    profile_mpeg->syntax->init(profile_mpeg->syntax,				(profile_mpeg->width >> 4),				(profile_mpeg->height >> 4),				&profile_mpeg->intra_matrix,				&profile_mpeg->inter_matrix,				profile_mpeg->intra_dc_y_scale_table,				profile_mpeg->intra_dc_c_scale_table,				&profile_mpeg->mismatch,				FAME_PROFILE_MPEG(profile)->syntax_flags);    /* Initialize the encoder */  if(profile_mpeg->encoder && profile_mpeg->encoder->init)    profile_mpeg->encoder->init(profile_mpeg->encoder,				profile_mpeg->width,				profile_mpeg->height,				profile_mpeg->intra_matrix,				profile_mpeg->inter_matrix,				profile_mpeg->intra_dc_y_scale_table,				profile_mpeg->intra_dc_c_scale_table,				profile_mpeg->mismatch);    /* Initialize the decoder */  if(profile_mpeg->decoder && profile_mpeg->decoder->init)    profile_mpeg->decoder->init(profile_mpeg->decoder,				profile_mpeg->width,				profile_mpeg->height,				profile_mpeg->intra_matrix,				profile_mpeg->inter_matrix,				profile_mpeg->intra_dc_y_scale_table,				profile_mpeg->intra_dc_c_scale_table,				profile_mpeg->mismatch);  /* Initialize the shape coder */  if(profile_mpeg->shape && profile_mpeg->shape->init)    profile_mpeg->shape->init(profile_mpeg->shape,			       (profile_mpeg->width >> 4),			       (profile_mpeg->height >> 4),			       FAME_PROFILE_MPEG(profile)->shape_flags);  /* Initialize statistics monitoring */  if(profile_mpeg->monitor && profile_mpeg->monitor->init)    profile_mpeg->monitor->init(profile_mpeg->monitor,				params->retrieve_cb,				(profile_mpeg->width >> 4),				(profile_mpeg->height >> 4),				profile_mpeg->total_frames,				FAME_PROFILE_MPEG(profile)->monitor_flags);    /* Initialize rate control */  if(profile_mpeg->rate && profile_mpeg->rate->init)    profile_mpeg->rate->init(profile_mpeg->rate,			     (profile_mpeg->width >> 4),			     (profile_mpeg->height >> 4),			     profile_mpeg->bitrate/			     profile_mpeg->fps_num*profile_mpeg->fps_den,			     profile_mpeg->coding,			     profile_mpeg->monitor->frame_stats_list,			     &(profile_mpeg->monitor->global_stats),			     FAME_PROFILE_MPEG(profile)->rate_flags);}/*  profile_mpeg_enter                                                       *//*                                                                           *//*  Description:                                                             *//*    Start encoding a picture.                                              *//*                                                                           *//*  Arguments:                                                               *//*    fame_profile_t * profile: the profile handle returned by fame_open     *//*    fame_yuv_t * yuv: the input frame in raw YUV format (YV12 planar)      *//*    unsigned char * mask: the input mask (0 = transparent, 255 = opaque)   *//*                                                                           *//*  Return value:                                                            *//*    None.                                                                  */static void profile_mpeg_enter(fame_profile_t *profile,			       fame_yuv_t *yuv,			       unsigned char *shape){  fame_profile_mpeg_t *profile_mpeg = FAME_PROFILE_MPEG(profile);  /* Update stats and choose coding mode */  profile_mpeg->current_coding = profile_mpeg->coding[profile_mpeg->frame_number % strlen(profile_mpeg->coding)];  profile_mpeg->next_coding = profile_mpeg->coding[(profile_mpeg->frame_number + 1) % strlen(profile_mpeg->coding)];  if (profile_mpeg->monitor && profile_mpeg->monitor->current_frame_stats)    profile_mpeg->frame_stats = profile_mpeg->monitor->current_frame_stats;  else    profile_mpeg->frame_stats = NULL;  /* Clear BAB map */  if(profile_mpeg->bab_map)    memset(profile_mpeg->bab_map, bab_not_coded,	   ((profile_mpeg->width >> 4) + 2)*((profile_mpeg->height >> 4) + 2));    /* input pitch = input width if not set */  if(yuv->p == 0) yuv->p = yuv->w;   /* Initialize statistics */  if(profile_mpeg->monitor && profile_mpeg->monitor->enter)    profile_mpeg->monitor->enter(profile_mpeg->monitor,				 profile_mpeg->frame_number,				 profile_mpeg->ref[profile_mpeg->future],				 yuv,				 shape,				 &profile_mpeg->current_coding);    /* 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 sequence */  if(profile_mpeg->frame_number % profile_mpeg->frames_per_sequence == 0)    if(profile_mpeg->syntax && profile_mpeg->syntax->start_sequence)      profile_mpeg->syntax->start_sequence(profile_mpeg->syntax,					   profile_mpeg->width,					   profile_mpeg->height,					   profile_mpeg->fps_num,					   profile_mpeg->fps_den,					   profile_mpeg->size*					   profile_mpeg->frames_per_gop,					   profile_mpeg->bitrate);  /* Generate group of pictures */  if(profile_mpeg->frame_number % profile_mpeg->frames_per_gop == 0)    if(profile_mpeg->syntax && profile_mpeg->syntax->start_GOP)      profile_mpeg->syntax->start_GOP(profile_mpeg->syntax, profile_mpeg->frame_number);  /* TODO: find bounding box */  profile_mpeg->bounding_box.x = 0;  profile_mpeg->bounding_box.y = 0;  profile_mpeg->bounding_box.w = profile_mpeg->width;  profile_mpeg->bounding_box.h = profile_mpeg->height;  /* Reset rounding control */  if(profile_mpeg->current_coding == 'I')    profile_mpeg->rounding = 0;  /* Generate picture */  if(profile_mpeg->syntax && profile_mpeg->syntax->start_picture)    profile_mpeg->syntax->start_picture(profile_mpeg->syntax,					profile_mpeg->current_coding,					profile_mpeg->frame_number%profile_mpeg->frames_per_gop,					&profile_mpeg->bounding_box,					profile_mpeg->rounding,					profile_mpeg->search_range);  /* Enter the encoder */  if(profile_mpeg->encoder && profile_mpeg->encoder->enter)    profile_mpeg->encoder->enter(profile_mpeg->encoder,				 profile_mpeg->ref[profile_mpeg->past],				 profile_mpeg->ref[profile_mpeg->current],				 profile_mpeg->ref[profile_mpeg->future],				 yuv,				 profile_mpeg->ref_shape);    if(profile_mpeg->decoder && profile_mpeg->decoder->enter)    profile_mpeg->decoder->enter(profile_mpeg->decoder,				 profile_mpeg->ref[profile_mpeg->past],				 profile_mpeg->ref[profile_mpeg->current],				 profile_mpeg->ref[profile_mpeg->future],				 yuv,				 profile_mpeg->ref_shape);  if(profile_mpeg->shape && profile_mpeg->shape->enter)    profile_mpeg->shape->enter(profile_mpeg->shape,			       shape,			       profile_mpeg->ref_shape,			       profile_mpeg->alpha_th);  if(profile_mpeg->motion && profile_mpeg->motion->enter)    profile_mpeg->motion->enter(profile_mpeg->motion,				profile_mpeg->ref[profile_mpeg->future],				yuv,				profile_mpeg->ref_shape,				profile_mpeg->search_range);  if(profile_mpeg->rate && profile_mpeg->rate->enter)    profile_mpeg->rate->enter(profile_mpeg->rate,			      profile_mpeg->ref[profile_mpeg->future],			      yuv,			      profile_mpeg->ref_shape,			      profile_mpeg->current_coding,			      profile_mpeg->frame_stats);			        /* estimate quantiser scale for frame */  if(profile_mpeg->rate && profile_mpeg->rate->global_estimation)    profile_mpeg->quant_scale =      profile_mpeg->rate->global_estimation(profile_mpeg->rate);  /* initialize block count */  profile_mpeg->intra = profile_mpeg->inter = 0;  /* initialize slice offset */  profile_mpeg->slice_start = 0;  profile_mpeg->total = 0;}/*  profile_mpeg_encode                                                      */

⌨️ 快捷键说明

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