summaryrefslogtreecommitdiffstats
path: root/gst/rtp/gstrtptheoradepay.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2007-05-14 17:10:12 +0000
committerWim Taymans <wim.taymans@gmail.com>2007-05-14 17:10:12 +0000
commit4da361f94cabf209d2dcd59e493b968d7ddd3e79 (patch)
tree1a6adb0cdaef79c1c2f7e044c87af77f7287ef64 /gst/rtp/gstrtptheoradepay.c
parent789ef04027fe1bc1cea3811104ddde44f4b3d50a (diff)
gst/rtp/: Update theora pay/depayloader in a similar to vorbis.
Original commit message from CVS: * gst/rtp/gstrtptheoradepay.c: (decode_base64), (gst_rtp_theora_depay_parse_configuration): * gst/rtp/gstrtptheorapay.c: (encode_base64), (gst_rtp_theora_pay_finish_headers), (gst_rtp_theora_pay_handle_buffer): Update theora pay/depayloader in a similar to vorbis. * gst/rtp/gstrtpvorbisdepay.c: (gst_rtp_vorbis_depay_parse_configuration): Update docs.
Diffstat (limited to 'gst/rtp/gstrtptheoradepay.c')
-rw-r--r--gst/rtp/gstrtptheoradepay.c169
1 files changed, 116 insertions, 53 deletions
diff --git a/gst/rtp/gstrtptheoradepay.c b/gst/rtp/gstrtptheoradepay.c
index 47ab3826..a8a642e6 100644
--- a/gst/rtp/gstrtptheoradepay.c
+++ b/gst/rtp/gstrtptheoradepay.c
@@ -59,7 +59,9 @@ GST_STATIC_PAD_TEMPLATE ("sink",
"clock-rate = (int) [1, MAX ], " "encoding-name = (string) \"THEORA\""
/* All required parameters
*
- * "encoding-params = (string) <num channels>"
+ * "sampling = (string) { "YCbCr-4:2:0", "YCbCr-4:2:2", "YCbCr-4:4:4" } "
+ * "width = (string) [1, 1048561] (multiples of 16) "
+ * "height = (string) [1, 1048561] (multiples of 16) "
* "delivery-method = (string) { inline, in_band, out_band/<specific_name> } "
* "configuration = (string) ANY"
*/
@@ -77,9 +79,6 @@ GST_STATIC_PAD_TEMPLATE ("src",
GST_STATIC_CAPS ("video/x-theora")
);
-/* 42 bytes for the theora identification packet length */
-#define THEORA_ID_LEN 42
-
GST_BOILERPLATE (GstRtpTheoraDepay, gst_rtp_theora_depay, GstBaseRTPDepayload,
GST_TYPE_BASE_RTP_DEPAYLOAD);
@@ -151,28 +150,70 @@ gst_rtp_theora_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_theora_depay_parse_configuration (GstRtpTheoraDepay * rtptheoradepay,
const gchar * configuration)
{
- GValue v = { 0 };
GstBuffer *buf;
guint32 num_headers;
guint8 *data;
guint size;
- gint i;
-
- /* deserialize base16 to buffer */
- g_value_init (&v, GST_TYPE_BUFFER);
- if (!gst_value_deserialize (&v, configuration))
- goto wrong_configuration;
+ gint i, j;
- buf = gst_value_get_buffer (&v);
- gst_buffer_ref (buf);
- g_value_unset (&v);
+ /* deserialize base64 to buffer */
+ size = strlen (configuration);
+ GST_DEBUG_OBJECT (rtptheoradepay, "base64 config size %u", size);
- data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
+ data = g_malloc (size);
+ size = decode_base64 (configuration, data);
GST_DEBUG_OBJECT (rtptheoradepay, "config size %u", size);
@@ -201,74 +242,96 @@ gst_rtp_theora_depay_parse_configuration (GstRtpTheoraDepay * rtptheoradepay,
/* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Ident | ..
+ * | Ident | length ..
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * .. | n. of headers | length1 | length2 ..
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * .. | Identification Header ..
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * .................................................................
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * .. length | Identification Header ..
+ * .. | Comment Header ..
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * .. Identification Header |
+ * .................................................................
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * .. Comment Header |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Setup Header ..
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * .................................................................
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* .. Setup Header |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
*/
for (i = 0; i < num_headers; i++) {
guint32 ident;
guint16 length;
+ guint8 n_headers, b;
GstRtpTheoraConfig *conf;
- GstTagList *list;
+ guint *h_sizes;
- if (size < 5)
+ if (size < 6)
goto too_small;
ident = (data[0] << 16) | (data[1] << 8) | data[2];
length = (data[3] << 8) | data[4];
- size -= 5;
- data += 5;
+ n_headers = data[5];
+ size -= 6;
+ data += 6;
- GST_DEBUG_OBJECT (rtptheoradepay, "header %d, ident %08x, length %u", i,
- ident, length);
+ GST_DEBUG_OBJECT (rtptheoradepay,
+ "header %d, ident 0x%08x, length %u, left %u", i, ident, length, size);
- if (size < length + THEORA_ID_LEN)
+ if (size < length)
goto too_small;
- GST_DEBUG_OBJECT (rtptheoradepay, "preparing headers");
+ /* read header sizes we read 2 sizes, the third size (for which we allocate
+ * space) must be derived from the total packed header length. */
+ h_sizes = g_newa (guint, n_headers + 1);
+ for (j = 0; j < n_headers; j++) {
+ guint h_size;
+
+ h_size = 0;
+ do {
+ if (size < 1)
+ goto too_small;
+ b = *data++;
+ size--;
+ h_size = (h_size << 7) | (b & 0x7f);
+ } while (b & 0x80);
+ GST_DEBUG_OBJECT (rtptheoradepay, "headers %d: size: %u", j, h_size);
+ h_sizes[j] = h_size;
+ length -= h_size;
+ }
+ /* last header length is the remaining space */
+ GST_DEBUG_OBJECT (rtptheoradepay, "last header size: %u", length);
+ h_sizes[j] = length;
+ GST_DEBUG_OBJECT (rtptheoradepay, "preparing headers");
conf = g_new0 (GstRtpTheoraConfig, 1);
conf->ident = ident;
- buf = gst_buffer_new_and_alloc (THEORA_ID_LEN);
- memcpy (GST_BUFFER_DATA (buf), data, THEORA_ID_LEN);
- conf->headers = g_list_append (conf->headers, buf);
- data += THEORA_ID_LEN;
- size -= THEORA_ID_LEN;
-
- /* create a dummy comment */
- list = gst_tag_list_new ();
- buf =
- gst_tag_list_to_vorbiscomment_buffer (list, (guint8 *) "\201theora", 7,
- "Theora RTP depayloader");
- conf->headers = g_list_append (conf->headers, buf);
- gst_tag_list_free (list);
-
- buf = gst_buffer_new_and_alloc (length);
- memcpy (GST_BUFFER_DATA (buf), data, length);
- conf->headers = g_list_append (conf->headers, buf);
- data += length;
- size -= length;
+ for (j = 0; j <= n_headers; j++) {
+ guint h_size;
+
+ h_size = h_sizes[j];
+ if (size < h_size)
+ goto too_small;
+ GST_DEBUG_OBJECT (rtptheoradepay, "reading header %d, size %u", j,
+ h_size);
+
+ buf = gst_buffer_new_and_alloc (h_size);
+ memcpy (GST_BUFFER_DATA (buf), data, h_size);
+ conf->headers = g_list_append (conf->headers, buf);
+ data += h_size;
+ size -= h_size;
+ }
rtptheoradepay->configs = g_list_append (rtptheoradepay->configs, conf);
}
-
return TRUE;
/* ERRORS */
-wrong_configuration:
- {
- GST_DEBUG_OBJECT (rtptheoradepay, "error parsing configuration");
- return FALSE;
- }
too_small:
{
GST_DEBUG_OBJECT (rtptheoradepay, "configuration too small");