diff --git a/gst/rtp/gstrtpvorbisdepay.c b/gst/rtp/gstrtpvorbisdepay.c index e96bc2b557..d1f25765c1 100644 --- a/gst/rtp/gstrtpvorbisdepay.c +++ b/gst/rtp/gstrtpvorbisdepay.c @@ -119,6 +119,33 @@ gst_rtp_vorbis_depay_init (GstRtpVorbisDepay * rtpvorbisdepay, { rtpvorbisdepay->adapter = gst_adapter_new (); } + +static void +free_config (GstRtpVorbisConfig * conf) +{ + GList *headers; + + for (headers = conf->headers; headers; headers = g_list_next (headers)) { + GstBuffer *header = GST_BUFFER_CAST (headers->data); + + gst_buffer_unref (header); + } + g_list_free (conf->headers); + g_free (conf); +} + +static void +free_indents (GstRtpVorbisDepay * rtpvorbisdepay) +{ + GList *walk; + + for (walk = rtpvorbisdepay->configs; walk; walk = g_list_next (walk)) { + free_config ((GstRtpVorbisConfig *) walk->data); + } + g_list_free (rtpvorbisdepay->configs); + rtpvorbisdepay->configs = NULL; +} + static void gst_rtp_vorbis_depay_finalize (GObject * object) { @@ -129,54 +156,6 @@ gst_rtp_vorbis_depay_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } -static const guint8 a2bin[256] = { - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, - 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, - 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 -}; - -static guint -decode_base64 (const gchar * in, guint8 * out) -{ - guint8 v1, v2; - guint len = 0; - - v1 = a2bin[(gint) * in]; - while (v1 <= 63) { - /* read 4 bytes, write 3 bytes, invalid base64 are zeroes */ - v2 = a2bin[(gint) * ++in]; - *out++ = (v1 << 2) | ((v2 & 0x3f) >> 4); - v1 = (v2 > 63 ? 64 : a2bin[(gint) * ++in]); - *out++ = (v2 << 4) | ((v1 & 0x3f) >> 2); - v2 = (v1 > 63 ? 64 : a2bin[(gint) * ++in]); - *out++ = (v1 << 6) | (v2 & 0x3f); - v1 = (v2 > 63 ? 64 : a2bin[(gint) * ++in]); - len += 3; - } - /* move to '\0' */ - while (*in != '\0') - in++; - - /* subtract padding */ - while (len > 0 && *--in == '=') - len--; - - return len; -} - static gboolean gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, const gchar * configuration) @@ -184,15 +163,18 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, GstBuffer *buf; guint32 num_headers; guint8 *data; - guint size; + GstBuffer *confbuf; + gsize size; + guint offset; gint i, j; /* deserialize base64 to buffer */ - size = strlen (configuration); - GST_DEBUG_OBJECT (rtpvorbisdepay, "base64 config size %u", size); + data = g_base64_decode (configuration, &size); - data = g_malloc (size); - size = decode_base64 (configuration, data); + confbuf = gst_buffer_new (); + GST_BUFFER_DATA (confbuf) = data; + GST_BUFFER_MALLOCDATA (confbuf) = data; + GST_BUFFER_SIZE (confbuf) = size; GST_DEBUG_OBJECT (rtpvorbisdepay, "config size %u", size); @@ -215,6 +197,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, num_headers = GST_READ_UINT32_BE (data); size -= 4; data += 4; + offset = 4; GST_DEBUG_OBJECT (rtpvorbisdepay, "have %u headers", num_headers); @@ -257,6 +240,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, n_headers = data[5]; size -= 6; data += 6; + offset += 6; GST_DEBUG_OBJECT (rtpvorbisdepay, "header %d, ident 0x%08x, length %u, left %u", i, ident, length, size); @@ -275,10 +259,15 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, if (size < 1) goto too_small; b = *data++; + offset++; size--; h_size = (h_size << 7) | (b & 0x7f); } while (b & 0x80); GST_DEBUG_OBJECT (rtpvorbisdepay, "headers %d: size: %u", j, h_size); + + if (length < h_size) + goto too_small; + h_sizes[j] = h_size; length -= h_size; } @@ -294,20 +283,22 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, guint h_size; h_size = h_sizes[j]; - if (size < h_size) + if (size < h_size) { + free_config (conf); goto too_small; + } GST_DEBUG_OBJECT (rtpvorbisdepay, "reading header %d, size %u", j, h_size); - buf = gst_buffer_new_and_alloc (h_size); - memcpy (GST_BUFFER_DATA (buf), data, h_size); + buf = gst_buffer_create_sub (confbuf, offset, h_size); conf->headers = g_list_append (conf->headers, buf); - data += h_size; + offset += h_size; size -= h_size; } rtpvorbisdepay->configs = g_list_append (rtpvorbisdepay->configs, conf); } + gst_buffer_unref (confbuf); return TRUE; @@ -315,6 +306,7 @@ gst_rtp_vorbis_depay_parse_configuration (GstRtpVorbisDepay * rtpvorbisdepay, too_small: { GST_DEBUG_OBJECT (rtpvorbisdepay, "configuration too small"); + gst_buffer_unref (confbuf); return FALSE; } } @@ -637,6 +629,9 @@ gst_rtp_vorbis_depay_change_state (GstElement * element, ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + free_indents (rtpvorbisdepay); + break; case GST_STATE_CHANGE_READY_TO_NULL: break; default: