[vlc-commits] video_output: rework the decision to use the next picture to display

Steve Lhomme git at videolan.org
Tue Jan 19 12:29:47 UTC 2021


vlc | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Tue Nov 17 13:52:20 2020 +0100| [6f6ba9cec8a6a762f30eb458382a7574a005fd67] | committer: Steve Lhomme

video_output: rework the decision to use the next picture to display

Until now, in normal playback (ie not frame by frame), 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 as long
as the "time to render" (the deadline to render - current time) is bigger than
the time it takes to render (render_delay: 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 corresponds to the date of displayed.current.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6f6ba9cec8a6a762f30eb458382a7574a005fd67
---

 src/video_output/video_output.c | 46 +++++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 93c3d50c75..eafd367c5f 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,42 @@ 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;
+                while (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 (unlikely(next == NULL))
+                        break;
+                    else
+                    {
                     // 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 (unlikely(pic_system_pts == INT64_MAX))
+                        break;
+                    else
+                        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)



More information about the vlc-commits mailing list