+
+
+/*
+ * Motion vectors
+ */
+
+/****************************************************************************
+ * MotionCode : Parse the next motion code
+ ****************************************************************************/
+static __inline__ int MotionCode( vpar_thread_t * p_vpar )
+{
+ int i_code;
+ static lookup_t pl_mv_tab0[8] =
+ { {-1,0}, {3,3}, {2,2}, {2,2}, {1,1}, {1,1}, {1,1}, {1,1} };
+ /* Table B-10, motion_code, codes 0000011 ... 000011x */
+ static lookup_t pl_mv_tab1[8] =
+ { {-1,0}, {-1,0}, {-1,0}, {7,6}, {6,6}, {5,6}, {4,5}, {4,5} };
+ /* Table B-10, motion_code, codes 0000001100 ... 000001011x */
+ static lookup_t pl_mv_tab2[12] = {
+ {16,9}, {15,9}, {14,9}, {13,9},
+ {12,9}, {11,9}, {10,8}, {10,8},
+ {9,8}, {9,8}, {8,8}, {8,8} };
+
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ return 0;
+ }
+ if( (i_code = ShowBits( &p_vpar->bit_stream, 9) ) >= 64 )
+ {
+ i_code >>= 6;
+ RemoveBits( &p_vpar->bit_stream, pl_mv_tab0[i_code].i_length );
+ return( GetBits( &p_vpar->bit_stream, 1 ) ?
+ -pl_mv_tab0[i_code].i_value : pl_mv_tab0[i_code].i_value );
+ }
+
+ if( i_code >= 24 )
+ {
+ i_code >>= 3;
+ RemoveBits( &p_vpar->bit_stream, pl_mv_tab1[i_code].i_length );
+ return( GetBits( &p_vpar->bit_stream, 1 ) ?
+ -pl_mv_tab1[i_code].i_value : pl_mv_tab1[i_code].i_value );
+ }
+
+ if( (i_code -= 12) < 0 )
+ {
+ p_vpar->picture.b_error = 1;
+ intf_DbgMsg( "vpar debug: Invalid motion_vector code" );
+ return 0;
+ }
+
+ RemoveBits( &p_vpar->bit_stream, pl_mv_tab2[i_code].i_length );
+ return( GetBits( &p_vpar->bit_stream, 1 ) ?
+ -pl_mv_tab2[i_code].i_value : pl_mv_tab2[i_code].i_value );
+}
+
+/****************************************************************************
+ * DecodeMotionVector : Decode a motion_vector
+ ****************************************************************************/
+static __inline__ void DecodeMotionVector( int * pi_prediction, int i_r_size,
+ int i_motion_code, int i_motion_residual, int i_full_pel )
+{
+ int i_limit, i_vector;
+
+ /* ISO/IEC 13818-1 section 7.6.3.1 */
+ i_limit = 16 << i_r_size;
+ i_vector = *pi_prediction >> i_full_pel;
+
+ if( i_motion_code > 0 )
+ {
+ i_vector += ((i_motion_code-1) << i_r_size) + i_motion_residual + 1;
+ if( i_vector >= i_limit )
+ i_vector -= i_limit + i_limit;
+ }
+ else if( i_motion_code < 0 )
+ {
+ i_vector -= ((-i_motion_code-1) << i_r_size) + i_motion_residual + 1;
+ if( i_vector < -i_limit )
+ i_vector += i_limit + i_limit;
+ }
+ *pi_prediction = i_vector << i_full_pel;
+}
+
+/****************************************************************************
+ * MotionVector : Parse the next motion_vector field
+ ****************************************************************************/
+static __inline__ void MotionVector( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb, int i_r,
+ int i_s, int i_full_pel, int i_structure,
+ int i_h_r_size, int i_v_r_size )
+{
+ int i_motion_code, i_motion_residual;
+ int pi_dm_vector[2];
+
+ i_motion_code = MotionCode( p_vpar );
+ i_motion_residual = (i_h_r_size != 0 && i_motion_code != 0) ?
+ GetBits( &p_vpar->bit_stream, i_h_r_size) : 0;
+ DecodeMotionVector( &p_vpar->mb.pppi_pmv[i_r][i_s][0], i_h_r_size,
+ i_motion_code, i_motion_residual, i_full_pel );
+ p_mb->pppi_motion_vectors[i_r][i_s][0] = p_vpar->mb.pppi_pmv[i_r][i_s][0];
+
+ if( p_vpar->mb.b_dmv )
+ {
+ if( GetBits(&p_vpar->bit_stream, 1) )
+ {
+ pi_dm_vector[0] = GetBits( &p_vpar->bit_stream, 1 ) ? -1 : 1;
+ }
+ else
+ {
+ pi_dm_vector[0] = 0;
+ }
+ }
+
+ i_motion_code = MotionCode( p_vpar );
+ i_motion_residual = (i_v_r_size != 0 && i_motion_code != 0) ?
+ GetBits( &p_vpar->bit_stream, i_v_r_size) : 0;
+
+
+ if( (p_vpar->mb.i_mv_format == MOTION_FIELD)
+ && (i_structure == FRAME_STRUCTURE) )
+ {
+ p_vpar->mb.pppi_pmv[i_r][i_s][1] >>= 1;
+ }
+
+ DecodeMotionVector( &p_vpar->mb.pppi_pmv[i_r][i_s][1], i_v_r_size,
+ i_motion_code, i_motion_residual, i_full_pel );
+
+ if( (p_vpar->mb.i_mv_format == MOTION_FIELD)
+ && (i_structure == FRAME_STRUCTURE) )
+ p_vpar->mb.pppi_pmv[i_r][i_s][1] <<= 1;
+
+ p_mb->pppi_motion_vectors[i_r][i_s][1] = p_vpar->mb.pppi_pmv[i_r][i_s][1];
+
+ if( p_vpar->mb.b_dmv )
+ {
+ if( GetBits(&p_vpar->bit_stream, 1) )
+ {
+ pi_dm_vector[1] = GetBits( &p_vpar->bit_stream, 1 ) ? -1 : 1;
+ }
+ else
+ {
+ pi_dm_vector[1] = 0;
+ }
+
+ /* Dual Prime Arithmetic (ISO/IEC 13818-2 section 7.6.3.6). */
+
+#define i_mv_x p_mb->pppi_motion_vectors[0][0][0]
+ if( i_structure == FRAME_STRUCTURE )
+ {
+#define i_mv_y (p_mb->pppi_motion_vectors[0][0][1] << 1)
+ if( p_vpar->picture.b_top_field_first )
+ {
+ /* vector for prediction of top field from bottom field */
+ p_mb->ppi_dmv[0][0] = ((i_mv_x + (i_mv_x > 0)) >> 1) + pi_dm_vector[0];
+ p_mb->ppi_dmv[0][1] = ((i_mv_y + (i_mv_y > 0)) >> 1) + pi_dm_vector[1] - 1;
+
+ /* vector for prediction of bottom field from top field */
+ p_mb->ppi_dmv[1][0] = ((3*i_mv_x + (i_mv_x > 0)) >> 1) + pi_dm_vector[0];
+ p_mb->ppi_dmv[1][1] = ((3*i_mv_y + (i_mv_y > 0)) >> 1) + pi_dm_vector[1] + 1;
+ }
+ else
+ {
+ /* vector for prediction of top field from bottom field */
+ p_mb->ppi_dmv[0][0] = ((3*i_mv_x + (i_mv_x > 0)) >> 1) + pi_dm_vector[0];
+ p_mb->ppi_dmv[0][1] = ((3*i_mv_y + (i_mv_y > 0)) >> 1) + pi_dm_vector[1] - 1;
+
+ /* vector for prediction of bottom field from top field */
+ p_mb->ppi_dmv[1][0] = ((i_mv_x + (i_mv_x > 0)) >> 1) + pi_dm_vector[0];
+ p_mb->ppi_dmv[1][1] = ((i_mv_y + (i_mv_y > 0)) >> 1) + pi_dm_vector[1] + 1;
+ }
+#undef i_mv_y
+ }
+ else
+ {
+#define i_mv_y p_mb->pppi_motion_vectors[0][0][1]
+ /* vector for prediction from field of opposite 'parity' */
+ p_mb->ppi_dmv[0][0] = ((i_mv_x + (i_mv_x > 0)) >> 1) + pi_dm_vector[0];
+ p_mb->ppi_dmv[0][1] = ((i_mv_y + (i_mv_y > 0)) >> 1) + pi_dm_vector[1];
+
+ /* correct for vertical field shift */
+ if( p_vpar->picture.i_structure == TOP_FIELD )
+ p_mb->ppi_dmv[0][1]--;
+ else
+ p_mb->ppi_dmv[0][1]++;
+#undef i_mv_y
+ }
+#undef i_mv_x
+ }
+}
+
+/*****************************************************************************
+ * DecodeMVMPEG1 : Parse the next MPEG-1 motion vectors
+ *****************************************************************************/
+static void DecodeMVMPEG1( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb, int i_s, int i_structure )
+{
+ int i_r_size = i_s ? p_vpar->picture.i_backward_f_code - 1 :
+ p_vpar->picture.i_forward_f_code - 1;
+ MotionVector( p_vpar, p_mb, 0, i_s,
+ p_vpar->picture.pb_full_pel_vector[i_s], FRAME_STRUCTURE,
+ i_r_size, i_r_size );
+}
+
+/*****************************************************************************
+ * DecodeMVMPEG2 : Parse the next MPEG-2 motion_vectors field
+ *****************************************************************************/
+static void DecodeMVMPEG2( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb, int i_s, int i_structure )
+{
+ if( p_vpar->mb.i_mv_count == 1 )
+ {
+ if( p_vpar->mb.i_mv_format == MOTION_FIELD && !p_vpar->mb.b_dmv )
+ {
+ p_mb->ppi_field_select[0][i_s] = p_mb->ppi_field_select[1][i_s]
+ = GetBits( &p_vpar->bit_stream, 1 );
+ }
+ MotionVector( p_vpar, p_mb, 0, i_s, 0, i_structure,
+ p_vpar->picture.ppi_f_code[i_s][0] - 1,
+ p_vpar->picture.ppi_f_code[i_s][1] - 1 );
+ p_vpar->mb.pppi_pmv[1][i_s][0] = p_vpar->mb.pppi_pmv[0][i_s][0];
+ p_vpar->mb.pppi_pmv[1][i_s][1] = p_vpar->mb.pppi_pmv[0][i_s][1];
+ p_mb->pppi_motion_vectors[1][i_s][0] = p_vpar->mb.pppi_pmv[0][i_s][0];
+ p_mb->pppi_motion_vectors[1][i_s][1] = p_vpar->mb.pppi_pmv[0][i_s][1];
+ }
+ else
+ {
+ p_mb->ppi_field_select[0][i_s] = GetBits( &p_vpar->bit_stream, 1 );
+ MotionVector( p_vpar, p_mb, 0, i_s, 0, i_structure,
+ p_vpar->picture.ppi_f_code[i_s][0] - 1,
+ p_vpar->picture.ppi_f_code[i_s][1] - 1 );
+ p_mb->ppi_field_select[1][i_s] = GetBits( &p_vpar->bit_stream, 1 );
+ MotionVector( p_vpar, p_mb, 1, i_s, 0, i_structure,
+ p_vpar->picture.ppi_f_code[i_s][0] - 1,
+ p_vpar->picture.ppi_f_code[i_s][1] - 1 );
+ }
+}
+
+
+/*
+ * Macroblock information structures
+ */
+
+/*****************************************************************************
+ * MacroblockAddressIncrement : Get the macroblock_address_increment field
+ *****************************************************************************/
+static int MacroblockAddressIncrement( vpar_thread_t * p_vpar )
+{
+ int i_addr_inc = 0;
+ /* Index in the lookup table mb_addr_inc */
+ int i_index = ShowBits( &p_vpar->bit_stream, 11 );
+
+ /* Test the presence of the escape character */
+ while( i_index == 8 )
+ {
+ RemoveBits( &p_vpar->bit_stream, 11 );
+ i_addr_inc += 33;
+ i_index = ShowBits( &p_vpar->bit_stream, 11 );
+ }
+
+ /* Affect the value from the lookup table */
+ i_addr_inc += p_vpar->pl_mb_addr_inc[i_index].i_value;
+
+ /* Dump the good number of bits */
+ RemoveBits( &p_vpar->bit_stream, p_vpar->pl_mb_addr_inc[i_index].i_length );
+
+ return i_addr_inc;
+}
+
+/*****************************************************************************
+ * IMBType : macroblock_type in I pictures
+ *****************************************************************************/
+static __inline__ int IMBType( vpar_thread_t * p_vpar )
+{
+ /* Take two bits for testing */
+ int i_type = ShowBits( &p_vpar->bit_stream, 2 );
+
+ /* Lookup table for macroblock_type */
+ static lookup_t pl_mb_Itype[4] = { {MB_ERROR, 0},
+ {MB_QUANT|MB_INTRA, 2},
+ {MB_INTRA, 1},
+ {MB_INTRA, 1} };
+ /* Dump the good number of bits */
+ RemoveBits( &p_vpar->bit_stream, pl_mb_Itype[i_type].i_length );
+ return pl_mb_Itype[i_type].i_value;
+}
+
+/*****************************************************************************
+ * PMBType : macroblock_type in P pictures
+ *****************************************************************************/
+static __inline__ int PMBType( vpar_thread_t * p_vpar )
+{
+ /* Testing on 6 bits */
+ int i_type = ShowBits( &p_vpar->bit_stream, 6 );
+
+ /* Dump the good number of bits */
+ RemoveBits( &p_vpar->bit_stream, p_vpar->ppl_mb_type[0][i_type].i_length );
+ /* return the value from the lookup table for P type */
+ return p_vpar->ppl_mb_type[0][i_type].i_value;
+}
+
+/*****************************************************************************
+ * BMBType : macroblock_type in B pictures
+ *****************************************************************************/
+static __inline__ int BMBType( vpar_thread_t * p_vpar )
+{
+ /* Testing on 6 bits */
+ int i_type = ShowBits( &p_vpar->bit_stream, 6 );
+
+ /* Dump the good number of bits */
+ RemoveBits( &p_vpar->bit_stream, p_vpar->ppl_mb_type[1][i_type].i_length );
+
+ /* return the value from the lookup table for B type */
+ return p_vpar->ppl_mb_type[1][i_type].i_value;
+}
+
+/*****************************************************************************
+ * DMBType : macroblock_type in D pictures
+ *****************************************************************************/
+static __inline__ int DMBType( vpar_thread_t * p_vpar )
+{
+ return GetBits( &p_vpar->bit_stream, 1 );
+}
+
+/*****************************************************************************
+ * CodedPattern420 : coded_block_pattern with 4:2:0 chroma
+ *****************************************************************************/
+static __inline__ int CodedPattern420( vpar_thread_t * p_vpar )
+{
+ /* Take the max 9 bits length vlc code for testing */
+ int i_vlc = ShowBits( &p_vpar->bit_stream, 9 );
+
+ /* Trash the good number of bits read in the lookup table */
+ RemoveBits( &p_vpar->bit_stream, pl_coded_pattern[i_vlc].i_length );
+
+ /* return the value from the vlc table */
+ return pl_coded_pattern[i_vlc].i_value;
+}
+
+/*****************************************************************************
+ * CodedPattern422 : coded_block_pattern with 4:2:2 chroma
+ *****************************************************************************/
+static __inline__ int CodedPattern422( vpar_thread_t * p_vpar )
+{
+ int i_vlc = ShowBits( &p_vpar->bit_stream, 9 );
+
+ RemoveBits( &p_vpar->bit_stream, pl_coded_pattern[i_vlc].i_length );
+
+ /* Supplementary 2 bits long code for 4:2:2 format */
+ return pl_coded_pattern[i_vlc].i_value |
+ (GetBits( &p_vpar->bit_stream, 2 ) << 6);
+}
+
+/*****************************************************************************
+ * CodedPattern444 : coded_block_pattern with 4:4:4 chroma
+ *****************************************************************************/
+static __inline__ int CodedPattern444( vpar_thread_t * p_vpar )
+{
+ int i_vlc = ShowBits( &p_vpar->bit_stream, 9 );
+
+ RemoveBits( &p_vpar->bit_stream, pl_coded_pattern[i_vlc].i_length );
+
+ return pl_coded_pattern[i_vlc].i_value |
+ (GetBits( &p_vpar->bit_stream, 6 ) << 6);
+}
+
+/*****************************************************************************
+ * InitMacroblock : Initialize macroblock values
+ *****************************************************************************/
+static __inline__ void InitMacroblock( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb, int i_coding_type,
+ int i_chroma_format,
+ int i_structure,
+ boolean_t b_second_field )
+{
+ p_mb->i_chroma_nb_blocks = 1 << i_chroma_format;
+ p_mb->p_picture = p_vpar->picture.p_picture;
+
+ if( i_coding_type == B_CODING_TYPE )
+ p_mb->p_backward = p_vpar->sequence.p_backward;
+ else
+ p_mb->p_backward = NULL;
+ if( (i_coding_type == P_CODING_TYPE) || (i_coding_type == B_CODING_TYPE) )
+ p_mb->p_forward = p_vpar->sequence.p_forward;
+ else
+ p_mb->p_forward = NULL;
+
+ p_mb->i_l_x = p_vpar->mb.i_l_x;
+ p_mb->i_c_x = p_vpar->mb.i_c_x;
+ p_mb->i_motion_l_y = p_vpar->mb.i_l_y;
+ p_mb->i_motion_c_y = p_vpar->mb.i_c_y;
+ if( (p_mb->b_motion_field = (i_structure == BOTTOM_FIELD)) )
+ {
+ p_mb->i_motion_l_y--;
+ p_mb->i_motion_c_y--;
+ }
+ p_mb->i_addb_l_stride = (p_mb->i_l_stride = p_vpar->picture.i_l_stride) - 8;
+ p_mb->i_addb_c_stride = (p_mb->i_c_stride = p_vpar->picture.i_c_stride) - 8;
+ p_mb->b_P_second = ( b_second_field && i_coding_type == P_CODING_TYPE );
+}
+
+/*****************************************************************************
+ * UpdateContext : Update the p_vpar contextual values
+ *****************************************************************************/
+static __inline__ void UpdateContext( vpar_thread_t * p_vpar, int i_structure )
+{
+ /* Update macroblock real position. */
+ p_vpar->mb.i_l_x += 16;
+ p_vpar->mb.i_l_y += (p_vpar->mb.i_l_x / p_vpar->sequence.i_width)
+ * (2 - (i_structure == FRAME_STRUCTURE)) * 16;
+ p_vpar->mb.i_l_x %= p_vpar->sequence.i_width;
+
+ p_vpar->mb.i_c_x += p_vpar->sequence.i_chroma_mb_width;
+ p_vpar->mb.i_c_y += (p_vpar->mb.i_c_x / p_vpar->sequence.i_chroma_width)
+ * (2 - (i_structure == FRAME_STRUCTURE))
+ * p_vpar->sequence.i_chroma_mb_height;
+ p_vpar->mb.i_c_x %= p_vpar->sequence.i_chroma_width;
+}
+
+/*****************************************************************************
+ * SkippedMacroblock : Generate a skipped macroblock with NULL motion vector
+ *****************************************************************************/
+static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb,
+ int i_mb_base, int i_coding_type,
+ int i_chroma_format,
+ int i_structure,
+ boolean_t b_second_field )
+{
+ macroblock_t * p_mb;
+
+ if( i_coding_type == I_CODING_TYPE )
+ {
+ intf_DbgMsg("vpar error: skipped macroblock in I-picture");
+ p_vpar->picture.b_error = 1;
+ return;
+ }
+
+ if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
+ {
+ /* b_die == 1 */
+ return;
+ }
+#ifdef VDEC_SMP
+ p_vpar->picture.pp_mb[i_mb_base + i_mb] = p_mb;
+#endif
+
+ InitMacroblock( p_vpar, p_mb, i_coding_type, i_chroma_format,
+ i_structure, b_second_field );
+
+ /* Motion type is picture structure. */
+ p_mb->pf_motion = p_vpar->ppf_motion_skipped[i_chroma_format]
+ [i_structure];
+ p_mb->i_coded_block_pattern = 0;
+
+ /* Motion direction and motion vectors depend on the coding type. */
+ if( i_coding_type == B_CODING_TYPE )
+ {
+ int i, j, k;
+ p_mb->i_mb_type = p_vpar->mb.i_motion_dir;
+ for( i = 0; i < 2; i++ )
+ for( j = 0; j < 2; j++ )
+ for( k = 0; k < 2; k++ )
+ p_mb->pppi_motion_vectors[i][j][k] = p_vpar->mb.pppi_pmv[i][j][k];
+ }
+ else if( i_coding_type == P_CODING_TYPE )
+ {
+ p_mb->i_mb_type = MB_MOTION_FORWARD;
+ memset( p_mb->pppi_motion_vectors, 0, 8*sizeof(int) );
+ }
+
+ /* Set the field we use for motion compensation */
+ p_mb->ppi_field_select[0][0] = p_mb->ppi_field_select[0][1]
+ = ( i_structure == BOTTOM_FIELD );
+
+ UpdateContext( p_vpar, i_structure );
+
+#ifndef VDEC_SMP
+ /* Decode the macroblock NOW ! */
+ vpar_DecodeMacroblock ( &p_vpar->vfifo, p_mb );
+#endif
+}
+
+/*****************************************************************************
+ * MacroblockModes : Get the macroblock_modes structure
+ *****************************************************************************/
+static __inline__ void MacroblockModes( vpar_thread_t * p_vpar,
+ macroblock_t * p_mb,
+ int i_chroma_format,
+ int i_coding_type,
+ int i_structure )
+{
+ static int ppi_mv_count[2][4] = { {0, 1, 2, 1}, {0, 2, 1, 1} };
+ static int ppi_mv_format[2][4] = { {0, 1, 1, 1}, {0, 1, 2, 1} };
+
+ /* Get macroblock_type. */
+ switch( i_coding_type )
+ {
+ case P_CODING_TYPE:
+ p_mb->i_mb_type = PMBType( p_vpar );
+ break;
+ case B_CODING_TYPE:
+ p_mb->i_mb_type = BMBType( p_vpar );
+ break;
+ case I_CODING_TYPE:
+ p_mb->i_mb_type = IMBType( p_vpar );
+ break;
+ case D_CODING_TYPE:
+ p_mb->i_mb_type = DMBType( p_vpar );
+ }
+
+ if( i_coding_type == B_CODING_TYPE )
+ {
+ /* We need to remember the motion direction of the last macroblock
+ * before a skipped macroblock (ISO/IEC 13818-2 7.6.6) */
+ p_vpar->mb.i_motion_dir = p_mb->i_mb_type
+ & (MB_MOTION_FORWARD | MB_MOTION_BACKWARD);
+ }
+
+ /* SCALABILITY : warning, we don't know if spatial_temporal_weight_code
+ * has to be dropped, take care if you use scalable streams. */
+ /* RemoveBits( &p_vpar->bit_stream, 2 ); */
+
+ if( (i_coding_type == P_CODING_TYPE || i_coding_type == B_CODING_TYPE)
+ && (p_mb->i_mb_type & (MB_MOTION_FORWARD | MB_MOTION_BACKWARD)) )
+ {
+ if( !(i_structure == FRAME_STRUCTURE
+ && p_vpar->picture.b_frame_pred_frame_dct) )
+ {
+ p_vpar->mb.i_motion_type = GetBits( &p_vpar->bit_stream, 2 );
+ }
+ else
+ {
+ p_vpar->mb.i_motion_type = MOTION_FRAME;
+ }
+
+ /* XXX?? */
+ p_vpar->mb.i_mv_count = ppi_mv_count[i_structure == FRAME_STRUCTURE]
+ [p_vpar->mb.i_motion_type];
+ p_vpar->mb.i_mv_format = ppi_mv_format[i_structure == FRAME_STRUCTURE]
+ [p_vpar->mb.i_motion_type];
+ p_vpar->mb.b_dmv = p_vpar->mb.i_motion_type == MOTION_DMV;
+ }
+
+ p_vpar->mb.b_dct_type = 0;
+ if( (i_structure == FRAME_STRUCTURE) &&
+ (!p_vpar->picture.b_frame_pred_frame_dct) &&
+ (p_mb->i_mb_type & (MB_PATTERN|MB_INTRA)) )
+ {
+ if( (p_vpar->mb.b_dct_type = GetBits( &p_vpar->bit_stream, 1 )) )
+ {
+ /* The DCT is coded on fields. Jump one line between each
+ * sample. */
+ p_mb->i_addb_l_stride <<= 1;
+ p_mb->i_addb_l_stride += 8;
+ /* With CHROMA_420, the DCT is necessarily frame-coded. */
+ if( i_chroma_format != CHROMA_420 )
+ {
+ p_mb->i_addb_c_stride <<= 1;
+ p_mb->i_addb_c_stride += 8;
+ }
+ }
+ }
+}
+
+/*****************************************************************************
+ * ParseMacroblock : Parse the next macroblock
+ *****************************************************************************/
+#define PARSEERROR \
+if( p_vpar->picture.b_error ) \
+{ \
+ /* Mark this block as skipped (better than green blocks), and \
+ * go to the next slice. */ \
+ (*pi_mb_address)--; \
+ vpar_DestroyMacroblock( &p_vpar->vfifo, p_mb ); \
+ return; \
+}
+
+#define PARSEBLOCKS( MPEG1FUNC, MPEG2FUNC ) \
+{ \
+ i_mask = 1 << (3 + (1 << i_chroma_format)); \
+ \
+ /* luminance */ \
+ p_data1 = p_mb->p_picture->p_y \
+ + p_mb->i_l_x + p_vpar->mb.i_l_y*(p_vpar->sequence.i_width); \
+ \
+ for( i_b = 0 ; i_b < 4 ; i_b++, i_mask >>= 1 ) \
+ { \
+ if( p_mb->i_coded_block_pattern & i_mask ) \
+ { \
+ memset( p_mb->ppi_blocks[i_b], 0, 64*sizeof(dctelem_t) ); \
+ if( b_mpeg2 ) \
+ MPEG2FUNC( p_vpar, p_mb, i_b, i_chroma_format ); \
+ else \
+ MPEG1FUNC( p_vpar, p_mb, i_b, i_chroma_format ); \
+ \
+ /* Calculate block coordinates. */ \
+ p_mb->p_data[i_b] = p_data1 \
+ + pi_y[p_vpar->mb.b_dct_type][i_b] \
+ * p_vpar->picture.i_l_stride \
+ + pi_x[i_b]; \
+ \
+ PARSEERROR \
+ } \
+ } \
+ \
+ /* chrominance */ \
+ p_data1 = p_mb->p_picture->p_u \
+ + p_mb->i_c_x \
+ + p_vpar->mb.i_c_y \
+ * (p_vpar->sequence.i_chroma_width); \
+ p_data2 = p_mb->p_picture->p_v \
+ + p_mb->i_c_x \
+ + p_vpar->mb.i_c_y \
+ * (p_vpar->sequence.i_chroma_width); \
+ \
+ for( i_b = 4; i_b < 4 + (1 << i_chroma_format); \
+ i_b++, i_mask >>= 1 ) \
+ { \
+ yuv_data_t * pp_data[2] = {p_data1, p_data2}; \
+ \
+ if( p_mb->i_coded_block_pattern & i_mask ) \
+ { \
+ memset( p_mb->ppi_blocks[i_b], 0, 64*sizeof(dctelem_t) ); \
+ if( b_mpeg2 ) \
+ MPEG2FUNC( p_vpar, p_mb, i_b, i_chroma_format ); \
+ else \
+ MPEG1FUNC( p_vpar, p_mb, i_b, i_chroma_format ); \
+ \
+ /* Calculate block coordinates. */ \
+ p_mb->p_data[i_b] = pp_data[i_b & 1] \
+ + pi_y[p_vpar->mb.b_dct_type][i_b] \
+ * p_vpar->picture.i_c_stride \
+ + pi_x[i_b]; \
+ \
+ PARSEERROR \
+ } \
+ } \
+}
+
+static __inline__ void ParseMacroblock(
+ vpar_thread_t * p_vpar,
+ int * pi_mb_address, /* previous address to be
+ * used for mb_addr_incr */
+ int i_mb_previous, /* actual previous mb */
+ int i_mb_base, /* non-zero if field structure */
+ /* The following parameters are explicit in
+ * optimized routines : */
+ boolean_t b_mpeg2, /* you know what ? */
+ int i_coding_type, /* I, P, B or D */
+ int i_chroma_format, /* 4:2:0, 4:2:2 or 4:4:4 */
+ int i_structure, /* T(OP), B(OTTOM) or F(RAME) */
+ boolean_t b_second_field ) /* second field of a
+ * field picture */
+{
+ static int pi_x[12] = {0,8,0,8,0,0,0,0,8,8,8,8};
+ static int pi_y[2][12] = { {0,0,8,8,0,0,8,8,0,0,8,8},
+ {0,0,1,1,0,0,1,1,0,0,1,1} };
+ int i_mb, i_b, i_mask;
+ int i_inc;
+ macroblock_t * p_mb;
+ yuv_data_t * p_data1;
+ yuv_data_t * p_data2;
+
+ i_inc = MacroblockAddressIncrement( p_vpar );
+ *pi_mb_address += i_inc;
+
+ if( i_inc < 0 )
+ {
+ intf_ErrMsg( "vpar error: bad address increment (%d)", i_inc );
+ p_vpar->picture.b_error = 1;
+ return;
+ }
+
+ if( *pi_mb_address - i_mb_previous - 1 )
+ {
+ /* Skipped macroblock (ISO/IEC 13818-2 7.6.6). */
+
+ /* Reset DC predictors (7.2.1). */
+ p_vpar->mb.pi_dc_dct_pred[0] = p_vpar->mb.pi_dc_dct_pred[1]
+ = p_vpar->mb.pi_dc_dct_pred[2]
+ = 1 << (7 + p_vpar->picture.i_intra_dc_precision);
+
+ if( i_coding_type == P_CODING_TYPE )
+ {
+ /* Reset motion vector predictors (ISO/IEC 13818-2 7.6.3.4). */
+ memset( p_vpar->mb.pppi_pmv, 0, 8*sizeof(int) );
+ }
+
+ for( i_mb = i_mb_previous + 1; i_mb < *pi_mb_address; i_mb++ )
+ {
+ SkippedMacroblock( p_vpar, i_mb, i_mb_base, i_coding_type,
+ i_chroma_format, i_structure, b_second_field );
+ }
+ }
+
+ /* Get a macroblock structure. */
+ if( (p_mb = vpar_NewMacroblock( &p_vpar->vfifo )) == NULL )
+ {
+ /* b_die == 1 */
+ return;
+ }
+#ifdef VDEC_SMP
+ p_vpar->picture.pp_mb[i_mb_base + *pi_mb_address] = p_mb;
+#endif
+
+ InitMacroblock( p_vpar, p_mb, i_coding_type, i_chroma_format,
+ i_structure, b_second_field );
+
+ /* Parse off macroblock_modes structure. */
+ MacroblockModes( p_vpar, p_mb, i_chroma_format, i_coding_type,
+ i_structure );
+
+ if( p_mb->i_mb_type & MB_QUANT )
+ {
+ LoadQuantizerScale( p_vpar );
+ }
+
+ if( (i_coding_type == P_CODING_TYPE || i_coding_type == B_CODING_TYPE)
+ && (p_mb->i_mb_type & MB_MOTION_FORWARD) )
+ {
+ if( b_mpeg2 )
+ DecodeMVMPEG2( p_vpar, p_mb, 0, i_structure );
+ else
+ DecodeMVMPEG1( p_vpar, p_mb, 0, i_structure );
+ PARSEERROR
+ }
+
+ if( (i_coding_type == B_CODING_TYPE)
+ && (p_mb->i_mb_type & MB_MOTION_BACKWARD) )
+ {
+ if( b_mpeg2 )
+ DecodeMVMPEG2( p_vpar, p_mb, 1, i_structure );
+ else
+ DecodeMVMPEG1( p_vpar, p_mb, 1, i_structure );
+ PARSEERROR
+ }
+
+ if( i_coding_type == P_CODING_TYPE
+ && !(p_mb->i_mb_type & (MB_MOTION_FORWARD|MB_INTRA)) )
+ {
+ /* Special No-MC macroblock in P pictures (7.6.3.5). */
+ p_mb->i_mb_type |= MB_MOTION_FORWARD;
+ memset( p_vpar->mb.pppi_pmv, 0, 8*sizeof(int) );
+ memset( p_mb->pppi_motion_vectors, 0, 8*sizeof(int) );
+ p_vpar->mb.i_motion_type = 1 + (i_structure == FRAME_STRUCTURE);
+ p_mb->ppi_field_select[0][0] = (i_structure == BOTTOM_FIELD);
+ }
+
+ if( (i_coding_type != I_CODING_TYPE) && !(p_mb->i_mb_type & MB_INTRA) )
+ {
+ /* Reset DC predictors (7.2.1). */
+ p_vpar->mb.pi_dc_dct_pred[0] = p_vpar->mb.pi_dc_dct_pred[1]
+ = p_vpar->mb.pi_dc_dct_pred[2]
+ = 1 << (7 + p_vpar->picture.i_intra_dc_precision);
+
+ /* Motion function pointer. */
+ p_mb->pf_motion = p_vpar->pppf_motion[i_chroma_format]
+ [i_structure == FRAME_STRUCTURE]
+ [p_vpar->mb.i_motion_type];
+
+ if( p_mb->i_mb_type & MB_PATTERN )
+ {
+ switch( i_chroma_format )
+ {
+ case CHROMA_420:
+ p_mb->i_coded_block_pattern = CodedPattern420( p_vpar );
+ break;
+ case CHROMA_422:
+ p_mb->i_coded_block_pattern = CodedPattern422( p_vpar );
+ break;
+ case CHROMA_444:
+ p_mb->i_coded_block_pattern = CodedPattern444( p_vpar );
+ }
+ }
+ else
+ {
+ p_mb->i_coded_block_pattern = 0;
+ }
+
+ /*
+ * Effectively decode blocks.
+ */
+ PARSEBLOCKS( DecodeMPEG1NonIntra, DecodeMPEG2NonIntra )
+ }
+ else
+ {
+ if( !p_vpar->picture.b_concealment_mv )
+ {
+ /* Reset MV predictors. */
+ memset( p_vpar->mb.pppi_pmv, 0, 8*sizeof(int) );
+ }
+ else
+ {
+ if( b_mpeg2 )
+ DecodeMVMPEG2( p_vpar, p_mb, 0, i_structure );
+ else
+ DecodeMVMPEG1( p_vpar, p_mb, 0, i_structure );
+ RemoveBits( &p_vpar->bit_stream, 1 );
+ }
+
+ if( p_mb->i_mb_type & MB_PATTERN )
+ {
+ switch( i_chroma_format )
+ {
+ case CHROMA_420:
+ p_mb->i_coded_block_pattern = CodedPattern420( p_vpar );
+ break;
+ case CHROMA_422:
+ p_mb->i_coded_block_pattern = CodedPattern422( p_vpar );
+ break;
+ case CHROMA_444:
+ p_mb->i_coded_block_pattern = CodedPattern444( p_vpar );
+ }
+ }
+ else
+ {
+ p_mb->i_coded_block_pattern =
+ (1 << (4 + (1 << i_chroma_format))) - 1;
+ }
+
+ /*
+ * Effectively decode blocks.
+ */
+ PARSEBLOCKS( DecodeMPEG1Intra, DecodeMPEG2Intra )
+ }
+
+ if( !p_vpar->picture.b_error )
+ {
+ UpdateContext( p_vpar, i_structure );
+#ifndef VDEC_SMP
+ /* Decode the macroblock NOW ! */
+ vpar_DecodeMacroblock ( &p_vpar->vfifo, p_mb );
+#endif
+ }
+ else
+ {
+ /* Mark this block as skipped (better than green blocks), and go
+ * to the next slice. */
+ (*pi_mb_address)--;
+ vpar_DestroyMacroblock( &p_vpar->vfifo, p_mb );
+ }
+}
+
+/*
+ * Picture data parsing management
+ */
+
+/*****************************************************************************
+ * ParseMacroblockVWXYZ : Parse the next macroblock ; specific functions
+ *****************************************************************************
+ * V = MPEG2 ?
+ * W = coding type ?
+ * X = chroma format ?
+ * Y = structure ?
+ * Z = second field ?
+ *****************************************************************************/
+void ParseMacroblockGENERIC( vpar_thread_t * p_vpar, int * pi_mb_address,
+ int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ b_mpeg2, i_coding_type, i_chroma_format,
+ i_structure, b_second_field );
+}
+
+#if (VPAR_OPTIM_LEVEL > 0)
+/* Optimizations for frame pictures */
+void ParseMacroblock2I420F0( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, I_CODING_TYPE, CHROMA_420,
+ FRAME_STRUCTURE, 0 );
+}
+
+void ParseMacroblock2P420F0( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, P_CODING_TYPE, CHROMA_420,
+ FRAME_STRUCTURE, 0 );
+}
+
+void ParseMacroblock2B420F0( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, B_CODING_TYPE, CHROMA_420,
+ FRAME_STRUCTURE, 0 );
+}
+#endif
+
+#if (VPAR_OPTIM_LEVEL > 1)
+/* Optimizations for field pictures */
+void ParseMacroblock2I420TZ( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, I_CODING_TYPE, CHROMA_420,
+ TOP_FIELD, (p_vpar->picture.i_structure !=
+ p_vpar->picture.i_current_structure) );
+}
+
+void ParseMacroblock2P420TZ( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, P_CODING_TYPE, CHROMA_420,
+ TOP_FIELD, (p_vpar->picture.i_structure !=
+ p_vpar->picture.i_current_structure) );
+}
+
+void ParseMacroblock2B420TZ( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, B_CODING_TYPE, CHROMA_420,
+ TOP_FIELD, (p_vpar->picture.i_structure !=
+ p_vpar->picture.i_current_structure) );
+}
+
+void ParseMacroblock2I420BZ( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, I_CODING_TYPE, CHROMA_420,
+ BOTTOM_FIELD, (p_vpar->picture.i_structure !=
+ p_vpar->picture.i_current_structure) );
+}
+
+void ParseMacroblock2P420BZ( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, P_CODING_TYPE, CHROMA_420,
+ BOTTOM_FIELD, (p_vpar->picture.i_structure !=
+ p_vpar->picture.i_current_structure) );
+}
+
+void ParseMacroblock2B420BZ( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ ParseMacroblock( p_vpar, pi_mb_address, i_mb_previous, i_mb_base,
+ 1, B_CODING_TYPE, CHROMA_420,
+ BOTTOM_FIELD, (p_vpar->picture.i_structure !=
+ p_vpar->picture.i_current_structure) );
+}
+#endif
+
+/*****************************************************************************
+ * SliceHeader : Parse the next slice structure
+ *****************************************************************************/
+typedef void (*f_parse_mb_t)( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_previous, int i_mb_base,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field );
+
+static __inline__ void SliceHeader( vpar_thread_t * p_vpar,
+ int * pi_mb_address, int i_mb_base,
+ u32 i_vert_code, boolean_t b_high,
+ boolean_t b_dp_scalable,
+ boolean_t b_mpeg2, int i_coding_type,
+ int i_chroma_format, int i_structure,
+ boolean_t b_second_field )
+{
+ static f_parse_mb_t ppf_parse_mb[4][4] =
+ {
+ {
+ NULL, NULL, NULL, NULL
+ },
+ {
+ /* TOP_FIELD */
+#if (VPAR_OPTIM_LEVEL > 1)
+ NULL, ParseMacroblock2I420TZ, ParseMacroblock2P420TZ,
+ ParseMacroblock2B420TZ
+#else
+ NULL, ParseMacroblockGENERIC, ParseMacroblockGENERIC,
+ ParseMacroblockGENERIC
+#endif
+ },
+ {
+ /* BOTTOM_FIELD */
+#if (VPAR_OPTIM_LEVEL > 1)
+ NULL, ParseMacroblock2I420BZ, ParseMacroblock2P420BZ,
+ ParseMacroblock2B420BZ
+#else
+ NULL, ParseMacroblockGENERIC, ParseMacroblockGENERIC,
+ ParseMacroblockGENERIC
+#endif
+ },
+ {
+ /* FRAME_PICTURE */
+#if (VPAR_OPTIM_LEVEL > 0)
+ NULL, ParseMacroblock2I420F0, ParseMacroblock2P420F0,
+ ParseMacroblock2B420F0
+#else
+ NULL, ParseMacroblockGENERIC, ParseMacroblockGENERIC,
+ ParseMacroblockGENERIC
+#endif
+ }
+ };
+
+ int i_mb_address_save = *pi_mb_address;
+
+ p_vpar->picture.b_error = 0;
+
+ if( b_high )
+ {
+ /* Picture with more than 2800 lines. */
+ i_vert_code += GetBits( &p_vpar->bit_stream, 3 ) << 7;
+ }
+ if( b_dp_scalable )
+ {
+ /* DATA_PARTITIONING scalability. */
+ RemoveBits( &p_vpar->bit_stream, 7 ); /* priority_breakpoint */
+ }
+
+ LoadQuantizerScale( p_vpar );
+
+ if( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ /* intra_slice, slice_id */
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ /* extra_information_slice */
+ while( GetBits( &p_vpar->bit_stream, 1 ) )
+ {
+ RemoveBits( &p_vpar->bit_stream, 8 );
+ }
+ }
+ *pi_mb_address = (i_vert_code - 1)*p_vpar->sequence.i_mb_width;
+
+ if( *pi_mb_address < i_mb_address_save )
+ {
+ intf_ErrMsg( "vpar error: slices do not follow, maybe a PES has been trashed" );
+ p_vpar->picture.b_error = 1;
+ return;
+ }
+
+ /* Reset DC coefficients predictors (ISO/IEC 13818-2 7.2.1). */
+ p_vpar->mb.pi_dc_dct_pred[0] = p_vpar->mb.pi_dc_dct_pred[1]
+ = p_vpar->mb.pi_dc_dct_pred[2]
+ = 1 << (7 + p_vpar->picture.i_intra_dc_precision);
+
+ /* Reset motion vector predictors (ISO/IEC 13818-2 7.6.3.4). */
+ memset( p_vpar->mb.pppi_pmv, 0, 8*sizeof(int) );
+
+ do
+ {
+ if( i_mb_address_save >= p_vpar->sequence.i_mb_size )
+ {
+ p_vpar->picture.b_error = 1;
+ return;
+ }
+
+ if( p_vpar->sequence.i_chroma_format != CHROMA_420
+ || !p_vpar->sequence.b_mpeg2 || p_vpar->sequence.i_height > 2800
+ || p_vpar->sequence.i_scalable_mode == SC_DP )
+ {
+ /* Weird stream. Use the slower generic function. */
+ ParseMacroblockGENERIC( p_vpar, pi_mb_address, i_mb_address_save,
+ i_mb_base, b_mpeg2, i_coding_type,
+ i_chroma_format, i_structure,
+ b_second_field );
+ }
+ else
+ {
+ /* Try to find an optimized function. */
+ if( ppf_parse_mb[i_structure]
+ [p_vpar->picture.i_coding_type] == NULL )
+ {
+ intf_ErrMsg( "vpar error: bad ppf_parse_mb function pointer (struct:%d, coding type:%d)",
+ i_structure, i_coding_type );
+ }
+ else
+ {
+ ppf_parse_mb[i_structure][i_coding_type]
+ ( p_vpar, pi_mb_address, i_mb_address_save,
+ i_mb_base, b_mpeg2, i_coding_type,
+ i_chroma_format, i_structure,
+ b_second_field );
+ }
+ }
+
+ i_mb_address_save = *pi_mb_address;
+ if( p_vpar->picture.b_error )
+ {
+ return;
+ }
+ }
+ while( ShowBits( &p_vpar->bit_stream, 23 )
+ && !p_vpar->p_fifo->b_die );
+ NextStartCode( &p_vpar->bit_stream );
+}
+
+/*****************************************************************************
+ * PictureData : Parse off all macroblocks (ISO/IEC 13818-2 6.2.3.7)
+ *****************************************************************************/
+void vpar_PictureData( vpar_thread_t * p_vpar, int i_mb_base )
+{
+ int i_mb_address = 0;
+ u32 i_dummy;
+
+ NextStartCode( &p_vpar->bit_stream );
+ while( ((p_vpar->picture.i_coding_type != I_CODING_TYPE
+ && p_vpar->picture.i_coding_type != D_CODING_TYPE)
+ || !p_vpar->picture.b_error)
+ && i_mb_address < (p_vpar->sequence.i_mb_size
+ >> (p_vpar->picture.i_structure != FRAME_STRUCTURE))
+ && !p_vpar->p_fifo->b_die )
+ {
+ if( ((i_dummy = ShowBits( &p_vpar->bit_stream, 32 ))
+ < SLICE_START_CODE_MIN) ||
+ (i_dummy > SLICE_START_CODE_MAX) )
+ {
+ intf_DbgMsg("vpar debug: premature end of picture");
+ p_vpar->picture.b_error = 1;
+ break;
+ }
+ RemoveBits32( &p_vpar->bit_stream );
+
+ /* Decode slice data. */
+ SliceHeader( p_vpar, &i_mb_address, i_mb_base, i_dummy & 255,
+ (p_vpar->sequence.i_height > 2800),
+ (p_vpar->sequence.i_scalable_mode == SC_DP),
+ p_vpar->sequence.b_mpeg2, p_vpar->picture.i_coding_type,
+ p_vpar->sequence.i_chroma_format,
+ p_vpar->picture.i_structure,
+ (p_vpar->picture.i_structure !=
+ p_vpar->picture.i_current_structure) );
+ }
+
+ /* Try to recover from error. If we missed less than half the
+ * number of macroblocks of the picture, mark the missed ones
+ * as skipped. */
+ if( (p_vpar->picture.i_coding_type == P_CODING_TYPE
+ || p_vpar->picture.i_coding_type == B_CODING_TYPE)
+ && p_vpar->picture.b_error &&
+ ( (i_mb_address-i_mb_base) > (p_vpar->sequence.i_mb_size >> 1)
+ || (p_vpar->picture.i_structure != FRAME_STRUCTURE
+ && (i_mb_address-i_mb_base) > (p_vpar->sequence.i_mb_size >> 2) ) ) )
+ {
+ int i_mb;
+
+ p_vpar->picture.b_error = 0;
+ for( i_mb = i_mb_address + 1;
+ i_mb < (p_vpar->sequence.i_mb_size
+ << (p_vpar->picture.i_structure != FRAME_STRUCTURE));
+ i_mb++ )
+ {
+ SkippedMacroblock( p_vpar, i_mb, i_mb_base,
+ p_vpar->picture.i_coding_type,
+ p_vpar->sequence.i_chroma_format,
+ p_vpar->picture.i_structure,
+ (p_vpar->picture.i_structure !=
+ p_vpar->picture.i_current_structure) );
+ }
+ }
+}
+