Unverified Commit 3ffbecf4 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #6034 from bluerobotics/video-timestamps

Correct video file timestamping issues
parents a088a330 54cbb2ed
...@@ -674,6 +674,14 @@ VideoReceiver::startRecording(const QString &videoFile) ...@@ -674,6 +674,14 @@ VideoReceiver::startRecording(const QString &videoFile)
gst_element_sync_state_with_parent(_sink->mux); gst_element_sync_state_with_parent(_sink->mux);
gst_element_sync_state_with_parent(_sink->filesink); gst_element_sync_state_with_parent(_sink->filesink);
// Install a probe on the recording branch to drop buffers until we hit our first keyframe
// When we hit our first keyframe, we can offset the timestamps appropriately according to the first keyframe time
// This will ensure the first frame is a keyframe at t=0, and decoding can begin immediately on playback
GstPad* probepad = gst_element_get_static_pad(_sink->queue, "src");
gst_pad_add_probe(probepad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER /* | GST_PAD_PROBE_TYPE_BLOCK */), _keyframeWatch, this, NULL); // to drop the buffer or to block the buffer?
gst_object_unref(probepad);
// Link the recording branch to the pipeline
GstPad* sinkpad = gst_element_get_static_pad(_sink->queue, "sink"); GstPad* sinkpad = gst_element_get_static_pad(_sink->queue, "sink");
gst_pad_link(_sink->teepad, sinkpad); gst_pad_link(_sink->teepad, sinkpad);
gst_object_unref(sinkpad); gst_object_unref(sinkpad);
...@@ -802,6 +810,33 @@ VideoReceiver::_unlinkCallBack(GstPad* pad, GstPadProbeInfo* info, gpointer user ...@@ -802,6 +810,33 @@ VideoReceiver::_unlinkCallBack(GstPad* pad, GstPadProbeInfo* info, gpointer user
} }
#endif #endif
//-----------------------------------------------------------------------------
#if defined(QGC_GST_STREAMING)
GstPadProbeReturn
VideoReceiver::_keyframeWatch(GstPad* pad, GstPadProbeInfo* info, gpointer user_data)
{
Q_UNUSED(pad);
if(info != NULL && user_data != NULL) {
GstBuffer* buf = gst_pad_probe_info_get_buffer(info);
if(GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DELTA_UNIT)) { // wait for a keyframe
return GST_PAD_PROBE_DROP;
} else {
VideoReceiver* pThis = (VideoReceiver*)user_data;
// reset the clock
GstClock* clock = gst_pipeline_get_clock(GST_PIPELINE(pThis->_pipeline));
GstClockTime time = gst_clock_get_time(clock);
gst_object_unref(clock);
gst_element_set_base_time(pThis->_pipeline, time); // offset pipeline timestamps to start at zero again
buf->dts = 0; // The offset will not apply to this current buffer, our first frame, timestamp is zero
buf->pts = 0;
qCDebug(VideoReceiverLog) << "Got keyframe, stop dropping buffers";
}
}
return GST_PAD_PROBE_REMOVE;
}
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
VideoReceiver::_updateTimer() VideoReceiver::_updateTimer()
......
...@@ -119,6 +119,7 @@ private: ...@@ -119,6 +119,7 @@ private:
static gboolean _onBusMessage (GstBus* bus, GstMessage* message, gpointer user_data); static gboolean _onBusMessage (GstBus* bus, GstMessage* message, gpointer user_data);
static GstPadProbeReturn _unlinkCallBack (GstPad* pad, GstPadProbeInfo* info, gpointer user_data); static GstPadProbeReturn _unlinkCallBack (GstPad* pad, GstPadProbeInfo* info, gpointer user_data);
static GstPadProbeReturn _keyframeWatch (GstPad* pad, GstPadProbeInfo* info, gpointer user_data);
void _detachRecordingBranch (GstPadProbeInfo* info); void _detachRecordingBranch (GstPadProbeInfo* info);
void _shutdownRecordingBranch(); void _shutdownRecordingBranch();
void _shutdownPipeline (); void _shutdownPipeline ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment