mp4: implement dlna profile and mime computation
authorLeandro Dorileo <leandro.maciel.dorileo@intel.com>
Tue, 3 Dec 2013 16:10:47 +0000 (14:10 -0200)
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>
Fri, 27 Dec 2013 13:23:14 +0000 (11:23 -0200)
src/plugins/mp4/mp4.c

index d19e667..09e2c40 100644 (file)
@@ -52,7 +52,8 @@ struct plugin {
 #define DECL_STR(cname, str)                                            \
     static const struct lms_string_size cname = LMS_STATIC_STRING_SIZE(str)
 
-DECL_STR(_container, "mp4");
+DECL_STR(_container_mp4, "mp4");
+DECL_STR(_container_3gp, "3gp");
 
 DECL_STR(_codec_audio_mpeg4aac_main, "mpeg4aac-main");
 DECL_STR(_codec_audio_mpeg4aac_lc, "mpeg4aac-lc");
@@ -174,7 +175,48 @@ DECL_STR(_codec_video_h261, "h261");
 
 DECL_STR(_codec_audio_amr, "amr");
 DECL_STR(_codec_audio_amr_wb, "amr-wb");
-#undef DECL_STR
+
+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_aac_iso_320, "AAC_ISO_320");
+DECL_STR(_dlna_profile_aac_iso, "AAC_ISO");
+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_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_mp4_mp_hd_1080i_aac, "AVC_MP4_MP_HD_1080i_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_avc_mp4_hp_hd_eac3, "AVC_MP4_HP_HD_EAC3");
+
+DECL_STR(_dlna_mime_video, "video/mp4");
+DECL_STR(_dlna_mime_video_3gp, "video/3gpp");
+DECL_STR(_dlna_mime_video_matroska, "video/x-matroska");
+DECL_STR(_dlna_mime_audio, "audio/mp4");
+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");
 
 struct type_str {
     uint8_t type;
@@ -334,6 +376,7 @@ static const char *_authors[] = {
     "Andre Moreira Magalhaes",
     "Lucas De Marchi",
     "Gustavo Sverzut Barbieri",
+    "Leandro Dorileo",
     NULL
 };
 
@@ -455,7 +498,51 @@ _get_video_codec(MP4FileHandle mp4_fh, MP4TrackId id)
             snprintf(str_level, sizeof(str_level), "%u.%u", level / 10,
                      level % 10);
 
-        ret.len = snprintf(buf, sizeof(buf), "h264-%s-%s",
+        /* fix constrained and 1b case for baseline and main */
+        if (profile == 66 || profile == 77) {
+            uint8_t *sps;
+            uint32_t spslen;
+            bool constrained = false;
+            bool level1b = false;
+
+            if (MP4HaveAtom(mp4_fh,
+                            "moov.trak.mdia.minf.stbl.stsd.avc1.avcC") &&
+                MP4GetBytesProperty(mp4_fh, "moov.trak.mdia.minf.stbl.stsd."
+                                    "avc1.avcC.sequenceEntries."
+                                    "sequenceParameterSetNALUnit",
+                                    &sps, &spslen)) {
+                /* SPS (Sequence Parameter Set) is:
+                 *  8 bits (1 byte) for profile_idc
+                 *  1 bit for constraint_set0_flag
+                 *  1 bit for constraint_set1_flag <- we use this for constr.
+                 *  1 bit for constraint_set2_flag
+                 *  1 bit for constraint_set3_flag <- we use this for 1b
+                 * based on ffmpeg's (libavcodec/h264_ps.c) and
+                 * x264 (encoder/set.c)
+                 */
+                if (spslen > 1) {
+                    if ((sps[1] >> 1) & 0x1)
+                        constrained = true;
+                    if (((sps[1] >> 3) & 0x1) && level / 10 == 1)
+                        level1b = true;
+                }
+                free(sps);
+
+                if (constrained) {
+                    if (profile == 66)
+                        memcpy(str_profile, "constrained-baseline",
+                               sizeof("constrained-baseline"));
+                    else
+                        memcpy(str_profile, "constrained-main",
+                               sizeof("constrained-main"));
+                }
+
+                if (level1b)
+                    memcpy(str_level, "1b", sizeof("1b"));
+            }
+        }
+
+        ret.len = snprintf(buf, sizeof(buf), "h264-%s-l%s",
                            str_profile, str_level);
         ret.str = buf;
         goto found;
@@ -498,6 +585,1864 @@ _get_lang(MP4FileHandle mp4_fh, MP4TrackId id)
     return ret;
 }
 
+static struct lms_string_size
+_get_container(MP4FileHandle mp4_fh)
+{
+    const char *brand;
+
+    if (!MP4GetStringProperty(mp4_fh, "ftyp.majorBrand", &brand))
+        return _container_mp4;
+
+    if (strncasecmp(brand, "3gp", 3) == 0)
+        return _container_3gp;
+
+    /* NOTE: this should be an array, but the C wrapper of mp4v2
+     * doesn't expose a way to give the index number and
+     * ftyp.compatibleBrands is not in counted format (name[idx])
+     */
+    if (!MP4GetStringProperty(mp4_fh, "ftyp.compatibleBrands", &brand))
+        return _container_mp4;
+
+    if (strncasecmp(brand, "3gp", 3) == 0)
+        return _container_3gp;
+
+    return _container_mp4;
+}
+
+#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_VIDEO_FRAMERATE_RANGE(_min, _max)                          \
+    &(struct dlna_video_framerate_range) {.min = _min, .max = _max}     \
+
+#define DLNA_AUDIO_RATE(_val...)                        \
+    &(struct dlna_audio_rate) {.rates = {_val}}         \
+
+#define MAX_AUDIO_LEVELS 5
+#define MAX_AUDIO_MPEG_VERSIONS 2
+#define MAX_AUDIO_RATES 9
+#define MAX_VIDEO_RULE_LEVEL 13
+
+struct dlna_bitrate {
+     unsigned int min;
+     unsigned int max;
+};
+
+struct dlna_video_framerate_range {
+    double min;
+    double max;
+};
+
+struct dlna_video_res {
+    unsigned int width;
+    unsigned int height;
+};
+
+struct dlna_video_res_range {
+    unsigned int width_min;
+    unsigned int width_max;
+    unsigned int height_min;
+    unsigned int height_max;
+};
+
+struct dlna_level {
+    const char *levels[MAX_VIDEO_RULE_LEVEL];
+};
+
+struct dlna_video_rule {
+     struct dlna_video_res *res;
+     struct dlna_video_res_range *res_range;
+     struct dlna_bitrate *bitrate;
+     struct dlna_level *levels;
+     struct dlna_video_framerate_range *framerate_range;
+};
+
+struct dlna_audio_rate {
+     unsigned int rates[MAX_AUDIO_RATES];
+};
+
+struct dlna_audio_rule {
+     const struct lms_string_size *codec;
+     const struct lms_string_size *container;
+     struct dlna_audio_rate *rates;
+     struct dlna_level *levels;
+     struct dlna_bitrate *channels;
+     struct dlna_bitrate *bitrate;
+};
+
+struct dlna_video_profile {
+     const struct lms_string_size *dlna_profile;
+     const struct lms_string_size *dlna_mime;
+     const struct dlna_video_rule *video_rules;
+     const struct dlna_audio_rule *audio_rule;
+};
+
+struct dlna_audio_profile {
+     const struct lms_string_size *dlna_profile;
+     const struct lms_string_size *dlna_mime;
+     const struct dlna_audio_rule *audio_rule;
+};
+
+static const struct 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 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 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 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 dlna_video_rule _dlna_video_rule_sp_l5[] = {
+    DLNA_VIDEO_RULE_SP_L5,
+    { NULL },
+};
+
+static const struct 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 dlna_video_rule _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac[] = {
+    DLNA_VIDEO_RULE_H263_P0_L10,
+    { NULL },
+};
+
+static const struct 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 dlna_video_rule _dlna_video_rule_avc_mp4_bl_cif15_aac_520[] = {
+    DLNA_VIDEO_RULES_AVC_MP4_BL_CIF15,
+    { NULL },
+};
+
+static const struct 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 dlna_video_rule _dlna_video_rule_avc_mp4_bl_l3l_sd_aac[] = {
+    DLNA_VIDEO_RULES_L3_L3L_SD_AAC,
+    { NULL },
+};
+
+static const struct 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 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 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 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 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),
+    },
+};
+
+// mpeg4
+static const struct 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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),
+};
+
+static const  struct dlna_video_profile _dlna_video_profile_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 dlna_audio_rule _dlna_audio_rule_aac_iso = {
+    DLNA_AUDIO_RULE_AAC_ISO,
+    .container = &_container_mp4,
+};
+
+static const struct dlna_audio_rule _dlna_audio_rule_aac_iso_3gp = {
+    DLNA_AUDIO_RULE_AAC_ISO,
+    .container = &_container_3gp,
+};
+
+#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 dlna_audio_rule _dlna_audio_rule_aac_iso_320 = {
+    DLNA_AUDIO_RULE_AAC_ISO_320,
+    .container = &_container_mp4,
+};
+
+static const struct dlna_audio_rule _dlna_audio_rule_aac_iso_320_3gp = {
+    DLNA_AUDIO_RULE_AAC_ISO_320,
+    .container = &_container_3gp,
+};
+
+#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 dlna_audio_rule _dlna_audio_rule_aac_mult5_iso = {
+    DLNA_AUDIO_RULE_AAC_MULT5_ISO,
+    .container = &_container_mp4,
+};
+
+static const struct dlna_audio_rule _dlna_audio_rule_aac_mult5_iso_3gp = {
+    DLNA_AUDIO_RULE_AAC_MULT5_ISO,
+    .container = &_container_3gp,
+};
+
+static const struct 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 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 dlna_audio_rule _dlna_audio_rule_amr_3gpp = {
+    .codec = &_codec_audio_amr,
+    .container = &_container_3gp,
+};
+
+static const struct dlna_audio_rule _dlna_audio_rule_amr = {
+    .codec = &_codec_audio_amr,
+};
+
+static const struct 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 dlna_audio_rule _dlna_audio_rule_amr_wbplus_3gp = {
+    .codec = &_codec_audio_amr_wb,
+    .container = &_container_3gp,
+    .rates = DLNA_AUDIO_RATE(8000, 16000, 24000, 32000, 48000),
+};
+
+//_dlna_profile_aac_mult5_iso
+static const  struct dlna_audio_profile _dlna_audio_profile_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,
+        .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,
+        .audio_rule = &_dlna_audio_rule_aac_iso_320,
+    },
+    {
+        .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,
+        .audio_rule = &_dlna_audio_rule_aac_mult5_iso,
+    },
+    {
+        .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_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_3gp,
+        .audio_rule = &_dlna_audio_rule_amr_3gpp,
+    },
+    {
+        .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,
+    },
+    {
+        .dlna_profile = &_dlna_profile_amr_wbplus,
+        .dlna_mime = &_dlna_mime_audio_3gp,
+        .audio_rule = &_dlna_audio_rule_amr_wbplus_3gp,
+    },
+    { NULL }
+};
+
+static bool
+_string_vector_has_value(const char **list, const char *wanted)
+{
+    int i;
+    const char *curr;
+
+    for (i = 0, curr = list[i]; curr != NULL; i++, curr = list[i]) {
+        if (!strcmp(curr, wanted)) return true;
+    }
+
+    return false;
+}
+
+static bool
+_uint_vector_has_value(const unsigned int *list, unsigned int wanted)
+{
+    int i;
+    unsigned int curr;
+
+    for (i = 0, curr = list[i]; curr != INT32_MAX; i++, curr = list[i])
+      if (curr == wanted) return true;
+
+    return false;
+}
+
+static void
+_fill_audio_dlna_profile(struct lms_audio_info *info)
+{
+    int i = 0;
+
+    while (true) {
+        const struct dlna_audio_profile *curr = _dlna_audio_profile_rules + i;
+        const struct dlna_audio_rule *rule;
+
+        if (curr->dlna_profile == NULL && curr->dlna_mime == NULL &&
+            curr->audio_rule == NULL)
+            break;
+
+        i++;
+        rule = curr->audio_rule;
+
+        if (rule->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->channels &&
+            (info->channels < rule->channels->min ||
+             info->channels > rule->channels->max))
+            continue;
+
+        if (rule->codec && strcmp(rule->codec->str, info->codec.str))
+            continue;
+
+        if (rule->container && strcmp(rule->container->str, info->container.str))
+            continue;
+
+        info->dlna_mime = *curr->dlna_mime;
+        info->dlna_profile = *curr->dlna_profile;
+        break;
+    }
+}
+
+static const struct dlna_video_profile *
+_get_video_dlna_profile(const struct lms_stream_audio_info *audio,
+                        const struct lms_stream *audio_stream,
+                        const struct lms_stream_video_info *video,
+                        const struct lms_stream *video_stream)
+{
+    int i, length;
+    const struct dlna_video_profile *curr;
+    char *level;
+
+    level = strstr(video_stream->codec.str, "-l");
+    length = sizeof(_dlna_video_profile_rules) / sizeof(struct dlna_video_profile);
+
+    for (i = 0, curr = &_dlna_video_profile_rules[i]; i < length; i++,
+             curr = &_dlna_video_profile_rules[i]) {
+        const struct dlna_video_rule *video_rule;
+        const struct dlna_audio_rule *audio_rule;
+        const struct dlna_video_rule *r;
+
+        audio_rule = curr->audio_rule;
+        r = curr->video_rules;
+
+        if (audio_rule->bitrate && (audio->bitrate < audio_rule->bitrate->min ||
+                                    audio->bitrate > audio_rule->bitrate->max))
+            continue;
+
+        if (audio_rule->rates &&
+            !_uint_vector_has_value(audio_rule->rates->rates,
+                                    audio->sampling_rate))
+            continue;
+
+        if (audio_rule->channels &&
+            (audio->channels < audio_rule->channels->min ||
+             audio->channels > audio_rule->channels->max))
+            continue;
+
+        if (audio_rule->codec &&
+            strcmp(audio_stream->codec.str, audio_rule->codec->str))
+            continue;
+
+        while (true) {
+            video_rule = r++;
+
+            if (!video_rule->res && !video_rule->bitrate &&
+                !video_rule->levels && !video_rule->framerate_range)
+                break;
+
+            if (video_rule->res && (video->width != video_rule->res->width &&
+                                    video->height != video_rule->res->height))
+                continue;
+
+            if (video_rule->res_range &&
+                !(video->width >= video_rule->res_range->width_min &&
+                  video->width <= video_rule->res_range->width_max &&
+                  video->height >= video_rule->res_range->height_min &&
+                  video->height <= video_rule->res_range->height_max))
+                continue;
+
+            if (video_rule->framerate_range &&
+                !(video->framerate >= video_rule->framerate_range->min &&
+                  video->framerate <= video_rule->framerate_range->max))
+                continue;
+
+            if (video_rule->bitrate &&
+                !(video->bitrate >= video_rule->bitrate->min &&
+                  video->bitrate <= video_rule->bitrate->max))
+                continue;
+
+            if (video_rule->levels &&
+                !_string_vector_has_value(video_rule->levels->levels,
+                                          level + 2))
+                continue;
+
+            return curr;
+        }
+    }
+
+    return NULL;
+}
+
+static void
+_fill_video_dlna_profile(struct lms_video_info *info)
+{
+    const struct dlna_video_profile *profile;
+    const struct lms_stream *s, *audio_stream, *video_stream;
+    const struct lms_stream_audio_info *audio;
+    const struct lms_stream_video_info *video;
+
+    audio_stream = video_stream = NULL;
+    audio = NULL;
+    video = NULL;
+
+    for (s = info->streams; s; s = s->next) {
+        if (s->type == LMS_STREAM_TYPE_VIDEO) {
+            video = &s->video;
+            video_stream = s;
+            if (audio) break;
+        } else if (s->type == LMS_STREAM_TYPE_AUDIO) {
+            audio = &s->audio;
+            audio_stream = s;
+            if (video) break;
+        }
+    }
+
+    profile = _get_video_dlna_profile(audio, audio_stream, video, video_stream);
+    if (!profile) return;
+
+    info->dlna_profile = *profile->dlna_profile;
+    info->dlna_mime = *profile->dlna_mime;
+}
+
 static int
 _parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match)
 {
@@ -613,14 +2558,20 @@ _parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_in
         audio_info.artist = info.artist;
         audio_info.album = info.album;
         audio_info.genre = info.genre;
-        audio_info.container = _container;
+        audio_info.container = _get_container(mp4_fh);
         audio_info.trackno = info.trackno;
+
+        _fill_audio_dlna_profile(&audio_info);
+
         r = lms_db_audio_add(plugin->audio_db, &audio_info);
     } else {
         video_info.id = finfo->id;
         video_info.title = info.title;
         video_info.artist = info.artist;
-        video_info.container = _container;
+        video_info.container = _get_container(mp4_fh);
+
+        _fill_video_dlna_profile(&video_info);
+
         r = lms_db_video_add(plugin->video_db, &video_info);
     }