From dd50e81c8969905671c66dfe7a927ca41aa2ded7 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Mon, 10 May 2010 20:26:07 +0200 Subject: [PATCH] Clean up crop/aspect ratio changes and associated video format. --- src/video_output/control.h | 31 +--- src/video_output/display.c | 6 +- src/video_output/video_output.c | 189 ++++++++++++++++------ src/video_output/vout_internal.h | 22 +-- src/video_output/vout_intf.c | 267 ++++++------------------------- src/video_output/vout_wrapper.c | 69 +------- 6 files changed, 202 insertions(+), 382 deletions(-) diff --git a/src/video_output/control.h b/src/video_output/control.h index a8010d0a32..168b5e78ad 100644 --- a/src/video_output/control.h +++ b/src/video_output/control.h @@ -40,10 +40,6 @@ enum { /* Controls */ - VOUT_CONTROL_SOURCE_ASPECT, - VOUT_CONTROL_SOURCE_CROP_BORDER, - VOUT_CONTROL_SOURCE_CROP_RATIO, - VOUT_CONTROL_SOURCE_CROP_WINDOW, /* OSD */ VOUT_CONTROL_OSD_MESSAGE, @@ -64,6 +60,11 @@ enum { VOUT_CONTROL_ON_TOP, /* bool */ VOUT_CONTROL_DISPLAY_FILLED, /* bool */ VOUT_CONTROL_ZOOM, /* pair */ + + VOUT_CONTROL_ASPECT_RATIO, /* pair */ + VOUT_CONTROL_CROP_BORDER, /* border */ + VOUT_CONTROL_CROP_RATIO, /* pair */ + VOUT_CONTROL_CROP_WINDOW, /* window */ }; typedef struct { @@ -86,17 +87,6 @@ typedef struct { int channel; char *string; } message; -#if 0 - struct { - int channel; - char *string; - text_style_t *style; - int flags; - int hmargin; - int vmargin; - mtime_t start; - mtime_t stop; - } text; struct { unsigned left; unsigned top; @@ -109,17 +99,6 @@ typedef struct { unsigned width; unsigned height; } window; - struct { - int channel; - int type; - float position; - } slider; - struct { - int channel; - int icon; - } icon; - subpicture_t *subpicture; -#endif } u; } vout_control_cmd_t; diff --git a/src/video_output/display.c b/src/video_output/display.c index 6ea5132624..7d747c215b 100644 --- a/src/video_output/display.c +++ b/src/video_output/display.c @@ -525,9 +525,6 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) if (!vd->info.has_hide_mouse) osys->mouse.last_moved = mdate(); - /* */ - vlc_mutex_unlock(&osys->lock); - /* */ vout_SendEventMouseVisible(osys->vout); #ifdef ALLOW_DUMMY_VOUT @@ -535,6 +532,7 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) #else vout_SendDisplayEventMouse(osys->vout, &m); #endif + vlc_mutex_unlock(&osys->lock); } static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args) @@ -1412,7 +1410,7 @@ void vout_SendDisplayEventMouse(vout_thread_t *vout, const vlc_mouse_t *m) vlc_mouse_t tmp; /* The check on p_spu is needed as long as ALLOW_DUMMY_VOUT is defined */ - if (vout->p->p_spu && spu_ProcessMouse( vout->p->p_spu, m, &vout->p->fmt_out)) + if (vout->p->p_spu && spu_ProcessMouse( vout->p->p_spu, m, &vout->p->display.vd->source)) return; vlc_mutex_lock( &vout->p->vfilter_lock ); diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 5069d7c5cf..8d82a419a1 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -161,11 +161,7 @@ vout_thread_t *vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout, free( psz_filter_chain ); } -#warning "FIXME: Check RGB masks in vout_Request" - /* FIXME: check RGB masks */ - if( p_vout->p->fmt_render.i_chroma != vlc_fourcc_GetCodec( VIDEO_ES, p_fmt->i_chroma ) || - p_vout->p->fmt_render.i_width != p_fmt->i_width || - p_vout->p->fmt_render.i_height != p_fmt->i_height || + if( !video_format_IsSimilar( &p_vout->p->original, p_fmt ) || p_vout->p->b_filter_change ) { vlc_mutex_unlock( &p_vout->p->change_lock ); @@ -178,32 +174,6 @@ vout_thread_t *vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout, else { /* This video output is cool! Hijack it. */ - /* Correct aspect ratio on change - * FIXME factorize this code with other aspect ration related code */ - unsigned int i_sar_num; - unsigned int i_sar_den; - vlc_ureduce( &i_sar_num, &i_sar_den, - p_fmt->i_sar_num, p_fmt->i_sar_den, 50000 ); -#if 0 - /* What's that, it does not seems to be used correcly everywhere */ - if( p_vout->i_par_num > 0 && p_vout->i_par_den > 0 ) - { - i_sar_num *= p_vout->i_par_den; - i_sar_den *= p_vout->i_par_num; - } -#endif - - if( i_sar_num > 0 && i_sar_den > 0 && - ( i_sar_num != p_vout->p->fmt_render.i_sar_num || - i_sar_den != p_vout->p->fmt_render.i_sar_den ) ) - { - p_vout->p->fmt_in.i_sar_num = i_sar_num; - p_vout->p->fmt_in.i_sar_den = i_sar_den; - - p_vout->p->fmt_render.i_sar_num = i_sar_num; - p_vout->p->fmt_render.i_sar_den = i_sar_den; - p_vout->p->i_changes |= VOUT_ASPECT_CHANGE; - } vlc_mutex_unlock( &p_vout->p->change_lock ); vlc_object_release( p_vout ); @@ -272,17 +242,12 @@ vout_thread_t * (vout_Create)( vlc_object_t *p_parent, video_format_t *p_fmt ) } /* */ - p_vout->p->fmt_render = *p_fmt; /* FIXME palette */ - p_vout->p->fmt_in = *p_fmt; /* FIXME palette */ - - p_vout->p->fmt_render.i_chroma = - p_vout->p->fmt_in.i_chroma = i_chroma; - video_format_FixRgb( &p_vout->p->fmt_render ); - video_format_FixRgb( &p_vout->p->fmt_in ); + p_vout->p->original = *p_fmt; /* FIXME palette */ + p_vout->p->original.i_chroma = i_chroma; + video_format_FixRgb( &p_vout->p->original ); /* Initialize misc stuff */ vout_control_Init( &p_vout->p->control ); - p_vout->p->i_changes = 0; vout_chrono_Init( &p_vout->p->render, 5, 10000 ); /* Arbitrary initial time */ vout_statistic_Init( &p_vout->p->statistic ); p_vout->p->b_filter_change = 0; @@ -593,6 +558,42 @@ void vout_ControlChangeZoom(vout_thread_t *vout, int num, int den) vout_control_PushPair(&vout->p->control, VOUT_CONTROL_ZOOM, num, den); } +void vout_ControlChangeSampleAspectRatio(vout_thread_t *vout, + unsigned num, unsigned den) +{ + vout_control_PushPair(&vout->p->control, VOUT_CONTROL_ASPECT_RATIO, + num, den); +} +void vout_ControlChangeCropRatio(vout_thread_t *vout, + unsigned num, unsigned den) +{ + vout_control_PushPair(&vout->p->control, VOUT_CONTROL_CROP_RATIO, + num, den); +} +void vout_ControlChangeCropWindow(vout_thread_t *vout, + int x, int y, int width, int height) +{ + vout_control_cmd_t cmd; + vout_control_cmd_Init(&cmd, VOUT_CONTROL_CROP_WINDOW); + cmd.u.window.x = x; + cmd.u.window.y = y; + cmd.u.window.width = width; + cmd.u.window.height = height; + + vout_control_Push(&vout->p->control, &cmd); +} +void vout_ControlChangeCropBorder(vout_thread_t *vout, + int left, int top, int right, int bottom) +{ + vout_control_cmd_t cmd; + vout_control_cmd_Init(&cmd, VOUT_CONTROL_CROP_BORDER); + cmd.u.border.left = left; + cmd.u.border.top = top; + cmd.u.border.right = right; + cmd.u.border.bottom = bottom; + + vout_control_Push(&vout->p->control, &cmd); +} /***************************************************************************** * InitThread: initialize video output thread @@ -613,19 +614,14 @@ static int ThreadInit(vout_thread_t *vout) /* print some usefull debug info about different vout formats */ - PrintVideoFormat(vout, "pic render", &vout->p->fmt_render); - PrintVideoFormat(vout, "pic in", &vout->p->fmt_in); - PrintVideoFormat(vout, "pic out", &vout->p->fmt_out); - - assert(vout->p->fmt_out.i_width == vout->p->fmt_render.i_width && - vout->p->fmt_out.i_height == vout->p->fmt_render.i_height && - vout->p->fmt_out.i_chroma == vout->p->fmt_render.i_chroma); + PrintVideoFormat(vout, "pic render", &vout->p->original); return VLC_SUCCESS; } static int ThreadDisplayPicture(vout_thread_t *vout, bool now, mtime_t *deadline) { + vout_display_t *vd = vout->p->display.vd; int displayed_count = 0; int lost_count = 0; @@ -743,7 +739,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout, (vout->p->decoder_pool != vout->p->display_pool || subpic)) { picture_t *render; if (vout->p->is_decoder_pool_slow) - render = picture_NewFromFormat(&vout->p->fmt_out); + render = picture_NewFromFormat(&vd->source); else if (vout->p->decoder_pool != vout->p->display_pool) render = picture_pool_Get(vout->p->display_pool); else @@ -753,8 +749,8 @@ static int ThreadDisplayPicture(vout_thread_t *vout, picture_Copy(render, filtered); spu_RenderSubpictures(vout->p->p_spu, - render, &vout->p->fmt_out, - subpic, &vout->p->fmt_in, spu_render_time); + render, &vd->source, + subpic, &vd->source, spu_render_time); } if (vout->p->is_decoder_pool_slow) { direct = picture_pool_Get(vout->p->display_pool); @@ -775,7 +771,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout, * Take a snapshot if requested */ if (direct && do_snapshot) - vout_snapshot_Set(&vout->p->snapshot, &vout->p->fmt_out, direct); + vout_snapshot_Set(&vout->p->snapshot, &vd->source, direct); /* Render the direct buffer returned by vout_RenderPicture */ if (direct) { @@ -857,8 +853,8 @@ static void ThreadDisplayOsdTitle(vout_thread_t *vout, const char *string) static void ThreadChangeFilters(vout_thread_t *vout, const char *filters) { es_format_t fmt; - es_format_Init(&fmt, VIDEO_ES, vout->p->fmt_render.i_chroma); - fmt.video = vout->p->fmt_render; + es_format_Init(&fmt, VIDEO_ES, vout->p->original.i_chroma); + fmt.video = vout->p->original; vlc_mutex_lock(&vout->p->vfilter_lock); @@ -975,6 +971,79 @@ static void ThreadChangeZoom(vout_thread_t *vout, int num, int den) vout_SetDisplayZoom(vout->p->display.vd, num, den); } +static void ThreadChangeAspectRatio(vout_thread_t *vout, + unsigned num, unsigned den) +{ + const video_format_t *source = &vout->p->original; + + if (num > 0 && den > 0) { + num *= source->i_visible_height; + den *= source->i_visible_width; + vlc_ureduce(&num, &den, num, den, 0); + } + vout_SetDisplayAspect(vout->p->display.vd, num, den); +} + + +static void ThreadExecuteCropWindow(vout_thread_t *vout, + unsigned crop_num, unsigned crop_den, + unsigned x, unsigned y, + unsigned width, unsigned height) +{ + const video_format_t *source = &vout->p->original; + + vout_SetDisplayCrop(vout->p->display.vd, + crop_num, crop_den, + source->i_x_offset + x, + source->i_y_offset + y, + width, height); +} +static void ThreadExecuteCropBorder(vout_thread_t *vout, + unsigned left, unsigned top, + unsigned right, unsigned bottom) +{ + const video_format_t *source = &vout->p->original; + ThreadExecuteCropWindow(vout, 0, 0, + left, + top, + /* At worst, it becomes < 0 (but unsigned) and will be rejected */ + source->i_visible_width - (left + right), + source->i_visible_height - (top + bottom)); +} + +static void ThreadExecuteCropRatio(vout_thread_t *vout, + unsigned num, unsigned den) +{ + const video_format_t *source = &vout->p->original; + + int x, y; + int width, height; + if (num <= 0 || den <= 0) { + num = 0; + den = 0; + x = 0; + y = 0; + width = source->i_visible_width; + height = source->i_visible_height; + } else { + unsigned scaled_width = (uint64_t)source->i_visible_height * num * source->i_sar_den / den / source->i_sar_num; + unsigned scaled_height = (uint64_t)source->i_visible_width * den * source->i_sar_num / num / source->i_sar_den; + + if (scaled_width < source->i_visible_width) { + x = (source->i_visible_width - scaled_width) / 2; + y = 0; + width = scaled_width; + height = source->i_visible_height; + } else { + x = 0; + y = (source->i_visible_height - scaled_height) / 2; + width = source->i_visible_width; + height = scaled_height; + } + } + ThreadExecuteCropWindow(vout, num, den, x, y, width, height); +} + static void ThreadClean(vout_thread_t *vout) { /* Destroy translation tables */ @@ -1070,6 +1139,22 @@ static void *Thread(void *object) case VOUT_CONTROL_ZOOM: ThreadChangeZoom(vout, cmd.u.pair.a, cmd.u.pair.b); break; + case VOUT_CONTROL_ASPECT_RATIO: + ThreadChangeAspectRatio(vout, cmd.u.pair.a, cmd.u.pair.b); + break; + case VOUT_CONTROL_CROP_RATIO: + ThreadExecuteCropRatio(vout, cmd.u.pair.a, cmd.u.pair.b); + break; + case VOUT_CONTROL_CROP_WINDOW: + ThreadExecuteCropWindow(vout, 0, 0, + cmd.u.window.x, cmd.u.window.y, + cmd.u.window.width, cmd.u.window.height); + break; + case VOUT_CONTROL_CROP_BORDER: + ThreadExecuteCropBorder(vout, + cmd.u.border.left, cmd.u.border.top, + cmd.u.border.right, cmd.u.border.bottom); + break; default: break; } diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h index 6367727493..f8baf52114 100644 --- a/src/video_output/vout_internal.h +++ b/src/video_output/vout_internal.h @@ -49,9 +49,7 @@ struct vout_thread_sys_t config_chain_t *p_cfg; /* */ - video_format_t fmt_render; /* render format (from the decoder) */ - video_format_t fmt_in; /* input (modified render) format */ - video_format_t fmt_out; /* output format (for the video output) */ + video_format_t original; /* Original format ie coming from the decoder */ /* Thread & synchronization */ vlc_thread_t thread; @@ -129,27 +127,17 @@ struct vout_thread_sys_t vout_chrono_t render; /**< picture render time estimator */ vlc_mutex_t change_lock; /**< thread change lock */ - - uint16_t i_changes; /**< changes made to the thread. - \see \ref vout_changes */ }; -/** \defgroup vout_changes Flags for changes - * These flags are set in the vout_thread_t::i_changes field when another - * thread changed a variable - * @{ - */ -/** cropping parameters changed */ -#define VOUT_CROP_CHANGE 0x1000 -/** aspect ratio changed */ -#define VOUT_ASPECT_CHANGE 0x2000 -/**@}*/ - /* TODO to move them to vlc_vout.h */ void vout_ControlChangeFullscreen(vout_thread_t *, bool fullscreen); void vout_ControlChangeOnTop(vout_thread_t *, bool is_on_top); void vout_ControlChangeDisplayFilled(vout_thread_t *, bool is_filled); void vout_ControlChangeZoom(vout_thread_t *, int num, int den); +void vout_ControlChangeSampleAspectRatio(vout_thread_t *, unsigned num, unsigned den); +void vout_ControlChangeCropRatio(vout_thread_t *, unsigned num, unsigned den); +void vout_ControlChangeCropWindow(vout_thread_t *, int x, int y, int width, int height); +void vout_ControlChangeCropBorder(vout_thread_t *, int left, int top, int right, int bottom); /* */ void vout_IntfInit( vout_thread_t * ); diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c index a06762ac72..c0fca4ed71 100644 --- a/src/video_output/vout_intf.c +++ b/src/video_output/vout_intf.c @@ -57,6 +57,8 @@ static int ZoomCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); static int CropCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); +static int CropBorderCallback( vlc_object_t *, char const *, + vlc_value_t, vlc_value_t, void * ); static int AspectCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); static int ScalingCallback( vlc_object_t *, char const *, @@ -212,10 +214,10 @@ void vout_IntfInit( vout_thread_t *p_vout ) var_Create( p_vout, "crop-right", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND ); var_Create( p_vout, "crop-bottom", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND ); - var_AddCallback( p_vout, "crop-left", CropCallback, NULL ); - var_AddCallback( p_vout, "crop-top", CropCallback, NULL ); - var_AddCallback( p_vout, "crop-right", CropCallback, NULL ); - var_AddCallback( p_vout, "crop-bottom", CropCallback, NULL ); + var_AddCallback( p_vout, "crop-left", CropBorderCallback, NULL ); + var_AddCallback( p_vout, "crop-top", CropBorderCallback, NULL ); + var_AddCallback( p_vout, "crop-right", CropBorderCallback, NULL ); + var_AddCallback( p_vout, "crop-bottom", CropBorderCallback, NULL ); /* Crop object var */ var_Create( p_vout, "crop", VLC_VAR_STRING | VLC_VAR_ISCOMMAND | @@ -627,224 +629,59 @@ static int ZoomCallback( vlc_object_t *p_this, char const *psz_cmd, return var_SetFloat( p_this, "scale", newval.f_float ); } -static int CropCallback( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) +static int CropCallback( vlc_object_t *object, char const *cmd, + vlc_value_t oldval, vlc_value_t newval, void *data ) { - vout_thread_t *p_vout = (vout_thread_t *)p_this; - int64_t i_aspect_num, i_aspect_den; - unsigned int i_width, i_height; - - (void)oldval; (void)p_data; - - /* Restore defaults */ - p_vout->p->fmt_in.i_x_offset = p_vout->p->fmt_render.i_x_offset; - p_vout->p->fmt_in.i_visible_width = p_vout->p->fmt_render.i_visible_width; - p_vout->p->fmt_in.i_y_offset = p_vout->p->fmt_render.i_y_offset; - p_vout->p->fmt_in.i_visible_height = p_vout->p->fmt_render.i_visible_height; - - if( !strcmp( psz_cmd, "crop" ) ) - { - char *psz_end = NULL, *psz_parser = strchr( newval.psz_string, ':' ); - if( psz_parser ) - { - /* We're using the 3:4 syntax */ - i_aspect_num = strtol( newval.psz_string, &psz_end, 10 ); - if( psz_end == newval.psz_string || !i_aspect_num ) goto crop_end; - - i_aspect_den = strtol( ++psz_parser, &psz_end, 10 ); - if( psz_end == psz_parser || !i_aspect_den ) goto crop_end; - - i_width = p_vout->p->fmt_in.i_sar_den*p_vout->p->fmt_render.i_visible_height * - i_aspect_num / i_aspect_den / p_vout->p->fmt_in.i_sar_num; - i_height = p_vout->p->fmt_render.i_visible_width*p_vout->p->fmt_in.i_sar_num * - i_aspect_den / i_aspect_num / p_vout->p->fmt_in.i_sar_den; - - if( i_width < p_vout->p->fmt_render.i_visible_width ) - { - p_vout->p->fmt_in.i_x_offset = p_vout->p->fmt_render.i_x_offset + - (p_vout->p->fmt_render.i_visible_width - i_width) / 2; - p_vout->p->fmt_in.i_visible_width = i_width; - } - else - { - p_vout->p->fmt_in.i_y_offset = p_vout->p->fmt_render.i_y_offset + - (p_vout->p->fmt_render.i_visible_height - i_height) / 2; - p_vout->p->fmt_in.i_visible_height = i_height; - } - } - else - { - psz_parser = strchr( newval.psz_string, 'x' ); - if( psz_parser ) - { - /* Maybe we're using the x++ syntax */ - unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left; - - i_crop_width = strtol( newval.psz_string, &psz_end, 10 ); - if( psz_end != psz_parser ) goto crop_end; - - psz_parser = strchr( ++psz_end, '+' ); - i_crop_height = strtol( psz_end, &psz_end, 10 ); - if( psz_end != psz_parser ) goto crop_end; - - psz_parser = strchr( ++psz_end, '+' ); - i_crop_left = strtol( psz_end, &psz_end, 10 ); - if( psz_end != psz_parser ) goto crop_end; - - psz_end++; - i_crop_top = strtol( psz_end, &psz_end, 10 ); - if( *psz_end != '\0' ) goto crop_end; - - if( i_crop_top + i_crop_height >= p_vout->p->fmt_render.i_visible_height || - i_crop_left + i_crop_width >= p_vout->p->fmt_render.i_visible_width ) - { - msg_Err( p_vout, "Unable to crop over picture boundaries"); - return VLC_EGENERIC; - } - - i_width = i_crop_width; - p_vout->p->fmt_in.i_visible_width = i_width; - - i_height = i_crop_height; - p_vout->p->fmt_in.i_visible_height = i_height; - - p_vout->p->fmt_in.i_x_offset = i_crop_left; - p_vout->p->fmt_in.i_y_offset = i_crop_top; - } - else - { - /* Maybe we're using the +++ syntax */ - unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right; - - psz_parser = strchr( newval.psz_string, '+' ); - i_crop_left = strtol( newval.psz_string, &psz_end, 10 ); - if( psz_end != psz_parser ) goto crop_end; - - psz_parser = strchr( ++psz_end, '+' ); - i_crop_top = strtol( psz_end, &psz_end, 10 ); - if( psz_end != psz_parser ) goto crop_end; - - psz_parser = strchr( ++psz_end, '+' ); - i_crop_right = strtol( psz_end, &psz_end, 10 ); - if( psz_end != psz_parser ) goto crop_end; - - psz_end++; - i_crop_bottom = strtol( psz_end, &psz_end, 10 ); - if( *psz_end != '\0' ) goto crop_end; - - if( i_crop_top + i_crop_bottom >= p_vout->p->fmt_render.i_visible_height || - i_crop_right + i_crop_left >= p_vout->p->fmt_render.i_visible_width ) - { - msg_Err( p_vout, "Unable to crop over picture boundaries" ); - return VLC_EGENERIC; - } - - i_width = p_vout->p->fmt_render.i_visible_width - - i_crop_left - i_crop_right; - p_vout->p->fmt_in.i_visible_width = i_width; - - i_height = p_vout->p->fmt_render.i_visible_height - - i_crop_top - i_crop_bottom; - p_vout->p->fmt_in.i_visible_height = i_height; - - p_vout->p->fmt_in.i_x_offset = i_crop_left; - p_vout->p->fmt_in.i_y_offset = i_crop_top; - } - } + vout_thread_t *vout = (vout_thread_t *)object; + VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data); + unsigned num, den; + unsigned y, x; + unsigned width, height; + unsigned left, top, right, bottom; + + if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2) { + vout_ControlChangeCropRatio(vout, num, den); + } else if (sscanf(newval.psz_string, "%ux%u+%u+%u", + &width, &height, &x, &y) == 4) { + vout_ControlChangeCropWindow(vout, x, y, width, height); + } else if (sscanf(newval.psz_string, "%u+%u+%u+%u", + &left, &top, &right, &bottom) == 4) { + vout_ControlChangeCropBorder(vout, left, top, right, bottom); + } else if (*newval.psz_string == '\0') { + vout_ControlChangeCropRatio(vout, 0, 0); + } else { + msg_Err(object, "Unknown crop format (%s)", newval.psz_string); } - else if( !strcmp( psz_cmd, "crop-top" ) - || !strcmp( psz_cmd, "crop-left" ) - || !strcmp( psz_cmd, "crop-bottom" ) - || !strcmp( psz_cmd, "crop-right" ) ) - { - unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right; - - i_crop_top = var_GetInteger( p_vout, "crop-top" ); - i_crop_left = var_GetInteger( p_vout, "crop-left" ); - i_crop_right = var_GetInteger( p_vout, "crop-right" ); - i_crop_bottom = var_GetInteger( p_vout, "crop-bottom" ); - - if( i_crop_top + i_crop_bottom >= p_vout->p->fmt_render.i_visible_height || - i_crop_right + i_crop_left >= p_vout->p->fmt_render.i_visible_width ) - { - msg_Err( p_vout, "Unable to crop over picture boundaries" ); - return VLC_EGENERIC; - } - - i_width = p_vout->p->fmt_render.i_visible_width - - i_crop_left - i_crop_right; - p_vout->p->fmt_in.i_visible_width = i_width; - - i_height = p_vout->p->fmt_render.i_visible_height - - i_crop_top - i_crop_bottom; - p_vout->p->fmt_in.i_visible_height = i_height; - - p_vout->p->fmt_in.i_x_offset = i_crop_left; - p_vout->p->fmt_in.i_y_offset = i_crop_top; - } - - crop_end: - p_vout->p->i_changes |= VOUT_CROP_CHANGE; - - msg_Dbg( p_vout, "cropping picture %ix%i to %i,%i,%ix%i", - p_vout->p->fmt_in.i_width, p_vout->p->fmt_in.i_height, - p_vout->p->fmt_in.i_x_offset, p_vout->p->fmt_in.i_y_offset, - p_vout->p->fmt_in.i_visible_width, - p_vout->p->fmt_in.i_visible_height ); - - var_TriggerCallback( p_vout, "crop-update" ); - return VLC_SUCCESS; } -static int AspectCallback( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) +static int CropBorderCallback(vlc_object_t *object, char const *cmd, + vlc_value_t oldval, vlc_value_t newval, void *data) { - vout_thread_t *p_vout = (vout_thread_t *)p_this; - unsigned int i_aspect_num, i_aspect_den, i_sar_num, i_sar_den; - vlc_value_t val; - - char *psz_end, *psz_parser = strchr( newval.psz_string, ':' ); - (void)psz_cmd; (void)oldval; (void)p_data; - - /* Restore defaults */ - p_vout->p->fmt_in.i_sar_num = p_vout->p->fmt_render.i_sar_num; - p_vout->p->fmt_in.i_sar_den = p_vout->p->fmt_render.i_sar_den; - - if( !psz_parser ) goto aspect_end; - - i_aspect_num = strtol( newval.psz_string, &psz_end, 10 ); - if( psz_end == newval.psz_string || !i_aspect_num ) goto aspect_end; - - i_aspect_den = strtol( ++psz_parser, &psz_end, 10 ); - if( psz_end == psz_parser || !i_aspect_den ) goto aspect_end; - - i_sar_num = i_aspect_num * p_vout->p->fmt_render.i_visible_height; - i_sar_den = i_aspect_den * p_vout->p->fmt_render.i_visible_width; - vlc_ureduce( &i_sar_num, &i_sar_den, i_sar_num, i_sar_den, 0 ); - p_vout->p->fmt_in.i_sar_num = i_sar_num; - p_vout->p->fmt_in.i_sar_den = i_sar_den; - - aspect_end: - if( p_vout->p->i_par_num && p_vout->p->i_par_den ) - { - p_vout->p->fmt_in.i_sar_num *= p_vout->p->i_par_den; - p_vout->p->fmt_in.i_sar_den *= p_vout->p->i_par_num; - } - - p_vout->p->i_changes |= VOUT_ASPECT_CHANGE; - - msg_Dbg( p_vout, "new aspect-ratio %i:%i, sample aspect-ratio %i:%i", - p_vout->p->fmt_in.i_sar_num * p_vout->p->fmt_in.i_width, - p_vout->p->fmt_in.i_sar_den * p_vout->p->fmt_in.i_height, - p_vout->p->fmt_in.i_sar_num, p_vout->p->fmt_in.i_sar_den ); - - if( var_Get( p_vout, "crop", &val ) ) - return VLC_EGENERIC; + vout_thread_t *vout = (vout_thread_t *)object; + VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data); VLC_UNUSED(newval); + + vout_ControlChangeCropBorder(vout, + var_GetInteger(object, "crop-left"), + var_GetInteger(object, "crop-top"), + var_GetInteger(object, "crop-right"), + var_GetInteger(object, "crop-bottom")); + return VLC_SUCCESS; +} - int i_ret = CropCallback( p_this, "crop", val, val, 0 ); - free( val.psz_string ); - return i_ret; +static int AspectCallback( vlc_object_t *object, char const *cmd, + vlc_value_t oldval, vlc_value_t newval, void *data ) +{ + vout_thread_t *vout = (vout_thread_t *)object; + VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data); + unsigned num, den; + + if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2 && + (num > 0) == (den > 0)) + vout_ControlChangeSampleAspectRatio(vout, num, den); + else if (*newval.psz_string == '\0') + vout_ControlChangeSampleAspectRatio(vout, 0, 0); + return VLC_SUCCESS; } static int ScalingCallback( vlc_object_t *p_this, char const *psz_cmd, diff --git a/src/video_output/vout_wrapper.c b/src/video_output/vout_wrapper.c index eebe517b10..5130e9dc73 100644 --- a/src/video_output/vout_wrapper.c +++ b/src/video_output/vout_wrapper.c @@ -66,7 +66,7 @@ int vout_OpenWrapper(vout_thread_t *vout, const char *name) sys->display.title = var_CreateGetNonEmptyString(vout, "video-title"); /* */ - video_format_t source = vout->p->fmt_render; + video_format_t source = vout->p->original; source.i_visible_width = source.i_width; source.i_visible_height = source.i_height; source.i_x_offset = 0; @@ -131,37 +131,8 @@ int vout_InitWrapper(vout_thread_t *vout) { vout_thread_sys_t *sys = vout->p; vout_display_t *vd = sys->display.vd; - - /* */ video_format_t source = vd->source; - vout->p->fmt_out.i_chroma = source.i_chroma; - vout->p->fmt_out.i_width = - vout->p->fmt_out.i_visible_width = source.i_width; - vout->p->fmt_out.i_height = - vout->p->fmt_out.i_visible_height = source.i_height; - if (source.i_sar_num > 0 && source.i_sar_den > 0) { - vlc_ureduce(&vout->p->fmt_out.i_sar_num, &vout->p->fmt_out.i_sar_den, - source.i_sar_num, source.i_sar_den, 0); - } else { - vout->p->fmt_out.i_sar_num = 1; - vout->p->fmt_out.i_sar_den = 1; - } - vout->p->fmt_out.i_sar_num = source.i_sar_num; - vout->p->fmt_out.i_sar_den = source.i_sar_den; - vout->p->fmt_out.i_x_offset = 0; - vout->p->fmt_out.i_y_offset = 0; - vout->p->fmt_out.i_rmask = source.i_rmask; - vout->p->fmt_out.i_gmask = source.i_gmask; - vout->p->fmt_out.i_bmask = source.i_bmask; - video_format_FixRgb(&vout->p->fmt_out); - - if (vout->p->fmt_in.i_visible_width != source.i_visible_width || - vout->p->fmt_in.i_visible_height != source.i_visible_height || - vout->p->fmt_in.i_x_offset != source.i_x_offset || - vout->p->fmt_in.i_y_offset != source.i_y_offset ) - sys->i_changes |= VOUT_CROP_CHANGE; - /* XXX For non dr case, the current vout implementation force us to * create at most 1 direct picture (otherwise the buffers will be kept * referenced even through the Init/End. @@ -213,44 +184,6 @@ int vout_ManageWrapper(vout_thread_t *vout) vout_thread_sys_t *sys = vout->p; vout_display_t *vd = sys->display.vd; - while (sys->i_changes & (VOUT_ASPECT_CHANGE | - VOUT_CROP_CHANGE)) { - /* */ - if (sys->i_changes & VOUT_ASPECT_CHANGE) { - vout->p->fmt_out.i_sar_num = vout->p->fmt_in.i_sar_num; - vout->p->fmt_out.i_sar_den = vout->p->fmt_in.i_sar_den; - - vout_SetDisplayAspect(vd, vout->p->fmt_in.i_sar_num, vout->p->fmt_in.i_sar_den); - - sys->i_changes &= ~VOUT_ASPECT_CHANGE; - } - if (sys->i_changes & VOUT_CROP_CHANGE) { - const video_format_t crop = vout->p->fmt_in; - const video_format_t org = vout->p->fmt_render; - /* FIXME because of rounding errors, the reconstructed ratio is wrong */ - unsigned num = 0; - unsigned den = 0; - if (crop.i_x_offset == org.i_x_offset && - crop.i_visible_width == org.i_visible_width && - crop.i_y_offset == org.i_y_offset + (org.i_visible_height - crop.i_visible_height)/2) { - vlc_ureduce(&num, &den, - crop.i_visible_width * crop.i_sar_num, - crop.i_visible_height * crop.i_sar_den, 0); - } else if (crop.i_y_offset == org.i_y_offset && - crop.i_visible_height == org.i_visible_height && - crop.i_x_offset == org.i_x_offset + (org.i_visible_width - crop.i_visible_width)/2) { - vlc_ureduce(&num, &den, - crop.i_visible_width * crop.i_sar_num, - crop.i_visible_height * crop.i_sar_den, 0); - } - vout_SetDisplayCrop(vd, num, den, - crop.i_x_offset, crop.i_y_offset, - crop.i_visible_width, crop.i_visible_height); - sys->i_changes &= ~VOUT_CROP_CHANGE; - } - - } - bool reset_display_pool = sys->display.use_dr && vout_AreDisplayPicturesInvalid(vd); vout_ManageDisplay(vd, !sys->display.use_dr || reset_display_pool); -- 2.39.2