]> git.sesse.net Git - vlc/blobdiff - src/video_output/video_output.c
ThreadDisplayPicture: simplify prototype
[vlc] / src / video_output / video_output.c
index f390e7db510046428e4da08d088684d40f6d353f..3876ccd0afd852de79e614de3098951f305ba4ef 100644 (file)
@@ -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 <seguin@via.ecp.fr>
  *          Gildas Bazin <gbazin@videolan.org>
  *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
  *
- * 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.
  *****************************************************************************/
 
 /*****************************************************************************
@@ -49,7 +49,6 @@
 #include <libvlc.h>
 #include "vout_internal.h"
 #include "interlacing.h"
-#include "postprocessing.h"
 #include "display.h"
 
 /*****************************************************************************
@@ -75,7 +74,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 +119,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,18 +143,15 @@ 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);
 
     /* Take care of some "interface/control" related initialisations */
     vout_IntfInit(vout);
 
-    vout->p->title.show     = var_GetBool(vout, "video-title-show");
-    vout->p->title.timeout  = var_GetInteger(vout, "video-title-timeout");
-    vout->p->title.position = var_GetInteger(vout, "video-title-position");
+    vout->p->title.show     = var_InheritBool(vout, "video-title-show");
+    vout->p->title.timeout  = var_InheritInteger(vout, "video-title-timeout");
+    vout->p->title.position = var_InheritInteger(vout, "video-title-position");
 
     /* Get splitter name if present */
     char *splitter_name = var_InheritString(vout, "video-splitter");
@@ -224,6 +221,7 @@ vout_thread_t *(vout_Request)(vlc_object_t *object,
 
         if (!vout->p->dead) {
             msg_Dbg(object, "reusing provided vout");
+            vout_IntfReinit(vout);
             return vout;
         }
         vout_CloseAndRelease(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,
@@ -852,14 +855,13 @@ static int ThreadDisplayPreparePicture(vout_thread_t *vout, bool reuse, bool is_
         vout->p->displayed.decoded       = picture_Hold(decoded);
         vout->p->displayed.timestamp     = decoded->date;
         vout->p->displayed.is_interlaced = !decoded->b_progressive;
-        vout->p->displayed.qtype         = decoded->i_qtype;
 
         picture = filter_chain_VideoFilter(vout->p->filter.chain_static, decoded);
     }
 
     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;
 
@@ -907,11 +909,28 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
     const bool do_dr_spu = !do_snapshot &&
                            vd->info.subpicture_chromas &&
                            *vd->info.subpicture_chromas != 0;
-    const bool do_early_spu = true; /* TODO */
+    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) {
-        fmt_spu = vd->source; /* TODO improve */
+        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) {
@@ -949,71 +968,68 @@ 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
      */
-    bool is_direct;
-    picture_t *todisplay;
-
-    if (filtered && do_early_spu && vout->p->spu_blend && subpic) {
-        if (vd->info.is_slow) {
-            is_direct = false;
-            todisplay = picture_NewFromFormat(&vd->source); /* FIXME a pool ? */
-        } else {
-            is_direct = true;
-            todisplay = picture_pool_Get(vout->p->display_pool);
-        }
-        if (todisplay) {
-            VideoFormatCopyCropAr(&todisplay->format, &filtered->format);
-            picture_Copy(todisplay, filtered);
-            picture_BlendSubpicture(todisplay, 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) {
+        picture_t *blent = picture_pool_Get(vout->p->private_pool);
+        if (blent) {
+            VideoFormatCopyCropAr(&blent->format, &filtered->format);
+            picture_Copy(blent, filtered);
+            if (vout->p->spu_blend
+             && picture_BlendSubpicture(blent, vout->p->spu_blend, subpic)) {
+                picture_Release(todisplay);
+                todisplay = blent;
+            } else
+                picture_Release(blent);
         }
-        picture_Release(filtered);
         subpicture_Delete(subpic);
         subpic = NULL;
-
-        if (!todisplay)
-            return VLC_EGENERIC;
-    } else {
-        is_direct = vout->p->decoder_pool == vout->p->display_pool;
-        todisplay = filtered;
     }
 
-    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);
+    assert(vout_IsDisplayFiltered(vd) == !sys->display.use_dr);
+    if (sys->display.use_dr && !is_direct) {
+        picture_t *direct = picture_pool_Get(vout->p->display_pool);
+        if (!direct) {
+            picture_Release(todisplay);
+            if (subpic)
+                subpicture_Delete(subpic);
+            return VLC_EGENERIC;
         }
-        picture_Release(todisplay);
-    } else {
-        direct = todisplay;
-    }
 
-    if (!direct) {
-        if (subpic)
-            subpicture_Delete(subpic);
-        return VLC_EGENERIC;
+        /* The display uses direct rendering (no conversion), but its pool of
+         * pictures is not usable by the decoder (too few, too slow or
+         * subject to invalidation...). Since there are no filters, copying
+         * pictures from the decoder to the output is unavoidable. */
+        VideoFormatCopyCropAr(&direct->format, &todisplay->format);
+        picture_Copy(direct, todisplay);
+        picture_Release(todisplay);
+        todisplay = direct;
     }
 
     /*
      * Take a snapshot if requested
      */
     if (do_snapshot)
-        vout_snapshot_Set(&vout->p->snapshot, &vd->source, direct);
+        vout_snapshot_Set(&vout->p->snapshot, &vd->source, todisplay);
 
     /* Render the direct buffer */
-    assert(vout_IsDisplayFiltered(vd) == !sys->display.use_dr);
-    vout_UpdateDisplaySourceProperties(vd, &direct->format);
+    vout_UpdateDisplaySourceProperties(vd, &todisplay->format);
     if (sys->display.use_dr) {
-        vout_display_Prepare(vd, direct, subpic);
+        vout_display_Prepare(vd, todisplay, subpic);
     } else {
-        sys->display.filtered = vout_FilterDisplay(vd, direct);
+        sys->display.filtered = vout_FilterDisplay(vd, todisplay);
         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);
+            subpic = NULL;
+        }
+        if (!sys->display.filtered)
+            return VLC_EGENERIC;
     }
 
     vout_chrono_Stop(&vout->p->render);
@@ -1033,24 +1049,24 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
         msg_Warn(vout, "picture is late (%lld ms)", delay / 1000);
 #endif
     if (!is_forced)
-        mwait(direct->date);
+        mwait(todisplay->date);
 
     /* Display the direct buffer returned by vout_RenderPicture */
     vout->p->displayed.date = mdate();
     vout_display_Display(vd,
                          sys->display.filtered ? sys->display.filtered
-                                                : direct,
+                                                : todisplay,
                          subpic);
     sys->display.filtered = NULL;
 
-    vout_statistic_Update(&vout->p->statistic, 1, 0);
+    vout_statistic_AddDisplayed(&vout->p->statistic, 1);
 
     return VLC_SUCCESS;
 }
 
-static int ThreadDisplayPicture(vout_thread_t *vout,
-                                bool now, mtime_t *deadline)
+static int ThreadDisplayPicture(vout_thread_t *vout, mtime_t *deadline)
 {
+    bool now = !deadline;
     bool is_late_dropped = vout->p->is_late_dropped && !vout->p->pause.is_on && !now;
     bool first = !vout->p->displayed.current;
     if (first && ThreadDisplayPreparePicture(vout, true, is_late_dropped)) /* FIXME not sure it is ok */
@@ -1092,12 +1108,14 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
         refresh = date_refresh <= date;
 
     if (!first && !refresh && !drop) {
-        if (date_next != VLC_TS_INVALID && date_refresh != VLC_TS_INVALID)
-            *deadline = __MIN(date_next, date_refresh);
-        else if (date_next != VLC_TS_INVALID)
-            *deadline = date_next;
-        else if (date_refresh != VLC_TS_INVALID)
-            *deadline = date_refresh;
+        if (!now) {
+            if (date_next != VLC_TS_INVALID && date_refresh != VLC_TS_INVALID)
+                *deadline = __MIN(date_next, date_refresh);
+            else if (date_next != VLC_TS_INVALID)
+                *deadline = date_next;
+            else if (date_refresh != VLC_TS_INVALID)
+                *deadline = date_refresh;
+        }
         return VLC_EGENERIC;
     }
 
@@ -1115,25 +1133,19 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
 
 static void ThreadManage(vout_thread_t *vout,
                          mtime_t *deadline,
-                         vout_interlacing_support_t *interlacing,
-                         vout_postprocessing_support_t *postprocessing)
+                         vout_interlacing_support_t *interlacing)
 {
     vlc_mutex_lock(&vout->p->picture_lock);
 
     *deadline = VLC_TS_INVALID;
-    for (;;) {
-        if (ThreadDisplayPicture(vout, false, deadline))
+    for (;;)
+        if (ThreadDisplayPicture(vout, deadline))
             break;
-    }
 
-    const int  picture_qtype      = vout->p->displayed.qtype;
     const bool picture_interlaced = vout->p->displayed.is_interlaced;
 
     vlc_mutex_unlock(&vout->p->picture_lock);
 
-    /* Post processing */
-    vout_SetPostProcessingState(vout, postprocessing, picture_qtype);
-
     /* Deinterlacing */
     vout_SetInterlacingState(vout, interlacing, picture_interlaced);
 
@@ -1161,10 +1173,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);
@@ -1233,8 +1251,7 @@ static void ThreadStep(vout_thread_t *vout, mtime_t *duration)
     if (vout->p->step.last <= VLC_TS_INVALID)
         vout->p->step.last = vout->p->displayed.timestamp;
 
-    mtime_t dummy;
-    if (ThreadDisplayPicture(vout, true, &dummy))
+    if (ThreadDisplayPicture(vout, NULL))
         return;
 
     vout->p->step.timestamp = vout->p->displayed.timestamp;
@@ -1249,8 +1266,6 @@ static void ThreadStep(vout_thread_t *vout, mtime_t *duration)
 
 static void ThreadChangeFullscreen(vout_thread_t *vout, bool fullscreen)
 {
-    /* FIXME not sure setting "fullscreen" is good ... */
-    var_SetBool(vout, "fullscreen", fullscreen);
     vout_SetDisplayFullscreen(vout->p->display.vd, fullscreen);
 }
 
@@ -1347,7 +1362,6 @@ static int ThreadStart(vout_thread_t *vout, const vout_display_state_t *state)
     vout->p->displayed.decoded       = NULL;
     vout->p->displayed.date          = VLC_TS_INVALID;
     vout->p->displayed.timestamp     = VLC_TS_INVALID;
-    vout->p->displayed.qtype         = QTYPE_NONE;
     vout->p->displayed.is_interlaced = false;
 
     vout->p->step.last               = VLC_TS_INVALID;
@@ -1463,9 +1477,6 @@ static void *Thread(void *object)
         .is_interlaced = false,
         .date = mdate(),
     };
-    vout_postprocessing_support_t postprocessing = {
-        .qtype = QTYPE_NONE,
-    };
 
     mtime_t deadline = VLC_TS_INVALID;
     for (;;) {
@@ -1504,6 +1515,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;
@@ -1556,7 +1570,7 @@ static void *Thread(void *object)
             vout_control_cmd_Clean(&cmd);
         }
 
-        ThreadManage(vout, &deadline, &interlacing, &postprocessing);
+        ThreadManage(vout, &deadline, &interlacing);
     }
 }