X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fdisplay.c;h=da5f4f9516b7eb0e789e6924de9c571f09915519;hb=33f12f759f925d206fa4ec2001db57d1133c11a6;hp=4bfe485c105d1c0722f88a01561c8230094caaea;hpb=fbedc7c617208aa2bdb5c02ddfc0f9d2d59194a8;p=vlc diff --git a/src/video_output/display.c b/src/video_output/display.c index 4bfe485c10..da5f4f9516 100644 --- a/src/video_output/display.c +++ b/src/video_output/display.c @@ -47,14 +47,14 @@ static void SplitterClose(vout_display_t *vd); *****************************************************************************/ static picture_t *VideoBufferNew(filter_t *filter) { + vout_display_t *vd = (vout_display_t*)filter->p_owner; const video_format_t *fmt = &filter->fmt_out.video; - picture_t *picture = picture_New(fmt->i_chroma, - fmt->i_width, fmt->i_height, - fmt->i_aspect); - if (!picture) - msg_Err(filter, "Failed to allocate picture"); - return picture; + assert(vd->fmt.i_chroma == fmt->i_chroma && + vd->fmt.i_width == fmt->i_width && + vd->fmt.i_height == fmt->i_height); + + return vout_display_Get(vd); } static void VideoBufferDelete(filter_t *filter, picture_t *picture) { @@ -62,12 +62,11 @@ static void VideoBufferDelete(filter_t *filter, picture_t *picture) picture_Release(picture); } -static int FilterAllocationInit(filter_t *filter, void *data) +static int FilterAllocationInit(filter_t *filter, void *vd) { - VLC_UNUSED(data); - filter->pf_vout_buffer_new = VideoBufferNew; filter->pf_vout_buffer_del = VideoBufferDelete; + filter->p_owner = vd; return VLC_SUCCESS; } @@ -75,6 +74,7 @@ static void FilterAllocationClean(filter_t *filter) { filter->pf_vout_buffer_new = NULL; filter->pf_vout_buffer_del = NULL; + filter->p_owner = NULL; } /***************************************************************************** @@ -161,7 +161,8 @@ static int vout_display_Control(vout_display_t *vd, int query, ...) } static void vout_display_Manage(vout_display_t *vd) { - vd->manage(vd); + if (vd->manage) + vd->manage(vd); } /* */ @@ -275,19 +276,6 @@ struct vout_display_owner_sys_t { bool is_wrapper; /* Is the current display a wrapper */ vout_display_t *wrapper; /* Vout display wrapper */ - /* mouse state */ - struct { - vlc_mouse_t state; - - mtime_t last_pressed; - mtime_t last_moved; - bool is_hidden; - - /* */ - mtime_t double_click_timeout; - mtime_t hide_timeout; - } mouse; - /* */ vout_display_cfg_t cfg; bool is_on_top_initial; @@ -306,15 +294,6 @@ struct vout_display_owner_sys_t { } crop_saved; /* */ - bool reset_pictures; - - bool ch_fullscreen; - bool is_fullscreen; - - bool ch_display_size; - int display_width; - int display_height; - bool ch_display_filled; bool is_display_filled; @@ -346,6 +325,35 @@ struct vout_display_owner_sys_t { /* */ video_format_t source; filter_chain_t *filters; + + /* Lock protecting the variables used by + * VoutDisplayEvent(ie vout_display_SendEvent) */ + vlc_mutex_t lock; + + /* mouse state */ + struct { + vlc_mouse_t state; + + mtime_t last_pressed; + mtime_t last_moved; + bool is_hidden; + bool ch_activity; + + /* */ + mtime_t double_click_timeout; + mtime_t hide_timeout; + } mouse; + + bool reset_pictures; + + bool ch_fullscreen; + bool is_fullscreen; + + bool ch_display_size; + int display_width; + int display_height; + bool display_is_fullscreen; + bool display_is_forced; }; static void VoutDisplayCreateRender(vout_display_t *vd) @@ -379,7 +387,7 @@ static void VoutDisplayCreateRender(vout_display_t *vd) osys->filters = filter_chain_New(vd, "video filter2", false, FilterAllocationInit, - FilterAllocationClean, NULL); + FilterAllocationClean, vd); assert(osys->filters); /* TODO critical */ /* */ @@ -425,6 +433,8 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) { vout_display_owner_sys_t *osys = vd->owner.sys; + vlc_mutex_lock(&osys->lock); + /* */ vlc_mouse_t m = osys->mouse.state; bool is_ignored = false; @@ -445,7 +455,7 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) 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); + //msg_Dbg(vd, "VoutDisplayEvent 'mouse' @%d,%d", x, y); m.i_x = x; m.i_y = y; @@ -486,8 +496,10 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) assert(0); } - if (is_ignored) + if (is_ignored) { + vlc_mutex_unlock(&osys->lock); return; + } /* Emulate double-click if needed */ if (!vd->info.has_double_click && @@ -506,10 +518,13 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) osys->mouse.state = m; /* */ - osys->mouse.is_hidden = false; + osys->mouse.ch_activity = true; if (!vd->info.has_hide_mouse) osys->mouse.last_moved = mdate(); + /* */ + vlc_mutex_unlock(&osys->lock); + /* */ vout_SendEventMouseVisible(osys->vout); vout_SendDisplayEventMouse(osys->vout, &m); @@ -544,22 +559,46 @@ static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args) msg_Dbg(vd, "VoutDisplayEvent 'fullscreen' %d", is_fullscreen); - if (!is_fullscreen == !osys->is_fullscreen) - break; - osys->ch_fullscreen = true; - osys->is_fullscreen = is_fullscreen; + vlc_mutex_lock(&osys->lock); + if (!is_fullscreen != !osys->is_fullscreen) { + osys->ch_fullscreen = true; + osys->is_fullscreen = is_fullscreen; + } + vlc_mutex_unlock(&osys->lock); + break; + } + + case VOUT_DISPLAY_EVENT_ON_TOP: { + const int is_on_top = (int)va_arg(args, int); + + msg_Dbg(vd, "VoutDisplayEvent 'on top' %d", is_on_top); + + vlc_mutex_lock(&osys->lock); + if (!is_on_top != !osys->is_on_top) { + osys->ch_on_top = true; + osys->is_on_top = is_on_top; + } + vlc_mutex_unlock(&osys->lock); break; } case VOUT_DISPLAY_EVENT_DISPLAY_SIZE: { const int width = (int)va_arg(args, int); const int height = (int)va_arg(args, int); - msg_Dbg(vd, "VoutDisplayEvent 'resize' %dx%d", width, height); + const bool is_fullscreen = (bool)va_arg(args, int); + msg_Dbg(vd, "VoutDisplayEvent 'resize' %dx%d %s", + width, height, is_fullscreen ? "fullscreen" : "window"); /* */ - osys->ch_display_size = true; - osys->display_width = width; - osys->display_height = height; + vlc_mutex_lock(&osys->lock); + + osys->ch_display_size = true; + osys->display_width = width; + osys->display_height = height; + osys->display_is_fullscreen = is_fullscreen; + osys->display_is_forced = false; + + vlc_mutex_unlock(&osys->lock); break; } @@ -568,7 +607,10 @@ static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args) /* */ assert(vd->info.has_pictures_invalid); + + vlc_mutex_lock(&osys->lock); osys->reset_pictures = true; + vlc_mutex_unlock(&osys->lock); break; } default: @@ -599,69 +641,102 @@ void vout_ManageDisplay(vout_display_t *vd) /* Handle mouse timeout */ const mtime_t date = mdate(); + bool hide_mouse = false; + + vlc_mutex_lock(&osys->lock); + if (!osys->mouse.is_hidden && osys->mouse.last_moved + osys->mouse.hide_timeout < date) { + osys->mouse.is_hidden = hide_mouse = true; + } else if (osys->mouse.ch_activity) { + osys->mouse.is_hidden = false; + } + osys->mouse.ch_activity = false; + vlc_mutex_unlock(&osys->lock); + + if (hide_mouse) { if (!vd->info.has_hide_mouse) { msg_Dbg(vd, "auto hidding mouse"); vout_display_Control(vd, VOUT_DISPLAY_HIDE_MOUSE); } - osys->mouse.is_hidden = true; - vout_SendEventMouseHidden(osys->vout); } - bool reset_pictures = false; + bool reset_render = false; for (;;) { - if (!osys->ch_fullscreen && - !osys->ch_display_size && - !osys->reset_pictures && + + vlc_mutex_lock(&osys->lock); + + bool ch_fullscreen = osys->ch_fullscreen; + bool is_fullscreen = osys->is_fullscreen; + osys->ch_fullscreen = false; + + bool ch_on_top = osys->ch_on_top; + bool is_on_top = osys->is_on_top; + osys->ch_on_top = false; + + bool ch_display_size = osys->ch_display_size; + int display_width = osys->display_width; + int display_height = osys->display_height; + bool display_is_fullscreen = osys->display_is_fullscreen; + bool display_is_forced = osys->display_is_forced; + osys->ch_display_size = false; + + bool reset_pictures = osys->reset_pictures; + osys->reset_pictures = false; + + vlc_mutex_unlock(&osys->lock); + + if (!ch_fullscreen && + !ch_display_size && + !reset_pictures && !osys->ch_display_filled && !osys->ch_zoom && - !osys->ch_on_top && + !ch_on_top && !osys->ch_sar && !osys->ch_crop) break; /* */ - if (osys->ch_fullscreen) { + if (ch_fullscreen) { vout_display_cfg_t cfg = osys->cfg; - cfg.is_fullscreen = osys->is_fullscreen; + cfg.is_fullscreen = is_fullscreen; cfg.display.width = cfg.is_fullscreen ? 0 : osys->width_saved; cfg.display.height = cfg.is_fullscreen ? 0 : osys->height_saved; if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_FULLSCREEN, &cfg)) { msg_Err(vd, "Failed to set fullscreen"); - osys->is_fullscreen = osys->cfg.is_fullscreen; + is_fullscreen = osys->cfg.is_fullscreen; } - osys->cfg.is_fullscreen = osys->is_fullscreen; - osys->ch_fullscreen = false; + osys->cfg.is_fullscreen = is_fullscreen; /* */ vout_SendEventFullscreen(osys->vout, osys->cfg.is_fullscreen); } /* */ - if (osys->ch_display_size) { + if (ch_display_size) { vout_display_cfg_t cfg = osys->cfg; - cfg.display.width = osys->display_width; - cfg.display.height = osys->display_height; + cfg.display.width = display_width; + cfg.display.height = display_height; - if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_DISPLAY_SIZE, &cfg)) { - msg_Err(vd, "Failed to resize display"); + if (!cfg.is_fullscreen != !display_is_fullscreen || + vout_display_Control(vd, VOUT_DISPLAY_CHANGE_DISPLAY_SIZE, &cfg, display_is_forced)) { + if (!cfg.is_fullscreen == !display_is_fullscreen) + msg_Err(vd, "Failed to resize display"); /* We ignore the resized */ - osys->display_width = osys->cfg.display.width; - osys->display_height = osys->cfg.display.height; + display_width = osys->cfg.display.width; + display_height = osys->cfg.display.height; } - osys->cfg.display.width = osys->display_width; - osys->cfg.display.height = osys->display_height; + osys->cfg.display.width = display_width; + osys->cfg.display.height = display_height; - if (!osys->is_fullscreen) { - osys->width_saved = osys->display_width; - osys->height_saved = osys->display_height; + if (!display_is_fullscreen) { + osys->width_saved = display_width; + osys->height_saved = display_height; } - osys->ch_display_size = false; } /* */ if (osys->ch_display_filled) { @@ -698,9 +773,18 @@ void vout_ManageDisplay(vout_display_t *vd) osys->zoom.num = osys->cfg.zoom.num; osys->zoom.den = osys->cfg.zoom.den; } else if (cfg.is_display_filled) { - osys->ch_display_size = true; - osys->display_width = (int64_t)vd->source.i_width * osys->zoom.num / osys->zoom.den; - osys->display_height = (int64_t)vd->source.i_height * osys->zoom.num / osys->zoom.den; + const int display_width = (int64_t)vd->source.i_width * osys->zoom.num / osys->zoom.den; + const int display_height = (int64_t)vd->source.i_height * osys->zoom.num / osys->zoom.den; + + vlc_mutex_lock(&osys->lock); + + osys->ch_display_size = true; + osys->display_width = display_width; + osys->display_height = display_height; + osys->display_is_fullscreen = osys->cfg.is_fullscreen; + osys->display_is_forced = true; + + vlc_mutex_unlock(&osys->lock); } osys->cfg.zoom.num = osys->zoom.num; @@ -710,16 +794,12 @@ void vout_ManageDisplay(vout_display_t *vd) vout_SendEventZoom(osys->vout, osys->cfg.zoom.num, osys->cfg.zoom.den); } /* */ - if (osys->ch_on_top) { - bool is_on_top = osys->is_on_top; - + if (ch_on_top) { if (vout_display_Control(vd, VOUT_DISPLAY_CHANGE_ON_TOP, is_on_top)) { msg_Err(vd, "Failed to set on top"); is_on_top = osys->is_on_top_initial; } - osys->is_on_top_initial = - osys->is_on_top = is_on_top; - osys->ch_on_top = false; + osys->is_on_top_initial = is_on_top; /* */ vout_SendEventOnTop(osys->vout, osys->is_on_top_initial); @@ -817,17 +897,15 @@ void vout_ManageDisplay(vout_display_t *vd) } /* */ - if (osys->reset_pictures) { + if (reset_pictures) { if (vout_display_Control(vd, VOUT_DISPLAY_RESET_PICTURES)) { /* FIXME what to do here ? */ msg_Err(vd, "Failed to reset pictures (probably fatal)"); } - reset_pictures = true; - - osys->reset_pictures = false; + reset_render = true; } } - if (reset_pictures) + if (reset_render) VoutDisplayResetRender(vd); } @@ -835,7 +913,11 @@ bool vout_AreDisplayPicturesInvalid(vout_display_t *vd) { vout_display_owner_sys_t *osys = vd->owner.sys; - return osys->reset_pictures; + vlc_mutex_lock(&osys->lock); + const bool reset_pictures = osys->reset_pictures; + vlc_mutex_unlock(&osys->lock); + + return reset_pictures; } bool vout_IsDisplayFiltered(vout_display_t *vd) @@ -849,8 +931,7 @@ picture_t *vout_FilterDisplay(vout_display_t *vd, picture_t *picture) { vout_display_owner_sys_t *osys = vd->owner.sys; - if (!osys->filters) - return picture; + assert(osys->filters); return filter_chain_VideoFilter(osys->filters, picture); } @@ -858,10 +939,12 @@ void vout_SetDisplayFullscreen(vout_display_t *vd, bool is_fullscreen) { vout_display_owner_sys_t *osys = vd->owner.sys; + vlc_mutex_lock(&osys->lock); if (!osys->is_fullscreen != !is_fullscreen) { osys->ch_fullscreen = true; osys->is_fullscreen = is_fullscreen; } + vlc_mutex_unlock(&osys->lock); } void vout_SetDisplayFilled(vout_display_t *vd, bool is_filled) @@ -888,10 +971,12 @@ void vout_SetDisplayOnTop(vout_display_t *vd, bool is_on_top) { vout_display_owner_sys_t *osys = vd->owner.sys; + vlc_mutex_lock(&osys->lock); if (!osys->is_on_top != !is_on_top) { osys->ch_on_top = true; osys->is_on_top = is_on_top; } + vlc_mutex_unlock(&osys->lock); } void vout_SetDisplayAspect(vout_display_t *vd, unsigned sar_num, unsigned sar_den) { @@ -948,6 +1033,8 @@ static vout_display_t *DisplayNew(vout_thread_t *vout, osys->is_wrapper = is_wrapper; osys->wrapper = wrapper; + vlc_mutex_init(&osys->lock); + vlc_mouse_Init(&osys->mouse.state); osys->mouse.last_moved = mdate(); osys->mouse.double_click_timeout = double_click_timeout; @@ -1033,6 +1120,7 @@ void vout_DeleteDisplay(vout_display_t *vd, vout_display_state_t *state) if (osys->is_wrapper) SplitterClose(vd); vout_display_Delete(vd); + vlc_mutex_destroy(&osys->lock); free(osys); } @@ -1137,6 +1225,7 @@ static void SplitterPrepare(vout_display_t *vd, picture_t *picture) for (int i = 0; i < sys->count; i++) { /* */ + /* FIXME now vout_FilterDisplay already return a direct buffer FIXME */ sys->picture[i] = vout_FilterDisplay(sys->display[i], sys->picture[i]); if (!sys->picture[i]) continue;