X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fvout_wrapper.c;h=2e24d63be4f86e0685c4763e983de7c50f1d72c9;hb=d72d22ae4d5a3115834bad8dae0a57b2e7904d94;hp=cfe5dde6e7f9295b5d69a2eea4dd10fdbeafffad;hpb=38ac8544e29a0cb3b31cfd96b4aac6679f7907da;p=vlc diff --git a/src/video_output/vout_wrapper.c b/src/video_output/vout_wrapper.c index cfe5dde6e7..2e24d63be4 100644 --- a/src/video_output/vout_wrapper.c +++ b/src/video_output/vout_wrapper.c @@ -1,24 +1,24 @@ /***************************************************************************** - * vout_display.c: "vout display" -> "video output" wrapper + * vout_wrapper.c: "vout display" -> "video output" wrapper ***************************************************************************** * Copyright (C) 2009 Laurent Aimar * $Id$ * * Authors: Laurent Aimar * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -30,32 +30,16 @@ #include #include -#include #include #include #include #include "vout_internal.h" #include "display.h" -/***************************************************************************** - * - *****************************************************************************/ -struct vout_sys_t { - char *title; - vout_display_t *vd; - bool use_dr; -}; - -struct picture_sys_t { - picture_t *direct; -}; - /***************************************************************************** * Local prototypes *****************************************************************************/ -static void VoutGetDisplayCfg(vout_thread_t *, - vout_display_cfg_t *, const char *title); -#ifdef WIN32 +#ifdef _WIN32 static int Forward(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *); #endif @@ -63,58 +47,39 @@ static int Forward(vlc_object_t *, char const *, /***************************************************************************** * *****************************************************************************/ -int vout_OpenWrapper(vout_thread_t *vout, const char *name) +int vout_OpenWrapper(vout_thread_t *vout, + const char *splitter_name, const vout_display_state_t *state) { - vout_sys_t *sys; - + vout_thread_sys_t *sys = vout->p; msg_Dbg(vout, "Opening vout display wrapper"); /* */ - sys = malloc(sizeof(*sys)); - if (!sys) - return VLC_ENOMEM; - - sys->title = var_CreateGetNonEmptyString(vout, "video-title"); + sys->display.title = var_InheritString(vout, "video-title"); /* */ - video_format_t source = vout->fmt_render; - source.i_visible_width = source.i_width; - source.i_visible_height = source.i_height; - source.i_x_offset = 0; - source.i_y_offset = 0; - - vout_display_state_t state; - VoutGetDisplayCfg(vout, &state.cfg, sys->title); - state.is_on_top = var_CreateGetBool(vout, "video-on-top"); - state.sar.num = 0; - state.sar.den = 0; - const mtime_t double_click_timeout = 300000; const mtime_t hide_timeout = var_CreateGetInteger(vout, "mouse-hide-timeout") * 1000; - sys->vd = vout_NewDisplay(vout, &source, &state, name ? name : "$vout", - double_click_timeout, hide_timeout); - /* If we need to video filter and it fails, then try a splitter - * XXX it is a hack for now FIXME */ - if (name && !sys->vd) - sys->vd = vout_NewSplitter(vout, &source, &state, "$vout", name, - double_click_timeout, hide_timeout); - if (!sys->vd) { - free(sys->title); - free(sys); + if (splitter_name) { + sys->display.vd = vout_NewSplitter(vout, &vout->p->original, state, "$vout", splitter_name, + double_click_timeout, hide_timeout); + } else { + sys->display.vd = vout_NewDisplay(vout, &vout->p->original, state, "$vout", + double_click_timeout, hide_timeout); + } + if (!sys->display.vd) { + free(sys->display.title); return VLC_EGENERIC; } /* */ -#ifdef WIN32 - var_Create(vout, "direct3d-desktop", VLC_VAR_BOOL|VLC_VAR_DOINHERIT); - var_AddCallback(vout, "direct3d-desktop", Forward, NULL); +#ifdef _WIN32 var_Create(vout, "video-wallpaper", VLC_VAR_BOOL|VLC_VAR_DOINHERIT); var_AddCallback(vout, "video-wallpaper", Forward, NULL); #endif /* */ - vout->p->p_sys = sys; + sys->decoder_pool = NULL; return VLC_SUCCESS; } @@ -122,104 +87,74 @@ int vout_OpenWrapper(vout_thread_t *vout, const char *name) /***************************************************************************** * *****************************************************************************/ -void vout_CloseWrapper(vout_thread_t *vout) +void vout_CloseWrapper(vout_thread_t *vout, vout_display_state_t *state) { - vout_sys_t *sys = vout->p->p_sys; + vout_thread_sys_t *sys = vout->p; -#ifdef WIN32 - var_DelCallback(vout, "direct3d-desktop", Forward, NULL); +#ifdef _WIN32 var_DelCallback(vout, "video-wallpaper", Forward, NULL); #endif - vout_DeleteDisplay(sys->vd, NULL); - free(sys->title); - free(sys ); + sys->decoder_pool = NULL; /* FIXME remove */ + + vout_DeleteDisplay(sys->display.vd, state); + free(sys->display.title); } /***************************************************************************** * *****************************************************************************/ -int vout_InitWrapper(vout_thread_t *vout) -{ - vout_sys_t *sys = vout->p->p_sys; - vout_display_t *vd = sys->vd; - - /* */ - video_format_t source = vd->source; - - vout->fmt_out.i_chroma = source.i_chroma; - vout->fmt_out.i_width = - vout->fmt_out.i_visible_width = source.i_width; - vout->fmt_out.i_height = - vout->fmt_out.i_visible_height = source.i_height; - vout->fmt_out.i_sar_num = source.i_sar_num; - vout->fmt_out.i_sar_den = source.i_sar_den; - vout->fmt_out.i_x_offset = 0; - vout->fmt_out.i_y_offset = 0; - vout->fmt_out.i_rmask = source.i_rmask; - vout->fmt_out.i_gmask = source.i_gmask; - vout->fmt_out.i_bmask = source.i_bmask; +/* Minimum number of display picture */ +#define DISPLAY_PICTURE_COUNT (1) - if (vout->fmt_in.i_visible_width != source.i_visible_width || - vout->fmt_in.i_visible_height != source.i_visible_height || - vout->fmt_in.i_x_offset != source.i_x_offset || - vout->fmt_in.i_y_offset != source.i_y_offset ) - vout->p->i_changes |= VOUT_CROP_CHANGE; - - if (vout->p->b_on_top) - vout_SetWindowState(vd, VOUT_WINDOW_STATE_ABOVE); - - /* 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. - */ - sys->use_dr = !vout_IsDisplayFiltered(vd); - const bool allow_dr = !vd->info.has_pictures_invalid && sys->use_dr; - const int picture_max = allow_dr ? VOUT_MAX_PICTURES : 1; - for (vout->p->output.i_pictures = 0; - vout->p->output.i_pictures < picture_max; - vout->p->output.i_pictures++) { - /* Find an empty picture slot */ - picture_t *picture = NULL; - for (int index = 0; index < VOUT_MAX_PICTURES; index++) { - if (vout->p->p_picture[index].i_status == FREE_PICTURE) { - picture = &vout->p->p_picture[index]; - break; - } - } - if (!picture) - break; - memset(picture, 0, sizeof(*picture)); +static void NoDrInit(vout_thread_t *vout) +{ + vout_thread_sys_t *sys = vout->p; - picture->p_sys = malloc(sizeof(*picture->p_sys)); + if (sys->display.use_dr) + sys->display_pool = vout_display_Pool(sys->display.vd, 3); + else + sys->display_pool = NULL; +} - if (sys->use_dr) { - picture_pool_t *pool = vout_display_Pool(vd, picture_max); - if (!pool) - break; - picture_t *direct = picture_pool_Get(pool); - if (!direct) - break; - picture->format = direct->format; - picture->i_planes = direct->i_planes; - for (int i = 0; i < direct->i_planes; i++) - picture->p[i] = direct->p[i]; - picture->b_slow = vd->info.is_slow; +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; - picture->p_sys->direct = direct; + sys->display.use_dr = !vout_IsDisplayFiltered(vd); + const bool allow_dr = !vd->info.has_pictures_invalid && !vd->info.is_slow && sys->display.use_dr; + const unsigned private_picture = 4; /* XXX 3 for filter, 1 for SPU */ + const unsigned decoder_picture = 1 + sys->dpb_size; + const unsigned kept_picture = 1; /* last displayed picture */ + const unsigned reserved_picture = DISPLAY_PICTURE_COUNT + + private_picture + + kept_picture; + picture_pool_t *display_pool = + vout_display_Pool(vd, allow_dr ? __MAX(VOUT_MAX_PICTURES, + reserved_picture + decoder_picture) : 3); + if (allow_dr && + picture_pool_GetSize(display_pool) >= reserved_picture + decoder_picture) { + sys->dpb_size = picture_pool_GetSize(display_pool) - reserved_picture; + sys->decoder_pool = display_pool; + sys->display_pool = display_pool; + } else if (!sys->decoder_pool) { + sys->decoder_pool = + picture_pool_NewFromFormat(&source, + __MAX(VOUT_MAX_PICTURES, + reserved_picture + decoder_picture - DISPLAY_PICTURE_COUNT)); + if (!sys->decoder_pool) + return VLC_EGENERIC; + if (allow_dr) { + msg_Warn(vout, "Not enough direct buffers, using system memory"); + sys->dpb_size = 0; } else { - vout_AllocatePicture(VLC_OBJECT(vd), picture, - vd->source.i_chroma, - vd->source.i_width, vd->source.i_height, - vd->source.i_sar_num, vd->source.i_sar_den); - if (!picture->i_planes) - break; - picture->p_sys->direct = NULL; + sys->dpb_size = picture_pool_GetSize(sys->decoder_pool) - reserved_picture; } - picture->i_status = DESTROYED_PICTURE; - picture->i_type = DIRECT_PICTURE; - - vout->p->output.pp_picture[vout->p->output.i_pictures] = picture; + NoDrInit(vout); } + sys->private_pool = picture_pool_Reserve(sys->decoder_pool, private_picture); + sys->display.filtered = NULL; return VLC_SUCCESS; } @@ -228,200 +163,34 @@ int vout_InitWrapper(vout_thread_t *vout) *****************************************************************************/ void vout_EndWrapper(vout_thread_t *vout) { - vout_sys_t *sys = vout->p->p_sys; + vout_thread_sys_t *sys = vout->p; - for (int i = 0; i < VOUT_MAX_PICTURES; i++) { - picture_t *picture = &vout->p->p_picture[i]; + assert(!sys->display.filtered); + if (sys->private_pool) + picture_pool_Delete(sys->private_pool); - if (picture->i_type != DIRECT_PICTURE) - continue; - - if (picture->p_sys->direct) - picture_Release(picture->p_sys->direct); - if (!sys->use_dr) - free(picture->p_data_orig); - free(picture->p_sys); - - picture->i_status = FREE_PICTURE; - } - if (sys->use_dr && vout_AreDisplayPicturesInvalid(sys->vd)) - vout_ManageDisplay(sys->vd, true); + if (sys->decoder_pool != sys->display_pool) + picture_pool_Delete(sys->decoder_pool); } /***************************************************************************** * *****************************************************************************/ -int vout_ManageWrapper(vout_thread_t *vout) -{ - vout_sys_t *sys = vout->p->p_sys; - vout_display_t *vd = sys->vd; - - while (vout->p->i_changes & (VOUT_FULLSCREEN_CHANGE | - VOUT_ASPECT_CHANGE | - VOUT_ZOOM_CHANGE | - VOUT_SCALE_CHANGE | - VOUT_ON_TOP_CHANGE | - VOUT_CROP_CHANGE)) { - /* */ - if (vout->p->i_changes & VOUT_FULLSCREEN_CHANGE) { - vout->p->b_fullscreen = !vout->p->b_fullscreen; - - var_SetBool(vout, "fullscreen", vout->p->b_fullscreen); - vout_SetDisplayFullscreen(vd, vout->p->b_fullscreen); - vout->p->i_changes &= ~VOUT_FULLSCREEN_CHANGE; - } - if (vout->p->i_changes & VOUT_ASPECT_CHANGE) { - vout->fmt_out.i_sar_num = vout->fmt_in.i_sar_num; - vout->fmt_out.i_sar_den = vout->fmt_in.i_sar_den; - - vout_SetDisplayAspect(vd, vout->fmt_in.i_sar_num, vout->fmt_in.i_sar_den); - - vout->p->i_changes &= ~VOUT_ASPECT_CHANGE; - } - if (vout->p->i_changes & VOUT_ZOOM_CHANGE) { - const float zoom = var_GetFloat(vout, "scale"); - - unsigned den = ZOOM_FP_FACTOR; - unsigned num = den * zoom; - if (num < (ZOOM_FP_FACTOR+9) / 10) - num = (ZOOM_FP_FACTOR+9) / 10; - else if (num > ZOOM_FP_FACTOR * 10) - num = ZOOM_FP_FACTOR * 10; - - vout_SetDisplayZoom(vd, num, den); - - vout->p->i_changes &= ~VOUT_ZOOM_CHANGE; - } - if (vout->p->i_changes & VOUT_SCALE_CHANGE) { - const bool is_display_filled = var_GetBool(vout, "autoscale"); - - vout_SetDisplayFilled(vd, is_display_filled); - - vout->p->i_changes &= ~VOUT_SCALE_CHANGE; - } - if (vout->p->i_changes & VOUT_ON_TOP_CHANGE) { - vout_SetWindowState(vd, vout->p->b_on_top - ? VOUT_WINDOW_STATE_ABOVE - : VOUT_WINDOW_STATE_NORMAL); - - vout->p->i_changes &= ~VOUT_ON_TOP_CHANGE; - } - if (vout->p->i_changes & VOUT_CROP_CHANGE) { - const video_format_t crop = vout->fmt_in; - const video_format_t org = vout->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); - vout->p->i_changes &= ~VOUT_CROP_CHANGE; - } - - } - - if (sys->use_dr && vout_AreDisplayPicturesInvalid(vd)) { - vout->p->i_changes |= VOUT_PICTURE_BUFFERS_CHANGE; - } - vout_ManageDisplay(vd, !sys->use_dr); - return VLC_SUCCESS; -} - -/***************************************************************************** - * Render - *****************************************************************************/ -void vout_RenderWrapper(vout_thread_t *vout, picture_t *picture) +void vout_ManageWrapper(vout_thread_t *vout) { - vout_sys_t *sys = vout->p->p_sys; - vout_display_t *vd = sys->vd; + vout_thread_sys_t *sys = vout->p; + vout_display_t *vd = sys->display.vd; - assert(sys->use_dr || !picture->p_sys->direct); - assert(vout_IsDisplayFiltered(vd) == !sys->use_dr); + bool reset_display_pool = vout_AreDisplayPicturesInvalid(vd); + reset_display_pool |= vout_ManageDisplay(vd, !sys->display.use_dr || reset_display_pool); - if (sys->use_dr) { - assert(picture->p_sys->direct); - vout_display_Prepare(vd, picture->p_sys->direct); - } else { - picture_t *direct = picture->p_sys->direct = vout_FilterDisplay(vd, picture); - if (direct) { - vout_display_Prepare(vd, direct); - } + if (reset_display_pool) { + sys->display.use_dr = !vout_IsDisplayFiltered(vd); + NoDrInit(vout); } } -/***************************************************************************** - * - *****************************************************************************/ -void vout_DisplayWrapper(vout_thread_t *vout, picture_t *picture) -{ - vout_sys_t *sys = vout->p->p_sys; - vout_display_t *vd = sys->vd; - - picture_t *direct = picture->p_sys->direct; - if (!direct) - return; - - /* XXX This is a hack that will work with current vout_display_t modules */ - if (sys->use_dr) - picture_Hold(direct); - - vout_display_Display(vd, direct); - - if (sys->use_dr) { - for (int i = 0; i < picture->i_planes; i++) { - picture->p[i].p_pixels = direct->p[i].p_pixels; - picture->p[i].i_pitch = direct->p[i].i_pitch; - picture->p[i].i_lines = direct->p[i].i_lines; - } - } else { - picture->p_sys->direct = NULL; - } -} - -static void VoutGetDisplayCfg(vout_thread_t *vout, vout_display_cfg_t *cfg, const char *title) -{ - /* Load configuration */ - cfg->is_fullscreen = var_CreateGetBool(vout, "fullscreen"); - cfg->display.title = title; - const int display_width = var_CreateGetInteger(vout, "width"); - const int display_height = var_CreateGetInteger(vout, "height"); - cfg->display.width = display_width > 0 ? display_width : 0; - cfg->display.height = display_height > 0 ? display_height : 0; - cfg->is_display_filled = var_CreateGetBool(vout, "autoscale"); - cfg->display.sar.num = 1; /* TODO monitor AR */ - cfg->display.sar.den = 1; - unsigned zoom_den = 1000; - unsigned zoom_num = zoom_den * var_CreateGetFloat(vout, "scale"); - vlc_ureduce(&zoom_num, &zoom_den, zoom_num, zoom_den, 0); - cfg->zoom.num = zoom_num; - cfg->zoom.den = zoom_den; - cfg->align.vertical = VOUT_DISPLAY_ALIGN_CENTER; - cfg->align.horizontal = VOUT_DISPLAY_ALIGN_CENTER; - const int align_mask = var_CreateGetInteger(vout, "align"); - if (align_mask & 0x1) - cfg->align.horizontal = VOUT_DISPLAY_ALIGN_LEFT; - else if (align_mask & 0x2) - cfg->align.horizontal = VOUT_DISPLAY_ALIGN_RIGHT; - if (align_mask & 0x4) - cfg->align.horizontal = VOUT_DISPLAY_ALIGN_TOP; - else if (align_mask & 0x8) - cfg->align.horizontal = VOUT_DISPLAY_ALIGN_BOTTOM; -} - -#ifdef WIN32 +#ifdef _WIN32 static int Forward(vlc_object_t *object, char const *var, vlc_value_t oldval, vlc_value_t newval, void *data) { @@ -429,6 +198,7 @@ static int Forward(vlc_object_t *object, char const *var, VLC_UNUSED(oldval); VLC_UNUSED(data); - return var_Set(vout->p_sys->vd, var, newval); + return var_Set(vout->p->display.vd, var, newval); } #endif +