mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-06 02:32:23 +00:00
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:
parent
4b051ea36d
commit
350c56dab4
4 changed files with 44 additions and 8 deletions
|
@ -809,11 +809,13 @@ public:
|
||||||
void (*got_video_frame) (GstElement * videosrc,
|
void (*got_video_frame) (GstElement * videosrc,
|
||||||
IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
|
IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
|
||||||
GstClockTime capture_time, GstClockTime stream_time,
|
GstClockTime capture_time, GstClockTime stream_time,
|
||||||
GstClockTime stream_duration, IDeckLinkTimecode * dtc, gboolean
|
GstClockTime stream_duration, GstClockTime hardware_time,
|
||||||
no_signal) = NULL;
|
GstClockTime hardware_duration, IDeckLinkTimecode * dtc,
|
||||||
|
gboolean no_signal) = NULL;
|
||||||
void (*got_audio_packet) (GstElement * videosrc,
|
void (*got_audio_packet) (GstElement * videosrc,
|
||||||
IDeckLinkAudioInputPacket * packet, GstClockTime capture_time,
|
IDeckLinkAudioInputPacket * packet, GstClockTime capture_time,
|
||||||
GstClockTime stream_time, GstClockTime stream_duration,
|
GstClockTime stream_time, GstClockTime stream_duration,
|
||||||
|
GstClockTime hardware_time, GstClockTime hardware_duration,
|
||||||
gboolean no_signal) = NULL;
|
gboolean no_signal) = NULL;
|
||||||
GstDecklinkModeEnum mode;
|
GstDecklinkModeEnum mode;
|
||||||
GstClockTime capture_time = GST_CLOCK_TIME_NONE;
|
GstClockTime capture_time = GST_CLOCK_TIME_NONE;
|
||||||
|
@ -823,6 +825,8 @@ public:
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
BMDTimeValue stream_time = GST_CLOCK_TIME_NONE;
|
BMDTimeValue stream_time = GST_CLOCK_TIME_NONE;
|
||||||
BMDTimeValue stream_duration = 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);
|
g_mutex_lock (&m_input->lock);
|
||||||
if (m_input->videosrc) {
|
if (m_input->videosrc) {
|
||||||
|
@ -872,6 +876,15 @@ public:
|
||||||
stream_duration = GST_CLOCK_TIME_NONE;
|
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) {
|
if (m_input->videosrc) {
|
||||||
/* FIXME: Avoid circularity between gstdecklink.cpp and
|
/* FIXME: Avoid circularity between gstdecklink.cpp and
|
||||||
* gstdecklinkvideosrc.cpp */
|
* gstdecklinkvideosrc.cpp */
|
||||||
|
@ -889,12 +902,14 @@ public:
|
||||||
|
|
||||||
/* passing dtc reference */
|
/* passing dtc reference */
|
||||||
got_video_frame (videosrc, video_frame, mode, capture_time,
|
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) {
|
if (got_audio_packet && audiosrc && audio_packet) {
|
||||||
m_input->got_audio_packet (audiosrc, audio_packet, capture_time,
|
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 {
|
} else {
|
||||||
if (!audio_packet)
|
if (!audio_packet)
|
||||||
GST_DEBUG ("Received no audio packet at %" GST_TIME_FORMAT,
|
GST_DEBUG ("Received no audio packet at %" GST_TIME_FORMAT,
|
||||||
|
|
|
@ -242,13 +242,13 @@ struct _GstDecklinkInput {
|
||||||
GMutex lock;
|
GMutex lock;
|
||||||
|
|
||||||
/* Set by the video source */
|
/* 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 */
|
/* Configured mode or NULL */
|
||||||
const GstDecklinkMode *mode;
|
const GstDecklinkMode *mode;
|
||||||
BMDPixelFormat format;
|
BMDPixelFormat format;
|
||||||
|
|
||||||
/* Set by the audio source */
|
/* 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;
|
GstElement *audiosrc;
|
||||||
gboolean audio_enabled;
|
gboolean audio_enabled;
|
||||||
|
|
|
@ -63,6 +63,8 @@ typedef struct
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
GstClockTime stream_timestamp;
|
GstClockTime stream_timestamp;
|
||||||
GstClockTime stream_duration;
|
GstClockTime stream_duration;
|
||||||
|
GstClockTime hardware_timestamp;
|
||||||
|
GstClockTime hardware_duration;
|
||||||
gboolean no_signal;
|
gboolean no_signal;
|
||||||
} CapturePacket;
|
} CapturePacket;
|
||||||
|
|
||||||
|
@ -471,7 +473,9 @@ gst_decklink_audio_src_get_caps (GstBaseSrc * bsrc, GstCaps * filter)
|
||||||
static void
|
static void
|
||||||
gst_decklink_audio_src_got_packet (GstElement * element,
|
gst_decklink_audio_src_got_packet (GstElement * element,
|
||||||
IDeckLinkAudioInputPacket * packet, GstClockTime capture_time,
|
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);
|
GstDecklinkAudioSrc *self = GST_DECKLINK_AUDIO_SRC_CAST (element);
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
|
@ -537,6 +541,8 @@ gst_decklink_audio_src_got_packet (GstElement * element,
|
||||||
p.timestamp = timestamp;
|
p.timestamp = timestamp;
|
||||||
p.stream_timestamp = stream_time;
|
p.stream_timestamp = stream_time;
|
||||||
p.stream_duration = stream_duration;
|
p.stream_duration = stream_duration;
|
||||||
|
p.hardware_timestamp = hardware_time;
|
||||||
|
p.hardware_duration = hardware_duration;
|
||||||
p.no_signal = no_signal;
|
p.no_signal = no_signal;
|
||||||
packet->AddRef ();
|
packet->AddRef ();
|
||||||
gst_queue_array_push_tail_struct (self->current_packets, &p);
|
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;
|
gboolean discont = FALSE;
|
||||||
static GstStaticCaps stream_reference =
|
static GstStaticCaps stream_reference =
|
||||||
GST_STATIC_CAPS ("timestamp/x-decklink-stream");
|
GST_STATIC_CAPS ("timestamp/x-decklink-stream");
|
||||||
|
static GstStaticCaps hardware_reference =
|
||||||
|
GST_STATIC_CAPS ("timestamp/x-decklink-hardware");
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
g_mutex_lock (&self->lock);
|
g_mutex_lock (&self->lock);
|
||||||
|
@ -678,6 +686,9 @@ retry:
|
||||||
gst_buffer_add_reference_timestamp_meta (*buffer,
|
gst_buffer_add_reference_timestamp_meta (*buffer,
|
||||||
gst_static_caps_get (&stream_reference), p.stream_timestamp,
|
gst_static_caps_get (&stream_reference), p.stream_timestamp,
|
||||||
p.stream_duration);
|
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,
|
GST_DEBUG_OBJECT (self,
|
||||||
"Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %"
|
"Outputting buffer %p with timestamp %" GST_TIME_FORMAT " and duration %"
|
||||||
|
|
|
@ -57,6 +57,8 @@ typedef struct
|
||||||
GstClockTime timestamp, duration;
|
GstClockTime timestamp, duration;
|
||||||
GstClockTime stream_timestamp;
|
GstClockTime stream_timestamp;
|
||||||
GstClockTime stream_duration;
|
GstClockTime stream_duration;
|
||||||
|
GstClockTime hardware_timestamp;
|
||||||
|
GstClockTime hardware_duration;
|
||||||
GstDecklinkModeEnum mode;
|
GstDecklinkModeEnum mode;
|
||||||
BMDPixelFormat format;
|
BMDPixelFormat format;
|
||||||
GstVideoTimeCode *tc;
|
GstVideoTimeCode *tc;
|
||||||
|
@ -626,7 +628,8 @@ static void
|
||||||
gst_decklink_video_src_got_frame (GstElement * element,
|
gst_decklink_video_src_got_frame (GstElement * element,
|
||||||
IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
|
IDeckLinkVideoInputFrame * frame, GstDecklinkModeEnum mode,
|
||||||
GstClockTime capture_time, GstClockTime stream_time,
|
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);
|
GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
|
||||||
GstClockTime timestamp, duration;
|
GstClockTime timestamp, duration;
|
||||||
|
@ -692,6 +695,8 @@ gst_decklink_video_src_got_frame (GstElement * element,
|
||||||
f.duration = duration;
|
f.duration = duration;
|
||||||
f.stream_timestamp = stream_time;
|
f.stream_timestamp = stream_time;
|
||||||
f.stream_duration = stream_duration;
|
f.stream_duration = stream_duration;
|
||||||
|
f.hardware_timestamp = hardware_time;
|
||||||
|
f.hardware_duration = hardware_duration;
|
||||||
f.mode = mode;
|
f.mode = mode;
|
||||||
f.format = frame->GetPixelFormat ();
|
f.format = frame->GetPixelFormat ();
|
||||||
f.no_signal = no_signal;
|
f.no_signal = no_signal;
|
||||||
|
@ -753,6 +758,8 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
|
||||||
const GstDecklinkMode *mode;
|
const GstDecklinkMode *mode;
|
||||||
static GstStaticCaps stream_reference =
|
static GstStaticCaps stream_reference =
|
||||||
GST_STATIC_CAPS ("timestamp/x-decklink-stream");
|
GST_STATIC_CAPS ("timestamp/x-decklink-stream");
|
||||||
|
static GstStaticCaps hardware_reference =
|
||||||
|
GST_STATIC_CAPS ("timestamp/x-decklink-hardware");
|
||||||
|
|
||||||
g_mutex_lock (&self->lock);
|
g_mutex_lock (&self->lock);
|
||||||
while (gst_queue_array_is_empty (self->current_frames) && !self->flushing) {
|
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_buffer_add_reference_timestamp_meta (*buffer,
|
||||||
gst_static_caps_get (&stream_reference), f.stream_timestamp,
|
gst_static_caps_get (&stream_reference), f.stream_timestamp,
|
||||||
f.stream_duration);
|
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);
|
mode = gst_decklink_get_mode (self->mode);
|
||||||
if (mode->interlaced && mode->tff)
|
if (mode->interlaced && mode->tff)
|
||||||
|
|
Loading…
Reference in a new issue