Commit febaed28 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont Committed by Jean-Baptiste Kempf

swscale: scale within the crop area, not top-left (really fixes #12085)

Unfortunately, this can cause a slight offset of the colour planes if the
top/left crop offset is not a multiple of the subsampling ratio.

(cherry picked from commit 05c433624791b01babcb1ccb72766fb2a5062fab)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>

Conflicts:
	modules/video_chroma/swscale.c
parent a09ec05d
...@@ -91,6 +91,8 @@ struct filter_sys_t ...@@ -91,6 +91,8 @@ struct filter_sys_t
video_format_t fmt_in; video_format_t fmt_in;
video_format_t fmt_out; video_format_t fmt_out;
const vlc_chroma_description_t *desc_in;
const vlc_chroma_description_t *desc_out;
struct SwsContext *ctx; struct SwsContext *ctx;
struct SwsContext *ctxA; struct SwsContext *ctxA;
...@@ -387,6 +389,11 @@ static int Init( filter_t *p_filter ) ...@@ -387,6 +389,11 @@ static int Init( filter_t *p_filter )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_sys->desc_in = vlc_fourcc_GetChromaDescription( p_fmti->i_chroma );
p_sys->desc_out = vlc_fourcc_GetChromaDescription( p_fmto->i_chroma );
if( p_sys->desc_in == NULL || p_sys->desc_out == NULL )
return VLC_EGENERIC;
/* swscale does not like too small width */ /* swscale does not like too small width */
p_sys->i_extend_factor = 1; p_sys->i_extend_factor = 1;
while( __MIN( p_fmti->i_visible_width, p_fmto->i_visible_width ) * p_sys->i_extend_factor < MINIMUM_WIDTH) while( __MIN( p_fmti->i_visible_width, p_fmto->i_visible_width ) * p_sys->i_extend_factor < MINIMUM_WIDTH)
...@@ -499,22 +506,35 @@ static void Clean( filter_t *p_filter ) ...@@ -499,22 +506,35 @@ static void Clean( filter_t *p_filter )
} }
static void GetPixels( uint8_t *pp_pixel[4], int pi_pitch[4], static void GetPixels( uint8_t *pp_pixel[4], int pi_pitch[4],
const picture_t *p_picture, const vlc_chroma_description_t *desc,
int i_plane_start, int i_plane_count, const video_format_t *fmt,
const picture_t *p_picture, unsigned planes,
bool b_swap_uv ) bool b_swap_uv )
{ {
assert( !b_swap_uv || i_plane_count >= 3 ); unsigned i = 0;
int n;
for( n = 0; n < __MIN(i_plane_count, p_picture->i_planes-i_plane_start ); n++ ) if( planes > (unsigned)p_picture->i_planes )
planes = p_picture->i_planes;
assert( !b_swap_uv || planes >= 3 );
for( ; i < planes; i++ )
{ {
const int nd = ( b_swap_uv && n >= 1 && n <= 2 ) ? (3 - n) : n; const plane_t *p = p_picture->p + i;
pp_pixel[nd] = p_picture->p[i_plane_start+n].p_pixels; if( b_swap_uv && (i == 1 || i== 2) )
pi_pitch[nd] = p_picture->p[i_plane_start+n].i_pitch; p = p_picture->p + 3 - i;
pp_pixel[i] = p->p_pixels
+ (((fmt->i_x_offset * desc->p[i].w.num) / desc->p[i].w.den)
* p->i_pixel_pitch)
+ (((fmt->i_y_offset * desc->p[i].h.num) / desc->p[i].h.den)
* p->i_pitch);
pi_pitch[i] = p->i_pitch;
} }
for( ; n < 4; n++ )
for( ; i < 4; i++ )
{ {
pp_pixel[n] = NULL; pp_pixel[i] = NULL;
pi_pitch[n] = 0; pi_pitch[i] = 0;
} }
} }
...@@ -571,16 +591,18 @@ static void SwapUV( picture_t *p_dst, const picture_t *p_src ) ...@@ -571,16 +591,18 @@ static void SwapUV( picture_t *p_dst, const picture_t *p_src )
picture_CopyPixels( p_dst, &tmp ); picture_CopyPixels( p_dst, &tmp );
} }
static void Convert( filter_t *p_filter, struct SwsContext *ctx, static void Convert( filter_t *p_filter, struct SwsContext *ctx,
picture_t *p_dst, picture_t *p_src, int i_height, int i_plane_start, int i_plane_count, picture_t *p_dst, picture_t *p_src, int i_height, int i_plane_start, int i_plane_count,
bool b_swap_uvi, bool b_swap_uvo ) bool b_swap_uvi, bool b_swap_uvo )
{ {
filter_sys_t *p_sys = p_filter->p_sys;
uint8_t palette[AVPALETTE_SIZE]; uint8_t palette[AVPALETTE_SIZE];
uint8_t *src[4]; int src_stride[4]; uint8_t *src[4]; int src_stride[4];
uint8_t *dst[4]; int dst_stride[4]; uint8_t *dst[4]; int dst_stride[4];
GetPixels( src, src_stride, p_src, i_plane_start, i_plane_count, b_swap_uvi ); GetPixels( src, src_stride, p_sys->desc_in, &p_filter->fmt_in.video,
p_src, i_plane_count, b_swap_uvi );
if( p_filter->fmt_in.video.i_chroma == VLC_CODEC_RGBP ) if( p_filter->fmt_in.video.i_chroma == VLC_CODEC_RGBP )
{ {
memset( palette, 0, sizeof(palette) ); memset( palette, 0, sizeof(palette) );
...@@ -591,7 +613,8 @@ static void Convert( filter_t *p_filter, struct SwsContext *ctx, ...@@ -591,7 +613,8 @@ static void Convert( filter_t *p_filter, struct SwsContext *ctx,
src_stride[1] = 4; src_stride[1] = 4;
} }
GetPixels( dst, dst_stride, p_dst, i_plane_start, i_plane_count, b_swap_uvo ); GetPixels( dst, dst_stride, p_sys->desc_out, &p_filter->fmt_out.video,
p_dst, i_plane_count, b_swap_uvo );
#if LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) #if LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0)
sws_scale( ctx, src, src_stride, 0, i_height, sws_scale( ctx, src, src_stride, 0, i_height,
......
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