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

📄 getpic.c

📁 DVD转换到AVI的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 "global.h"
#include "getbit.h"

/* private prototypes*/
__forceinline static void Update_Picture_Buffers(void);
__forceinline static void picture_data(void);
__forceinline static int slice(int MBAmax);
__forceinline static void macroblock_modes(int *pmacroblock_type, int *pmotion_type, 
	int *pmotion_vector_count, int *pmv_format, int *pdmv, int *pmvscale, int *pdct_type);
__forceinline static void Clear_Block(int count);
__forceinline static void Add_Block(int count, int bx, int by, int dct_type, int addflag);
__forceinline static void motion_compensation(int MBA, int macroblock_type, int motion_type,
	int PMV[2][2][2], int motion_vertical_field_select[2][2], int dmvector[2], int dct_type);
__forceinline static void skipped_macroblock(int dc_dct_pred[3], int PMV[2][2][2], 
	int *motion_type, int motion_vertical_field_select[2][2], int *macroblock_type);
__forceinline static int start_of_slice(int *MBA, int *MBAinc, int dc_dct_pred[3], int PMV[2][2][2]);
__forceinline static int decode_macroblock(int *macroblock_type, int *motion_type, int *dct_type,
	int PMV[2][2][2], int dc_dct_pred[3], int motion_vertical_field_select[2][2], int dmvector[2]);
__forceinline static void Decode_MPEG2_Intra_Block(int comp, int dc_dct_pred[]);
__forceinline static void Decode_MPEG2_Non_Intra_Block(int comp);

__forceinline static int Get_macroblock_type(void);
__forceinline static int Get_I_macroblock_type(void);
__forceinline static int Get_P_macroblock_type(void);
__forceinline static int Get_B_macroblock_type(void);
__forceinline static int Get_D_macroblock_type(void);
__forceinline static int Get_coded_block_pattern(void);
__forceinline static int Get_macroblock_address_increment(void);
__forceinline static int Get_Luma_DC_dct_diff(void);
__forceinline static int Get_Chroma_DC_dct_diff(void);

__forceinline static void form_predictions(int bx, int by, int macroblock_type, int motion_type, 
	int PMV[2][2][2], int motion_vertical_field_select[2][2], int dmvector[2]);
static void form_prediction(unsigned char *src[], int sfield, unsigned char *dst[], int dfield, 
	int lx, int lx2, int w, int h, int x, int y, int dx, int dy, int average_flag);
__forceinline static void form_component_prediction(unsigned char *src, unsigned char *dst,
	int lx, int lx2, int w, int h, int x, int y, int dx, int dy, int average_flag);

unsigned char cc_table[12] = {
	0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2
};

void Decode_Picture(int ref, unsigned char *dst, int pitch)
{
	if (picture_structure==FRAME_PICTURE && Second_Field)
		Second_Field = 0;

	if (picture_coding_type!=B_TYPE)
	{
		pf_forward = pf_backward;
		pf_backward = pf_current;
	}

	Update_Picture_Buffers();

	picture_data();

	if (ref && (picture_structure==FRAME_PICTURE || Second_Field))
	{
		if (picture_coding_type==B_TYPE)
			FrametoRGB(auxframe, pf_current, dst, pitch);
		else
			FrametoRGB(forward_reference_frame, pf_forward, dst, pitch);
	}

	if (picture_structure!=FRAME_PICTURE)
		Second_Field = !Second_Field;
}

/* reuse old picture buffers as soon as they are no longer needed */
static void Update_Picture_Buffers()
{                           
	int cc;              /* color component index */
	unsigned char *tmp;  /* temporary swap pointer */

	for (cc=0; cc<3; cc++)
	{
		/* B pictures  do not need to be save for future reference */
		if (picture_coding_type==B_TYPE)
			current_frame[cc] = auxframe[cc];
		else
		{
			if (!Second_Field)
			{
				/* only update at the beginning of the coded frame */
				tmp = forward_reference_frame[cc];

				/* the previously decoded reference frame is stored coincident with the 
				   location where the backward reference frame is stored (backwards 
				   prediction is not needed in P pictures) */
				forward_reference_frame[cc] = backward_reference_frame[cc];

				/* update pointer for potential future B pictures */
				backward_reference_frame[cc] = tmp;
			}

			/* can erase over old backward reference frame since it is not used
			   in a P picture, and since any subsequent B pictures will use the 
			   previously decoded I or P frame as the backward_reference_frame */
			current_frame[cc] = backward_reference_frame[cc];
		}

	    if (picture_structure==BOTTOM_FIELD)
			current_frame[cc] += (cc==0) ? Coded_Picture_Width : Chroma_Width;
	}
}

/* decode all macroblocks of the current picture */
/* stages described in ISO/IEC 13818-2 section 7 */
static void picture_data()
{
	int MBAmax;

	/* number of macroblocks per picture */
	MBAmax = mb_width*mb_height;

	if (picture_structure!=FRAME_PICTURE)
		MBAmax>>=1;

	for (;;)
		if (slice(MBAmax)<0)
			return;
}

/* decode all macroblocks of the current picture */
/* ISO/IEC 13818-2 section 6.3.16 */
/* return 0 : go to next slice */
/* return -1: go to next picture */
static int slice(int MBAmax)
{
	int MBA = 0, MBAinc =0, macroblock_type, motion_type, dct_type, ret;
	int dc_dct_pred[3], PMV[2][2][2], motion_vertical_field_select[2][2], dmvector[2];

	if ((ret=start_of_slice(&MBA, &MBAinc, dc_dct_pred, PMV))!=1)
		return ret;

	for (;;)
	{
		/* this is how we properly exit out of picture */
		if (MBA>=MBAmax) return -1;		// all macroblocks decoded

		if (MBAinc==0)
		{
			if (!Show_Bits(23) || Fault_Flag)	// next_start_code or fault
			{
resync:
				Fault_Flag = 0;
				return 0;	// trigger: go to next slice
			}
			else /* neither next_start_code nor Fault_Flag */
			{
				/* decode macroblock address increment */
				MBAinc = Get_macroblock_address_increment();
				if (Fault_Flag) goto resync;
			}
		}

		if (MBAinc==1) /* not skipped */
		{
			if (!decode_macroblock(&macroblock_type, &motion_type, &dct_type, PMV,
				dc_dct_pred, motion_vertical_field_select, dmvector))
				goto resync;
		}
		else /* MBAinc!=1: skipped macroblock */
			/* ISO/IEC 13818-2 section 7.6.6 */
			skipped_macroblock(dc_dct_pred, PMV, &motion_type, motion_vertical_field_select, &macroblock_type);

		/* ISO/IEC 13818-2 section 7.6 */
		motion_compensation(MBA, macroblock_type, motion_type, PMV,
							motion_vertical_field_select, dmvector, dct_type);

		/* advance to next macroblock */
		MBA++; MBAinc--;

		if (MBA>=MBAmax) return -1;		// all macroblocks decoded
	}
}

/* ISO/IEC 13818-2 section 6.3.17.1: Macroblock modes */
static void macroblock_modes(int *pmacroblock_type, int *pmotion_type,
							 int *pmotion_vector_count, int *pmv_format,
							 int *pdmv, int *pmvscale, int *pdct_type)
{
	int macroblock_type, motion_type, motion_vector_count;
	int mv_format, dmv, mvscale, dct_type;

	/* get macroblock_type */
	macroblock_type = Get_macroblock_type();
	if (Fault_Flag) return;

	/* get frame/field motion type */
	if (macroblock_type & (MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD))
	{
		if (picture_structure==FRAME_PICTURE)
			motion_type = frame_pred_frame_dct ? MC_FRAME : Get_Bits(2);
		else
			motion_type = Get_Bits(2);
    }
	else if ((macroblock_type & MACROBLOCK_INTRA) && concealment_motion_vectors)
		motion_type = (picture_structure==FRAME_PICTURE) ? MC_FRAME : MC_FIELD;

	/* derive motion_vector_count, mv_format and dmv, (table 6-17, 6-18) */
	if (picture_structure==FRAME_PICTURE)
	{
		motion_vector_count = (motion_type==MC_FIELD) ? 2 : 1;
		mv_format = (motion_type==MC_FRAME) ? MV_FRAME : MV_FIELD;
	}
	else
	{
		motion_vector_count = (motion_type==MC_16X8) ? 2 : 1;
		mv_format = MV_FIELD;
	}
	
	dmv = (motion_type==MC_DMV); /* dual prime */

	/*
	   field mv predictions in frame pictures have to be scaled
	   ISO/IEC 13818-2 section 7.6.3.1 Decoding the motion vectors
	*/
	mvscale = (mv_format==MV_FIELD && picture_structure==FRAME_PICTURE);

	/* get dct_type (frame DCT / field DCT) */
	dct_type = (picture_structure==FRAME_PICTURE) && (!frame_pred_frame_dct)
				&& (macroblock_type & (MACROBLOCK_PATTERN|MACROBLOCK_INTRA)) ? Get_Bits(1) : 0;

	/* return values */
	*pmacroblock_type = macroblock_type;
	*pmotion_type = motion_type;
	*pmotion_vector_count = motion_vector_count;
	*pmv_format = mv_format;
	*pdmv = dmv;
	*pmvscale = mvscale;
	*pdct_type = dct_type;
}

/* move/add 8x8-Block from block[comp] to backward_reference_frame */
/* copy reconstructed 8x8 block from block[comp] to current_frame[]
   ISO/IEC 13818-2 section 7.6.8: Adding prediction and coefficient data
   This stage also embodies some of the operations implied by:
   - ISO/IEC 13818-2 section 7.6.7: Combining predictions
   - ISO/IEC 13818-2 section 6.1.3: Macroblock
*/
static void Add_Block(int count, int bx, int by, int dct_type, int addflag)
{
	static const __int64 mmmask_128 = 0x0080008000800080;

	int comp, cc, iincr, bxh, byh;
	unsigned char *rfp;
	short *Block_Ptr;

	for (comp=0; comp<count; comp++)
	{
		Block_Ptr = block[comp];
		cc = cc_table[comp];

		if (cc==0)
		{
			if (picture_structure==FRAME_PICTURE)
			{
				if (dct_type)
				{
					rfp = current_frame[0] + Coded_Picture_Width*(by+((comp&2)>>1)) + bx + ((comp&1)<<3);
					iincr = Coded_Picture_Width<<1;
				}
				else
				{
					rfp = current_frame[0] + Coded_Picture_Width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
					iincr = Coded_Picture_Width;
				}
			}
			else
			{
				rfp = current_frame[0] + (Coded_Picture_Width<<1)*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
				iincr = Coded_Picture_Width<<1;
			}
		}
		else
		{
			if (chroma_format!=CHROMA444)
				bxh = bx >> 1;
			if (chroma_format==CHROMA420)
				byh = by >> 1;

			if (picture_structure==FRAME_PICTURE)
			{
				if (dct_type && chroma_format!=CHROMA420)
				{
					/* field DCT coding */
					rfp = current_frame[cc] + Chroma_Width*(byh+((comp&2)>>1)) + bxh + (comp&8);
					iincr = Chroma_Width<<1;
				}
				else
				{
					/* frame DCT coding */
					rfp = current_frame[cc] + Chroma_Width*(byh+((comp&2)<<2)) + bxh + (comp&8);
					iincr = Chroma_Width;
				}
			}
			else
			{
				/* field picture */
				rfp = current_frame[cc] + (Chroma_Width<<1)*(byh+((comp&2)<<2)) + bxh + (comp&8);
				iincr = Chroma_Width<<1;
			}
		}

		if (addflag)
		{
			__asm
			{
				pxor		mm0, mm0
				mov			eax, [rfp]
				mov			ebx, [Block_Ptr]
				mov			edi, 8
addon:
				movq		mm2, [ebx+8]

				movq		mm3, [eax]
				movq		mm4, mm3

				movq		mm1, [ebx]
				punpckhbw	mm3, mm0

				paddsw		mm3, mm2
				packuswb	mm3, mm0

				punpcklbw	mm4, mm0
				psllq		mm3, 32

				paddsw		mm4, mm1
				packuswb	mm4, mm0

				por			mm3, mm4			
				add			ebx, 16

				sub			edi, 0x01
				movq		[eax], mm3

				add			eax, [iincr]
				cmp			edi, 0x00
				jg			addon
			}
		}
		else
		{
			__asm
			{
				mov			eax, [rfp]
				mov			ebx, [Block_Ptr]
				mov			edi, 8

				pxor		mm0, mm0
				movq		mm7, [mmmask_128]
addoff:
				movq		mm3, [ebx+8]
				movq		mm4, [ebx]

				paddsw		mm3, mm7
				paddsw		mm4, mm7

				packuswb	mm3, mm0
				packuswb	mm4, mm0

				psllq		mm3, 32
				por			mm3, mm4
			
				add			ebx, 16
				sub			edi, 0x01

				movq		[eax], mm3

				add			eax, [iincr]
				cmp			edi, 0x00
				jg			addoff
			}
		}
	}
}

/* set scratch pad macroblock to zero */
static void Clear_Block(int count)
{
	int comp;
	short *Block_Ptr;

	for (comp=0; comp<count; comp++)
	{
		Block_Ptr = block[comp];

		__asm
		{
			mov			eax, [Block_Ptr];
			pxor		mm0, mm0;
			movq		[eax+0 ], mm0;
			movq		[eax+8 ], mm0;
			movq		[eax+16], mm0;
			movq		[eax+24], mm0;
			movq		[eax+32], mm0;
			movq		[eax+40], mm0;
			movq		[eax+48], mm0;
			movq		[eax+56], mm0;
			movq		[eax+64], mm0;
			movq		[eax+72], mm0;
			movq		[eax+80], mm0;
			movq		[eax+88], mm0;
			movq		[eax+96], mm0;
			movq		[eax+104],mm0;
			movq		[eax+112],mm0;
			movq		[eax+120],mm0;
		}
	}
}

/* ISO/IEC 13818-2 section 7.6 */
static void motion_compensation(int MBA, int macroblock_type, int motion_type, 
								int PMV[2][2][2], int motion_vertical_field_select[2][2],
								int dmvector[2], int dct_type)
{
	int bx, by;
	int comp;

	/* derive current macroblock position within picture */
	/* ISO/IEC 13818-2 section 6.3.1.6 and 6.3.1.7 */
	bx = 16*(MBA%mb_width);
	by = 16*(MBA/mb_width);

	/* motion compensation */
	if (!(macroblock_type & MACROBLOCK_INTRA))
		form_predictions(bx, by, macroblock_type, motion_type, PMV, 
			motion_vertical_field_select, dmvector);

	switch (IDCT_Flag)
	{
		case IDCT_MMX:
			for (comp=0; comp<block_count; comp++)
				MMX_IDCT(block[comp]);
			break;

		case IDCT_FPU:
			__asm emms;
			for (comp=0; comp<block_count; comp++)
				FPU_IDCT(block[comp]);
			break;

		case IDCT_REF:
			__asm emms;
			for (comp=0; comp<block_count; comp++)
				REF_IDCT(block[comp]);
			break;
	}

	Add_Block(block_count, bx, by, dct_type, (macroblock_type & MACROBLOCK_INTRA)==0);
}

/* ISO/IEC 13818-2 section 7.6.6 */
static void skipped_macroblock(int dc_dct_pred[3], int PMV[2][2][2], int *motion_type, 
							   int motion_vertical_field_select[2][2], int *macroblock_type)
{
	Clear_Block(block_count);

	/* reset intra_dc predictors */
	/* ISO/IEC 13818-2 section 7.2.1: DC coefficients in intra blocks */
	dc_dct_pred[0]=dc_dct_pred[1]=dc_dct_pred[2]=0;

	/* reset motion vector predictors */
	/* ISO/IEC 13818-2 section 7.6.3.4: Resetting motion vector predictors */
	if (picture_coding_type==P_TYPE)
		PMV[0][0][0]=PMV[0][0][1]=PMV[1][0][0]=PMV[1][0][1]=0;

	/* derive motion_type */
	if (picture_structure==FRAME_PICTURE)
		*motion_type = MC_FRAME;
	else
	{
		*motion_type = MC_FIELD;
		motion_vertical_field_select[0][0] = motion_vertical_field_select[0][1] = 
			(picture_structure==BOTTOM_FIELD);
	}

	/* clear MACROBLOCK_INTRA */
	*macroblock_type&= ~MACROBLOCK_INTRA;
}

/* return==-1 means go to next picture */
/* the expression "start of slice" is used throughout the normative
   body of the MPEG specification */
static int start_of_slice(int *MBA, int *MBAinc,
						  int dc_dct_pred[3], int PMV[2][2][2])
{
	unsigned int code;
	int slice_vert_pos_ext;

	next_start_code();
	code = Get_Bits(32);

	if (code<SLICE_START_CODE_MIN || code>SLICE_START_CODE_MAX)
	{
		// only slice headers are allowed in picture_data
		Fault_Flag = 10;
		return -1;
	}

	/* decode slice header (may change quantizer_scale) */
	slice_vert_pos_ext = slice_header();

	/* decode macroblock address increment */
	*MBAinc = Get_macroblock_address_increment();
	if (Fault_Flag) return -1;

	/* set current location */
	/* NOTE: the arithmetic used to derive macroblock_address below is
	   equivalent to ISO/IEC 13818-2 section 6.3.17: Macroblock */
	*MBA = ((slice_vert_pos_ext<<7) + (code&255) - 1)*mb_width + *MBAinc - 1;
	*MBAinc = 1;	// first macroblock in slice: not skipped

	/* reset all DC coefficient and motion vector predictors */
	/* ISO/IEC 13818-2 section 7.2.1: DC coefficients in intra blocks */
	dc_dct_pred[0]=dc_dct_pred[1]=dc_dct_pred[2]=0;
  
	/* ISO/IEC 13818-2 section 7.6.3.4: Resetting motion vector predictors */
	PMV[0][0][0]=PMV[0][0][1]=PMV[1][0][0]=PMV[1][0][1]=0;
	PMV[0][1][0]=PMV[0][1][1]=PMV[1][1][0]=PMV[1][1][1]=0;

	/* successfull: trigger decode macroblocks in slice */
	return 1;
}

/* ISO/IEC 13818-2 sections 7.2 through 7.5 */
static int decode_macroblock(int *macroblock_type, int *motion_type, int *dct_type,
							 int PMV[2][2][2], int dc_dct_pred[3], 
							 int motion_vertical_field_select[2][2], int dmvector[2])
{
	int quantizer_scale_code, comp, motion_vector_count, mv_format; 
	int dmv, mvscale, coded_block_pattern;

	/* ISO/IEC 13818-2 section 6.3.17.1: Macroblock modes */
	macroblock_modes(macroblock_type, motion_type, &motion_vector_count, &mv_format,
					 &dmv, &mvscale, dct_type);
	if (Fault_Flag) return 0;	// trigger: go to next slice

	if (*macroblock_type & MACROBLOCK_QUANT)
	{
		quantizer_scale_code = Get_Bits(5);

		/* ISO/IEC 13818-2 section 7.4.2.2: Quantizer scale factor */
		quantizer_scale = q_scale_type ?
		Non_Linear_quantizer_scale[quantizer_scale_code] : (quantizer_scale_code << 1);
	}

	/* ISO/IEC 13818-2 section 6.3.17.2: Motion vectors */
	/* decode forward motion vectors */
	if ((*macroblock_type & MACROBLOCK_MOTION_FORWARD) 
		|| ((*macroblock_type & MACROBLOCK_INTRA) && concealment_motion_vectors))

⌨️ 快捷键说明

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