📄 getpic.c
字号:
/* 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"
static int cc_table[12] = {
0, 0, 0, 0, 1, 2, 1, 2, 1, 2, 1, 2
};
/* 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);
/* decode one frame */
void Decode_Picture()
{
if (picture_structure==FRAME_PICTURE && Second_Field)
Second_Field = 0;
if (picture_coding_type!=B_TYPE)
{
d2v_forward = d2v_backward;
d2v_backward = d2v_current;
}
if (D2V_Flag)
{
if ((Frame_Number && picture_structure==FRAME_PICTURE) || Second_Field)
{
if (d2v_current.type==B_TYPE)
{
fprintf(D2VFile, " %d", d2v_current.trf);
DetectVideoType(Frame_Number-1, d2v_current.trf);
}
else
switch (d2v_forward.type)
{
case P_TYPE:
fprintf(D2VFile, " %d", d2v_forward.trf);
DetectVideoType(Frame_Number-1, d2v_forward.trf);
break;
case I_TYPE:
fprintf(D2VFile, "\n7 %d %X", d2v_forward.file, (int)d2v_forward.lba);
fprintf(D2VFile, " %d", d2v_forward.trf);
DetectVideoType(Frame_Number-1, d2v_forward.trf);
break;
default:
SetDlgItemText(hDlg, IDC_DEBUG, "P.E.");
break;
}
}
}
else
{
/* update picture buffer pointers */
Update_Picture_Buffers();
/* decode picture data ISO/IEC 13818-2 section 6.2.3.7 */
picture_data();
/* write or display current or previously decoded reference frame */
/* ISO/IEC 13818-2 section 6.1.1.11: Frame reordering */
if (Frame_Number && (picture_structure==FRAME_PICTURE || Second_Field))
{
if (picture_coding_type==B_TYPE)
Write_Frame(auxframe, d2v_current, Frame_Number-1);
else
Write_Frame(forward_reference_frame, d2v_forward, Frame_Number-1);
}
else if (process.locate!=LOCATE_RIP && (picture_structure==FRAME_PICTURE || Second_Field))
{
Write_Frame(backward_reference_frame, d2v_backward, 0);
ThreadKill();
}
}
if (picture_structure!=FRAME_PICTURE)
Second_Field = !Second_Field;
if (!Second_Field)
Frame_Number ++;
}
/* 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:
if (Fault_Flag)
SetDlgItemText(hDlg, IDC_DEBUG, "V.E.");
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(¯oblock_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, ¯oblock_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;
}
}
__asm emms;
}
/* 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);
__asm emms;
}
/* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -