decklinksrc: Sample the pipeline clock for the timestamps instead of coming up with our own

If we just count the frames and calculate timestamps from that, all frames
will arrive late in the sink as we have a live source here. Instead take
the pipeline clock at capture time as reference.
This commit is contained in:
Sebastian Dröge 2014-11-14 10:38:33 +01:00
parent ee8766b342
commit 50c4ea54f6
3 changed files with 35 additions and 11 deletions

View file

@ -78,6 +78,8 @@ HRESULT
videoFrame, IDeckLinkAudioInputPacket * audioFrame)
{
GstDecklinkSrc *decklinksrc;
GstClock *clock;
GstClockTime base_time, clock_time, capture_time;
const char *timecodeString = NULL;
g_return_val_if_fail (priv != NULL, S_OK);
@ -109,9 +111,32 @@ HRESULT
}
}
GST_DEBUG_OBJECT (decklinksrc, "Frame received [%s] - %s - Size: %li bytes",
timecodeString != NULL ? timecodeString : "No timecode",
"Valid Frame", videoFrame->GetRowBytes () * videoFrame->GetHeight ());
GST_OBJECT_LOCK (decklinksrc);
if ((clock = GST_ELEMENT_CLOCK (decklinksrc))) {
base_time = GST_ELEMENT (decklinksrc)->base_time;
gst_object_ref (clock);
} else {
base_time = GST_CLOCK_TIME_NONE;
}
GST_OBJECT_UNLOCK (decklinksrc);
if (clock) {
clock_time = gst_clock_get_time (clock);
gst_object_unref (clock);
} else {
clock_time = GST_CLOCK_TIME_NONE;
}
if (base_time != GST_CLOCK_TIME_NONE) {
capture_time = clock_time - base_time;
} else {
capture_time = GST_CLOCK_TIME_NONE;
}
GST_DEBUG_OBJECT (decklinksrc,
"Frame received [%s] - %s - %" GST_TIME_FORMAT "Size: %li bytes",
timecodeString != NULL ? timecodeString : "No timecode", "Valid Frame",
GST_TIME_ARGS (capture_time),
videoFrame->GetRowBytes () * videoFrame->GetHeight ());
if (timecodeString)
FREE_COM_STRING (timecodeString);
@ -130,6 +155,7 @@ HRESULT
audioFrame->AddRef ();
decklinksrc->audio_frame = audioFrame;
}
decklinksrc->capture_time = capture_time;
/* increment regardless whether frame was dropped or not */
decklinksrc->frame_num++;

View file

@ -756,6 +756,7 @@ gst_decklink_src_task (void *priv)
GstFlowReturn video_flow, audio_flow, flow;
const GstDecklinkMode *mode;
gboolean discont = FALSE;
GstClockTime capture_time;
GST_DEBUG_OBJECT (decklinksrc, "task");
@ -766,6 +767,7 @@ gst_decklink_src_task (void *priv)
}
video_frame = decklinksrc->video_frame;
audio_frame = decklinksrc->audio_frame;
capture_time = decklinksrc->capture_time;
decklinksrc->video_frame = NULL;
decklinksrc->audio_frame = NULL;
g_mutex_unlock (&decklinksrc->mutex);
@ -846,12 +848,9 @@ gst_decklink_src_task (void *priv)
vf->input->AddRef ();
}
GST_BUFFER_TIMESTAMP (buffer) =
gst_util_uint64_scale_int (decklinksrc->frame_num * GST_SECOND,
GST_BUFFER_TIMESTAMP (buffer) = capture_time;
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (GST_SECOND,
mode->fps_d, mode->fps_n);
GST_BUFFER_DURATION (buffer) =
gst_util_uint64_scale_int ((decklinksrc->frame_num + 1) * GST_SECOND,
mode->fps_d, mode->fps_n) - GST_BUFFER_TIMESTAMP (buffer);
GST_BUFFER_OFFSET (buffer) = decklinksrc->frame_num;
GST_BUFFER_OFFSET_END (buffer) = decklinksrc->frame_num; /* FIXME: +1? */
@ -873,9 +872,7 @@ gst_decklink_src_task (void *priv)
audio_buffer = gst_buffer_new_and_alloc (n_samples * 2 * 2);
gst_buffer_fill (audio_buffer, 0, data, n_samples * 2 * 2);
GST_BUFFER_TIMESTAMP (audio_buffer) =
gst_util_uint64_scale_int (decklinksrc->num_audio_samples * GST_SECOND,
1, 48000);
GST_BUFFER_TIMESTAMP (audio_buffer) = capture_time;
/* FIXME: should be next_timestamp - timestamp for perfect stream */
GST_BUFFER_DURATION (audio_buffer) =
gst_util_uint64_scale_int (n_samples * GST_SECOND, 1, 48000);

View file

@ -60,6 +60,7 @@ struct _GstDecklinkSrc
int dropped_frames;
int dropped_frames_old;
gboolean stop;
GstClockTime capture_time;
IDeckLinkVideoInputFrame *video_frame;
IDeckLinkAudioInputPacket * audio_frame;