[MPlayer-cvslog] r32710 - trunk/playtreeparser.c

reimar subversion at mplayerhq.hu
Sun Dec 12 20:25:43 CET 2010


Author: reimar
Date: Sun Dec 12 20:25:43 2010
New Revision: 32710

Log:
Add playlist parser for .nsc files.
Tested to properly decode .nsc files, but not properly tested since
no publically available stream could be found.

Modified:
   trunk/playtreeparser.c

Modified: trunk/playtreeparser.c
==============================================================================
--- trunk/playtreeparser.c	Sun Dec 12 18:16:59 2010	(r32709)
+++ trunk/playtreeparser.c	Sun Dec 12 20:25:43 2010	(r32710)
@@ -680,6 +680,116 @@ parse_textplain(play_tree_parser_t* p) {
   return entry;
 }
 
+/**
+ * \brief decode the base64 used in nsc files
+ * \param in input string, 0-terminated
+ * \param buf output buffer, must point to memory suitable for realloc,
+ *            will be NULL on failure.
+ * \return decoded length in bytes
+ */
+static int decode_nsc_base64(char *in, char **buf) {
+  int i, j, n;
+  if (in[0] != '0' || in[1] != '2')
+    goto err_out;
+  in += 2; // skip prefix
+  if (strlen(in) < 16) // error out if nothing to decode
+    goto err_out;
+  in += 12; // skip encoded string length
+  n = strlen(in) / 4;
+  *buf = realloc(*buf, n * 3);
+  for (i = 0; i < n; i++) {
+    uint8_t c[4];
+    for (j = 0; j < 4; j++) {
+      c[j] = in[4 * i + j];
+      if (c[j] >= '0' && c[j] <= '9') c[j] += 0 - '0';
+      else if (c[j] >= 'A' && c[j] <= 'Z') c[j] += 10 - 'A';
+      else if (c[j] >= 'a' && c[j] <= 'z') c[j] += 36 - 'a';
+      else if (c[j] == '{') c[j] = 62;
+      else if (c[j] == '}') c[j] = 63;
+      else {
+        mp_msg(MSGT_PLAYTREE, MSGL_ERR, "Invalid character %c (0x%02"PRIx8")\n", c[j], c[j]);
+        goto err_out;
+      }
+    }
+    (*buf)[3 * i] = (c[0] << 2) | (c[1] >> 4);
+    (*buf)[3 * i + 1] = (c[1] << 4) | (c[2] >> 2);
+    (*buf)[3 * i + 2] = (c[2] << 6) | c[3];
+  }
+  return 3 * n;
+err_out:
+  if (*buf) free(*buf);
+  *buf = NULL;
+  return 0;
+}
+
+/**
+ * \brief "converts" utf16 to ascii by just discarding every second byte
+ * \param buf buffer to convert
+ * \param len lenght of buffer, must be > 0
+ */
+static void utf16_to_ascii(char *buf, int len) {
+  int i;
+  if (len <= 0) return;
+  for (i = 0; i < len / 2; i++)
+    buf[i] = buf[i * 2];
+  buf[i] = 0; // just in case
+}
+
+static play_tree_t *parse_nsc(play_tree_parser_t* p) {
+  char *line, *addr = NULL, *url, *unicast_url = NULL;
+  int port = 0;
+  play_tree_t *entry = NULL;
+
+  mp_msg(MSGT_PLAYTREE,MSGL_V,"Trying nsc playlist...\n");
+  while((line = play_tree_parser_get_line(p)) != NULL) {
+    strstrip(line);
+    if(!line[0]) // Ignore empties
+      continue;
+    if (strncasecmp(line,"[Address]", 9) == 0)
+      break; // nsc header found
+    else
+      return NULL;
+  }
+  mp_msg(MSGT_PLAYTREE,MSGL_V,"Detected nsc playlist format\n");
+  play_tree_parser_stop_keeping(p);
+  while ((line = play_tree_parser_get_line(p)) != NULL) {
+    strstrip(line);
+    if (!line[0])
+      continue;
+    if (strncasecmp(line, "Unicast URL=", 12) == 0) {
+      int len = decode_nsc_base64(&line[12], &unicast_url);
+      if (len <= 0)
+        mp_msg(MSGT_PLAYTREE, MSGL_WARN, "[nsc] Unsupported Unicast URL encoding\n");
+      else
+        utf16_to_ascii(unicast_url, len);
+    } else if (strncasecmp(line, "IP Address=", 11) == 0) {
+      int len = decode_nsc_base64(&line[11], &addr);
+      if (len <= 0)
+        mp_msg(MSGT_PLAYTREE, MSGL_WARN, "[nsc] Unsupported IP Address encoding\n");
+      else
+        utf16_to_ascii(addr, len);
+    } else if (strncasecmp(line, "IP Port=", 8) == 0) {
+      port = strtol(&line[8], NULL, 0);
+    }
+  }
+
+  if (unicast_url)
+    url = strdup(unicast_url);
+  else if (addr && port) {
+    url = malloc(strlen(addr) + 7 + 20 + 1);
+    sprintf(url, "http://%s:%i", addr, port);
+  } else
+   goto out;
+
+  entry = play_tree_new();
+  play_tree_add_file(entry, url);
+  free(url);
+out:
+  if (addr) free(addr);
+  if (unicast_url) free(unicast_url);
+  return entry;
+}
+
 play_tree_t*
 parse_playtree(stream_t *stream, int forced) {
   play_tree_parser_t* p;
@@ -839,6 +949,10 @@ play_tree_parser_get_play_tree(play_tree
     if(tree) break;
     play_tree_parser_reset(p);
 
+    tree = parse_nsc(p);
+    if(tree) break;
+    play_tree_parser_reset(p);
+
     // Here come the others formats ( textplain must stay the last one )
     if (forced)
     {


More information about the MPlayer-cvslog mailing list