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.
This commit is contained in:
Sebastian Dröge 2017-09-28 13:55:18 +03:00
parent 4b051ea36d
commit 350c56dab4
4 changed files with 44 additions and 8 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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 %"

View file

@ -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)