From: Jan Schmidt Date: Mon, 2 Feb 2015 14:19:05 +0000 (+1100) Subject: theora: If no header packets in stream, look for them in the caps X-Git-Tag: 1.6.0~601 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f852f3bc7526afd470acb4e65a77b22d4821cc8e;p=platform%2Fupstream%2Fgst-plugins-base.git theora: If no header packets in stream, look for them in the caps Makes theora work in cases where the header packets are only in the caps (because theoradec was connected to oggdemux late and missed the beginning of the stream) --- diff --git a/ext/theora/gsttheoradec.c b/ext/theora/gsttheoradec.c index d1a7b24..d2f14b0 100644 --- a/ext/theora/gsttheoradec.c +++ b/ext/theora/gsttheoradec.c @@ -418,7 +418,7 @@ theora_handle_type_packet (GstTheoraDec * dec) } /* theora has: * - * width/height : dimension of the encoded frame + * width/height : dimension of the encoded frame * pic_width/pic_height : dimension of the visible part * pic_x/pic_y : offset in encoded frame where visible part starts */ @@ -559,6 +559,62 @@ header_read_error: } } +#define MIN_NUM_HEADERS 3 +static GstFlowReturn +theoradec_handle_header_caps (GstTheoraDec * dec) +{ + GstFlowReturn result = GST_CUSTOM_FLOW_DROP; + GstCaps *caps; + GstStructure *s = NULL; + const GValue *array = NULL; + + GST_DEBUG_OBJECT (dec, "Looking for Theora headers in caps"); + caps = gst_pad_get_current_caps (GST_VIDEO_DECODER_SINK_PAD (dec)); + if (caps) + s = gst_caps_get_structure (caps, 0); + if (s) + array = gst_structure_get_value (s, "streamheader"); + + if (caps) + gst_caps_unref (caps); + + if (array && (gst_value_array_get_size (array) >= MIN_NUM_HEADERS)) { + const GValue *value = NULL; + GstBuffer *buf = NULL; + gint i = 0; + + while (result == GST_CUSTOM_FLOW_DROP + && i < gst_value_array_get_size (array)) { + value = gst_value_array_get_value (array, i); + buf = gst_value_get_buffer (value); + if (!buf) + goto null_buffer; + GST_LOG_OBJECT (dec, "Submitting header packet"); + result = theora_dec_decode_buffer (dec, buf, NULL); + i++; + } + } else + goto array_error; + +done: + return (result != + GST_CUSTOM_FLOW_DROP ? GST_FLOW_NOT_NEGOTIATED : GST_FLOW_OK); + + /* ERRORS */ +array_error: + { + GST_WARNING_OBJECT (dec, "streamheader array not found"); + result = GST_FLOW_ERROR; + goto done; + } +null_buffer: + { + GST_WARNING_OBJECT (dec, "streamheader with null buffer received"); + result = GST_FLOW_ERROR; + goto done; + } +} + /* Allocate buffer and copy image data into Y444 format */ static GstFlowReturn theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf, @@ -683,10 +739,13 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet, GstFlowReturn result; ogg_int64_t gp; - if (G_UNLIKELY (!dec->have_header)) - goto not_initialized; + if (G_UNLIKELY (!dec->have_header)) { + result = theoradec_handle_header_caps (dec); + if (result != GST_FLOW_OK) + goto not_initialized; + } - /* the second most significant bit of the first data byte is cleared + /* the second most significant bit of the first data byte is cleared * for keyframes. We can only check it if it's not a zero-length packet. */ keyframe = packet->bytes && ((packet->packet[0] & 0x40) == 0); if (G_UNLIKELY (keyframe)) {