X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fvideo_output.c;h=b83d04055d05013bee94960ef6585251b2b862a7;hb=a5e3a954b54587db0a7b47320f94ed7284122763;hp=0c72b2d353722877aced1211f322f621e40c43ac;hpb=b0fc931f3a6faf28692d8958f28a2c87dc104456;p=vlc diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 0c72b2d353..b83d04055d 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -5,26 +5,26 @@ * It includes functions allowing to open a new thread, send pictures to a * thread, and destroy a previously oppened video output thread. ***************************************************************************** - * Copyright (C) 2000-2007 the VideoLAN team + * Copyright (C) 2000-2007 VLC authors and VideoLAN * $Id$ * * Authors: Vincent Seguin * Gildas Bazin * 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. *****************************************************************************/ /***************************************************************************** @@ -75,7 +75,8 @@ static void VoutDestructor(vlc_object_t *); static int VoutValidateFormat(video_format_t *dst, const video_format_t *src) { - if (src->i_width <= 0 || src->i_height <= 0) + if (src->i_width <= 0 || src->i_width > 8192 || + src->i_height <= 0 || src->i_height > 8192) return VLC_EGENERIC; if (src->i_sar_num <= 0 || src->i_sar_den <= 0) return VLC_EGENERIC; @@ -119,7 +120,7 @@ static vout_thread_t *VoutCreate(vlc_object_t *object, /* Allocate descriptor */ vout_thread_t *vout = vlc_custom_create(object, sizeof(*vout) + sizeof(*vout->p), - VLC_OBJECT_VOUT, "video output"); + "video output"); if (!vout) { video_format_Clean(&original); return NULL; @@ -143,9 +144,6 @@ static vout_thread_t *VoutCreate(vlc_object_t *object, vlc_mutex_init(&vout->p->filter.lock); vlc_mutex_init(&vout->p->spu_lock); - /* Attach the new object now so we can use var inheritance below */ - vlc_object_attach(vout, object); - /* Initialize subpicture unit */ vout->p->spu = spu_Create(vout); @@ -472,8 +470,8 @@ int vout_GetSnapshot(vout_thread_t *vout, if (type && image_Type2Fourcc(type)) codec = image_Type2Fourcc(type); - const int override_width = var_GetInteger(vout, "snapshot-width"); - const int override_height = var_GetInteger(vout, "snapshot-height"); + const int override_width = var_InheritInteger(vout, "snapshot-width"); + const int override_height = var_InheritInteger(vout, "snapshot-height"); if (picture_Export(VLC_OBJECT(vout), image_dst, fmt, picture, codec, override_width, override_height)) { @@ -551,6 +549,11 @@ void vout_ControlChangeFilters(vout_thread_t *vout, const char *filters) vout_control_PushString(&vout->p->control, VOUT_CONTROL_CHANGE_FILTERS, filters); } +void vout_ControlChangeSubSources(vout_thread_t *vout, const char *filters) +{ + vout_control_PushString(&vout->p->control, VOUT_CONTROL_CHANGE_SUB_SOURCES, + filters); +} void vout_ControlChangeSubFilters(vout_thread_t *vout, const char *filters) { vout_control_PushString(&vout->p->control, VOUT_CONTROL_CHANGE_SUB_FILTERS, @@ -859,7 +862,7 @@ static int ThreadDisplayPreparePicture(vout_thread_t *vout, bool reuse, bool is_ vlc_mutex_unlock(&vout->p->filter.lock); - vout_statistic_Update(&vout->p->statistic, 0, lost_count); + vout_statistic_AddLost(&vout->p->statistic, lost_count); if (!picture) return VLC_EGENERIC; @@ -873,6 +876,7 @@ static int ThreadDisplayPreparePicture(vout_thread_t *vout, bool reuse, bool is_ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced) { + vout_thread_sys_t *sys = vout->p; vout_display_t *vd = vout->p->display.vd; picture_t *torender = picture_Hold(vout->p->displayed.current); @@ -900,10 +904,64 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced) render_subtitle_date = filtered->date > 1 ? filtered->date : mdate(); mtime_t render_osd_date = mdate(); /* FIXME wrong */ - subpicture_t *subpic = spu_Render(vout->p->spu, NULL, &vd->source, &vd->source, + /* + * Get the subpicture to be displayed + */ + const bool do_dr_spu = !do_snapshot && + vd->info.subpicture_chromas && + *vd->info.subpicture_chromas != 0; + const bool do_early_spu = !do_dr_spu && + (vd->info.is_slow || + sys->display.use_dr || + do_snapshot || + !vout_IsDisplayFiltered(vd) || + vd->fmt.i_width * vd->fmt.i_height <= vd->source.i_width * vd->source.i_height); + + const vlc_fourcc_t *subpicture_chromas; + video_format_t fmt_spu; + if (do_dr_spu) { + vout_display_place_t place; + vout_display_PlacePicture(&place, &vd->source, vd->cfg, false); + + fmt_spu = vd->source; + if (fmt_spu.i_width * fmt_spu.i_height < place.width * place.height) { + fmt_spu.i_sar_num = vd->cfg->display.sar.num; + fmt_spu.i_sar_den = vd->cfg->display.sar.den; + fmt_spu.i_width = + fmt_spu.i_visible_width = place.width; + fmt_spu.i_height = + fmt_spu.i_visible_height = place.height; + } + subpicture_chromas = vd->info.subpicture_chromas; + } else { + if (do_early_spu) { + fmt_spu = vd->source; + } else { + fmt_spu = vd->fmt; + fmt_spu.i_sar_num = vd->cfg->display.sar.num; + fmt_spu.i_sar_den = vd->cfg->display.sar.den; + } + subpicture_chromas = NULL; + + if (vout->p->spu_blend && + vout->p->spu_blend->fmt_out.video.i_chroma != fmt_spu.i_chroma) { + filter_DeleteBlend(vout->p->spu_blend); + vout->p->spu_blend = NULL; + vout->p->spu_blend_chroma = 0; + } + if (!vout->p->spu_blend && vout->p->spu_blend_chroma != fmt_spu.i_chroma) { + vout->p->spu_blend_chroma = fmt_spu.i_chroma; + vout->p->spu_blend = filter_NewBlend(VLC_OBJECT(vout), &fmt_spu); + if (!vout->p->spu_blend) + msg_Err(vout, "Failed to create blending filter, OSD/Subtitles will not work"); + } + } + + subpicture_t *subpic = spu_Render(vout->p->spu, + subpicture_chromas, &fmt_spu, + &vd->source, render_subtitle_date, render_osd_date, do_snapshot); - /* * Perform rendering * @@ -911,43 +969,41 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced) * - be sure to end up with a direct buffer. * - blend subtitles, and in a fast access buffer */ - picture_t *direct = NULL; - if (filtered && - (vout->p->decoder_pool != vout->p->display_pool || subpic)) { - picture_t *render; - if (vout->p->is_decoder_pool_slow) - render = picture_NewFromFormat(&vd->source); - else if (vout->p->decoder_pool != vout->p->display_pool) - render = picture_pool_Get(vout->p->display_pool); - else - render = picture_pool_Get(vout->p->private_pool); - - if (render) { - picture_Copy(render, filtered); - - if (vout->p->spu_blend && subpic) - picture_BlendSubpicture(render, vout->p->spu_blend, subpic); + bool is_direct = vout->p->decoder_pool == vout->p->display_pool; + picture_t *todisplay = filtered; + if (do_early_spu && subpic) { + todisplay = picture_pool_Get(vout->p->private_pool); + if (todisplay) { + VideoFormatCopyCropAr(&todisplay->format, &filtered->format); + picture_Copy(todisplay, filtered); + if (vout->p->spu_blend) + picture_BlendSubpicture(todisplay, vout->p->spu_blend, subpic); } - if (vout->p->is_decoder_pool_slow) { - direct = picture_pool_Get(vout->p->display_pool); - if (direct) - picture_Copy(direct, render); - picture_Release(render); + picture_Release(filtered); + subpicture_Delete(subpic); + subpic = NULL; - } else { - direct = render; + if (!todisplay) + return VLC_EGENERIC; + } + + picture_t *direct; + if (!is_direct && todisplay) { + direct = picture_pool_Get(vout->p->display_pool); + if (direct) { + VideoFormatCopyCropAr(&direct->format, &todisplay->format); + picture_Copy(direct, todisplay); } - VideoFormatCopyCropAr(&direct->format, &filtered->format); - picture_Release(filtered); - filtered = NULL; + picture_Release(todisplay); } else { - direct = filtered; + direct = todisplay; } - if (subpic) - subpicture_Delete(subpic); - if (!direct) + if (!direct) { + if (subpic) + subpicture_Delete(subpic); return VLC_EGENERIC; + } /* * Take a snapshot if requested @@ -955,8 +1011,23 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced) if (do_snapshot) vout_snapshot_Set(&vout->p->snapshot, &vd->source, direct); - /* Render the direct buffer returned by vout_RenderPicture */ - vout_RenderWrapper(vout, direct, NULL); + /* Render the direct buffer */ + assert(vout_IsDisplayFiltered(vd) == !sys->display.use_dr); + vout_UpdateDisplaySourceProperties(vd, &direct->format); + if (sys->display.use_dr) { + vout_display_Prepare(vd, direct, subpic); + } else { + sys->display.filtered = vout_FilterDisplay(vd, direct); + if (sys->display.filtered) { + if (!do_dr_spu && !do_early_spu && vout->p->spu_blend && subpic) + picture_BlendSubpicture(sys->display.filtered, vout->p->spu_blend, subpic); + vout_display_Prepare(vd, sys->display.filtered, do_dr_spu ? subpic : NULL); + } + if (!do_dr_spu && subpic) + subpicture_Delete(subpic); + if (!sys->display.filtered) + return VLC_EGENERIC; + } vout_chrono_Stop(&vout->p->render); #if 0 @@ -979,10 +1050,13 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced) /* Display the direct buffer returned by vout_RenderPicture */ vout->p->displayed.date = mdate(); + vout_display_Display(vd, + sys->display.filtered ? sys->display.filtered + : direct, + subpic); + sys->display.filtered = NULL; - vout_DisplayWrapper(vout, direct, NULL); - - vout_statistic_Update(&vout->p->statistic, 1, 0); + vout_statistic_AddDisplayed(&vout->p->statistic, 1); return VLC_SUCCESS; } @@ -1100,10 +1174,16 @@ static void ThreadDisplayOsdTitle(vout_thread_t *vout, const char *string) string); } +static void ThreadChangeSubSources(vout_thread_t *vout, const char *filters) +{ + spu_ChangeSources(vout->p->spu, filters); +} + static void ThreadChangeSubFilters(vout_thread_t *vout, const char *filters) { spu_ChangeFilters(vout->p->spu, filters); } + static void ThreadChangeSubMargin(vout_thread_t *vout, int margin) { spu_ChangeMargin(vout->p->spu, margin); @@ -1292,10 +1372,8 @@ static int ThreadStart(vout_thread_t *vout, const vout_display_state_t *state) vout->p->step.last = VLC_TS_INVALID; vout->p->step.timestamp = VLC_TS_INVALID; - - vout->p->spu_blend = filter_NewBlend(VLC_OBJECT(vout), &vout->p->original); - if (!vout->p->spu_blend) - msg_Err(vout, "Failed to create blending filter, OSD/Subtitles will not work"); + vout->p->spu_blend_chroma = 0; + vout->p->spu_blend = NULL; video_format_Print(VLC_OBJECT(vout), "original format", &vout->p->original); return VLC_SUCCESS; @@ -1445,6 +1523,9 @@ static void *Thread(void *object) case VOUT_CONTROL_CHANGE_FILTERS: ThreadChangeFilters(vout, NULL, cmd.u.string, false); break; + case VOUT_CONTROL_CHANGE_SUB_SOURCES: + ThreadChangeSubSources(vout, cmd.u.string); + break; case VOUT_CONTROL_CHANGE_SUB_FILTERS: ThreadChangeSubFilters(vout, cmd.u.string); break;