From: Leandro Dorileo Date: Tue, 3 Dec 2013 16:10:47 +0000 (-0200) Subject: mp4: implement dlna profile and mime computation X-Git-Tag: accepted/tizen/generic/20140106.140339~11 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7307661ef8dd4ac4b6ab028f75880e1835a3110f;p=platform%2Fupstream%2Flightmediascanner.git mp4: implement dlna profile and mime computation --- diff --git a/src/plugins/mp4/mp4.c b/src/plugins/mp4/mp4.c index d19e667..09e2c40 100644 --- a/src/plugins/mp4/mp4.c +++ b/src/plugins/mp4/mp4.c @@ -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); }