📄 fame_decoder_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.*//**************************** mpeg decoder ***********************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "fame.h"#include "fame_malloc.h"#include "fame_decoder.h"#include "fame_decoder_mpeg.h"#include "table_scale.h"#if defined(HAS_MMX)#define arch_enter_state()#define arch_leave_state() asm("emms")#include "transpose_mmx.h"#include "idct_mmx.h"#include "dequantize_mmx.h"#include "reconstruct_mmx.h"#include "pad_int.h" /* TODO */#include "half_mmx.h"#else#define arch_enter_state() #define arch_leave_state() #include "idct_float.h"#include "dequantize_float.h"#include "reconstruct_float.h"#include "pad_int.h"#include "half_int.h"#endifstatic void mpeg_init(fame_decoder_t *decoder, int width, int height, unsigned char *intra_quantisation_table, unsigned char *inter_quantisation_table, unsigned char *intra_dc_y_scale_table, unsigned char *intra_dc_c_scale_table, fame_mismatch_t mismatch_type);static void mpeg_enter(fame_decoder_t *decoder, fame_yuv_t **past_ref, fame_yuv_t **new_ref, fame_yuv_t **future_ref, fame_yuv_t *yuv, unsigned char *shape);static void mpeg_reconstruct_intra_mb(fame_decoder_t *decoder, short x, short y, short *blocks[6], unsigned char q, fame_bab_t bab_type);static void mpeg_reconstruct_inter_mb(fame_decoder_t *decoder, short x, short y, short *blocks[6], fame_motion_vector_t *forward, fame_motion_vector_t *backward, fame_motion_coding_t motion_coding, unsigned char q, fame_bab_t bab_type);static void mpeg_pad(fame_decoder_t *decoder, unsigned char *bab_map, fame_box_t *box);static void mpeg_interpolate(fame_decoder_t *decoder, int rounding);static void mpeg_leave(fame_decoder_t *decoder);static void mpeg_close(fame_decoder_t *decoder);FAME_CONSTRUCTOR(fame_decoder_mpeg_t){ FAME_OBJECT(this)->name = "MPEG decoder"; FAME_DECODER(this)->init = mpeg_init; FAME_DECODER(this)->enter = mpeg_enter; FAME_DECODER(this)->reconstruct_intra_mb = mpeg_reconstruct_intra_mb; FAME_DECODER(this)->reconstruct_inter_mb = mpeg_reconstruct_inter_mb; FAME_DECODER(this)->pad = mpeg_pad; FAME_DECODER(this)->interpolate = mpeg_interpolate; FAME_DECODER(this)->leave = mpeg_leave; FAME_DECODER(this)->close = mpeg_close; return(this);}/* mpeg_init *//* *//* Description: *//* Initialize the decoder. *//* *//* Arguments: *//* fame_decoder_t *decoder: the decoder to initialize *//* int width: width of the frame *//* int height: height of the frame *//* unsigned char *intra_quantisation_table: quantisation matrix for intra *//* unsigned char *inter_quantisation_table: quantisation matrix for inter *//* unsigned char *intra_dc_y_scale_table: quantisation table for DC of Y *//* unsigned char *intra_dc_c_scale_table: quantisation table for DC of C *//* fame_mismatch_t mismatch_type: type of mismatch control *//* *//* Return value: *//* None. */static void mpeg_init(fame_decoder_t *decoder, int width, int height, unsigned char *iqtable, unsigned char *niqtable, unsigned char *intra_dc_y_scale_table, unsigned char *intra_dc_c_scale_table, fame_mismatch_t mismatch_type){ fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder); int i, q;#ifdef HAS_MMX asm("emms");#endif /* set width and height */ decoder_mpeg->width = width; decoder_mpeg->height = height; decoder_mpeg->mismatch = mismatch_type;#ifdef HAS_MMX if(mismatch_type == fame_mismatch_global) for(i = 0; i < 6; i++) { decoder_mpeg->mismatch_accumulator[i] = (dct_t *) fame_malloc((decoder_mpeg->width>>3)* (decoder_mpeg->height>>3)*sizeof(dct_t)); memset(decoder_mpeg->mismatch_accumulator[i], 0, (decoder_mpeg->width>>3)* (decoder_mpeg->height>>3)*sizeof(dct_t)); }#endif /* compute quantization matrixes */ for(q = 1; q < 32; q++) { /* compute the intra quantisation and dequantisation DC scaler */#ifdef HAS_MMX decoder_mpeg->yidqmatrixes[q][0] = (short) (intra_dc_y_scale_table[q] << 3); decoder_mpeg->cidqmatrixes[q][0] = (short) (intra_dc_c_scale_table[q] << 3);#else decoder_mpeg->yidqmatrixes[q][0] = intra_dc_y_scale_table[q]; decoder_mpeg->cidqmatrixes[q][0] = intra_dc_c_scale_table[q];#endif /* compute the intra quantisation and dequantisation matrix */ for(i = 1; i < 64; i++) {#ifdef HAS_MMX decoder_mpeg->yidqmatrixes[q][i] = decoder_mpeg->cidqmatrixes[q][i] = (short) q*iqtable[i];#else decoder_mpeg->yidqmatrixes[q][i] = decoder_mpeg->cidqmatrixes[q][i] = q*iqtable[i];#endif } /* compute the inter quantisation and dequantisation matrix */ for(i = 0; i < 64; i++) {#ifdef HAS_MMX decoder_mpeg->nidqmatrixes[q][i] = (short) q*niqtable[i]; decoder_mpeg->psmatrix[i] = (short) ((double)(1UL << 16) * prescale[i] + 0.5);#else decoder_mpeg->nidqmatrixes[q][i] = q*niqtable[i]; decoder_mpeg->psmatrix[i] = prescale[i];#endif } }}/* mpeg_enter *//* *//* Description: *//* Start encoding a new picture. *//* *//* Arguments: *//* fame_decoder_t *decoder: the decoder *//* fame_yuv_t **past_ref: past reference images *//* fame_yuv_t **new_ref: new reconstructed reference images *//* fame_yuv_t **future_ref: future reference images *//* fame_yuv_t *yuv: source image *//* unsigned char *shape: shape binary mask *//* *//* Return value: *//* None. */ static void mpeg_enter(fame_decoder_t *decoder, fame_yuv_t **past_ref, fame_yuv_t **new_ref, fame_yuv_t **future_ref, fame_yuv_t *yuv, unsigned char *shape){ fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder); /* Make pointers on the input frame and reference frame */ decoder_mpeg->input = yuv; decoder_mpeg->past_ref = past_ref; decoder_mpeg->new_ref = new_ref; decoder_mpeg->future_ref = future_ref; decoder_mpeg->shape = shape; arch_enter_state();}/* mpeg_pad_mb *//* *//* Description: *//* Perform repetitive padding for motion estimation on a border block. *//* *//* Arguments: *//* fame_decoder_t *decoder: the decoder *//* short x: the x location of the macroblock in macroblock units *//* short y: the y location of the macroblock in macroblock units *//* fame_box_t box: bounding box *//* *//* Return value: *//* None. */static void mpeg_pad_mb(fame_decoder_t *decoder, short x, short y){ fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder); int spitch, rpitch; unsigned char *shape, *Y, *U, *V; /* Make offsets to blocks */ spitch = decoder_mpeg->input->p; shape = decoder_mpeg->shape + (y << 4) * spitch + (x << 4); /* Make offsets to blocks */ rpitch = decoder_mpeg->new_ref[0]->p; Y = decoder_mpeg->new_ref[0]->y + (y << 4) * rpitch + (x << 4); /* Y */ U = decoder_mpeg->new_ref[0]->u + (y << 3) * (rpitch >> 1) + (x << 3); /*Cb*/ V = decoder_mpeg->new_ref[0]->v + (y << 3) * (rpitch >> 1) + (x << 3); /*Cr*/ repetitive_fill_Y(Y, shape, rpitch, spitch); repetitive_fill_C(U, shape, rpitch, spitch); repetitive_fill_C(V, shape, rpitch, spitch);}/* mpeg_reconstruct_intra_mb *//* *//* Description: *//* Reconstruct an intra macroblock for further motion estimation. *//* *//* Arguments: *//* fame_decoder_t *decoder: the decoder *//* bitbuffer_t *bb: a bit buffer to write the resulting encoded data to. *//* short x: the x location of the macroblock in macroblock units *//* short y: the y location of the macroblock in macroblock units *//* short *blocks[6]: the DCT coded blocks *//* unsigned char q: the quantizer scale for this block *//* fame_bab_t bab_type: binary alpha block type *//* *//* Return value: *//* None. */static void mpeg_reconstruct_intra_mb(fame_decoder_t *decoder, short x, short y, short *blocks[6], unsigned char q, fame_bab_t bab_type){ fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder); unsigned long offset0,offset1,offset2,offset3,offset4,offset5; int pitch; void (* dequantize)(short *block, dct_t *cache, dct_t *dqmatrix, dct_t *psmatrix, dct_t *mismatch); void (* idct_)(dct_t *block); void (* reconstruct_)(unsigned char *plane, dct_t *block, int pitch); pitch = decoder_mpeg->new_ref[0]->p; /* Make offsets to blocks */ offset0 = (y << 4) * pitch + (x << 4); /* Y(0,0) */ offset1 = offset0 + 8; /* Y(0,1) */ offset2 = offset0 + (pitch << 3); /* Y(1,0) */ offset3 = offset2 + 8; /* Y(1,1) */ offset4 = (y << 3) * (pitch >> 1) + (x << 3); /* Cb */ offset5 = (y << 3) * (pitch >> 1) + (x << 3); /* Cr */ if(decoder_mpeg->mismatch == fame_mismatch_local) dequantize = dequantize_intra_local; else dequantize = dequantize_intra_global; idct_ = idct; reconstruct_ = reconstruct; /* Reconstruct blocks */ /* Y(0,0) */ dequantize(blocks[0], decoder_mpeg->tmpblock, decoder_mpeg->yidqmatrixes[q], decoder_mpeg->psmatrix,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -