diff libdlna-0.2.3/src/profiles.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/profiles.c	Sun Oct 10 15:33:18 2010 +0900
@@ -0,0 +1,492 @@
+/*
+ * libdlna: reference DLNA standards implementation.
+ * Copyright (C) 2007 Benjamin Zores <ben@geexbox.org>
+ *
+ * This file is part of libdlna.
+ *
+ * libdlna is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libdlna is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with libdlna; if not, write to the Free Software
+ * Foundation, Inc, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dlna_internals.h"
+#include "profiles.h"
+#include "containers.h"
+
+extern dlna_registered_profile_t dlna_profile_image_jpeg;
+extern dlna_registered_profile_t dlna_profile_image_png;
+extern dlna_registered_profile_t dlna_profile_audio_ac3;
+extern dlna_registered_profile_t dlna_profile_audio_amr;
+extern dlna_registered_profile_t dlna_profile_audio_atrac3;
+extern dlna_registered_profile_t dlna_profile_audio_lpcm;
+extern dlna_registered_profile_t dlna_profile_audio_mp3;
+extern dlna_registered_profile_t dlna_profile_audio_mpeg4;
+extern dlna_registered_profile_t dlna_profile_audio_wma;
+extern dlna_registered_profile_t dlna_profile_av_mpeg1;
+extern dlna_registered_profile_t dlna_profile_av_mpeg2;
+extern dlna_registered_profile_t dlna_profile_av_mpeg4_part2;
+extern dlna_registered_profile_t dlna_profile_av_mpeg4_part10;
+extern dlna_registered_profile_t dlna_profile_av_wmv9;
+
+static void
+dlna_register_profile (dlna_t *dlna, dlna_registered_profile_t *profile)
+{
+  void **p;
+
+  if (!dlna)
+    return;
+
+  if (!dlna->inited)
+    dlna = dlna_init ();
+  
+  p = &dlna->first_profile;
+  while (*p != NULL)
+  {
+    if (((dlna_registered_profile_t *) *p)->id == profile->id)
+      return; /* already registered */
+    p = (void *) &((dlna_registered_profile_t *) *p)->next;
+  }
+  *p = profile;
+  profile->next = NULL;
+}
+
+void
+dlna_register_all_media_profiles (dlna_t *dlna)
+{
+  if (!dlna)
+    return;
+  
+  if (!dlna->inited)
+    dlna = dlna_init ();
+  
+  dlna_register_profile (dlna, &dlna_profile_image_jpeg);
+  dlna_register_profile (dlna, &dlna_profile_image_png);
+  dlna_register_profile (dlna, &dlna_profile_audio_ac3);
+  dlna_register_profile (dlna, &dlna_profile_audio_amr);
+  dlna_register_profile (dlna, &dlna_profile_audio_atrac3);
+  dlna_register_profile (dlna, &dlna_profile_audio_lpcm);
+  dlna_register_profile (dlna, &dlna_profile_audio_mp3);
+  dlna_register_profile (dlna, &dlna_profile_audio_mpeg4);
+  dlna_register_profile (dlna, &dlna_profile_audio_wma);
+  dlna_register_profile (dlna, &dlna_profile_av_mpeg1);
+  dlna_register_profile (dlna, &dlna_profile_av_mpeg2);
+  dlna_register_profile (dlna, &dlna_profile_av_mpeg4_part2);
+  dlna_register_profile (dlna, &dlna_profile_av_mpeg4_part10);
+  dlna_register_profile (dlna, &dlna_profile_av_wmv9);
+}
+
+void
+dlna_register_media_profile (dlna_t *dlna, dlna_media_profile_t profile)
+{
+  if (!dlna)
+    return;
+  
+  if (!dlna->inited)
+    dlna = dlna_init ();
+  
+  switch (profile)
+  {
+  case DLNA_PROFILE_IMAGE_JPEG:
+    dlna_register_profile (dlna, &dlna_profile_image_jpeg);
+    break;
+  case DLNA_PROFILE_IMAGE_PNG:
+    dlna_register_profile (dlna, &dlna_profile_image_png);
+    break;
+  case DLNA_PROFILE_AUDIO_AC3:
+    dlna_register_profile (dlna, &dlna_profile_audio_ac3);
+    break;
+  case DLNA_PROFILE_AUDIO_AMR:
+    dlna_register_profile (dlna, &dlna_profile_audio_amr);
+    break;
+  case DLNA_PROFILE_AUDIO_ATRAC3:
+    dlna_register_profile (dlna, &dlna_profile_audio_atrac3);
+    break;
+  case DLNA_PROFILE_AUDIO_LPCM:
+    dlna_register_profile (dlna, &dlna_profile_audio_lpcm);
+    break;
+  case DLNA_PROFILE_AUDIO_MP3:
+    dlna_register_profile (dlna, &dlna_profile_audio_mp3);
+    break;
+  case DLNA_PROFILE_AUDIO_MPEG4:
+    dlna_register_profile (dlna, &dlna_profile_audio_mpeg4);
+    break;
+  case DLNA_PROFILE_AUDIO_WMA:
+    dlna_register_profile (dlna, &dlna_profile_audio_wma);
+    break;
+  case DLNA_PROFILE_AV_MPEG1:
+    dlna_register_profile (dlna, &dlna_profile_av_mpeg1);
+    break;
+  case DLNA_PROFILE_AV_MPEG2:
+    dlna_register_profile (dlna, &dlna_profile_av_mpeg2);
+    break;
+  case DLNA_PROFILE_AV_MPEG4_PART2:
+    dlna_register_profile (dlna, &dlna_profile_av_mpeg4_part2);
+    break;
+  case DLNA_PROFILE_AV_MPEG4_PART10:
+    dlna_register_profile (dlna, &dlna_profile_av_mpeg4_part10);
+    break;
+  case DLNA_PROFILE_AV_WMV9:
+    dlna_register_profile (dlna, &dlna_profile_av_wmv9);
+    break;
+  default:
+    break;
+  }
+}
+
+dlna_t *
+dlna_init (void)
+{
+  dlna_t *dlna;
+
+  dlna = malloc (sizeof (dlna_t));
+  dlna->inited = 1;
+  dlna->verbosity = 0;
+  dlna->first_profile = NULL;
+  
+  /* register all FFMPEG demuxers */
+  av_register_all ();
+
+  return dlna;
+}
+
+void
+dlna_uninit (dlna_t *dlna)
+{
+  if (!dlna)
+    return;
+
+  dlna->inited = 0;
+  if (dlna->verbosity)
+    fprintf (stderr, "DLNA: uninit\n");
+  dlna->first_profile = NULL;
+  free (dlna);
+}
+
+void
+dlna_set_verbosity (dlna_t *dlna, int level)
+{
+  if (!dlna)
+    return;
+
+  dlna->verbosity = level;
+}
+
+void
+dlna_set_extension_check (dlna_t *dlna, int level)
+{
+  if (!dlna)
+    return;
+
+  dlna->check_extensions = level;
+}
+
+static av_codecs_t *
+av_profile_get_codecs (AVFormatContext *ctx)
+{
+  av_codecs_t *codecs = NULL;
+  unsigned int i;
+  int audio_stream = -1, video_stream = -1;
+ 
+  codecs = malloc (sizeof (av_codecs_t));
+
+  for (i = 0; i < ctx->nb_streams; i++)
+  {
+    if (audio_stream == -1 &&
+        ctx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
+    {
+      audio_stream = i;
+      continue;
+    }
+    else if (video_stream == -1 &&
+             ctx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
+    {
+      video_stream = i;
+      continue;
+    }
+  }
+
+  codecs->as = audio_stream >= 0 ? ctx->streams[audio_stream] : NULL;
+  codecs->ac = audio_stream >= 0 ? ctx->streams[audio_stream]->codec : NULL;
+
+  codecs->vs = video_stream >= 0 ? ctx->streams[video_stream] : NULL;
+  codecs->vc = video_stream >= 0 ? ctx->streams[video_stream]->codec : NULL;
+
+  /* check for at least one video stream and one audio stream in container */
+  if (!codecs->ac && !codecs->vc)
+  {
+    free (codecs);
+    return NULL;
+  }
+  
+  return codecs;
+}
+
+static int
+match_file_extension (const char *filename, const char *extensions)
+{
+  const char *ext, *p;
+  char ext1[32], *q;
+
+  if (!filename)
+    return 0;
+
+  ext = strrchr (filename, '.');
+  if (ext)
+  {
+    ext++;
+    p = extensions;
+    for (;;)
+    {
+      q = ext1;
+      while (*p != '\0' && *p != ',' && (q - ext1 < (int) sizeof (ext1) - 1))
+        *q++ = *p++;
+      *q = '\0';
+      if (!strcasecmp (ext1, ext))
+        return 1;
+      if (*p == '\0')
+        break;
+      p++;
+    }
+  }
+  
+  return 0;
+}
+
+dlna_profile_t *
+dlna_guess_media_profile (dlna_t *dlna, const char *filename)
+{
+  AVFormatContext *ctx;
+  dlna_registered_profile_t *p;
+  dlna_profile_t *profile = NULL;
+  dlna_container_type_t st;
+  av_codecs_t *codecs;
+
+  if (!dlna)
+    return NULL;
+  
+  if (!dlna->inited)
+    dlna = dlna_init ();
+  
+  if (av_open_input_file (&ctx, filename, NULL, 0, NULL) != 0)
+  {
+    if (dlna->verbosity)
+      fprintf (stderr, "can't open file: %s\n", filename);
+    return NULL;
+  }
+
+  if (av_find_stream_info (ctx) < 0)
+  {
+    if (dlna->verbosity)
+      fprintf (stderr, "can't find stream info\n");
+    return NULL;
+  }
+
+#ifdef HAVE_DEBUG
+  dump_format (ctx, 0, NULL, 0);
+#endif /* HAVE_DEBUG */
+
+  /* grab codecs info */
+  codecs = av_profile_get_codecs (ctx);
+  if (!codecs)
+    return NULL;
+
+  /* check for container type */
+  st = stream_get_container (ctx);
+  
+  p = dlna->first_profile;
+  while (p)
+  {
+    dlna_profile_t *prof;
+    
+    if (dlna->check_extensions)
+    {
+      if (p->extensions)
+      {
+        /* check for valid file extension */
+        if (!match_file_extension (filename, p->extensions))
+        {
+          p = p->next;
+          continue;
+        }
+      }
+    }
+    
+    prof = p->probe (ctx, st, codecs);
+    if (prof)
+    {
+      profile = prof;
+      profile->class = p->class;
+      break;
+    }
+    p = p->next;
+  }
+
+  av_close_input_file (ctx);
+  free (codecs);
+  return profile;
+}
+
+/* UPnP ContentDirectory Object Item */
+#define UPNP_OBJECT_ITEM_PHOTO            "object.item.imageItem.photo"
+#define UPNP_OBJECT_ITEM_AUDIO            "object.item.audioItem.musicTrack"
+#define UPNP_OBJECT_ITEM_VIDEO            "object.item.videoItem.movie"
+
+char *
+dlna_profile_upnp_object_item (dlna_profile_t *profile)
+{
+  if (!profile)
+    return NULL;
+
+  switch (profile->class)
+  {
+  case DLNA_CLASS_IMAGE:
+    return UPNP_OBJECT_ITEM_PHOTO;
+  case DLNA_CLASS_AUDIO:
+    return UPNP_OBJECT_ITEM_AUDIO;
+  case DLNA_CLASS_AV:
+    return UPNP_OBJECT_ITEM_VIDEO;
+  default:
+    break;
+  }
+
+  return NULL;
+}
+
+int
+stream_ctx_is_image (AVFormatContext *ctx,
+                     av_codecs_t *codecs, dlna_container_type_t st)
+{
+  /* should only have 1 stream */
+  if (ctx->nb_streams > 1)
+    return 0;
+
+  /* should be inside image container */
+  if (st != CT_IMAGE)
+    return 0;
+
+  if (!codecs->vc)
+    return 0;
+
+  return 1;
+}
+
+int
+stream_ctx_is_audio (av_codecs_t *codecs)
+{
+  /* we need an audio codec ... */
+  if (!codecs->ac)
+    return 0;
+
+  /* ... but no video one */
+  if (codecs->vc)
+    return 0;
+
+  return 1;
+}
+
+int
+stream_ctx_is_av (av_codecs_t *codecs)
+{
+  if (!codecs->as || !codecs->ac || !codecs->vs || !codecs->vc)
+    return 0;
+
+  return 1;
+}
+
+char *
+get_file_extension (const char *filename)
+{
+  char *str = NULL;
+
+  str = strrchr (filename, '.');
+  if (str)
+    str++;
+
+  return str;
+}
+
+char *
+dlna_write_protocol_info (dlna_protocol_info_type_t type,
+                          dlna_org_play_speed_t speed,
+                          dlna_org_conversion_t ci,
+                          dlna_org_operation_t op,
+                          dlna_org_flags_t flags,
+                          dlna_profile_t *p)
+{
+  char protocol[512];
+  char dlna_info[448];
+
+  if (type == DLNA_PROTOCOL_INFO_TYPE_HTTP)
+    sprintf (protocol, "http-get:*:");
+
+  strcat (protocol, p->mime);
+  strcat (protocol, ":");
+  
+  sprintf (dlna_info, "%s=%d;%s=%d;%s=%.2x;%s=%s;%s=%.8x%.24x",
+           "DLNA.ORG_PS", speed, "DLNA.ORG_CI", ci,
+           "DLNA.ORG_OP", op, "DLNA.ORG_PN", p->id,
+           "DLNA.ORG_FLAGS", flags, 0);
+  strcat (protocol, dlna_info);
+
+  return strdup (protocol);
+}
+
+audio_profile_t
+audio_profile_guess (AVCodecContext *ac)
+{
+  audio_profile_t ap = AUDIO_PROFILE_INVALID;
+  
+  if (!ac)
+    return ap;
+
+  ap = audio_profile_guess_aac (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  ap = audio_profile_guess_ac3 (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  ap = audio_profile_guess_amr (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  ap = audio_profile_guess_atrac (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  ap = audio_profile_guess_g726 (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  ap = audio_profile_guess_lpcm (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  ap = audio_profile_guess_mp2 (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  ap = audio_profile_guess_mp3 (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  ap = audio_profile_guess_wma (ac);
+  if (ap != AUDIO_PROFILE_INVALID)
+    return ap;
+
+  return AUDIO_PROFILE_INVALID;
+}