[vlc-devel] [PATCH v3 2/8] video_output: rework the decision to use the next picture to display

Steve Lhomme robux4 at ycbcr.xyz
Wed Nov 18 12:56:12 CET 2020


Until now, in normal playback, the way to skip to the next frame to display was
* get displayed.current
* get displayed.next
* if displayed.next has time to render use it to replace displayed.current
* the vout thread waits until the deadline to render displayed.current

Now we don't use displayed.next anymore. We keep the displayed.current has long
as the "time to render" (the deadline to render - current time) is bigger than
the time it takes to render (average of previous frames + 4 ms tolerance).
If there is not enough time, we try to get the next picture from the
decoder+prerender. And we check if there's enough time to render that one.
If there is not enough time, we try to get the next picture from the
decoder+prerender. And so on...

This allows having one picture about to be displayed in memory rather than 2
(displayed.current and displayed.next), which should be useful to decide when to
change the display module (when displayed.current changes, not displayed.next).

date_refresh is set to the render date of the next picture if there is one and
the render date of the current picture otherwise. Before the deadline was the
date of the next picture even if we're sticking to the current picture. It
would potentially start the rendering of the current picture too late. Now the
(start render) deadline always correspond to the date of displayed.current.
---
 src/video_output/video_output.c | 42 +++++++++++++++++----------------
 1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index cea13d44c4a..e78b0fd8480 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -1502,15 +1502,6 @@ static int ThreadDisplayPicture(vout_thread_sys_t *vout, vlc_tick_t *deadline)
     }
     else
     {
-        if (!paused)
-        {
-            if (!sys->displayed.next)
-            {
-                sys->displayed.next =
-                    ThreadDisplayPreparePicture(vout, false, false, &paused);
-            }
-        }
-
         const vlc_tick_t system_now = vlc_tick_now();
         const vlc_tick_t render_delay = vout_chrono_GetHigh(&sys->render) + VOUT_MWAIT_TOLERANCE;
 
@@ -1534,27 +1525,38 @@ static int ThreadDisplayPicture(vout_thread_sys_t *vout, vlc_tick_t *deadline)
         }
         render_now = refresh;
 
-        if (!paused && sys->displayed.next) {
-            const vlc_tick_t next_system_pts =
+        if (!paused) {
+            vlc_tick_t pic_system_pts =
                 vlc_clock_ConvertToSystem(sys->clock, system_now,
-                                        sys->displayed.next->date, sys->rate);
-            if (likely(next_system_pts != INT64_MAX))
+                                          sys->displayed.current->date, sys->rate);
+            if (likely(pic_system_pts != INT64_MAX))
             {
-                vlc_tick_t date_next = next_system_pts - render_delay;
-                if (date_refresh == VLC_TICK_INVALID || date_next < date_refresh)
-                    date_refresh = date_next;
-
-                if (date_next <= system_now)
+                vlc_tick_t pic_render_deadline = pic_system_pts - render_delay;
+                if (pic_render_deadline <= system_now)
                 {
+                    // not enough (predicted) time to render current, get non-late pic
+                    picture_t *next;
+                    next = ThreadDisplayPreparePicture(vout, false, false, &paused);
+                    if (likely(next != NULL))
+                    {
                     // next frame will still need some waiting before display
                     dropped_current_frame = true;
                     render_now = false;
 
                     if (likely(sys->displayed.current != NULL))
                         picture_Release(sys->displayed.current);
-                    sys->displayed.current = sys->displayed.next;
-                    sys->displayed.next    = NULL;
+                    sys->displayed.current = next;
+
+                    pic_system_pts =
+                        vlc_clock_ConvertToSystem(sys->clock, vlc_tick_now(),
+                                                  sys->displayed.current->date, sys->rate);
+                    if (likely(pic_system_pts != INT64_MAX))
+                        pic_render_deadline = pic_system_pts - render_delay;
+                    }
                 }
+
+                if (date_refresh == VLC_TICK_INVALID || pic_render_deadline < date_refresh)
+                    date_refresh = pic_render_deadline;
             }
         }
         if (date_refresh != VLC_TICK_INVALID)
-- 
2.26.2



More information about the vlc-devel mailing list