📄 fame_profile_mpeg.c
字号:
/* 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 + -