mpeg2coder.cc

来自「Motion JPEG编解码器源代码」· CC 代码 · 共 874 行 · 第 1/2 页

CC
874
字号
/* mpeg2coder.hh - MPEG2 packed bit / VLC syntax coding engine *//*  (C) 2003 Andrew Stevens *//*  This Software and modifications to existing software are free *  software; you can redistribute them and/or modify it under the terms *  of the GNU General Public License as published by the Free *  Software Foundation; either version 2 of the License, or (at your *  option) any later version. * *  This program 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 *  General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * *//* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. *//* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose.  In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders.  Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */#include <config.h>#include <stdio.h>#include <math.h>#include <cassert>#include "mpeg2syntaxcodes.h"#include "tables.h"#include "mpeg2coder.hh"#include "elemstrmwriter.hh"#include "mpeg2encoder.hh"#include "picture.hh"MPEG2CodingBuf::MPEG2CodingBuf( EncoderParams &_encparams, ElemStrmWriter &_writer ) :    ElemStrmFragBuf( _writer ),    encparams( _encparams ){}/* convert frame number to time_code * * drop_frame not implemented */int MPEG2CodingBuf::FrameToTimeCode(int gop_timecode0_frame){	int frame = gop_timecode0_frame;	int fps, pict, sec, minute, hour, tc;	/* Note: no drop_frame_flag support here, so we're simply rounding	   the frame rate as per 6.3.8 13818-2	*/	fps = (int)(encparams.decode_frame_rate+0.5);	pict = frame%fps;	frame = (frame-pict)/fps;	sec = frame%60;	frame = (frame-sec)/60;	minute = frame%60;	frame = (frame-minute)/60;	hour = frame%24;	tc = (hour<<19) | (minute<<13) | (1<<12) | (sec<<6) | pict;	return tc;}/**************** * * generate sequence header (6.2.2.1, 6.3.3) * ***************/void MPEG2CodingBuf::PutSeqHdr(){	int i;    assert( Aligned() );	PutBits(SEQ_START_CODE,32); /* sequence_header_code */	PutBits(encparams.horizontal_size,12); /* horizontal_size_value */	PutBits(encparams.vertical_size,12); /* vertical_size_value */	PutBits(encparams.aspectratio,4); /* aspect_ratio_information */	PutBits(encparams.frame_rate_code,4); /* frame_rate_code */	/* MPEG-1 VBR is FFFF rate code. 	   MPEG-2 VBR is a matter of mux-ing.  The ceiling bit_rate is always	   sent 	*/	if(encparams.mpeg1 && (encparams.quant_floor != 0 || encparams.still_size > 0) ) {		PutBits(0xfffff,18);	} else {		PutBits((int)ceil(encparams.bit_rate/400.0),18); /* bit_rate_value */	}	PutBits(1,1); /* marker_bit */	PutBits(encparams.vbv_buffer_code,10); /* vbv_buffer_size_value */	PutBits(encparams.constrparms,1); /* constrained_parameters_flag */	PutBits(encparams.load_iquant,1); /* load_intra_quantizer_matrix */	if (encparams.load_iquant)		for (i=0; i<64; i++)  /* matrices are always downloaded in zig-zag order */			PutBits(encparams.intra_q[zig_zag_scan[i]],8); /* intra_quantizer_matrix */	PutBits(encparams.load_niquant,1); /* load_non_intra_quantizer_matrix */	if (encparams.load_niquant)		for (i=0; i<64; i++)			PutBits(encparams.inter_q[zig_zag_scan[i]],8); /* non_intra_quantizer_matrix */	if (!encparams.mpeg1)	{		PutSeqExt();		PutSeqDispExt();	}	AlignBits();}/************************** * * generate sequence extension (6.2.2.3, 6.3.5) header (MPEG-2 only) * *************************/void MPEG2CodingBuf::PutSeqExt(){	assert( Aligned() );	PutBits(EXT_START_CODE,32); /* extension_start_code */	PutBits(SEQ_ID,4); /* extension_start_code_identifier */	PutBits((encparams.profile<<4)|encparams.level,8); /* profile_and_level_indication */	PutBits(encparams.prog_seq,1); /* progressive sequence */	PutBits(CHROMA420,2); /* chroma_format */	PutBits(encparams.horizontal_size>>12,2); /* horizontal_size_extension */	PutBits(encparams.vertical_size>>12,2); /* vertical_size_extension */	PutBits(((int)ceil(encparams.bit_rate/400.0))>>18,12); /* bit_rate_extension */	PutBits(1,1); /* marker_bit */	PutBits(encparams.vbv_buffer_code>>10,8); /* vbv_buffer_size_extension */	PutBits(0,1); /* low_delay  -- currently not implemented */	PutBits(0,2); /* frame_rate_extension_n */	PutBits(0,5); /* frame_rate_extension_d */    AlignBits();}/***************************** *  * generate sequence display extension (6.2.2.4, 6.3.6) * ****************************/void MPEG2CodingBuf::PutSeqDispExt(){	assert(Aligned() );	PutBits(EXT_START_CODE,32); /* extension_start_code */	PutBits(DISP_ID,4); /* extension_start_code_identifier */	PutBits(encparams.video_format,3); /* video_format */	PutBits(1,1); /* colour_description */	PutBits(encparams.color_primaries,8); /* colour_primaries */	PutBits(encparams.transfer_characteristics,8); /* transfer_characteristics */	PutBits(encparams.matrix_coefficients,8); /* matrix_coefficients */	PutBits(encparams.display_horizontal_size,14); /* display_horizontal_size */	PutBits(1,1); /* marker_bit */	PutBits(encparams.display_vertical_size,14); /* display_vertical_size */    AlignBits();}/******************************** * * Output user data (6.2.2.2.2, 6.3.4.1) * * TODO: string must not embed start codes 0x00 0x00 0x00 0xXX * *******************************/void MPEG2CodingBuf::PutUserData(const uint8_t *userdata, int len){	int i;	assert( Aligned() );	PutBits(USER_START_CODE,32); /* user_data_start_code */	for( i =0; i < len; ++i )		PutBits(userdata[i],8);}/* generate group of pictures header (6.2.2.6, 6.3.9) * * uses tc0 (timecode of first frame) and frame0 (number of first frame) */void MPEG2CodingBuf::PutGopHdr(int frame,int closed_gop ){	int tc;	AlignBits();	PutBits(GOP_START_CODE,32); /* group_start_code */	tc = FrameToTimeCode(frame);	PutBits(tc,25); /* time_code */	PutBits(closed_gop,1); /* closed_gop */	PutBits(0,1); /* broken_link */    AlignBits();}/* generate sequence_end_code (6.2.2) */void MPEG2CodingBuf::PutSeqEnd(void){	AlignBits();	PutBits(SEQ_END_CODE,32);}/* generate variable length codes for an intra-coded block (6.2.6, 6.3.17) */void MPEG2CodingBuf::PutIntraBlk(Picture *picture, int16_t *blk, int cc){	int n, dct_diff, run, signed_level;	/* DC coefficient (7.2.1) */	dct_diff = blk[0] - picture->dc_dct_pred[cc]; /* difference to previous block */	picture->dc_dct_pred[cc] = blk[0];	if (cc==0)		PutDClum(dct_diff);	else		PutDCchrom(dct_diff);	/* AC coefficients (7.2.2) */	run = 0;	const uint8_t *scan_tbl = (picture->altscan ? alternate_scan : zig_zag_scan);	for (n=1; n<64; n++)	{		/* use appropriate entropy scanning pattern */		signed_level = blk[scan_tbl[n]];		if (signed_level!=0)		{			PutAC(run,signed_level,picture->intravlc);			run = 0;		}		else			run++; /* count zero coefficients */	}	/* End of Block -- normative block punctuation */	if (picture->intravlc)		PutBits(6,4); /* 0110 (Table B-15) */	else		PutBits(2,2); /* 10 (Table B-14) */}/* generate variable length codes for a non-intra-coded block (6.2.6, 6.3.17) */void  MPEG2CodingBuf::PutNonIntraBlk(Picture *picture, int16_t *blk){	int n, run, signed_level, first;	run = 0;	first = 1;	for (n=0; n<64; n++)	{		/* use appropriate entropy scanning pattern */		signed_level = blk[(picture->altscan ? alternate_scan : zig_zag_scan)[n]];		if (signed_level!=0)		{			if (first)			{				/* first coefficient in non-intra block */				PutACfirst(run,signed_level);				first = 0;			}			else				PutAC(run,signed_level,0);			run = 0;		}		else			run++; /* count zero coefficients */	}	/* End of Block -- normative block punctuation  */	PutBits(2,2);}/* generate variable length code for a motion vector component (7.6.3.1) */void  MPEG2CodingBuf::PutMV(int dmv, int f_code){  int r_size, f, vmin, vmax, dv, temp, motion_code, motion_residual;  r_size = f_code - 1; /* number of fixed length code ('residual') bits */  f = 1<<r_size;  vmin = -16*f; /* lower range limit */  vmax = 16*f - 1; /* upper range limit */  dv = 32*f;  /* fold vector difference into [vmin...vmax] */  if (dmv>vmax)    dmv-= dv;  else if (dmv<vmin)    dmv+= dv;  /* check value */  if (dmv<vmin || dmv>vmax)  {      fprintf(stderr,"Too large MV %03d not in [%04d..:%03d]\n", dmv, vmin, vmax);      exit(1);  }  /* split dmv into motion_code and motion_residual */  temp = ((dmv<0) ? -dmv : dmv) + f - 1;  motion_code = temp>>r_size;  if (dmv<0)    motion_code = -motion_code;  motion_residual = temp & (f-1);  PutMotionCode(motion_code); /* variable length code */  if (r_size!=0 && motion_code!=0)    PutBits(motion_residual,r_size); /* fixed length code */}/* generate variable length code for DC coefficient (7.2.1) */void MPEG2CodingBuf::PutDC(const sVLCtable *tab, int val){	int absval, size;	absval = abs(val);    assert(absval<=encparams.dctsatlim);	/* compute dct_dc_size */	size = 0;	while (absval)	{		absval >>= 1;		size++;	}	/* generate VLC for dct_dc_size (Table B-12 or B-13) */	PutBits(tab[size].code,tab[size].len);	/* append fixed length code (dc_dct_differential) */	if (size!=0)	{		if (val>=0)			absval = val;		else			absval = val + (1<<size) - 1; /* val + (2 ^ size) - 1 */		PutBits(absval,size);	}}/* generate variable length code for DC coefficient (7.2.1) */int MPEG2CodingBuf::DC_bits(const sVLCtable *tab, int val){	int absval, size;	absval = abs(val);	/* compute dct_dc_size */	size = 0;	while (absval)	{		absval >>= 1;		size++;	}	/* generate VLC for dct_dc_size (Table B-12 or B-13) */	return tab[size].len+size;}/* generate variable length code for first coefficient * of a non-intra block (7.2.2.2) */void MPEG2CodingBuf::PutACfirst(int run, int val){	if (run==0 && (val==1 || val==-1)) /* these are treated differently */		PutBits(2|(val<0),2); /* generate '1s' (s=sign), (Table B-14, line 2) */	else		PutAC(run,val,0); /* no difference for all others */}/* generate variable length code for other DCT coefficients (7.2.2) */void MPEG2CodingBuf::PutAC(int run, int signed_level, int vlcformat){	int level, len;	const VLCtable *ptab = NULL;	level = abs(signed_level);	/* make sure run and level are valid */	if (run<0 || run>63 || level==0 || level>encparams.dctsatlim)	{		assert( signed_level == -(encparams.dctsatlim+1)); 	/* Negative range is actually 1 more */	}	len = 0;	if (run<2 && level<41)	{		/* vlcformat selects either of Table B-14 / B-15 */		if (vlcformat)			ptab = &dct_code_tab1a[run][level-1];		else			ptab = &dct_code_tab1[run][level-1];		len = ptab->len;	}	else if (run<32 && level<6)	{		/* vlcformat selects either of Table B-14 / B-15 */		if (vlcformat)			ptab = &dct_code_tab2a[run-2][level-1];		else			ptab = &dct_code_tab2[run-2][level-1];		len = ptab->len;	}

⌨️ 快捷键说明

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