change project url to github.
[platform/upstream/lightmediascanner.git] / src / plugins / mp4 / mp4.c
1 /**
2  * Copyright (C) 2008 by INdT
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * @author Andre Moreira Magalhaes <andre.magalhaes@openbossa.org>
19  */
20
21 /**
22  * @brief
23  *
24  * mp4 file parser.
25  */
26
27 static const char PV[] = PACKAGE_VERSION; /* mp4.h screws PACKAGE_VERSION */
28
29 #include <lightmediascanner_plugin.h>
30 #include <lightmediascanner_db.h>
31
32 #include <mp4v2/mp4v2.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <math.h>
36
37 struct mp4_info {
38     struct lms_string_size title;
39     struct lms_string_size artist;
40     struct lms_string_size album;
41     struct lms_string_size genre;
42     uint16_t trackno;
43     uint64_t length;
44 };
45
46 struct plugin {
47     struct lms_plugin plugin;
48     lms_db_audio_t *audio_db;
49     lms_db_video_t *video_db;
50 };
51
52 #define DECL_STR(cname, str)                                            \
53     static const struct lms_string_size cname = LMS_STATIC_STRING_SIZE(str)
54
55 DECL_STR(_container_mp4, "mp4");
56 DECL_STR(_container_3gp, "3gp");
57
58 DECL_STR(_codec_audio_mpeg4aac_main, "mpeg4aac-main");
59 DECL_STR(_codec_audio_mpeg4aac_lc, "mpeg4aac-lc");
60 DECL_STR(_codec_audio_mpeg4aac_ssr, "mpeg4aac-ssr");
61 DECL_STR(_codec_audio_mpeg4aac_ltp, "mpeg4aac-ltp");
62 DECL_STR(_codec_audio_mpeg4aac_he, "mpeg4aac-he");
63 DECL_STR(_codec_audio_mpeg4aac_scalable, "mpeg4aac-scalable");
64 DECL_STR(_codec_audio_mpeg4_twinvq, "mpeg4twinvq");
65 DECL_STR(_codec_audio_mpeg4_celp, "mpeg4celp");
66 DECL_STR(_codec_audio_mpeg4_hvxc, "mpeg4hvxc");
67 DECL_STR(_codec_audio_mpeg4_tssi, "mpeg4ttsi");
68 DECL_STR(_codec_audio_mpeg4_main_synthetic,"mpeg4main-synthetic");
69 DECL_STR(_codec_audio_mpeg4_wavetable_syn, "mpeg4wavetable-syn");
70 DECL_STR(_codec_audio_mpeg4_general_midi, "mpeg4general-midi");
71 DECL_STR(_codec_audio_mpeg4_algo_syn_and_audio_fx, "mpeg4algo-syn-and-audio-fx");
72 DECL_STR(_codec_audio_mpeg4_er_aac_lc, "mpeg4er-aac-lc");
73 DECL_STR(_codec_audio_mpeg4_er_aac_ltp, "mpeg4er-aac-ltp");
74 DECL_STR(_codec_audio_mpeg4_er_aac_scalable, "mpeg4er-aac-scalable");
75 DECL_STR(_codec_audio_mpeg4_er_twinvq, "mpeg4er-twinvq");
76 DECL_STR(_codec_audio_mpeg4_er_bsac, "mpeg4er-bsac");
77 DECL_STR(_codec_audio_mpeg4_er_acc_ld, "mpeg4er-acc-ld");
78 DECL_STR(_codec_audio_mpeg4_er_celp, "mpeg4er-celp");
79 DECL_STR(_codec_audio_mpeg4_er_hvxc, "mpeg4er-hvxc");
80 DECL_STR(_codec_audio_mpeg4_er_hiln, "mpeg4er-hiln");
81 DECL_STR(_codec_audio_mpeg4_er_parametric, "mpeg4er-parametric");
82 DECL_STR(_codec_audio_mpeg4_ssc, "mpeg4ssc");
83 DECL_STR(_codec_audio_mpeg4_ps, "mpeg4ps");
84 DECL_STR(_codec_audio_mpeg4_mpeg_surround, "mpeg4mpeg-surround");
85 DECL_STR(_codec_audio_mpeg4_layer1, "mpeg4layer1");
86 DECL_STR(_codec_audio_mpeg4_layer2, "mpeg4layer2");
87 DECL_STR(_codec_audio_mpeg4_layer3, "mpeg4layer3");
88 DECL_STR(_codec_audio_mpeg4_dst, "mpeg4dst");
89 DECL_STR(_codec_audio_mpeg4_audio_lossless, "mpeg4audio-lossless");
90 DECL_STR(_codec_audio_mpeg4_sls, "mpeg4sls");
91 DECL_STR(_codec_audio_mpeg4_sls_non_core, "mpeg4sls-non-core");
92
93 DECL_STR(_codec_audio_mpeg2aac_main, "mpeg2aac-main");
94 DECL_STR(_codec_audio_mpeg2aac_lc, "mpeg2aac-lc");
95 DECL_STR(_codec_audio_mpeg2aac_ssr, "mpeg2aac-ssr");
96 DECL_STR(_codec_audio_mpeg2audio, "mpeg2audio");
97 DECL_STR(_codec_audio_mpeg1audio, "mpeg1audio");
98 DECL_STR(_codec_audio_pcm16le, "pcm16le");
99 DECL_STR(_codec_audio_vorbis, "vorbis");
100 DECL_STR(_codec_audio_alaw, "alaw");
101 DECL_STR(_codec_audio_ulaw, "ulaw");
102 DECL_STR(_codec_audio_g723, "g723");
103 DECL_STR(_codec_audio_pcm16be, "pcm16be");
104
105 DECL_STR(_codec_video_mpeg4_simple_l1, "mpeg4-simple-l1");
106 DECL_STR(_codec_video_mpeg4_simple_l2, "mpeg4-simple-l2");
107 DECL_STR(_codec_video_mpeg4_simple_l3, "mpeg4-simple-l3");
108 DECL_STR(_codec_video_mpeg4_simple_l0, "mpeg4-simple-l0");
109 DECL_STR(_codec_video_mpeg4_simple_scalable_l1, "mpeg4-simple-scalable-l1");
110 DECL_STR(_codec_video_mpeg4_simple_scalable_l2, "mpeg4-simple-scalable-l2");
111 DECL_STR(_codec_video_mpeg4_core_l1, "mpeg4-core-l1");
112 DECL_STR(_codec_video_mpeg4_core_l2, "mpeg4-core-l2");
113 DECL_STR(_codec_video_mpeg4_main_l2, "mpeg4-main-l2");
114 DECL_STR(_codec_video_mpeg4_main_l3, "mpeg4-main-l3");
115 DECL_STR(_codec_video_mpeg4_main_l4, "mpeg4-main-l4");
116 DECL_STR(_codec_video_mpeg4_nbit_l2, "mpeg4-nbit-l2");
117 DECL_STR(_codec_video_mpeg4_scalable_texture_l1, "mpeg4-scalable-texture-l1");
118 DECL_STR(_codec_video_mpeg4_simple_face_anim_l1, "mpeg4-simple-face-anim-l1");
119 DECL_STR(_codec_video_mpeg4_simple_face_anim_l2, "mpeg4-simple-face-anim-l2");
120 DECL_STR(_codec_video_mpeg4_simple_fba_l1, "mpeg4-simple-fba-l1");
121 DECL_STR(_codec_video_mpeg4_simple_fba_l2, "mpeg4-simple-fba-l2");
122 DECL_STR(_codec_video_mpeg4_basic_anim_text_l1, "mpeg4-basic-anim-text-l1");
123 DECL_STR(_codec_video_mpeg4_basic_anim_text_l2, "mpeg4-basic-anim-text-l2");
124 DECL_STR(_codec_video_mpeg4_hybrid_l1, "mpeg4-hybrid-l1");
125 DECL_STR(_codec_video_mpeg4_hybrid_l2, "mpeg4-hybrid-l2");
126 DECL_STR(_codec_video_mpeg4_adv_rt_simple_l1, "mpeg4-adv-rt-simple-l1");
127 DECL_STR(_codec_video_mpeg4_adv_rt_simple_l2, "mpeg4-adv-rt-simple-l2");
128 DECL_STR(_codec_video_mpeg4_adv_rt_simple_l3, "mpeg4-adv-rt-simple-l3");
129 DECL_STR(_codec_video_mpeg4_adv_rt_simple_l4, "mpeg4-adv-rt-simple-l4");
130 DECL_STR(_codec_video_mpeg4_core_scalable_l1, "mpeg4-core-scalable-l1");
131 DECL_STR(_codec_video_mpeg4_core_scalable_l2, "mpeg4-core-scalable-l2");
132 DECL_STR(_codec_video_mpeg4_core_scalable_l3, "mpeg4-core-scalable-l3");
133 DECL_STR(_codec_video_mpeg4_adv_coding_efficiency_l1, "mpeg4-adv-coding-efficiency-l1");
134 DECL_STR(_codec_video_mpeg4_adv_coding_efficiency_l2, "mpeg4-adv-coding-efficiency-l2");
135 DECL_STR(_codec_video_mpeg4_adv_coding_efficiency_l3, "mpeg4-adv-coding-efficiency-l3");
136 DECL_STR(_codec_video_mpeg4_adv_coding_efficiency_l4, "mpeg4-adv-coding-efficiency-l4");
137 DECL_STR(_codec_video_mpeg4_adv_core_l1, "mpeg4-adv-core-l1");
138 DECL_STR(_codec_video_mpeg4_adv_core_l2, "mpeg4-adv-core-l2");
139 DECL_STR(_codec_video_mpeg4_adv_scalable_texture_l1, "mpeg4-adv-scalable-texture-l1");
140 DECL_STR(_codec_video_mpeg4_adv_scalable_texture_l2, "mpeg4-adv-scalable-texture-l2");
141 DECL_STR(_codec_video_mpeg4_adv_scalable_texture_l3, "mpeg4-adv-scalable-texture-l3");
142 DECL_STR(_codec_video_mpeg4_simple_studio_l1, "mpeg4-simple-studio-l1");
143 DECL_STR(_codec_video_mpeg4_simple_studio_l2, "mpeg4-simple-studio-l2");
144 DECL_STR(_codec_video_mpeg4_simple_studio_l3, "mpeg4-simple-studio-l3");
145 DECL_STR(_codec_video_mpeg4_simple_studio_l4, "mpeg4-simple-studio-l4");
146 DECL_STR(_codec_video_mpeg4_core_studio_l1, "mpeg4-core-studio-l1");
147 DECL_STR(_codec_video_mpeg4_core_studio_l2, "mpeg4-core-studio-l2");
148 DECL_STR(_codec_video_mpeg4_core_studio_l3, "mpeg4-core-studio-l3");
149 DECL_STR(_codec_video_mpeg4_core_studio_l4, "mpeg4-core-studio-l4");
150 DECL_STR(_codec_video_mpeg4_adv_simple_l0, "mpeg4-adv-simple-l0");
151 DECL_STR(_codec_video_mpeg4_adv_simple_l1, "mpeg4-adv-simple-l1");
152 DECL_STR(_codec_video_mpeg4_adv_simple_l2, "mpeg4-adv-simple-l2");
153 DECL_STR(_codec_video_mpeg4_adv_simple_l3, "mpeg4-adv-simple-l3");
154 DECL_STR(_codec_video_mpeg4_adv_simple_l4, "mpeg4-adv-simple-l4");
155 DECL_STR(_codec_video_mpeg4_adv_simple_l5, "mpeg4-adv-simple-l5");
156 DECL_STR(_codec_video_mpeg4_adv_simple_l3b, "mpeg4-adv-simple-l3b");
157 DECL_STR(_codec_video_mpeg4_fgs_l0, "mpeg4-fgs-l0");
158 DECL_STR(_codec_video_mpeg4_fgs_l1, "mpeg4-fgs-l1");
159 DECL_STR(_codec_video_mpeg4_fgs_l2, "mpeg4-fgs-l2");
160 DECL_STR(_codec_video_mpeg4_fgs_l3, "mpeg4-fgs-l3");
161 DECL_STR(_codec_video_mpeg4_fgs_l4, "mpeg4-fgs-l4");
162 DECL_STR(_codec_video_mpeg4_fgs_l5, "mpeg4-fgs-l5");
163
164 DECL_STR(_codec_video_mpeg2_simple, "mpeg2-simple");
165 DECL_STR(_codec_video_mpeg2_main, "mpeg2-main");
166 DECL_STR(_codec_video_mpeg2_snr, "mpeg2-snr");
167 DECL_STR(_codec_video_mpeg2_spatial, "mpeg2-spatial");
168 DECL_STR(_codec_video_mpeg2_high, "mpeg2-high");
169 DECL_STR(_codec_video_mpeg2_422, "mpeg2-422");
170 DECL_STR(_codec_video_mpeg1, "mpeg1");
171 DECL_STR(_codec_video_jpeg, "jpeg");
172 DECL_STR(_codec_video_yuv12, "yuv12");
173 DECL_STR(_codec_video_h263, "h263");
174 DECL_STR(_codec_video_h261, "h261");
175
176 DECL_STR(_codec_audio_amr, "amr");
177 DECL_STR(_codec_audio_amr_wb, "amr-wb");
178
179 DECL_STR(_dlna_profile_p2_sp_aac, "MPEG4_P2_MP4_SP_AAC");
180 DECL_STR(_dlna_profile_p2_sp_aac_ltp, "MPEG4_P2_MP4_SP_AAC_LTP");
181 DECL_STR(_dlna_profile_p2_sp_vga_aac, "MPEG4_P2_MP4_SP_VGA_AAC");
182 DECL_STR(_dlna_profile_p2_sp_l2_aac, "MPEG4_P2_MP4_SP_L2_AAC");
183 DECL_STR(_dlna_profile_p2_sp_l5_aac, "MPEG4_P2_MP4_SP_L5_AAC");
184 DECL_STR(_dlna_profile_p2_sp_l6_aac, "MPEG4_P2_MP4_SP_L6_AAC");
185 DECL_STR(_dlna_profile_h263_p0_l10_aac, "MPEG4_H263_MP4_P0_L10_AAC");
186 DECL_STR(_dlna_profile_h263_p0_l10_aac_ltp, "MPEG4_H263_MP4_P0_L10_AAC_LTP");
187
188 DECL_STR(_dlna_profile_aac_iso_320, "AAC_ISO_320");
189 DECL_STR(_dlna_profile_aac_iso, "AAC_ISO");
190 DECL_STR(_dlna_profile_aac_mult5_iso, "AAC_MULT5_ISO");
191 DECL_STR(_dlna_profile_ac3, "AC3");
192 DECL_STR(_dlna_profile_eac3, "EAC3");
193 DECL_STR(_dlna_profile_amr_3gpp, "AMR_3GPP");
194 DECL_STR(_dlna_profile_amr_wbplus, "AMR_WBplus");
195 DECL_STR(_dlna_profile_avc_mp4_bl_cif15_aac_520, "AVC_MP4_BL_CIF15_AAC_520");
196 DECL_STR(_dlna_profile_avc_mp4_bl_cif15_aac, "AVC_MP4_BL_CIF15_AAC");
197 DECL_STR(_dlna_profile_avc_mp4_bl_l3l_sd_aac, "AVC_MP4_BL_L3L_SD_AAC");
198 DECL_STR(_dlna_profile_avc_mp4_bl_l3_sd_aac, "AVC_MP4_BL_L3_SD_AAC");
199 DECL_STR(_dlna_profile_avc_mp4_mp_sd_aac_mult5, "AVC_MP4_MP_SD_AAC_MULT5");
200 DECL_STR(_dlna_profile_avc_mp4_mp_sd_mpeg1_l3, "AVC_MP4_MP_SD_MPEG1_L3");
201 DECL_STR(_dlna_profile_avc_mp4_mp_sd_ac3, "AVC_MP4_MP_SD_AC3");
202 DECL_STR(_dlna_profile_avc_mp4_mp_sd_eac3, "AVC_MP4_MP_SD_EAC3");
203 DECL_STR(_dlna_profile_avc_mp4_mp_hd_720p_aac, "AVC_MP4_MP_HD_720p_AAC");
204 DECL_STR(_dlna_profile_avc_mp4_mp_hd_1080i_aac, "AVC_MP4_MP_HD_1080i_AAC");
205 DECL_STR(_dlna_profile_avc_mkv_mp_hd_aac_mult5, "AVC_MKV_MP_HD_AAC_MULT5");
206 DECL_STR(_dlna_profile_avc_mkv_hp_hd_aac_mult5, "AVC_MKV_HP_HD_AAC_MULT5");
207 DECL_STR(_dlna_profile_avc_mkv_mp_hd_ac3, "AVC_MKV_MP_HD_AC3");
208 DECL_STR(_dlna_profile_avc_mkv_hp_hd_ac3, "AVC_MKV_HP_HD_AC3");
209 DECL_STR(_dlna_profile_avc_mkv_mp_hd_mpeg1_l3, "AVC_MKV_MP_HD_MPEG1_L3");
210 DECL_STR(_dlna_profile_avc_mkv_hp_hd_mpeg1_l3, "AVC_MKV_HP_HD_MPEG1_L3");
211 DECL_STR(_dlna_profile_avc_mp4_hp_hd_eac3, "AVC_MP4_HP_HD_EAC3");
212
213 DECL_STR(_dlna_mime_video, "video/mp4");
214 DECL_STR(_dlna_mime_video_3gp, "video/3gpp");
215 DECL_STR(_dlna_mime_video_matroska, "video/x-matroska");
216 DECL_STR(_dlna_mime_audio, "audio/mp4");
217 DECL_STR(_dlna_mime_audio_3gp, "audio/3gpp");
218 DECL_STR(_dlna_mime_audio_dolby, "audio/vnd.dolby.dd-raw");
219 DECL_STR(_dlna_mime_audio_eac3, "audio/eac3");
220
221 struct type_str {
222     uint8_t type;
223     const struct lms_string_size *str;
224 };
225
226 static const struct lms_string_size *_audio_codecs[] = {
227     &_codec_audio_mpeg4aac_main,
228     &_codec_audio_mpeg4aac_lc,
229     &_codec_audio_mpeg4aac_ssr,
230     &_codec_audio_mpeg4aac_ltp,
231     &_codec_audio_mpeg4aac_he,
232     &_codec_audio_mpeg4aac_scalable,
233     &_codec_audio_mpeg4_twinvq,
234     &_codec_audio_mpeg4_celp,
235     &_codec_audio_mpeg4_hvxc,
236     NULL,
237     NULL,
238     &_codec_audio_mpeg4_tssi,
239     &_codec_audio_mpeg4_main_synthetic,
240     &_codec_audio_mpeg4_wavetable_syn,
241     &_codec_audio_mpeg4_general_midi,
242     &_codec_audio_mpeg4_algo_syn_and_audio_fx,
243     &_codec_audio_mpeg4_er_aac_lc,
244     NULL,
245     &_codec_audio_mpeg4_er_aac_ltp,
246     &_codec_audio_mpeg4_er_aac_scalable,
247     &_codec_audio_mpeg4_er_twinvq,
248     &_codec_audio_mpeg4_er_bsac,
249     &_codec_audio_mpeg4_er_acc_ld,
250     &_codec_audio_mpeg4_er_celp,
251     &_codec_audio_mpeg4_er_hvxc,
252     &_codec_audio_mpeg4_er_hiln,
253     &_codec_audio_mpeg4_er_parametric,
254     &_codec_audio_mpeg4_ssc,
255     &_codec_audio_mpeg4_ps,
256     &_codec_audio_mpeg4_mpeg_surround,
257     NULL,
258     &_codec_audio_mpeg4_layer1,
259     &_codec_audio_mpeg4_layer2,
260     &_codec_audio_mpeg4_layer3,
261     &_codec_audio_mpeg4_dst,
262     &_codec_audio_mpeg4_audio_lossless,
263     &_codec_audio_mpeg4_sls,
264     &_codec_audio_mpeg4_sls_non_core
265 };
266
267 static const struct type_str _audio_types[] = {
268     {MP4_MPEG2_AAC_MAIN_AUDIO_TYPE, &_codec_audio_mpeg2aac_main},
269     {MP4_MPEG2_AAC_LC_AUDIO_TYPE, &_codec_audio_mpeg2aac_lc},
270     {MP4_MPEG2_AAC_SSR_AUDIO_TYPE, &_codec_audio_mpeg2aac_ssr},
271     {MP4_MPEG2_AUDIO_TYPE, &_codec_audio_mpeg2audio},
272     {MP4_MPEG1_AUDIO_TYPE, &_codec_audio_mpeg1audio},
273     {MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE, &_codec_audio_pcm16le},
274     {MP4_VORBIS_AUDIO_TYPE, &_codec_audio_vorbis},
275     {MP4_ALAW_AUDIO_TYPE, &_codec_audio_alaw},
276     {MP4_ULAW_AUDIO_TYPE, &_codec_audio_ulaw},
277     {MP4_G723_AUDIO_TYPE, &_codec_audio_g723},
278     {MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE, &_codec_audio_pcm16be},
279     {}
280 };
281
282 static const struct type_str _video_vprofiles[] = {
283     {MPEG4_SP_L1, &_codec_video_mpeg4_simple_l1},
284     {MPEG4_SP_L2, &_codec_video_mpeg4_simple_l2},
285     {MPEG4_SP_L3, &_codec_video_mpeg4_simple_l3},
286     {MPEG4_SP_L0, &_codec_video_mpeg4_simple_l0},
287     {MPEG4_SSP_L1, &_codec_video_mpeg4_simple_scalable_l1},
288     {MPEG4_SSP_L2, &_codec_video_mpeg4_simple_scalable_l2},
289     {MPEG4_CP_L1, &_codec_video_mpeg4_core_l1},
290     {MPEG4_CP_L2, &_codec_video_mpeg4_core_l2},
291     {MPEG4_MP_L2, &_codec_video_mpeg4_main_l2},
292     {MPEG4_MP_L3, &_codec_video_mpeg4_main_l3},
293     {MPEG4_MP_L4, &_codec_video_mpeg4_main_l4},
294     {MPEG4_NBP_L2, &_codec_video_mpeg4_nbit_l2},
295     {MPEG4_STP_L1, &_codec_video_mpeg4_scalable_texture_l1},
296     {MPEG4_SFAP_L1, &_codec_video_mpeg4_simple_face_anim_l1},
297     {MPEG4_SFAP_L2, &_codec_video_mpeg4_simple_face_anim_l2},
298     {MPEG4_SFBAP_L1, &_codec_video_mpeg4_simple_fba_l1},
299     {MPEG4_SFBAP_L2, &_codec_video_mpeg4_simple_fba_l2},
300     {MPEG4_BATP_L1, &_codec_video_mpeg4_basic_anim_text_l1},
301     {MPEG4_BATP_L2, &_codec_video_mpeg4_basic_anim_text_l2},
302     {MPEG4_HP_L1, &_codec_video_mpeg4_hybrid_l1},
303     {MPEG4_HP_L2, &_codec_video_mpeg4_hybrid_l2},
304     {MPEG4_ARTSP_L1, &_codec_video_mpeg4_adv_rt_simple_l1},
305     {MPEG4_ARTSP_L2, &_codec_video_mpeg4_adv_rt_simple_l2},
306     {MPEG4_ARTSP_L3, &_codec_video_mpeg4_adv_rt_simple_l3},
307     {MPEG4_ARTSP_L4, &_codec_video_mpeg4_adv_rt_simple_l4},
308     {MPEG4_CSP_L1, &_codec_video_mpeg4_core_scalable_l1},
309     {MPEG4_CSP_L2, &_codec_video_mpeg4_core_scalable_l2},
310     {MPEG4_CSP_L3, &_codec_video_mpeg4_core_scalable_l3},
311     {MPEG4_ACEP_L1, &_codec_video_mpeg4_adv_coding_efficiency_l1},
312     {MPEG4_ACEP_L2, &_codec_video_mpeg4_adv_coding_efficiency_l2},
313     {MPEG4_ACEP_L3, &_codec_video_mpeg4_adv_coding_efficiency_l3},
314     {MPEG4_ACEP_L4, &_codec_video_mpeg4_adv_coding_efficiency_l4},
315     {MPEG4_ACP_L1, &_codec_video_mpeg4_adv_core_l1},
316     {MPEG4_ACP_L2, &_codec_video_mpeg4_adv_core_l2},
317     {MPEG4_AST_L1, &_codec_video_mpeg4_adv_scalable_texture_l1},
318     {MPEG4_AST_L2, &_codec_video_mpeg4_adv_scalable_texture_l2},
319     {MPEG4_AST_L3, &_codec_video_mpeg4_adv_scalable_texture_l3},
320     {MPEG4_S_STUDIO_P_L1, &_codec_video_mpeg4_simple_studio_l1},
321     {MPEG4_S_STUDIO_P_L2, &_codec_video_mpeg4_simple_studio_l2},
322     {MPEG4_S_STUDIO_P_L3, &_codec_video_mpeg4_simple_studio_l3},
323     {MPEG4_S_STUDIO_P_L4, &_codec_video_mpeg4_simple_studio_l4},
324     {MPEG4_C_STUDIO_P_L1, &_codec_video_mpeg4_core_studio_l1},
325     {MPEG4_C_STUDIO_P_L2, &_codec_video_mpeg4_core_studio_l2},
326     {MPEG4_C_STUDIO_P_L3, &_codec_video_mpeg4_core_studio_l3},
327     {MPEG4_C_STUDIO_P_L4, &_codec_video_mpeg4_core_studio_l4},
328     {MPEG4_ASP_L0, &_codec_video_mpeg4_adv_simple_l0},
329     {MPEG4_ASP_L1, &_codec_video_mpeg4_adv_simple_l1},
330     {MPEG4_ASP_L2, &_codec_video_mpeg4_adv_simple_l2},
331     {MPEG4_ASP_L3, &_codec_video_mpeg4_adv_simple_l3},
332     {MPEG4_ASP_L4, &_codec_video_mpeg4_adv_simple_l4},
333     {MPEG4_ASP_L5, &_codec_video_mpeg4_adv_simple_l5},
334     {MPEG4_ASP_L3B, &_codec_video_mpeg4_adv_simple_l3b},
335     {MPEG4_FGSP_L0, &_codec_video_mpeg4_fgs_l0},
336     {MPEG4_FGSP_L1, &_codec_video_mpeg4_fgs_l1},
337     {MPEG4_FGSP_L2, &_codec_video_mpeg4_fgs_l2},
338     {MPEG4_FGSP_L3, &_codec_video_mpeg4_fgs_l3},
339     {MPEG4_FGSP_L4, &_codec_video_mpeg4_fgs_l4},
340     {MPEG4_FGSP_L5, &_codec_video_mpeg4_fgs_l5},
341     {}
342 };
343
344 static const struct type_str _video_types[] = {
345     {MP4_MPEG2_SIMPLE_VIDEO_TYPE, &_codec_video_mpeg2_simple},
346     {MP4_MPEG2_MAIN_VIDEO_TYPE, &_codec_video_mpeg2_main},
347     {MP4_MPEG2_SNR_VIDEO_TYPE, &_codec_video_mpeg2_snr},
348     {MP4_MPEG2_SPATIAL_VIDEO_TYPE, &_codec_video_mpeg2_spatial},
349     {MP4_MPEG2_HIGH_VIDEO_TYPE, &_codec_video_mpeg2_high},
350     {MP4_MPEG2_442_VIDEO_TYPE, &_codec_video_mpeg2_422},
351     {MP4_MPEG1_VIDEO_TYPE, &_codec_video_mpeg1},
352     {MP4_JPEG_VIDEO_TYPE, &_codec_video_jpeg},
353     {MP4_YUV12_VIDEO_TYPE, &_codec_video_yuv12},
354     {MP4_H263_VIDEO_TYPE, &_codec_video_h263},
355     {MP4_H261_VIDEO_TYPE, &_codec_video_h261},
356     {}
357 };
358
359
360 static const char _name[] = "mp4";
361 static const struct lms_string_size _exts[] = {
362     LMS_STATIC_STRING_SIZE(".mp4"),
363     LMS_STATIC_STRING_SIZE(".m4a"),
364     LMS_STATIC_STRING_SIZE(".m4v"),
365     LMS_STATIC_STRING_SIZE(".mov"),
366     LMS_STATIC_STRING_SIZE(".qt"),
367     LMS_STATIC_STRING_SIZE(".3gp")
368 };
369 static const char *_cats[] = {
370     "multimedia",
371     "audio",
372     "video",
373     NULL
374 };
375 static const char *_authors[] = {
376     "Andre Moreira Magalhaes",
377     "Lucas De Marchi",
378     "Gustavo Sverzut Barbieri",
379     "Leandro Dorileo",
380     NULL
381 };
382
383 static const struct lms_string_size nullstr = { };
384
385 static void *
386 _match(struct plugin *p, const char *path, int len, int base)
387 {
388     long i;
389
390     i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts));
391     if (i < 0)
392       return NULL;
393     else
394       return (void*)(i + 1);
395 }
396
397 static inline struct lms_string_size
398 _find_type_str(const struct type_str *base, uint8_t type)
399 {
400     const struct type_str *itr;
401
402     for (itr = base; itr->str != NULL; itr++) {
403         if (itr->type == type)
404             return *itr->str;
405     }
406
407     return nullstr;
408 }
409
410 static struct lms_string_size
411 _get_audio_codec(MP4FileHandle mp4_fh, MP4TrackId id)
412 {
413     const char *data_name = MP4GetTrackMediaDataName(mp4_fh, id);
414     uint8_t type;
415
416     if (!data_name)
417         return nullstr;
418     if (strcasecmp(data_name, "samr") == 0)
419         return _codec_audio_amr;
420     if (strcasecmp(data_name, "sawb") == 0)
421         return _codec_audio_amr_wb;
422     if (strcasecmp(data_name, "mp4a") != 0)
423         return nullstr;
424
425     type = MP4GetTrackEsdsObjectTypeId(mp4_fh, id);
426     if (type == MP4_MPEG4_AUDIO_TYPE) {
427         type = MP4GetTrackAudioMpeg4Type(mp4_fh, id);
428         if (type == 0 || type > LMS_ARRAY_SIZE(_audio_codecs) ||
429             _audio_codecs[type - 1] == NULL)
430             return nullstr;
431
432         return *_audio_codecs[type - 1];
433     }
434
435     return _find_type_str(_audio_types, type);
436 }
437
438 /* WARNING: returned str is malloc()'ed if not NULL, use free() */
439 static struct lms_string_size
440 _get_video_codec(MP4FileHandle mp4_fh, MP4TrackId id)
441 {
442     const char *data_name = MP4GetTrackMediaDataName(mp4_fh, id);
443     struct lms_string_size ret = {}, tmp;
444     char buf[256];
445     char ofmt[8] = {};
446
447     if (!data_name)
448         return nullstr;
449
450     if (strcasecmp(data_name, "encv") == 0) {
451         if (!MP4GetTrackMediaDataOriginalFormat(mp4_fh, id, ofmt, sizeof(ofmt)))
452             return nullstr;
453     }
454
455     if (strcasecmp(data_name, "s263") == 0) {
456         ret = _codec_video_h263;
457         goto found;
458     }
459
460     if (strcasecmp(data_name, "avc1") == 0 ||
461         strcasecmp(ofmt, "264b") == 0) {
462         uint8_t profile, level;
463         char str_profile[64], str_level[64];
464
465         if (!MP4GetTrackH264ProfileLevel(mp4_fh, id, &profile, &level)) {
466             return nullstr;
467         }
468
469         switch (profile) {
470         case 66:
471             memcpy(str_profile, "baseline", sizeof("baseline"));
472             break;
473         case 77:
474             memcpy(str_profile, "main", sizeof("main"));
475             break;
476         case 88:
477             memcpy(str_profile, "extended", sizeof("extended"));
478             break;
479         case 100:
480             memcpy(str_profile, "high", sizeof("high"));
481             break;
482         case 110:
483             memcpy(str_profile, "high-10", sizeof("high-10"));
484             break;
485         case 122:
486             memcpy(str_profile, "high-422", sizeof("high-422"));
487             break;
488         case 144:
489             memcpy(str_profile, "high-444", sizeof("high-444"));
490             break;
491         default:
492             snprintf(str_profile, sizeof(str_profile), "unknown-%d", profile);
493         }
494
495         if (level % 10 == 0)
496             snprintf(str_level, sizeof(str_level), "%u", level / 10);
497         else
498             snprintf(str_level, sizeof(str_level), "%u.%u", level / 10,
499                      level % 10);
500
501         /* fix constrained and 1b case for baseline and main */
502         if (profile == 66 || profile == 77) {
503             uint8_t *sps;
504             uint32_t spslen;
505             bool constrained = false;
506             bool level1b = false;
507
508             if (MP4HaveAtom(mp4_fh,
509                             "moov.trak.mdia.minf.stbl.stsd.avc1.avcC") &&
510                 MP4GetBytesProperty(mp4_fh, "moov.trak.mdia.minf.stbl.stsd."
511                                     "avc1.avcC.sequenceEntries."
512                                     "sequenceParameterSetNALUnit",
513                                     &sps, &spslen)) {
514                 /* SPS (Sequence Parameter Set) is:
515                  *  8 bits (1 byte) for profile_idc
516                  *  1 bit for constraint_set0_flag
517                  *  1 bit for constraint_set1_flag <- we use this for constr.
518                  *  1 bit for constraint_set2_flag
519                  *  1 bit for constraint_set3_flag <- we use this for 1b
520                  * based on ffmpeg's (libavcodec/h264_ps.c) and
521                  * x264 (encoder/set.c)
522                  */
523                 if (spslen > 1) {
524                     if ((sps[1] >> 1) & 0x1)
525                         constrained = true;
526                     if (((sps[1] >> 3) & 0x1) && level / 10 == 1)
527                         level1b = true;
528                 }
529                 free(sps);
530
531                 if (constrained) {
532                     if (profile == 66)
533                         memcpy(str_profile, "constrained-baseline",
534                                sizeof("constrained-baseline"));
535                     else
536                         memcpy(str_profile, "constrained-main",
537                                sizeof("constrained-main"));
538                 }
539
540                 if (level1b)
541                     memcpy(str_level, "1b", sizeof("1b"));
542             }
543         }
544
545         ret.len = snprintf(buf, sizeof(buf), "h264-%s-l%s",
546                            str_profile, str_level);
547         ret.str = buf;
548         goto found;
549     } else if (strcasecmp(data_name, "mp4v") == 0 ||
550              strcasecmp(data_name, "encv") == 0) {
551         uint8_t type = MP4GetTrackEsdsObjectTypeId(mp4_fh, id);
552
553         if (type == MP4_MPEG4_VIDEO_TYPE) {
554             type = MP4GetVideoProfileLevel(mp4_fh, id);
555             ret = _find_type_str(_video_vprofiles, type);
556         } else
557             ret = _find_type_str(_video_types, type);
558         goto found;
559     }
560
561     return nullstr;
562
563 found: /* ugly, but h264 codec is composed in runtime */
564
565     if (!lms_string_size_dup(&tmp, &ret))
566         return nullstr;
567     return tmp;
568 }
569
570 static struct lms_string_size
571 _get_lang(MP4FileHandle mp4_fh, MP4TrackId id)
572 {
573     struct lms_string_size ret;
574     char buf[4];
575
576     if (!MP4GetTrackLanguage(mp4_fh, id, buf))
577         return nullstr;
578
579     if (memcmp(buf, "und", 4) == 0)
580         return nullstr;
581
582     if (!lms_string_size_strndup(&ret, buf, -1))
583         return nullstr;
584
585     return ret;
586 }
587
588 static struct lms_string_size
589 _get_container(MP4FileHandle mp4_fh)
590 {
591     const char *brand;
592
593     if (!MP4GetStringProperty(mp4_fh, "ftyp.majorBrand", &brand))
594         return _container_mp4;
595
596     if (strncasecmp(brand, "3gp", 3) == 0)
597         return _container_3gp;
598
599     /* NOTE: this should be an array, but the C wrapper of mp4v2
600      * doesn't expose a way to give the index number and
601      * ftyp.compatibleBrands is not in counted format (name[idx])
602      */
603     if (!MP4GetStringProperty(mp4_fh, "ftyp.compatibleBrands", &brand))
604         return _container_mp4;
605
606     if (strncasecmp(brand, "3gp", 3) == 0)
607         return _container_3gp;
608
609     return _container_mp4;
610 }
611
612 #define DLNA_VIDEO_RES(_width, _height)                                 \
613     &(struct dlna_video_res) {.width = _width, .height = _height}       \
614
615 #define DLNA_VIDEO_RES_RANGE(_wmin, _wmax, _hmin, _hmax)                \
616     &(struct dlna_video_res_range) {.width_min = _wmin,                 \
617             .width_max = _wmax, .height_min = _hmin,                    \
618             .height_max = _hmax}                                        \
619
620 #define DLNA_BITRATE(_min, _max)                            \
621     &(struct dlna_bitrate) {.min = _min, .max = _max}       \
622
623 #define DLNA_LEVEL(_val...)                                 \
624     &(struct dlna_level) {.levels = {_val, NULL}}           \
625
626 #define DLNA_VIDEO_FRAMERATE_RANGE(_min, _max)                          \
627     &(struct dlna_video_framerate_range) {.min = _min, .max = _max}     \
628
629 #define DLNA_AUDIO_RATE(_val...)                        \
630     &(struct dlna_audio_rate) {.rates = {_val}}         \
631
632 #define MAX_AUDIO_LEVELS 5
633 #define MAX_AUDIO_MPEG_VERSIONS 2
634 #define MAX_AUDIO_RATES 9
635 #define MAX_VIDEO_RULE_LEVEL 13
636
637 struct dlna_bitrate {
638      unsigned int min;
639      unsigned int max;
640 };
641
642 struct dlna_video_framerate_range {
643     double min;
644     double max;
645 };
646
647 struct dlna_video_res {
648     unsigned int width;
649     unsigned int height;
650 };
651
652 struct dlna_video_res_range {
653     unsigned int width_min;
654     unsigned int width_max;
655     unsigned int height_min;
656     unsigned int height_max;
657 };
658
659 struct dlna_level {
660     const char *levels[MAX_VIDEO_RULE_LEVEL];
661 };
662
663 struct dlna_video_rule {
664      struct dlna_video_res *res;
665      struct dlna_video_res_range *res_range;
666      struct dlna_bitrate *bitrate;
667      struct dlna_level *levels;
668      struct dlna_video_framerate_range *framerate_range;
669 };
670
671 struct dlna_audio_rate {
672      unsigned int rates[MAX_AUDIO_RATES];
673 };
674
675 struct dlna_audio_rule {
676      const struct lms_string_size *codec;
677      const struct lms_string_size *container;
678      struct dlna_audio_rate *rates;
679      struct dlna_level *levels;
680      struct dlna_bitrate *channels;
681      struct dlna_bitrate *bitrate;
682 };
683
684 struct dlna_video_profile {
685      const struct lms_string_size *dlna_profile;
686      const struct lms_string_size *dlna_mime;
687      const struct dlna_video_rule *video_rules;
688      const struct dlna_audio_rule *audio_rule;
689 };
690
691 struct dlna_audio_profile {
692      const struct lms_string_size *dlna_profile;
693      const struct lms_string_size *dlna_mime;
694      const struct dlna_audio_rule *audio_rule;
695 };
696
697 static const struct dlna_video_rule _dlna_video_rule_sp_l3[] = {
698     {
699         .res = DLNA_VIDEO_RES(352, 288),
700         .bitrate = DLNA_BITRATE(1, 64000),
701         .levels = DLNA_LEVEL("0", "1"),
702     },
703     {
704         .res = DLNA_VIDEO_RES(352, 240),
705         .bitrate = DLNA_BITRATE(1, 64000),
706         .levels = DLNA_LEVEL("0", "1"),
707     },
708     {
709         .res = DLNA_VIDEO_RES(320, 240),
710         .bitrate = DLNA_BITRATE(1, 64000),
711         .levels = DLNA_LEVEL("0", "1"),
712     },
713     {
714         .res = DLNA_VIDEO_RES(320, 180),
715         .bitrate = DLNA_BITRATE(1, 64000),
716         .levels = DLNA_LEVEL("0", "1")
717     },
718     {
719         .res = DLNA_VIDEO_RES(240, 180),
720         .bitrate = DLNA_BITRATE(1, 64000),
721         .levels = DLNA_LEVEL("0", "1"),
722     },
723     {
724         .res = DLNA_VIDEO_RES(208, 160),
725         .bitrate = DLNA_BITRATE(1, 64000),
726         .levels = DLNA_LEVEL("0", "1"),
727     },
728     {
729         .res = DLNA_VIDEO_RES(176, 144),
730         .bitrate = DLNA_BITRATE(1, 64000),
731         .levels = DLNA_LEVEL("0", "1"),
732     },
733     {
734         .res = DLNA_VIDEO_RES(176, 120),
735         .bitrate = DLNA_BITRATE(1, 64000),
736         .levels = DLNA_LEVEL("0", "1"),
737     },
738     {
739         .res = DLNA_VIDEO_RES(160, 120),
740         .bitrate = DLNA_BITRATE(1, 64000),
741         .levels = DLNA_LEVEL("0", "1"),
742     },
743     {
744         .res = DLNA_VIDEO_RES(160, 112),
745         .bitrate = DLNA_BITRATE(1, 64000),
746         .levels = DLNA_LEVEL("0", "1"),
747     },
748     {
749         .res = DLNA_VIDEO_RES(160, 90),
750         .bitrate = DLNA_BITRATE(1, 64000),
751         .levels = DLNA_LEVEL("0", "1"),
752     },
753     {
754         .res = DLNA_VIDEO_RES(128, 96),
755         .bitrate = DLNA_BITRATE(1, 64000),
756         .levels = DLNA_LEVEL("0", "1"),
757     },
758     {
759         .res = DLNA_VIDEO_RES(352, 288),
760         .bitrate = DLNA_BITRATE(1, 128000),
761         .levels = DLNA_LEVEL("0b", "2"),
762     },
763     {
764         .res = DLNA_VIDEO_RES(352, 240),
765         .bitrate = DLNA_BITRATE(1, 128000),
766         .levels = DLNA_LEVEL("0b", "2"),
767     },
768     {
769         .res = DLNA_VIDEO_RES(320, 240),
770         .bitrate = DLNA_BITRATE(1, 128000),
771         .levels = DLNA_LEVEL("0b", "2"),
772     },
773     {
774         .res = DLNA_VIDEO_RES(320, 180),
775         .bitrate = DLNA_BITRATE(1, 128000),
776         .levels = DLNA_LEVEL("0b", "2"),
777     },
778     {
779         .res = DLNA_VIDEO_RES(240, 180),
780         .bitrate = DLNA_BITRATE(1, 128000),
781         .levels = DLNA_LEVEL("0b", "2"),
782     },
783     {
784         .res = DLNA_VIDEO_RES(208, 160),
785         .bitrate = DLNA_BITRATE(1, 128000),
786         .levels = DLNA_LEVEL("0b", "2"),
787     },
788     {
789         .res = DLNA_VIDEO_RES(176, 144),
790         .bitrate = DLNA_BITRATE(1, 128000),
791         .levels = DLNA_LEVEL("0b", "2"),
792     },
793     {
794         .res = DLNA_VIDEO_RES(176, 120),
795         .bitrate = DLNA_BITRATE(1, 128000),
796         .levels = DLNA_LEVEL("0b", "2"),
797     },
798     {
799         .res = DLNA_VIDEO_RES(160, 120),
800         .bitrate = DLNA_BITRATE(1, 128000),
801         .levels = DLNA_LEVEL("0b", "2"),
802     },
803     {
804         .res = DLNA_VIDEO_RES(160, 112),
805         .bitrate = DLNA_BITRATE(1, 128000),
806         .levels = DLNA_LEVEL("0b", "2"),
807     },
808     {
809         .res = DLNA_VIDEO_RES(160, 90),
810         .bitrate = DLNA_BITRATE(1, 128000),
811         .levels = DLNA_LEVEL("0b", "2"),
812     },
813     {
814         .res = DLNA_VIDEO_RES(128, 96),
815         .bitrate = DLNA_BITRATE(1, 128000),
816         .levels = DLNA_LEVEL("0b", "2"),
817     },
818     {
819         .res = DLNA_VIDEO_RES(352, 288),
820         .bitrate = DLNA_BITRATE(1, 384000),
821         .levels = DLNA_LEVEL("3"),
822     },
823     {
824         .res = DLNA_VIDEO_RES(352, 240),
825         .bitrate = DLNA_BITRATE(1, 384000),
826         .levels = DLNA_LEVEL("3"),
827     },
828     {
829         .res = DLNA_VIDEO_RES(320, 240),
830         .bitrate = DLNA_BITRATE(1, 384000),
831         .levels = DLNA_LEVEL("3"),
832     },
833     {
834         .res = DLNA_VIDEO_RES(320, 180),
835         .bitrate = DLNA_BITRATE(1, 384000),
836         .levels = DLNA_LEVEL("3"),
837     },
838     {
839         .res = DLNA_VIDEO_RES(240, 180),
840         .bitrate = DLNA_BITRATE(1, 384000),
841         .levels = DLNA_LEVEL("3"),
842     },
843     {
844         .res = DLNA_VIDEO_RES(208, 160),
845         .bitrate = DLNA_BITRATE(1, 384000),
846         .levels = DLNA_LEVEL("3"),
847     },
848     {
849         .res = DLNA_VIDEO_RES(176, 155),
850         .bitrate = DLNA_BITRATE(1, 384000),
851         .levels = DLNA_LEVEL("3"),
852     },
853     {
854         .res = DLNA_VIDEO_RES(176, 120),
855         .bitrate = DLNA_BITRATE(1, 384000),
856         .levels = DLNA_LEVEL("3"),
857     },
858     {
859         .res = DLNA_VIDEO_RES(160, 120),
860         .bitrate = DLNA_BITRATE(1, 384000),
861         .levels = DLNA_LEVEL("3"),
862     },
863     {
864         .res = DLNA_VIDEO_RES(160, 112),
865         .bitrate = DLNA_BITRATE(1, 384000),
866         .levels = DLNA_LEVEL("3"),
867     },
868     {
869         .res = DLNA_VIDEO_RES(160, 90),
870         .bitrate = DLNA_BITRATE(1, 384000),
871         .levels = DLNA_LEVEL("3"),
872     },
873     {
874         .res = DLNA_VIDEO_RES(128, 96),
875         .bitrate = DLNA_BITRATE(1, 384000),
876         .levels = DLNA_LEVEL("3"),
877     },
878     { NULL },
879 };
880
881 #define DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD                         \
882     "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3"      \
883
884 static const struct dlna_video_rule _dlna_video_rule_avc_mp4_mp_sd[] = {
885     {
886         .res = DLNA_VIDEO_RES(720, 576),
887         .bitrate = DLNA_BITRATE(1, 10000000),
888         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
889     },
890     {
891         .res = DLNA_VIDEO_RES(720, 480),
892         .bitrate = DLNA_BITRATE(1, 10000000),
893         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
894     },
895     {
896         .res = DLNA_VIDEO_RES(704, 576),
897         .bitrate = DLNA_BITRATE(1, 10000000),
898         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
899     },
900     {
901         .res = DLNA_VIDEO_RES(704, 480),
902         .bitrate = DLNA_BITRATE(1, 10000000),
903         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
904     },
905     {
906         .res = DLNA_VIDEO_RES(704, 480),
907         .bitrate = DLNA_BITRATE(1, 10000000),
908         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
909     },
910     {
911         .res = DLNA_VIDEO_RES(640, 480),
912         .bitrate = DLNA_BITRATE(1, 10000000),
913         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
914     },
915     {
916         .res = DLNA_VIDEO_RES(640, 360),
917         .bitrate = DLNA_BITRATE(1, 10000000),
918         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
919     },
920     {
921         .res = DLNA_VIDEO_RES(544, 576),
922         .bitrate = DLNA_BITRATE(1, 10000000),
923         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
924     },
925     {
926         .res = DLNA_VIDEO_RES(544, 480),
927         .bitrate = DLNA_BITRATE(1, 10000000),
928         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
929     },
930     {
931         .res = DLNA_VIDEO_RES(480, 576),
932         .bitrate = DLNA_BITRATE(1, 10000000),
933         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
934     },
935     {
936         .res = DLNA_VIDEO_RES(480, 480),
937         .bitrate = DLNA_BITRATE(1, 10000000),
938         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
939     },
940     {
941         .res = DLNA_VIDEO_RES(480, 360),
942         .bitrate = DLNA_BITRATE(1, 10000000),
943         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
944     },
945     {
946         .res = DLNA_VIDEO_RES(480, 270),
947         .bitrate = DLNA_BITRATE(1, 10000000),
948         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
949     },
950     {
951         .res = DLNA_VIDEO_RES(352, 576),
952         .bitrate = DLNA_BITRATE(1, 10000000),
953         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
954     },
955     {
956         .res = DLNA_VIDEO_RES(352, 480),
957         .bitrate = DLNA_BITRATE(1, 10000000),
958         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
959     },
960     {
961         .res = DLNA_VIDEO_RES(352, 288),
962         .bitrate = DLNA_BITRATE(1, 10000000),
963         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
964     },
965     {
966         .res = DLNA_VIDEO_RES(352, 240),
967         .bitrate = DLNA_BITRATE(1, 10000000),
968         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
969     },
970     {
971         .res = DLNA_VIDEO_RES(320, 240),
972         .bitrate = DLNA_BITRATE(1, 10000000),
973         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
974     },
975     {
976         .res = DLNA_VIDEO_RES(320, 180),
977         .bitrate = DLNA_BITRATE(1, 10000000),
978         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
979     },
980     {
981         .res = DLNA_VIDEO_RES(240, 180),
982         .bitrate = DLNA_BITRATE(1, 10000000),
983         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
984     },
985     {
986         .res = DLNA_VIDEO_RES(208, 160),
987         .bitrate = DLNA_BITRATE(1, 10000000),
988         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
989     },
990     {
991         .res = DLNA_VIDEO_RES(176, 144),
992         .bitrate = DLNA_BITRATE(1, 10000000),
993         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
994     },
995     {
996         .res = DLNA_VIDEO_RES(176, 120),
997         .bitrate = DLNA_BITRATE(1, 10000000),
998         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
999     },
1000     {
1001         .res = DLNA_VIDEO_RES(150, 120),
1002         .bitrate = DLNA_BITRATE(1, 10000000),
1003         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
1004     },
1005     {
1006         .res = DLNA_VIDEO_RES(160, 112),
1007         .bitrate = DLNA_BITRATE(1, 10000000),
1008         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
1009     },
1010     {
1011         .res = DLNA_VIDEO_RES(160, 90),
1012         .bitrate = DLNA_BITRATE(1, 10000000),
1013         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
1014     },
1015     {
1016         .res = DLNA_VIDEO_RES(128, 96),
1017         .bitrate = DLNA_BITRATE(1, 10000000),
1018         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MP4_MP_SD),
1019     },
1020     { NULL },
1021 };
1022
1023 #define DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_VGA_AAC \
1024     "0", "0b", "1", "2", "3"                      \
1025
1026 static const struct dlna_video_rule _dlna_video_mpeg4_p2_mp4_sp_vga_aac[] = {
1027     {
1028         .res = DLNA_VIDEO_RES(640, 480),
1029         .bitrate = DLNA_BITRATE(1, 3000000),
1030         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_VGA_AAC),
1031         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(-1, -1),
1032     },
1033     {
1034         .res = DLNA_VIDEO_RES(640, 360),
1035         .bitrate = DLNA_BITRATE(1, 3000000),
1036         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_VGA_AAC),
1037     },
1038     { NULL },
1039 };
1040
1041 #define DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC        \
1042     "0", "0b", "1", "2"                                 \
1043
1044 static const struct dlna_video_rule _dlna_video_mpeg4_p2_mp4_sp_l2_aac[] = {
1045     {
1046         .res = DLNA_VIDEO_RES(352, 288),
1047         .bitrate = DLNA_BITRATE(1, 128000),
1048         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
1049         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 15/1),
1050     },
1051     {
1052         .res = DLNA_VIDEO_RES(320, 240),
1053         .bitrate = DLNA_BITRATE(1, 128000),
1054         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
1055         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 15/1),
1056     },
1057     {
1058         .res = DLNA_VIDEO_RES(320, 180),
1059         .bitrate = DLNA_BITRATE(1, 128000),
1060         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
1061         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 15/1),
1062     },
1063     {
1064         .res = DLNA_VIDEO_RES(176, 144),
1065         .bitrate = DLNA_BITRATE(1, 128000),
1066         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
1067         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
1068     },
1069     {
1070         .res = DLNA_VIDEO_RES(128, 96),
1071         .bitrate = DLNA_BITRATE(1, 128000),
1072         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MPEG4_P2_MP4_SP_L2_ACC),
1073         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
1074     },
1075     { NULL },
1076 };
1077
1078 #define DLNA_VIDEO_RULE_SP_L5                           \
1079     {                                                   \
1080         .res = DLNA_VIDEO_RES(640, 480),                \
1081         .bitrate = DLNA_BITRATE(1, 64000),              \
1082         .levels = DLNA_LEVEL("0", "1"),                 \
1083     },                                                  \
1084     {                                                   \
1085         .res = DLNA_VIDEO_RES(640, 360),                \
1086         .bitrate = DLNA_BITRATE(1, 64000),              \
1087         .levels = DLNA_LEVEL("0", "1"),                 \
1088     },                                                  \
1089     {                                                   \
1090         .res = DLNA_VIDEO_RES(720, 576),                \
1091         .bitrate = DLNA_BITRATE(1, 64000),              \
1092         .levels = DLNA_LEVEL("0", "1"),                 \
1093     },                                                  \
1094     {                                                   \
1095         .res = DLNA_VIDEO_RES(720, 480),                \
1096         .bitrate = DLNA_BITRATE(1, 64000),              \
1097         .levels = DLNA_LEVEL("0", "1"),                 \
1098     },                                                  \
1099     {                                                   \
1100         .res = DLNA_VIDEO_RES(352, 288),                \
1101         .bitrate = DLNA_BITRATE(1, 64000),              \
1102         .levels = DLNA_LEVEL("0", "1"),                 \
1103     },                                                  \
1104     {                                                   \
1105         .res = DLNA_VIDEO_RES(352, 240),                \
1106         .bitrate = DLNA_BITRATE(1, 64000),              \
1107         .levels = DLNA_LEVEL("0", "1"),                 \
1108     },                                                  \
1109     {                                                   \
1110         .res = DLNA_VIDEO_RES(320, 240),                \
1111         .bitrate = DLNA_BITRATE(1, 64000),              \
1112         .levels = DLNA_LEVEL("0", "1"),                 \
1113     },                                                  \
1114     {                                                   \
1115         .res = DLNA_VIDEO_RES(320, 180),                \
1116         .bitrate = DLNA_BITRATE(1, 64000),              \
1117         .levels = DLNA_LEVEL("0", "1"),                 \
1118     },                                                  \
1119     {                                                   \
1120         .res = DLNA_VIDEO_RES(240, 180),                \
1121         .bitrate = DLNA_BITRATE(1, 64000),              \
1122         .levels = DLNA_LEVEL("0", "1"),                 \
1123     },                                                  \
1124     {                                                   \
1125         .res = DLNA_VIDEO_RES(208, 160),                \
1126         .bitrate = DLNA_BITRATE(1, 64000),              \
1127         .levels = DLNA_LEVEL("0", "1"),                 \
1128     },                                                  \
1129     {                                                   \
1130         .res = DLNA_VIDEO_RES(176, 144),                \
1131         .bitrate = DLNA_BITRATE(1, 64000),              \
1132         .levels = DLNA_LEVEL("0", "1"),                 \
1133     },                                                  \
1134     {                                                   \
1135         .res = DLNA_VIDEO_RES(176, 120),                \
1136         .bitrate = DLNA_BITRATE(1, 64000),              \
1137         .levels = DLNA_LEVEL("0", "1"),                 \
1138     },                                                  \
1139     {                                                   \
1140         .res = DLNA_VIDEO_RES(160, 120),                \
1141         .bitrate = DLNA_BITRATE(1, 64000),              \
1142         .levels = DLNA_LEVEL("0", "1"),                 \
1143     },                                                  \
1144     {                                                   \
1145         .res = DLNA_VIDEO_RES(160, 112),                \
1146         .bitrate = DLNA_BITRATE(1, 64000),              \
1147         .levels = DLNA_LEVEL("0", "1"),                 \
1148     },                                                  \
1149     {                                                   \
1150         .res = DLNA_VIDEO_RES(160, 90),                 \
1151         .bitrate = DLNA_BITRATE(1, 64000),              \
1152         .levels = DLNA_LEVEL("0", "1"),                 \
1153     },                                                  \
1154     {                                                   \
1155         .res = DLNA_VIDEO_RES(640, 480),                \
1156         .bitrate = DLNA_BITRATE(1, 128000),             \
1157         .levels = DLNA_LEVEL("0b", "2"),                \
1158     },                                                  \
1159     {                                                   \
1160         .res = DLNA_VIDEO_RES(640, 360),                \
1161         .bitrate = DLNA_BITRATE(1, 128000),             \
1162         .levels = DLNA_LEVEL("0b", "2"),                \
1163     },                                                  \
1164     {                                                   \
1165         .res = DLNA_VIDEO_RES(720, 576),                \
1166         .bitrate = DLNA_BITRATE(1, 128000),             \
1167         .levels = DLNA_LEVEL("0b", "2"),                \
1168     },                                                  \
1169     {                                                   \
1170         .res = DLNA_VIDEO_RES(720, 480),                \
1171         .bitrate = DLNA_BITRATE(1, 128000),             \
1172         .levels = DLNA_LEVEL("0b", "2"),                \
1173     },                                                  \
1174     {                                                   \
1175         .res = DLNA_VIDEO_RES(352, 288),                \
1176         .bitrate = DLNA_BITRATE(1, 128000),             \
1177         .levels = DLNA_LEVEL("0b", "2"),                \
1178     },                                                  \
1179     {                                                   \
1180         .res = DLNA_VIDEO_RES(352, 240),                \
1181         .bitrate = DLNA_BITRATE(1, 128000),             \
1182         .levels = DLNA_LEVEL("0b", "2"),                \
1183     },                                                  \
1184     {                                                   \
1185         .res = DLNA_VIDEO_RES(320, 240),                \
1186         .bitrate = DLNA_BITRATE(1, 128000),             \
1187         .levels = DLNA_LEVEL("0b", "2"),                \
1188     },                                                  \
1189     {                                                   \
1190         .res = DLNA_VIDEO_RES(320, 180),                \
1191         .bitrate = DLNA_BITRATE(1, 128000),             \
1192         .levels = DLNA_LEVEL("0b", "2"),                \
1193     },                                                  \
1194     {                                                   \
1195         .res = DLNA_VIDEO_RES(240, 180),                \
1196         .bitrate = DLNA_BITRATE(1, 128000),             \
1197         .levels = DLNA_LEVEL("0b", "2"),                \
1198     },                                                  \
1199     {                                                   \
1200         .res = DLNA_VIDEO_RES(208, 160),                \
1201         .bitrate = DLNA_BITRATE(1, 128000),             \
1202         .levels = DLNA_LEVEL("0b", "2"),                \
1203     },                                                  \
1204     {                                                   \
1205         .res = DLNA_VIDEO_RES(176, 144),                \
1206         .bitrate = DLNA_BITRATE(1, 128000),             \
1207         .levels = DLNA_LEVEL("0b", "2"),                \
1208     },                                                  \
1209     {                                                   \
1210         .res = DLNA_VIDEO_RES(176, 120),                \
1211         .bitrate = DLNA_BITRATE(1, 128000),             \
1212         .levels = DLNA_LEVEL("0b", "2"),                \
1213     },                                                  \
1214     {                                                   \
1215         .res = DLNA_VIDEO_RES(160, 120),                \
1216         .bitrate = DLNA_BITRATE(1, 128000),             \
1217         .levels = DLNA_LEVEL("0b", "2"),                \
1218     },                                                  \
1219     {                                                   \
1220         .res = DLNA_VIDEO_RES(160, 112),                \
1221         .bitrate = DLNA_BITRATE(1, 128000),             \
1222         .levels = DLNA_LEVEL("0b", "2"),                \
1223     },                                                  \
1224     {                                                   \
1225         .res = DLNA_VIDEO_RES(160, 90),                 \
1226         .bitrate = DLNA_BITRATE(1, 128000),             \
1227         .levels = DLNA_LEVEL("0b", "2"),                \
1228     },                                                  \
1229     {                                                   \
1230         .res = DLNA_VIDEO_RES(640, 480),                \
1231         .bitrate = DLNA_BITRATE(1, 384000),             \
1232         .levels = DLNA_LEVEL("3"),                      \
1233     },                                                  \
1234     {                                                   \
1235         .res = DLNA_VIDEO_RES(640, 360),                \
1236         .bitrate = DLNA_BITRATE(1, 384000),             \
1237         .levels = DLNA_LEVEL("3"),                      \
1238     },                                                  \
1239     {                                                   \
1240         .res = DLNA_VIDEO_RES(720, 576),                \
1241         .bitrate = DLNA_BITRATE(1, 384000),             \
1242         .levels = DLNA_LEVEL("3"),                      \
1243     },                                                  \
1244     {                                                   \
1245         .res = DLNA_VIDEO_RES(720, 480),                \
1246         .bitrate = DLNA_BITRATE(1, 384000),             \
1247         .levels = DLNA_LEVEL("3"),                      \
1248     },                                                  \
1249     {                                                   \
1250         .res = DLNA_VIDEO_RES(352, 288),                \
1251         .bitrate = DLNA_BITRATE(1, 384000),             \
1252         .levels = DLNA_LEVEL("3"),                      \
1253     },                                                  \
1254     {                                                   \
1255         .res = DLNA_VIDEO_RES(352, 240),                \
1256         .bitrate = DLNA_BITRATE(1, 384000),             \
1257         .levels = DLNA_LEVEL("3"),                      \
1258     },                                                  \
1259     {                                                   \
1260         .res = DLNA_VIDEO_RES(320, 240),                \
1261         .bitrate = DLNA_BITRATE(1, 384000),             \
1262         .levels = DLNA_LEVEL("3"),                      \
1263     },                                                  \
1264     {                                                   \
1265         .res = DLNA_VIDEO_RES(320, 180),                \
1266         .bitrate = DLNA_BITRATE(1, 384000),             \
1267         .levels = DLNA_LEVEL("3"),                      \
1268     },                                                  \
1269     {                                                   \
1270         .res = DLNA_VIDEO_RES(240, 180),                \
1271         .bitrate = DLNA_BITRATE(1, 384000),             \
1272         .levels = DLNA_LEVEL("3")                       \
1273     },                                                  \
1274     {                                                   \
1275         .res = DLNA_VIDEO_RES(208, 160),                \
1276         .bitrate = DLNA_BITRATE(1, 384000),             \
1277         .levels = DLNA_LEVEL("3"),                      \
1278     },                                                  \
1279     {                                                   \
1280         .res = DLNA_VIDEO_RES(176, 144),                \
1281         .bitrate = DLNA_BITRATE(1, 384000),             \
1282         .levels = DLNA_LEVEL("3"),                      \
1283     },                                                  \
1284     {                                                   \
1285         .res = DLNA_VIDEO_RES(176, 120),                \
1286         .bitrate = DLNA_BITRATE(1, 384000),             \
1287         .levels = DLNA_LEVEL("3"),                      \
1288     },                                                  \
1289     {                                                   \
1290         .res = DLNA_VIDEO_RES(160, 120),                \
1291         .bitrate = DLNA_BITRATE(1, 384000),             \
1292         .levels = DLNA_LEVEL("3"),                      \
1293     },                                                  \
1294     {                                                   \
1295         .res = DLNA_VIDEO_RES(160, 112),                \
1296         .bitrate = DLNA_BITRATE(1, 384000),             \
1297         .levels = DLNA_LEVEL("3"),                      \
1298     },                                                  \
1299     {                                                   \
1300         .res = DLNA_VIDEO_RES(160, 90),                 \
1301         .bitrate = DLNA_BITRATE(1, 384000),             \
1302         .levels = DLNA_LEVEL("3"),                      \
1303     },                                                  \
1304     {                                                   \
1305         .res = DLNA_VIDEO_RES(640, 480),                \
1306         .bitrate = DLNA_BITRATE(1, 8000000),            \
1307         .levels = DLNA_LEVEL("5"),                      \
1308     },                                                  \
1309     {                                                   \
1310         .res = DLNA_VIDEO_RES(640, 360),                \
1311         .bitrate = DLNA_BITRATE(1, 8000000),            \
1312         .levels = DLNA_LEVEL("5")                       \
1313     },                                                  \
1314     {                                                   \
1315         .res = DLNA_VIDEO_RES(720, 576),                \
1316         .bitrate = DLNA_BITRATE(1, 8000000),            \
1317         .levels = DLNA_LEVEL("5")                       \
1318     },                                                  \
1319     {                                                   \
1320         .res = DLNA_VIDEO_RES(720, 480),                \
1321         .bitrate = DLNA_BITRATE(1, 8000000),            \
1322         .levels = DLNA_LEVEL("5")                       \
1323     },                                                  \
1324     {                                                   \
1325         .res = DLNA_VIDEO_RES(352, 288),                \
1326         .bitrate = DLNA_BITRATE(1, 8000000),            \
1327         .levels = DLNA_LEVEL("5")                       \
1328     },                                                  \
1329     {                                                   \
1330         .res = DLNA_VIDEO_RES(352, 240),                \
1331         .bitrate = DLNA_BITRATE(1, 8000000),            \
1332         .levels = DLNA_LEVEL("5")                       \
1333     },                                                  \
1334     {                                                   \
1335         .res = DLNA_VIDEO_RES(320, 240),                \
1336         .bitrate = DLNA_BITRATE(1, 8000000),            \
1337         .levels = DLNA_LEVEL("5")                       \
1338     },                                                  \
1339     {                                                   \
1340         .res = DLNA_VIDEO_RES(320, 180),                \
1341         .bitrate = DLNA_BITRATE(1, 8000000),            \
1342         .levels = DLNA_LEVEL("5")                       \
1343     },                                                  \
1344     {                                                   \
1345         .res = DLNA_VIDEO_RES(240, 180),                \
1346         .bitrate = DLNA_BITRATE(1, 8000000),            \
1347         .levels = DLNA_LEVEL("5")                       \
1348     },                                                  \
1349     {                                                   \
1350         .res = DLNA_VIDEO_RES(208, 160),                \
1351         .bitrate = DLNA_BITRATE(1, 8000000),            \
1352         .levels = DLNA_LEVEL("5")                       \
1353     },                                                  \
1354     {                                                   \
1355         .res = DLNA_VIDEO_RES(176, 144),                \
1356         .bitrate = DLNA_BITRATE(1, 8000000),            \
1357         .levels = DLNA_LEVEL("5")                       \
1358     },                                                  \
1359     {                                                   \
1360         .res = DLNA_VIDEO_RES(176, 120),                \
1361         .bitrate = DLNA_BITRATE(1, 8000000),            \
1362         .levels = DLNA_LEVEL("5")                       \
1363     },                                                  \
1364     {                                                   \
1365         .res = DLNA_VIDEO_RES(160, 120),                \
1366         .bitrate = DLNA_BITRATE(1, 8000000),            \
1367         .levels = DLNA_LEVEL("5")                       \
1368     },                                                  \
1369     {                                                   \
1370         .res = DLNA_VIDEO_RES(160, 112),                \
1371         .bitrate = DLNA_BITRATE(1, 8000000),            \
1372         .levels = DLNA_LEVEL("5")                       \
1373     },                                                  \
1374     {                                                   \
1375         .res = DLNA_VIDEO_RES(160, 90),                 \
1376         .bitrate = DLNA_BITRATE(1, 8000000),            \
1377         .levels = DLNA_LEVEL("5")                       \
1378     }                                                   \
1379
1380 static const struct dlna_video_rule _dlna_video_rule_sp_l5[] = {
1381     DLNA_VIDEO_RULE_SP_L5,
1382     { NULL },
1383 };
1384
1385 static const struct dlna_video_rule _dlna_video_rule_sp_l6[] = {
1386     DLNA_VIDEO_RULE_SP_L5,
1387     {
1388         .res = DLNA_VIDEO_RES(1280, 720),
1389         .bitrate = DLNA_BITRATE(1, 64000),
1390         .levels = DLNA_LEVEL("0", "1"),
1391     },
1392     {
1393         .res = DLNA_VIDEO_RES(1280, 720),
1394         .bitrate = DLNA_BITRATE(1, 128000),
1395         .levels = DLNA_LEVEL("0b", "2"),
1396     },
1397     {
1398         .res = DLNA_VIDEO_RES(1280, 720),
1399         .bitrate = DLNA_BITRATE(1, 384000),
1400         .levels = DLNA_LEVEL("3"),
1401     },
1402     {
1403         .res = DLNA_VIDEO_RES(640, 480),
1404         .bitrate = DLNA_BITRATE(1, 4000000),
1405         .levels = DLNA_LEVEL("4a"),
1406     },
1407     {
1408         .res = DLNA_VIDEO_RES(720, 576),
1409         .bitrate = DLNA_BITRATE(1, 4000000),
1410         .levels = DLNA_LEVEL("4a"),
1411     },
1412     {
1413         .res = DLNA_VIDEO_RES(720, 480),
1414         .bitrate = DLNA_BITRATE(1, 4000000),
1415         .levels = DLNA_LEVEL("4a"),
1416     },
1417     {
1418         .res = DLNA_VIDEO_RES(352, 288),
1419         .bitrate = DLNA_BITRATE(1, 4000000),
1420         .levels = DLNA_LEVEL("4a"),
1421     },
1422     {
1423         .res = DLNA_VIDEO_RES(352, 240),
1424         .bitrate = DLNA_BITRATE(1, 4000000),
1425         .levels = DLNA_LEVEL("4a"),
1426     },
1427     {
1428         .res = DLNA_VIDEO_RES(320, 240),
1429         .bitrate = DLNA_BITRATE(1, 4000000),
1430         .levels = DLNA_LEVEL("4a"),
1431     },
1432     {
1433         .res = DLNA_VIDEO_RES(320, 180),
1434         .bitrate = DLNA_BITRATE(1, 4000000),
1435         .levels = DLNA_LEVEL("4a"),
1436     },
1437     {
1438         .res = DLNA_VIDEO_RES(240, 180),
1439         .bitrate = DLNA_BITRATE(1, 4000000),
1440         .levels = DLNA_LEVEL("4a"),
1441     },
1442     {
1443         .res = DLNA_VIDEO_RES(208, 160),
1444         .bitrate = DLNA_BITRATE(1, 4000000),
1445         .levels = DLNA_LEVEL("4a"),
1446     },
1447     {
1448         .res = DLNA_VIDEO_RES(176, 144),
1449         .bitrate = DLNA_BITRATE(1, 4000000),
1450         .levels = DLNA_LEVEL("4a"),
1451     },
1452     {
1453         .res = DLNA_VIDEO_RES(176, 120),
1454         .bitrate = DLNA_BITRATE(1, 4000000),
1455         .levels = DLNA_LEVEL("4a"),
1456     },
1457     {
1458         .res = DLNA_VIDEO_RES(160, 120),
1459         .bitrate = DLNA_BITRATE(1, 4000000),
1460         .levels = DLNA_LEVEL("4a"),
1461     },
1462     {
1463         .res = DLNA_VIDEO_RES(160, 112),
1464         .bitrate = DLNA_BITRATE(1, 4000000),
1465         .levels = DLNA_LEVEL("4a"),
1466     },
1467     {
1468         .res = DLNA_VIDEO_RES(160, 90),
1469         .bitrate = DLNA_BITRATE(1, 4000000),
1470         .levels = DLNA_LEVEL("4a"),
1471     },
1472     {
1473         .res = DLNA_VIDEO_RES(1280, 720),
1474         .bitrate = DLNA_BITRATE(1, 4000000),
1475         .levels = DLNA_LEVEL("4a"),
1476     },
1477     {
1478         .res = DLNA_VIDEO_RES(1280, 720),
1479         .bitrate = DLNA_BITRATE(1, 8000000),
1480         .levels = DLNA_LEVEL("5"),
1481     },
1482     {
1483         .res = DLNA_VIDEO_RES(640, 480),
1484         .bitrate = DLNA_BITRATE(1, 12000000),
1485         .levels = DLNA_LEVEL("6"),
1486     },
1487     {
1488         .res = DLNA_VIDEO_RES(640, 360),
1489         .bitrate = DLNA_BITRATE(1, 12000000),
1490         .levels = DLNA_LEVEL("6"),
1491     },
1492     {
1493         .res = DLNA_VIDEO_RES(720, 576),
1494         .bitrate = DLNA_BITRATE(1, 12000000),
1495         .levels = DLNA_LEVEL("6"),
1496     },
1497     {
1498         .res = DLNA_VIDEO_RES(720, 480),
1499         .bitrate = DLNA_BITRATE(1, 12000000),
1500         .levels = DLNA_LEVEL("6"),
1501     },
1502     {
1503         .res = DLNA_VIDEO_RES(352, 288),
1504         .bitrate = DLNA_BITRATE(1, 12000000),
1505         .levels = DLNA_LEVEL("6"),
1506     },
1507     {
1508         .res = DLNA_VIDEO_RES(352, 240),
1509         .bitrate = DLNA_BITRATE(1, 12000000),
1510         .levels = DLNA_LEVEL("6"),
1511     },
1512     {
1513         .res = DLNA_VIDEO_RES(320, 240),
1514         .bitrate = DLNA_BITRATE(1, 12000000),
1515         .levels = DLNA_LEVEL("6"),
1516     },
1517     {
1518         .res = DLNA_VIDEO_RES(320, 180),
1519         .bitrate = DLNA_BITRATE(1, 12000000),
1520         .levels = DLNA_LEVEL("6"),
1521     },
1522     {
1523         .res = DLNA_VIDEO_RES(240, 180),
1524         .bitrate = DLNA_BITRATE(1, 12000000),
1525         .levels = DLNA_LEVEL("6"),
1526     },
1527     {
1528         .res = DLNA_VIDEO_RES(208, 160),
1529         .bitrate = DLNA_BITRATE(1, 12000000),
1530         .levels = DLNA_LEVEL("6"),
1531     },
1532     {
1533         .res = DLNA_VIDEO_RES(176, 144),
1534         .bitrate = DLNA_BITRATE(1, 12000000),
1535         .levels = DLNA_LEVEL("6"),
1536     },
1537     {
1538         .res = DLNA_VIDEO_RES(176, 120),
1539         .bitrate = DLNA_BITRATE(1, 12000000),
1540         .levels = DLNA_LEVEL("6"),
1541     },
1542     {
1543         .res = DLNA_VIDEO_RES(160, 120),
1544         .bitrate = DLNA_BITRATE(1, 12000000),
1545         .levels = DLNA_LEVEL("6"),
1546     },
1547     {
1548         .res = DLNA_VIDEO_RES(160, 112),
1549         .bitrate = DLNA_BITRATE(1, 12000000),
1550         .levels = DLNA_LEVEL("6"),
1551     },
1552     {
1553         .res = DLNA_VIDEO_RES(160, 90),
1554         .bitrate = DLNA_BITRATE(1, 12000000),
1555         .levels = DLNA_LEVEL("6"),
1556     },
1557     {
1558         .res = DLNA_VIDEO_RES(1280, 720),
1559         .bitrate = DLNA_BITRATE(1, 12000000),
1560         .levels = DLNA_LEVEL("6"),
1561     },
1562     { NULL },
1563 };
1564
1565 #define DLNA_VIDEO_RULE_H263_P0_L10             \
1566     {                                           \
1567         .res = DLNA_VIDEO_RES(176, 144),        \
1568         .bitrate = DLNA_BITRATE(1, 64000),      \
1569         .levels = DLNA_LEVEL("0")               \
1570     },                                          \
1571     {                                           \
1572         .res = DLNA_VIDEO_RES(128, 96),         \
1573         .bitrate = DLNA_BITRATE(1, 64000),      \
1574         .levels = DLNA_LEVEL("0")               \
1575     }                                           \
1576
1577 static const struct dlna_video_rule _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac[] = {
1578     DLNA_VIDEO_RULE_H263_P0_L10,
1579     { NULL },
1580 };
1581
1582 static const struct dlna_video_rule _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac_ltp[] = {
1583     DLNA_VIDEO_RULE_H263_P0_L10,
1584     { NULL },
1585 };
1586
1587 #define DLNA_VIDEO_LEVELS_CIF                   \
1588     "1", "1b", "1.1", "1.2"                     \
1589
1590 #define DLNA_VIDEO_RULES_AVC_MP4_BL_CIF15                               \
1591     {                                                                   \
1592         .res = DLNA_VIDEO_RES(352, 288),                                \
1593         .bitrate = DLNA_BITRATE(1, 384000),                             \
1594         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1595         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 15/1),       \
1596     },                                                                  \
1597     {                                                                   \
1598         .res = DLNA_VIDEO_RES(352, 240),                                \
1599         .bitrate = DLNA_BITRATE(1, 384000),                             \
1600         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1601         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 18/1),       \
1602     },                                                                  \
1603     {                                                                   \
1604         .res = DLNA_VIDEO_RES(320, 240),                                \
1605         .bitrate = DLNA_BITRATE(1, 384000),                             \
1606         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1607         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 20/1),       \
1608     },                                                                  \
1609     {                                                                   \
1610         .res = DLNA_VIDEO_RES(320, 180),                                \
1611         .bitrate = DLNA_BITRATE(1, 384000),                             \
1612         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1613         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 26/1),       \
1614     },                                                                  \
1615     {                                                                   \
1616         .res = DLNA_VIDEO_RES(240, 180),                                \
1617         .bitrate = DLNA_BITRATE(1, 384000),                             \
1618         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1619         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1620     },                                                                  \
1621     {                                                                   \
1622         .res = DLNA_VIDEO_RES(208, 160),                                \
1623         .bitrate = DLNA_BITRATE(1, 384000),                             \
1624         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1625         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1626     },                                                                  \
1627     {                                                                   \
1628         .res = DLNA_VIDEO_RES(176, 144),                                \
1629         .bitrate = DLNA_BITRATE(1, 384000),                             \
1630         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1631         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1632     },                                                                  \
1633     {                                                                   \
1634         .res = DLNA_VIDEO_RES(176, 120),                                \
1635         .bitrate = DLNA_BITRATE(1, 384000),                             \
1636         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1637         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1638     },                                                                  \
1639     {                                                                   \
1640         .res = DLNA_VIDEO_RES(160, 120),                                \
1641         .bitrate = DLNA_BITRATE(1, 384000),                             \
1642         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1643         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1644     },                                                                  \
1645     {                                                                   \
1646         .res = DLNA_VIDEO_RES(160, 112),                                \
1647         .bitrate = DLNA_BITRATE(1, 384000),                             \
1648         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1649         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1650     },                                                                  \
1651     {                                                                   \
1652         .res = DLNA_VIDEO_RES(160, 90),                                 \
1653         .bitrate = DLNA_BITRATE(1, 384000),                             \
1654         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1655         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1656     },                                                                  \
1657     {                                                                   \
1658         .res = DLNA_VIDEO_RES(128, 96),                                 \
1659         .bitrate = DLNA_BITRATE(1, 384000),                             \
1660         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1661         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1662     },                                                                  \
1663     {                                                                   \
1664         .res = DLNA_VIDEO_RES(240, 135),                                \
1665         .bitrate = DLNA_BITRATE(1, 384000),                             \
1666         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_CIF),                    \
1667         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1668     }                                                                   \
1669
1670 static const struct dlna_video_rule _dlna_video_rule_avc_mp4_bl_cif15_aac_520[] = {
1671     DLNA_VIDEO_RULES_AVC_MP4_BL_CIF15,
1672     { NULL },
1673 };
1674
1675 static const struct dlna_video_rule _dlna_video_rule_avc_mp4_bl_cif15_aac[] = {
1676     DLNA_VIDEO_RULES_AVC_MP4_BL_CIF15,
1677     { NULL },
1678 };
1679
1680 #define DLNA_VIDEO_RULES_BL_L3L_SD_AAC                          \
1681     "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3"      \
1682
1683 // common between l3 and l3l sd aac
1684 #define DLNA_VIDEO_RULES_L3_L3L_SD_AAC                                  \
1685     {                                                                   \
1686         .res = DLNA_VIDEO_RES(720, 576),                                \
1687         .bitrate = DLNA_BITRATE(1, 4500000),                            \
1688         .levels = DLNA_LEVEL(DLNA_VIDEO_RULES_BL_L3L_SD_AAC),           \
1689         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 25/1),       \
1690     },                                                                  \
1691     {                                                                   \
1692         .res = DLNA_VIDEO_RES(720, 480),                                \
1693         .bitrate = DLNA_BITRATE(1, 4500000),                            \
1694         .levels = DLNA_LEVEL(DLNA_VIDEO_RULES_BL_L3L_SD_AAC),           \
1695         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30000/1001), \
1696     },                                                                  \
1697     {                                                                   \
1698         .res = DLNA_VIDEO_RES(640, 480),                                \
1699         .bitrate = DLNA_BITRATE(1, 4500000),                            \
1700         .levels = DLNA_LEVEL(DLNA_VIDEO_RULES_BL_L3L_SD_AAC),           \
1701         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1702     },                                                                  \
1703     {                                                                   \
1704         .res = DLNA_VIDEO_RES(640, 360),                                \
1705         .bitrate = DLNA_BITRATE(1, 4500000),                            \
1706         .levels = DLNA_LEVEL(DLNA_VIDEO_RULES_BL_L3L_SD_AAC),           \
1707         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),       \
1708     }                                                                   \
1709
1710 static const struct dlna_video_rule _dlna_video_rule_avc_mp4_bl_l3l_sd_aac[] = {
1711     DLNA_VIDEO_RULES_L3_L3L_SD_AAC,
1712     { NULL },
1713 };
1714
1715 static const struct dlna_video_rule _dlna_video_rule_avc_mp4_bl_l3_sd_aac[] = {
1716     DLNA_VIDEO_RULES_L3_L3L_SD_AAC,
1717     { NULL },
1718 };
1719
1720 #define DLNA_VIDEO_LEVELS_SD_EAC3                               \
1721     "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3"      \
1722
1723 static const struct dlna_video_rule _dlna_video_rule_avc_mp4_mp_sd_eac3[] = {
1724     {
1725         .res = DLNA_VIDEO_RES(864, 480),
1726         .bitrate = DLNA_BITRATE(1, 10000000),
1727         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_SD_EAC3),
1728         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 25/1),
1729     },
1730     {
1731         .res = DLNA_VIDEO_RES(720, 576),
1732         .bitrate = DLNA_BITRATE(1, 10000000),
1733         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_SD_EAC3),
1734         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 50/1),
1735     },
1736     {
1737         .res = DLNA_VIDEO_RES(720, 480),
1738         .bitrate = DLNA_BITRATE(1, 10000000),
1739         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_SD_EAC3),
1740         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
1741     },
1742     {
1743         .res = DLNA_VIDEO_RES(640, 480),
1744         .bitrate = DLNA_BITRATE(1, 10000000),
1745         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_SD_EAC3),
1746         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
1747     },
1748 };
1749
1750 #define DLNA_VIDEO_LEVELS_MP_HD_720P                                    \
1751     "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3", "3.1"       \
1752
1753 static const struct dlna_video_rule _dlna_video_rule_avc_mp4_mp_hd_720p_aac[] = {
1754     {
1755         .res = DLNA_VIDEO_RES(1280, 720),
1756         .bitrate = DLNA_BITRATE(1, 14000000),
1757         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MP_HD_720P),
1758         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
1759     },
1760     {
1761         .res = DLNA_VIDEO_RES(640, 480),
1762         .bitrate = DLNA_BITRATE(1, 14000000),
1763         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MP_HD_720P),
1764         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
1765     },
1766 };
1767
1768 #define DLNA_VIDEO_LEVELS_MP_HD_1080I                                   \
1769     "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3", "3.1", "3.2", "4" \
1770
1771 static const struct dlna_video_rule _dlna_video_rule_avc_mp4_mp_hd_1080i_aac[] = {
1772     {
1773         .res = DLNA_VIDEO_RES(1920, 1080),
1774         .bitrate = DLNA_BITRATE(1, 20000000),
1775         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MP_HD_1080I),
1776         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
1777     },
1778     {
1779         .res = DLNA_VIDEO_RES(1280, 720),
1780         .bitrate = DLNA_BITRATE(1, 20000000),
1781         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_MP_HD_1080I),
1782         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
1783     },
1784 };
1785
1786 #define DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD                                 \
1787     "1", "1b", "1.1", "1.2", "1.3", "2", "2.1", "2.2", "3", "3.1", "3.2", "4" \
1788
1789 static const struct dlna_video_rule _dlna_video_avc_mkv_hp_hd[] = {
1790     {
1791         .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1152),
1792         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
1793         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
1794     },
1795     {
1796         .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1152),
1797         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
1798         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 50/1),
1799     },
1800     {
1801         .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1152),
1802         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
1803         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 25/1),
1804     },
1805     {
1806         .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1080),
1807         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
1808         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 30/1),
1809     },
1810     {
1811         .res_range = DLNA_VIDEO_RES_RANGE(1, 1920, 1, 1080),
1812         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
1813         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
1814     },
1815     {
1816         .res_range = DLNA_VIDEO_RES_RANGE(1, 1280, 1, 720),
1817         .levels = DLNA_LEVEL(DLNA_VIDEO_LEVELS_AVC_MKV_HP_HD),
1818         .framerate_range = DLNA_VIDEO_FRAMERATE_RANGE(0/1, 60/1),
1819     },
1820 };
1821
1822 // mpeg4
1823 static const struct dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_aac = {
1824     .codec = &_codec_audio_mpeg4aac_lc,
1825     .bitrate = DLNA_BITRATE(1, 216000),
1826     .levels = DLNA_LEVEL("1", "2"),
1827     .channels = DLNA_BITRATE(1, 2),
1828 };
1829
1830 static const struct dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_aac_ltp = {
1831     .codec = &_codec_audio_mpeg4aac_ltp,
1832     .bitrate = DLNA_BITRATE(1, 216000),
1833     .levels = DLNA_LEVEL("1", "2"),
1834     .channels = DLNA_BITRATE(1, 2),
1835 };
1836
1837 static const struct dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_vga_aac = {
1838     .codec = &_codec_audio_mpeg4aac_lc,
1839     .bitrate = DLNA_BITRATE(1, 256000),
1840     .levels = DLNA_LEVEL("1", "2"),
1841     .channels = DLNA_BITRATE(1, 2),
1842 };
1843
1844 static const struct dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_l2_aac = {
1845     .codec = &_codec_audio_mpeg4aac_lc,
1846     .bitrate = DLNA_BITRATE(1, 128000),
1847     .levels = DLNA_LEVEL("1", "2"),
1848     .channels = DLNA_BITRATE(1, 2),
1849 };
1850
1851 static const struct dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_l5_aac = {
1852     .codec = &_codec_audio_mpeg4aac_lc,
1853     .levels = DLNA_LEVEL("1", "2"),
1854     .channels = DLNA_BITRATE(1, 2),
1855 };
1856
1857 static const struct dlna_audio_rule _dlna_audio_mpeg4_p2_mp4_sp_l6_aac = {
1858     .codec = &_codec_audio_mpeg4aac_lc,
1859     .levels = DLNA_LEVEL("1", "2"),
1860     .channels = DLNA_BITRATE(1, 2),
1861 };
1862
1863 static const struct dlna_audio_rule _dlna_audio_mpeg4_h263_mp4_p0_l10_aac = {
1864     .codec = &_codec_audio_mpeg4aac_lc,
1865     .bitrate = DLNA_BITRATE(1, 86000),
1866     .levels = DLNA_LEVEL("1", "2"),
1867     .channels = DLNA_BITRATE(1, 2),
1868 };
1869
1870 static const struct dlna_audio_rule _dlna_audio_mpeg4_h263_mp4_p0_l10_aac_ltp = {
1871     .codec = &_codec_audio_mpeg4aac_ltp,
1872     .bitrate = DLNA_BITRATE(1, 86000),
1873     .levels = DLNA_LEVEL("1", "2"),
1874     .channels = DLNA_BITRATE(1, 2),
1875 };
1876
1877 // avc
1878 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_bl_cif15_aac_520 = {
1879     .codec = &_codec_audio_mpeg4aac_lc,
1880     .bitrate = DLNA_BITRATE(1, 128000),
1881     .levels = DLNA_LEVEL("1", "2"),
1882     .channels = DLNA_BITRATE(1, 2),
1883 };
1884
1885 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_bl_cif15_aac = {
1886     .codec = &_codec_audio_mpeg4aac_lc,
1887     .bitrate = DLNA_BITRATE(1, 200000),
1888     .levels = DLNA_LEVEL("1", "2"),
1889     .channels = DLNA_BITRATE(1, 2),
1890 };
1891
1892 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_bl_l3l_sd_aac = {
1893     .codec = &_codec_audio_mpeg4aac_lc,
1894     .bitrate = DLNA_BITRATE(1, 256000),
1895     .levels = DLNA_LEVEL("1", "2"),
1896     .channels = DLNA_BITRATE(1, 2),
1897 };
1898
1899 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_bl_l3_sd_aac = {
1900     .codec = &_codec_audio_mpeg4aac_lc,
1901     .bitrate = DLNA_BITRATE(1, 256000),
1902     .levels = DLNA_LEVEL("1", "2"),
1903     .channels = DLNA_BITRATE(1, 2),
1904 };
1905
1906 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_sd_aac_mult5 = {
1907     .codec = &_codec_audio_mpeg4aac_lc,
1908     .bitrate = DLNA_BITRATE(0,1440000),
1909     .levels = DLNA_LEVEL("1", "2", "4"),
1910     .channels = DLNA_BITRATE(1, 6),
1911 };
1912
1913 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_sd_mpeg1_l3 = {
1914     .codec = &_codec_audio_mpeg4aac_lc,
1915     .bitrate = DLNA_BITRATE(32000, 32000),
1916     .channels = DLNA_BITRATE(1, 2),
1917     .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
1918 };
1919
1920 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_sd_ac3 = {
1921     .codec = &_codec_audio_mpeg4aac_lc,
1922     .bitrate = DLNA_BITRATE(64000, 64000),
1923     .channels = DLNA_BITRATE(1, 6),
1924     .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
1925 };
1926
1927 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_sd_eac3 = {
1928     .codec = &_codec_audio_mpeg4aac_lc,
1929     .bitrate = DLNA_BITRATE(0, 3024000),
1930     .channels = DLNA_BITRATE(1, 6),
1931     .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
1932 };
1933
1934 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_hd_720p_aac = {
1935     .codec = &_codec_audio_mpeg4aac_lc,
1936     .bitrate = DLNA_BITRATE(0, 576000),
1937     .channels = DLNA_BITRATE(1, 2),
1938     .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
1939 };
1940
1941 static const struct dlna_audio_rule _dlna_audio_rule_avc_mp4_mp_hd_1080i_aac = {
1942     .codec = &_codec_audio_mpeg4aac_lc,
1943     .bitrate = DLNA_BITRATE(0, 576000),
1944     .channels = DLNA_BITRATE(1, 2),
1945     .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
1946 };
1947
1948 static const struct dlna_audio_rule _dlna_audio_rule_avc_mkv_mp_hd_aac_mult5 = {
1949     .codec = &_codec_audio_mpeg4aac_lc,
1950     .bitrate = DLNA_BITRATE(0, 1440000),
1951     .channels = DLNA_BITRATE(1, 6),
1952     .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000),
1953     .levels = DLNA_LEVEL("1", "2", "4"),
1954 };
1955
1956 static const struct dlna_audio_rule _dlna_audio_rule_avc_mkv_mp_hd_ac3 = {
1957     .codec = &_codec_audio_mpeg4aac_lc,
1958     .bitrate = DLNA_BITRATE(0, 1440000),
1959     .channels = DLNA_BITRATE(1, 6),
1960     .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
1961 };
1962
1963 static const struct dlna_audio_rule _dlna_audio_rule_avc_mkv_mp_hd_mpeg1_l3 = {
1964     .codec = &_codec_audio_mpeg4aac_lc,
1965     .channels = DLNA_BITRATE(1, 2),
1966     .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
1967     .bitrate = DLNA_BITRATE(32000, 320000),
1968 };
1969
1970 static const  struct dlna_video_profile _dlna_video_profile_rules[] = {
1971     // mpeg4
1972     {
1973         .dlna_profile = &_dlna_profile_p2_sp_aac,
1974         .dlna_mime = &_dlna_mime_video,
1975         .video_rules = _dlna_video_rule_sp_l3,
1976         .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_aac,
1977     },
1978     {
1979         .dlna_profile = &_dlna_profile_p2_sp_aac_ltp,
1980         .dlna_mime = &_dlna_mime_video,
1981         .video_rules = _dlna_video_rule_sp_l3,
1982         .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_aac_ltp,
1983     },
1984     {
1985         .dlna_profile = &_dlna_profile_p2_sp_vga_aac,
1986         .dlna_mime = &_dlna_mime_video,
1987         .video_rules = _dlna_video_mpeg4_p2_mp4_sp_vga_aac,
1988         .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_vga_aac,
1989     },
1990     {
1991         .dlna_profile = &_dlna_profile_p2_sp_l2_aac,
1992         .dlna_mime = &_dlna_mime_video,
1993         .video_rules = _dlna_video_mpeg4_p2_mp4_sp_l2_aac,
1994         .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_l2_aac,
1995     },
1996     {
1997         .dlna_profile = &_dlna_profile_p2_sp_l5_aac,
1998         .dlna_mime = &_dlna_mime_video,
1999         .video_rules = _dlna_video_rule_sp_l5,
2000         .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_l5_aac,
2001     },
2002     {
2003         .dlna_profile = &_dlna_profile_p2_sp_l6_aac,
2004         .dlna_mime = &_dlna_mime_video,
2005         .video_rules = _dlna_video_rule_sp_l6,
2006         .audio_rule = &_dlna_audio_mpeg4_p2_mp4_sp_l6_aac,
2007     },
2008     {
2009         .dlna_profile = &_dlna_profile_h263_p0_l10_aac,
2010         .dlna_mime = &_dlna_mime_video_3gp,
2011         .video_rules = _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac,
2012         .audio_rule = &_dlna_audio_mpeg4_h263_mp4_p0_l10_aac,
2013     },
2014     {
2015         .dlna_profile = &_dlna_profile_h263_p0_l10_aac_ltp,
2016         .dlna_mime = &_dlna_mime_video_3gp,
2017         .video_rules = _dlna_video_rule_mpeg4_h263_mp4_p0_l10_aac_ltp,
2018         .audio_rule = &_dlna_audio_mpeg4_h263_mp4_p0_l10_aac_ltp,
2019     },
2020     // avc
2021     {
2022         .dlna_profile = &_dlna_profile_avc_mp4_bl_cif15_aac_520,
2023         .dlna_mime = &_dlna_mime_video,
2024         .video_rules = _dlna_video_rule_avc_mp4_bl_cif15_aac_520,
2025         .audio_rule = &_dlna_audio_rule_avc_mp4_bl_cif15_aac_520,
2026     },
2027     {
2028         .dlna_profile = &_dlna_profile_avc_mp4_bl_cif15_aac,
2029         .dlna_mime = &_dlna_mime_video,
2030         .video_rules = _dlna_video_rule_avc_mp4_bl_cif15_aac,
2031         .audio_rule = &_dlna_audio_rule_avc_mp4_bl_cif15_aac,
2032     },
2033     {
2034         .dlna_profile = &_dlna_profile_avc_mp4_bl_l3l_sd_aac,
2035         .dlna_mime = &_dlna_mime_video,
2036         .video_rules = _dlna_video_rule_avc_mp4_bl_l3l_sd_aac,
2037         .audio_rule = &_dlna_audio_rule_avc_mp4_bl_l3l_sd_aac,
2038     },
2039     {
2040         .dlna_profile = &_dlna_profile_avc_mp4_bl_l3_sd_aac,
2041         .dlna_mime = &_dlna_mime_video,
2042         .video_rules = _dlna_video_rule_avc_mp4_bl_l3_sd_aac,
2043         .audio_rule = &_dlna_audio_rule_avc_mp4_bl_l3_sd_aac,
2044     },
2045     {
2046         .dlna_profile = &_dlna_profile_avc_mp4_mp_sd_aac_mult5,
2047         .dlna_mime = &_dlna_mime_video,
2048         .video_rules = _dlna_video_rule_avc_mp4_mp_sd,
2049         .audio_rule = &_dlna_audio_rule_avc_mp4_mp_sd_aac_mult5,
2050     },
2051     {
2052         .dlna_profile = &_dlna_profile_avc_mp4_mp_sd_mpeg1_l3,
2053         .dlna_mime = &_dlna_mime_video,
2054         .video_rules = _dlna_video_rule_avc_mp4_mp_sd,
2055         .audio_rule = &_dlna_audio_rule_avc_mp4_mp_sd_mpeg1_l3,
2056     },
2057     {
2058         .dlna_profile = &_dlna_profile_avc_mp4_mp_sd_ac3,
2059         .dlna_mime = &_dlna_mime_video,
2060         .video_rules = _dlna_video_rule_avc_mp4_mp_sd,
2061         .audio_rule = &_dlna_audio_rule_avc_mp4_mp_sd_ac3,
2062     },
2063     {
2064         .dlna_profile = &_dlna_profile_avc_mp4_mp_sd_eac3,
2065         .dlna_mime = &_dlna_mime_video,
2066         .video_rules = _dlna_video_rule_avc_mp4_mp_sd_eac3,
2067         .audio_rule = &_dlna_audio_rule_avc_mp4_mp_sd_eac3,
2068     },
2069     {
2070         .dlna_profile = &_dlna_profile_avc_mp4_mp_hd_720p_aac,
2071         .dlna_mime = &_dlna_mime_video,
2072         .video_rules = _dlna_video_rule_avc_mp4_mp_hd_720p_aac,
2073         .audio_rule = &_dlna_audio_rule_avc_mp4_mp_hd_720p_aac,
2074     },
2075     {
2076         .dlna_profile = &_dlna_profile_avc_mp4_mp_hd_720p_aac,
2077         .dlna_mime = &_dlna_mime_video,
2078         .video_rules = _dlna_video_rule_avc_mp4_mp_hd_1080i_aac,
2079         .audio_rule = &_dlna_audio_rule_avc_mp4_mp_hd_1080i_aac,
2080     },
2081     {
2082         .dlna_profile = &_dlna_profile_avc_mkv_mp_hd_aac_mult5,
2083         .dlna_mime = &_dlna_mime_video_matroska,
2084         .video_rules = _dlna_video_avc_mkv_hp_hd,
2085         .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_aac_mult5,
2086     },
2087     {
2088         .dlna_profile = &_dlna_profile_avc_mkv_hp_hd_aac_mult5, // same rules as mp
2089         .dlna_mime = &_dlna_mime_video_matroska,
2090         .video_rules = _dlna_video_avc_mkv_hp_hd,
2091         .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_aac_mult5,
2092     },
2093     {
2094         .dlna_profile = &_dlna_profile_avc_mkv_mp_hd_ac3,
2095         .dlna_mime = &_dlna_mime_video_matroska,
2096         .video_rules = _dlna_video_avc_mkv_hp_hd,
2097         .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_ac3,
2098     },
2099     {
2100         .dlna_profile = &_dlna_profile_avc_mkv_hp_hd_ac3, // same rules as mp
2101         .dlna_mime = &_dlna_mime_video_matroska,
2102         .video_rules = _dlna_video_avc_mkv_hp_hd,
2103         .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_ac3,
2104     },
2105     {
2106         .dlna_profile = &_dlna_profile_avc_mkv_mp_hd_mpeg1_l3,
2107         .dlna_mime = &_dlna_mime_video_matroska,
2108         .video_rules = _dlna_video_avc_mkv_hp_hd,
2109         .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_mpeg1_l3,
2110     },
2111     {
2112         .dlna_profile = &_dlna_profile_avc_mkv_hp_hd_mpeg1_l3, // same rules as mp
2113         .dlna_mime = &_dlna_mime_video_matroska,
2114         .video_rules = _dlna_video_avc_mkv_hp_hd,
2115         .audio_rule = &_dlna_audio_rule_avc_mkv_mp_hd_mpeg1_l3,
2116     },
2117 };
2118
2119 #define DLNA_AUDIO_RULE_AAC_ISO                                         \
2120     .codec = &_codec_audio_mpeg4aac_lc,                                 \
2121     .channels = DLNA_BITRATE(1, 2),                                     \
2122     .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000,                 \
2123                 22050, 24000, 32000, 44100, 48000),                     \
2124     .bitrate = DLNA_BITRATE(0, 576000)                                  \
2125
2126 static const struct dlna_audio_rule _dlna_audio_rule_aac_iso = {
2127     DLNA_AUDIO_RULE_AAC_ISO,
2128     .container = &_container_mp4,
2129 };
2130
2131 static const struct dlna_audio_rule _dlna_audio_rule_aac_iso_3gp = {
2132     DLNA_AUDIO_RULE_AAC_ISO,
2133     .container = &_container_3gp,
2134 };
2135
2136 #define DLNA_AUDIO_RULE_AAC_ISO_320                                     \
2137     .codec = &_codec_audio_mpeg4aac_lc,                                 \
2138     .channels = DLNA_BITRATE(1, 2),                                     \
2139     .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000,                 \
2140                 22050, 24000, 32000, 44100, 48000),                     \
2141     .bitrate = DLNA_BITRATE(0, 320000)                                  \
2142
2143 static const struct dlna_audio_rule _dlna_audio_rule_aac_iso_320 = {
2144     DLNA_AUDIO_RULE_AAC_ISO_320,
2145     .container = &_container_mp4,
2146 };
2147
2148 static const struct dlna_audio_rule _dlna_audio_rule_aac_iso_320_3gp = {
2149     DLNA_AUDIO_RULE_AAC_ISO_320,
2150     .container = &_container_3gp,
2151 };
2152
2153 #define DLNA_AUDIO_RULE_AAC_MULT5_ISO                                   \
2154     .codec = &_codec_audio_mpeg4aac_lc,                                 \
2155     .channels = DLNA_BITRATE(1, 6),                                     \
2156     .rates = DLNA_AUDIO_RATE(8000, 11025, 12000, 16000,                 \
2157                 22050, 24000, 32000, 44100, 48000),                     \
2158     .bitrate = DLNA_BITRATE(0, 1440000)                                 \
2159
2160 static const struct dlna_audio_rule _dlna_audio_rule_aac_mult5_iso = {
2161     DLNA_AUDIO_RULE_AAC_MULT5_ISO,
2162     .container = &_container_mp4,
2163 };
2164
2165 static const struct dlna_audio_rule _dlna_audio_rule_aac_mult5_iso_3gp = {
2166     DLNA_AUDIO_RULE_AAC_MULT5_ISO,
2167     .container = &_container_3gp,
2168 };
2169
2170 static const struct dlna_audio_rule _dlna_audio_rule_ac3 = {
2171     .codec = &_codec_audio_mpeg4aac_lc,
2172     .channels = DLNA_BITRATE(1, 6),
2173     .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
2174     .bitrate = DLNA_BITRATE(64000, 64000),
2175 };
2176
2177 static const struct dlna_audio_rule _dlna_audio_rule_eac3 = {
2178     .codec = &_codec_audio_mpeg4aac_lc,
2179     .channels = DLNA_BITRATE(1, 6),
2180     .rates = DLNA_AUDIO_RATE(32000, 44100, 48000),
2181     .bitrate = DLNA_BITRATE( 32000, 6144000),
2182 };
2183
2184 static const struct dlna_audio_rule _dlna_audio_rule_amr_3gpp = {
2185     .codec = &_codec_audio_amr,
2186     .container = &_container_3gp,
2187 };
2188
2189 static const struct dlna_audio_rule _dlna_audio_rule_amr = {
2190     .codec = &_codec_audio_amr,
2191 };
2192
2193 static const struct dlna_audio_rule _dlna_audio_rule_amr_wbplus = {
2194     .codec = &_codec_audio_amr_wb,
2195     .rates = DLNA_AUDIO_RATE(8000, 16000, 24000, 32000, 48000),
2196 };
2197
2198 static const struct dlna_audio_rule _dlna_audio_rule_amr_wbplus_3gp = {
2199     .codec = &_codec_audio_amr_wb,
2200     .container = &_container_3gp,
2201     .rates = DLNA_AUDIO_RATE(8000, 16000, 24000, 32000, 48000),
2202 };
2203
2204 //_dlna_profile_aac_mult5_iso
2205 static const  struct dlna_audio_profile _dlna_audio_profile_rules[] = {
2206     {
2207         .dlna_profile = &_dlna_profile_aac_iso,
2208         .dlna_mime = &_dlna_mime_audio,
2209         .audio_rule = &_dlna_audio_rule_aac_iso,
2210     },
2211     {
2212         .dlna_profile = &_dlna_profile_aac_iso,
2213         .dlna_mime = &_dlna_mime_audio_3gp,
2214         .audio_rule = &_dlna_audio_rule_aac_iso_3gp,
2215     },
2216     {
2217         .dlna_profile = &_dlna_profile_aac_iso_320,
2218         .dlna_mime = &_dlna_mime_audio,
2219         .audio_rule = &_dlna_audio_rule_aac_iso_320,
2220     },
2221     {
2222         .dlna_profile = &_dlna_profile_aac_iso_320,
2223         .dlna_mime = &_dlna_mime_audio_3gp,
2224         .audio_rule = &_dlna_audio_rule_aac_iso_320_3gp,
2225     },
2226     {
2227         .dlna_profile = &_dlna_profile_aac_mult5_iso,
2228         .dlna_mime = &_dlna_mime_audio,
2229         .audio_rule = &_dlna_audio_rule_aac_mult5_iso,
2230     },
2231     {
2232         .dlna_profile = &_dlna_profile_aac_mult5_iso,
2233         .dlna_mime = &_dlna_mime_audio_3gp,
2234         .audio_rule = &_dlna_audio_rule_aac_mult5_iso_3gp,
2235     },
2236     {
2237         .dlna_profile = &_dlna_profile_ac3,
2238         .dlna_mime = &_dlna_mime_audio_dolby,
2239         .audio_rule = &_dlna_audio_rule_ac3,
2240     },
2241     {
2242         .dlna_profile = &_dlna_profile_eac3,
2243         .dlna_mime = &_dlna_mime_audio_eac3,
2244         .audio_rule = &_dlna_audio_rule_eac3,
2245     },
2246     {
2247         .dlna_profile = &_dlna_profile_amr_3gpp,
2248         .dlna_mime = &_dlna_mime_audio_3gp,
2249         .audio_rule = &_dlna_audio_rule_amr_3gpp,
2250     },
2251     {
2252         .dlna_profile = &_dlna_profile_amr_3gpp,
2253         .dlna_mime = &_dlna_mime_audio,
2254         .audio_rule = &_dlna_audio_rule_amr,
2255     },
2256     {
2257         .dlna_profile = &_dlna_profile_amr_wbplus,
2258         .dlna_mime = &_dlna_mime_audio,
2259         .audio_rule = &_dlna_audio_rule_amr_wbplus,
2260     },
2261     {
2262         .dlna_profile = &_dlna_profile_amr_wbplus,
2263         .dlna_mime = &_dlna_mime_audio_3gp,
2264         .audio_rule = &_dlna_audio_rule_amr_wbplus_3gp,
2265     },
2266     { NULL }
2267 };
2268
2269 static bool
2270 _string_vector_has_value(const char **list, const char *wanted)
2271 {
2272     int i;
2273     const char *curr;
2274
2275     for (i = 0, curr = list[i]; curr != NULL; i++, curr = list[i]) {
2276         if (!strcmp(curr, wanted)) return true;
2277     }
2278
2279     return false;
2280 }
2281
2282 static bool
2283 _uint_vector_has_value(const unsigned int *list, unsigned int wanted)
2284 {
2285     int i;
2286     unsigned int curr;
2287
2288     for (i = 0, curr = list[i]; curr != INT32_MAX; i++, curr = list[i])
2289       if (curr == wanted) return true;
2290
2291     return false;
2292 }
2293
2294 static void
2295 _fill_audio_dlna_profile(struct lms_audio_info *info)
2296 {
2297     int i = 0;
2298
2299     while (true) {
2300         const struct dlna_audio_profile *curr = _dlna_audio_profile_rules + i;
2301         const struct dlna_audio_rule *rule;
2302
2303         if (curr->dlna_profile == NULL && curr->dlna_mime == NULL &&
2304             curr->audio_rule == NULL)
2305             break;
2306
2307         i++;
2308         rule = curr->audio_rule;
2309
2310         if (rule->bitrate && (info->bitrate < rule->bitrate->min ||
2311                               info->bitrate > rule->bitrate->max))
2312             continue;
2313
2314         if (rule->rates &&
2315             !_uint_vector_has_value(rule->rates->rates, info->sampling_rate))
2316             continue;
2317
2318         if (rule->channels &&
2319             (info->channels < rule->channels->min ||
2320              info->channels > rule->channels->max))
2321             continue;
2322
2323         if (rule->codec && strcmp(rule->codec->str, info->codec.str))
2324             continue;
2325
2326         if (rule->container && strcmp(rule->container->str, info->container.str))
2327             continue;
2328
2329         info->dlna_mime = *curr->dlna_mime;
2330         info->dlna_profile = *curr->dlna_profile;
2331         break;
2332     }
2333 }
2334
2335 static const struct dlna_video_profile *
2336 _get_video_dlna_profile(const struct lms_stream_audio_info *audio,
2337                         const struct lms_stream *audio_stream,
2338                         const struct lms_stream_video_info *video,
2339                         const struct lms_stream *video_stream)
2340 {
2341     int i, length;
2342     const struct dlna_video_profile *curr;
2343     char *level;
2344
2345     level = strstr(video_stream->codec.str, "-l");
2346     length = sizeof(_dlna_video_profile_rules) / sizeof(struct dlna_video_profile);
2347
2348     for (i = 0, curr = &_dlna_video_profile_rules[i]; i < length; i++,
2349              curr = &_dlna_video_profile_rules[i]) {
2350         const struct dlna_video_rule *video_rule;
2351         const struct dlna_audio_rule *audio_rule;
2352         const struct dlna_video_rule *r;
2353
2354         audio_rule = curr->audio_rule;
2355         r = curr->video_rules;
2356
2357         if (audio_rule->bitrate && (audio->bitrate < audio_rule->bitrate->min ||
2358                                     audio->bitrate > audio_rule->bitrate->max))
2359             continue;
2360
2361         if (audio_rule->rates &&
2362             !_uint_vector_has_value(audio_rule->rates->rates,
2363                                     audio->sampling_rate))
2364             continue;
2365
2366         if (audio_rule->channels &&
2367             (audio->channels < audio_rule->channels->min ||
2368              audio->channels > audio_rule->channels->max))
2369             continue;
2370
2371         if (audio_rule->codec &&
2372             strcmp(audio_stream->codec.str, audio_rule->codec->str))
2373             continue;
2374
2375         while (true) {
2376             video_rule = r++;
2377
2378             if (!video_rule->res && !video_rule->bitrate &&
2379                 !video_rule->levels && !video_rule->framerate_range)
2380                 break;
2381
2382             if (video_rule->res && (video->width != video_rule->res->width &&
2383                                     video->height != video_rule->res->height))
2384                 continue;
2385
2386             if (video_rule->res_range &&
2387                 !(video->width >= video_rule->res_range->width_min &&
2388                   video->width <= video_rule->res_range->width_max &&
2389                   video->height >= video_rule->res_range->height_min &&
2390                   video->height <= video_rule->res_range->height_max))
2391                 continue;
2392
2393             if (video_rule->framerate_range &&
2394                 !(video->framerate >= video_rule->framerate_range->min &&
2395                   video->framerate <= video_rule->framerate_range->max))
2396                 continue;
2397
2398             if (video_rule->bitrate &&
2399                 !(video->bitrate >= video_rule->bitrate->min &&
2400                   video->bitrate <= video_rule->bitrate->max))
2401                 continue;
2402
2403             if (video_rule->levels &&
2404                 !_string_vector_has_value(video_rule->levels->levels,
2405                                           level + 2))
2406                 continue;
2407
2408             return curr;
2409         }
2410     }
2411
2412     return NULL;
2413 }
2414
2415 static void
2416 _fill_video_dlna_profile(struct lms_video_info *info)
2417 {
2418     const struct dlna_video_profile *profile;
2419     const struct lms_stream *s, *audio_stream, *video_stream;
2420     const struct lms_stream_audio_info *audio;
2421     const struct lms_stream_video_info *video;
2422
2423     audio_stream = video_stream = NULL;
2424     audio = NULL;
2425     video = NULL;
2426
2427     for (s = info->streams; s; s = s->next) {
2428         if (s->type == LMS_STREAM_TYPE_VIDEO) {
2429             video = &s->video;
2430             video_stream = s;
2431             if (audio) break;
2432         } else if (s->type == LMS_STREAM_TYPE_AUDIO) {
2433             audio = &s->audio;
2434             audio_stream = s;
2435             if (video) break;
2436         }
2437     }
2438
2439     profile = _get_video_dlna_profile(audio, audio_stream, video, video_stream);
2440     if (!profile) return;
2441
2442     info->dlna_profile = *profile->dlna_profile;
2443     info->dlna_mime = *profile->dlna_mime;
2444 }
2445
2446 static int
2447 _parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match)
2448 {
2449     struct mp4_info info = { };
2450     struct lms_audio_info audio_info = { };
2451     struct lms_video_info video_info = { };
2452     int r, stream_type = LMS_STREAM_TYPE_AUDIO;
2453     MP4FileHandle mp4_fh;
2454     u_int32_t num_tracks, i;
2455     const MP4Tags *tags;
2456
2457     mp4_fh = MP4Read(finfo->path);
2458     if (mp4_fh == MP4_INVALID_FILE_HANDLE) {
2459         fprintf(stderr, "ERROR: cannot read mp4 file %s\n", finfo->path);
2460         return -1;
2461     }
2462
2463     tags = MP4TagsAlloc();
2464     if (!tags)
2465         return -1;
2466
2467     if (!MP4TagsFetch(tags, mp4_fh)) {
2468         r = -1;
2469         goto fail;
2470     }
2471
2472     lms_string_size_strndup(&info.title, tags->name, -1);
2473     lms_string_size_strndup(&info.artist, tags->artist, -1);
2474
2475     /* check if the file contains a video track */
2476     num_tracks = MP4GetNumberOfTracks(mp4_fh, MP4_VIDEO_TRACK_TYPE, 0);
2477     if (num_tracks > 0)
2478         stream_type = LMS_STREAM_TYPE_VIDEO;
2479
2480     info.length = MP4GetDuration(mp4_fh) /
2481         MP4GetTimeScale(mp4_fh) ?: 1;
2482
2483     if (stream_type == LMS_STREAM_TYPE_AUDIO) {
2484         MP4TrackId id;
2485
2486         lms_string_size_strndup(&info.album, tags->album, -1);
2487         lms_string_size_strndup(&info.genre, tags->genre, -1);
2488         if (tags->track)
2489             info.trackno = tags->track->index;
2490
2491         id = MP4FindTrackId(mp4_fh, 0, MP4_AUDIO_TRACK_TYPE, 0);
2492         audio_info.bitrate = MP4GetTrackBitRate(mp4_fh, id);
2493         audio_info.channels = MP4GetTrackAudioChannels(mp4_fh, id);
2494         audio_info.sampling_rate = MP4GetTrackTimeScale(mp4_fh, id);
2495         audio_info.length = info.length;
2496         audio_info.codec = _get_audio_codec(mp4_fh, id);
2497     } else {
2498         num_tracks = MP4GetNumberOfTracks(mp4_fh, NULL, 0);
2499         for (i = 0; i < num_tracks; i++) {
2500             MP4TrackId id = MP4FindTrackId(mp4_fh, i, NULL, 0);
2501             const char *type = MP4GetTrackType(mp4_fh, id);
2502             enum lms_stream_type lmstype;
2503             struct lms_stream *s;
2504
2505             if (strcmp(type, MP4_AUDIO_TRACK_TYPE) == 0)
2506                 lmstype = LMS_STREAM_TYPE_AUDIO;
2507             else if (strcmp(type, MP4_VIDEO_TRACK_TYPE) == 0)
2508                 lmstype = LMS_STREAM_TYPE_VIDEO;
2509             else
2510                 continue;
2511
2512             s = calloc(1, sizeof(*s));
2513             s->type = lmstype;
2514             s->stream_id = id;
2515             s->lang = _get_lang(mp4_fh, id);
2516
2517             if (lmstype == LMS_STREAM_TYPE_AUDIO) {
2518                 s->codec = _get_audio_codec(mp4_fh, id);
2519                 s->audio.sampling_rate = MP4GetTrackTimeScale(mp4_fh, id);
2520                 s->audio.bitrate = MP4GetTrackBitRate(mp4_fh, id);
2521                 s->audio.channels = MP4GetTrackAudioChannels(mp4_fh, id);
2522             } else if (lmstype == LMS_STREAM_TYPE_VIDEO) {
2523                 s->codec = _get_video_codec(mp4_fh, id); /* malloc() */
2524                 s->video.bitrate = MP4GetTrackBitRate(mp4_fh, id);
2525                 s->video.width = MP4GetTrackVideoWidth(mp4_fh, id);
2526                 s->video.height = MP4GetTrackVideoHeight(mp4_fh, id);
2527                 s->video.framerate = MP4GetTrackVideoFrameRate(mp4_fh, id);
2528                 lms_stream_video_info_aspect_ratio_guess(&s->video);
2529             }
2530
2531             s->next = video_info.streams;
2532             video_info.streams = s;
2533         }
2534         video_info.length = info.length;
2535     }
2536
2537     lms_string_size_strip_and_free(&info.title);
2538     lms_string_size_strip_and_free(&info.artist);
2539     lms_string_size_strip_and_free(&info.album);
2540     lms_string_size_strip_and_free(&info.genre);
2541
2542     if (!info.title.str)
2543         lms_name_from_path(&info.title, finfo->path, finfo->path_len,
2544                            finfo->base, _exts[((long) match) - 1].len,
2545                            NULL);
2546     if (info.title.str)
2547         lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len);
2548     if (info.artist.str)
2549         lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len);
2550     if (info.album.str)
2551         lms_charset_conv(ctxt->cs_conv, &info.album.str, &info.album.len);
2552     if (info.genre.str)
2553         lms_charset_conv(ctxt->cs_conv, &info.genre.str, &info.genre.len);
2554
2555     if (stream_type == LMS_STREAM_TYPE_AUDIO) {
2556         audio_info.id = finfo->id;
2557         audio_info.title = info.title;
2558         audio_info.artist = info.artist;
2559         audio_info.album = info.album;
2560         audio_info.genre = info.genre;
2561         audio_info.container = _get_container(mp4_fh);
2562         audio_info.trackno = info.trackno;
2563
2564         _fill_audio_dlna_profile(&audio_info);
2565
2566         r = lms_db_audio_add(plugin->audio_db, &audio_info);
2567     } else {
2568         video_info.id = finfo->id;
2569         video_info.title = info.title;
2570         video_info.artist = info.artist;
2571         video_info.container = _get_container(mp4_fh);
2572
2573         _fill_video_dlna_profile(&video_info);
2574
2575         r = lms_db_video_add(plugin->video_db, &video_info);
2576     }
2577
2578 fail:
2579     MP4TagsFree(tags);
2580
2581     free(info.title.str);
2582     free(info.artist.str);
2583     free(info.album.str);
2584     free(info.genre.str);
2585
2586     while (video_info.streams) {
2587         struct lms_stream *s = video_info.streams;
2588         video_info.streams = s->next;
2589         if (s->type == LMS_STREAM_TYPE_VIDEO) {
2590             free(s->codec.str); /* ugly, but h264 needs alloc */
2591             free(s->video.aspect_ratio.str);
2592         }
2593         free(s->lang.str);
2594         free(s);
2595     }
2596
2597     MP4Close(mp4_fh, 0);
2598
2599     return r;
2600 }
2601
2602 static int
2603 _setup(struct plugin *plugin, struct lms_context *ctxt)
2604 {
2605     plugin->audio_db = lms_db_audio_new(ctxt->db);
2606     if (!plugin->audio_db)
2607         return -1;
2608     plugin->video_db = lms_db_video_new(ctxt->db);
2609     if (!plugin->video_db)
2610         return -1;
2611
2612     return 0;
2613 }
2614
2615 static int
2616 _start(struct plugin *plugin, struct lms_context *ctxt)
2617 {
2618     int r;
2619     r = lms_db_audio_start(plugin->audio_db);
2620     r |= lms_db_video_start(plugin->video_db);
2621     return r;
2622 }
2623
2624 static int
2625 _finish(struct plugin *plugin, struct lms_context *ctxt)
2626 {
2627     if (plugin->audio_db)
2628         lms_db_audio_free(plugin->audio_db);
2629     if (plugin->video_db)
2630         lms_db_video_free(plugin->video_db);
2631
2632     return 0;
2633 }
2634
2635 static int
2636 _close(struct plugin *plugin)
2637 {
2638     free(plugin);
2639     return 0;
2640 }
2641
2642 API struct lms_plugin *
2643 lms_plugin_open(void)
2644 {
2645     struct plugin *plugin;
2646
2647     plugin = (struct plugin *)malloc(sizeof(*plugin));
2648     plugin->plugin.name = _name;
2649     plugin->plugin.match = (lms_plugin_match_fn_t)_match;
2650     plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse;
2651     plugin->plugin.close = (lms_plugin_close_fn_t)_close;
2652     plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup;
2653     plugin->plugin.start = (lms_plugin_start_fn_t)_start;
2654     plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish;
2655     plugin->plugin.order = 0;
2656
2657     return (struct lms_plugin *)plugin;
2658 }
2659
2660 API const struct lms_plugin_info *
2661 lms_plugin_info(void)
2662 {
2663     static struct lms_plugin_info info = {
2664         _name,
2665         _cats,
2666         "MP4 files (MP4, M4A, MOV, QT, 3GP)",
2667         PV,
2668         _authors,
2669         "http://github.com/profusion/lightmediascanner"
2670     };
2671
2672     return &info;
2673 }