mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 03:00:35 +00:00
flvmux: Don't refuse caps changes after starting to write headers in streamable mode.
Flv does support changing the stream type and stream properties after the headers were started to be written, and for example H264 codec_data changes can be supported. https://bugzilla.gnome.org/show_bug.cgi?id=797256
This commit is contained in:
parent
faee020994
commit
8cae95a22d
2 changed files with 110 additions and 12 deletions
|
@ -324,6 +324,7 @@ gst_flv_mux_reset (GstElement * element)
|
|||
mux->first_timestamp = GST_CLOCK_STIME_NONE;
|
||||
|
||||
mux->state = GST_FLV_MUX_STATE_HEADER;
|
||||
mux->sent_header = FALSE;
|
||||
|
||||
/* tags */
|
||||
gst_tag_setter_reset_tags (GST_TAG_SETTER (mux));
|
||||
|
@ -397,6 +398,12 @@ gst_flv_mux_video_pad_setcaps (GstFlvMuxPad * pad, GstCaps * caps)
|
|||
GstFlvMux *mux = GST_FLV_MUX (gst_pad_get_parent (pad));
|
||||
gboolean ret = TRUE;
|
||||
GstStructure *s;
|
||||
guint old_codec;
|
||||
GstBuffer *old_codec_data = NULL;
|
||||
|
||||
old_codec = pad->codec;
|
||||
if (pad->codec_data)
|
||||
old_codec_data = gst_buffer_ref (pad->codec_data);
|
||||
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
|
||||
|
@ -419,8 +426,35 @@ gst_flv_mux_video_pad_setcaps (GstFlvMuxPad * pad, GstCaps * caps)
|
|||
|
||||
if (val)
|
||||
gst_buffer_replace (&pad->codec_data, gst_value_get_buffer (val));
|
||||
else if (!val && pad->codec_data)
|
||||
gst_buffer_unref (pad->codec_data);
|
||||
}
|
||||
|
||||
if (ret && mux->streamable && mux->state != GST_FLV_MUX_STATE_HEADER) {
|
||||
if (old_codec != pad->codec) {
|
||||
pad->info_changed = TRUE;
|
||||
}
|
||||
|
||||
if (old_codec_data && pad->codec_data) {
|
||||
GstMapInfo map;
|
||||
|
||||
gst_buffer_map (old_codec_data, &map, GST_MAP_READ);
|
||||
if (map.size != gst_buffer_get_size (pad->codec_data) ||
|
||||
gst_buffer_memcmp (pad->codec_data, 0, map.data, map.size))
|
||||
pad->info_changed = TRUE;
|
||||
|
||||
gst_buffer_unmap (old_codec_data, &map);
|
||||
} else if (!old_codec_data && pad->codec_data) {
|
||||
pad->info_changed = TRUE;
|
||||
}
|
||||
|
||||
if (pad->info_changed)
|
||||
mux->state = GST_FLV_MUX_STATE_HEADER;
|
||||
}
|
||||
|
||||
if (old_codec_data)
|
||||
gst_buffer_unref (old_codec_data);
|
||||
|
||||
gst_object_unref (mux);
|
||||
|
||||
return ret;
|
||||
|
@ -432,6 +466,15 @@ gst_flv_mux_audio_pad_setcaps (GstFlvMuxPad * pad, GstCaps * caps)
|
|||
GstFlvMux *mux = GST_FLV_MUX (gst_pad_get_parent (pad));
|
||||
gboolean ret = TRUE;
|
||||
GstStructure *s;
|
||||
guint old_codec, old_rate, old_width, old_channels;
|
||||
GstBuffer *old_codec_data = NULL;
|
||||
|
||||
old_codec = pad->codec;
|
||||
old_rate = pad->rate;
|
||||
old_width = pad->width;
|
||||
old_channels = pad->channels;
|
||||
if (pad->codec_data)
|
||||
old_codec_data = gst_buffer_ref (pad->codec_data);
|
||||
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
|
||||
|
@ -560,8 +603,36 @@ gst_flv_mux_audio_pad_setcaps (GstFlvMuxPad * pad, GstCaps * caps)
|
|||
|
||||
if (val)
|
||||
gst_buffer_replace (&pad->codec_data, gst_value_get_buffer (val));
|
||||
else if (!val && pad->codec_data)
|
||||
gst_buffer_unref (pad->codec_data);
|
||||
}
|
||||
|
||||
if (ret && mux->streamable && mux->state != GST_FLV_MUX_STATE_HEADER) {
|
||||
if (old_codec != pad->codec || old_rate != pad->rate ||
|
||||
old_width != pad->width || old_channels != pad->channels) {
|
||||
pad->info_changed = TRUE;
|
||||
}
|
||||
|
||||
if (old_codec_data && pad->codec_data) {
|
||||
GstMapInfo map;
|
||||
|
||||
gst_buffer_map (old_codec_data, &map, GST_MAP_READ);
|
||||
if (map.size != gst_buffer_get_size (pad->codec_data) ||
|
||||
gst_buffer_memcmp (pad->codec_data, 0, map.data, map.size))
|
||||
pad->info_changed = TRUE;
|
||||
|
||||
gst_buffer_unmap (old_codec_data, &map);
|
||||
} else if (!old_codec_data && pad->codec_data) {
|
||||
pad->info_changed = TRUE;
|
||||
}
|
||||
|
||||
if (pad->info_changed)
|
||||
mux->state = GST_FLV_MUX_STATE_HEADER;
|
||||
}
|
||||
|
||||
if (old_codec_data)
|
||||
gst_buffer_unref (old_codec_data);
|
||||
|
||||
gst_object_unref (mux);
|
||||
|
||||
return ret;
|
||||
|
@ -579,6 +650,7 @@ gst_flv_mux_reset_pad (GstFlvMuxPad * pad)
|
|||
pad->rate = G_MAXUINT;
|
||||
pad->width = G_MAXUINT;
|
||||
pad->channels = G_MAXUINT;
|
||||
pad->info_changed = FALSE;
|
||||
|
||||
gst_flv_mux_pad_flush (GST_AGGREGATOR_PAD_CAST (pad), NULL);
|
||||
}
|
||||
|
@ -1371,29 +1443,48 @@ gst_flv_mux_write_header (GstFlvMux * mux)
|
|||
gst_query_unref (query);
|
||||
}
|
||||
|
||||
caps = gst_flv_mux_prepare_src_caps (mux,
|
||||
&header, &metadata, &video_codec_data, &audio_codec_data);
|
||||
if (!mux->streamable) {
|
||||
caps = gst_flv_mux_prepare_src_caps (mux,
|
||||
&header, &metadata, &video_codec_data, &audio_codec_data);
|
||||
} else {
|
||||
if (!mux->sent_header) {
|
||||
caps = gst_flv_mux_prepare_src_caps (mux,
|
||||
&header, &metadata, &video_codec_data, &audio_codec_data);
|
||||
} else {
|
||||
caps = gst_flv_mux_prepare_src_caps (mux,
|
||||
NULL, NULL,
|
||||
(mux->video_pad->info_changed ? &video_codec_data : NULL),
|
||||
(mux->audio_pad->info_changed ? &audio_codec_data : NULL));
|
||||
}
|
||||
}
|
||||
|
||||
gst_aggregator_set_src_caps (GST_AGGREGATOR_CAST (mux), caps);
|
||||
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* push the header buffer, the metadata and the codec info, if any */
|
||||
ret = gst_flv_mux_push (mux, header);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto failure_header;
|
||||
ret = gst_flv_mux_push (mux, metadata);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto failure_metadata;
|
||||
if (header != NULL) {
|
||||
ret = gst_flv_mux_push (mux, header);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto failure_header;
|
||||
mux->sent_header = TRUE;
|
||||
}
|
||||
if (metadata != NULL) {
|
||||
ret = gst_flv_mux_push (mux, metadata);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto failure_metadata;
|
||||
}
|
||||
if (video_codec_data != NULL) {
|
||||
ret = gst_flv_mux_push (mux, video_codec_data);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto failure_video_codec_data;
|
||||
mux->video_pad->info_changed = FALSE;
|
||||
}
|
||||
if (audio_codec_data != NULL) {
|
||||
ret = gst_flv_mux_push (mux, audio_codec_data);
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto failure_audio_codec_data;
|
||||
mux->audio_pad->info_changed = FALSE;
|
||||
}
|
||||
return GST_FLOW_OK;
|
||||
|
||||
|
@ -1722,10 +1813,13 @@ gst_flv_mux_aggregate (GstAggregator * aggregator, gboolean timeout)
|
|||
mux->state = GST_FLV_MUX_STATE_DATA;
|
||||
|
||||
best = gst_flv_mux_find_best_pad (aggregator, &ts);
|
||||
if (best && GST_CLOCK_STIME_IS_VALID (ts))
|
||||
mux->first_timestamp = ts;
|
||||
else
|
||||
mux->first_timestamp = 0;
|
||||
|
||||
if (!mux->streamable || mux->first_timestamp == GST_CLOCK_STIME_NONE) {
|
||||
if (best && GST_CLOCK_STIME_IS_VALID (ts))
|
||||
mux->first_timestamp = ts;
|
||||
else
|
||||
mux->first_timestamp = 0;
|
||||
}
|
||||
} else {
|
||||
best = gst_flv_mux_find_best_pad (aggregator, &ts);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ struct _GstFlvMuxPad
|
|||
GstClockTime last_timestamp;
|
||||
gint64 pts;
|
||||
gint64 dts;
|
||||
|
||||
gboolean info_changed;
|
||||
};
|
||||
|
||||
typedef struct _GstFlvMuxPadClass {
|
||||
|
@ -96,6 +98,8 @@ typedef struct _GstFlvMux {
|
|||
guint64 byte_count;
|
||||
guint64 duration;
|
||||
gint64 first_timestamp;
|
||||
|
||||
gboolean sent_header;
|
||||
} GstFlvMux;
|
||||
|
||||
typedef struct _GstFlvMuxClass {
|
||||
|
|
Loading…
Reference in a new issue