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:
parent
be05515da7
commit
1cd5a5241f
@ -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_write_header (GstFlvMux * mux);
|
||||||
static GstFlowReturn gst_flv_mux_rewrite_header (GstFlvMux * mux);
|
static GstFlowReturn gst_flv_mux_rewrite_header (GstFlvMux * mux);
|
||||||
static gboolean gst_flv_mux_are_all_pads_eos (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
|
static GstFlowReturn
|
||||||
gst_flv_mux_pad_flush (GstAggregatorPad * pad, GstAggregator * aggregator)
|
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->flush = GST_DEBUG_FUNCPTR (gst_flv_mux_flush);
|
||||||
gstaggregator_class->get_next_time =
|
gstaggregator_class->get_next_time =
|
||||||
GST_DEBUG_FUNCPTR (gst_flv_mux_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,
|
gst_element_class_add_static_pad_template_with_gtype (gstelement_class,
|
||||||
&videosink_templ, GST_TYPE_FLV_MUX_PAD);
|
&videosink_templ, GST_TYPE_FLV_MUX_PAD);
|
||||||
@ -1241,8 +1244,10 @@ gst_flv_mux_put_buffer_in_streamheader (GValue * streamheader,
|
|||||||
g_value_unset (&value);
|
g_value_unset (&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstCaps *
|
||||||
gst_flv_mux_write_header (GstFlvMux * mux)
|
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 *header, *metadata;
|
||||||
GstBuffer *video_codec_data, *audio_codec_data;
|
GstBuffer *video_codec_data, *audio_codec_data;
|
||||||
@ -1250,31 +1255,6 @@ gst_flv_mux_write_header (GstFlvMux * mux)
|
|||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
GValue streamheader = { 0 };
|
GValue streamheader = { 0 };
|
||||||
GList *l;
|
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);
|
header = gst_flv_mux_create_header (mux);
|
||||||
metadata = gst_flv_mux_create_metadata (mux, TRUE);
|
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);
|
gst_structure_set_value (structure, "streamheader", &streamheader);
|
||||||
g_value_unset (&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_aggregator_set_src_caps (GST_AGGREGATOR_CAST (mux), caps);
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
@ -1816,3 +1860,14 @@ wait_for_data:
|
|||||||
GST_OBJECT_UNLOCK (aggregator);
|
GST_OBJECT_UNLOCK (aggregator);
|
||||||
return GST_CLOCK_TIME_NONE;
|
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;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user