]> git.sesse.net Git - vlc/blob - modules/demux/mp4/essetup.c
demux: mp4: split es setup
[vlc] / modules / demux / mp4 / essetup.c
1 /*****************************************************************************
2  * essetup.h: es setup from stsd and extensions parsing
3  *****************************************************************************
4  * Copyright (C) 2001-2004, 2010, 2014 VLC authors and VideoLAN
5  *
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include "mp4.h"
28 #include "essetup.h"
29
30 #include <vlc_demux.h>
31 #include <vlc_aout.h>
32 #include <assert.h>
33
34 static void SetupESDS( demux_t *p_demux, mp4_track_t *p_track, const MP4_descriptor_decoder_config_t *p_decconfig )
35 {
36     /* First update information based on i_objectTypeIndication */
37     switch( p_decconfig->i_objectProfileIndication )
38     {
39     case( 0x20 ): /* MPEG4 VIDEO */
40         p_track->fmt.i_codec = VLC_CODEC_MP4V;
41         break;
42     case( 0x21 ): /* H.264 */
43         p_track->fmt.i_codec = VLC_CODEC_H264;
44         break;
45     case( 0x40):
46         p_track->fmt.i_codec = VLC_CODEC_MP4A;
47         if( p_decconfig->i_decoder_specific_info_len >= 2 &&
48                 p_decconfig->p_decoder_specific_info[0]       == 0xF8 &&
49                 (p_decconfig->p_decoder_specific_info[1]&0xE0) == 0x80 )
50         {
51             p_track->fmt.i_codec = VLC_CODEC_ALS;
52         }
53         break;
54     case( 0x60):
55     case( 0x61):
56     case( 0x62):
57     case( 0x63):
58     case( 0x64):
59     case( 0x65): /* MPEG2 video */
60         p_track->fmt.i_codec = VLC_CODEC_MPGV;
61         break;
62         /* Theses are MPEG2-AAC */
63     case( 0x66): /* main profile */
64     case( 0x67): /* Low complexity profile */
65     case( 0x68): /* Scaleable Sampling rate profile */
66         p_track->fmt.i_codec = VLC_CODEC_MP4A;
67         break;
68         /* True MPEG 2 audio */
69     case( 0x69):
70         p_track->fmt.i_codec = VLC_CODEC_MPGA;
71         break;
72     case( 0x6a): /* MPEG1 video */
73         p_track->fmt.i_codec = VLC_CODEC_MPGV;
74         break;
75     case( 0x6b): /* MPEG1 audio */
76         p_track->fmt.i_codec = VLC_CODEC_MPGA;
77         break;
78     case( 0x6c ): /* jpeg */
79         p_track->fmt.i_codec = VLC_CODEC_JPEG;
80         break;
81     case( 0x6d ): /* png */
82         p_track->fmt.i_codec = VLC_CODEC_PNG;
83         break;
84     case( 0x6e ): /* jpeg2000 */
85         p_track->fmt.i_codec = VLC_FOURCC( 'M','J','2','C' );
86         break;
87     case( 0xa3 ): /* vc1 */
88         p_track->fmt.i_codec = VLC_CODEC_VC1;
89         break;
90     case( 0xa4 ):
91         p_track->fmt.i_codec = VLC_CODEC_DIRAC;
92         break;
93     case( 0xa5 ):
94         p_track->fmt.i_codec = VLC_CODEC_A52;
95         break;
96     case( 0xa6 ):
97         p_track->fmt.i_codec = VLC_CODEC_EAC3;
98         break;
99     case( 0xa9 ): /* dts */
100     case( 0xaa ): /* DTS-HD HRA */
101     case( 0xab ): /* DTS-HD Master Audio */
102         p_track->fmt.i_codec = VLC_CODEC_DTS;
103         break;
104     case( 0xDD ):
105         p_track->fmt.i_codec = VLC_CODEC_VORBIS;
106         break;
107
108         /* Private ID */
109     case( 0xe0 ): /* NeroDigital: dvd subs */
110         if( p_track->fmt.i_cat == SPU_ES )
111         {
112             p_track->fmt.i_codec = VLC_CODEC_SPU;
113             if( p_track->i_width > 0 )
114                 p_track->fmt.subs.spu.i_original_frame_width = p_track->i_width;
115             if( p_track->i_height > 0 )
116                 p_track->fmt.subs.spu.i_original_frame_height = p_track->i_height;
117             break;
118         }
119     case( 0xe1 ): /* QCelp for 3gp */
120         if( p_track->fmt.i_cat == AUDIO_ES )
121         {
122             p_track->fmt.i_codec = VLC_CODEC_QCELP;
123         }
124         break;
125
126         /* Fallback */
127     default:
128         /* Unknown entry, but don't touch i_fourcc */
129         msg_Warn( p_demux,
130                   "unknown objectProfileIndication(0x%x) (Track[ID 0x%x])",
131                   p_decconfig->i_objectProfileIndication,
132                   p_track->i_track_ID );
133         break;
134     }
135
136     p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len;
137     if( p_track->fmt.i_extra > 0 )
138     {
139         p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
140         memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info,
141                 p_track->fmt.i_extra );
142     }
143     if( p_track->fmt.i_codec == VLC_CODEC_SPU &&
144             p_track->fmt.i_extra >= 16 * 4 )
145     {
146         for( int i = 0; i < 16; i++ )
147         {
148             p_track->fmt.subs.spu.palette[1 + i] =
149                     GetDWBE((char*)p_track->fmt.p_extra + i * 4);
150         }
151         p_track->fmt.subs.spu.palette[0] = 0xBeef;
152     }
153 }
154
155 int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
156 {
157     MP4_Box_data_sample_vide_t *p_vide = p_sample->data.p_sample_vide;
158
159     p_track->fmt.video.i_width = p_vide->i_width;
160     p_track->fmt.video.i_height = p_vide->i_height;
161     p_track->fmt.video.i_bits_per_pixel = p_vide->i_depth;
162
163     /* fall on display size */
164     if( p_track->fmt.video.i_width <= 0 )
165         p_track->fmt.video.i_width = p_track->i_width;
166     if( p_track->fmt.video.i_height <= 0 )
167         p_track->fmt.video.i_height = p_track->i_height;
168
169     /* Find out apect ratio from display size */
170     if( p_track->i_width > 0 && p_track->i_height > 0 &&
171         /* Work-around buggy muxed files */
172         p_vide->i_width != p_track->i_width )
173     {
174         p_track->fmt.video.i_sar_num = p_track->i_width  * p_track->fmt.video.i_height;
175         p_track->fmt.video.i_sar_den = p_track->i_height * p_track->fmt.video.i_width;
176     }
177
178     /* Support for cropping (eg. in H263 files) */
179     p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
180     p_track->fmt.video.i_visible_height = p_track->fmt.video.i_height;
181
182     /* Rotation */
183     switch( (int)p_track->f_rotation ) {
184         case 90:
185             p_track->fmt.video.orientation = ORIENT_ROTATED_90;
186             break;
187         case 180:
188             p_track->fmt.video.orientation = ORIENT_ROTATED_180;
189             break;
190         case 270:
191             p_track->fmt.video.orientation = ORIENT_ROTATED_270;
192             break;
193     }
194
195     /* It's a little ugly but .. there are special cases */
196     switch( p_sample->i_type )
197     {
198         case( VLC_FOURCC( 's', '2', '6', '3' ) ):
199             p_track->fmt.i_codec = VLC_CODEC_H263;
200             break;
201         case VLC_FOURCC('y','v','1','2'):
202             p_track->fmt.i_codec = VLC_CODEC_YV12;
203             break;
204         case VLC_FOURCC('y','u','v','2'):
205             p_track->fmt.i_codec = VLC_FOURCC('Y','U','Y','2');
206             break;
207
208         default:
209             p_track->fmt.i_codec = p_sample->i_type;
210             break;
211     }
212
213
214     /* Read extensions */
215
216     /* Set up A/R from extension atom */
217     const MP4_Box_t *p_pasp = MP4_BoxGet( p_sample, "pasp" );
218     if( p_pasp && BOXDATA(p_pasp) && BOXDATA(p_pasp)->i_horizontal_spacing > 0 &&
219                   BOXDATA(p_pasp)->i_vertical_spacing > 0 )
220     {
221         p_track->fmt.video.i_sar_num = BOXDATA(p_pasp)->i_horizontal_spacing;
222         p_track->fmt.video.i_sar_den = BOXDATA(p_pasp)->i_vertical_spacing;
223     }
224
225     /* now see if esds is present and if so create a data packet
226         with decoder_specific_info  */
227     MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
228     if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
229     {
230         assert(p_sample->i_type == ATOM_mp4v);
231         SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
232     }
233     else switch( p_sample->i_type )
234     {
235         /* qt decoder, send the complete chunk */
236         case VLC_FOURCC ('h', 'd', 'v', '1'): // HDV 720p30
237         case VLC_FOURCC ('h', 'd', 'v', '2'): // HDV 1080i60
238         case VLC_FOURCC ('h', 'd', 'v', '3'): // HDV 1080i50
239         case VLC_FOURCC ('h', 'd', 'v', '5'): // HDV 720p25
240         case VLC_FOURCC ('m', 'x', '5', 'n'): // MPEG2 IMX NTSC 525/60 50mb/s produced by FCP
241         case VLC_FOURCC ('m', 'x', '5', 'p'): // MPEG2 IMX PAL 625/60 50mb/s produced by FCP
242         case VLC_FOURCC ('m', 'x', '4', 'n'): // MPEG2 IMX NTSC 525/60 40mb/s produced by FCP
243         case VLC_FOURCC ('m', 'x', '4', 'p'): // MPEG2 IMX PAL 625/60 40mb/s produced by FCP
244         case VLC_FOURCC ('m', 'x', '3', 'n'): // MPEG2 IMX NTSC 525/60 30mb/s produced by FCP
245         case VLC_FOURCC ('m', 'x', '3', 'p'): // MPEG2 IMX PAL 625/50 30mb/s produced by FCP
246         case VLC_FOURCC ('x', 'd', 'v', '2'): // XDCAM HD 1080i60
247         case VLC_FOURCC ('A', 'V', 'm', 'p'): // AVID IMX PAL
248             p_track->fmt.i_codec = VLC_CODEC_MPGV;
249             break;
250         /* qt decoder, send the complete chunk */
251         case VLC_CODEC_SVQ1:
252         case VLC_CODEC_SVQ3:
253         case VLC_FOURCC( 'V', 'P', '3', '1' ):
254         case VLC_FOURCC( '3', 'I', 'V', '1' ):
255         case VLC_FOURCC( 'Z', 'y', 'G', 'o' ):
256         {
257             p_track->fmt.i_extra =
258                 p_sample->data.p_sample_vide->i_qt_image_description;
259             if( p_track->fmt.i_extra > 0 )
260             {
261                 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
262                 memcpy( p_track->fmt.p_extra,
263                         p_sample->data.p_sample_vide->p_qt_image_description,
264                         p_track->fmt.i_extra);
265             }
266             break;
267         }
268
269         case VLC_FOURCC( 'v', 'c', '-', '1' ):
270         {
271             MP4_Box_t *p_dvc1 = MP4_BoxGet( p_sample, "dvc1" );
272             if( p_dvc1 && BOXDATA(p_dvc1) )
273             {
274                 p_track->fmt.i_extra = BOXDATA(p_dvc1)->i_vc1;
275                 if( p_track->fmt.i_extra > 0 )
276                 {
277                     p_track->fmt.p_extra = malloc( BOXDATA(p_dvc1)->i_vc1 );
278                     memcpy( p_track->fmt.p_extra, BOXDATA(p_dvc1)->p_vc1,
279                             p_track->fmt.i_extra );
280                 }
281             }
282             else
283             {
284                 msg_Err( p_demux, "missing dvc1" );
285             }
286             break;
287         }
288
289         /* avc1: send avcC (h264 without annexe B, ie without start code)*/
290         case VLC_FOURCC( 'a', 'v', 'c', '1' ):
291         {
292             MP4_Box_t *p_avcC = MP4_BoxGet( p_sample, "avcC" );
293
294             if( p_avcC && BOXDATA(p_avcC) )
295             {
296                 p_track->fmt.i_extra = BOXDATA(p_avcC)->i_avcC;
297                 if( p_track->fmt.i_extra > 0 )
298                 {
299                     p_track->fmt.p_extra = malloc( BOXDATA(p_avcC)->i_avcC );
300                     memcpy( p_track->fmt.p_extra, BOXDATA(p_avcC)->p_avcC,
301                             p_track->fmt.i_extra );
302                 }
303             }
304             else
305             {
306                 msg_Err( p_demux, "missing avcC" );
307             }
308             break;
309         }
310         case VLC_FOURCC( 'h', 'v', 'c', '1' ):
311         case VLC_FOURCC( 'h', 'e', 'v', '1' ):
312         {
313             MP4_Box_t *p_hvcC = MP4_BoxGet( p_sample, "hvcC" );
314
315             if( p_hvcC && BOXDATA(p_hvcC) )
316             {
317                 p_track->fmt.i_extra = BOXDATA(p_hvcC)->i_hvcC;
318                 if( p_track->fmt.i_extra > 0 )
319                 {
320                     p_track->fmt.p_extra = malloc( BOXDATA(p_hvcC)->i_hvcC );
321                     memcpy( p_track->fmt.p_extra, BOXDATA(p_hvcC)->p_hvcC,
322                             p_track->fmt.i_extra );
323                 }
324                 p_track->fmt.i_codec = VLC_CODEC_HEVC;
325             }
326             else
327             {
328                 msg_Err( p_demux, "missing hvcC" );
329             }
330             break;
331         }
332
333         case ATOM_WMV3:
334         {
335             MP4_Box_t *p_strf = MP4_BoxGet(  p_sample, "strf", 0 );
336             if ( p_strf && BOXDATA(p_strf) )
337             {
338                 p_track->fmt.i_codec = VLC_CODEC_WMV3;
339                 p_track->fmt.video.i_width = BOXDATA(p_strf)->bmiHeader.biWidth;
340                 p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
341                 p_track->fmt.video.i_height = BOXDATA(p_strf)->bmiHeader.biHeight;
342                 p_track->fmt.video.i_visible_height =p_track->fmt.video.i_height;
343                 p_track->fmt.video.i_bits_per_pixel = BOXDATA(p_strf)->bmiHeader.biBitCount;
344                 p_track->fmt.i_extra = BOXDATA(p_strf)->i_extra;
345                 if( p_track->fmt.i_extra > 0 )
346                 {
347                     p_track->fmt.p_extra = malloc( BOXDATA(p_strf)->i_extra );
348                     memcpy( p_track->fmt.p_extra, BOXDATA(p_strf)->p_extra,
349                             p_track->fmt.i_extra );
350                 }
351                 p_track->p_asf = MP4_BoxGet( p_sample, "ASF " );
352             }
353             break;
354         }
355
356         default:
357             msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
358             break;
359     }
360
361     return 1;
362 }
363
364 int SetupAudioES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
365 {
366     MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;
367
368     p_track->fmt.audio.i_channels = p_soun->i_channelcount;
369     p_track->fmt.audio.i_rate = p_soun->i_sampleratehi;
370     p_track->fmt.i_bitrate = p_soun->i_channelcount * p_soun->i_sampleratehi *
371                              p_soun->i_samplesize;
372     p_track->fmt.audio.i_bitspersample = p_soun->i_samplesize;
373
374     p_track->fmt.i_original_fourcc = p_sample->i_type;
375
376     if( ( p_track->i_sample_size == 1 || p_track->i_sample_size == 2 ) )
377     {
378         if( p_soun->i_qt_version == 0 )
379         {
380             switch( p_sample->i_type )
381             {
382             case VLC_CODEC_ADPCM_IMA_QT:
383                 p_soun->i_qt_version = 1;
384                 p_soun->i_sample_per_packet = 64;
385                 p_soun->i_bytes_per_packet  = 34;
386                 p_soun->i_bytes_per_frame   = 34 * p_soun->i_channelcount;
387                 p_soun->i_bytes_per_sample  = 2;
388                 break;
389             case VLC_CODEC_MACE3:
390                 p_soun->i_qt_version = 1;
391                 p_soun->i_sample_per_packet = 6;
392                 p_soun->i_bytes_per_packet  = 2;
393                 p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;
394                 p_soun->i_bytes_per_sample  = 2;
395                 break;
396             case VLC_CODEC_MACE6:
397                 p_soun->i_qt_version = 1;
398                 p_soun->i_sample_per_packet = 12;
399                 p_soun->i_bytes_per_packet  = 2;
400                 p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;
401                 p_soun->i_bytes_per_sample  = 2;
402                 break;
403             case VLC_CODEC_ALAW:
404             case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
405                 p_soun->i_samplesize = 8;
406                 p_track->i_sample_size = p_soun->i_channelcount;
407                 break;
408             case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
409             case VLC_FOURCC( 'r', 'a', 'w', ' ' ):
410             case VLC_FOURCC( 't', 'w', 'o', 's' ):
411             case VLC_FOURCC( 's', 'o', 'w', 't' ):
412                 /* What would be the fun if you could trust the .mov */
413                 p_track->i_sample_size = ((p_soun->i_samplesize+7)/8) * p_soun->i_channelcount;
414                 break;
415             default:
416                 p_track->fmt.i_codec = p_sample->i_type;
417                 break;
418             }
419
420         }
421         else if( p_soun->i_qt_version == 1 && p_soun->i_sample_per_packet <= 0 )
422         {
423             p_soun->i_qt_version = 0;
424         }
425     }
426     else if( p_sample->data.p_sample_soun->i_qt_version == 1 )
427     {
428         switch( p_sample->i_type )
429         {
430         case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
431         case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
432         {
433             if( p_track->i_sample_size > 1 )
434                 p_soun->i_qt_version = 0;
435             break;
436         }
437         case( ATOM_ac3 ):
438         case( ATOM_eac3 ):
439         case( VLC_FOURCC( 'm', 's', 0x20, 0x00 ) ):
440             p_soun->i_qt_version = 0;
441             break;
442         default:
443             break;
444         }
445     }
446
447     if( p_track->i_sample_size != 0 && p_soun->i_qt_version == 1 &&
448         p_soun->i_sample_per_packet <= 0 )
449     {
450         msg_Err( p_demux, "Invalid sample per packet value for qt_version 1. Broken muxer!" );
451         p_soun->i_qt_version = 0;
452     }
453
454
455     /* Endianness atom */
456     const MP4_Box_t *p_enda = MP4_BoxGet( p_sample, "wave/enda" );
457     if( !p_enda )
458         p_enda = MP4_BoxGet( p_sample, "enda" );
459
460     /* It's a little ugly but .. there are special cases */
461     switch( p_sample->i_type )
462     {
463         case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
464         case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
465         {
466             p_track->fmt.i_codec = VLC_CODEC_MPGA;
467             break;
468         }
469         case( ATOM_eac3 ):
470         {
471             const MP4_Box_t *p_dec3 = MP4_BoxGet(  p_sample, "dec3", 0 );
472
473             p_track->fmt.i_codec = VLC_CODEC_EAC3;
474             if( p_dec3 && BOXDATA(p_dec3) )
475             {
476                 p_track->fmt.audio.i_channels = 0;
477                 p_track->fmt.i_bitrate = BOXDATA(p_dec3)->i_data_rate * 1000;
478                 p_track->fmt.audio.i_bitspersample = 0;
479             }
480             break;
481         }
482         case( ATOM_ac3 ):
483         {
484             MP4_Box_t *p_dac3 = MP4_BoxGet(  p_sample, "dac3", 0 );
485
486             p_track->fmt.i_codec = VLC_CODEC_A52;
487             if( p_dac3 && BOXDATA(p_dac3) )
488             {
489                 static const int pi_bitrate[] = {
490                      32,  40,  48,  56,
491                      64,  80,  96, 112,
492                     128, 160, 192, 224,
493                     256, 320, 384, 448,
494                     512, 576, 640,
495                 };
496                 p_track->fmt.audio.i_channels = 0;
497                 p_track->fmt.i_bitrate = 0;
498                 if( BOXDATA(p_dac3)->i_bitrate_code < sizeof(pi_bitrate)/sizeof(*pi_bitrate) )
499                     p_track->fmt.i_bitrate = pi_bitrate[BOXDATA(p_dac3)->i_bitrate_code] * 1000;
500                 p_track->fmt.audio.i_bitspersample = 0;
501             }
502             break;
503         }
504
505         case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):
506         case( VLC_FOURCC( 'N', 'O', 'N', 'E' ) ):
507         {
508             if( (p_soun->i_samplesize+7)/8 == 1 )
509                 p_track->fmt.i_codec = VLC_CODEC_U8;
510             else
511                 p_track->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
512
513             /* Buggy files workaround */
514             if( (p_track->i_timescale != p_soun->i_sampleratehi) )
515             {
516                 msg_Warn( p_demux, "i_timescale (%"PRId32") != i_sampleratehi "
517                           "(%u), making both equal (report any problem).",
518                           p_track->i_timescale, p_soun->i_sampleratehi );
519
520                 if( p_soun->i_sampleratehi != 0 )
521                     p_track->i_timescale = p_soun->i_sampleratehi;
522                 else
523                     p_soun->i_sampleratehi = p_track->i_timescale;
524             }
525             break;
526         }
527
528         case VLC_FOURCC('i','n','2','4'):
529             p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
530                                     VLC_FOURCC('4','2','n','i') : VLC_FOURCC('i','n','2','4');
531             break;
532         case VLC_FOURCC('i','n','3','2'):
533             p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
534                                     VLC_CODEC_S32L : VLC_CODEC_S32B;
535             break;
536         case VLC_FOURCC('f','l','3','2'):
537             p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
538                                     VLC_CODEC_F32L : VLC_CODEC_F32B;
539             break;
540         case VLC_FOURCC('f','l','6','4'):
541             p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
542                                     VLC_CODEC_F64L : VLC_CODEC_F64B;
543             break;
544
545         case VLC_CODEC_DVD_LPCM:
546         {
547             if( p_soun->i_qt_version == 2 )
548             {
549                 /* Flags:
550                  *  0x01: IsFloat
551                  *  0x02: IsBigEndian
552                  *  0x04: IsSigned
553                  */
554                 static const struct {
555                     unsigned     i_flags;
556                     unsigned     i_mask;
557                     unsigned     i_bits;
558                     vlc_fourcc_t i_codec;
559                 } p_formats[] = {
560                     { 0x01,           0x03, 32, VLC_CODEC_F32L },
561                     { 0x01,           0x03, 64, VLC_CODEC_F64L },
562                     { 0x01|0x02,      0x03, 32, VLC_CODEC_F32B },
563                     { 0x01|0x02,      0x03, 64, VLC_CODEC_F64B },
564
565                     { 0x00,           0x05,  8, VLC_CODEC_U8 },
566                     { 0x00|     0x04, 0x05,  8, VLC_CODEC_S8 },
567
568                     { 0x00,           0x07, 16, VLC_CODEC_U16L },
569                     { 0x00|0x02,      0x07, 16, VLC_CODEC_U16B },
570                     { 0x00     |0x04, 0x07, 16, VLC_CODEC_S16L },
571                     { 0x00|0x02|0x04, 0x07, 16, VLC_CODEC_S16B },
572
573                     { 0x00,           0x07, 24, VLC_CODEC_U24L },
574                     { 0x00|0x02,      0x07, 24, VLC_CODEC_U24B },
575                     { 0x00     |0x04, 0x07, 24, VLC_CODEC_S24L },
576                     { 0x00|0x02|0x04, 0x07, 24, VLC_CODEC_S24B },
577
578                     { 0x00,           0x07, 32, VLC_CODEC_U32L },
579                     { 0x00|0x02,      0x07, 32, VLC_CODEC_U32B },
580                     { 0x00     |0x04, 0x07, 32, VLC_CODEC_S32L },
581                     { 0x00|0x02|0x04, 0x07, 32, VLC_CODEC_S32B },
582
583                     {0, 0, 0, 0}
584                 };
585
586                 for( int i = 0; p_formats[i].i_codec; i++ )
587                 {
588                     if( p_formats[i].i_bits == p_soun->i_constbitsperchannel &&
589                         (p_soun->i_formatflags & p_formats[i].i_mask) == p_formats[i].i_flags )
590                     {
591                         p_track->fmt.i_codec = p_formats[i].i_codec;
592                         p_track->fmt.audio.i_bitspersample = p_soun->i_constbitsperchannel;
593                         p_track->fmt.audio.i_blockalign =
594                                 p_soun->i_channelcount * p_soun->i_constbitsperchannel / 8;
595                         p_track->i_sample_size = p_track->fmt.audio.i_blockalign;
596
597                         p_soun->i_qt_version = 0;
598                         break;
599                     }
600                 }
601             }
602             break;
603         }
604         default:
605             p_track->fmt.i_codec = p_sample->i_type;
606             break;
607     }
608
609
610     /* Process extensions */
611
612     /* Lookup for then channels extension */
613     const MP4_Box_t *p_chan = MP4_BoxGet( p_sample, "chan" );
614     if ( p_chan )
615     {
616         if ( BOXDATA(p_chan)->layout.i_channels_layout_tag == MP4_CHAN_USE_CHANNELS_BITMAP )
617         {
618             uint32_t rgi_chans_sequence[AOUT_CHAN_MAX + 1];
619             uint16_t i_vlc_mapping = 0;
620             uint8_t i_channels = 0;
621             const uint32_t i_bitmap = BOXDATA(p_chan)->layout.i_channels_bitmap;
622             for (uint8_t i=0;i<MP4_CHAN_BITMAP_MAPPING_COUNT;i++)
623             {
624                 if ( chan_bitmap_mapping[i].i_bitmap & i_bitmap )
625                 {
626                     i_channels++;
627                     if ( (chan_bitmap_mapping[i].i_vlc & i_vlc_mapping) ||
628                          i_channels > AOUT_CHAN_MAX )
629                     {
630                         /* double mapping or unsupported number of channels */
631                         i_vlc_mapping = 0;
632                         msg_Warn( p_demux, "discarding chan mapping" );
633                         break;
634                     }
635                     i_vlc_mapping |= chan_bitmap_mapping[i].i_vlc;
636                     rgi_chans_sequence[i_channels - 1] = chan_bitmap_mapping[i].i_vlc;
637                 }
638             }
639             rgi_chans_sequence[i_channels] = 0;
640             p_track->b_chans_reorder = !!
641                     aout_CheckChannelReorder( rgi_chans_sequence, NULL, i_vlc_mapping,
642                                               p_track->rgi_chans_reordering );
643         }
644
645     }
646
647     /* now see if esds is present and if so create a data packet
648         with decoder_specific_info  */
649     MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
650     if ( !p_esds ) p_esds = MP4_BoxGet( p_sample, "wave/esds" );
651     if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
652     {
653         assert(p_sample->i_type == ATOM_mp4a);
654         SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
655     }
656     else switch( p_sample->i_type )
657     {
658         case VLC_CODEC_AMR_NB:
659             p_track->fmt.audio.i_rate = 8000;
660             break;
661         case VLC_CODEC_AMR_WB:
662             p_track->fmt.audio.i_rate = 16000;
663             break;
664         case VLC_FOURCC( 'Q', 'D', 'M', 'C' ):
665         case VLC_CODEC_QDM2:
666         case VLC_CODEC_ALAC:
667         {
668             p_track->fmt.i_extra =
669                 p_sample->data.p_sample_soun->i_qt_description;
670             if( p_track->fmt.i_extra > 0 )
671             {
672                 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
673                 memcpy( p_track->fmt.p_extra,
674                         p_sample->data.p_sample_soun->p_qt_description,
675                         p_track->fmt.i_extra);
676             }
677             if( p_track->fmt.i_extra == 56 && p_sample->i_type == VLC_CODEC_ALAC )
678             {
679                 p_track->fmt.audio.i_channels = *((uint8_t*)p_track->fmt.p_extra + 41);
680                 p_track->fmt.audio.i_rate = GetDWBE((uint8_t*)p_track->fmt.p_extra + 52);
681             }
682             break;
683         }
684         case VLC_CODEC_ADPCM_MS:
685         case VLC_CODEC_ADPCM_IMA_WAV:
686         case VLC_CODEC_QCELP:
687         {
688             p_track->fmt.audio.i_blockalign = p_sample->data.p_sample_soun->i_bytes_per_frame;
689             break;
690         }
691         case ATOM_WMA2:
692         {
693             MP4_Box_t *p_WMA2 = MP4_BoxGet( p_sample, "wave/WMA2" );
694             if( p_WMA2 && BOXDATA(p_WMA2) )
695             {
696                 p_track->fmt.audio.i_channels = BOXDATA(p_WMA2)->Format.nChannels;
697                 p_track->fmt.audio.i_rate = BOXDATA(p_WMA2)->Format.nSamplesPerSec;
698                 p_track->fmt.i_bitrate = BOXDATA(p_WMA2)->Format.nAvgBytesPerSec * 8;
699                 p_track->fmt.audio.i_blockalign = BOXDATA(p_WMA2)->Format.nBlockAlign;
700                 p_track->fmt.audio.i_bitspersample = BOXDATA(p_WMA2)->Format.wBitsPerSample;
701                 p_track->fmt.i_extra = BOXDATA(p_WMA2)->i_extra;
702                 if( p_track->fmt.i_extra > 0 )
703                 {
704                     p_track->fmt.p_extra = malloc( BOXDATA(p_WMA2)->i_extra );
705                     memcpy( p_track->fmt.p_extra, BOXDATA(p_WMA2)->p_extra,
706                             p_track->fmt.i_extra );
707                 }
708                 p_track->p_asf = MP4_BoxGet( p_sample, "wave/ASF " );
709             }
710             else
711             {
712                 msg_Err( p_demux, "missing WMA2 %4.4s", (char*) &p_sample->p_father->i_type );
713             }
714             break;
715         }
716
717         default:
718             msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
719             break;
720     }
721
722     return 1;
723 }
724
725
726 int SetupSpuES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
727 {
728     MP4_Box_data_sample_text_t *p_text = p_sample->data.p_sample_text;
729
730     /* It's a little ugly but .. there are special cases */
731     switch( p_sample->i_type )
732     {
733         case( ATOM_c608 ): /* EIA608 closed captions */
734         //case( ATOM_c708 ): /* EIA708 closed captions */
735             p_track->fmt.i_codec = VLC_CODEC_EIA608_1;
736             p_track->fmt.i_cat = SPU_ES;
737             break;
738
739         case( VLC_FOURCC( 't', 'e', 'x', 't' ) ):
740         case( VLC_FOURCC( 't', 'x', '3', 'g' ) ):
741         {
742             p_track->fmt.i_codec = VLC_CODEC_TX3G;
743
744             text_style_t *p_style = text_style_New();
745             if ( p_style )
746             {
747                 if ( p_text->i_font_size ) /* !WARN: % in absolute storage */
748                     p_style->i_font_size = p_text->i_font_size;
749                 if ( p_text->i_font_color )
750                 {
751                     p_style->i_font_color = p_text->i_font_color >> 8;
752                     p_style->i_font_alpha = p_text->i_font_color & 0xFF;
753                 }
754                 if ( p_text->i_background_color[3] >> 8 )
755                 {
756                     p_style->i_background_color = p_text->i_background_color[0] >> 8;
757                     p_style->i_background_color |= p_text->i_background_color[1] >> 8;
758                     p_style->i_background_color |= p_text->i_background_color[2] >> 8;
759                     p_style->i_background_alpha = p_text->i_background_color[3] >> 8;
760                 }
761             }
762             p_track->fmt.subs.p_style = p_style;
763
764             /* FIXME UTF-8 doesn't work here ? */
765             if( p_track->b_mac_encoding )
766                 p_track->fmt.subs.psz_encoding = strdup( "MAC" );
767             else
768                 p_track->fmt.subs.psz_encoding = strdup( "UTF-8" );
769             break;
770         }
771
772         default:
773             p_track->fmt.i_codec = p_sample->i_type;
774             break;
775     }
776
777     /* now see if esds is present and if so create a data packet
778         with decoder_specific_info  */
779     MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
780     if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
781     {
782         SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
783     }
784
785     return 1;
786 }