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

📄 fame_syntax_mpeg1.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 <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_mpeg1.h"#include "table_zigzag_mpeg1.h"#include "table_rlehuff_mpeg1.h"#include "table_dc_mpeg1.h"#include "table_cbp_mpeg1.h"#include "table_quant_mpeg1.h"#include "table_clip_mpeg1.h"#include "table_mv.h"/* The header codes */#define SEQUENCE_START_CODE 0x1b3#define SEQUENCE_END_CODE   0x1b9#define GOP_START_CODE      0x1b8#define PICT_START_CODE     0x100#define SLICE_BASE_CODE     0x101/* The frame type values */#define I_FRAME 1#define P_FRAME 2#define B_FRAME 3static void mpeg1_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 mpeg1_close(fame_syntax_t *syntax);static void mpeg1_use(fame_syntax_t *syntax,		      unsigned char *buffer,		      int size);static int  mpeg1_flush(fame_syntax_t *syntax);static void mpeg1_start_sequence(fame_syntax_t *syntax,				 int width,				 int height,				 int fps_num,				 int fps_den,				 int size,				 int bitrate);static void mpeg1_start_GOP(fame_syntax_t *syntax,			    int frame);static void mpeg1_start_picture(fame_syntax_t *syntax,				char frame_type,				int frame_number,				fame_box_t *box,				int rounding_control,				int search_range);static void mpeg1_start_slice(fame_syntax_t *syntax,			      int vpos,			      int length,			      unsigned char qscale);static void mpeg1_end_slice(fame_syntax_t *syntax);static void mpeg1_end_sequence(fame_syntax_t *syntax);static void mpeg1_predict_vector(fame_syntax_t *syntax,				 int mb_x,				 int mb_y,				 int k,				 fame_motion_vector_t *mv);static void mpeg1_compute_chrominance_vectors(fame_syntax_t *syntax,					      fame_motion_vector_t *vectors,					      unsigned char pattern);static int mpeg1_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 mpeg1_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_mpeg1_t){  FAME_OBJECT(this)->name = "MPEG-1 bitstream syntax";  FAME_SYNTAX(this)->init = mpeg1_init;  FAME_SYNTAX(this)->use = mpeg1_use;  FAME_SYNTAX(this)->flush = mpeg1_flush;  FAME_SYNTAX(this)->start_sequence = mpeg1_start_sequence;  FAME_SYNTAX(this)->start_GOP = mpeg1_start_GOP;  FAME_SYNTAX(this)->start_picture = mpeg1_start_picture;  FAME_SYNTAX(this)->start_slice = mpeg1_start_slice;  FAME_SYNTAX(this)->end_slice = mpeg1_end_slice;  FAME_SYNTAX(this)->end_sequence = mpeg1_end_sequence;  FAME_SYNTAX(this)->predict_vector = mpeg1_predict_vector;  FAME_SYNTAX(this)->compute_chrominance_vectors = mpeg1_compute_chrominance_vectors;  FAME_SYNTAX(this)->write_intra_mb = mpeg1_write_intra_mb;  FAME_SYNTAX(this)->write_inter_mb = mpeg1_write_inter_mb;  FAME_SYNTAX(this)->close = mpeg1_close;  return(this);}static void inline mpeg1_init_vlc_table(fame_vlc_t *vlc){  int z, l;    for(l = -255; l < 256; l++) {    for(z = 0; z < 64; z++) {      if(z < HUFFMAXRUN &&	 l <  rlehuff_max_level[z] &&	 l > -rlehuff_max_level[z])      {	/* encode value and number of z */	vlc->code = huff_table[z][l+rlehuff_max_level[z]-1];	vlc->length =huff_bits[z][l+rlehuff_max_level[z]-1];      }      else      {	/* escape code and encode number of z */	vlc->code = ((0x40+z) << rlehuff_table[l+255].length) |	            rlehuff_table[l+255].code;	vlc->length = rlehuff_table[l+255].length+12;      }      vlc++;    }  }}static void inline mpeg1_next_start_code(fame_bitbuffer_t *buffer){  if(bitbuffer_padding(buffer) != 0)    bitbuffer_write(buffer, 0x00, bitbuffer_padding(buffer));}static void mpeg1_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_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  int qscale;  syntax_mpeg1->mb_width = mb_width;  syntax_mpeg1->mb_height = mb_height;  syntax_mpeg1->fps_num = 25;  syntax_mpeg1->fps_den =  1;  /* initialize vlc_table */  syntax_mpeg1->vlc_table = (fame_vlc_t *) fame_malloc(64*511*sizeof(fame_vlc_t));  mpeg1_init_vlc_table(syntax_mpeg1->vlc_table);  /* center vlc_table */  syntax_mpeg1->vlc_table += 64*255;  /* fill in quantization tables */  if(*intra_matrix) {    /* TODO: flag to write matrix to bitstream */    /* TEMP: use default matrix instead */    FAME_WARNING("Custom quantisation matrix not supported, using default.\n");    *intra_matrix = mpeg1_intra_quantisation_table;  } else {    *intra_matrix = mpeg1_intra_quantisation_table;  }  if(*inter_matrix) {    /* TODO: flag to write matrix to bitstream */    /* TEMP: use default matrix instead */    FAME_WARNING("Custom quantisation matrix not supported, using default.\n");    *inter_matrix = mpeg1_inter_quantisation_table;  } else {    *inter_matrix = mpeg1_inter_quantisation_table;  }  /* fill in intra DC quantizer values */  for(qscale = 0; qscale < 32; qscale++) {    /* MPEG-1 uses linear quantization */    intra_dc_y_scale_table[qscale] = 8;    intra_dc_c_scale_table[qscale] = 8;  }  /* MPEG-1 uses local mismatch control */  *mismatch_type = fame_mismatch_local;}static void mpeg1_close(fame_syntax_t *syntax){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  syntax_mpeg1->vlc_table -= 64*255;  /* uncenter vlc_table */  fame_free(syntax_mpeg1->vlc_table);}static void mpeg1_use(fame_syntax_t *syntax,		      unsigned char *buffer,		      int size){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  bitbuffer_init(&syntax_mpeg1->buffer, buffer, size);}static int mpeg1_flush(fame_syntax_t *syntax){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  return(bitbuffer_flush(&syntax_mpeg1->buffer));}static void mpeg1_start_sequence(fame_syntax_t *syntax,				 int width,				 int height,				 int fps_num,				 int fps_den,				 int size,				 int bitrate){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  int frame_rate = 0;  if(fps_num == 60    && fps_den ==    1) frame_rate = 8; /* 60         fps */  if(fps_num == 60000 && fps_den == 1001) frame_rate = 7; /* 60000/1001 fps */  if(fps_num == 50    && fps_den ==    1) frame_rate = 6; /* 50         fps */  if(fps_num == 30    && fps_den ==    1) frame_rate = 5; /* 30         fps */  if(fps_num == 30000 && fps_den == 1001) frame_rate = 4; /* 30000/1001 fps */  if(fps_num == 25    && fps_den ==    1) frame_rate = 3; /* 25         fps */  if(fps_num == 24    && fps_den ==    1) frame_rate = 2; /* 24         fps */  if(fps_num == 24000 && fps_den == 1001) frame_rate = 1; /* 24000/1001 fps */  if(!frame_rate) {    FAME_WARNING("MPEG-1 doesn't support frame rate %d/%d! "		 "Using 25 fps instead.\n", fps_num, fps_den);    fps_num = 25;    fps_den =  1;    frame_rate = 3; /* 25 fps */  }  syntax_mpeg1->fps_num = fps_num;  syntax_mpeg1->fps_den = fps_den;  /* sequence start code                  */  bitbuffer_write(&syntax_mpeg1->buffer, SEQUENCE_START_CODE, 32);  /* picture size x                       */   bitbuffer_write(&syntax_mpeg1->buffer, width & 0xfff, 12);  /* picture size y                       */  bitbuffer_write(&syntax_mpeg1->buffer, height & 0xfff, 12);  /* pixel aspect ratio                   */  bitbuffer_write(&syntax_mpeg1->buffer, 1,   4);  /* frames per second                    */  bitbuffer_write(&syntax_mpeg1->buffer, frame_rate,   4);  /* bitrate                              */  bitbuffer_write(&syntax_mpeg1->buffer, (bitrate/50) & 0x3ffff, 18);  /* marker                               */  bitbuffer_write(&syntax_mpeg1->buffer, 1, 1);  /* VBV buffer size                      */  bitbuffer_write(&syntax_mpeg1->buffer, size/2048, 10);  /* constrained mode                     */  bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);  /* load intra matrix                    */  bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);  /* load non-intra matrix                */  bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);}static void mpeg1_start_GOP(fame_syntax_t *syntax, int frame){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  int fps_num, fps_den;  fps_num = syntax_mpeg1->fps_num;  fps_den = syntax_mpeg1->fps_den;  /* gop start code                       */  bitbuffer_write(&syntax_mpeg1->buffer, GOP_START_CODE, 32);  /* drop frame flag                      */  bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);  /* timecount hours                      */  bitbuffer_write(&syntax_mpeg1->buffer,		  ((int)(frame*fps_den/(3600*fps_num))) & 0x1f, 5);  /* timecount minutes                    */  bitbuffer_write(&syntax_mpeg1->buffer, 		  (((int)(frame*fps_den/(60*fps_num)))%60) & 0x3f, 6);   /* marker                               */  bitbuffer_write(&syntax_mpeg1->buffer, 1, 1);  /* timecount seconds                    */  bitbuffer_write(&syntax_mpeg1->buffer,		  (((int)(frame*fps_den/fps_num))%60) & 0x3f, 6);  /* timecount frames                     */  bitbuffer_write(&syntax_mpeg1->buffer,		  (frame%(fps_num/fps_den+1)) & 0x3f, 6);  /* closed GOP                           */  bitbuffer_write(&syntax_mpeg1->buffer, 1, 1);  /* broken link                          */  bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);  /* fill out to 8 bytes                  */  bitbuffer_write(&syntax_mpeg1->buffer, 0, 5);}static void mpeg1_start_picture(fame_syntax_t *syntax,				char frame_type,				int frame_number,				fame_box_t *box,				int rounding_control,				int search_range){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  /* compute fcode */  if(search_range < 8)    syntax_mpeg1->f_code = 1;  else if(search_range < 16)    syntax_mpeg1->f_code = 2;  else if(search_range < 32)    syntax_mpeg1->f_code = 3;  else if(search_range < 64)    syntax_mpeg1->f_code = 4;  else if(search_range < 128)    syntax_mpeg1->f_code = 5;  else if(search_range < 256)    syntax_mpeg1->f_code = 6;  else    syntax_mpeg1->f_code = 7;  switch(frame_type) {    case 'I':      syntax_mpeg1->frame_type = frame_type_I;    break;    case 'P':      syntax_mpeg1->frame_type = frame_type_P;    break;    default:      FAME_ERROR("Unsupported picture coding type %c", frame_type);      return;  }  /* picture start code                   */  bitbuffer_write(&syntax_mpeg1->buffer, PICT_START_CODE, 32);  /* frame number                         */  bitbuffer_write(&syntax_mpeg1->buffer, frame_number & 0x3ff, 10);  /* frame type                           */  switch(syntax_mpeg1->frame_type) {    case frame_type_I:      bitbuffer_write(&syntax_mpeg1->buffer, I_FRAME,  3);    break;    case frame_type_P:      bitbuffer_write(&syntax_mpeg1->buffer, P_FRAME,  3);    break;  }  /* vbv delay */  bitbuffer_write(&syntax_mpeg1->buffer, 0xFFFF, 16); /* variable bitrate */  switch(syntax_mpeg1->frame_type) {    case frame_type_I:      bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);  /* end marker */      bitbuffer_write(&syntax_mpeg1->buffer, 0, 2);  /* fill out to 8 bytes */    break;    case frame_type_P:      /* half-pel forward vector */      bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);      /* forward vector range */      bitbuffer_write(&syntax_mpeg1->buffer, syntax_mpeg1->f_code & 0x7, 3);      /* end marker                           */      bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);      /* fill out to 8 bytes                  */      bitbuffer_write(&syntax_mpeg1->buffer, 0, 6);    break;  }}static void mpeg1_start_slice(fame_syntax_t *syntax,			      int vpos,			      int length,			      unsigned char qscale){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  /* reset the predictors to their original values */  syntax_mpeg1->y_dc_pred = 128;  syntax_mpeg1->cr_dc_pred = syntax_mpeg1->cb_dc_pred = 128;  syntax_mpeg1->mv_pred.dx = syntax_mpeg1->mv_pred.dy = 0;  syntax_mpeg1->slice_start = syntax_mpeg1->prev_mb_addr =     vpos * syntax_mpeg1->mb_width - 1;  syntax_mpeg1->slice_length = length;  syntax_mpeg1->previous_coding = motion_intra;  syntax_mpeg1->qscale = qscale;  /* new slice starting at vpos      */  bitbuffer_write(&syntax_mpeg1->buffer, SLICE_BASE_CODE + vpos, 32);  /* quantization scale              */  bitbuffer_write(&syntax_mpeg1->buffer, qscale & 31, 5);  /* end marker                      */  bitbuffer_write(&syntax_mpeg1->buffer, 0, 1);}static void mpeg1_end_slice(fame_syntax_t *syntax){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  mpeg1_next_start_code(&syntax_mpeg1->buffer);  /* align to byte */}static void mpeg1_end_sequence(fame_syntax_t *syntax){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  /* end sequence code                    */  bitbuffer_write(&syntax_mpeg1->buffer, SEQUENCE_END_CODE, 32);}static void mpeg1_predict_vector(fame_syntax_t *syntax,				 int mb_x,				 int mb_y,				 int k,				 fame_motion_vector_t *mv){  fame_syntax_mpeg1_t *syntax_mpeg1 = FAME_SYNTAX_MPEG1(syntax);  mv[k].dx = syntax_mpeg1->mv_pred.dx;

⌨️ 快捷键说明

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