dlna: introduce a dlna lower layer
authorLeandro Dorileo <leandro.maciel.dorileo@intel.com>
Fri, 17 Jan 2014 12:21:19 +0000 (10:21 -0200)
committerLeandro Dorileo <leandro.maciel.dorileo@intel.com>
Wed, 29 Jan 2014 11:45:40 +0000 (09:45 -0200)
A small change on how the dlna profile and mime are defined, now LMS
knows about the rules and aplies it wherever possible.

In the next patches we make use of it.

src/lib/Makefile.am
src/lib/lightmediascanner_dlna.c [new file with mode: 0644]
src/lib/lightmediascanner_dlna.h [new file with mode: 0644]
src/lib/lightmediascanner_dlna_rules.c [new file with mode: 0644]
src/lib/lightmediascanner_utils.h

index 5368f40..731cdb4 100644 (file)
@@ -11,7 +11,7 @@ include_HEADERS = \
        lightmediascanner_utils.h \
        lightmediascanner_db.h \
        lightmediascanner_charset_conv.h
-noinst_HEADERS = lightmediascanner_private.h lightmediascanner_db_private.h
+noinst_HEADERS = lightmediascanner_private.h lightmediascanner_db_private.h lightmediascanner_dlna.h
 
 lib_LTLIBRARIES = liblightmediascanner.la
 
@@ -25,7 +25,9 @@ liblightmediascanner_la_SOURCES = \
        lightmediascanner_db_image.c \
        lightmediascanner_db_audio.c \
        lightmediascanner_db_video.c \
-       lightmediascanner_db_playlist.c
+       lightmediascanner_db_playlist.c \
+       lightmediascanner_dlna_rules.c \
+       lightmediascanner_dlna.c
 
 liblightmediascanner_la_LIBADD = -ldl @SQLITE3_LIBS@ @LTLIBICONV@
 liblightmediascanner_la_LDFLAGS = -version-info @version_info@
diff --git a/src/lib/lightmediascanner_dlna.c b/src/lib/lightmediascanner_dlna.c
new file mode 100644 (file)
index 0000000..a04d43b
--- /dev/null
@@ -0,0 +1,424 @@
+/**
+ * Copyright (C) 2013 by Intel Corporation
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * @author Leandro Dorileo <leandro.maciel.dorileo@intel.com>
+ */
+
+#include <lightmediascanner_db.h>
+#include <lightmediascanner_dlna.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct dlna_video_container_rule {
+    const struct lms_string_size *container;
+    const struct lms_dlna_video_profile *rules;
+};
+
+struct dlna_audio_container_rule {
+    const struct lms_string_size *container;
+    const struct lms_dlna_audio_profile *rules;
+};
+
+struct dlna_image_container_rule {
+    const struct lms_string_size *container;
+    const struct lms_dlna_image_profile *rules;
+};
+
+DECL_STR(_container_mp4, "mp4");
+DECL_STR(_container_3gp, "3gp");
+DECL_STR(_container_asf, "asf");
+DECL_STR(_container_wma2, "wma2");
+DECL_STR(_container_jpeg, "jpeg");
+DECL_STR(_container_png, "png");
+DECL_STR(_container_wave, "wave");
+
+static const struct dlna_video_container_rule _video_container_rules[] = {
+    {
+        .container = &_container_mpeg,
+        .rules = _dlna_mpeg_rules,
+    },
+    {
+        .container = &_container_mpegts,
+        .rules = _dlna_mpegts_rules,
+    },
+    {
+        .container = &_container_mp4,
+        .rules = _dlna_mp4_video_rules,
+    },
+};
+
+static const struct dlna_audio_container_rule _audio_container_rules[] = {
+    {
+        .container = &_container_mp3,
+        .rules = _dlna_mp3_rules,
+    },
+    {
+        .container = &_container_3gp,
+        .rules = _dlna_3gp_audio_rules,
+    },
+    {
+        .container = &_container_mp4,
+        .rules = _dlna_mp4_audio_rules,
+    },
+    {
+        .container = &_container_asf,
+        .rules = _dlna_wma_rules,
+    },
+    {
+        .container = &_container_wma2,
+        .rules = _dlna_wma_rules,
+    },
+    {
+        .container = &_container_wave,
+        .rules = _dlna_wave_rules,
+    },
+};
+
+static const struct dlna_image_container_rule _image_container_rules[] = {
+    {
+        .container = &_container_jpeg,
+        .rules = _dlna_jpeg_rules,
+    },
+    {
+        .container = &_container_png,
+        .rules = _dlna_png_rules,
+    },
+};
+
+static bool
+_uint_vector_has_value(const unsigned int *list, const unsigned int wanted)
+{
+    const unsigned int *itr;
+
+    for (itr = list; *itr != UINT32_MAX; itr++)
+        if (*itr == wanted) return true;
+
+    return false;
+}
+
+static bool
+_double_vector_has_value(const double *list, const double wanted, const double accepted_error)
+{
+    const double *itr;
+
+    for (itr = list; !isnan(*itr); itr++)
+        if (fabs(*itr - wanted) < accepted_error) return true;
+
+    return false;
+}
+
+static bool
+_string_vector_has_value(const char **list, const char *wanted)
+{
+    const char **itr;
+
+    for (itr = list; *itr != NULL; itr++)
+        if (!strcmp(*itr, wanted)) return true;
+
+    return false;
+}
+
+static inline bool
+_dlna_audio_rule_match_stream(const struct lms_dlna_audio_rule *rule,
+                              const struct lms_stream *audio_stream) {
+
+    if (audio_stream) {
+        if (rule->bitrate &&
+            (audio_stream->audio.bitrate < rule->bitrate->min ||
+             audio_stream->audio.bitrate > rule->bitrate->max)) {
+            return false;
+        }
+        if (rule->rates &&
+            !_uint_vector_has_value(rule->rates->rates,
+                                    audio_stream->audio.sampling_rate))
+            return false;
+
+        if (rule->channels &&
+            (audio_stream->audio.channels < rule->channels->min ||
+             audio_stream->audio.channels > rule->channels->max))
+            return false;
+    }
+
+    if (audio_stream && rule->codec &&
+        strcmp(audio_stream->codec.str, rule->codec->str))
+        return false;
+
+    return true;
+}
+
+static inline bool
+_video_rule_match_stream(const struct lms_dlna_video_rule *rule,
+                         const char *profile, const char *level,
+                         const struct lms_stream *video) {
+    if (rule->res && 
+        (video->video.width != rule->res->width &&
+         video->video.height != rule->res->height))
+        return false;
+
+    if (rule->res_range &&
+        !(video->video.width >= rule->res_range->width_min &&
+          video->video.width <= rule->res_range->width_max &&
+          video->video.height >= rule->res_range->height_min &&
+          video->video.height <= rule->res_range->height_max))
+        return false;
+
+    if (rule->framerate &&
+        !_double_vector_has_value(rule->framerate->framerate,
+                                  video->video.framerate, 0.1))
+        return false;
+
+    if (rule->pixel_aspect && !_string_vector_has_value
+        ((const char **)rule->pixel_aspect->pixel_aspect_ratio,
+         video->video.aspect_ratio.str))
+        return false;
+
+    if (rule->bitrate &&
+        !(video->video.bitrate >= rule->bitrate->min &&
+          video->video.bitrate <= rule->bitrate->max))
+        return false;
+
+    if (rule->levels &&
+        !_string_vector_has_value
+        ((const char **)rule->levels->levels, level))
+        return false;
+
+    if (rule->profiles &&
+        !_string_vector_has_value
+        ((const char **)rule->profiles->profiles, profile))
+        return false;
+
+    return true;
+}
+
+static bool
+_video_rule_is_sentinel(const struct lms_dlna_video_rule *video_rule)
+{
+    return (!video_rule->res && !video_rule->bitrate && !video_rule->levels);
+}
+
+static const struct lms_dlna_video_profile *
+_match_video_profile(const struct lms_dlna_video_profile *video_rules,
+                     const struct lms_stream *video,
+                     const struct lms_stream *audio,
+                     const int64_t packet_size) {
+    int i;
+    const struct lms_dlna_video_profile *curr;
+    char *tmp, *p;
+    const char *profile, *level;
+
+    tmp = strdupa(video->codec.str);
+    p = strstr(tmp, "-p");
+    if (!p) profile = "";
+    else {
+        p[0] = '\0';
+        profile = p + 2;
+    }
+
+    p = strstr(profile, "-l");
+    if (!p) level = "";
+    else {
+        p[0] = '\0';
+        level = p + 2;
+    }
+
+    curr = video_rules;
+    for (i = 0; curr->dlna_profile != NULL; i++, curr = video_rules + i) {
+        const struct lms_dlna_video_rule *video_rule;
+        const struct lms_dlna_audio_rule *audio_rule;
+
+        audio_rule = curr->audio_rule;
+
+        if (curr->packet_size &&
+            curr->packet_size->packet_size != packet_size)
+            continue;
+
+        if (!_dlna_audio_rule_match_stream(audio_rule, audio))
+            continue;
+
+        for (video_rule = curr->video_rules;
+             !_video_rule_is_sentinel(video_rule); video_rule++) {
+
+            if (_video_rule_match_stream(video_rule, profile, level, video))
+                return curr;
+        }
+    }
+
+    return NULL;
+}
+
+static const struct lms_dlna_video_profile *
+_get_video_rules(const struct lms_video_info *info) {
+    int i, length;
+
+    if (!info->container.str) return NULL;
+
+    length = sizeof(_video_container_rules) /
+        sizeof(struct dlna_video_container_rule);
+
+    for (i = 0; i < length; i++) {
+        const struct dlna_video_container_rule *curr;
+
+        curr = _video_container_rules + i;
+        if (!strcmp(curr->container->str, info->container.str))
+            return curr->rules;
+    }
+
+    return NULL;
+}
+
+static const struct lms_dlna_audio_profile *
+_get_audio_rules(const struct lms_audio_info *info) {
+    int i, length;
+
+    if (!info->container.str) return NULL;
+
+    length = sizeof(_audio_container_rules) /
+        sizeof(struct dlna_audio_container_rule);
+
+    for (i = 0; i < length; i++) {
+        const struct dlna_audio_container_rule *curr;
+
+        curr = _audio_container_rules + i;
+        if (!strcmp(curr->container->str, info->container.str))
+            return curr->rules;
+    }
+
+    return NULL;
+}
+
+static const struct lms_dlna_image_profile *
+_get_image_rules(const struct lms_image_info *info) {
+    int i, length;
+
+    if (!info->container.str) return NULL;
+
+    length = sizeof(_image_container_rules) /
+        sizeof(struct dlna_image_container_rule);
+
+    for (i = 0; i < length; i++) {
+        const struct dlna_image_container_rule *curr;
+
+        curr = _image_container_rules + i;
+        if (!strcmp(curr->container->str, info->container.str))
+            return curr->rules;
+    }
+
+    return NULL;
+}
+
+const struct lms_dlna_video_profile *
+lms_dlna_get_video_profile(struct lms_video_info *info) {
+    const struct lms_dlna_video_profile *rules;
+    const struct lms_stream *s, *audio_stream, *video_stream;
+
+    audio_stream = video_stream = NULL;
+
+    rules = _get_video_rules(info);
+    if (!rules) return NULL;
+
+    for (s = info->streams; s; s = s->next) {
+        if (s->type == LMS_STREAM_TYPE_VIDEO) {
+            video_stream = s;
+            if (audio_stream) break;
+        } else if (s->type == LMS_STREAM_TYPE_AUDIO) {
+            audio_stream = s;
+            if (video_stream) break;
+        }
+    }
+
+    return _match_video_profile(rules, video_stream, audio_stream,
+                                info->packet_size);
+}
+
+static bool
+_audio_rule_is_sentinel(const struct lms_dlna_audio_profile *audio_rule)
+{
+    return (!audio_rule && !audio_rule->dlna_mime && !audio_rule->audio_rule);
+}
+
+const struct lms_dlna_audio_profile *
+lms_dlna_get_audio_profile(struct lms_audio_info *info) {
+    const struct lms_dlna_audio_profile *rules = _get_audio_rules(info);
+    const struct lms_dlna_audio_profile *profile;
+
+    if (!rules) return NULL;
+
+    for (profile = rules; !_audio_rule_is_sentinel(profile); profile++) {
+        const struct lms_dlna_audio_rule *rule = profile->audio_rule;
+
+        if (rule->bitrate && info->bitrate &&
+            (info->bitrate < rule->bitrate->min ||
+             info->bitrate > rule->bitrate->max))
+            continue;
+
+        if (rule->rates &&
+            !_uint_vector_has_value(rule->rates->rates, info->sampling_rate))
+            continue;
+
+        if (rule->rate_range &&
+            (info->sampling_rate < rule->rate_range->min ||
+             info->sampling_rate > rule->rate_range->max))
+            continue;
+
+        if (rule->channels &&
+            (info->channels < rule->channels->min ||
+             info->channels > rule->channels->max))
+            continue;
+
+        if (rule->codec && strcmp(rule->codec->str, info->codec.str))
+            continue;
+
+        return profile;
+    }
+
+    return NULL;
+}
+
+static bool
+_image_rule_is_sentinel(const struct lms_dlna_image_profile *rule)
+{
+    return (!rule->dlna_profile && !rule->dlna_mime && !rule->image_rule);
+}
+
+const struct lms_dlna_image_profile *
+lms_dlna_get_image_profile(struct lms_image_info *info) {
+    const struct lms_dlna_image_profile *rules = _get_image_rules(info);
+    const struct lms_dlna_image_profile *profile;
+
+    if (!rules) return NULL;
+
+    for (profile = rules; !_image_rule_is_sentinel(profile); profile++) {
+        const struct lms_dlna_image_rule *rule = profile->image_rule;
+
+        if (rule->width && info->width &&
+            (info->width < rule->width->min ||
+             info->width > rule->width->max))
+            continue;
+
+        if (rule->height && info->height &&
+            (info->height < rule->height->min ||
+             info->height > rule->height->max))
+            continue;
+
+        return profile;
+    }
+
+    return NULL;
+}
diff --git a/src/lib/lightmediascanner_dlna.h b/src/lib/lightmediascanner_dlna.h
new file mode 100644 (file)
index 0000000..4f37528
--- /dev/null
@@ -0,0 +1,182 @@
+/**
+ * Copyright (C) 2013 by Intel Corporation
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * @author Leandro Dorileo <leandro.maciel.dorileo@intel.com>
+ */
+
+#include <lightmediascanner_db.h>
+#include <stdio.h>
+#include <math.h>
+
+#ifndef _LIGHTMEDIASCANNER_DLNA_H_
+#define _LIGHTMEDIASCANNER_DLNA_H_
+
+#define MAX_AUDIO_MPEG_VERSIONS 2
+#define MAX_AUDIO_RATES 10
+#define MAX_AUDIO_LEVELS 5
+#define MAX_VIDEO_RULE_LEVEL 13
+#define MAX_VIDEO_RULE_PROFILE 3
+#define MAX_VIDEO_RULE_FRAMERATE 7
+#define MAX_VIDEO_PIXEL_ASPECT 3
+
+#define DLNA_VIDEO_RES(_width, _height)                                 \
+    &(struct dlna_video_res) {.width = _width, .height = _height}       \
+
+#define DLNA_VIDEO_RES_RANGE(_wmin, _wmax, _hmin, _hmax)                \
+    &(struct dlna_video_res_range) {.width_min = _wmin,                 \
+                                         .width_max = _wmax, .height_min = _hmin, \
+                                         .height_max = _hmax}           \
+
+#define DLNA_BITRATE(_min, _max)                        \
+    &(struct dlna_bitrate) {.min = _min, .max = _max}   \
+
+#define DLNA_LEVEL(_val...)                            \
+    &(struct dlna_level) {.levels = {_val, NULL}}       \
+
+#define DLNA_PROFILE(_val...)                           \
+    &(struct dlna_profile) {.profiles = {_val, NULL}}   \
+
+#define DLNA_AUDIO_RATE(_val...)                               \
+    &(struct dlna_audio_rate) {.rates = {_val, UINT32_MAX}}    \
+
+#define DLNA_VIDEO_PIXEL_ASPECT(_val...)                               \
+    &(struct dlna_video_pixel_aspect) {                                        \
+                                       .pixel_aspect_ratio = {_val, NULL}} \
+
+#define DLNA_VIDEO_FRAMERATE(_val...)                                  \
+    &(struct dlna_video_framerate) {.framerate = {_val, NAN}}           \
+
+#define DLNA_VIDEO_PACKETSIZE(_packet_size)                            \
+    &(struct dlna_video_packet_size) {.packet_size = _packet_size}     \
+
+#define DLNA_VIDEO_FRAMERATE_RANGE(_min, _max)                          \
+    &(struct dlna_video_framerate_range) {.min = _min, .max = _max}     \
+
+struct dlna_bitrate {
+    const unsigned int min;
+    const unsigned int max;
+};
+
+struct dlna_video_res {
+    const unsigned int width;
+    const unsigned int height;
+};
+
+struct dlna_video_res_range {
+    const unsigned int width_min;
+    const unsigned int width_max;
+    const unsigned int height_min;
+    const unsigned int height_max;
+};
+
+struct dlna_video_framerate_range {
+    double min;
+    double max;
+};
+
+struct dlna_level {
+    const char *levels[MAX_VIDEO_RULE_LEVEL];
+};
+
+struct dlna_profile {
+    const char *profiles[MAX_VIDEO_RULE_PROFILE];
+};
+
+struct dlna_video_framerate {
+    const double framerate[MAX_VIDEO_RULE_FRAMERATE];
+};
+
+struct dlna_video_pixel_aspect {
+    const char *pixel_aspect_ratio[MAX_VIDEO_PIXEL_ASPECT];
+};
+
+struct lms_dlna_video_rule {
+    const struct dlna_video_res *res;
+    const struct dlna_video_res_range *res_range;
+    const struct dlna_bitrate *bitrate;
+    const struct dlna_profile *profiles;
+    const struct dlna_level *levels;
+    const struct dlna_video_framerate *framerate;
+    const struct dlna_video_pixel_aspect *pixel_aspect;
+    struct dlna_video_framerate_range *framerate_range;
+};
+
+struct dlna_audio_rate {
+    const unsigned int rates[MAX_AUDIO_RATES];
+};
+
+struct lms_dlna_audio_rule {
+    const struct lms_string_size *codec;
+    const struct dlna_audio_rate *rates;
+    const struct dlna_level *levels;
+    const struct dlna_bitrate *channels;
+    const struct dlna_bitrate *bitrate;
+    const struct dlna_bitrate *rate_range;
+};
+
+struct dlna_video_packet_size {
+    const int64_t packet_size;
+};
+
+struct lms_dlna_video_profile {
+    const struct lms_string_size *dlna_profile;
+    const struct lms_string_size *dlna_mime;
+    const struct lms_dlna_video_rule *video_rules;
+    const struct lms_dlna_audio_rule *audio_rule;
+    const struct dlna_video_packet_size *packet_size;
+};
+
+struct lms_dlna_image_rule {
+    const struct dlna_bitrate *width;
+    const struct dlna_bitrate *height;
+};
+
+struct lms_dlna_audio_profile {
+    const struct lms_string_size *dlna_profile;
+    const struct lms_string_size *dlna_mime;
+    const struct lms_dlna_audio_rule *audio_rule;
+};
+
+struct lms_dlna_image_profile {
+    const struct lms_string_size *dlna_profile;
+    const struct lms_string_size *dlna_mime;
+    const struct lms_dlna_image_rule *image_rule;
+};
+
+const struct lms_dlna_video_profile *lms_dlna_get_video_profile(struct lms_video_info *info);
+const struct lms_dlna_audio_profile *lms_dlna_get_audio_profile(struct lms_audio_info *info);
+const struct lms_dlna_image_profile *lms_dlna_get_image_profile(struct lms_image_info *info);
+
+extern const struct lms_string_size _container_mp3;
+extern const struct lms_string_size _container_mpeg;
+extern const struct lms_string_size _container_mpegts;
+
+extern const struct lms_dlna_image_profile _dlna_jpeg_rules[];
+extern const struct lms_dlna_image_profile _dlna_png_rules[];
+
+extern const struct lms_dlna_audio_profile _dlna_mp3_rules[];
+extern const struct lms_dlna_audio_profile _dlna_mp4_audio_rules[];
+extern const struct lms_dlna_audio_profile _dlna_3gp_audio_rules[];
+extern const struct lms_dlna_audio_profile _dlna_wma_rules[];
+extern const struct lms_dlna_audio_profile _dlna_wave_rules[];
+
+extern const struct lms_dlna_video_profile _dlna_mpeg_rules[];
+extern const struct lms_dlna_video_profile _dlna_mpegts_rules[];
+extern const struct lms_dlna_video_profile _dlna_mp4_video_rules[];
+
+#endif /* _LIGHTMEDIASCANNER_DLNA_H_ */
diff --git a/src/lib/lightmediascanner_dlna_rules.c b/src/lib/lightmediascanner_dlna_rules.c
new file mode 100644 (file)
index 0000000..85826fa
--- /dev/null
@@ -0,0 +1,2322 @@
+/**
+ * Copyright (C) 2013 by Intel Corporation
+ *
+ * This library 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.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * @author Leandro Dorileo <leandro.maciel.dorileo@intel.com>
+ */
+
+#include <lightmediascanner_dlna.h>
+
+#define DECL_STR(cname, str)                                            \
+    static const struct lms_string_size cname = LMS_STATIC_STRING_SIZE(str)
+
+/** MP3 **/
+DECL_STR(_dlna_mime_audio, "audio/mpeg");
+DECL_STR(_dlna_mime_adts, "audio/vnd.dlna.adts");
+
+DECL_STR(_dlna_profile_mp3, "MP3");
+DECL_STR(_dlna_profile_mp3x, "MP3X");
+
+DECL_STR(_codec_mpeg2aac_lc, "mpeg2aac-lc");
+DECL_STR(_codec_mpeg4aac_lc, "mpeg4aac-lc");
+
+DECL_STR(_dlna_profile_aac_adts_320, "AAC_ADTS_320");
+DECL_STR(_dlna_profile_aac_adts, "AAC_ADTS");
+DECL_STR(_dlna_profile_aac_adts_mult5, "AAC_MULT5_ADTS");
+
+const struct lms_string_size _container_mp3 = LMS_STATIC_STRING_SIZE("mp3");
+const struct lms_string_size _testing = LMS_STATIC_STRING_SIZE("testing");
+
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg2_aac_adts_320 = {
+    .codec = &_codec_mpeg2aac_lc,
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(0, 320000),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg2_aac_adts = {
+    .codec = &_codec_mpeg2aac_lc,
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(0, 576000),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg2_aac_adts_mult5 = {
+    .codec = &_codec_mpeg2aac_lc,
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(0, 1440000),
+    .channels = DLNA_BITRATE(1, 6),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg4_aac_adts_320 = {
+    .codec = &_codec_mpeg4aac_lc,
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(0, 320000),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg4_aac_adts = {
+    .codec = &_codec_mpeg4aac_lc,
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(0, 576000),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg4_aac_adts_mult5 = {
+    .codec = &_codec_mpeg4aac_lc,
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(0, 1440000),
+    .channels = DLNA_BITRATE(1, 6),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mp3 = {
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(320000, 320000),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mp3x = {
+    .rates = DLNA_AUDIO_RATE(16000, 22050, 24000, 32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(8000, 320000),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+const struct lms_dlna_audio_profile _dlna_mp3_rules[] = {
+    {
+        .dlna_profile = &_dlna_profile_aac_adts_320,
+        .dlna_mime = &_dlna_mime_adts,
+        .audio_rule = &_dlna_audio_rule_mpeg2_aac_adts_320,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_adts,
+        .dlna_mime = &_dlna_mime_adts,
+        .audio_rule = &_dlna_audio_rule_mpeg2_aac_adts,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_adts_mult5,
+        .dlna_mime = &_dlna_mime_adts,
+        .audio_rule = &_dlna_audio_rule_mpeg2_aac_adts_mult5,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_adts_320,
+        .dlna_mime = &_dlna_mime_adts,
+        .audio_rule = &_dlna_audio_rule_mpeg4_aac_adts_320,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_adts,
+        .dlna_mime = &_dlna_mime_adts,
+        .audio_rule = &_dlna_audio_rule_mpeg4_aac_adts,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_adts_mult5,
+        .dlna_mime = &_dlna_mime_adts,
+        .audio_rule = &_dlna_audio_rule_mpeg4_aac_adts_mult5,
+    },
+    {
+        .dlna_profile = &_dlna_profile_mp3,
+        .dlna_mime = &_dlna_mime_audio,
+        .audio_rule = &_dlna_audio_rule_mp3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_mp3x,
+        .dlna_mime = &_dlna_mime_audio,
+        .audio_rule = &_dlna_audio_rule_mp3x,
+    },
+    {NULL},
+};
+
+/** MPEG (1/2) **/
+DECL_STR(_dlna_profile_mpeg_ts_sd_eu_iso, "MPEG_TS_SD_EU_ISO");
+DECL_STR(_dlna_profile_mpeg_ts_sd_eu, "MPEG_TS_SD_EU");
+DECL_STR(_dlna_profile_mpeg_ts_hd_na_iso, "MPEG_TS_HD_NA_ISO");
+DECL_STR(_dlna_profile_mpeg_ts_hd_na, "MPEG_TS_HD_NA");
+DECL_STR(_dlna_profile_mpeg_ts_sd_na_iso, "MPEG_TS_SD_NA_ISO");
+DECL_STR(_dlna_profile_mpeg_ts_sd_na, "MPEG_TS_SD_NA");
+DECL_STR(_dlna_profile_mpeg_ps_pal, "MPEG_PS_PAL");
+DECL_STR(_dlna_profile_mpeg_ps_ntsc, "MPEG_PS_NTSC");
+DECL_STR(_dlna_profile_mpeg1, "MPEG1");
+
+DECL_STR(_dlna_mime_video, "video/mpeg");
+DECL_STR(_dlna_mim_video_tts, "video/vnd.dlna.mpeg-tts");
+
+const struct lms_string_size _container_mpeg = LMS_STATIC_STRING_SIZE("mpeg");
+const struct lms_string_size _container_mpegts = LMS_STATIC_STRING_SIZE("mpegts");
+
+static const struct lms_dlna_video_rule _dlna_video_rule_mpeg_ps_pal[] = {
+    {
+        .res = DLNA_VIDEO_RES(720, 576),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main"),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("64:45", "16:15"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(704, 576),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main"),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("64:45", "16:15"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(544, 576),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main"),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("32:17", "24:17"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(480, 576),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main"),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("32:15", "8:5"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 576),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main"),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("32:11", "24:11"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main"),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("16:11", "12:11"),
+    },
+    { NULL },
+};
+
+static const struct lms_dlna_video_rule _dlna_video_rule_mpeg1[] = {
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1150000, 1152000),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .bitrate = DLNA_BITRATE(1150000, 1152000),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .bitrate = DLNA_BITRATE(1150000, 1152000),
+        .framerate = DLNA_VIDEO_FRAMERATE(24000/1001),
+    },
+    {
+        .bitrate = DLNA_BITRATE(1150000, 1152000),
+    },
+    { NULL },
+};
+
+static const struct lms_dlna_video_rule _dlna_video_rule_mpeg_ps_ntsc[] = {
+    {
+        .res = DLNA_VIDEO_RES(720, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("32:27", "8:9"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(704, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .framerate = DLNA_VIDEO_FRAMERATE(24000/1001, 24/1, 30000/1001, 30/1,
+                                          60000/1001, 60/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("40:33", "10:11"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(480, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("16:9", "4:3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(544, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("80:51", "20:17"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("80:33", "20:11"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .bitrate = DLNA_BITRATE(1, 9800000),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("16:11", "12:11"),
+    },
+    { NULL },
+};
+
+static const struct lms_dlna_video_rule _dlna_video_rule_mpeg_ts_sd_na[] = {
+    {
+        .res = DLNA_VIDEO_RES(720, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("32:27", "8:9"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(704, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(24000/1001, 24/1, 30000/1001, 30/1,
+                                          60000/1001, 60/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("40:33", "10:11"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(24000/1001, 24/1, 30000/1001, 30/1,
+                                          60000/1001, 60/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("1:1", "4:3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(480, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("16:9", "4:3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(544, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("80:51", "20:17"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 480),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("80:33", "20:11"),
+    },
+    { NULL },
+};
+
+static const struct lms_dlna_video_rule _dlna_video_rule_mpeg_ts_hd_na[] = {
+    {
+        .res = DLNA_VIDEO_RES(1920, 1080),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001, 30/1, 24000/1001, 24/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("1:1", "9:16"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001, 30/1, 24000/1001, 24/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("1:1", "9:16"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1080, 1440),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001, 30/1, 24000/1001, 24/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("4:3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1080, 1280),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(30000/1001, 30/1, 24000/1001, 24/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("3:2"),
+    },
+    { NULL },
+};
+
+static const struct lms_dlna_video_rule _dlna_video_rule_mpeg_ts_sd_eu[] = {
+    {
+        .res = DLNA_VIDEO_RES(720, 576),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("64:45", "16:15"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(544, 576),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("32:17", "24:17"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(480, 576),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("32:15", "8:15"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 576),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("32:11", "24:11"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .profiles = DLNA_PROFILE("simple", "main"),
+        .levels = DLNA_LEVEL("low", "main", "high-1440", "high"),
+        .bitrate = DLNA_BITRATE(1, 18881700),
+        .framerate = DLNA_VIDEO_FRAMERATE(25/1),
+        .pixel_aspect = DLNA_VIDEO_PIXEL_ASPECT("16:11", "12:11"),
+    },
+    { NULL },
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg_ps = {
+    .rates = DLNA_AUDIO_RATE(48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg1 = {
+    .bitrate = DLNA_BITRATE(224000, 224000),
+    .channels = DLNA_BITRATE(2, 2),
+    .rates = DLNA_AUDIO_RATE(44100),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg_ts_sd_hd_na = {
+    .bitrate = DLNA_BITRATE(1, 448000),
+    .channels = DLNA_BITRATE(1, 6),
+    .rates = DLNA_AUDIO_RATE(48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_mpeg_ts_sd_eu = {
+    .bitrate = DLNA_BITRATE(1, 448000),
+    .channels = DLNA_BITRATE(1, 6),
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+};
+
+// rules
+const struct lms_dlna_video_profile _dlna_mpeg_rules[] = {
+    {
+        .dlna_profile = &_dlna_profile_mpeg_ps_pal,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_mpeg_ps_pal,
+        .audio_rule = &_dlna_audio_rule_mpeg_ps,
+    },
+    {
+        .dlna_profile = &_dlna_profile_mpeg1,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_mpeg1,
+        .audio_rule = &_dlna_audio_rule_mpeg1,
+    },
+    {
+        .dlna_profile = &_dlna_profile_mpeg_ps_ntsc,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_mpeg_ps_ntsc,
+        .audio_rule = &_dlna_audio_rule_mpeg_ps,
+    },
+    {NULL}
+};
+
+const struct lms_dlna_video_profile _dlna_mpegts_rules[] = {
+    {
+        .dlna_profile = &_dlna_profile_mpeg_ts_sd_na,
+        .dlna_mime = &_dlna_mim_video_tts,
+        .video_rules = _dlna_video_rule_mpeg_ts_sd_na,
+        .audio_rule = &_dlna_audio_rule_mpeg_ts_sd_hd_na,
+        .packet_size = DLNA_VIDEO_PACKETSIZE(192),
+    },
+    {
+        .dlna_profile = &_dlna_profile_mpeg_ts_sd_na_iso,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_mpeg_ts_sd_na,
+        .audio_rule = &_dlna_audio_rule_mpeg_ts_sd_hd_na,
+        .packet_size = DLNA_VIDEO_PACKETSIZE(188),
+    },
+    {
+        .dlna_profile = &_dlna_profile_mpeg_ts_hd_na,
+        .dlna_mime = &_dlna_mim_video_tts,
+        .video_rules = _dlna_video_rule_mpeg_ts_hd_na,
+        .audio_rule = &_dlna_audio_rule_mpeg_ts_sd_hd_na,
+        .packet_size = DLNA_VIDEO_PACKETSIZE(192),
+    },
+    {
+        .dlna_profile = &_dlna_profile_mpeg_ts_hd_na_iso,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_mpeg_ts_hd_na,
+        .audio_rule = &_dlna_audio_rule_mpeg_ts_sd_hd_na,
+        .packet_size = DLNA_VIDEO_PACKETSIZE(188),
+    },
+    {
+        .dlna_profile = &_dlna_profile_mpeg_ts_sd_eu,
+        .dlna_mime = &_dlna_mim_video_tts,
+        .video_rules = _dlna_video_rule_mpeg_ts_sd_eu,
+        .audio_rule = &_dlna_audio_rule_mpeg_ts_sd_eu,
+        .packet_size = DLNA_VIDEO_PACKETSIZE(192),
+    },
+    {
+        .dlna_profile = &_dlna_profile_mpeg_ts_sd_eu_iso,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_mpeg_ts_sd_eu,
+        .audio_rule = &_dlna_audio_rule_mpeg_ts_sd_eu,
+        .packet_size = DLNA_VIDEO_PACKETSIZE(188),
+    },
+    {NULL}
+};
+
+/** MP4 */
+
+DECL_STR(_container_mp4, "mp4");
+DECL_STR(_container_3gp, "3gp");
+
+DECL_STR(_codec_audio_mpeg4aac_lc, "mpeg4aac-lc");
+DECL_STR(_codec_audio_mpeg4aac_ltp, "mpeg4aac-ltp");
+DECL_STR(_codec_audio_amr, "amr");
+DECL_STR(_codec_audio_amr_wb, "amr-wb");
+
+DECL_STR(_dlna_profile_p2_sp_aac, "MPEG4_P2_MP4_SP_AAC");
+DECL_STR(_dlna_profile_p2_sp_aac_ltp, "MPEG4_P2_MP4_SP_AAC_LTP");
+DECL_STR(_dlna_profile_p2_sp_vga_aac, "MPEG4_P2_MP4_SP_VGA_AAC");
+DECL_STR(_dlna_profile_p2_sp_l2_aac, "MPEG4_P2_MP4_SP_L2_AAC");
+DECL_STR(_dlna_profile_p2_sp_l5_aac, "MPEG4_P2_MP4_SP_L5_AAC");
+DECL_STR(_dlna_profile_p2_sp_l6_aac, "MPEG4_P2_MP4_SP_L6_AAC");
+DECL_STR(_dlna_profile_h263_p0_l10_aac, "MPEG4_H263_MP4_P0_L10_AAC");
+DECL_STR(_dlna_profile_h263_p0_l10_aac_ltp, "MPEG4_H263_MP4_P0_L10_AAC_LTP");
+DECL_STR(_dlna_profile_avc_mp4_bl_cif15_aac_520, "AVC_MP4_BL_CIF15_AAC_520");
+DECL_STR(_dlna_profile_avc_mp4_bl_cif15_aac, "AVC_MP4_BL_CIF15_AAC");
+DECL_STR(_dlna_profile_avc_mp4_bl_l3l_sd_aac, "AVC_MP4_BL_L3L_SD_AAC");
+DECL_STR(_dlna_profile_avc_mp4_bl_l3_sd_aac, "AVC_MP4_BL_L3_SD_AAC");
+DECL_STR(_dlna_profile_avc_mp4_mp_sd_aac_mult5, "AVC_MP4_MP_SD_AAC_MULT5");
+DECL_STR(_dlna_profile_avc_mp4_mp_sd_mpeg1_l3, "AVC_MP4_MP_SD_MPEG1_L3");
+DECL_STR(_dlna_profile_avc_mp4_mp_sd_ac3, "AVC_MP4_MP_SD_AC3");
+DECL_STR(_dlna_profile_avc_mp4_mp_sd_eac3, "AVC_MP4_MP_SD_EAC3");
+DECL_STR(_dlna_profile_avc_mp4_mp_hd_720p_aac, "AVC_MP4_MP_HD_720p_AAC");
+DECL_STR(_dlna_profile_avc_mkv_mp_hd_aac_mult5, "AVC_MKV_MP_HD_AAC_MULT5");
+DECL_STR(_dlna_profile_avc_mkv_hp_hd_aac_mult5, "AVC_MKV_HP_HD_AAC_MULT5");
+DECL_STR(_dlna_profile_avc_mkv_mp_hd_ac3, "AVC_MKV_MP_HD_AC3");
+DECL_STR(_dlna_profile_avc_mkv_hp_hd_ac3, "AVC_MKV_HP_HD_AC3");
+DECL_STR(_dlna_profile_avc_mkv_mp_hd_mpeg1_l3, "AVC_MKV_MP_HD_MPEG1_L3");
+DECL_STR(_dlna_profile_avc_mkv_hp_hd_mpeg1_l3, "AVC_MKV_HP_HD_MPEG1_L3");
+
+DECL_STR(_dlna_profile_aac_iso, "AAC_ISO");
+DECL_STR(_dlna_profile_aac_iso_320, "AAC_ISO_320");
+DECL_STR(_dlna_profile_aac_mult5_iso, "AAC_MULT5_ISO");
+DECL_STR(_dlna_profile_ac3, "AC3");
+DECL_STR(_dlna_profile_eac3, "EAC3");
+DECL_STR(_dlna_profile_amr_3gpp, "AMR_3GPP");
+DECL_STR(_dlna_profile_amr_wbplus, "AMR_WBplus");
+
+DECL_STR(_dlna_mime_video_3gp, "video/3gpp");
+DECL_STR(_dlna_mime_video_matroska, "video/x-matroska");
+
+DECL_STR(_dlna_mime_audio_3gp, "audio/3gpp");
+DECL_STR(_dlna_mime_audio_dolby, "audio/vnd.dolby.dd-raw");
+DECL_STR(_dlna_mime_audio_eac3, "audio/eac3");
+
+static const struct lms_dlna_video_rule _dlna_video_rule_sp_l3[] = {
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 240),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 180),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1")
+    },
+    {
+        .res = DLNA_VIDEO_RES(240, 180),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(208, 160),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 144),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 120),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 120),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 112),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 90),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(128, 96),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 240),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 180),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(240, 180),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(208, 160),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 144),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 120),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 120),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 112),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 90),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(128, 96),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 240),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 180),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(240, 180),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(208, 160),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 155),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 120),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 120),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 112),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 90),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(128, 96),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    { NULL },
+};
+
+#define DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD                         \
+    "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3"      \
+
+static const struct lms_dlna_video_rule _dlna_video_rule_avc_mp4_mp_sd[] = {
+    {
+        .res = DLNA_VIDEO_RES(720, 576),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(720, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(704, 576),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(704, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(704, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 360),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(544, 576),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(544, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(480, 576),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(480, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(480, 360),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(480, 270),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 576),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 240),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 180),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(240, 180),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(208, 160),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 144),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 120),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(150, 120),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 112),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 90),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    {
+        .res = DLNA_VIDEO_RES(128, 96),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
+    },
+    { NULL },
+};
+
+#define DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_VGA_AAC       \
+    "0", "0b", "1", "2", "3"                            \
+
+static const struct lms_dlna_video_rule _dlna_video_mpeg4_p2_mp4_sp_vga_aac[] = {
+    {
+        .res = DLNA_VIDEO_RES(640, 480),
+        .bitrate = DLNA_BITRATE(1, 3000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_VGA_AAC),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(-1, -1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 360),
+        .bitrate = DLNA_BITRATE(1, 3000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_VGA_AAC),
+    },
+    { NULL },
+};
+
+#define DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC        \
+    "0", "0b", "1", "2"                                 \
+
+static const struct lms_dlna_video_rule _dlna_video_mpeg4_p2_mp4_sp_l2_aac[] = {
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 15/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 240),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 15/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 180),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 15/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 144),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(128, 96),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
+    },
+    { NULL },
+};
+
+#define DLNA_VIDEO_RULE_SP_L5                           \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(640, 480),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(640, 360),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(720, 576),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(720, 480),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(352, 288),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(352, 240),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(320, 240),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(320, 180),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(240, 180),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(208, 160),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(176, 144),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(176, 120),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 120),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 112),                \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 90),                 \
+            .bitrate = DLNA_BITRATE(1, 64000),          \
+            .levels = DLNA_LEVEL("0", "1"),             \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(640, 480),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(640, 360),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(720, 576),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(720, 480),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(352, 288),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(352, 240),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(320, 240),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(320, 180),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(240, 180),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(208, 160),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(176, 144),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(176, 120),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 120),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 112),                \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 90),                 \
+            .bitrate = DLNA_BITRATE(1, 128000),         \
+            .levels = DLNA_LEVEL("0b", "2"),            \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(640, 480),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(640, 360),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(720, 576),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(720, 480),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(352, 288),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(352, 240),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(320, 240),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(320, 180),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(240, 180),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(208, 160),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(176, 144),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(176, 120),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 120),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 112),                \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 90),                 \
+            .bitrate = DLNA_BITRATE(1, 384000),         \
+            .levels = DLNA_LEVEL("3"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(640, 480),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5"),                  \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(640, 360),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(720, 576),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(720, 480),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(352, 288),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(352, 240),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(320, 240),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(320, 180),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(240, 180),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(208, 160),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(176, 144),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(176, 120),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 120),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 112),                \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            },                                          \
+    {                                                   \
+        .res = DLNA_VIDEO_RES(160, 90),                 \
+            .bitrate = DLNA_BITRATE(1, 8000000),        \
+            .levels = DLNA_LEVEL("5")                   \
+            }                                           \
+
+static const struct lms_dlna_video_rule _dlna_video_rule_sp_l5[] = {
+    DLNA_VIDEO_RULE_SP_L5,
+    { NULL },
+};
+
+static const struct lms_dlna_video_rule _dlna_video_rule_sp_l6[] = {
+    DLNA_VIDEO_RULE_SP_L5,
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .bitrate = DLNA_BITRATE(1, 64000),
+        .levels = DLNA_LEVEL("0", "1"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .bitrate = DLNA_BITRATE(1, 128000),
+        .levels = DLNA_LEVEL("0b", "2"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .bitrate = DLNA_BITRATE(1, 384000),
+        .levels = DLNA_LEVEL("3"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 480),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(720, 576),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(720, 480),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 240),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 180),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(240, 180),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(208, 160),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 144),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 120),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 120),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 112),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 90),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .bitrate = DLNA_BITRATE(1, 4000000),
+        .levels = DLNA_LEVEL("4a"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .bitrate = DLNA_BITRATE(1, 8000000),
+        .levels = DLNA_LEVEL("5"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 480),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 360),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(720, 576),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(720, 480),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 288),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(352, 240),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 240),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(320, 180),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(240, 180),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(208, 160),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 144),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(176, 120),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 120),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 112),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(160, 90),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .bitrate = DLNA_BITRATE(1, 12000000),
+        .levels = DLNA_LEVEL("6"),
+    },
+    { NULL },
+};
+
+#define DLNA_VIDEO_RULE_H263_P0_L10             \
+    {                                           \
+        .res = DLNA_VIDEO_RES(176, 144),        \
+            .bitrate = DLNA_BITRATE(1, 64000),  \
+            .levels = DLNA_LEVEL("0")           \
+            },                                  \
+    {                                           \
+        .res = DLNA_VIDEO_RES(128, 96),         \
+            .bitrate = DLNA_BITRATE(1, 64000),  \
+            .levels = DLNA_LEVEL("0")           \
+            }                                   \
+
+static const struct lms_dlna_video_rule _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac[] = {
+DLNA_VIDEO_RULE_H263_P0_L10,
+{ NULL },
+    };
+
+static const struct lms_dlna_video_rule _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac_ltp[] = {
+DLNA_VIDEO_RULE_H263_P0_L10,
+{ NULL },
+    };
+
+#define DLNA_VIDEO_LEVELS_CIF                   \
+    "1", "1b", "1.1", "1.2"                     \
+
+#define DLNA_VIDEO_RULES_AVC_MP4_BL_CIF15                               \
+    {                                                                   \
+     .res = DLNA_VIDEO_RES(352, 288),                                   \
+          .bitrate = DLNA_BITRATE(1, 384000),                           \
+          .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                  \
+          .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 15/1),     \
+          },                                                            \
+    {                                                                   \
+     .res = DLNA_VIDEO_RES(352, 240),                                   \
+          .bitrate = DLNA_BITRATE(1, 384000),                           \
+          .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                  \
+          .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 18/1),     \
+          },                                                            \
+    {                                                                   \
+     .res = DLNA_VIDEO_RES(320, 240),                                   \
+          .bitrate = DLNA_BITRATE(1, 384000),                           \
+          .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                  \
+          .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 20/1),     \
+          },                                                            \
+    {                                                                   \
+     .res = DLNA_VIDEO_RES(320, 180),                                   \
+          .bitrate = DLNA_BITRATE(1, 384000),                           \
+          .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                  \
+          .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 26/1),     \
+          },                                                            \
+    {                                                                   \
+     .res = DLNA_VIDEO_RES(240, 180),                                   \
+          .bitrate = DLNA_BITRATE(1, 384000),                           \
+          .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                  \
+          .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),     \
+          },                                                            \
+          {                                                             \
+           .res = DLNA_VIDEO_RES(208, 160),                             \
+                .bitrate = DLNA_BITRATE(1, 384000),                     \
+                .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),            \
+                .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1), \
+                },                                                      \
+          {                                                             \
+           .res = DLNA_VIDEO_RES(176, 144),                             \
+                .bitrate = DLNA_BITRATE(1, 384000),                     \
+                .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),            \
+                .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1), \
+                },                                                      \
+          {                                                             \
+           .res = DLNA_VIDEO_RES(176, 120),                             \
+                .bitrate = DLNA_BITRATE(1, 384000),                     \
+                .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),            \
+                .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1), \
+                },                                                      \
+          {                                                             \
+           .res = DLNA_VIDEO_RES(160, 120),                             \
+                .bitrate = DLNA_BITRATE(1, 384000),                     \
+                .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),            \
+                .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1), \
+                },                                                      \
+          {                                                             \
+           .res = DLNA_VIDEO_RES(160, 112),                             \
+                .bitrate = DLNA_BITRATE(1, 384000),                     \
+                .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),            \
+                .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1), \
+                },                                                      \
+                {                                                       \
+                 .res = DLNA_VIDEO_RES(160, 90),                        \
+                      .bitrate = DLNA_BITRATE(1, 384000),               \
+                      .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),      \
+                      .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1), \
+                      },                                                \
+                {                                                       \
+                 .res = DLNA_VIDEO_RES(128, 96),                        \
+                      .bitrate = DLNA_BITRATE(1, 384000),               \
+                      .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),      \
+                      .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1), \
+                      },                                                \
+                {                                                       \
+                 .res = DLNA_VIDEO_RES(240, 135),                       \
+                      .bitrate = DLNA_BITRATE(1, 384000),               \
+                      .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),      \
+                      .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1), \
+                      }                                                 \
+
+static const struct lms_dlna_video_rule _dlna_video_rule_avc_mp4_bl_cif15_aac_520[] = {
+    DLNA_VIDEO_RULES_AVC_MP4_BL_CIF15,
+    { NULL },
+};
+
+static const struct lms_dlna_video_rule _dlna_video_rule_avc_mp4_bl_cif15_aac[] = {
+    DLNA_VIDEO_RULES_AVC_MP4_BL_CIF15,
+    { NULL },
+};
+
+#define DLNA_VIDEO_RULES_BL_L3L_SD_AAC                          \
+    "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3"      \
+
+// common between l3 and l3l sd aac
+#define DLNA_VIDEO_RULES_L3_L3L_SD_AAC                                  \
+    {                                                                   \
+        .res = DLNA_VIDEO_RES(720, 576),                                \
+            .bitrate = DLNA_BITRATE(1, 4500000),                        \
+            .levels = DLNA_LEVEL(DLNA_VIDEO_RULES_BL_L3L_SD_AAC),       \
+            .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 25/1),   \
+            },                                                          \
+    {                                                                   \
+        .res = DLNA_VIDEO_RES(720, 480),                                \
+            .bitrate = DLNA_BITRATE(1, 4500000),                        \
+            .levels = DLNA_LEVEL(DLNA_VIDEO_RULES_BL_L3L_SD_AAC),       \
+            .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30000/1001), \
+            },                                                          \
+    {                                                                   \
+        .res = DLNA_VIDEO_RES(640, 480),                                \
+            .bitrate = DLNA_BITRATE(1, 4500000),                        \
+            .levels = DLNA_LEVEL(DLNA_VIDEO_RULES_BL_L3L_SD_AAC),       \
+            .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),   \
+            },                                                          \
+    {                                                                   \
+        .res = DLNA_VIDEO_RES(640, 360),                                \
+            .bitrate = DLNA_BITRATE(1, 4500000),                        \
+            .levels = DLNA_LEVEL(DLNA_VIDEO_RULES_BL_L3L_SD_AAC),       \
+            .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),   \
+            }                                                           \
+
+static const struct lms_dlna_video_rule _dlna_video_rule_avc_mp4_bl_l3l_sd_aac[] = {
+    DLNA_VIDEO_RULES_L3_L3L_SD_AAC,
+    { NULL },
+};
+
+static const struct lms_dlna_video_rule _dlna_video_rule_avc_mp4_bl_l3_sd_aac[] = {
+    DLNA_VIDEO_RULES_L3_L3L_SD_AAC,
+    { NULL },
+};
+
+#define DLNA_VIDEO_LEVELS_SD_EAC3                               \
+    "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3"      \
+
+static const struct lms_dlna_video_rule _dlna_video_rule_avc_mp4_mp_sd_eac3[] = {
+    {
+        .res = DLNA_VIDEO_RES(864, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_SD_EAC3),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 25/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(720, 576),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_SD_EAC3),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 50/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(720, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_SD_EAC3),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 480),
+        .bitrate = DLNA_BITRATE(1, 10000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_SD_EAC3),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
+    },
+};
+
+#define DLNA_VIDEO_LEVELS_MP_HD_720P                                    \
+    "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3", "3.1"       \
+
+static const struct lms_dlna_video_rule _dlna_video_rule_avc_mp4_mp_hd_720p_aac[] = {
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .bitrate = DLNA_BITRATE(1, 14000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MP_HD_720P),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(640, 480),
+        .bitrate = DLNA_BITRATE(1, 14000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MP_HD_720P),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
+    },
+};
+
+#define DLNA_VIDEO_LEVELS_MP_HD_1080I                                   \
+    "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3", "3.1", "3.2", "4" \
+
+static const struct lms_dlna_video_rule _dlna_video_rule_avc_mp4_mp_hd_1080i_aac[] = {
+    {
+        .res = DLNA_VIDEO_RES(1920, 1080),
+        .bitrate = DLNA_BITRATE(1, 20000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MP_HD_1080I),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
+    },
+    {
+        .res = DLNA_VIDEO_RES(1280, 720),
+        .bitrate = DLNA_BITRATE(1, 20000000),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MP_HD_1080I),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
+    },
+};
+
+#define DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD                                 \
+    "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3", "3.1", "3.2", "4" \
+
+static const struct lms_dlna_video_rule _dlna_video_avc_mkv_hp_hd[] = {
+    {
+        .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1152),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
+    },
+    {
+        .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1152),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 50/1),
+    },
+    {
+        .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1152),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 25/1),
+    },
+    {
+        .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1080),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
+    },
+    {
+        .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1080),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
+    },
+    {
+        .res_range = DLNA_VIDEO_RES_RANGE(1, 1280, 1, 720),
+        .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
+        .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
+    },
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(1, 216000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_aac_ltp = {
+    .codec = &_codec_audio_mpeg4aac_ltp,
+    .bitrate = DLNA_BITRATE(1, 216000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_vga_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(1, 256000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_l2_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(1, 128000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_l5_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_l6_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_mpeg4_h263_mp4_p0_l10_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(1, 86000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_mpeg4_h263_mp4_p0_l10_aac_ltp = {
+    .codec = &_codec_audio_mpeg4aac_ltp,
+    .bitrate = DLNA_BITRATE(1, 86000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+// avc
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_bl_cif15_aac_520 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(1, 128000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_bl_cif15_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(1, 200000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_bl_l3l_sd_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(1, 256000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_bl_l3_sd_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(1, 256000),
+    .levels = DLNA_LEVEL("1", "2"),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_sd_aac_mult5 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(0,1440000),
+    .levels = DLNA_LEVEL("1", "2", "4"),
+    .channels = DLNA_BITRATE(1, 6),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_sd_mpeg1_l3 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(32000, 32000),
+    .channels = DLNA_BITRATE(1, 2),
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_sd_ac3 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(64000, 64000),
+    .channels = DLNA_BITRATE(1, 6),
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_sd_eac3 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(0, 3024000),
+    .channels = DLNA_BITRATE(1, 6),
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_hd_720p_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(0, 576000),
+    .channels = DLNA_BITRATE(1, 2),
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_hd_1080i_aac = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(0, 576000),
+    .channels = DLNA_BITRATE(1, 2),
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mkv_mp_hd_aac_mult5 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(0, 1440000),
+    .channels = DLNA_BITRATE(1, 6),
+    .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
+    .levels = DLNA_LEVEL("1", "2", "4"),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mkv_mp_hd_ac3 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .bitrate = DLNA_BITRATE(0, 1440000),
+    .channels = DLNA_BITRATE(1, 6),
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_avc_mkv_mp_hd_mpeg1_l3 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .channels = DLNA_BITRATE(1, 2),
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(32000, 320000),
+};
+
+const struct lms_dlna_video_profile _dlna_mp4_video_rules[] = {
+    // mpeg4
+    {
+        .dlna_profile = &_dlna_profile_p2_sp_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_sp_l3,
+        .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_p2_sp_aac_ltp,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_sp_l3,
+        .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_aac_ltp,
+    },
+    {
+        .dlna_profile = &_dlna_profile_p2_sp_vga_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_mpeg4_p2_mp4_sp_vga_aac,
+        .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_vga_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_p2_sp_l2_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_mpeg4_p2_mp4_sp_l2_aac,
+        .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_l2_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_p2_sp_l5_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_sp_l5,
+        .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_l5_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_p2_sp_l6_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_sp_l6,
+        .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_l6_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_h263_p0_l10_aac,
+        .dlna_mime = &_dlna_mime_video_3gp,
+        .video_rules = _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac,
+        .audio_rule = &_dlna_audio_mpeg4_h263_mp4_p0_l10_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_h263_p0_l10_aac_ltp,
+        .dlna_mime = &_dlna_mime_video_3gp,
+        .video_rules = _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac_ltp,
+        .audio_rule = &_dlna_audio_mpeg4_h263_mp4_p0_l10_aac_ltp,
+    },
+    // avc
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_bl_cif15_aac_520,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_bl_cif15_aac_520,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_bl_cif15_aac_520,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_bl_cif15_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_bl_cif15_aac,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_bl_cif15_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_bl_l3l_sd_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_bl_l3l_sd_aac,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_bl_l3l_sd_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_bl_l3_sd_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_bl_l3_sd_aac,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_bl_l3_sd_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_mp_sd_aac_mult5,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_mp_sd,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_mp_sd_aac_mult5,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_mp_sd_mpeg1_l3,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_mp_sd,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_mp_sd_mpeg1_l3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_mp_sd_ac3,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_mp_sd,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_mp_sd_ac3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_mp_sd_eac3,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_mp_sd_eac3,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_mp_sd_eac3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_mp_hd_720p_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_mp_hd_720p_aac,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_mp_hd_720p_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mp4_mp_hd_720p_aac,
+        .dlna_mime = &_dlna_mime_video,
+        .video_rules = _dlna_video_rule_avc_mp4_mp_hd_1080i_aac,
+        .audio_rule = &_dlna_audio_rule_avc_mp4_mp_hd_1080i_aac,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mkv_mp_hd_aac_mult5,
+        .dlna_mime = &_dlna_mime_video_matroska,
+        .video_rules = _dlna_video_avc_mkv_hp_hd,
+        .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_aac_mult5,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mkv_hp_hd_aac_mult5, // same rules as mp
+        .dlna_mime = &_dlna_mime_video_matroska,
+        .video_rules = _dlna_video_avc_mkv_hp_hd,
+        .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_aac_mult5,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mkv_mp_hd_ac3,
+        .dlna_mime = &_dlna_mime_video_matroska,
+        .video_rules = _dlna_video_avc_mkv_hp_hd,
+        .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_ac3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mkv_hp_hd_ac3, // same rules as mp
+        .dlna_mime = &_dlna_mime_video_matroska,
+        .video_rules = _dlna_video_avc_mkv_hp_hd,
+        .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_ac3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mkv_mp_hd_mpeg1_l3,
+        .dlna_mime = &_dlna_mime_video_matroska,
+        .video_rules = _dlna_video_avc_mkv_hp_hd,
+        .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_mpeg1_l3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_avc_mkv_hp_hd_mpeg1_l3, // same rules as mp
+        .dlna_mime = &_dlna_mime_video_matroska,
+        .video_rules = _dlna_video_avc_mkv_hp_hd,
+        .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_mpeg1_l3,
+    },
+};
+
+#define DLNA_AUDIO_RULE_AAC_ISO                                         \
+    .codec = &_codec_audio_mpeg4aac_lc,                                 \
+        .channels = DLNA_BITRATE(1, 2),                                 \
+        .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000,             \
+                                 22050, 24000, 32000, 44100, 48000),    \
+        .bitrate = DLNA_BITRATE(0, 576000)                              \
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_aac_iso = {
+    DLNA_AUDIO_RULE_AAC_ISO,
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_aac_iso_3gp = {
+    DLNA_AUDIO_RULE_AAC_ISO,
+};
+
+#define DLNA_AUDIO_RULE_AAC_ISO_320                                     \
+    .codec = &_codec_audio_mpeg4aac_lc,                                 \
+        .channels = DLNA_BITRATE(1, 2),                                 \
+        .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000,             \
+                                 22050, 24000, 32000, 44100, 48000),    \
+        .bitrate = DLNA_BITRATE(0, 320000)                              \
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_aac_iso_320 = {
+    DLNA_AUDIO_RULE_AAC_ISO_320,
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_aac_iso_320_3gp = {
+    DLNA_AUDIO_RULE_AAC_ISO_320,
+};
+
+#define DLNA_AUDIO_RULE_AAC_MULT5_ISO                                   \
+    .codec = &_codec_audio_mpeg4aac_lc,                                 \
+        .channels = DLNA_BITRATE(1, 6),                                 \
+        .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000,             \
+                                 22050, 24000, 32000, 44100, 48000),    \
+        .bitrate = DLNA_BITRATE(0, 1440000)                             \
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_aac_mult5_iso = {
+    DLNA_AUDIO_RULE_AAC_MULT5_ISO,
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_aac_mult5_iso_3gp = {
+    DLNA_AUDIO_RULE_AAC_MULT5_ISO,
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_ac3 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .channels = DLNA_BITRATE(1, 6),
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE(64000, 64000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_eac3 = {
+    .codec = &_codec_audio_mpeg4aac_lc,
+    .channels = DLNA_BITRATE(1, 6),
+    .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
+    .bitrate = DLNA_BITRATE( 32000, 6144000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_amr_3gpp = {
+    .codec = &_codec_audio_amr,
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_amr = {
+    .codec = &_codec_audio_amr,
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_amr_wbplus = {
+    .codec = &_codec_audio_amr_wb,
+    .rates = DLNA_AUDIO_RATE(8000, 16000, 24000, 32000, 48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_amr_wbplus_3gp = {
+    .codec = &_codec_audio_amr_wb,
+    .rates = DLNA_AUDIO_RATE(8000, 16000, 24000, 32000, 48000),
+};
+
+const struct lms_dlna_audio_profile _dlna_mp4_audio_rules[] = {
+    {
+        .dlna_profile = &_dlna_profile_aac_iso,
+        .dlna_mime = &_dlna_mime_audio,
+        .audio_rule = &_dlna_audio_rule_aac_iso,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_iso_320,
+        .dlna_mime = &_dlna_mime_audio,
+        .audio_rule = &_dlna_audio_rule_aac_iso_320,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_mult5_iso,
+        .dlna_mime = &_dlna_mime_audio,
+        .audio_rule = &_dlna_audio_rule_aac_mult5_iso,
+    },
+    {
+        .dlna_profile = &_dlna_profile_ac3,
+        .dlna_mime = &_dlna_mime_audio_dolby,
+        .audio_rule = &_dlna_audio_rule_ac3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_eac3,
+        .dlna_mime = &_dlna_mime_audio_eac3,
+        .audio_rule = &_dlna_audio_rule_eac3,
+    },
+    {
+        .dlna_profile = &_dlna_profile_amr_3gpp,
+        .dlna_mime = &_dlna_mime_audio,
+        .audio_rule = &_dlna_audio_rule_amr,
+    },
+    {
+        .dlna_profile = &_dlna_profile_amr_wbplus,
+        .dlna_mime = &_dlna_mime_audio,
+        .audio_rule = &_dlna_audio_rule_amr_wbplus,
+    },
+    {NULL}
+};
+
+const struct lms_dlna_audio_profile _dlna_3gp_audio_rules[] = {
+    {
+        .dlna_profile = &_dlna_profile_aac_iso,
+        .dlna_mime = &_dlna_mime_audio_3gp,
+        .audio_rule = &_dlna_audio_rule_aac_iso_3gp,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_iso_320,
+        .dlna_mime = &_dlna_mime_audio_3gp,
+        .audio_rule = &_dlna_audio_rule_aac_iso_320_3gp,
+    },
+    {
+        .dlna_profile = &_dlna_profile_aac_mult5_iso,
+        .dlna_mime = &_dlna_mime_audio_3gp,
+        .audio_rule = &_dlna_audio_rule_aac_mult5_iso_3gp,
+    },
+    {
+        .dlna_profile = &_dlna_profile_amr_3gpp,
+        .dlna_mime = &_dlna_mime_audio_3gp,
+        .audio_rule = &_dlna_audio_rule_amr_3gpp,
+    },
+    {
+        .dlna_profile = &_dlna_profile_amr_wbplus,
+        .dlna_mime = &_dlna_mime_audio_3gp,
+        .audio_rule = &_dlna_audio_rule_amr_wbplus_3gp,
+    },
+    {NULL}
+};
+
+/** asf */
+DECL_STR(_codec_audio_wmavpro, "wmavpro");
+
+DECL_STR(_dlna_wma_base, "WMABASE");
+DECL_STR(_dlna_wma_full, "WMAFULL");
+DECL_STR(_dlna_wma_pro, "WMAPRO");
+DECL_STR(_dlna_wma_mime, "audio/x-ms-wma");
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_wma_base = {
+    .rate_range = DLNA_BITRATE(0, 48000),
+    .bitrate = DLNA_BITRATE(0, 192999),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_wma_full = {
+    .rate_range = DLNA_BITRATE(0, 48000),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_wma_pro = {
+    .codec = &_codec_audio_wmavpro,
+    .rate_range = DLNA_BITRATE(0, 96000),
+    .channels = DLNA_BITRATE(1, 8),
+    .bitrate = DLNA_BITRATE(0, 1500000),
+};
+
+const struct lms_dlna_audio_profile _dlna_wma_rules[] = {
+    {
+        .dlna_profile = &_dlna_wma_base,
+        .dlna_mime = &_dlna_wma_mime,
+        .audio_rule = &_dlna_audio_rule_wma_base,
+    },
+    {
+        .dlna_profile = &_dlna_wma_full,
+        .dlna_mime = &_dlna_wma_mime,
+        .audio_rule = &_dlna_audio_rule_wma_full,
+    },
+    {
+        .dlna_profile = &_dlna_wma_pro,
+        .dlna_mime = &_dlna_wma_mime,
+        .audio_rule = &_dlna_audio_rule_wma_pro,
+    },
+    {NULL}
+};
+
+/** wma */
+DECL_STR(_dlna_profile_wave_lpcm, "LPCM");
+
+DECL_STR(_dlna_mime_44_mono, "audio/L16;rate=44100;channels=1");
+DECL_STR(_dlna_mime_44_stereo, "audio/L16;rate=44100;channels=2");
+DECL_STR(_dlna_mime_48_mono, "audio/L16;rate=48000;channels=1");
+DECL_STR(_dlna_mime_48_stereo, "audio/L16;rate=48000;channels=2");
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_wave_lpcm_44_mono = {
+    .rates = DLNA_AUDIO_RATE(44100),
+    .channels = DLNA_BITRATE(1, 1),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_wave_lpcm_44_stereo = {
+    .rates = DLNA_AUDIO_RATE(44100),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_wave_lpcm_48_mono = {
+    .rates = DLNA_AUDIO_RATE(48000),
+    .channels = DLNA_BITRATE(1, 1),
+};
+
+static const struct lms_dlna_audio_rule _dlna_audio_rule_wave_lpcm_48_stereo = {
+    .rates = DLNA_AUDIO_RATE(48000),
+    .channels = DLNA_BITRATE(1, 2),
+};
+
+const struct lms_dlna_audio_profile _dlna_wave_rules[] = {
+    {
+        .dlna_profile = &_dlna_profile_wave_lpcm,
+        .dlna_mime = &_dlna_mime_44_mono,
+        .audio_rule = &_dlna_audio_rule_wave_lpcm_44_mono,
+    },
+    {
+        .dlna_profile = &_dlna_profile_wave_lpcm,
+        .dlna_mime = &_dlna_mime_44_stereo,
+        .audio_rule = &_dlna_audio_rule_wave_lpcm_44_stereo,
+    },
+    {
+        .dlna_profile = &_dlna_profile_wave_lpcm,
+        .dlna_mime = &_dlna_mime_48_mono,
+        .audio_rule = &_dlna_audio_rule_wave_lpcm_48_mono,
+    },
+    {
+        .dlna_profile = &_dlna_profile_wave_lpcm,
+        .dlna_mime = &_dlna_mime_48_stereo,
+        .audio_rule = &_dlna_audio_rule_wave_lpcm_48_stereo,
+    },
+    {NULL}
+};
+
+/** jpeg */
+DECL_STR(_dlna_jpeg_mime, "image/jpeg");
+
+DECL_STR(_dlna_jpeg_sm_ico, "JPEG_SM_ICO");
+DECL_STR(_dlna_jpeg_lrg_ico, "JPEG_LRG_ICO");
+DECL_STR(_dlna_jpeg_tn, "JPEG_TN");
+DECL_STR(_dlna_jpeg_sm, "JPEG_SM");
+DECL_STR(_dlna_jpeg_med, "JPEG_MED");
+DECL_STR(_dlna_jpeg_lrg, "JPEG_LRG");
+
+static const struct lms_dlna_image_rule _dlna_image_rule_jpeg_sm_ico = {
+    .width = DLNA_BITRATE(48, 48),
+    .height = DLNA_BITRATE(48, 48),
+};
+
+static const struct lms_dlna_image_rule _dlna_image_rule_jpeg_lrg_ico = {
+    .width = DLNA_BITRATE(0, 120),
+    .height = DLNA_BITRATE(0, 120),
+};
+
+static const struct lms_dlna_image_rule _dlna_image_rule_jpeg_tn = {
+    .width = DLNA_BITRATE(0, 160),
+    .height = DLNA_BITRATE(0, 160),
+};
+
+static const struct lms_dlna_image_rule _dlna_image_rule_jpeg_sm = {
+    .width = DLNA_BITRATE(0, 640),
+    .height = DLNA_BITRATE(0, 480),
+};
+
+static const struct lms_dlna_image_rule _dlna_image_rule_jpeg_med = {
+    .width = DLNA_BITRATE(0, 1024),
+    .height = DLNA_BITRATE(0, 768),
+};
+
+static const struct lms_dlna_image_rule _dlna_image_rule_jpeg_lrg = {
+    .width = DLNA_BITRATE(0, 4096),
+    .height = DLNA_BITRATE(0, 4096),
+};
+
+const struct lms_dlna_image_profile _dlna_jpeg_rules[] = {
+    {
+        .dlna_profile = &_dlna_jpeg_sm_ico,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_sm_ico,
+    },
+    {
+        .dlna_profile = &_dlna_jpeg_lrg_ico,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_lrg_ico,
+    },
+    {
+        .dlna_profile = &_dlna_jpeg_tn,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_tn,
+    },
+    {
+        .dlna_profile = &_dlna_jpeg_sm,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_sm,
+    },
+    {
+        .dlna_profile = &_dlna_jpeg_med,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_med,
+    },
+    {
+        .dlna_profile = &_dlna_jpeg_lrg,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_lrg,
+    },
+    {NULL}
+};
+
+/** png */
+
+DECL_STR(_dlna_png_mime, "image/png");
+
+DECL_STR(_dlna_png_sm_ico, "PNG_SM_ICO");
+DECL_STR(_dlna_png_lrg_ico, "PNG_LRG_ICO");
+DECL_STR(_dlna_png_tn, "PNG_TN");
+DECL_STR(_dlna_png_lrg, "PNG_LRG");
+
+/** using the same rules as jpeg but in a smaller subset */
+const struct lms_dlna_image_profile _dlna_png_rules[] = {
+    {
+        .dlna_profile = &_dlna_jpeg_sm_ico,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_sm_ico,
+    },
+    {
+        .dlna_profile = &_dlna_jpeg_lrg_ico,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_lrg_ico,
+    },
+    {
+        .dlna_profile = &_dlna_jpeg_tn,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_tn,
+    },
+    {
+        .dlna_profile = &_dlna_jpeg_lrg,
+        .dlna_mime = &_dlna_jpeg_mime,
+        .image_rule = &_dlna_image_rule_jpeg_lrg,
+    },
+    {NULL}
+};
index c5fd5f4..f8be270 100644 (file)
@@ -52,6 +52,9 @@ extern "C" {
         unsigned int len;
     };
 
+#define DECL_STR(cname, str)                                                \
+    static const struct lms_string_size cname = LMS_STATIC_STRING_SIZE(str) \
+
 #define LMS_STATIC_STRING_SIZE(s) ((struct lms_string_size) { (char *)s, sizeof(s) - 1})
 #define LMS_ARRAY_SIZE(a)  (sizeof(a) / sizeof(*a))