diff libdlna-0.2.3/src/av_mpeg2.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/av_mpeg2.c	Sun Oct 10 15:33:18 2010 +0900
@@ -0,0 +1,644 @@
+/*
+ * 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "dlna_internals.h"
+#include "profiles.h"
+#include "containers.h"
+
+typedef struct mpeg_ps_es_stream_s {
+  int width;
+  int height;
+} mpeg_ps_es_stream_t;
+
+typedef struct mpeg_ts_stream_s {
+  int width;
+  int height;
+  int fps_num;
+  int fps_den;
+} mpeg_ts_stream_t;
+
+static mpeg_ps_es_stream_t mpeg_ps_es_valid_streams_ntsc[] = {
+  { 720, 480 },
+  { 704, 480 },
+  { 544, 480 },
+  { 480, 480 },
+  { 352, 480 },
+  { 352, 240 }
+};
+
+static mpeg_ps_es_stream_t mpeg_ps_es_valid_streams_pal[] = {
+  { 720, 576 },
+  { 704, 576 },
+  { 544, 576 },
+  { 480, 576 },
+  { 352, 576 },
+  { 352, 288 }
+};
+
+static mpeg_ts_stream_t mpeg_ts_valid_streams_eu_sd[] = {
+  { 720, 576, 25, 1},
+  { 544, 576, 25, 1},
+  { 480, 576, 25, 1},
+  { 352, 576, 25, 1},
+  { 252, 288, 25, 1}
+};
+
+static mpeg_ts_stream_t mpeg_ts_valid_streams_na_sd[] = {
+  { 720, 480, 30, 1001},
+  { 704, 480, 30, 1001},
+  { 704, 480, 30, 1},
+  { 704, 480, 24, 1001},
+  { 704, 480, 24, 1},
+  { 640, 480, 30, 1001},
+  { 640, 480, 30, 1},
+  { 640, 480, 24, 1001},
+  { 640, 480, 24, 1},
+  { 544, 480, 30, 1001},
+  { 480, 480, 30, 1001},
+  { 352, 480, 30, 1001}
+};
+
+static mpeg_ts_stream_t mpeg_ts_valid_streams_na_hd[] = {
+  { 1920, 1080, 30, 1001},
+  { 1920, 1080, 30, 1},
+  { 1920, 1080, 24, 1001},
+  { 1920, 1080, 24, 1},
+  { 1280, 720, 30, 1001},
+  { 1280, 720, 30, 1},
+  { 1280, 720, 24, 1001},
+  { 1280, 720, 24, 1},
+  { 1440, 1080, 30, 1001},
+  { 1440, 1080, 30, 1},
+  { 1440, 1080, 24, 1001},
+  { 1440, 1080, 24, 1},
+  { 1280, 1080, 30, 1001},
+  { 1280, 1080, 30, 1},
+  { 1280, 1080, 24, 1001},
+  { 1280, 1080, 24, 1}
+};
+
+/* Profile for NTSC-formatted AV class media */
+static dlna_profile_t mpeg_ps_ntsc = {
+  .id = "MPEG_PS_NTSC",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* Profile for NTSC-formatted AV class media */
+static dlna_profile_t mpeg_ps_ntsc_xac3 = {
+  .id = "MPEG_PS_NTSC_XAC3",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* Profile for PAL-formatted AV class media */
+static dlna_profile_t mpeg_ps_pal = {
+  .id = "MPEG_PS_PAL",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* Profile for PAL-formatted AV class media */
+static dlna_profile_t mpeg_ps_pal_xac3 = {
+  .id = "MPEG_PS_PAL_XAC3",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* MPEG-2 Main Profile at Low Level AAC LC audio encapsulated in
+   MPEG-2 transport stream with zero value timestamp */
+static dlna_profile_t mpeg_ts_mp_ll_aac = {
+  .id = "MPEG_TS_MP_LL_AAC",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_CIF30
+};
+
+/* MPEG-2 Main Profile at Low Level AAC LC audio encapsulated in
+   MPEG-2 transport stream with valid value timestamp */
+static dlna_profile_t mpeg_ts_mp_ll_aac_t = {
+  .id = "MPEG_TS_MP_LL_AAC_T",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_CIF30
+};
+
+/* MPEG-2 Main Profile at Low Level AAC LC audio encapsulated in
+   MPEG-2 transport stream without a Timestamp field */
+static dlna_profile_t mpeg_ts_mp_ll_aac_iso = {
+  .id = "MPEG_TS_MP_LL_AAC_ISO",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_CIF30
+};
+
+/* European region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet with zero value timestamp */
+static dlna_profile_t mpeg_ts_sd_eu = {
+  .id = "MPEG_TS_SD_EU",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_SD
+};
+
+/* European region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet with a valid non-zero value timestamp */
+static dlna_profile_t mpeg_ts_sd_eu_t = {
+  .id = "MPEG_TS_SD_EU_T",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_SD
+};
+
+/* European region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet without a Timestamp field */
+static dlna_profile_t mpeg_ts_sd_eu_iso = {
+  .id = "MPEG_TS_SD_EU_ISO",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* North America region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet with zero value timestamp */
+static dlna_profile_t mpeg_ts_sd_na = {
+  .id = "MPEG_TS_SD_NA",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_SD
+};
+
+/* North America region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet with a valid non-zero value timestamp */
+static dlna_profile_t mpeg_ts_sd_na_t = {
+  .id = "MPEG_TS_SD_NA_T",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_SD
+};
+
+/* North America region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet without a Timestamp field */
+static dlna_profile_t mpeg_ts_sd_na_iso = {
+  .id = "MPEG_TS_SD_NA_ISO",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* North America region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet with zero value timestamp */
+static dlna_profile_t mpeg_ts_sd_na_xac3 = {
+  .id = "MPEG_TS_SD_NA_XAC3",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_SD
+};
+
+/* North America region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet with a valid non-zero value timestamp */
+static dlna_profile_t mpeg_ts_sd_na_xac3_t = {
+  .id = "MPEG_TS_SD_NA_XAC3_T",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_SD
+};
+
+/* North America region profile for Standard Definition AV class utilizing
+   a DLNA Transport Packet without a Timestamp field */
+static dlna_profile_t mpeg_ts_sd_na_xac3_iso = {
+  .id = "MPEG_TS_SD_NA_XAC3_ISO",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* North America region profile for High Definition AV class utilizing
+   a DLNA Transport Packet with zero value timestamp */
+static dlna_profile_t mpeg_ts_hd_na = {
+  .id = "MPEG_TS_HD_NA",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_HD
+};
+
+/* North America region profile for High Definition AV class utilizing
+   a DLNA Transport Packet with a valid non-zero value timestamp */
+static dlna_profile_t mpeg_ts_hd_na_t = {
+  .id = "MPEG_TS_HD_NA_T",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_HD
+};
+
+/* North America region profile for High Definition AV class utilizing
+   a DLNA Transport Packet without a Timestamp field */
+static dlna_profile_t mpeg_ts_hd_na_iso = {
+  .id = "MPEG_TS_HD_NA_ISO",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_HD
+};
+
+/* North America region profile for transcoded High Definition AV class
+   media with a zero value timestamp */
+static dlna_profile_t mpeg_ts_hd_na_xac3 = {
+  .id = "MPEG_TS_HD_NA_XAC3",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_HD
+};
+
+/* North America region profile for transcoded High Definition AV class
+   media with a valid non-zero value timestamp */
+static dlna_profile_t mpeg_ts_hd_na_xac3_t = {
+  .id = "MPEG_TS_HD_NA_XAC3_T",
+  .mime = MIME_VIDEO_MPEG_TS,
+  .label = LABEL_VIDEO_HD
+};
+
+/* North America region profile for transcoded High Definition AV class
+   media without a Timestamp field */
+static dlna_profile_t mpeg_ts_hd_na_xac3_iso = {
+  .id = "MPEG_TS_HD_NA_XAC3_ISO",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_HD
+};
+
+/* Profile defining ES encapsulation for transport of MPEG_PS_PAL over RTP */
+static dlna_profile_t mpeg_es_pal = {
+  .id = "MPEG_ES_PAL",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* Profile defining ES encapsulation for transport of MPEG_PS_NTSC over RTP */
+static dlna_profile_t mpeg_es_ntsc = {
+  .id = "MPEG_ES_NTSC",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* Profile defining ES encapsulation for transport of
+   MPEG_PS_PAL_XAC3 over RTP */
+static dlna_profile_t mpeg_es_pal_xac3 = {
+  .id = "MPEG_ES_PAL_XAC3",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+/* Profile defining ES encapsulation for transport of
+   MPEG_PS_NTSC_XAC3 over RTP */
+static dlna_profile_t mpeg_es_ntsc_xac3 = {
+  .id = "MPEG_ES_NTSC_XAC3",
+  .mime = MIME_VIDEO_MPEG,
+  .label = LABEL_VIDEO_SD
+};
+
+static int
+is_mpeg_ps_es_audio_stream_lpcm (AVFormatContext *ctx dlna_unused,
+                                 av_codecs_t *codecs)
+{
+  if (audio_profile_guess_lpcm (codecs->ac) != AUDIO_PROFILE_LPCM)
+    return 0;
+  
+  /* audio bit rate: 1.536 Mbps for stereo, 768 Kbps for mono */
+  if (codecs->ac->channels == 2 && codecs->ac->bit_rate > 1536000)
+    return 0;
+  if (codecs->ac->channels == 1 && codecs->ac->bit_rate > 768000)
+    return 0;
+  
+  return 1;
+}
+
+static int
+is_mpeg_ps_es_audio_stream_extended_ac3 (AVFormatContext *ctx dlna_unused,
+                                      av_codecs_t *codecs)
+{
+  return (audio_profile_guess_ac3 (codecs->ac) == AUDIO_PROFILE_AC3_EXTENDED)
+    ? 1 : 0;
+}
+
+static int
+is_mpeg_ps_es_audio_stream_ac3 (AVFormatContext *ctx dlna_unused,
+                                av_codecs_t *codecs)
+{
+  return (audio_profile_guess_ac3 (codecs->ac) == AUDIO_PROFILE_AC3) ? 1 : 0;
+}
+
+static int
+is_mpeg_ps_es_audio_stream_mp2 (AVFormatContext *ctx dlna_unused,
+                                av_codecs_t *codecs)
+{
+  if (audio_profile_guess_mp2 (codecs->ac) != AUDIO_PROFILE_MP2)
+    return 0;
+
+  /* supported channels: 1/0, 1/0 + 1/0, 2/0 */
+  if (codecs->ac->channels > 2)
+    return 0;
+
+  /* audio bit rate: 64-192 Kbps for mono, 64-384 Kbps for stereo */
+  if (codecs->ac->channels == 1 &&
+      (codecs->ac->bit_rate < 64000 || codecs->ac->bit_rate > 192000))
+    return 0;
+  if (codecs->ac->channels == 2 &&
+      (codecs->ac->bit_rate < 64000 || codecs->ac->bit_rate > 384000))
+    return 0;
+  
+  return 1;
+}
+
+static int
+is_mpeg_ts_audio_stream_mp2 (AVFormatContext *ctx dlna_unused,
+                             av_codecs_t *codecs)
+{
+  return (audio_profile_guess_mp2 (codecs->ac) == AUDIO_PROFILE_MP2) ? 1 : 0;
+}
+
+static int
+is_mpeg_ts_audio_stream_ac3 (AVFormatContext *ctx dlna_unused,
+                             av_codecs_t *codecs)
+{
+  return (audio_profile_guess_ac3 (codecs->ac) == AUDIO_PROFILE_AC3) ? 1 : 0;
+}
+
+static dlna_profile_t *
+probe_mpeg_ps_es (AVFormatContext *ctx, av_codecs_t *codecs,
+                  dlna_profile_t *pal, dlna_profile_t *pal_xac3,
+                  dlna_profile_t *ntsc, dlna_profile_t *ntsc_xac3)
+{
+  int i;
+
+  /* determine region through frame rate */
+  if ((codecs->vs->r_frame_rate.num == 30000 &&
+       codecs->vs->r_frame_rate.den == 1001)) /* NTSC */
+  {
+    for (i = 0; i < (int) (sizeof (mpeg_ps_es_valid_streams_ntsc)
+                           / sizeof (mpeg_ps_es_stream_t)); i++)
+    {
+      if (mpeg_ps_es_valid_streams_ntsc[i].width == codecs->vc->width &&
+          mpeg_ps_es_valid_streams_ntsc[i].height == codecs->vc->height)
+      {
+        if (is_mpeg_ps_es_audio_stream_extended_ac3 (ctx, codecs))
+          return ntsc_xac3;
+        else if (is_mpeg_ps_es_audio_stream_lpcm (ctx, codecs) ||
+                 is_mpeg_ps_es_audio_stream_ac3 (ctx, codecs) ||
+                 is_mpeg_ps_es_audio_stream_mp2 (ctx, codecs))
+          return ntsc;
+
+        return NULL;
+      }
+    }
+
+    /* invalid resolution */
+    return NULL;
+  }
+  else if (codecs->vs->r_frame_rate.num == 25 &&
+           codecs->vs->r_frame_rate.den == 1) /* PAL */
+  {
+    for (i = 0; i < (int) (sizeof (mpeg_ps_es_valid_streams_pal)
+                           / sizeof (mpeg_ps_es_stream_t)); i++)
+    {
+      if (mpeg_ps_es_valid_streams_pal[i].width == codecs->vc->width &&
+          mpeg_ps_es_valid_streams_pal[i].height == codecs->vc->height)
+      {
+        if (is_mpeg_ps_es_audio_stream_extended_ac3 (ctx, codecs))
+          return pal_xac3;
+        else if (is_mpeg_ps_es_audio_stream_lpcm (ctx, codecs) ||
+                 is_mpeg_ps_es_audio_stream_ac3 (ctx, codecs) ||
+                 is_mpeg_ps_es_audio_stream_mp2 (ctx, codecs))
+          return pal;
+
+        return NULL;
+      }
+    }
+
+    /* invalid resolution */
+    return NULL;
+  }
+
+  return NULL;
+}
+
+static dlna_profile_t *
+probe_mpeg_ps (AVFormatContext *ctx, av_codecs_t *codecs)
+{
+  return probe_mpeg_ps_es (ctx, codecs,
+                           &mpeg_ps_pal, &mpeg_ps_pal_xac3,
+                           &mpeg_ps_ntsc, &mpeg_ps_ntsc_xac3);
+}
+
+static dlna_profile_t *
+probe_mpeg_es (AVFormatContext *ctx, av_codecs_t *codecs)
+{
+  return probe_mpeg_ps_es (ctx, codecs,
+                           &mpeg_es_pal, &mpeg_es_pal_xac3,
+                           &mpeg_es_ntsc, &mpeg_es_ntsc_xac3);
+}
+
+static dlna_profile_t *
+probe_mpeg_ts (AVFormatContext *ctx,
+               av_codecs_t *codecs, dlna_container_type_t st)
+{
+  int xac3 = 0; /* extended AC3 audio */
+  int i;
+  
+  /* check for MPEG-2 MP@LL profile */
+  if (codecs->ac->codec_id == CODEC_ID_AAC)
+  {
+    /* 352x288 only */
+    if (codecs->vc->width != 352 && codecs->vc->height != 288)
+      return NULL;
+
+    /* 30 fps */
+    if (codecs->vs->r_frame_rate.num != 30 &&
+        codecs->vs->r_frame_rate.den != 1)
+      return NULL;
+
+    /* video bitrate is less or equal to 4 Mbps */
+    if (codecs->vc->bit_rate > 4000000)
+      return NULL;
+
+    /* audio bitrate is less or equal to 256 Kbps */
+    if (codecs->ac->bit_rate > 256000)
+      return NULL;
+
+    switch (st)
+    {
+    case CT_MPEG_TRANSPORT_STREAM:
+      return &mpeg_ts_mp_ll_aac_iso;
+    case CT_MPEG_TRANSPORT_STREAM_DLNA:
+      return &mpeg_ts_mp_ll_aac_t;
+    case CT_MPEG_TRANSPORT_STREAM_DLNA_NO_TS:
+      return &mpeg_ts_mp_ll_aac;
+    default:
+      return NULL;
+    }
+  }
+
+  /* check for Region: only Europe supports 25 fps (50i) */
+  if (codecs->vs->r_frame_rate.num == 25 &&
+      codecs->vs->r_frame_rate.den == 1)
+  {
+    for (i = 0; i < (int) (sizeof (mpeg_ts_valid_streams_eu_sd)
+                           / sizeof (mpeg_ts_stream_t)); i++)
+    {
+      if (mpeg_ts_valid_streams_eu_sd[i].width == codecs->vc->width &&
+          mpeg_ts_valid_streams_eu_sd[i].height == codecs->vc->height &&
+          mpeg_ts_valid_streams_eu_sd[i].fps_num == 25 &&
+          mpeg_ts_valid_streams_eu_sd[i].fps_den == 1)
+      {
+        if (is_mpeg_ts_audio_stream_ac3 (ctx, codecs) ||
+            is_mpeg_ts_audio_stream_mp2 (ctx, codecs))
+        {
+          switch (st)
+          {
+          case CT_MPEG_TRANSPORT_STREAM:
+            return &mpeg_ts_sd_eu_iso;
+          case CT_MPEG_TRANSPORT_STREAM_DLNA:
+            return &mpeg_ts_sd_eu_t;
+          case CT_MPEG_TRANSPORT_STREAM_DLNA_NO_TS:
+            return &mpeg_ts_sd_eu;
+          default:
+            return NULL;
+          }
+        }
+
+        /* invalid audio stream */
+        return NULL;
+      }
+    }
+
+    /* invalid resolution */
+    return NULL;
+  }
+
+  /* now comes the stupid part: there's no way to differentiate region
+     codes between North America (NA) and Korea (KO) as both have exactly
+     the same requirements !! NA however supports additional stream formats
+     so all streams will be declared as NA ones (which shouldn't bother
+     the real KO ones). */
+
+  /* NA and KO streams can be either SD (Standard Definition)
+     or HD (High-Definition) and only support AC3 as audio stream codec */
+
+  /* maximum system bit rate is 19.3927 Mb/s */
+  if (ctx->bit_rate > 19392700)
+    return NULL;
+
+  if (codecs->ac->codec_id != CODEC_ID_AC3)
+    return NULL;
+
+  /* 48 KHz only */
+  if (codecs->ac->sample_rate != 48000)
+    return NULL;
+
+  /* up to 5 audio channels */
+  if (codecs->ac->channels > 5)
+    return NULL;
+
+  /* audio bitrate up to 448 Kbps (or 640 for extended AC3) */
+  if (codecs->ac->bit_rate > 448000)
+    xac3 = 1;
+  if (codecs->ac->bit_rate > 640000)
+    return NULL;
+
+  /* look for compatible SD video stream */
+  for (i = 0; i < (int) (sizeof (mpeg_ts_valid_streams_na_sd)
+                         / sizeof (mpeg_ts_stream_t)); i++)
+  {
+    if (mpeg_ts_valid_streams_na_sd[i].width == codecs->vc->width &&
+        mpeg_ts_valid_streams_na_sd[i].height == codecs->vc->height &&
+        mpeg_ts_valid_streams_na_sd[i].fps_num
+        == codecs->vs->r_frame_rate.num &&
+        mpeg_ts_valid_streams_na_sd[i].fps_den
+        == codecs->vs->r_frame_rate.num)
+    {
+      switch (st)
+      {
+      case CT_MPEG_TRANSPORT_STREAM:
+        return xac3 ? &mpeg_ts_sd_na_xac3_iso : &mpeg_ts_sd_na_iso;
+      case CT_MPEG_TRANSPORT_STREAM_DLNA:
+        return xac3 ? &mpeg_ts_sd_na_xac3_t : &mpeg_ts_sd_na_t;
+      case CT_MPEG_TRANSPORT_STREAM_DLNA_NO_TS:
+        return xac3 ? &mpeg_ts_sd_na_xac3 : &mpeg_ts_sd_na;
+      default:
+        return NULL;
+      }
+    }
+  }
+
+  /* look for compatible HD video stream */
+  for (i = 0; i < (int) (sizeof (mpeg_ts_valid_streams_na_hd)
+                         / sizeof (mpeg_ts_stream_t)); i++)
+  {
+    if (mpeg_ts_valid_streams_na_hd[i].width == codecs->vc->width &&
+        mpeg_ts_valid_streams_na_hd[i].height == codecs->vc->height &&
+        mpeg_ts_valid_streams_na_hd[i].fps_num
+        == codecs->vs->r_frame_rate.num &&
+        mpeg_ts_valid_streams_na_hd[i].fps_den
+        == codecs->vs->r_frame_rate.num)
+    {
+      switch (st)
+      {
+      case CT_MPEG_TRANSPORT_STREAM:
+        return xac3 ? &mpeg_ts_hd_na_xac3_iso : &mpeg_ts_hd_na_iso;
+      case CT_MPEG_TRANSPORT_STREAM_DLNA:
+        return xac3 ? &mpeg_ts_hd_na_xac3_t : &mpeg_ts_hd_na_t;
+      case CT_MPEG_TRANSPORT_STREAM_DLNA_NO_TS:
+        return xac3 ? &mpeg_ts_hd_na_xac3 : &mpeg_ts_hd_na;
+      default:
+        return NULL;
+      }
+    }
+  }
+
+  /* no compliant resolution found */
+  return NULL;
+}
+
+static dlna_profile_t *
+probe_mpeg2 (AVFormatContext *ctx,
+             dlna_container_type_t st,
+             av_codecs_t *codecs)
+{
+  if (!stream_ctx_is_av (codecs))
+    return NULL;
+  
+  /* check for MPEG-2 video codec */
+  if (codecs->vc->codec_id != CODEC_ID_MPEG2VIDEO)
+    return NULL;
+
+  switch (st)
+  {
+  case CT_MPEG_ELEMENTARY_STREAM:
+    return probe_mpeg_es (ctx, codecs);
+  case CT_MPEG_PROGRAM_STREAM:
+    return probe_mpeg_ps (ctx, codecs);
+  case CT_MPEG_TRANSPORT_STREAM:
+  case CT_MPEG_TRANSPORT_STREAM_DLNA:
+  case CT_MPEG_TRANSPORT_STREAM_DLNA_NO_TS:
+    return probe_mpeg_ts (ctx, codecs, st);
+  default:
+    break;
+  }
+  
+  return NULL;
+}
+
+dlna_registered_profile_t dlna_profile_av_mpeg2 = {
+  .id = DLNA_PROFILE_AV_MPEG2,
+  .class = DLNA_CLASS_AV,
+  .extensions = "mpg,mpeg,mpe,m2v,mp2p,mp2t,ts,ps,pes",
+  .probe = probe_mpeg2,
+  .next = NULL
+};