[vlc-commits] sout: sdi: fix with 4.0 non abs clock timestamps

Francois Cartegnie git at videolan.org
Sun May 5 15:26:49 CEST 2019


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri May  3 17:07:21 2019 +0200| [f6f98c83b30857e049ba39af0157a4aefc791b7d] | committer: Francois Cartegnie

sout: sdi: fix with 4.0 non abs clock timestamps

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

 modules/stream_out/sdi/DBMSDIOutput.cpp | 103 ++++++++++++++++++++------------
 modules/stream_out/sdi/DBMSDIOutput.hpp |  11 +++-
 2 files changed, 74 insertions(+), 40 deletions(-)

diff --git a/modules/stream_out/sdi/DBMSDIOutput.cpp b/modules/stream_out/sdi/DBMSDIOutput.cpp
index d54d2ce688..5cb007c34a 100644
--- a/modules/stream_out/sdi/DBMSDIOutput.cpp
+++ b/modules/stream_out/sdi/DBMSDIOutput.cpp
@@ -44,15 +44,14 @@ DBMSDIOutput::DBMSDIOutput(sout_stream_t *p_stream) :
 {
     p_card = NULL;
     p_output = NULL;
-    offset = 0;
+    clock.system_reference = VLC_TICK_INVALID;
+    clock.offset = 0;
     lasttimestamp = 0;
     b_running = false;
 }
 
 DBMSDIOutput::~DBMSDIOutput()
 {
-    if(video.pic_nosignal)
-        picture_Release(video.pic_nosignal);
     es_format_Clean(&video.configuredfmt);
     if(p_output)
     {
@@ -73,8 +72,6 @@ AbstractStream *DBMSDIOutput::Add(const es_format_t *fmt)
     {
         msg_Dbg(p_stream, "accepted %s %4.4s",
                           s->getID().toString().c_str(), (const char *) &fmt->i_codec);
-        if( videoStream && (!audioStreams.empty() || audio.i_channels == 0) )
-            Start();
     }
     else
     {
@@ -85,6 +82,16 @@ AbstractStream *DBMSDIOutput::Add(const es_format_t *fmt)
     return s;
 }
 
+int DBMSDIOutput::Send(AbstractStream *s, block_t *b)
+{
+    if(!b_running && b->i_dts != VLC_TICK_INVALID)
+    {
+        if( videoStream && (!audioStreams.empty() || audio.i_channels == 0) )
+            Start(b->i_dts);
+    }
+    return SDIOutput::Send(s, b);
+}
+
 IDeckLinkDisplayMode * DBMSDIOutput::MatchDisplayMode(const video_format_t *fmt, BMDDisplayMode forcedmode)
 {
     HRESULT result;
@@ -502,7 +509,7 @@ error:
     return VLC_EGENERIC;
 }
 
-int DBMSDIOutput::Start()
+int DBMSDIOutput::Start(vlc_tick_t startTime)
 {
     HRESULT result;
     if(FAKE_DRIVER && !b_running)
@@ -512,8 +519,8 @@ int DBMSDIOutput::Start()
     }
     if(b_running)
         return VLC_EGENERIC;
-    result = p_output->StartScheduledPlayback(
-                     samples_from_vlc_tick(vlc_tick_now(), timescale), timescale, 1.0);
+
+    result = p_output->StartScheduledPlayback(startTime, CLOCK_FREQ, 1.0);
     CHECK("Could not start playback");
     b_running = true;
     return VLC_SUCCESS;
@@ -575,12 +582,14 @@ int DBMSDIOutput::ProcessAudio(block_t *p_block)
         return VLC_EGENERIC;
     }
 
-    p_block->i_pts -= offset;
+    p_block->i_pts -= clock.offset;
 
     uint32_t sampleFrameCount = p_block->i_nb_samples;
     uint32_t written;
     HRESULT result = p_output->ScheduleAudioSamples(
-            p_block->p_buffer, p_block->i_nb_samples, p_block->i_pts, CLOCK_FREQ, &written);
+                p_block->p_buffer, p_block->i_nb_samples,
+                p_block->i_pts + CLOCK_FREQ,
+                CLOCK_FREQ, &written);
 
     if (result != S_OK)
         msg_Err(p_stream, "Failed to schedule audio sample: 0x%X", result);
@@ -598,22 +607,26 @@ int DBMSDIOutput::ProcessAudio(block_t *p_block)
 
 int DBMSDIOutput::ProcessVideo(picture_t *picture, block_t *p_cc)
 {
-    mtime_t now = vlc_tick_now();
-
     if (!picture)
         return VLC_EGENERIC;
 
-    if(picture->date - now >  5000)
-        vlc_msleep_i11e(picture->date - now);
+    checkClockDrift();
 
-    if (video.pic_nosignal &&
-        now - picture->date > vlc_tick_from_sec(video.nosignal_delay))
+    if(video.pic_nosignal)
     {
-        msg_Dbg(p_stream, "no signal");
-
-        picture_Hold(video.pic_nosignal);
-        video.pic_nosignal->date = now;
-        doProcessVideo(picture, NULL);
+        BMDTimeValue streamTime;
+        double playbackSpeed;
+        if(S_OK == p_output->GetScheduledStreamTime(CLOCK_FREQ, &streamTime, &playbackSpeed))
+        {
+            if(picture->date + CLOCK_FREQ - streamTime >
+                    VLC_TICK_FROM_SEC(video.nosignal_delay))
+            {
+                msg_Info(p_stream, "no signal");
+                picture_Hold(video.pic_nosignal);
+                video.pic_nosignal->date = streamTime + VLC_TICK_FROM_MS(30);
+                doProcessVideo(video.pic_nosignal, NULL);
+            }
+        }
     }
 
     return doProcessVideo(picture, p_cc);
@@ -623,7 +636,6 @@ int DBMSDIOutput::doProcessVideo(picture_t *picture, block_t *p_cc)
 {
     HRESULT result;
     int w, h, stride, length, ret = VLC_EGENERIC;
-    mtime_t now;
     IDeckLinkMutableVideoFrame *pDLVideoFrame = NULL;
     w = video.configuredfmt.video.i_visible_width;
     h = video.configuredfmt.video.i_visible_height;
@@ -634,7 +646,7 @@ int DBMSDIOutput::doProcessVideo(picture_t *picture, block_t *p_cc)
     result = p_output->CreateVideoFrame(w, h, w*3,
                                         video.tenbits ? bmdFormat10BitYUV : bmdFormat8BitYUV,
                                         bmdFrameFlagDefault, &pDLVideoFrame);
-    if (result != S_OK) {
+    if(result != S_OK) {
         msg_Err(p_stream, "Failed to create video frame: 0x%X", result);
         goto error;
     }
@@ -693,10 +705,10 @@ int DBMSDIOutput::doProcessVideo(picture_t *picture, block_t *p_cc)
 
     // compute frame duration in CLOCK_FREQ units
     length = (frameduration * CLOCK_FREQ) / timescale;
-
-    picture->date -= offset;
+    picture->date -= clock.offset;
     result = p_output->ScheduleVideoFrame(pDLVideoFrame,
-                                          picture->date, length, CLOCK_FREQ);
+                                          picture->date + CLOCK_FREQ,
+                                          length, CLOCK_FREQ);
     if (result != S_OK) {
         msg_Err(p_stream, "Dropped Video frame %" PRId64 ": 0x%x",
                 picture->date, result);
@@ -704,18 +716,6 @@ int DBMSDIOutput::doProcessVideo(picture_t *picture, block_t *p_cc)
     }
     lasttimestamp = __MAX(picture->date, lasttimestamp);
 
-    now = vlc_tick_now() - offset;
-
-    BMDTimeValue decklink_now;
-    double speed;
-    p_output->GetScheduledStreamTime (CLOCK_FREQ, &decklink_now, &speed);
-
-    if ((now - decklink_now) > 400000) {
-        /* XXX: workaround card clock drift */
-        offset += 50000;
-        msg_Err(p_stream, "Delaying: offset now %" PRId64, offset);
-    }
-
 end:
     ret = VLC_SUCCESS;
 
@@ -729,6 +729,33 @@ error:
     return ret;
 }
 
+void DBMSDIOutput::checkClockDrift()
+{
+    BMDTimeValue hardwareTime, timeInFrame, ticksPerFrame;
+    if(S_OK == p_output->GetHardwareReferenceClock(CLOCK_FREQ,
+                                                   &hardwareTime,
+                                                   &timeInFrame,
+                                                   &ticksPerFrame))
+    {
+        if(clock.system_reference == VLC_TICK_INVALID)
+        {
+            clock.system_reference = vlc_tick_now();
+            clock.hardware_reference = hardwareTime;
+        }
+        else
+        {
+            vlc_tick_t elapsed_system = vlc_tick_now() - clock.system_reference;
+            BMDTimeValue elapsed_hardware = hardwareTime - clock.hardware_reference;
+            if(std::abs(elapsed_system - elapsed_hardware) >
+                    std::abs(clock.offset) + VLC_TICK_FROM_MS(15))
+            {
+                clock.offset = elapsed_system - elapsed_hardware;
+                msg_Info(p_stream, "offset now %" PRId64 " ms", clock.offset / 1000);
+            }
+        }
+    }
+}
+
 picture_t * DBMSDIOutput::CreateNoSignalPicture(const char *psz_file, const video_format_t *fmt)
 {
     picture_t *p_pic = NULL;
diff --git a/modules/stream_out/sdi/DBMSDIOutput.hpp b/modules/stream_out/sdi/DBMSDIOutput.hpp
index 95fe8bf9ce..60fca102ef 100644
--- a/modules/stream_out/sdi/DBMSDIOutput.hpp
+++ b/modules/stream_out/sdi/DBMSDIOutput.hpp
@@ -36,6 +36,7 @@ namespace sdi_sout
             virtual AbstractStream *Add(const es_format_t *); /* reimpl */
             virtual int Open(); /* impl */
             virtual int Process(); /* impl */
+            virtual int Send(AbstractStream *, block_t *); /* reimpl */
 
         protected:
             int ProcessVideo(picture_t *, block_t *);
@@ -51,14 +52,20 @@ namespace sdi_sout
             BMDTimeValue frameduration;
             vlc_tick_t lasttimestamp;
             /* XXX: workaround card clock drift */
-            vlc_tick_t offset;
+            struct
+            {
+                vlc_tick_t offset; /* > 0 if clock card is slower */
+                vlc_tick_t system_reference;
+                BMDTimeValue hardware_reference;
+            } clock;
             bool b_running;
-            int Start();
+            int Start(vlc_tick_t);
             const char *ErrorToString(long i_code);
             IDeckLinkDisplayMode * MatchDisplayMode(const video_format_t *,
                                                     BMDDisplayMode = bmdDisplayModeNotSupported);
             int doProcessVideo(picture_t *, block_t *);
             picture_t * CreateNoSignalPicture(const char*, const video_format_t *);
+            void checkClockDrift();
     };
 }
 



More information about the vlc-commits mailing list