diff --git a/ext/ogg/gstoggmux.c b/ext/ogg/gstoggmux.c index 9f3047f659..4dda50b4ec 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -848,7 +848,18 @@ gst_ogg_mux_queue_pads (GstOggMux * ogg_mux) /* if we're not yet in data mode, ensure we're setup on the first packet */ if (!pad->have_type) { - pad->have_type = gst_ogg_stream_setup_map (&pad->map, &packet); + /* Use headers in caps, if any; this will allow us to be resilient + * to starting streams on the fly, and some streams (like VP8 + * at least) do not send headers packets, as other muxers don't + * expect/need them. */ + pad->have_type = + gst_ogg_stream_setup_map_from_caps_headers (&pad->map, + GST_BUFFER_CAPS (buf)); + + if (!pad->have_type) { + /* fallback on the packet */ + pad->have_type = gst_ogg_stream_setup_map (&pad->map, &packet); + } if (!pad->have_type) { GST_ERROR_OBJECT (pad, "mapper didn't recognise input stream " "(pad caps: %" GST_PTR_FORMAT ")", GST_PAD_CAPS (pad)); diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index 3ef2fd00f5..e843f48721 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -2051,3 +2051,58 @@ gst_ogg_stream_setup_map (GstOggStream * pad, ogg_packet * packet) return FALSE; } + +gboolean +gst_ogg_stream_setup_map_from_caps_headers (GstOggStream * pad, + const GstCaps * caps) +{ + const GstStructure *structure; + const GstBuffer *buf; + const GValue *streamheader; + const GValue *first_element; + ogg_packet packet; + + GST_INFO ("Checking streamheader on caps %" GST_PTR_FORMAT, caps); + + if (caps == NULL) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + streamheader = gst_structure_get_value (structure, "streamheader"); + + if (streamheader == NULL) { + GST_LOG ("no streamheader field in caps %" GST_PTR_FORMAT, caps); + return FALSE; + } + + if (!GST_VALUE_HOLDS_ARRAY (streamheader)) { + GST_ERROR ("streamheader field not an array, caps: %" GST_PTR_FORMAT, caps); + return FALSE; + } + + if (gst_value_array_get_size (streamheader) == 0) { + GST_ERROR ("empty streamheader field in caps %" GST_PTR_FORMAT, caps); + return FALSE; + } + + first_element = gst_value_array_get_value (streamheader, 0); + + if (!GST_VALUE_HOLDS_BUFFER (first_element)) { + GST_ERROR ("first streamheader not a buffer, caps: %" GST_PTR_FORMAT, caps); + return FALSE; + } + + buf = gst_value_get_buffer (first_element); + if (buf == NULL || GST_BUFFER_SIZE (buf) == 0) { + GST_ERROR ("invalid first streamheader buffer"); + return FALSE; + } + + GST_MEMDUMP ("streamheader", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + + GST_INFO ("Found headers on caps, using those to determine type"); + return gst_ogg_stream_setup_map (pad, &packet); +} diff --git a/ext/ogg/gstoggstream.h b/ext/ogg/gstoggstream.h index 94c8f05504..f843692eaf 100644 --- a/ext/ogg/gstoggstream.h +++ b/ext/ogg/gstoggstream.h @@ -106,6 +106,8 @@ struct _GstOggStream gboolean gst_ogg_stream_setup_map (GstOggStream * pad, ogg_packet *packet); +gboolean gst_ogg_stream_setup_map_from_caps_headers (GstOggStream * pad, + const GstCaps * caps); GstClockTime gst_ogg_stream_get_end_time_for_granulepos (GstOggStream *pad, gint64 granulepos); GstClockTime gst_ogg_stream_get_start_time_for_granulepos (GstOggStream *pad,