summaryrefslogtreecommitdiff
path: root/sys/decklink
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2016-11-22 19:30:27 +0200
committerSebastian Dröge <sebastian@centricular.com>2016-11-28 14:27:51 +0200
commit881a08671eda4324b6ad781a9d3ddf82f1813cbb (patch)
tree8ae0b86ec4d8d79c4782854dde4d362dc95d1ce1 /sys/decklink
parent423e4593aabb5d86ec66975cbc618d423e8817bc (diff)
downloadgstreamer-plugins-bad-881a08671eda4324b6ad781a9d3ddf82f1813cbb.tar.gz
decklinksrc: Stop using the "hardware" timestamps and directly use the pipeline clock
The hardware timestamps have no relation to when frames were produced, only when frames arrived somewhere in the hardware. Especially there is no guarantee that audio and video will have the same hardware timestamps although they belong together, and even more important: the rate with which the hardware timestamps increase is completely unrelated to the rate with which the frames are captured! As such we can as well use the pipeline clock directly and stop doing complicated calculations. Also as a side effect this allows now running without any pipeline clock, by directly making use of the stream times as reported by the driver. https://bugzilla.gnome.org/show_bug.cgi?id=774850
Diffstat (limited to 'sys/decklink')
-rw-r--r--sys/decklink/gstdecklink.cpp269
-rw-r--r--sys/decklink/gstdecklink.h8
-rw-r--r--sys/decklink/gstdecklinkaudiosrc.cpp30
-rw-r--r--sys/decklink/gstdecklinkvideosink.cpp3
-rw-r--r--sys/decklink/gstdecklinkvideosrc.cpp189
-rw-r--r--sys/decklink/gstdecklinkvideosrc.h5
6 files changed, 138 insertions, 366 deletions
diff --git a/sys/decklink/gstdecklink.cpp b/sys/decklink/gstdecklink.cpp
index 184f124a9..2a797412d 100644
--- a/sys/decklink/gstdecklink.cpp
+++ b/sys/decklink/gstdecklink.cpp
@@ -617,7 +617,6 @@ struct _GstDecklinkClock
{
GstSystemClock clock;
- GstDecklinkInput *input;
GstDecklinkOutput *output;
};
@@ -722,99 +721,108 @@ public:
GstElement *videosrc = NULL, *audiosrc = NULL;
void (*got_video_frame) (GstElement * videosrc,
IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
- GstClockTime capture_time, GstClockTime capture_duration, guint hours,
- guint minutes, guint seconds, guint frames, BMDTimecodeFlags bflags) =
- NULL;
+ GstClockTime capture_time, GstClockTime stream_time,
+ GstClockTime stream_duration, guint hours, guint minutes, guint seconds,
+ guint frames, BMDTimecodeFlags bflags) = NULL;
void (*got_audio_packet) (GstElement * videosrc,
IDeckLinkAudioInputPacket * packet, GstClockTime capture_time,
- gboolean discont) = NULL;
+ GstClockTime packet_time) = NULL;
GstDecklinkModeEnum mode;
- BMDTimeValue capture_time = GST_CLOCK_TIME_NONE, capture_duration =
- GST_CLOCK_TIME_NONE;
+ GstClockTime capture_time = GST_CLOCK_TIME_NONE;
+ GstClockTime base_time;
+ GstClock *clock = NULL;
HRESULT res;
- IDeckLinkTimecode *dtc;
- uint8_t hours, minutes, seconds, frames;
- BMDTimecodeFlags bflags;
-
- hours = minutes = seconds = frames = bflags = 0;
- if (video_frame == NULL)
- goto no_video_frame;
-
- res =
- video_frame->GetHardwareReferenceTimestamp (GST_SECOND, &capture_time,
- &capture_duration);
- if (res != S_OK) {
- GST_ERROR ("Failed to get capture time: 0x%08x", res);
- capture_time = GST_CLOCK_TIME_NONE;
- capture_duration = GST_CLOCK_TIME_NONE;
- }
-
- if (m_input->videosrc) {
- /* FIXME: Avoid circularity between gstdecklink.cpp and
- * gstdecklinkvideosrc.cpp */
- videosrc = GST_ELEMENT_CAST (gst_object_ref (m_input->videosrc));
- res =
- video_frame->
- GetTimecode (GST_DECKLINK_VIDEO_SRC (videosrc)->timecode_format,
- &dtc);
-
- if (res != S_OK) {
- GST_DEBUG_OBJECT (videosrc, "Failed to get timecode: 0x%08x", res);
- dtc = NULL;
- } else {
- res = dtc->GetComponents (&hours, &minutes, &seconds, &frames);
- if (res != S_OK) {
- GST_ERROR ("Could not get components for timecode %p: 0x%08x", dtc,
- res);
- hours = 0;
- minutes = 0;
- seconds = 0;
- frames = 0;
- bflags = 0;
- } else {
- GST_DEBUG_OBJECT (videosrc, "Got timecode %02d:%02d:%02d:%02d", hours,
- minutes, seconds, frames);
- bflags = dtc->GetFlags ();
- }
- }
- }
g_mutex_lock (&m_input->lock);
-
- if (capture_time > (BMDTimeValue) m_input->clock_start_time)
- capture_time -= m_input->clock_start_time;
- else
- capture_time = 0;
-
- if (capture_time > (BMDTimeValue) m_input->clock_offset)
- capture_time -= m_input->clock_offset;
- else
- capture_time = 0;
-
if (m_input->videosrc) {
+ videosrc = GST_ELEMENT_CAST (gst_object_ref (m_input->videosrc));
+ clock = gst_element_get_clock (videosrc);
+ base_time = gst_element_get_base_time (videosrc);
got_video_frame = m_input->got_video_frame;
}
mode = gst_decklink_get_mode_enum_from_bmd (m_input->mode->mode);
if (m_input->audiosrc) {
audiosrc = GST_ELEMENT_CAST (gst_object_ref (m_input->audiosrc));
+ if (!clock) {
+ clock = gst_element_get_clock (GST_ELEMENT_CAST (audiosrc));
+ base_time = gst_element_get_base_time (audiosrc);
+ }
got_audio_packet = m_input->got_audio_packet;
}
g_mutex_unlock (&m_input->lock);
- if (got_video_frame && videosrc) {
+ if (clock) {
+ capture_time = gst_clock_get_time (clock);
+ if (capture_time > base_time)
+ capture_time -= base_time;
+ else
+ capture_time = 0;
+ }
+
+ if (got_video_frame && videosrc && video_frame) {
+ BMDTimeValue stream_time = GST_CLOCK_TIME_NONE;
+ BMDTimeValue stream_duration = GST_CLOCK_TIME_NONE;
+ IDeckLinkTimecode *dtc;
+ uint8_t hours, minutes, seconds, frames;
+ BMDTimecodeFlags bflags;
+
+ hours = minutes = seconds = frames = bflags = 0;
+
+ res =
+ video_frame->GetStreamTime (&stream_time, &stream_duration,
+ GST_SECOND);
+ if (res != S_OK) {
+ GST_ERROR ("Failed to get stream time: 0x%08x", res);
+ stream_time = GST_CLOCK_TIME_NONE;
+ stream_duration = GST_CLOCK_TIME_NONE;
+ }
+
+ if (m_input->videosrc) {
+ /* FIXME: Avoid circularity between gstdecklink.cpp and
+ * gstdecklinkvideosrc.cpp */
+ res =
+ video_frame->
+ GetTimecode (GST_DECKLINK_VIDEO_SRC (videosrc)->timecode_format,
+ &dtc);
+
+ if (res != S_OK) {
+ GST_DEBUG_OBJECT (videosrc, "Failed to get timecode: 0x%08x", res);
+ dtc = NULL;
+ } else {
+ res = dtc->GetComponents (&hours, &minutes, &seconds, &frames);
+ if (res != S_OK) {
+ GST_ERROR ("Could not get components for timecode %p: 0x%08x", dtc,
+ res);
+ hours = 0;
+ minutes = 0;
+ seconds = 0;
+ frames = 0;
+ bflags = 0;
+ } else {
+ GST_DEBUG_OBJECT (videosrc, "Got timecode %02d:%02d:%02d:%02d",
+ hours, minutes, seconds, frames);
+ bflags = dtc->GetFlags ();
+ }
+ }
+ }
+
got_video_frame (videosrc, video_frame, mode, capture_time,
- capture_duration, (guint8) hours, (guint8) minutes, (guint8) seconds,
- (guint8) frames, bflags);
+ stream_time, stream_duration, (guint8) hours, (guint8) minutes,
+ (guint8) seconds, (guint8) frames, bflags);
}
- no_video_frame:
if (got_audio_packet && audiosrc && audio_packet) {
+ BMDTimeValue packet_time = GST_CLOCK_TIME_NONE;
+
+ res = audio_packet->GetPacketTime (&packet_time, GST_SECOND);
+ if (res != S_OK) {
+ GST_ERROR ("Failed to get stream time: 0x%08x", res);
+ packet_time = GST_CLOCK_TIME_NONE;
+ }
m_input->got_audio_packet (audiosrc, audio_packet, capture_time,
- m_input->audio_discont);
- m_input->audio_discont = FALSE;
+ packet_time);
} else {
- m_input->audio_discont = TRUE;
if (!audio_packet)
GST_DEBUG ("Received no audio packet at %" GST_TIME_FORMAT,
GST_TIME_ARGS (capture_time));
@@ -822,6 +830,7 @@ public:
gst_object_replace ((GstObject **) & videosrc, NULL);
gst_object_replace ((GstObject **) & audiosrc, NULL);
+ gst_object_replace ((GstObject **) & clock, NULL);
return S_OK;
}
@@ -919,9 +928,6 @@ init_devices (gpointer data)
ret);
} else {
devices[i].input.device = decklink;
- devices[i].input.clock = gst_decklink_clock_new ("GstDecklinkInputClock");
- GST_DECKLINK_CLOCK_CAST (devices[i].input.clock)->input =
- &devices[i].input;
devices[i].input.
input->SetCallback (new GStreamerDecklinkInputCallback (&devices[i].
input));
@@ -1073,7 +1079,6 @@ gst_decklink_acquire_nth_input (gint n, GstElement * src, gboolean is_audio)
g_mutex_lock (&input->lock);
if (is_audio && !input->audiosrc) {
input->audiosrc = GST_ELEMENT_CAST (gst_object_ref (src));
- input->audio_discont = TRUE;
g_mutex_unlock (&input->lock);
return input;
} else if (!input->videosrc) {
@@ -1148,88 +1153,46 @@ gst_decklink_clock_get_internal_time (GstClock * clock)
BMDTimeValue time;
HRESULT ret;
- if (self->input != NULL) {
- g_mutex_lock (&self->input->lock);
- start_time = self->input->clock_start_time;
- offset = self->input->clock_offset;
- last_time = self->input->clock_last_time;
- time = -1;
- if (!self->input->started) {
- result = last_time;
- ret = -1;
- } else {
- ret =
- self->input->input->GetHardwareReferenceClock (GST_SECOND, &time,
- NULL, NULL);
- if (ret == S_OK && time >= 0) {
- result = time;
- if (start_time == GST_CLOCK_TIME_NONE)
- start_time = self->input->clock_start_time = result;
-
- if (result > start_time)
- result -= start_time;
- else
- result = 0;
-
- if (self->input->clock_restart) {
- self->input->clock_offset = result - last_time;
- offset = self->input->clock_offset;
- self->input->clock_restart = FALSE;
- }
- result = MAX (last_time, result);
- result -= offset;
- result = MAX (last_time, result);
- } else {
- result = last_time;
+ g_mutex_lock (&self->output->lock);
+ start_time = self->output->clock_start_time;
+ offset = self->output->clock_offset;
+ last_time = self->output->clock_last_time;
+ time = -1;
+ if (!self->output->started) {
+ result = last_time;
+ ret = -1;
+ } else {
+ ret =
+ self->output->output->GetHardwareReferenceClock (GST_SECOND, &time,
+ NULL, NULL);
+ if (ret == S_OK && time >= 0) {
+ result = time;
+
+ if (start_time == GST_CLOCK_TIME_NONE)
+ start_time = self->output->clock_start_time = result;
+
+ if (result > start_time)
+ result -= start_time;
+ else
+ result = 0;
+
+ if (self->output->clock_restart) {
+ self->output->clock_offset = result - last_time;
+ offset = self->output->clock_offset;
+ self->output->clock_restart = FALSE;
}
-
- self->input->clock_last_time = result;
- }
- result += self->input->clock_epoch;
- g_mutex_unlock (&self->input->lock);
- } else if (self->output != NULL) {
- g_mutex_lock (&self->output->lock);
- start_time = self->output->clock_start_time;
- offset = self->output->clock_offset;
- last_time = self->output->clock_last_time;
- time = -1;
- if (!self->output->started) {
- result = last_time;
- ret = -1;
+ result = MAX (last_time, result);
+ result -= offset;
+ result = MAX (last_time, result);
} else {
- ret =
- self->output->output->GetHardwareReferenceClock (GST_SECOND, &time,
- NULL, NULL);
- if (ret == S_OK && time >= 0) {
- result = time;
-
- if (start_time == GST_CLOCK_TIME_NONE)
- start_time = self->output->clock_start_time = result;
-
- if (result > start_time)
- result -= start_time;
- else
- result = 0;
-
- if (self->output->clock_restart) {
- self->output->clock_offset = result - last_time;
- offset = self->output->clock_offset;
- self->output->clock_restart = FALSE;
- }
- result = MAX (last_time, result);
- result -= offset;
- result = MAX (last_time, result);
- } else {
- result = last_time;
- }
-
- self->output->clock_last_time = result;
+ result = last_time;
}
- result += self->output->clock_epoch;
- g_mutex_unlock (&self->output->lock);
- } else {
- g_assert_not_reached ();
+
+ self->output->clock_last_time = result;
}
+ result += self->output->clock_epoch;
+ g_mutex_unlock (&self->output->lock);
+
GST_LOG_OBJECT (clock,
"result %" GST_TIME_FORMAT " time %" GST_TIME_FORMAT " last time %"
GST_TIME_FORMAT " offset %" GST_TIME_FORMAT " start time %"
diff --git a/sys/decklink/gstdecklink.h b/sys/decklink/gstdecklink.h
index 9f95c56ad..40cc9173e 100644
--- a/sys/decklink/gstdecklink.h
+++ b/sys/decklink/gstdecklink.h
@@ -196,25 +196,21 @@ struct _GstDecklinkInput {
IDeckLinkInput *input;
IDeckLinkConfiguration *config;
IDeckLinkAttributes *attributes;
- GstClock *clock;
- GstClockTime clock_start_time, clock_offset, clock_last_time, clock_epoch;
- gboolean started, clock_restart;
/* Everything below protected by mutex */
GMutex lock;
/* Set by the video source */
- void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime capture_duration, guint hours, guint minutes, guint seconds, guint frames, BMDTimecodeFlags bflags);
+ void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime stream_time, GstClockTime stream_duration, guint hours, guint minutes, guint seconds, guint frames, BMDTimecodeFlags bflags);
/* Configured mode or NULL */
const GstDecklinkMode *mode;
BMDPixelFormat format;
/* Set by the audio source */
- void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time, gboolean discont);
+ void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time, GstClockTime packet_time);
GstElement *audiosrc;
gboolean audio_enabled;
- gboolean audio_discont;
GstElement *videosrc;
gboolean video_enabled;
void (*start_streams) (GstElement *videosrc);
diff --git a/sys/decklink/gstdecklinkaudiosrc.cpp b/sys/decklink/gstdecklinkaudiosrc.cpp
index b14c5d469..6f88a9b7b 100644
--- a/sys/decklink/gstdecklinkaudiosrc.cpp
+++ b/sys/decklink/gstdecklinkaudiosrc.cpp
@@ -57,7 +57,6 @@ typedef struct
{
IDeckLinkAudioInputPacket *packet;
GstClockTime capture_time;
- gboolean discont;
} CapturePacket;
static void
@@ -422,27 +421,13 @@ gst_decklink_audio_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
static void
gst_decklink_audio_src_got_packet (GstElement * element,
IDeckLinkAudioInputPacket * packet, GstClockTime capture_time,
- gboolean discont)
+ GstClockTime packet_time)
{
GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (element);
- GstDecklinkVideoSrc *videosrc = NULL;
- GST_LOG_OBJECT (self, "Got audio packet at %" GST_TIME_FORMAT,
- GST_TIME_ARGS (capture_time));
-
- g_mutex_lock (&self->input->lock);
- if (self->input->videosrc)
- videosrc =
- GST_DECKLINK_VIDEO_SRC_CAST (gst_object_ref (self->input->videosrc));
- g_mutex_unlock (&self->input->lock);
-
- if (videosrc) {
- gst_decklink_video_src_convert_to_external_clock (videosrc, &capture_time,
- NULL);
- gst_object_unref (videosrc);
- GST_LOG_OBJECT (self, "Actual timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (capture_time));
- }
+ GST_LOG_OBJECT (self,
+ "Got audio packet at %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (capture_time), GST_TIME_ARGS (packet_time));
g_mutex_lock (&self->lock);
if (!self->flushing) {
@@ -457,8 +442,8 @@ gst_decklink_audio_src_got_packet (GstElement * element,
p = (CapturePacket *) g_malloc0 (sizeof (CapturePacket));
p->packet = packet;
- p->capture_time = capture_time;
- p->discont = discont;
+ p->capture_time =
+ capture_time != GST_CLOCK_TIME_NONE ? capture_time : packet_time;
packet->AddRef ();
g_queue_push_tail (&self->current_packets, p);
g_cond_signal (&self->cond);
@@ -523,7 +508,6 @@ retry:
ap->input->AddRef ();
timestamp = p->capture_time;
- discont = p->discont;
// Jitter and discontinuity handling, based on audiobasesrc
start_time = timestamp;
@@ -538,7 +522,7 @@ retry:
duration = end_time - start_time;
- if (discont || self->next_offset == (guint64) - 1) {
+ if (self->next_offset == (guint64) - 1) {
discont = TRUE;
} else {
guint64 diff, max_sample_diff;
diff --git a/sys/decklink/gstdecklinkvideosink.cpp b/sys/decklink/gstdecklinkvideosink.cpp
index c1c93c8c1..324f86a43 100644
--- a/sys/decklink/gstdecklinkvideosink.cpp
+++ b/sys/decklink/gstdecklinkvideosink.cpp
@@ -955,7 +955,8 @@ gst_decklink_video_sink_change_state (GstElement * element,
gst_decklink_video_sink_stop (self);
break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:{
- if (gst_decklink_video_sink_stop_scheduled_playback (self) == GST_STATE_CHANGE_FAILURE)
+ if (gst_decklink_video_sink_stop_scheduled_playback (self) ==
+ GST_STATE_CHANGE_FAILURE)
ret = GST_STATE_CHANGE_FAILURE;
break;
}
diff --git a/sys/decklink/gstdecklinkvideosrc.cpp b/sys/decklink/gstdecklinkvideosrc.cpp
index cdff18857..054f69dab 100644
--- a/sys/decklink/gstdecklinkvideosrc.cpp
+++ b/sys/decklink/gstdecklinkvideosrc.cpp
@@ -89,7 +89,6 @@ static void gst_decklink_video_src_finalize (GObject * object);
static GstStateChangeReturn
gst_decklink_video_src_change_state (GstElement * element,
GstStateChange transition);
-static GstClock *gst_decklink_video_src_provide_clock (GstElement * element);
static gboolean gst_decklink_video_src_set_caps (GstBaseSrc * bsrc,
GstCaps * caps);
@@ -128,8 +127,6 @@ gst_decklink_video_src_class_init (GstDecklinkVideoSrcClass * klass)
element_class->change_state =
GST_DEBUG_FUNCPTR (gst_decklink_video_src_change_state);
- element_class->provide_clock =
- GST_DEBUG_FUNCPTR (gst_decklink_video_src_provide_clock);
basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_decklink_video_src_get_caps);
basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_decklink_video_src_set_caps);
@@ -434,97 +431,19 @@ gst_decklink_video_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
return caps;
}
-void
-gst_decklink_video_src_convert_to_external_clock (GstDecklinkVideoSrc * self,
- GstClockTime * timestamp, GstClockTime * duration)
-{
- GstClock *clock;
-
- g_assert (timestamp != NULL);
-
- if (*timestamp == GST_CLOCK_TIME_NONE)
- return;
-
- clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
- if (clock && clock != self->input->clock) {
- GstClockTime internal, external, rate_n, rate_d;
- GstClockTimeDiff external_start_time_diff;
-
- gst_clock_get_calibration (self->input->clock, &internal, &external,
- &rate_n, &rate_d);
-
- if (rate_n != rate_d && self->internal_base_time != GST_CLOCK_TIME_NONE) {
- GstClockTime internal_timestamp = *timestamp;
-
- // Convert to the running time corresponding to both clock times
- internal -= self->internal_base_time;
- external -= self->external_base_time;
-
- // Get the difference in the internal time, note
- // that the capture time is internal time.
- // Then scale this difference and offset it to
- // our external time. Now we have the running time
- // according to our external clock.
- //
- // For the duration we just scale
- *timestamp =
- gst_clock_adjust_with_calibration (NULL, internal_timestamp, internal,
- external, rate_n, rate_d);
-
- GST_LOG_OBJECT (self,
- "Converted %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT " (external: %"
- GST_TIME_FORMAT " internal %" GST_TIME_FORMAT " rate: %lf)",
- GST_TIME_ARGS (internal_timestamp), GST_TIME_ARGS (*timestamp),
- GST_TIME_ARGS (external), GST_TIME_ARGS (internal),
- ((gdouble) rate_n) / ((gdouble) rate_d));
-
- if (duration) {
- GstClockTime internal_duration = *duration;
-
- *duration = gst_util_uint64_scale (internal_duration, rate_d, rate_n);
-
- GST_LOG_OBJECT (self,
- "Converted duration %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT
- " (external: %" GST_TIME_FORMAT " internal %" GST_TIME_FORMAT
- " rate: %lf)", GST_TIME_ARGS (internal_duration),
- GST_TIME_ARGS (*duration), GST_TIME_ARGS (external),
- GST_TIME_ARGS (internal), ((gdouble) rate_n) / ((gdouble) rate_d));
- }
- } else {
- GST_LOG_OBJECT (self, "No clock conversion needed, relative rate is 1.0");
- }
-
- // Add the diff between the external time when we
- // went to playing and the external time when the
- // pipeline went to playing. Otherwise we will
- // always start outputting from 0 instead of the
- // current running time.
- external_start_time_diff =
- gst_element_get_base_time (GST_ELEMENT_CAST (self));
- external_start_time_diff =
- self->external_base_time - external_start_time_diff;
- *timestamp += external_start_time_diff;
- } else {
- GST_LOG_OBJECT (self, "No clock conversion needed, same clocks");
- }
-}
-
static void
gst_decklink_video_src_got_frame (GstElement * element,
IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
- GstClockTime capture_time, GstClockTime capture_duration, guint hours,
- guint minutes, guint seconds, guint frames, BMDTimecodeFlags bflags)
+ GstClockTime capture_time, GstClockTime stream_time,
+ GstClockTime stream_duration, guint hours, guint minutes, guint seconds,
+ guint frames, BMDTimecodeFlags bflags)
{
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
- GST_LOG_OBJECT (self, "Got video frame at %" GST_TIME_FORMAT,
- GST_TIME_ARGS (capture_time));
-
- gst_decklink_video_src_convert_to_external_clock (self, &capture_time,
- &capture_duration);
-
- GST_LOG_OBJECT (self, "Actual timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (capture_time));
+ GST_LOG_OBJECT (self,
+ "Got video frame at %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT " (%"
+ GST_TIME_FORMAT ")", GST_TIME_ARGS (capture_time),
+ GST_TIME_ARGS (stream_time), GST_TIME_ARGS (stream_duration));
g_mutex_lock (&self->lock);
if (!self->flushing) {
@@ -542,8 +461,9 @@ gst_decklink_video_src_got_frame (GstElement * element,
f = (CaptureFrame *) g_malloc0 (sizeof (CaptureFrame));
f->frame = frame;
- f->capture_time = capture_time;
- f->capture_duration = capture_duration;
+ f->capture_time =
+ capture_time != GST_CLOCK_TIME_NONE ? capture_time : stream_time;
+ f->capture_duration = stream_duration;
f->mode = mode;
f->format = frame->GetPixelFormat ();
bmode = gst_decklink_get_mode (mode);
@@ -659,7 +579,7 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
vf->input = self->input->input;
vf->input->AddRef ();
- flags = f->frame->GetFlags();
+ flags = f->frame->GetFlags ();
if (flags & bmdFrameHasNoInputSource) {
if (!self->no_signal) {
self->no_signal = TRUE;
@@ -771,10 +691,6 @@ gst_decklink_video_src_open (GstDecklinkVideoSrc * self)
self->input->mode = mode;
self->input->got_video_frame = gst_decklink_video_src_got_frame;
self->input->start_streams = gst_decklink_video_src_start_streams;
- self->input->clock_start_time = GST_CLOCK_TIME_NONE;
- self->input->clock_epoch += self->input->clock_last_time;
- self->input->clock_last_time = 0;
- self->input->clock_offset = 0;
g_mutex_unlock (&self->input->lock);
return TRUE;
@@ -832,42 +748,14 @@ gst_decklink_video_src_start_streams (GstElement * element)
|| self->input->audio_enabled)
&& (GST_STATE (self) == GST_STATE_PLAYING
|| GST_STATE_PENDING (self) == GST_STATE_PLAYING)) {
- GstClock *clock;
-
- clock = gst_element_get_clock (element);
- if (!clock) {
- GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL),
- ("Streams supposed to start but we have no clock"));
- return;
- }
-
GST_DEBUG_OBJECT (self, "Starting streams");
res = self->input->input->StartStreams ();
if (res != S_OK) {
GST_ELEMENT_ERROR (self, STREAM, FAILED,
(NULL), ("Failed to start streams: 0x%08x", res));
- gst_object_unref (clock);
return;
}
-
- self->input->started = TRUE;
- self->input->clock_restart = TRUE;
-
- // Need to unlock to get the clock time
- g_mutex_unlock (&self->input->lock);
-
- // Current times of internal and external clock when we go to
- // playing. We need this to convert the pipeline running time
- // to the running time of the hardware
- //
- // We can't use the normal base time for the external clock
- // because we might go to PLAYING later than the pipeline
- self->internal_base_time = gst_clock_get_internal_time (self->input->clock);
- self->external_base_time = gst_clock_get_internal_time (clock);
-
- gst_object_unref (clock);
- g_mutex_lock (&self->input->lock);
} else {
GST_DEBUG_OBJECT (self, "Not starting streams yet");
}
@@ -893,35 +781,8 @@ gst_decklink_video_src_change_state (GstElement * element,
}
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
- g_mutex_lock (&self->input->lock);
- self->input->clock_start_time = GST_CLOCK_TIME_NONE;
- self->input->clock_epoch += self->input->clock_last_time;
- self->input->clock_last_time = 0;
- self->input->clock_offset = 0;
- g_mutex_unlock (&self->input->lock);
- gst_element_post_message (element,
- gst_message_new_clock_provide (GST_OBJECT_CAST (element),
- self->input->clock, TRUE));
self->flushing = FALSE;
break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
- GstClock *clock;
-
- clock = gst_element_get_clock (GST_ELEMENT_CAST (self));
- if (clock) {
- if (clock != self->input->clock) {
- gst_clock_set_master (self->input->clock, clock);
- }
-
- gst_object_unref (clock);
- } else {
- GST_ELEMENT_ERROR (self, STREAM, FAILED,
- (NULL), ("Need a clock to go to PLAYING"));
- ret = GST_STATE_CHANGE_FAILURE;
- }
-
- break;
- }
default:
break;
}
@@ -934,19 +795,7 @@ gst_decklink_video_src_change_state (GstElement * element,
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_element_post_message (element,
- gst_message_new_clock_lost (GST_OBJECT_CAST (element),
- self->input->clock));
- gst_clock_set_master (self->input->clock, NULL);
- // Reset calibration to make the clock reusable next time we use it
- gst_clock_set_calibration (self->input->clock, 0, 0, 1, 1);
- g_mutex_lock (&self->input->lock);
- self->input->clock_start_time = GST_CLOCK_TIME_NONE;
- self->input->clock_epoch += self->input->clock_last_time;
- self->input->clock_last_time = 0;
- self->input->clock_offset = 0;
self->no_signal = FALSE;
- g_mutex_unlock (&self->input->lock);
gst_decklink_video_src_stop (self);
break;
@@ -954,9 +803,6 @@ gst_decklink_video_src_change_state (GstElement * element,
HRESULT res;
GST_DEBUG_OBJECT (self, "Stopping streams");
- g_mutex_lock (&self->input->lock);
- self->input->started = FALSE;
- g_mutex_unlock (&self->input->lock);
res = self->input->input->StopStreams ();
if (res != S_OK) {
@@ -964,8 +810,6 @@ gst_decklink_video_src_change_state (GstElement * element,
(NULL), ("Failed to stop streams: 0x%08x", res));
ret = GST_STATE_CHANGE_FAILURE;
}
- self->internal_base_time = GST_CLOCK_TIME_NONE;
- self->external_base_time = GST_CLOCK_TIME_NONE;
break;
}
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:{
@@ -986,14 +830,3 @@ out:
return ret;
}
-
-static GstClock *
-gst_decklink_video_src_provide_clock (GstElement * element)
-{
- GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
-
- if (!self->input)
- return NULL;
-
- return GST_CLOCK_CAST (gst_object_ref (self->input->clock));
-}
diff --git a/sys/decklink/gstdecklinkvideosrc.h b/sys/decklink/gstdecklinkvideosrc.h
index 8c7f38a42..f6af21e37 100644
--- a/sys/decklink/gstdecklinkvideosrc.h
+++ b/sys/decklink/gstdecklinkvideosrc.h
@@ -69,9 +69,6 @@ struct _GstDecklinkVideoSrc
gboolean no_signal;
guint buffer_size;
-
- GstClockTime internal_base_time;
- GstClockTime external_base_time;
};
struct _GstDecklinkVideoSrcClass
@@ -80,8 +77,6 @@ struct _GstDecklinkVideoSrcClass
};
GType gst_decklink_video_src_get_type (void);
-void gst_decklink_video_src_convert_to_external_clock (GstDecklinkVideoSrc * self,
- GstClockTime * timestamp, GstClockTime * duration);
G_END_DECLS