rmdemux: add better sipr nibble swap routine
authorWim Taymans <wim.taymans@collabora.co.uk>
Fri, 14 May 2010 14:02:47 +0000 (16:02 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Fri, 14 May 2010 14:02:47 +0000 (16:02 +0200)
gst/realmedia/rmdemux.c
gst/realmedia/rmutils.c
gst/realmedia/rmutils.h

index b180ffa..dd1338c 100644 (file)
@@ -261,6 +261,8 @@ gst_rmdemux_init (GstRMDemux * rmdemux)
   rmdemux->first_ts = GST_CLOCK_TIME_NONE;
   rmdemux->base_ts = GST_CLOCK_TIME_NONE;
   rmdemux->need_newsegment = TRUE;
+
+  gst_rm_utils_run_tests ();
 }
 
 static gboolean
index b118425..8a110dc 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #endif
 
+#include <string.h>
 #include "rmutils.h"
 
 gchar *
@@ -141,7 +142,69 @@ gst_rm_utils_descramble_dnet_buffer (GstBuffer * buf)
   return buf;
 }
 
-static const gint sipr_swaps[38][2] = {
+static void
+gst_rm_utils_swap_nibbles (guint8 * data, gint idx1, gint idx2, gint len)
+{
+  guint8 *d1, *d2, tmp1, tmp2, tmp1n, tmp2n;
+
+  if ((idx2 & 1) && !(idx1 & 1)) {
+    /* align destination to a byte by swapping the indexes */
+    tmp1 = idx1;
+    idx1 = idx2;
+    idx2 = tmp1;
+  }
+  d1 = data + (idx1 >> 1);
+  d2 = data + (idx2 >> 1);
+
+  /* check if we have aligned offsets and we can copy bytes */
+  if ((idx1 & 1) == (idx2 & 1)) {
+    if (idx1 & 1) {
+      /* swap first nibble */
+      tmp1 = *d1;
+      tmp2 = *d2;
+      *d1++ = (tmp2 & 0xf0) | (tmp1 & 0x0f);
+      *d2++ = (tmp1 & 0xf0) | (tmp2 & 0x0f);
+      len--;
+    }
+    for (; len > 1; len -= 2) {
+      /* swap 2 nibbles */
+      tmp1 = *d1;
+      *d1++ = *d2;
+      *d2++ = tmp1;
+    }
+    if (len) {
+      /* swap leftover nibble */
+      tmp1 = *d1;
+      tmp2 = *d2;
+      *d1 = (tmp2 & 0x0f) | (tmp1 & 0xf0);
+      *d2 = (tmp1 & 0x0f) | (tmp2 & 0xf0);
+    }
+  } else {
+    /* preload nibbles from source */
+    tmp2n = tmp1 = tmp1n = *d1;
+    tmp2 = *d2;
+
+    for (; len > 1; len -= 2) {
+      /* assemble nibbles */
+      *d1++ = (tmp2n & 0x0f) | (tmp2 << 4);
+      tmp1n = *d1;
+      *d2++ = (tmp1n << 4) | (tmp1 >> 4);
+
+      tmp1 = tmp1n;
+      tmp2n = (tmp2 >> 4);
+      tmp2 = *d2;
+    }
+    if (len) {
+      /* last leftover */
+      *d1 = (tmp2 << 4) | (tmp2n & 0x0f);
+      *d2 = (tmp1 >> 4) | (tmp2 & 0xf0);
+    } else {
+      *d1 = (tmp1 & 0xf0) | (tmp2n);
+    }
+  }
+}
+
+static const gint sipr_swap_index[38][2] = {
   {0, 63}, {1, 22}, {2, 44}, {3, 90},
   {5, 81}, {7, 31}, {8, 86}, {9, 58},
   {10, 36}, {12, 68}, {13, 39}, {14, 73},
@@ -161,30 +224,66 @@ gst_rm_utils_descramble_sipr_buffer (GstBuffer * buf)
   guint size;
   gint n, bs;
 
-  buf = gst_buffer_make_writable (buf);
-
-  data = GST_BUFFER_DATA (buf);
   size = GST_BUFFER_SIZE (buf);
 
+  /* split the packet in 96 blocks of nibbles */
   bs = size * 2 / 96;
+  if (bs == 0)
+    return buf;
 
-  for (n = 0; n < 38; n++) {
-    int j;
-    int i = bs * sipr_swaps[n][0];
-    int o = bs * sipr_swaps[n][1];
+  buf = gst_buffer_make_writable (buf);
+
+  data = GST_BUFFER_DATA (buf);
 
-    /* swap 4bit-nibbles of block 'i' with 'o' */
-    for (j = 0; j < bs; j++, i++, o++) {
-      int x, y;
+  /* we need to perform 38 swaps on the blocks */
+  for (n = 0; n < 38; n++) {
+    gint idx1, idx2;
 
-      x = (data[i >> 1] >> (4 * (i & 1))) & 0xF;
-      y = (data[o >> 1] >> (4 * (o & 1))) & 0xF;
+    /* get the indexes of the blocks of nibbles that need swapping */
+    idx1 = bs * sipr_swap_index[n][0];
+    idx2 = bs * sipr_swap_index[n][1];
 
-      data[o >> 1] = (x << (4 * (o & 1))) |
-          (data[o >> 1] & (0xF << (4 * !(o & 1))));
-      data[i >> 1] = (y << (4 * (i & 1))) |
-          (data[i >> 1] & (0xF << (4 * !(i & 1))));
-    }
+    /* swap the blocks */
+    gst_rm_utils_swap_nibbles (data, idx1, idx2, bs);
   }
   return buf;
 }
+
+void
+gst_rm_utils_run_tests (void)
+{
+#if 0
+  guint8 tab1[] = { 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe };
+  guint8 tab2[8];
+
+  memcpy (tab2, tab1, 8);
+  gst_util_dump_mem (tab2, 8);
+
+  gst_rm_utils_swap_nibbles (tab2, 0, 8, 4);
+  gst_util_dump_mem (tab2, 8);
+  memcpy (tab2, tab1, 8);
+  gst_rm_utils_swap_nibbles (tab2, 0, 8, 5);
+  gst_util_dump_mem (tab2, 8);
+
+  memcpy (tab2, tab1, 8);
+  gst_rm_utils_swap_nibbles (tab2, 1, 8, 4);
+  gst_util_dump_mem (tab2, 8);
+  memcpy (tab2, tab1, 8);
+  gst_rm_utils_swap_nibbles (tab2, 1, 8, 5);
+  gst_util_dump_mem (tab2, 8);
+
+  memcpy (tab2, tab1, 8);
+  gst_rm_utils_swap_nibbles (tab2, 0, 9, 4);
+  gst_util_dump_mem (tab2, 8);
+  memcpy (tab2, tab1, 8);
+  gst_rm_utils_swap_nibbles (tab2, 0, 9, 5);
+  gst_util_dump_mem (tab2, 8);
+
+  memcpy (tab2, tab1, 8);
+  gst_rm_utils_swap_nibbles (tab2, 1, 9, 4);
+  gst_util_dump_mem (tab2, 8);
+  memcpy (tab2, tab1, 8);
+  gst_rm_utils_swap_nibbles (tab2, 1, 9, 5);
+  gst_util_dump_mem (tab2, 8);
+#endif
+}
index ed0ace5..bd10c5e 100644 (file)
@@ -41,6 +41,9 @@ GstTagList    *gst_rm_utils_read_tags     (const guint8            * data,
 GstBuffer     *gst_rm_utils_descramble_dnet_buffer (GstBuffer * buf);
 GstBuffer     *gst_rm_utils_descramble_sipr_buffer (GstBuffer * buf);
 
+void gst_rm_utils_run_tests (void);
+
+
 G_END_DECLS
 
 #endif /* __GST_RM_UTILS_H__ */