[vlc-devel] [PATCH 9/9] video_output: allow the vout to select which picture it wants to display

Steve Lhomme robux4 at ycbcr.xyz
Sat Oct 27 08:46:35 CEST 2018


Optionally pass a second picture per prepare/display for real stereo display.

For frame sequential the display may need both pictures at once, or only one
of them. And the video_output doesn't know about it, only the display knows
which mode it's currently using, so we need to ask it what it wants and pass
it that way.
---
 src/video_output/display.c       | 40 ++++++++++++++++++++
 src/video_output/video_output.c  | 64 +++++++++++++++++++++++++++-----
 src/video_output/vout_internal.h |  2 +
 src/video_output/vout_wrapper.h  |  3 ++
 4 files changed, 100 insertions(+), 9 deletions(-)

diff --git a/src/video_output/display.c b/src/video_output/display.c
index f347700643..2ba19b6ebf 100644
--- a/src/video_output/display.c
+++ b/src/video_output/display.c
@@ -749,6 +749,46 @@ bool vout_ManageDisplay(vout_display_t *vd, bool allow_reset_pictures)
     return false;
 }
 
+void vout_SelectMultiviewPictures(vout_display_t *vd, picture_t *eyes[2])
+{
+    vout_display_owner_sys_t *osys = vd->owner.sys;
+    vlc_stereoscopic_mode_t stereo_mode = osys->stereo_mode;
+
+    if (stereo_mode == VIDEO_STEREO_OUTPUT_AUTO)
+        stereo_mode = VIDEO_STEREO_OUTPUT_LEFT_ONLY;
+
+    switch ( stereo_mode )
+    {
+    case VIDEO_STEREO_OUTPUT_ORIGINAL:
+        /* unmodified source */
+        break;
+    case VIDEO_STEREO_OUTPUT_LEFT_ONLY:
+        if ( eyes[0]->format.multiview_mode == MULTIVIEW_STEREO_FRAME ) {
+            if (!eyes[0]->format.b_multiview_left_eye)
+            {
+                eyes[0] = NULL;
+            }
+            eyes[1] = NULL;
+        } else {
+            assert( eyes[1] == NULL );
+        }
+        break;
+    case VIDEO_STEREO_OUTPUT_RIGHT_ONLY:
+        if ( eyes[0]->format.multiview_mode == MULTIVIEW_STEREO_FRAME ) {
+            if (eyes[0]->format.b_multiview_left_eye)
+            {
+                eyes[0] = NULL;
+            }
+            eyes[1] = NULL;
+        } else {
+            assert( eyes[1] == NULL );
+        }
+        break;
+    case VIDEO_STEREO_OUTPUT_AUTO:
+        vlc_assert_unreachable();
+    }
+}
+
 bool vout_AreDisplayPicturesInvalid(vout_display_t *vd)
 {
     vout_display_owner_sys_t *osys = vd->owner.sys;
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 0336de353f..ad3b59dd45 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -1196,21 +1196,56 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
     /* Render the direct buffer */
     vout_UpdateDisplaySourceProperties(vd, &todisplay->format);
 
-    todisplay = vout_FilterDisplay(vd, todisplay);
-    if (todisplay == NULL) {
+    picture_t *eyes[2] = { todisplay, NULL };
+    if ( todisplay->format.multiview_mode == MULTIVIEW_STEREO_FRAME )
+    {
+        /* only display pictures by pair of Left/Right eye */
+        if ( todisplay->format.b_multiview_left_eye ==
+             !todisplay->format.b_multiview_right_eye_first )
+        {
+            /* keep the first eye picture until the next one arrived */
+            if (sys->stereo_pic)
+                picture_Release(sys->stereo_pic);
+            sys->stereo_pic = picture_Hold(todisplay);
+        }
+        else if (todisplay != sys->stereo_pic)
+            eyes[1] = sys->stereo_pic;
+    }
+
+    vout_SelectMultiviewPictures(vd, eyes);
+    if (eyes[0] == NULL)
+    {
+        if (subpic != NULL)
+            subpicture_Delete(subpic);
+        picture_Release(todisplay);
+        return VLC_SUCCESS;
+    }
+
+    eyes[0] = vout_FilterDisplay(vd, eyes[0]);
+    if (eyes[0] == NULL) {
         if (subpic != NULL)
             subpicture_Delete(subpic);
         return VLC_EGENERIC;
     }
+    if (eyes[1] != NULL) {
+        eyes[1] = vout_FilterDisplay(vd, eyes[1]);
+        if (eyes[1] == NULL) {
+            picture_Release(eyes[0]);
+            if (subpic != NULL)
+                subpicture_Delete(subpic);
+            return VLC_EGENERIC;
+        }
+    }
 
     if ( subpic &&
          !sys->display.use_dr && !do_dr_spu && !do_early_spu && sys->spu_blend)
     {
-        picture_BlendSubpicture(todisplay, sys->spu_blend, subpic);
-
+        picture_BlendSubpicture(eyes[0], sys->spu_blend, subpic);
+        if (eyes[1])
+            picture_BlendSubpicture(eyes[1], sys->spu_blend, subpic);
     }
-    vout_display_Prepare(vd, todisplay,
-            sys->display.use_dr || do_dr_spu ? subpic : NULL, todisplay->date);
+    vout_display_Prepare(vd, eyes[0],
+            sys->display.use_dr || do_dr_spu ? subpic : NULL, eyes[0]->date);
 
     vout_chrono_Stop(&sys->render);
 #if 0
@@ -1224,16 +1259,17 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
 
     /* Wait the real date (for rendering jitter) */
 #if 0
-    vlc_tick_t delay = todisplay->date - vlc_tick_now();
+    vlc_tick_t delay = eyes[0]->date - vlc_tick_now();
     if (delay < 1000)
         msg_Warn(vout, "picture is late (%lld ms)", delay / 1000);
 #endif
     if (!is_forced)
-        vlc_tick_wait(todisplay->date);
+        vlc_tick_wait(eyes[0]->date);
 
     /* Display the direct buffer returned by vout_RenderPicture */
     sys->displayed.date = vlc_tick_now();
-    vout_display_Display(vd, todisplay);
+    vout_display_Display(vd, eyes[0]);
+    eyes[0]->p_next = NULL;
     if (subpic)
         subpicture_Delete(subpic);
 
@@ -1371,6 +1407,11 @@ static void ThreadFlush(vout_thread_t *vout, bool below, vlc_tick_t date)
         }
     }
 
+    if (vout->p->stereo_pic) {
+        picture_Release(vout->p->stereo_pic);
+        vout->p->stereo_pic = NULL;
+    }
+
     picture_fifo_Flush(vout->p->decoder_fifo, date, below);
     vout_FilterFlush(vout->p->display.vd);
 }
@@ -1525,6 +1566,11 @@ static void ThreadStop(vout_thread_t *vout, vout_display_state_t *state)
         vout_CloseWrapper(vout, state);
     }
 
+    if (vout->p->stereo_pic) {
+        picture_Release(vout->p->stereo_pic);
+        vout->p->stereo_pic = NULL;
+    }
+
     /* Destroy the video filters */
     ThreadDelAllFilterCallbacks(vout);
     filter_chain_Delete(vout->p->filter.chain_interactive);
diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
index b189f4a8ef..fe541064ff 100644
--- a/src/video_output/vout_internal.h
+++ b/src/video_output/vout_internal.h
@@ -148,6 +148,8 @@ struct vout_thread_sys_t
     picture_pool_t  *decoder_pool;
     picture_fifo_t  *decoder_fifo;
     vout_chrono_t   render;           /**< picture render time estimator */
+
+    picture_t       *stereo_pic; /* frame sequential first eye in the sequence */
 };
 
 /**
diff --git a/src/video_output/vout_wrapper.h b/src/video_output/vout_wrapper.h
index c5dbb3a20c..7ce2f1363e 100644
--- a/src/video_output/vout_wrapper.h
+++ b/src/video_output/vout_wrapper.h
@@ -83,6 +83,9 @@ picture_t * vout_FilterDisplay(vout_display_t *, picture_t *);
 void vout_FilterFlush(vout_display_t *);
 bool vout_AreDisplayPicturesInvalid(vout_display_t *);
 
+
+void vout_SelectMultiviewPictures(vout_display_t *, picture_t *eyes[2]);
+
 bool vout_ManageDisplay(vout_display_t *, bool allow_reset_pictures);
 
 void vout_SetDisplaySize(vout_display_t *, unsigned width, unsigned height);
-- 
2.17.0



More information about the vlc-devel mailing list