X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fdisplay.c;h=0b0933f128a21b8c1caa6e3ec4cabf7a717791be;hb=a42fe7a14d00f05748bb751dc4cd8956e29c3335;hp=af73be86988c14da809cd7d64e8dab2efc7b0cde;hpb=7d5dbadace37c60324afb93d0c572776da0dc658;p=vlc diff --git a/src/video_output/display.c b/src/video_output/display.c index af73be8698..0b0933f128 100644 --- a/src/video_output/display.c +++ b/src/video_output/display.c @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -99,7 +100,7 @@ static vout_display_t *vout_display_New(vlc_object_t *obj, vout_display_owner_t *owner) { /* */ - vout_display_t *vd = vlc_object_create(obj, sizeof(*vd)); + vout_display_t *vd = vlc_custom_create(obj, sizeof(*vd), "vout display" ); /* */ video_format_Copy(&vd->source, fmt); @@ -114,6 +115,7 @@ static vout_display_t *vout_display_New(vlc_object_t *obj, vd->info.has_hide_mouse = false; vd->info.has_pictures_invalid = false; vd->info.has_event_thread = false; + vd->info.subpicture_chromas = NULL; vd->cfg = cfg; vd->pool = NULL; @@ -125,8 +127,6 @@ static vout_display_t *vout_display_New(vlc_object_t *obj, vd->owner = *owner; - vlc_object_attach(vd, obj); - if (load_module) { vd->module = module_need(vd, "vout display", module, module && *module != '\0'); if (!vd->module) { @@ -164,6 +164,7 @@ static int vout_display_Control(vout_display_t *vd, int query, ...) return result; } + static void vout_display_Manage(vout_display_t *vd) { if (vd->manage) @@ -286,8 +287,8 @@ struct vout_display_owner_sys_t { } sar_initial; /* */ - int width_saved; - int height_saved; + unsigned width_saved; + unsigned height_saved; struct { unsigned num; @@ -315,10 +316,10 @@ struct vout_display_owner_sys_t { bool ch_crop; struct { - unsigned x; - unsigned y; - unsigned width; - unsigned height; + int left; + int top; + int right; + int bottom; unsigned num; unsigned den; } crop; @@ -421,11 +422,7 @@ static void VoutDisplayCreateRender(vout_display_t *vd) break; } if (!filter) - { - msg_Err(vd, "VoutDisplayCreateRender FAILED"); - /* TODO */ - assert(0); - } + msg_Err(vd, "Failed to adapt decoder format to display"); } static void VoutDisplayDestroyRender(vout_display_t *vd) @@ -466,15 +463,12 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) case VOUT_DISPLAY_EVENT_MOUSE_MOVED: { const int x = (int)va_arg(args, int); const int y = (int)va_arg(args, int); - if (x != osys->mouse.state.i_x || y != osys->mouse.state.i_y) { - //msg_Dbg(vd, "VoutDisplayEvent 'mouse' @%d,%d", x, y); - m.i_x = x; - m.i_y = y; - m.b_double_click = false; - } else { - is_ignored = true; - } + //msg_Dbg(vd, "VoutDisplayEvent 'mouse' @%d,%d", x, y); + + m.i_x = x; + m.i_y = y; + m.b_double_click = false; break; } case VOUT_DISPLAY_EVENT_MOUSE_PRESSED: @@ -544,6 +538,7 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) vlc_mutex_unlock(&osys->lock); } +VLC_NORETURN static void *VoutDisplayEventKeyDispatch(void *data) { vout_display_owner_sys_t *osys = data; @@ -688,7 +683,7 @@ static vout_window_t *VoutDisplayNewWindow(vout_display_t *vd, const vout_window if (!var_InheritBool(osys->vout, "embedded-video")) cfg_override.is_standalone = true; - return vout_window_New(VLC_OBJECT(osys->vout), NULL, &cfg_override); + return vout_window_New(VLC_OBJECT(osys->vout), "$window", &cfg_override); } #endif return vout_NewDisplayWindow(osys->vout, vd, cfg); @@ -740,8 +735,7 @@ static void VoutDisplayFitWindow(vout_display_t *vd, bool default_size) vlc_mutex_unlock(&osys->lock); } -static void VoutDisplayCropRatio(unsigned *x, unsigned *y, - unsigned *width, unsigned *height, +static void VoutDisplayCropRatio(int *left, int *top, int *right, int *bottom, const video_format_t *source, unsigned num, unsigned den) { @@ -749,18 +743,16 @@ static void VoutDisplayCropRatio(unsigned *x, unsigned *y, 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; + *left = (source->i_visible_width - scaled_width) / 2; + *top = 0; + *right = *left + scaled_width; + *bottom = *top + source->i_visible_height; } else { - *x = 0; - *y = (source->i_visible_height - scaled_height) / 2; - *width = source->i_visible_width; - *height = scaled_height; + *left = 0; + *top = (source->i_visible_height - scaled_height) / 2; + *right = *left + source->i_visible_width; + *bottom = *top + scaled_height; } - *x += source->i_x_offset; - *y += source->i_y_offset; } void vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures) @@ -786,7 +778,7 @@ void vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures) if (hide_mouse) { if (!vd->info.has_hide_mouse) { - msg_Dbg(vd, "auto hidding mouse"); + msg_Dbg(vd, "auto hiding mouse"); vout_display_Control(vd, VOUT_DISPLAY_HIDE_MOUSE); } vout_SendEventMouseHidden(osys->vout); @@ -994,28 +986,36 @@ void vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures) video_format_t fmt = osys->source; fmt.i_sar_num = source.i_sar_num; fmt.i_sar_den = source.i_sar_den; - VoutDisplayCropRatio(&osys->crop.x, &osys->crop.y, - &osys->crop.width, &osys->crop.height, + VoutDisplayCropRatio(&osys->crop.left, &osys->crop.top, + &osys->crop.right, &osys->crop.bottom, &fmt, crop_num, crop_den); } - - source.i_x_offset = osys->crop.x; - source.i_y_offset = osys->crop.y; - source.i_visible_width = osys->crop.width; - source.i_visible_height = osys->crop.height; - - /* */ - const bool is_valid = source.i_x_offset < source.i_width && - source.i_y_offset < source.i_height && - source.i_x_offset + source.i_visible_width <= source.i_width && - source.i_y_offset + source.i_visible_height <= source.i_height && - source.i_visible_width > 0 && source.i_visible_height > 0; - - if (!is_valid || vout_display_Control(vd, VOUT_DISPLAY_CHANGE_SOURCE_CROP, &source)) { - if (is_valid) - msg_Err(vd, "Failed to change source crop TODO implement crop at core"); - else - msg_Err(vd, "Invalid crop requested"); + const int right_max = osys->source.i_x_offset + osys->source.i_visible_width; + const int bottom_max = osys->source.i_y_offset + osys->source.i_visible_height; + int left = VLC_CLIP((int)osys->source.i_x_offset + osys->crop.left, + 0, right_max - 1); + int top = VLC_CLIP((int)osys->source.i_y_offset + osys->crop.top, + 0, bottom_max - 1); + int right, bottom; + if (osys->crop.right <= 0) + right = (int)(osys->source.i_x_offset + osys->source.i_visible_width) + osys->crop.right; + else + right = (int)osys->source.i_x_offset + osys->crop.right; + right = VLC_CLIP(right, left + 1, right_max); + if (osys->crop.bottom <= 0) + bottom = (int)(osys->source.i_y_offset + osys->source.i_visible_height) + osys->crop.bottom; + else + bottom = (int)osys->source.i_y_offset + osys->crop.bottom; + bottom = VLC_CLIP(bottom, top + 1, bottom_max); + + source.i_x_offset = left; + source.i_y_offset = top; + source.i_visible_width = right - left; + source.i_visible_height = bottom - top; + video_format_Print(VLC_OBJECT(vd), "SOURCE ", &osys->source); + video_format_Print(VLC_OBJECT(vd), "CROPPED", &source); + if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_SOURCE_CROP, &source)) { + msg_Err(vd, "Failed to change source crop TODO implement crop at core"); source = vd->source; crop_num = osys->crop_saved.num; @@ -1027,22 +1027,21 @@ void vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures) osys->fit_window = 1; } vd->source = source; - osys->crop.x = source.i_x_offset; - osys->crop.y = source.i_y_offset; - osys->crop.width = source.i_visible_width; - osys->crop.height = source.i_visible_height; + osys->crop.left = source.i_x_offset - osys->source.i_x_offset; + osys->crop.top = source.i_y_offset - osys->source.i_y_offset; + /* FIXME for right/bottom we should keep the 'type' border vs window */ + osys->crop.right = (source.i_x_offset + source.i_visible_width) - + (osys->source.i_x_offset + osys->source.i_visible_width); + osys->crop.bottom = (source.i_y_offset + source.i_visible_height) - + (osys->source.i_y_offset + osys->source.i_visible_height); osys->crop.num = crop_num; osys->crop.den = crop_den; osys->ch_crop = false; - /* TODO fix when a ratio is used (complicated). */ - const unsigned left = osys->crop.x - osys->source.i_x_offset; - const unsigned top = osys->crop.y - osys->source.i_y_offset; - const unsigned right = osys->source.i_visible_width - (osys->crop.width + osys->crop.x); - const unsigned bottom = osys->source.i_visible_height - (osys->crop.height + osys->crop.y); vout_SendEventSourceCrop(osys->vout, osys->crop.num, osys->crop.den, - left, top, right, bottom); + osys->crop.left, osys->crop.top, + -osys->crop.right, -osys->crop.bottom); } /* */ @@ -1081,9 +1080,43 @@ picture_t *vout_FilterDisplay(vout_display_t *vd, picture_t *picture) vout_display_owner_sys_t *osys = vd->owner.sys; assert(osys->filters); + if (filter_chain_GetLength(osys->filters) <= 0) { + picture_Release(picture); + return NULL; + } return filter_chain_VideoFilter(osys->filters, picture); } +void vout_UpdateDisplaySourceProperties(vout_display_t *vd, const video_format_t *source) +{ + vout_display_owner_sys_t *osys = vd->owner.sys; + + if (source->i_sar_num * osys->source.i_sar_den != + source->i_sar_den * osys->source.i_sar_num) { + + osys->source.i_sar_num = source->i_sar_num; + osys->source.i_sar_den = source->i_sar_den; + vlc_ureduce(&osys->source.i_sar_num, &osys->source.i_sar_den, + osys->source.i_sar_num, osys->source.i_sar_den, 0); + + /* FIXME it will override any AR that the user would have forced */ + osys->ch_sar = true; + osys->sar.num = osys->source.i_sar_num; + osys->sar.den = osys->source.i_sar_den; + } + if (source->i_x_offset != osys->source.i_x_offset || + source->i_y_offset != osys->source.i_y_offset || + source->i_visible_width != osys->source.i_visible_width || + source->i_visible_height != osys->source.i_visible_height) { + + video_format_CopyCrop(&osys->source, source); + + /* Force the vout to reapply the current user crop settings over the new decoder + * crop settings. */ + osys->ch_crop = true; + } +} + void vout_SetDisplayFullscreen(vout_display_t *vd, bool is_fullscreen) { vout_display_owner_sys_t *osys = vd->owner.sys; @@ -1130,10 +1163,20 @@ void vout_SetWindowState(vout_display_t *vd, unsigned state) vlc_mutex_unlock(&osys->lock); } -void vout_SetDisplayAspect(vout_display_t *vd, unsigned sar_num, unsigned sar_den) +void vout_SetDisplayAspect(vout_display_t *vd, unsigned dar_num, unsigned dar_den) { vout_display_owner_sys_t *osys = vd->owner.sys; + unsigned sar_num, sar_den; + if (dar_num > 0 && dar_den > 0) { + sar_num = dar_num * osys->source.i_visible_height; + sar_den = dar_den * osys->source.i_visible_width; + vlc_ureduce(&sar_num, &sar_den, sar_num, sar_den, 0); + } else { + sar_num = 0; + sar_den = 0; + } + if (osys->sar.num != sar_num || osys->sar.den != sar_den) { osys->ch_sar = true; osys->sar.num = sar_num; @@ -1142,28 +1185,29 @@ void vout_SetDisplayAspect(vout_display_t *vd, unsigned sar_num, unsigned sar_de } void vout_SetDisplayCrop(vout_display_t *vd, unsigned crop_num, unsigned crop_den, - unsigned x, unsigned y, unsigned width, unsigned height) + unsigned left, unsigned top, int right, int bottom) { vout_display_owner_sys_t *osys = vd->owner.sys; - if (osys->crop.x != x || osys->crop.y != y || - osys->crop.width != width || osys->crop.height != height || + if (osys->crop.left != (int)left || osys->crop.top != (int)top || + osys->crop.right != right || osys->crop.bottom != bottom || (crop_num > 0 && crop_den > 0 && (crop_num != osys->crop.num || crop_den != osys->crop.den))) { - osys->crop.x = x; - osys->crop.y = y; - osys->crop.width = width; - osys->crop.height = height; + osys->crop.left = left; + osys->crop.top = top; + osys->crop.right = right; + osys->crop.bottom = bottom; osys->crop.num = crop_num; osys->crop.den = crop_den; osys->ch_crop = true; } } -vout_opengl_t *vout_GetDisplayOpengl(vout_display_t *vd) + +struct vlc_gl_t *vout_GetDisplayOpengl(vout_display_t *vd) { - vout_opengl_t *gl; + struct vlc_gl_t *gl; if (vout_display_Control(vd, VOUT_DISPLAY_GET_OPENGL, &gl)) return NULL; return gl; @@ -1221,24 +1265,17 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, osys->event.fifo = NULL; osys->source = *source_org; - - video_format_t source = *source_org; - - source.i_x_offset = - osys->crop.x = 0; - source.i_y_offset = - osys->crop.y = 0; - source.i_visible_width = - osys->crop.width = source.i_width; - source.i_visible_height = - osys->crop.height = source.i_height; + osys->crop.left = 0; + osys->crop.top = 0; + osys->crop.right = 0; + osys->crop.bottom = 0; osys->crop_saved.num = 0; osys->crop_saved.den = 0; osys->crop.num = 0; osys->crop.den = 0; - osys->sar.num = osys->sar_initial.num ? osys->sar_initial.num : source.i_sar_num; - osys->sar.den = osys->sar_initial.den ? osys->sar_initial.den : source.i_sar_den; + osys->sar.num = osys->sar_initial.num ? osys->sar_initial.num : source_org->i_sar_num; + osys->sar.den = osys->sar_initial.den ? osys->sar_initial.den : source_org->i_sar_den; #ifdef ALLOW_DUMMY_VOUT vlc_mouse_Init(&osys->vout_mouse); #endif @@ -1254,6 +1291,13 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, owner.sys = osys; /* */ + video_format_t source = *source_org; + + source.i_x_offset = 0; + source.i_y_offset = 0; + source.i_visible_width = source.i_width; + source.i_visible_height = source.i_height; + vout_display_t *p_display = vout_display_New(VLC_OBJECT(vout), module, !is_wrapper, &source, cfg, &owner); @@ -1265,15 +1309,15 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, VoutDisplayCreateRender(p_display); /* Setup delayed request */ - if (osys->sar.num != source_org->i_sar_num || - osys->sar.den != source_org->i_sar_den) + if (osys->sar.num != source.i_sar_num || + osys->sar.den != source.i_sar_den) osys->ch_sar = true; if (osys->wm_state != osys->wm_state_initial) osys->ch_wm_state = true; - if (osys->crop.x != source_org->i_x_offset || - osys->crop.y != source_org->i_y_offset || - osys->crop.width != source_org->i_visible_width || - osys->crop.height != source_org->i_visible_height) + if (source.i_x_offset != source_org->i_x_offset || + source.i_y_offset != source_org->i_y_offset || + source.i_visible_width != source_org->i_visible_width || + source.i_visible_height != source_org->i_visible_height) osys->ch_crop = true; return p_display; @@ -1386,11 +1430,14 @@ static picture_pool_t *SplitterPool(vout_display_t *vd, unsigned count) sys->pool = picture_pool_NewFromFormat(&vd->fmt, count); return sys->pool; } -static void SplitterPrepare(vout_display_t *vd, picture_t *picture) +static void SplitterPrepare(vout_display_t *vd, + picture_t *picture, + subpicture_t *subpicture) { vout_display_sys_t *sys = vd->sys; picture_Hold(picture); + assert(!subpicture); if (video_splitter_Filter(sys->splitter, sys->picture, picture)) { for (int i = 0; i < sys->count; i++) @@ -1403,21 +1450,25 @@ static void SplitterPrepare(vout_display_t *vd, picture_t *picture) if (vout_IsDisplayFiltered(sys->display[i])) sys->picture[i] = vout_FilterDisplay(sys->display[i], sys->picture[i]); if (sys->picture[i]) - vout_display_Prepare(sys->display[i], sys->picture[i]); + vout_display_Prepare(sys->display[i], sys->picture[i], NULL); } } -static void SplitterDisplay(vout_display_t *vd, picture_t *picture) +static void SplitterDisplay(vout_display_t *vd, + picture_t *picture, + subpicture_t *subpicture) { vout_display_sys_t *sys = vd->sys; + assert(!subpicture); for (int i = 0; i < sys->count; i++) { if (sys->picture[i]) - vout_display_Display(sys->display[i], sys->picture[i]); + vout_display_Display(sys->display[i], sys->picture[i], NULL); } picture_Release(picture); } static int SplitterControl(vout_display_t *vd, int query, va_list args) { + (void)vd; (void)query; (void)args; return VLC_EGENERIC; } static void SplitterManage(vout_display_t *vd) @@ -1563,33 +1614,26 @@ vout_display_t *vout_NewSplitter(vout_thread_t *vout, #include "vout_internal.h" void vout_SendDisplayEventMouse(vout_thread_t *vout, const vlc_mouse_t *m) { - vlc_mouse_t tmp; + vlc_mouse_t tmp1, tmp2; - /* 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->display.vd->source)) + /* The check on spu is needed as long as ALLOW_DUMMY_VOUT is defined */ + if (vout->p->spu && spu_ProcessMouse( vout->p->spu, m, &vout->p->display.vd->source)) return; - vlc_mutex_lock( &vout->p->vfilter_lock ); - if (vout->p->vfilter_chain) { - if (!filter_chain_MouseFilter(vout->p->vfilter_chain, &tmp, m)) - m = &tmp; + vlc_mutex_lock( &vout->p->filter.lock ); + if (vout->p->filter.chain_static && vout->p->filter.chain_interactive) { + if (!filter_chain_MouseFilter(vout->p->filter.chain_interactive, &tmp1, m)) + m = &tmp1; + if (!filter_chain_MouseFilter(vout->p->filter.chain_static, &tmp2, m)) + m = &tmp2; } - vlc_mutex_unlock( &vout->p->vfilter_lock ); + vlc_mutex_unlock( &vout->p->filter.lock ); if (vlc_mouse_HasMoved(&vout->p->mouse, m)) { vout_SendEventMouseMoved(vout, m->i_x, m->i_y); } if (vlc_mouse_HasButton(&vout->p->mouse, m)) { - static const int buttons[] = { - MOUSE_BUTTON_LEFT, - MOUSE_BUTTON_CENTER, - MOUSE_BUTTON_RIGHT, - MOUSE_BUTTON_WHEEL_UP, - MOUSE_BUTTON_WHEEL_DOWN, - -1 - }; - for (int i = 0; buttons[i] >= 0; i++) { - const int button = buttons[i]; + for (unsigned button = 0; button < MOUSE_BUTTON_MAX; button++) { if (vlc_mouse_HasPressed(&vout->p->mouse, m, button)) vout_SendEventMousePressed(vout, button); else if (vlc_mouse_HasReleased(&vout->p->mouse, m, button)) @@ -1607,14 +1651,15 @@ static void DummyVoutSendDisplayEventMouse(vout_thread_t *vout, vlc_mouse_t *fal if (!vout->p) { p.mouse = *fallback; - vlc_mutex_init(&p.vfilter_lock); - p.vfilter_chain = NULL; - p.p_spu = NULL; + vlc_mutex_init(&p.filter.lock); + p.filter.chain_static = NULL; + p.filter.chain_interactive = NULL; + p.spu = NULL; vout->p = &p; } vout_SendDisplayEventMouse(vout, m); if (vout->p == &p) { - vlc_mutex_destroy(&p.vfilter_lock); + vlc_mutex_destroy(&p.filter.lock); *fallback = p.mouse; vout->p = NULL; }