From 350c56dab4dc80931fc5d645c7c764ee309387cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 28 Sep 2017 13:55:18 +0300 Subject: [PATCH] decklinkaudio/videosrc: Put hardware reference timestamp in a reference timestamp meta This can be useful to know on multi-channel cards which frames from different channels were captured at the same time. --- sys/decklink/gstdecklink.cpp | 23 +++++++++++++++++++---- sys/decklink/gstdecklink.h | 4 ++-- sys/decklink/gstdecklinkaudiosrc.cpp | 13 ++++++++++++- sys/decklink/gstdecklinkvideosrc.cpp | 12 +++++++++++- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/sys/decklink/gstdecklink.cpp b/sys/decklink/gstdecklink.cpp index 79a209623a..f47f696364 100644 --- a/sys/decklink/gstdecklink.cpp +++ b/sys/decklink/gstdecklink.cpp @@ -809,11 +809,13 @@ public: void (*got_video_frame) (GstElement * videosrc, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime stream_time, - GstClockTime stream_duration, IDeckLinkTimecode * dtc, gboolean - no_signal) = NULL; + GstClockTime stream_duration, GstClockTime hardware_time, + GstClockTime hardware_duration, IDeckLinkTimecode * dtc, + gboolean no_signal) = NULL; void (*got_audio_packet) (GstElement * videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time, GstClockTime stream_time, GstClockTime stream_duration, + GstClockTime hardware_time, GstClockTime hardware_duration, gboolean no_signal) = NULL; GstDecklinkModeEnum mode; GstClockTime capture_time = GST_CLOCK_TIME_NONE; @@ -823,6 +825,8 @@ public: HRESULT res; BMDTimeValue stream_time = GST_CLOCK_TIME_NONE; BMDTimeValue stream_duration = GST_CLOCK_TIME_NONE; + BMDTimeValue hardware_time = GST_CLOCK_TIME_NONE; + BMDTimeValue hardware_duration = GST_CLOCK_TIME_NONE; g_mutex_lock (&m_input->lock); if (m_input->videosrc) { @@ -872,6 +876,15 @@ public: stream_duration = GST_CLOCK_TIME_NONE; } + res = + video_frame->GetHardwareReferenceTimestamp (GST_SECOND, + &hardware_time, &hardware_duration); + if (res != S_OK) { + GST_ERROR ("Failed to get hardware time: 0x%08lx", (unsigned long) res); + hardware_time = GST_CLOCK_TIME_NONE; + hardware_duration = GST_CLOCK_TIME_NONE; + } + if (m_input->videosrc) { /* FIXME: Avoid circularity between gstdecklink.cpp and * gstdecklinkvideosrc.cpp */ @@ -889,12 +902,14 @@ public: /* passing dtc reference */ got_video_frame (videosrc, video_frame, mode, capture_time, - stream_time, stream_duration, dtc, no_signal); + stream_time, stream_duration, hardware_time, hardware_duration, dtc, + no_signal); } if (got_audio_packet && audiosrc && audio_packet) { m_input->got_audio_packet (audiosrc, audio_packet, capture_time, - stream_time, stream_duration, no_signal); + stream_time, stream_duration, hardware_time, hardware_duration, + no_signal); } else { if (!audio_packet) GST_DEBUG ("Received no audio packet at %" GST_TIME_FORMAT, diff --git a/sys/decklink/gstdecklink.h b/sys/decklink/gstdecklink.h index 3bcf72fa28..817358ae62 100644 --- a/sys/decklink/gstdecklink.h +++ b/sys/decklink/gstdecklink.h @@ -242,13 +242,13 @@ struct _GstDecklinkInput { GMutex lock; /* Set by the video source */ - void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime stream_time, GstClockTime stream_duration, IDeckLinkTimecode *dtc, gboolean no_signal); + void (*got_video_frame) (GstElement *videosrc, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime stream_time, GstClockTime stream_duration, GstClockTime hardware_time, GstClockTime hardware_duration, IDeckLinkTimecode *dtc, gboolean no_signal); /* 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, GstClockTime stream_time, GstClockTime stream_duration, gboolean no_signal); + void (*got_audio_packet) (GstElement *videosrc, IDeckLinkAudioInputPacket * packet, GstClockTime capture_time, GstClockTime stream_time, GstClockTime stream_duration, GstClockTime hardware_time, GstClockTime hardware_duration, gboolean no_signal); GstElement *audiosrc; gboolean audio_enabled; diff --git a/sys/decklink/gstdecklinkaudiosrc.cpp b/sys/decklink/gstdecklinkaudiosrc.cpp index 7aa642f0ff..2b63036ab4 100644 --- a/sys/decklink/gstdecklinkaudiosrc.cpp +++ b/sys/decklink/gstdecklinkaudiosrc.cpp @@ -63,6 +63,8 @@ typedef struct GstClockTime timestamp; GstClockTime stream_timestamp; GstClockTime stream_duration; + GstClockTime hardware_timestamp; + GstClockTime hardware_duration; gboolean no_signal; } CapturePacket; @@ -471,7 +473,9 @@ 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, - GstClockTime stream_time, GstClockTime stream_duration, gboolean no_signal) + GstClockTime stream_time, GstClockTime stream_duration, + GstClockTime hardware_time, GstClockTime hardware_duration, + gboolean no_signal) { GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (element); GstClockTime timestamp; @@ -537,6 +541,8 @@ gst_decklink_audio_src_got_packet (GstElement * element, p.timestamp = timestamp; p.stream_timestamp = stream_time; p.stream_duration = stream_duration; + p.hardware_timestamp = hardware_time; + p.hardware_duration = hardware_duration; p.no_signal = no_signal; packet->AddRef (); gst_queue_array_push_tail_struct (self->current_packets, &p); @@ -561,6 +567,8 @@ gst_decklink_audio_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) gboolean discont = FALSE; static GstStaticCaps stream_reference = GST_STATIC_CAPS ("timestamp/x-decklink-stream"); + static GstStaticCaps hardware_reference = + GST_STATIC_CAPS ("timestamp/x-decklink-hardware"); retry: g_mutex_lock (&self->lock); @@ -678,6 +686,9 @@ retry: gst_buffer_add_reference_timestamp_meta (*buffer, gst_static_caps_get (&stream_reference), p.stream_timestamp, p.stream_duration); + gst_buffer_add_reference_timestamp_meta (*buffer, + gst_static_caps_get (&hardware_reference), p.hardware_timestamp, + p.hardware_duration); GST_DEBUG_OBJECT (self, "Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %" diff --git a/sys/decklink/gstdecklinkvideosrc.cpp b/sys/decklink/gstdecklinkvideosrc.cpp index 8978143eea..5486d191ce 100644 --- a/sys/decklink/gstdecklinkvideosrc.cpp +++ b/sys/decklink/gstdecklinkvideosrc.cpp @@ -57,6 +57,8 @@ typedef struct GstClockTime timestamp, duration; GstClockTime stream_timestamp; GstClockTime stream_duration; + GstClockTime hardware_timestamp; + GstClockTime hardware_duration; GstDecklinkModeEnum mode; BMDPixelFormat format; GstVideoTimeCode *tc; @@ -626,7 +628,8 @@ static void gst_decklink_video_src_got_frame (GstElement * element, IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode, GstClockTime capture_time, GstClockTime stream_time, - GstClockTime stream_duration, IDeckLinkTimecode * dtc, gboolean no_signal) + GstClockTime stream_duration, GstClockTime hardware_time, + GstClockTime hardware_duration, IDeckLinkTimecode * dtc, gboolean no_signal) { GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element); GstClockTime timestamp, duration; @@ -692,6 +695,8 @@ gst_decklink_video_src_got_frame (GstElement * element, f.duration = duration; f.stream_timestamp = stream_time; f.stream_duration = stream_duration; + f.hardware_timestamp = hardware_time; + f.hardware_duration = hardware_duration; f.mode = mode; f.format = frame->GetPixelFormat (); f.no_signal = no_signal; @@ -753,6 +758,8 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) const GstDecklinkMode *mode; static GstStaticCaps stream_reference = GST_STATIC_CAPS ("timestamp/x-decklink-stream"); + static GstStaticCaps hardware_reference = + GST_STATIC_CAPS ("timestamp/x-decklink-hardware"); g_mutex_lock (&self->lock); while (gst_queue_array_is_empty (self->current_frames) && !self->flushing) { @@ -853,6 +860,9 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer) gst_buffer_add_reference_timestamp_meta (*buffer, gst_static_caps_get (&stream_reference), f.stream_timestamp, f.stream_duration); + gst_buffer_add_reference_timestamp_meta (*buffer, + gst_static_caps_get (&hardware_reference), f.hardware_timestamp, + f.hardware_duration); mode = gst_decklink_get_mode (self->mode); if (mode->interlaced && mode->tff)