flvmux: Insert AVC end of sequence

This FLV specific mark is needed to prevent Flow Player (most likely
all Flash base player) from going into buffering state when near EOS.

https://bugzilla.gnome.org/show_bug.cgi?id=751320
This commit is contained in:
Nicolas Dufresne 2015-06-22 14:35:52 -04:00
parent 9a1ed36b7a
commit bbea34bb6e

View file

@ -1005,8 +1005,8 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
GstMapInfo map;
guint size;
guint32 pts, dts, cts;
guint8 *data, *bdata;
gsize bsize;
guint8 *data, *bdata = NULL;
gsize bsize = 0;
if (!GST_CLOCK_STIME_IS_VALID (cpad->dts)) {
pts = dts = cpad->last_timestamp / GST_MSECOND;
@ -1029,9 +1029,11 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
GST_LOG_OBJECT (mux, "got pts %i dts %i cts %i\n", pts, dts, cts);
if (buffer != NULL) {
gst_buffer_map (buffer, &map, GST_MAP_READ);
bdata = map.data;
bsize = map.size;
}
size = 11;
if (cpad->video) {
@ -1064,7 +1066,7 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
data[8] = data[9] = data[10] = 0;
if (cpad->video) {
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT))
if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT))
data[11] |= 2 << 4;
else
data[11] |= 1 << 4;
@ -1075,6 +1077,10 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
if (is_codec_data) {
data[12] = 0;
GST_WRITE_UINT24_BE (data + 13, 0);
} else if (bsize == 0) {
/* AVC end of sequence */
data[12] = 2;
GST_WRITE_UINT24_BE (data + 13, 0);
} else {
/* ACV NALU */
data[12] = 1;
@ -1099,6 +1105,7 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
}
}
if (buffer)
gst_buffer_unmap (buffer, &map);
GST_WRITE_UINT32_BE (data + size - 4, size - 4);
@ -1106,6 +1113,8 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
GST_BUFFER_PTS (tag) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DTS (tag) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION (tag) = GST_CLOCK_TIME_NONE;
if (buffer) {
GST_BUFFER_OFFSET (tag) = GST_BUFFER_OFFSET (buffer);
GST_BUFFER_OFFSET_END (tag) = GST_BUFFER_OFFSET_END (buffer);
@ -1114,9 +1123,11 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
if ((mux->have_video && !cpad->video) ||
GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT))
GST_BUFFER_FLAG_SET (tag, GST_BUFFER_FLAG_DELTA_UNIT);
} else {
GST_BUFFER_FLAG_SET (tag, GST_BUFFER_FLAG_DELTA_UNIT);
GST_BUFFER_OFFSET (tag) = GST_BUFFER_OFFSET_END (tag) =
GST_BUFFER_OFFSET_NONE;
}
return tag;
}
@ -1135,6 +1146,12 @@ gst_flv_mux_codec_data_buffer_to_tag (GstFlvMux * mux, GstBuffer * buffer,
return gst_flv_mux_buffer_to_tag_internal (mux, buffer, cpad, TRUE);
}
static inline GstBuffer *
gst_flv_mux_eos_to_tag (GstFlvMux * mux, GstFlvPad * cpad)
{
return gst_flv_mux_buffer_to_tag_internal (mux, NULL, cpad, FALSE);
}
static void
gst_flv_mux_put_buffer_in_streamheader (GValue * streamheader,
GstBuffer * buffer)
@ -1344,6 +1361,29 @@ gst_flv_mux_determine_duration (GstFlvMux * mux)
return duration;
}
static GstFlowReturn
gst_flv_mux_write_eos (GstFlvMux * mux)
{
GstBuffer *tag;
GstFlvPad *video_pad = NULL;
GSList *l = mux->collect->data;
if (!mux->have_video)
return GST_FLOW_OK;
for (; l; l = l->next) {
GstFlvPad *cpad = l->data;
if (cpad && cpad->video) {
video_pad = cpad;
break;
}
}
tag = gst_flv_mux_eos_to_tag (mux, video_pad);
return gst_flv_mux_push (mux, tag);
}
static GstFlowReturn
gst_flv_mux_rewrite_header (GstFlvMux * mux)
{
@ -1550,6 +1590,8 @@ gst_flv_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
if (best) {
return gst_flv_mux_write_buffer (mux, best, buffer);
} else {
/* FIXME check return values */
gst_flv_mux_write_eos (mux);
gst_flv_mux_rewrite_header (mux);
gst_pad_push_event (mux->srcpad, gst_event_new_eos ());
return GST_FLOW_EOS;