📄 fame_monitor.c
字号:
/* libfame - Fast Assembly MPEG Encoder Library Copyright (C) 2000-2001 Damien Vincent 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 <stdio.h>#include <stdlib.h>#include "fame.h"#include "fame_malloc.h"#include "fame_monitor.h"#ifdef HAS_MMX#include "mad_mmx.h"#include "mae_mmx.h"#include "fetch_mmx.h"#else#include "mad_int.h"#include "mae_int.h"#include "fetch_float.h"#endif#define SCENE_CHANGE_THRESHOLD 10#define SCENE_CHANGE_MAXLENGTH 300static void monitor_init(fame_monitor_t *monitor, int (* retrieve_cb)(fame_frame_statistics_t *stats), unsigned int mb_width, unsigned int mb_height, unsigned int total_frames, unsigned int flags);static void monitor_close(fame_monitor_t *monitor);static void monitor_enter(fame_monitor_t *monitor, unsigned int frame_number, fame_yuv_t **ref, fame_yuv_t *frame, unsigned char *shape, char *coding);fame_frame_statistics_t * monitor_leave(fame_monitor_t *monitor, unsigned int spent, float quant_scale);FAME_CONSTRUCTOR(fame_monitor_t){ FAME_OBJECT(this)->name = "statistics monitoring"; FAME_MONITOR(this)->init = monitor_init; FAME_MONITOR(this)->close = monitor_close; FAME_MONITOR(this)->enter = monitor_enter; FAME_MONITOR(this)->leave = monitor_leave; FAME_MONITOR(this)->flags = 0; return(this);}/* activity *//* *//* Description: *//* returns the activity of the luminance component of the given frame *//* *//* *//* Arguments: *//* fame_yuv_t *frame: frame to compute activity for *//* unsigned char *shape: shape of the given frame (TODO) *//* unsigned int mb_width, mb_height: macroblock's width and height *//* *//* Return value: *//* activity of the frame. */unsigned int activity(fame_yuv_t *frame, unsigned char *shape, unsigned int mb_width, unsigned int mb_height){ int bx, by; int a, p; unsigned long m; unsigned char *input; a = 0; p = frame->p; input = frame->y; for(by = 0; by < mb_height*2; by++) { for(bx = 0; bx < mb_width*2; bx++) { mad_withoutmask(input, p, &m); a+=m; input+=8; } input += (p << 3) - p; } return a;}unsigned int activity2(fame_yuv_t *ref, fame_yuv_t *frame, unsigned char *shape, unsigned int mb_width, unsigned int mb_height){ int bx, by; int a, pi, pr; unsigned long m; unsigned char *input, *rref; a = 0; pi = frame->p; pr = ref->p; input = frame->y; rref = ref->y; for(by = 0; by < mb_height*2; by++) { for(bx = 0; bx < mb_width*2; bx++) { m = MAE8x8_withoutmask(rref, input, NULL, pi); a+=m; input+=8; rref +=8; } input += (pi << 3) - (mb_width << 4); rref += (pr << 3) - (mb_width << 4); } return a;}/* monitor_init *//* *//* Description: *//* Initialise statistics monitor. *//* *//* Arguments: *//* fame_monitor_t *monitor: statistics monitoring *//* store_cb: callback used to send statistics information out to the *//* program using libfame. *//* retrieve_cb: callback called to get initial statistics information *//* from the program. *//* int flags: flags to setup monitoring. *//* *//* Return value: *//* None. */static void monitor_init(fame_monitor_t *monitor, int (* retrieve_cb)(fame_frame_statistics_t *stats), unsigned int mb_width, unsigned int mb_height, unsigned int total_frames, unsigned int flags){ int i; monitor->retrieve_stats_callback = retrieve_cb; monitor->mb_width = mb_width; monitor->mb_height = mb_height; monitor->old_activity = 0; monitor->keyframe = SCENE_CHANGE_MAXLENGTH; monitor->flags = flags; if (monitor->retrieve_stats_callback) monitor->flags |= FAME_MONITOR_LOAD_STATS; if (monitor->flags & FAME_MONITOR_LOAD_STATS) { monitor->global_stats.total_frames = total_frames; monitor->frame_stats_list = (fame_frame_statistics_t *) fame_malloc(total_frames*sizeof(fame_frame_statistics_t)); if (monitor->retrieve_stats_callback) for (i=0; i<total_frames; i++) { monitor->retrieve_stats_callback(&(monitor->frame_stats_list[i])); monitor->global_stats.target_rate += monitor->frame_stats_list[i].target_bits; monitor->global_stats.actual_rate += monitor->frame_stats_list[i].actual_bits; monitor->global_stats.mean_spatial_activity += monitor->frame_stats_list[i].spatial_activity; } monitor->current_frame_stats = monitor->frame_stats_list; } else { monitor->current_frame_stats = (fame_frame_statistics_t *) fame_malloc(sizeof(fame_frame_statistics_t)); monitor->global_stats.total_frames = 0; monitor->frame_stats_list = NULL; }}/* monitor_close *//* *//* Description: *//* Release statistics monitoring. *//* *//* Arguments: *//* fame_monitor_t *monitor: statistics monitoring *//* *//* Return value: *//* None. */static void monitor_close(fame_monitor_t *monitor){ if (monitor->flags && FAME_MONITOR_LOAD_STATS) { if (monitor->frame_stats_list) fame_free(monitor->frame_stats_list); } else { if (monitor->current_frame_stats) fame_free(monitor->current_frame_stats); }}/* monitor_enter *//* *//* Description: *//* Prepare for a new frame. *//* *//* Arguments: *//* fame_monitor_t *monitor: statistics monitoring *//* unsigned int frame_number: the current frame number *//* *//* Return value: *//* None. */static void monitor_enter(struct _fame_monitor_t_ *monitor, unsigned int frame_number, fame_yuv_t **ref, fame_yuv_t *frame, unsigned char *shape, char *coding){ int threshold; if ((monitor->current_frame_stats)&& !(monitor->flags & FAME_MONITOR_LOAD_STATS)) { monitor->current_frame_stats->frame_number = frame_number; monitor->current_frame_stats->spatial_activity = activity2(ref[0], frame, shape, monitor->mb_width, monitor->mb_height); } /* scene change detection */ /* the decay term (keyframe) is here to avoid very long sequences of inter */ /* frames that would result in artifacts due to the DCT/iDCT lack of */ /* accuracy and that would also limit random access. */ threshold = monitor->keyframe*SCENE_CHANGE_THRESHOLD/SCENE_CHANGE_MAXLENGTH; if ((frame_number == 0) || (monitor->current_frame_stats && monitor->current_frame_stats->spatial_activity > (monitor->old_activity + threshold*monitor->mb_width*monitor->mb_height*256))) { monitor->current_frame_stats->coding = 'I'; } else monitor->current_frame_stats->coding = 'P'; if (monitor->current_frame_stats && *coding == 'A') *coding = monitor->current_frame_stats->coding; /* update inter frame counter */ if(*coding == 'I') monitor->keyframe = SCENE_CHANGE_MAXLENGTH; else if(monitor->keyframe > 0) monitor->keyframe--;}/* monitor_leave *//* *//* Description: *//* Finish estimating a frame. *//* *//* Arguments: *//* fame_monitor_t *monitor: statistics monitoring *//* *//* Return value: *//* None. */fame_frame_statistics_t * monitor_leave(fame_monitor_t *monitor, unsigned int spent, float quant_scale){ fame_frame_statistics_t *current = NULL;#ifdef HAS_MMX /* restore floating point context */ asm("emms");#endif if (monitor->current_frame_stats) { monitor->current_frame_stats->actual_bits = spent; monitor->current_frame_stats->quant_scale = quant_scale; monitor->old_activity = monitor->current_frame_stats->spatial_activity; current = monitor->current_frame_stats; if ((monitor->frame_stats_list) && (monitor->current_frame_stats->frame_number <= monitor->global_stats.total_frames)) { /* TODO: update global_stats */ monitor->current_frame_stats++; } } return current;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -