[vlc-devel] [RFC] video_output: handle a second picture to display for Frame Sequential 3D sources

Steve Lhomme robux4 at ycbcr.xyz
Tue Aug 21 15:30:25 CEST 2018


---
 include/vlc_vout_display.h       |  4 +++
 include/vlc_vout_wrapper.h       | 11 ++++++--
 src/video_output/display.c       |  4 +--
 src/video_output/video_output.c  | 47 +++++++++++++++++++++++++++++---
 src/video_output/vout_internal.h |  2 ++
 5 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/include/vlc_vout_display.h b/include/vlc_vout_display.h
index 025cae13f1..f66578f960 100644
--- a/include/vlc_vout_display.h
+++ b/include/vlc_vout_display.h
@@ -277,6 +277,8 @@ struct vout_display_t {
      */
     void       (*prepare)(vout_display_t *, picture_t *, subpicture_t *,
                           vlc_tick_t date);
+    void       (*prepare_stereo)(vout_display_t *, picture_t *, picture_t *,
+                                 subpicture_t *, vlc_tick_t date);
 
     /* Display a picture and an optional subpicture (mandatory).
      *
@@ -289,6 +291,8 @@ struct vout_display_t {
      * subpicture, so you must release them as soon as possible.
      */
     void       (*display)(vout_display_t *, picture_t *, subpicture_t *);
+    void       (*display_stereo)(vout_display_t *, picture_t *, picture_t *,
+                                 subpicture_t *);
 
     /* Control on the module (mandatory) */
     int        (*control)(vout_display_t *, int, va_list);
diff --git a/include/vlc_vout_wrapper.h b/include/vlc_vout_wrapper.h
index e0a6ab0d1f..2ee69597f9 100644
--- a/include/vlc_vout_wrapper.h
+++ b/include/vlc_vout_wrapper.h
@@ -41,10 +41,13 @@ static inline picture_pool_t *vout_display_Pool(vout_display_t *vd, unsigned cou
  */
 static inline void vout_display_Prepare(vout_display_t *vd,
                                         picture_t *picture,
+                                        picture_t *second_eye,
                                         subpicture_t *subpicture,
                                         vlc_tick_t date)
 {
-    if (vd->prepare)
+    if (second_eye && vd->prepare_stereo)
+        vd->prepare_stereo(vd, picture, second_eye, subpicture, date);
+    else if (vd->prepare)
         vd->prepare(vd, picture, subpicture, date);
 }
 
@@ -53,9 +56,13 @@ static inline void vout_display_Prepare(vout_display_t *vd,
  */
 static inline void vout_display_Display(vout_display_t *vd,
                                         picture_t *picture,
+                                        picture_t *second_eye,
                                         subpicture_t *subpicture)
 {
-    vd->display(vd, picture, subpicture);
+    if (second_eye && vd->display_stereo)
+        vd->display_stereo(vd, picture, second_eye, subpicture);
+    else
+        vd->display(vd, picture,  subpicture);
 }
 
 /**
diff --git a/src/video_output/display.c b/src/video_output/display.c
index 1d2e039111..1fafb87d4d 100644
--- a/src/video_output/display.c
+++ b/src/video_output/display.c
@@ -1205,7 +1205,7 @@ static void SplitterPrepare(vout_display_t *vd,
     for (int i = 0; i < sys->count; i++) {
         sys->picture[i] = vout_FilterDisplay(sys->display[i], sys->picture[i]);
         if (sys->picture[i])
-            vout_display_Prepare(sys->display[i], sys->picture[i], NULL, date);
+            vout_display_Prepare(sys->display[i], sys->picture[i], NULL, NULL, date);
     }
 }
 static void SplitterDisplay(vout_display_t *vd,
@@ -1217,7 +1217,7 @@ static void SplitterDisplay(vout_display_t *vd,
     assert(!subpicture);
     for (int i = 0; i < sys->count; i++) {
         if (sys->picture[i])
-            vout_display_Display(sys->display[i], sys->picture[i], NULL);
+            vout_display_Display(sys->display[i], sys->picture[i], NULL, NULL);
     }
     picture_Release(picture);
 }
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 4561c39e81..84e4df15c1 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -1123,6 +1123,7 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
      */
     bool is_direct = vout->p->decoder_pool == vout->p->display_pool;
     picture_t *todisplay = filtered;
+    picture_t *todisplay_right = NULL;
     picture_t *snap_pic = todisplay;
     if (do_early_spu && subpic) {
         if (vout->p->spu_blend) {
@@ -1185,6 +1186,22 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
             picture_Release(snap_pic);
     }
 
+    if (todisplay->format.multiview_mode == MULTIVIEW_STEREO_FRAME)
+    {
+        /* special handling of multiframe videos */
+        if (todisplay->format.b_multiview_right_eye_first == !todisplay->format.b_multiview_left_eye)
+        {
+            /* keep this picture for later */
+            if (sys->stereo_pic)
+                picture_Release(sys->stereo_pic);
+            sys->stereo_pic = todisplay;
+            return VLC_SUCCESS;
+        }
+
+        /* we have both pictures */
+        todisplay_right = picture_Hold(sys->stereo_pic);
+    }
+
     /* Render the direct buffer */
     vout_UpdateDisplaySourceProperties(vd, &todisplay->format);
 
@@ -1194,13 +1211,25 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
             subpicture_Delete(subpic);
         return VLC_EGENERIC;
     }
+    if (todisplay_right != NULL) {
+        todisplay_right = vout_FilterDisplay(vd, todisplay_right);
+        if (todisplay_right == NULL) {
+            picture_Release(todisplay);
+            if (subpic != NULL)
+                subpicture_Delete(subpic);
+            return VLC_EGENERIC;
+        }
+    }
 
     if (sys->display.use_dr) {
-        vout_display_Prepare(vd, todisplay, subpic, todisplay->date);
+        vout_display_Prepare(vd, todisplay, todisplay_right, subpic, todisplay->date);
     } else {
-        if (!do_dr_spu && !do_early_spu && vout->p->spu_blend && subpic)
+        if (!do_dr_spu && !do_early_spu && vout->p->spu_blend && subpic) {
             picture_BlendSubpicture(todisplay, vout->p->spu_blend, subpic);
-        vout_display_Prepare(vd, todisplay, do_dr_spu ? subpic : NULL,
+            if (todisplay_right)
+                picture_BlendSubpicture(todisplay_right, vout->p->spu_blend, subpic);
+        }
+        vout_display_Prepare(vd, todisplay, todisplay_right, do_dr_spu ? subpic : NULL,
                              todisplay->date);
 
         if (!do_dr_spu && subpic)
@@ -1231,7 +1260,7 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
 
     /* Display the direct buffer returned by vout_RenderPicture */
     vout->p->displayed.date = vlc_tick_now();
-    vout_display_Display(vd, todisplay, subpic);
+    vout_display_Display(vd, todisplay, todisplay_right, subpic);
 
     vout_statistic_AddDisplayed(&vout->p->statistic, 1);
 
@@ -1366,6 +1395,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);
 }
@@ -1579,6 +1613,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 1ae5cb009d..59a57aed65 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 */
 };
 
 /**
-- 
2.17.0



More information about the vlc-devel mailing list