mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 18:51:11 +00:00
oggmux: prefer headers from caps to determine stream type
Ogg mandates the first header packet must determine a stream's type. However, some streams (such as VP8) do not include such a header when muxed in other containers, and thus do not include this header as a buffer, but only in caps. We thus use headers from caps when available to determine a new stream's type. https://bugzilla.gnome.org/show_bug.cgi?id=647856
This commit is contained in:
parent
1d05e81435
commit
55e767b632
3 changed files with 69 additions and 1 deletions
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue