Commit e3e5395d authored by Laurent Aimar's avatar Laurent Aimar

Added support for all planar 8 bit YUV chromas to the deinterlace filter.

parent 87371c40
...@@ -1438,9 +1438,9 @@ static bool IVTCOutputOrDropFrame( filter_t *p_filter, picture_t *p_dst ) ...@@ -1438,9 +1438,9 @@ static bool IVTCOutputOrDropFrame( filter_t *p_filter, picture_t *p_dst )
else if( op == IVTC_OP_COPY_C ) else if( op == IVTC_OP_COPY_C )
picture_Copy( p_dst, p_curr ); picture_Copy( p_dst, p_curr );
else if( op == IVTC_OP_COMPOSE_TNBC ) else if( op == IVTC_OP_COMPOSE_TNBC )
ComposeFrame( p_filter, p_dst, p_next, p_curr, CC_ALTLINE ); ComposeFrame( p_filter, p_dst, p_next, p_curr, CC_ALTLINE, false );
else if( op == IVTC_OP_COMPOSE_TCBN ) else if( op == IVTC_OP_COMPOSE_TCBN )
ComposeFrame( p_filter, p_dst, p_curr, p_next, CC_ALTLINE ); ComposeFrame( p_filter, p_dst, p_curr, p_next, CC_ALTLINE, false );
/* Slide history of outgoing interlace scores. This must be done last, /* Slide history of outgoing interlace scores. This must be done last,
and only if the frame was not dropped, so we do it here. and only if the frame was not dropped, so we do it here.
......
...@@ -68,8 +68,9 @@ ...@@ -68,8 +68,9 @@
* @see RenderPhosphor() * @see RenderPhosphor()
* @see ComposeFrame() * @see ComposeFrame()
*/ */
static void DarkenField( picture_t *p_dst, const int i_field, static void DarkenField( picture_t *p_dst,
const int i_strength ) const int i_field, const int i_strength,
bool process_chroma )
{ {
assert( p_dst != NULL ); assert( p_dst != NULL );
assert( i_field == 0 || i_field == 1 ); assert( i_field == 0 || i_field == 1 );
...@@ -147,8 +148,7 @@ static void DarkenField( picture_t *p_dst, const int i_field, ...@@ -147,8 +148,7 @@ static void DarkenField( picture_t *p_dst, const int i_field,
The chroma processing is a bit more complicated than luma, The chroma processing is a bit more complicated than luma,
and needs MMX for vectorization. and needs MMX for vectorization.
*/ */
if( p_dst->format.i_chroma == VLC_CODEC_I422 || if( process_chroma )
p_dst->format.i_chroma == VLC_CODEC_J422 )
{ {
for( i_plane = 0 ; i_plane < p_dst->i_planes ; i_plane++ ) for( i_plane = 0 ; i_plane < p_dst->i_planes ; i_plane++ )
{ {
...@@ -213,7 +213,7 @@ static void DarkenField( picture_t *p_dst, const int i_field, ...@@ -213,7 +213,7 @@ static void DarkenField( picture_t *p_dst, const int i_field,
(*po) = 128 + ( ((*po) - 128) / (1 << i_strength) ); (*po) = 128 + ( ((*po) - 128) / (1 << i_strength) );
} /* for p_out... */ } /* for p_out... */
} /* for i_plane... */ } /* for i_plane... */
} /* if b_i422 */ } /* if process_chroma */
#ifdef CAN_COMPILE_MMXEXT #ifdef CAN_COMPILE_MMXEXT
if( u_cpu & CPU_CAPABILITY_MMXEXT ) if( u_cpu & CPU_CAPABILITY_MMXEXT )
...@@ -265,9 +265,13 @@ int RenderPhosphor( filter_t *p_filter, ...@@ -265,9 +265,13 @@ int RenderPhosphor( filter_t *p_filter,
p_in_top = p_old; p_in_top = p_old;
} }
compose_chroma_t cc = CC_ALTLINE; /* initialize to prevent compiler warning */ compose_chroma_t cc = CC_ALTLINE;
switch( p_sys->phosphor.i_chroma_for_420 ) if( 2 * p_sys->chroma->p[1].h.num == p_sys->chroma->p[1].h.den &&
2 * p_sys->chroma->p[2].h.num == p_sys->chroma->p[2].h.den )
{ {
/* Only 420 like chroma */
switch( p_sys->phosphor.i_chroma_for_420 )
{
case PC_BLEND: case PC_BLEND:
cc = CC_MERGE; cc = CC_MERGE;
break; break;
...@@ -287,9 +291,9 @@ int RenderPhosphor( filter_t *p_filter, ...@@ -287,9 +291,9 @@ int RenderPhosphor( filter_t *p_filter,
/* The above are the only possibilities, if there are no bugs. */ /* The above are the only possibilities, if there are no bugs. */
assert(0); assert(0);
break; break;
}
} }
ComposeFrame( p_filter, p_dst, p_in_top, p_in_bottom, cc, p_filter->fmt_in.video.i_chroma == VLC_CODEC_YV12 );
ComposeFrame( p_filter, p_dst, p_in_top, p_in_bottom, cc );
/* Simulate phosphor light output decay for the old field. /* Simulate phosphor light output decay for the old field.
...@@ -301,7 +305,9 @@ int RenderPhosphor( filter_t *p_filter, ...@@ -301,7 +305,9 @@ int RenderPhosphor( filter_t *p_filter,
In most use cases the dimmer is used. In most use cases the dimmer is used.
*/ */
if( p_sys->phosphor.i_dimmer_strength > 0 ) if( p_sys->phosphor.i_dimmer_strength > 0 )
DarkenField( p_dst, !i_field, p_sys->phosphor.i_dimmer_strength ); DarkenField( p_dst, !i_field, p_sys->phosphor.i_dimmer_strength,
p_sys->chroma->p[1].h.num == p_sys->chroma->p[1].h.den &&
p_sys->chroma->p[2].h.num == p_sys->chroma->p[2].h.den );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -242,7 +242,8 @@ void GetOutputFormat( filter_t *p_filter, ...@@ -242,7 +242,8 @@ void GetOutputFormat( filter_t *p_filter,
} }
if( p_sys->i_mode == DEINTERLACE_PHOSPHOR && if( p_sys->i_mode == DEINTERLACE_PHOSPHOR &&
p_src->i_chroma != VLC_CODEC_I422 && p_src->i_chroma != VLC_CODEC_J422 && 2 * p_sys->chroma->p[1].h.num == p_sys->chroma->p[1].h.den &&
2 * p_sys->chroma->p[2].h.num == p_sys->chroma->p[2].h.den &&
p_sys->phosphor.i_chroma_for_420 == PC_UPCONVERT ) p_sys->phosphor.i_chroma_for_420 == PC_UPCONVERT )
{ {
p_dst->i_chroma = p_src->i_chroma == VLC_CODEC_J420 ? VLC_CODEC_J422 : p_dst->i_chroma = p_src->i_chroma == VLC_CODEC_J420 ? VLC_CODEC_J422 :
...@@ -255,19 +256,6 @@ void GetOutputFormat( filter_t *p_filter, ...@@ -255,19 +256,6 @@ void GetOutputFormat( filter_t *p_filter,
} }
/*****************************************************************************
* IsChromaSupported: return whether the specified chroma is implemented.
*****************************************************************************/
bool IsChromaSupported( vlc_fourcc_t i_chroma )
{
return i_chroma == VLC_CODEC_I420 ||
i_chroma == VLC_CODEC_J420 ||
i_chroma == VLC_CODEC_YV12 ||
i_chroma == VLC_CODEC_I422 ||
i_chroma == VLC_CODEC_J422;
}
/***************************************************************************** /*****************************************************************************
* video filter2 functions * video filter2 functions
*****************************************************************************/ *****************************************************************************/
...@@ -607,14 +595,21 @@ int Open( vlc_object_t *p_this ) ...@@ -607,14 +595,21 @@ int Open( vlc_object_t *p_this )
filter_t *p_filter = (filter_t*)p_this; filter_t *p_filter = (filter_t*)p_this;
filter_sys_t *p_sys; filter_sys_t *p_sys;
if( !IsChromaSupported( p_filter->fmt_in.video.i_chroma ) ) const vlc_fourcc_t fourcc = p_filter->fmt_in.video.i_chroma;
const vlc_chroma_description_t *chroma = vlc_fourcc_GetChromaDescription( fourcc );
if( !vlc_fourcc_IsYUV( fourcc ) ||
!chroma || chroma->plane_count != 3 || chroma->pixel_size != 1 )
{
msg_Err( p_filter, "Unsupported chroma (%4.4s)", (char*)&fourcc );
return VLC_EGENERIC; return VLC_EGENERIC;
}
/* */ /* */
p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) ); p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) );
if( !p_sys ) if( !p_sys )
return VLC_ENOMEM; return VLC_ENOMEM;
p_sys->chroma = chroma;
p_sys->i_mode = DEINTERLACE_BLEND; p_sys->i_mode = DEINTERLACE_BLEND;
p_sys->b_double_rate = false; p_sys->b_double_rate = false;
p_sys->b_half_height = true; p_sys->b_half_height = true;
......
...@@ -89,6 +89,8 @@ typedef struct { ...@@ -89,6 +89,8 @@ typedef struct {
*/ */
struct filter_sys_t struct filter_sys_t
{ {
const vlc_chroma_description_t *chroma;
int i_mode; /**< Deinterlace mode */ int i_mode; /**< Deinterlace mode */
/* Algorithm behaviour flags */ /* Algorithm behaviour flags */
...@@ -150,20 +152,6 @@ void GetOutputFormat( filter_t *p_filter, ...@@ -150,20 +152,6 @@ void GetOutputFormat( filter_t *p_filter,
video_format_t *p_dst, video_format_t *p_dst,
const video_format_t *p_src ); const video_format_t *p_src );
/**
* Returns whether the specified chroma is implemented in the deinterlace
* filter.
*
* Currently, supported chromas are I420, J420 (4:2:0 full scale),
* YV12 (like I420, but YVU), I422 and J422.
*
* Note for deinterlace hackers: adding support for a new chroma typically
* requires changes to all low-level functions across all the algorithms.
*
* @see vlc_fourcc_t
*/
bool IsChromaSupported( vlc_fourcc_t i_chroma );
/***************************************************************************** /*****************************************************************************
* video filter2 functions * video filter2 functions
*****************************************************************************/ *****************************************************************************/
......
...@@ -246,11 +246,11 @@ static inline int TestForMotionInBlock( uint8_t *p_pix_p, uint8_t *p_pix_c, ...@@ -246,11 +246,11 @@ static inline int TestForMotionInBlock( uint8_t *p_pix_p, uint8_t *p_pix_c,
*****************************************************************************/ *****************************************************************************/
/* See header for function doc. */ /* See header for function doc. */
void ComposeFrame( filter_t *p_filter, picture_t *p_outpic, void ComposeFrame( filter_t *p_filter,
picture_t *p_outpic,
picture_t *p_inpic_top, picture_t *p_inpic_bottom, picture_t *p_inpic_top, picture_t *p_inpic_bottom,
compose_chroma_t i_output_chroma ) compose_chroma_t i_output_chroma, bool swapped_uv_conversion )
{ {
assert( p_filter != NULL );
assert( p_outpic != NULL ); assert( p_outpic != NULL );
assert( p_inpic_top != NULL ); assert( p_inpic_top != NULL );
assert( p_inpic_bottom != NULL ); assert( p_inpic_bottom != NULL );
...@@ -262,21 +262,14 @@ void ComposeFrame( filter_t *p_filter, picture_t *p_outpic, ...@@ -262,21 +262,14 @@ void ComposeFrame( filter_t *p_filter, picture_t *p_outpic,
i_output_chroma == CC_SOURCE_BOTTOM || i_output_chroma == CC_SOURCE_BOTTOM ||
i_output_chroma == CC_MERGE ); i_output_chroma == CC_MERGE );
const int i_chroma = p_filter->fmt_in.video.i_chroma; const bool b_upconvert_chroma = i_output_chroma == CC_UPCONVERT;
const bool b_i422 = i_chroma == VLC_CODEC_I422 ||
i_chroma == VLC_CODEC_J422;
const bool b_upconvert_chroma = ( !b_i422 &&
i_output_chroma == CC_UPCONVERT );
for( int i_plane = 0 ; i_plane < p_inpic_top->i_planes ; i_plane++ ) for( int i_plane = 0 ; i_plane < p_inpic_top->i_planes ; i_plane++ )
{ {
bool b_is_chroma_plane = ( i_plane == U_PLANE || i_plane == V_PLANE ); bool b_is_chroma_plane = ( i_plane == U_PLANE || i_plane == V_PLANE );
/* YV12 is YVU, but I422 is YUV. For such input, swap chroma planes
in output when converting to 4:2:2. */
int i_out_plane; int i_out_plane;
if( b_is_chroma_plane && b_upconvert_chroma && if( b_is_chroma_plane && b_upconvert_chroma && swapped_uv_conversion )
i_chroma == VLC_CODEC_YV12 )
{ {
if( i_plane == U_PLANE ) if( i_plane == U_PLANE )
i_out_plane = V_PLANE; i_out_plane = V_PLANE;
...@@ -289,7 +282,7 @@ void ComposeFrame( filter_t *p_filter, picture_t *p_outpic, ...@@ -289,7 +282,7 @@ void ComposeFrame( filter_t *p_filter, picture_t *p_outpic,
} }
/* Copy luma or chroma, alternating between input fields. */ /* Copy luma or chroma, alternating between input fields. */
if( !b_is_chroma_plane || b_i422 || i_output_chroma == CC_ALTLINE ) if( !b_is_chroma_plane || i_output_chroma == CC_ALTLINE )
{ {
/* Do an alternating line copy. This is always done for luma, /* Do an alternating line copy. This is always done for luma,
and for 4:2:2 chroma. It can be requested for 4:2:0 chroma and for 4:2:2 chroma. It can be requested for 4:2:0 chroma
......
...@@ -89,13 +89,15 @@ typedef enum { CC_ALTLINE, CC_UPCONVERT, CC_SOURCE_TOP, CC_SOURCE_BOTTOM, ...@@ -89,13 +89,15 @@ typedef enum { CC_ALTLINE, CC_UPCONVERT, CC_SOURCE_TOP, CC_SOURCE_BOTTOM,
* @param p_inpic_top Picture to extract the top field from. * @param p_inpic_top Picture to extract the top field from.
* @param p_inpic_bottom Picture to extract the bottom field from. * @param p_inpic_bottom Picture to extract the bottom field from.
* @param i_output_chroma Chroma operation mode for 4:2:0 (see function doc) * @param i_output_chroma Chroma operation mode for 4:2:0 (see function doc)
* @param swapped_uv_conversion Swap UV while up converting (for YV12)
* @see compose_chroma_t * @see compose_chroma_t
* @see RenderPhosphor() * @see RenderPhosphor()
* @see RenderIVTC() * @see RenderIVTC()
*/ */
void ComposeFrame( filter_t *p_filter, picture_t *p_outpic, void ComposeFrame( filter_t *p_filter,
picture_t *p_outpic,
picture_t *p_inpic_top, picture_t *p_inpic_bottom, picture_t *p_inpic_top, picture_t *p_inpic_bottom,
compose_chroma_t i_output_chroma ); compose_chroma_t i_output_chroma, bool swapped_uv_conversion );
/** /**
* Helper function: Estimates the number of 8x8 blocks which have motion * Helper function: Estimates the number of 8x8 blocks which have motion
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment