📄 fame_syntax_mpeg4.c
字号:
/* libfame - Fast Assembly MPEG Encoder Library Copyright (C) 2000-2001 Vivien Chappelier Thomas Cougnard 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 <string.h>#include "fame.h"#include "fame_malloc.h"#include "fame_syntax.h"#include "fame_bitbuffer.h"#include "fame_syntax_mpeg4.h"#include "table_zigzag_mpeg4.h"#include "table_rlehuff_mpeg4.h"#include "table_dc_mpeg4.h"#include "table_cae.h"#include "table_quant_mpeg4.h"#include "table_cbp_mpeg4.h"#include "table_mv.h"#include "table_clip_mpeg4.h"#if defined(HAS_MMX)#include "ac_mmx.h"#else#include "ac_int.h"#endif#define OPENDIVX_COMPATIBILITY /* needed to output OpenDivX readable output *//* prediction direction */#define LEFT_PREDICTED 0#define TOP_PREDICTED 1/* maximum size of arithmetic coded sequence */#define CAE_SEQUENCE_LENGTH 4096#define CAE_MAX_HEADING 3#define CAE_MAX_MIDDLE 10#define CAE_MAX_TRAILING 2#define CAE_1_2 0x80000000#define CAE_1_4 0x40000000/* The header codes */#define MPEG4_SEQUENCE_START_CODE 0x1b0#define MPEG4_SEQUENCE_END_CODE 0x1b1#define MPEG4_VISUAL_OBJ_START_CODE 0x1b5#define MPEG4_VIDEO_OBJ_START_CODE 0x100#define MPEG4_VIDEO_OBJ_LAYER_START_CODE 0x120#define MPEG4_GVOP_START_CODE 0x1b3#define MPEG4_VOP_START_CODE 0x1b6#define MPEG4_SLICE_BASE_CODE 0x100/* Visual Object Type */#define MPEG4_Visual_Object_Type_VideoID 0x01#define MPEG4_Visual_Object_Type_still_textureID 0x02#define MPEG4_Visual_Object_Type_meshID 0x03#define MPEG4_Visual_Object_Type_FBA_ID 0x04#define MPEG4_Visual_Object_Type_3D_meshID 0x05/* Video Object type */#define MPEG4_Video_Object_Type_SimpleObject 0x01/* ... */#define MPEG4_Video_Object_Type_FineGranularityScalable 0x12/* Aspect Ratio Info */#define MPEG4_Aspect_Ratio_Info_Square 0x01#define MPEG4_Aspect_Ratio_Info_ExtendedPAR 0x0A/* Video Object layer Shape */#define MPEG4_Video_Object_Layer_Shape_Rectangular 0x00#define MPEG4_Video_Object_Layer_Shape_Binary 0x01#define MPEG4_Video_Object_Layer_Shape_BinaryOnly 0x02#define MPEG4_Video_Object_Layer_Shape_Grayscale 0x03/* VOP Coding Type */#define MPEG4_I_FRAME 0#define MPEG4_P_FRAME 1#define MPEG4_B_FRAME 2/* The fixed values */#define MPEG4_PROFILE_AND_LEVEL 0x01#define MPEG4_IS_VISUAL_OBJ_IDENT 0x00#define MPEG4_VISUAL_OBJ_TYPE 0x01#define MPEG4_VIDEO_SIGNAL_TYPE 0x00#define MPEG4_IS_OBJ_LAYER_IDENT 0x00#define MPEG4_VOL_SHAPE_RECTANGULAR 0x00#define MPEG4_VOL_SHAPE_BINARY_ONLY 0x02#define MPEG4_VOP_TIME_INCR_RES 0x000F /* ?? */static void mpeg4_init(fame_syntax_t *syntax, int mb_width, int mb_height, unsigned char **intra_default_matrix, unsigned char **inter_default_matrix, unsigned char *intra_dc_y_scale_table, unsigned char *intra_dc_c_scale_table, fame_mismatch_t *mismatch_type, unsigned int flags);static void mpeg4_close(fame_syntax_t *syntax);static void mpeg4_use(fame_syntax_t *syntax, unsigned char *buffer, int size);static int mpeg4_flush(fame_syntax_t *syntax);static void mpeg4_start_sequence(fame_syntax_t *syntax, int width, int height, int fps_num, int fps_den, int size, int bitrate);static void mpeg4_start_GOP(fame_syntax_t *syntax, int frame);static void mpeg4_start_picture(fame_syntax_t *syntax, char frame_type, int frame_number, fame_box_t *box, int rounding_control, int search_range);static void mpeg4_start_slice(fame_syntax_t *syntax, int vpos, int length, unsigned char qscale);static void mpeg4_end_slice(fame_syntax_t *syntax);static void mpeg4_end_sequence(fame_syntax_t *syntax);static void mpeg4_predict_vector(fame_syntax_t *syntax, int mb_x, int mb_y, int k, fame_motion_vector_t *mv);static void mpeg4_compute_chrominance_vectors(fame_syntax_t *syntax, fame_motion_vector_t *vectors, unsigned char pattern);static int mpeg4_write_intra_mb(fame_syntax_t *syntax, int mb_x, int mb_y, short *blocks[6], unsigned char *bab, unsigned char *bab_map, fame_bab_t bab_type, int dquant, unsigned char pattern);static int mpeg4_write_inter_mb(fame_syntax_t *syntax, int mb_x, int mb_y, short *blocks[6], unsigned char *bab, unsigned char *bab_map, fame_bab_t bab_type, int dquant, unsigned char pattern, fame_motion_vector_t *forward, fame_motion_vector_t *backward, fame_motion_coding_t motion_coding);FAME_CONSTRUCTOR(fame_syntax_mpeg4_t){ FAME_OBJECT(this)->name = "MPEG-4 bitstream syntax"; FAME_SYNTAX(this)->init = mpeg4_init; FAME_SYNTAX(this)->use = mpeg4_use; FAME_SYNTAX(this)->flush = mpeg4_flush; FAME_SYNTAX(this)->start_sequence = mpeg4_start_sequence; FAME_SYNTAX(this)->start_GOP = mpeg4_start_GOP; FAME_SYNTAX(this)->start_picture = mpeg4_start_picture; FAME_SYNTAX(this)->start_slice = mpeg4_start_slice; FAME_SYNTAX(this)->end_slice = mpeg4_end_slice; FAME_SYNTAX(this)->end_sequence = mpeg4_end_sequence; FAME_SYNTAX(this)->predict_vector = mpeg4_predict_vector; FAME_SYNTAX(this)->compute_chrominance_vectors = mpeg4_compute_chrominance_vectors; FAME_SYNTAX(this)->write_intra_mb = mpeg4_write_intra_mb; FAME_SYNTAX(this)->write_inter_mb = mpeg4_write_inter_mb; FAME_SYNTAX(this)->close = mpeg4_close; return(this);}static const int bab_type_intra_context_weight[4] = { 1, 3, 9, 27};static const int bab_type_intra_vl[81][3] = { { 1, 3, 2 }, { 3, 2, 1 }, { 2, 3, 1 }, { 1, 3, 2 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 3, 2 }, { 1, 2, 3 }, { 2, 3, 1 }, { 3, 2, 1 }, { 1, 2, 3 }, { 1, 2, 3 }, { 3, 2, 1 }, { 1, 2, 3 }, { 2, 1, 3 }, { 3, 2, 1 }, { 1, 2, 3 }, { 1, 2, 3 }, { 2, 3, 1 }, { 1, 2, 3 }, { 3, 2, 1 }, { 2, 3, 1 }, { 1, 2, 3 }, { 3, 2, 1 }, { 2, 3, 1 }, { 3, 2, 1 }, { 3, 2, 1 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 3, 2, 1 }, { 1, 2, 3 }, { 3, 2, 1 }, { 3, 2, 1 }, { 1, 2, 3 }, { 3, 1, 2 }, { 3, 2, 1 }, { 1, 2, 3 }, { 3, 1, 2 }, { 3, 2, 1 }, { 1, 2, 3 }, { 3, 2, 1 }, { 2, 3, 1 }, { 1, 2, 3 }, { 3, 2, 1 }, { 2, 3, 1 }, { 1, 3, 2 }, { 3, 1, 2 }, { 2, 3, 1 }, { 1, 3, 2 }, { 2, 3, 1 }, { 2, 3, 1 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 2, 3, 1 }, { 1, 2, 3 }, { 3, 2, 1 }, { 3, 2, 1 }, { 2, 3, 1 }, { 3, 1, 2 }, { 3, 1, 2 }, { 2, 3, 1 }, { 3, 1, 2 }, { 3, 2, 1 }, { 1, 3, 2 }, { 3, 2, 1 }, { 2, 3, 1 }, { 2, 3, 1 }, { 3, 1, 2 }, { 3, 2, 1 }, { 1, 3, 2 }, { 3, 1, 2 }, { 3, 2, 1 }};static int inline get_min_bit(unsigned int n){ unsigned int i=0; while (n) { i++; n>>=1; } return i;}static void inline mpeg4_init_vlc_tables(fame_vlc_t *intra, fame_vlc_t *inter){ int z, l; int level, run, last, t; for(t = 0; t < 2; t++) { fame_vlc_t *vlc; /* level = [-255;255], run = [0;64], last = [0;1] */ if(t == 0) vlc = intra; else vlc = inter; for(last = 0; last < 2; last++) { char *max_level, *max_run; fame_vlc_t **table; if(t == 0) { if(last == 0) { max_level = rlehuff_intra_max_level; max_run = rlehuff_intra_max_run; table = rlehuff_intra_notlast_vlc; } else { max_level = rlehuff_intra_max_level_last; max_run = rlehuff_intra_max_run_last; table = rlehuff_intra_last_vlc; } } else { if(last == 0) { max_level = rlehuff_inter_max_level; max_run = rlehuff_inter_max_run; table = rlehuff_inter_notlast_vlc; } else { max_level = rlehuff_inter_max_level_last; max_run = rlehuff_inter_max_run_last; table = rlehuff_inter_last_vlc; } } for(l = -255; l < 256; l++) { for(z = 0; z < 64; z++) { level = l; run = z; if(abs(level) <= max_level[run] && run <= max_run[abs(level)]) { /* vlc */ vlc->code = table[run][level].code; vlc->length = table[run][level].length; } else { /* reduce level */ if(level > 0) level -= max_level[run]; else level += max_level[run]; if(abs(level) <= max_level[run] && run <= max_run[abs(level)]) { /* escape + 1 + vlc */ vlc->code = (0x06 << table[run][level].length) | table[run][level].code; vlc->length = table[run][level].length + 8; } else { /* restore level */ if(level > 0) level += max_level[run]; else level -= max_level[run]; /* reduce run */ run -= max_run[abs(level)] + 1; if(abs(level) <= max_level[run] && run <= max_run[abs(level)]) { /* escape + 01 + vlc */ vlc->code = (0x0e << table[run][level].length) | table[run][level].code; vlc->length = table[run][level].length + 9; } else { /* restore run */ run += max_run[abs(level)] + 1; /* escape + 00 + last + run + level */ vlc->code = (unsigned long) ((0x1e + last) << 20) | (z << 14) | (1 << 13) | ((l & 0xfff) << 1) | 1; vlc->length = 30; } } } vlc++; } } } }}static void inline mpeg4_init_symbol(int *symbol){ int i; for(i = 0; i < 2048; i++) { if(i & 1) { if(cae_intra_prob[i >> 1] > 32768) symbol[i] = 65536 - cae_intra_prob[i >> 1]; /* > 0 : LPS */ else symbol[i] = -cae_intra_prob[i >> 1]; /* < 0 : MPS */ } else { if(cae_intra_prob[i >> 1] > 32768) symbol[i] = -(65536 - cae_intra_prob[i >> 1]); /* < 0 : MPS */ else symbol[i] = cae_intra_prob[i >> 1]; /* > 0 : LPS */ } }}static void inline mpeg4_next_start_code(fame_bitbuffer_t *buffer){ bitbuffer_write(buffer, 0, 1); if(bitbuffer_padding(buffer) != 0) bitbuffer_write(buffer, ((1 << bitbuffer_padding(buffer)) - 1), bitbuffer_padding(buffer));}/* The default intra quantisation table */static void mpeg4_init(fame_syntax_t *syntax, int mb_width, int mb_height, unsigned char **intra_matrix, unsigned char **inter_matrix, unsigned char *intra_dc_y_scale_table, unsigned char *intra_dc_c_scale_table, fame_mismatch_t *mismatch_type, unsigned int flags){ fame_syntax_mpeg4_t *syntax_mpeg4 = FAME_SYNTAX_MPEG4(syntax); int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -