flvmux: Don't omit streamheader from caps on downstream reconfigure

The reconfigured downstream elements (e.g., dynamically added sink element)
most likely require the flv streamheader

https://bugzilla.gnome.org/show_bug.cgi?id=797089
This commit is contained in:
Seungha Yang 2018-09-06 13:13:19 +09:00 committed by Olivier Crête
parent be05515da7
commit 1cd5a5241f

View file

@ -128,7 +128,8 @@ static GstFlowReturn gst_flv_mux_write_eos (GstFlvMux * mux);
static GstFlowReturn gst_flv_mux_write_header (GstFlvMux * mux);
static GstFlowReturn gst_flv_mux_rewrite_header (GstFlvMux * mux);
static gboolean gst_flv_mux_are_all_pads_eos (GstFlvMux * mux);
static GstFlowReturn gst_flv_mux_update_src_caps (GstAggregator * aggregator,
GstCaps * caps, GstCaps ** ret);
static GstFlowReturn
gst_flv_mux_pad_flush (GstAggregatorPad * pad, GstAggregator * aggregator)
@ -239,6 +240,8 @@ gst_flv_mux_class_init (GstFlvMuxClass * klass)
gstaggregator_class->flush = GST_DEBUG_FUNCPTR (gst_flv_mux_flush);
gstaggregator_class->get_next_time =
GST_DEBUG_FUNCPTR (gst_flv_mux_get_next_time);
gstaggregator_class->update_src_caps =
GST_DEBUG_FUNCPTR (gst_flv_mux_update_src_caps);
gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
&videosink_templ, GST_TYPE_FLV_MUX_PAD);
@ -1241,8 +1244,10 @@ gst_flv_mux_put_buffer_in_streamheader (GValue * streamheader,
g_value_unset (&value);
}
static GstFlowReturn
gst_flv_mux_write_header (GstFlvMux * mux)
static GstCaps *
gst_flv_mux_prepare_src_caps (GstFlvMux * mux, GstBuffer ** header_buf,
GstBuffer ** metadata_buf, GstBuffer ** video_codec_data_buf,
GstBuffer ** audio_codec_data_buf)
{
GstBuffer *header, *metadata;
GstBuffer *video_codec_data, *audio_codec_data;
@ -1250,31 +1255,6 @@ gst_flv_mux_write_header (GstFlvMux * mux)
GstStructure *structure;
GValue streamheader = { 0 };
GList *l;
GstFlowReturn ret;
/* if not streaming, check if downstream is seekable */
if (!mux->streamable) {
gboolean seekable;
GstQuery *query;
query = gst_query_new_seeking (GST_FORMAT_BYTES);
if (gst_pad_peer_query (mux->srcpad, query)) {
gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
GST_INFO_OBJECT (mux, "downstream is %sseekable", seekable ? "" : "not ");
} else {
/* have to assume seeking is supported if query not handled downstream */
GST_WARNING_OBJECT (mux, "downstream did not handle seeking query");
seekable = FALSE;
}
if (!seekable) {
mux->streamable = TRUE;
g_object_notify (G_OBJECT (mux), "streamable");
GST_WARNING_OBJECT (mux, "downstream is not seekable, but "
"streamable=false. Will ignore that and create streamable output "
"instead");
}
gst_query_unref (query);
}
header = gst_flv_mux_create_header (mux);
metadata = gst_flv_mux_create_metadata (mux, TRUE);
@ -1330,6 +1310,70 @@ gst_flv_mux_write_header (GstFlvMux * mux)
gst_structure_set_value (structure, "streamheader", &streamheader);
g_value_unset (&streamheader);
if (header_buf) {
*header_buf = header;
} else {
gst_buffer_unref (header);
}
if (metadata_buf) {
*metadata_buf = metadata;
} else {
gst_buffer_unref (metadata);
}
if (video_codec_data_buf) {
*video_codec_data_buf = video_codec_data;
} else if (video_codec_data) {
gst_buffer_unref (video_codec_data);
}
if (audio_codec_data_buf) {
*audio_codec_data_buf = audio_codec_data;
} else if (audio_codec_data) {
gst_buffer_unref (audio_codec_data);
}
return caps;
}
static GstFlowReturn
gst_flv_mux_write_header (GstFlvMux * mux)
{
GstBuffer *header, *metadata;
GstBuffer *video_codec_data, *audio_codec_data;
GstCaps *caps;
GstFlowReturn ret;
header = metadata = video_codec_data = audio_codec_data = NULL;
/* if not streaming, check if downstream is seekable */
if (!mux->streamable) {
gboolean seekable;
GstQuery *query;
query = gst_query_new_seeking (GST_FORMAT_BYTES);
if (gst_pad_peer_query (mux->srcpad, query)) {
gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
GST_INFO_OBJECT (mux, "downstream is %sseekable", seekable ? "" : "not ");
} else {
/* have to assume seeking is supported if query not handled downstream */
GST_WARNING_OBJECT (mux, "downstream did not handle seeking query");
seekable = FALSE;
}
if (!seekable) {
mux->streamable = TRUE;
g_object_notify (G_OBJECT (mux), "streamable");
GST_WARNING_OBJECT (mux, "downstream is not seekable, but "
"streamable=false. Will ignore that and create streamable output "
"instead");
}
gst_query_unref (query);
}
caps = gst_flv_mux_prepare_src_caps (mux,
&header, &metadata, &video_codec_data, &audio_codec_data);
gst_aggregator_set_src_caps (GST_AGGREGATOR_CAST (mux), caps);
gst_caps_unref (caps);
@ -1816,3 +1860,14 @@ wait_for_data:
GST_OBJECT_UNLOCK (aggregator);
return GST_CLOCK_TIME_NONE;
}
static GstFlowReturn
gst_flv_mux_update_src_caps (GstAggregator * aggregator,
GstCaps * caps, GstCaps ** ret)
{
GstFlvMux *mux = GST_FLV_MUX (aggregator);
*ret = gst_flv_mux_prepare_src_caps (mux, NULL, NULL, NULL, NULL);
return GST_FLOW_OK;
}