diff libdlna-0.2.3/src/containers.c @ 129:4f6d9621ee00

add multi session streaming & add depending librarys. - libupnp-1.6.6 - libdlna-0.2.3
author Naoya OYAMA <naoya.oyama@gmail.com>
date Sun, 10 Oct 2010 15:33:18 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libdlna-0.2.3/src/containers.c	Sun Oct 10 15:33:18 2010 +0900
@@ -0,0 +1,119 @@
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <ffmpeg/avformat.h>
+
+#include "containers.h"
+#include "profiles.h"
+
+#define MPEG_PACK_HEADER 0xba
+#define MPEG_TS_SYNC_CODE 0x47
+#define MPEG_TS_PACKET_LENGTH 188
+#define MPEG_TS_PACKET_LENGTH_DLNA 192 /* prepends 4 bytes to TS packet */
+
+static const struct {
+  const char *name;
+  const dlna_container_type_t type;
+} avf_format_mapping[] = {
+  { "image2",                     CT_IMAGE         },
+  { "asf",                        CT_ASF           },
+  { "amr",                        CT_AMR           },
+  { "aac",                        CT_AAC           },
+  { "ac3",                        CT_AC3           },
+  { "mp3",                        CT_MP3           },
+  { "wav",                        CT_WAV           },
+  { "mov,mp4,m4a,3gp,3g2,mj2",    CT_MOV           },
+  { "mpeg",                       CT_FF_MPEG       },
+  { "mpegts",                     CT_FF_MPEG_TS    },
+  { NULL, 0 }
+};
+
+static dlna_container_type_t
+mpeg_find_container_type (const char *filename)
+{
+  unsigned char buffer[2*MPEG_TS_PACKET_LENGTH_DLNA+1];
+  int fd, i;
+
+  /* read file header */
+  fd = open (filename, O_RDONLY);
+  read (fd, buffer, 2 * MPEG_TS_PACKET_LENGTH_DLNA); 
+  close (fd);
+
+  /* check for MPEG-TS container */
+  for (i = 0; i < MPEG_TS_PACKET_LENGTH; i++)
+  {
+    if (buffer[i] == MPEG_TS_SYNC_CODE)
+    {
+      if (buffer[i + MPEG_TS_PACKET_LENGTH] == MPEG_TS_SYNC_CODE)
+        return CT_MPEG_TRANSPORT_STREAM;
+    }
+  }
+
+  /* check for DLNA specific MPEG-TS container */
+  for (i = 0; i < MPEG_TS_PACKET_LENGTH_DLNA; i++)
+  {
+    if (buffer[i] == MPEG_TS_SYNC_CODE)
+    {
+      if (buffer[i + MPEG_TS_PACKET_LENGTH_DLNA] == MPEG_TS_SYNC_CODE)
+      {
+        if (buffer[i] == 0x00 && buffer [i+1] == 0x00 &&
+            buffer [i+2] == 0x00 && buffer [i+3] == 0x00)
+          return CT_MPEG_TRANSPORT_STREAM_DLNA_NO_TS; /* empty timestamp */
+        else
+          return CT_MPEG_TRANSPORT_STREAM_DLNA; /* valid timestamp */
+      }
+    }
+  }
+
+  /* check for MPEG-PS and MPEG-(P)ES container */
+  if (buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0x01)
+    return (buffer[3] == MPEG_PACK_HEADER) ?
+      CT_MPEG_PROGRAM_STREAM : CT_MPEG_ELEMENTARY_STREAM;
+
+  return CT_UNKNOWN;
+}
+
+static dlna_container_type_t
+mov_find_container_type (const char *filename)
+{
+  if (!filename)
+    return CT_UNKNOWN;
+
+  if (!strcasecmp (get_file_extension (filename), "3gp") ||
+      !strcasecmp (get_file_extension (filename), "3gpp") ||
+      !strcasecmp (get_file_extension (filename), "3g2"))
+    return CT_3GP;
+
+  return CT_MP4;
+}
+
+dlna_container_type_t
+stream_get_container (AVFormatContext *ctx)
+{
+  int i;
+
+#ifdef HAVE_DEBUG
+  fprintf (stderr, "Found container: %s\n", ctx->iformat->name);
+#endif /* HAVE_DEBUG */
+  
+  for (i = 0; avf_format_mapping[i].name; i++)
+    if (!strcmp (ctx->iformat->name, avf_format_mapping[i].name))
+    {
+      switch (avf_format_mapping[i].type)
+      {
+      case CT_FF_MPEG:
+      case CT_FF_MPEG_TS:
+        return mpeg_find_container_type (ctx->filename);
+      case CT_MOV:
+        return mov_find_container_type (ctx->filename);
+      default:
+        return avf_format_mapping[i].type;
+      }
+    }
+
+  /* unknown or invalid container */
+  return CT_UNKNOWN;
+}