flvmux: Add negative runtime DTS support

This is done by using new feature of the CollectPad clip function
which sets the DTS as a gint64 in the collected data. It also simplify
the code a bit.

https://bugzilla.gnome.org/show_bug.cgi?id=740575
This commit is contained in:
Nicolas Dufresne 2015-06-10 18:15:52 -04:00
parent 37e3ca1447
commit 2274ca7d07
2 changed files with 32 additions and 20 deletions

View file

@ -253,7 +253,7 @@ gst_flv_mux_reset (GstElement * element)
mux->have_audio = mux->have_video = FALSE; mux->have_audio = mux->have_video = FALSE;
mux->duration = GST_CLOCK_TIME_NONE; mux->duration = GST_CLOCK_TIME_NONE;
mux->new_tags = FALSE; mux->new_tags = FALSE;
mux->first_timestamp = GST_CLOCK_TIME_NONE; mux->first_timestamp = GST_CLOCK_STIME_NONE;
mux->state = GST_FLV_MUX_STATE_HEADER; mux->state = GST_FLV_MUX_STATE_HEADER;
@ -531,6 +531,8 @@ gst_flv_mux_reset_pad (GstFlvMux * mux, GstFlvPad * cpad, gboolean video)
cpad->video_codec_data = NULL; cpad->video_codec_data = NULL;
cpad->video_codec = G_MAXUINT; cpad->video_codec = G_MAXUINT;
cpad->last_timestamp = 0; cpad->last_timestamp = 0;
cpad->pts = GST_CLOCK_STIME_NONE;
cpad->dts = GST_CLOCK_STIME_NONE;
} }
static GstPad * static GstPad *
@ -1006,25 +1008,21 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
guint8 *data, *bdata; guint8 *data, *bdata;
gsize bsize; gsize bsize;
if (GST_BUFFER_DTS_IS_VALID (buffer)) if (GST_CLOCK_STIME_IS_VALID (cpad->dts)) {
dts = GST_BUFFER_DTS (buffer) / GST_MSECOND; pts = dts = cpad->last_timestamp / GST_MSECOND;
else if (GST_BUFFER_PTS_IS_VALID (buffer)) } else {
dts = GST_BUFFER_PTS (buffer) / GST_MSECOND; pts = cpad->pts / GST_MSECOND;
else dts = cpad->dts / GST_MSECOND;
dts = cpad->last_timestamp / GST_MSECOND; }
if (GST_BUFFER_PTS_IS_VALID (buffer))
pts = GST_BUFFER_PTS (buffer) / GST_MSECOND;
else
pts = dts;
/* Be safe in case TS are buggy */
if (pts > dts) if (pts > dts)
cts = pts - dts; cts = pts - dts;
else else
cts = 0; cts = 0;
/* Timestamp must start at zero */ /* Timestamp must start at zero */
if (GST_CLOCK_TIME_IS_VALID (mux->first_timestamp)) { if (GST_CLOCK_STIME_IS_VALID (mux->first_timestamp)) {
dts -= mux->first_timestamp / GST_MSECOND; dts -= mux->first_timestamp / GST_MSECOND;
pts = dts + cts; pts = dts + cts;
} }
@ -1490,7 +1488,7 @@ gst_flv_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
{ {
GstFlvMux *mux = GST_FLV_MUX (user_data); GstFlvMux *mux = GST_FLV_MUX (user_data);
GstFlvPad *best; GstFlvPad *best;
GstClockTime best_time; gint64 best_time;
GstFlowReturn ret; GstFlowReturn ret;
if (mux->state == GST_FLV_MUX_STATE_HEADER) { if (mux->state == GST_FLV_MUX_STATE_HEADER) {
@ -1505,8 +1503,8 @@ gst_flv_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
return ret; return ret;
mux->state = GST_FLV_MUX_STATE_DATA; mux->state = GST_FLV_MUX_STATE_DATA;
if (GST_BUFFER_DTS_IS_VALID (buffer)) if (GST_COLLECT_PADS_DTS_IS_VALID (cdata))
mux->first_timestamp = GST_BUFFER_DTS (buffer); mux->first_timestamp = GST_COLLECT_PADS_DTS (cdata);
else else
mux->first_timestamp = 0; mux->first_timestamp = 0;
} }
@ -1521,15 +1519,27 @@ gst_flv_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
best = (GstFlvPad *) cdata; best = (GstFlvPad *) cdata;
if (best) { if (best) {
g_assert (buffer); g_assert (buffer);
best_time = GST_BUFFER_DTS (buffer); best->dts = GST_COLLECT_PADS_DTS (cdata);
if (GST_CLOCK_STIME_IS_VALID (best->dts))
best_time = best->dts - mux->first_timestamp;
if (GST_BUFFER_PTS_IS_VALID (buffer))
best->pts = GST_BUFFER_PTS (buffer);
else
best->pts = best->dts;
GST_LOG_OBJECT (mux, "got buffer PTS %" GST_TIME_FORMAT " DTS %"
GST_STIME_FORMAT "\n", GST_TIME_ARGS (best->pts),
GST_STIME_ARGS (best->dts));
} else { } else {
best_time = GST_CLOCK_TIME_NONE; best_time = GST_CLOCK_STIME_NONE;
} }
/* The FLV timestamp is an int32 field. For non-live streams error out if a /* The FLV timestamp is an int32 field. For non-live streams error out if a
bigger timestamp is seen, for live the timestamp will get wrapped in bigger timestamp is seen, for live the timestamp will get wrapped in
gst_flv_mux_buffer_to_tag */ gst_flv_mux_buffer_to_tag */
if (!mux->streamable && GST_CLOCK_TIME_IS_VALID (best_time) if (!mux->streamable && (GST_CLOCK_STIME_IS_VALID (best_time))
&& best_time / GST_MSECOND > G_MAXINT32) { && best_time / GST_MSECOND > G_MAXINT32) {
GST_WARNING_OBJECT (mux, "Timestamp larger than FLV supports - EOS"); GST_WARNING_OBJECT (mux, "Timestamp larger than FLV supports - EOS");
gst_buffer_unref (buffer); gst_buffer_unref (buffer);

View file

@ -53,6 +53,8 @@ typedef struct
GstBuffer *video_codec_data; GstBuffer *video_codec_data;
GstClockTime last_timestamp; GstClockTime last_timestamp;
gint64 pts;
gint64 dts;
} GstFlvPad; } GstFlvPad;
typedef enum typedef enum
@ -78,7 +80,7 @@ typedef struct _GstFlvMux {
GList *index; GList *index;
guint64 byte_count; guint64 byte_count;
guint64 duration; guint64 duration;
GstClockTime first_timestamp; gint64 first_timestamp;
} GstFlvMux; } GstFlvMux;
typedef struct _GstFlvMuxClass { typedef struct _GstFlvMuxClass {