diff --git a/include/video_decoder.h b/include/video_decoder.h index 85f1efa7826ca416f56863d4b9df0cec9ae3fd0d..ebe4a21f2e53937ded0f8150625b7c081cc820e2 100644 --- a/include/video_decoder.h +++ b/include/video_decoder.h @@ -70,6 +70,9 @@ typedef struct vdec_thread_s count_t c_decoded_i_pictures; /* number of I pictures decoded */ count_t c_decoded_p_pictures; /* number of P pictures decoded */ count_t c_decoded_b_pictures; /* number of B pictures decoded */ + +/* void (*vdec_DecodeMacroblock) ( struct vdec_thread_s *p_vdec, + struct macroblock_s *p_mb );*/ #endif } vdec_thread_t; @@ -84,6 +87,10 @@ struct macroblock_s; int vdec_InitThread ( struct vdec_thread_s *p_vdec ); void vdec_DecodeMacroblock ( struct vdec_thread_s *p_vdec, struct macroblock_s *p_mb ); +void vdec_DecodeMacroblockC ( struct vdec_thread_s *p_vdec, + struct macroblock_s *p_mb ); +void vdec_DecodeMacroblockBW ( struct vdec_thread_s *p_vdec, + struct macroblock_s *p_mb ); #endif vdec_thread_t * vdec_CreateThread ( struct vpar_thread_s *p_vpar /*, int *pi_status */ ); diff --git a/include/video_output.h b/include/video_output.h index c9512846d1c27959331ae7c9b914cb46be915fb9..5e44b4e2469357d79b740241fd950d48ec2ffcbd 100644 --- a/include/video_output.h +++ b/include/video_output.h @@ -117,6 +117,10 @@ typedef int (yuv_sys_init_t) ( p_vout_thread_t p_vout ); typedef int (yuv_sys_reset_t) ( p_vout_thread_t p_vout ); typedef void (yuv_sys_end_t) ( p_vout_thread_t p_vout ); +struct macroblock_s; +typedef void (vdec_DecodeMacroblock_t) ( struct vdec_thread_s *p_vdec, + struct macroblock_s *p_mb ); + typedef struct vout_thread_s { /* Thread properties and lock */ @@ -129,6 +133,8 @@ typedef struct vout_thread_s vlc_mutex_t change_lock; /* thread change lock */ int * pi_status; /* temporary status flag */ p_vout_sys_t p_sys; /* system output method */ + vdec_DecodeMacroblock_t * + vdec_DecodeMacroblock; /* decoder function to use */ /* Current display properties */ u16 i_changes; /* changes made to the thread */ diff --git a/src/video_decoder/video_decoder.c b/src/video_decoder/video_decoder.c index 51a29f9aaa6c481b407ca63a021f32f7e6cb14f5..a94dd6e287518bec08c9a269915cbd83d8246559 100644 --- a/src/video_decoder/video_decoder.c +++ b/src/video_decoder/video_decoder.c @@ -59,8 +59,10 @@ */ #ifdef VDEC_SMP static int vdec_InitThread ( vdec_thread_t *p_vdec ); -static void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, - macroblock_t * p_mb ); +static void vdec_DecodeMacroblockC ( vdec_thread_t *p_vdec, + macroblock_t * p_mb ); +static void vdec_DecodeMacroblockBW ( vdec_thread_t *p_vdec, + macroblock_t * p_mb ); #endif static void RunThread ( vdec_thread_t *p_vdec ); static void ErrorThread ( vdec_thread_t *p_vdec ); @@ -397,7 +399,7 @@ static __inline__ void CopyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, /***************************************************************************** * vdec_DecodeMacroblock : decode a macroblock of a picture *****************************************************************************/ -#define DECODEBLOCKS( OPBLOCK ) \ +#define DECODEBLOCKSC( OPBLOCK ) \ { \ int i_b, i_mask; \ \ @@ -445,10 +447,37 @@ static __inline__ void CopyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, } \ } +#define DECODEBLOCKSBW( OPBLOCK ) \ +{ \ + int i_b, i_mask; \ + \ + i_mask = 1 << (3 + p_mb->i_chroma_nb_blocks); \ + \ + /* luminance */ \ + for( i_b = 0; i_b < 4; i_b++, i_mask >>= 1 ) \ + { \ + if( p_mb->i_coded_block_pattern & i_mask ) \ + { \ + /* \ + * Inverse DCT (ISO/IEC 13818-2 section Annex A) \ + */ \ + (p_mb->pf_idct[i_b])( p_vdec, p_mb->ppi_blocks[i_b], \ + p_mb->pi_sparse_pos[i_b] ); \ + \ + /* \ + * Adding prediction and coefficient data (ISO/IEC 13818-2 \ + * section 7.6.8) \ + */ \ + OPBLOCK( p_vdec, p_mb->ppi_blocks[i_b], \ + p_mb->p_data[i_b], p_mb->i_addb_l_stride ); \ + } \ + } \ +} + #ifdef VDEC_SMP -static __inline__ void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb ) +static __inline__ void vdec_DecodeMacroblockC ( vdec_thread_t *p_vdec, macroblock_t * p_mb ) #else -void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb ) +void vdec_DecodeMacroblockC ( vdec_thread_t *p_vdec, macroblock_t * p_mb ) #endif { if( !(p_mb->i_mb_type & MB_INTRA) ) @@ -465,11 +494,11 @@ void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb ) p_mb->pf_motion( p_mb ); } - DECODEBLOCKS( AddBlock ) + DECODEBLOCKSC( AddBlock ) } else { - DECODEBLOCKS( CopyBlock ) + DECODEBLOCKSC( CopyBlock ) } /* @@ -479,6 +508,41 @@ void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb ) vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb ); } +#ifdef VDEC_SMP +static __inline__ void vdec_DecodeMacroblockBW ( vdec_thread_t *p_vdec, macroblock_t * p_mb ) +#else +void vdec_DecodeMacroblockBW ( vdec_thread_t *p_vdec, macroblock_t * p_mb ) +#endif +{ + if( !(p_mb->i_mb_type & MB_INTRA) ) + { + /* + * Motion Compensation (ISO/IEC 13818-2 section 7.6) + */ + if( p_mb->pf_motion == 0 ) + { + intf_ErrMsg( "vdec error: pf_motion set to NULL\n" ); + } + else + { + p_mb->pf_motion( p_mb ); + } + + DECODEBLOCKSBW( AddBlock ) + } + else + { + DECODEBLOCKSBW( CopyBlock ) + } + + /* + * Decoding is finished, release the macroblock and free + * unneeded memory. + */ + vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb ); +} + + /***************************************************************************** * RunThread: video decoder thread @@ -511,7 +575,7 @@ static void RunThread( vdec_thread_t *p_vdec ) if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL ) { - vdec_DecodeMacroblock( p_vdec, p_mb ); + p_vdec->p_vpar->p_vout->vdec_DecodeMacroblock ( p_vdec, p_mb ); } } diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 8199b82f988fd5dce8c5f74e0b1c0ea4e3d76176..15df2916b63a3049332a3f2f7838edfddf4da841 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -47,6 +47,9 @@ #include "intf_msg.h" #include "main.h" +#include "vdec_idct.h" +#include "video_decoder.h" + /***************************************************************************** * Local prototypes *****************************************************************************/ @@ -69,7 +72,7 @@ static void RenderSubPicture ( vout_thread_t *p_vout, subpicture_t *p_subpic ); static void RenderInterface ( vout_thread_t *p_vout ); static int RenderIdle ( vout_thread_t *p_vout ); -static int RenderSplash( vout_thread_t *p_vout ); +static int RenderSplash ( vout_thread_t *p_vout ); static void RenderInfo ( vout_thread_t *p_vout ); static void Synchronize ( vout_thread_t *p_vout, s64 i_delay ); static int Manage ( vout_thread_t *p_vout ); @@ -149,19 +152,20 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window, /* Initialize some fields used by the system-dependant method - these * fields will probably be modified by the method, and are only * preferences */ - p_vout->i_changes = 0; - p_vout->i_width = i_width; - p_vout->i_height = i_height; - p_vout->i_bytes_per_line = i_width * 2; - p_vout->i_screen_depth = 15; - p_vout->i_bytes_per_pixel = 2; - p_vout->f_gamma = VOUT_GAMMA; - - p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR, + p_vout->i_changes = 0; + p_vout->i_width = i_width; + p_vout->i_height = i_height; + p_vout->i_bytes_per_line = i_width * 2; + p_vout->i_screen_depth = 15; + p_vout->i_bytes_per_pixel = 2; + p_vout->f_gamma = VOUT_GAMMA; + + p_vout->b_grayscale = main_GetIntVariable( VOUT_GRAYSCALE_VAR, VOUT_GRAYSCALE_DEFAULT ); - p_vout->b_info = 0; - p_vout->b_interface = 0; - p_vout->b_scale = 1; + p_vout->vdec_DecodeMacroblock = vdec_DecodeMacroblockC; + p_vout->b_info = 0; + p_vout->b_interface = 0; + p_vout->b_scale = 1; intf_DbgMsg( "wished configuration: %dx%d, %d/%d bpp (%d Bpl)\n", p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, @@ -2107,6 +2111,17 @@ static int Manage( vout_thread_t *p_vout ) if( p_vout->i_changes & (VOUT_GAMMA_CHANGE | VOUT_GRAYSCALE_CHANGE | VOUT_YUV_CHANGE) ) { + /* Change vdec_DecodeMacroblock when switching between BW and C */ + if( (!p_vout->b_grayscale) + && (VOUT_GRAYSCALE_CHANGE) ) + { + p_vout->vdec_DecodeMacroblock = vdec_DecodeMacroblockC; + } + else if( (p_vout->b_grayscale) + && (VOUT_GRAYSCALE_CHANGE) ) + { + p_vout->vdec_DecodeMacroblock = vdec_DecodeMacroblockBW; + } if( vout_ResetYUV( p_vout ) ) { intf_ErrMsg("error: can't rebuild convertion tables\n"); diff --git a/src/video_parser/vpar_blocks.c b/src/video_parser/vpar_blocks.c index 82870b4ddfba065ac7bc729aae665781a2df88e9..99d3438a68e52704fd82432f405bfe2103c07175 100644 --- a/src/video_parser/vpar_blocks.c +++ b/src/video_parser/vpar_blocks.c @@ -1631,7 +1631,7 @@ static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb, #ifndef VDEC_SMP /* Decode the macroblock NOW ! */ - vdec_DecodeMacroblock( p_vpar->pp_vdec[0], p_mb ); + p_vpar->p_vout->vdec_DecodeMacroblock ( p_vpar->pp_vdec[0], p_mb ); #endif } @@ -2005,7 +2005,7 @@ static __inline__ void ParseMacroblock( UpdateContext( p_vpar, i_structure ); #ifndef VDEC_SMP /* Decode the macroblock NOW ! */ - vdec_DecodeMacroblock( p_vpar->pp_vdec[0], p_mb ); + p_vpar->p_vout->vdec_DecodeMacroblock ( p_vpar->pp_vdec[0], p_mb ); #endif } else