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 "avci.h"
29 #include "../xiph.h"
30 #include "../../packetizer/iso_color_tables.h"
31 #include "mpeg4.h"
32 
33 #include <vlc_demux.h>
34 #include <vlc_aout.h>
35 #include <assert.h>
36 
37 
38 
39 
SetupGlobalExtensions(mp4_track_t * p_track,MP4_Box_t * p_sample)40 static void SetupGlobalExtensions( mp4_track_t *p_track, MP4_Box_t *p_sample )
41 {
42     if( !p_track->fmt.i_bitrate )
43     {
44         const MP4_Box_t *p_btrt = MP4_BoxGet( p_sample, "btrt" );
45         if( p_btrt && BOXDATA(p_btrt) )
46         {
47             p_track->fmt.i_bitrate = BOXDATA(p_btrt)->i_avg_bitrate;
48         }
49     }
50 }
51 
SetupESDS(demux_t * p_demux,mp4_track_t * p_track,const MP4_descriptor_decoder_config_t * p_decconfig)52 static void SetupESDS( demux_t *p_demux, mp4_track_t *p_track, const MP4_descriptor_decoder_config_t *p_decconfig )
53 {
54     /* First update information based on i_objectTypeIndication */
55     switch( p_decconfig->i_objectProfileIndication )
56     {
57         /* Private ID */
58     case( 0xe0 ): /* NeroDigital: dvd subs */
59         if( p_track->fmt.i_cat == SPU_ES )
60         {
61             p_track->fmt.i_codec = VLC_CODEC_SPU;
62             if( p_track->i_width > 0 )
63                 p_track->fmt.subs.spu.i_original_frame_width = p_track->i_width;
64             if( p_track->i_height > 0 )
65                 p_track->fmt.subs.spu.i_original_frame_height = p_track->i_height;
66         }
67         break;
68     case( 0xe1 ): /* QCelp for 3gp */
69         if( p_track->fmt.i_cat == AUDIO_ES )
70         {
71             p_track->fmt.i_codec = VLC_CODEC_QCELP;
72         }
73         break;
74 
75         /* Fallback */
76     default:
77         if( MPEG4_Codec_By_ObjectType( p_decconfig->i_objectProfileIndication,
78                                        p_decconfig->p_decoder_specific_info,
79                                        p_decconfig->i_decoder_specific_info_len,
80                                        &p_track->fmt.i_codec,
81                                        &p_track->fmt.i_profile ) )
82             break;
83         /* Unknown entry, but don't touch i_fourcc */
84         msg_Warn( p_demux,
85                   "unknown objectProfileIndication(0x%x) (Track[ID 0x%x])",
86                   p_decconfig->i_objectProfileIndication,
87                   p_track->i_track_ID );
88         return;
89     }
90 
91     p_track->fmt.i_original_fourcc = 0; /* so we don't have MP4A as original fourcc */
92     p_track->fmt.i_bitrate = p_decconfig->i_avg_bitrate;
93 
94     p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len;
95     if( p_track->fmt.i_extra > 0 )
96     {
97         p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
98         memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info,
99                 p_track->fmt.i_extra );
100     }
101     if( p_track->fmt.i_codec == VLC_CODEC_SPU &&
102             p_track->fmt.i_extra >= 16 * 4 )
103     {
104         for( int i = 0; i < 16; i++ )
105         {
106             p_track->fmt.subs.spu.palette[1 + i] =
107                     GetDWBE((char*)p_track->fmt.p_extra + i * 4);
108         }
109         p_track->fmt.subs.spu.palette[0] = SPU_PALETTE_DEFINED;
110     }
111 }
112 
SetupRTPReceptionHintTrack(demux_t * p_demux,mp4_track_t * p_track,MP4_Box_t * p_sample)113 static int SetupRTPReceptionHintTrack( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
114 {
115     p_track->fmt.i_original_fourcc = p_sample->i_type;
116 
117     if( !p_track->p_sdp )
118     {
119         msg_Err(p_demux, "Required 'sdp '-box not found");
120         return 0;
121     }
122     MP4_Box_t *p_sdp = p_track->p_sdp;
123     char *strtok_state;
124     char * pch = strtok_r(BOXDATA(p_sdp)->psz_text, " =\n", &strtok_state); /* media entry */
125     if( pch && pch[0] != 'm' )
126     {
127         msg_Err(p_demux, "No Media entry found in SDP:%s", pch);
128         return 0;
129     }
130 
131     if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* media type */
132         return 0;
133     /* media type has already been checked */
134     msg_Dbg(p_demux, "sdp: media type:%s", pch);
135     if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* port */
136         return 0;
137     msg_Dbg(p_demux, "sdp: port:%s", pch);
138     if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* protocol */
139         return 0;
140     msg_Dbg(p_demux, "sdp: protocol:%s", pch);
141 
142     if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* fmt */
143         return 0;
144 
145     bool codec_set = false;
146     /* process rtp types until we get an attribute field or end of sdp */
147     while( pch && pch[0] != 'a' )
148     {
149         int rtp_payload = atoi(pch);
150         msg_Dbg(p_demux, "sdp: payload type:%d", rtp_payload);
151 
152         if( !codec_set )
153         {
154             /* Payload types 34 and under have a set type and can be identified here */
155             switch( rtp_payload )
156             {
157              case 3:
158                 p_track->fmt.i_codec = VLC_CODEC_GSM;
159                 codec_set = true;
160                 break;
161              default:
162                 break;
163             }
164         }
165         pch = strtok_r(NULL, " =\n", &strtok_state); /* attribute or additional payload type */
166         if( !pch && !codec_set )
167             return 0;
168     }
169 
170     while( pch && pch[0] == 'a' )
171     {
172         if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* attribute type */
173             return 0;
174         msg_Dbg(p_demux, "sdp: atrribute type:%s", pch);
175 
176         if( !strcmp(pch, "rtpmap") )
177         {
178             if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* payload type */
179                 return 0;
180             msg_Dbg(p_demux, "sdp: payload type:%s", pch);
181             if( !(pch = strtok_r(NULL, " /:=\n", &strtok_state) ) ) /* encoding name */
182                 return 0;
183             msg_Dbg(p_demux, "sdp: encoding name:%s", pch);
184 
185             /* Simply adding codec recognition should work for most codecs */
186             /* Codecs using slices need their picture constructed from sample */
187             if( !strcmp(pch, "H264") )
188             {
189                 p_track->fmt.i_codec = VLC_CODEC_H264;
190                 /* ******* sending AnnexB ! */
191                 p_track->fmt.b_packetized = false;
192             }
193             else if( !strcmp(pch, "GSM") )
194             {
195                 p_track->fmt.i_codec = VLC_CODEC_GSM;
196             }
197             else if( !strcmp(pch, "Speex") )
198             {
199                 p_track->fmt.i_codec = VLC_CODEC_SPEEX;
200             }
201             else if( !codec_set )
202             {
203                 msg_Err(p_demux, "Support for codec contained in RTP \
204                         Reception Hint Track RTP stream has not been added");
205                 return 0;
206             }
207 
208             if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* clock rate */
209                 return 0;
210             int clock_rate = atoi(pch);
211             msg_Dbg(p_demux, "sdp clock rate:%d", clock_rate);
212             if( p_track->fmt.i_cat == AUDIO_ES )
213                 p_track->fmt.audio.i_rate = clock_rate;
214         }
215         pch = strtok_r(NULL, " =\n", &strtok_state); /* next attribute */
216     }
217 
218     const MP4_Box_t *p_tims = MP4_BoxGet(p_sample, "tims");
219     if( p_tims && BOXDATA(p_tims) && BOXDATA(p_tims)->i_timescale )
220     {
221         p_track->i_timescale = BOXDATA(p_tims)->i_timescale;
222     }
223     else
224     {
225         msg_Warn(p_demux, "Missing mandatory box tims");
226         return 0;
227     }
228 
229     const MP4_Box_t *p_tssy = MP4_BoxGet(p_sample, "tssy");
230     if( p_tssy && BOXDATA(p_tssy) )
231     {
232         /* take the 2 last bits which indicate the synchronization mode */
233         p_track->sync_mode = (RTP_timstamp_synchronization_t)
234                              BOXDATA(p_tssy)->i_reserved_timestamp_sync & 0x03;
235     }
236 
237     const MP4_Box_t *p_tsro = MP4_BoxGet(p_sample, "tsro");
238     if( p_tsro && BOXDATA(p_tsro) )
239         p_track->i_tsro_offset = BOXDATA(p_tsro)->i_offset;
240     else
241         msg_Dbg(p_demux, "No tsro box present");
242     msg_Dbg(p_demux, "setting tsro: %" PRId32, p_track->i_tsro_offset);
243 
244     return 1;
245 }
246 
247 
SetupVideoES(demux_t * p_demux,mp4_track_t * p_track,MP4_Box_t * p_sample)248 int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
249 {
250     MP4_Box_data_sample_vide_t *p_vide = p_sample->data.p_sample_vide;
251     if(!p_vide)
252         return 0;
253 
254     p_track->fmt.video.i_width = p_vide->i_width;
255     p_track->fmt.video.i_height = p_vide->i_height;
256     p_track->fmt.video.i_bits_per_pixel = p_vide->i_depth;
257 
258     /* fall on display size */
259     if( p_track->fmt.video.i_width <= 0 )
260         p_track->fmt.video.i_width = p_track->i_width;
261     if( p_track->fmt.video.i_height <= 0 )
262         p_track->fmt.video.i_height = p_track->i_height;
263 
264     /* Find out apect ratio from display size */
265     if( p_track->i_width > 0 && p_track->i_height > 0 &&
266         /* Work-around buggy muxed files */
267         p_vide->i_width != p_track->i_width )
268     {
269         p_track->fmt.video.i_sar_num = p_track->i_width  * p_track->fmt.video.i_height;
270         p_track->fmt.video.i_sar_den = p_track->i_height * p_track->fmt.video.i_width;
271     }
272 
273     /* Support for cropping (eg. in H263 files) */
274     p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
275     p_track->fmt.video.i_visible_height = p_track->fmt.video.i_height;
276 
277     /* Rotation */
278     switch( (int)p_track->f_rotation ) {
279         case 90:
280             p_track->fmt.video.orientation = ORIENT_ROTATED_90;
281             break;
282         case 180:
283             p_track->fmt.video.orientation = ORIENT_ROTATED_180;
284             break;
285         case 270:
286             p_track->fmt.video.orientation = ORIENT_ROTATED_270;
287             break;
288     }
289 
290     /* Set 360 video mode */
291     p_track->fmt.video.projection_mode = PROJECTION_MODE_RECTANGULAR;
292     const MP4_Box_t *p_uuid = MP4_BoxGet( p_track->p_track, "uuid" );
293     for( ; p_uuid; p_uuid = p_uuid->p_next)
294     {
295         if( p_uuid->i_type == ATOM_uuid
296             && !CmpUUID( &p_uuid->i_uuid, &XML360BoxUUID )
297             && p_uuid->data.p_360 )
298         {
299             p_track->fmt.video.projection_mode = p_uuid->data.p_360->i_projection_mode;
300             switch (p_uuid->data.p_360->e_stereo_mode)
301             {
302             case XML360_STEREOSCOPIC_TOP_BOTTOM:
303                 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;
304                 break;
305             case XML360_STEREOSCOPIC_LEFT_RIGHT:
306                 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS;
307                 break;
308             default:
309                 p_track->fmt.video.multiview_mode = MULTIVIEW_2D;
310                 break;
311             }
312         }
313     }
314 
315     const MP4_Box_t *p_st3d = MP4_BoxGet( p_sample, "st3d" );
316     if (p_st3d && BOXDATA(p_st3d))
317     {
318         switch( BOXDATA(p_st3d)->i_stereo_mode )
319         {
320         case ST3D_MONOSCOPIC:
321             p_track->fmt.video.multiview_mode = MULTIVIEW_2D;
322             break;
323         case ST3D_STEREOSCOPIC_TOP_BOTTOM:
324             p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;
325             break;
326         case ST3D_STEREOSCOPIC_LEFT_RIGHT:
327             p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS;
328             break;
329         default:
330             msg_Warn( p_demux, "Unknown stereo mode %d", BOXDATA(p_st3d)->i_stereo_mode );
331             break;
332         }
333     }
334     else
335     {
336         for( p_uuid = MP4_BoxGet( p_sample, "uuid" ); p_uuid;
337              p_uuid = p_uuid->p_next )
338         {
339             if( p_uuid->i_type == ATOM_uuid &&
340                !CmpUUID( &p_uuid->i_uuid, &PS3DDSBoxUUID ) &&
341                 p_uuid->data.p_binary &&
342                 p_uuid->data.p_binary->i_blob == 4 &&
343                 !memcmp( p_uuid->data.p_binary->p_blob, "\x82\x81\x10\x02", 4 ) )
344             {
345                 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_FRAME;
346                 break;
347             }
348         }
349     }
350 
351     const MP4_Box_t *p_prhd = MP4_BoxGet( p_sample, "sv3d/proj/prhd" );
352     if (p_prhd && BOXDATA(p_prhd))
353     {
354         p_track->fmt.video.pose.yaw = BOXDATA(p_prhd)->f_pose_yaw_degrees;
355         p_track->fmt.video.pose.pitch = BOXDATA(p_prhd)->f_pose_pitch_degrees;
356         p_track->fmt.video.pose.roll = BOXDATA(p_prhd)->f_pose_roll_degrees;
357     }
358 
359     const MP4_Box_t *p_equi = MP4_BoxGet( p_sample, "sv3d/proj/equi" );
360     const MP4_Box_t *p_cbmp = MP4_BoxGet( p_sample, "sv3d/proj/cbmp" );
361     if (p_equi && BOXDATA(p_equi))
362         p_track->fmt.video.projection_mode = PROJECTION_MODE_EQUIRECTANGULAR;
363     else if (p_cbmp && BOXDATA(p_cbmp))
364         p_track->fmt.video.projection_mode = PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD;
365 
366     /* It's a little ugly but .. there are special cases */
367     switch( p_sample->i_type )
368     {
369         case( VLC_FOURCC( 's', '2', '6', '3' ) ):
370             p_track->fmt.i_codec = VLC_CODEC_H263;
371             break;
372         case VLC_FOURCC('y','v','1','2'):
373             p_track->fmt.i_codec = VLC_CODEC_YV12;
374             break;
375         case VLC_FOURCC('y','u','v','2'):
376             p_track->fmt.i_codec = VLC_CODEC_YUYV;
377             break;
378         case VLC_FOURCC('r','a','w',' '):
379             switch( p_vide->i_depth ) {
380                 case 16:
381                     p_track->fmt.i_codec = VLC_CODEC_RGB15;
382                     break;
383                 case 24:
384                     p_track->fmt.i_codec = VLC_CODEC_RGB24;
385                     break;
386                 case 32:
387                     p_track->fmt.i_codec = VLC_CODEC_ARGB;
388                     break;
389                 case 32 + 8:
390                     p_track->fmt.i_codec = VLC_CODEC_GREY;
391                     break;
392                 default:
393                     msg_Dbg( p_demux, "Unrecognized raw video format (depth = %d)",
394                              p_vide->i_depth );
395                     p_track->fmt.i_codec = p_sample->i_type;
396                     break;
397             }
398             break;
399         case( VLC_FOURCC( 'r', 'r', 't', 'p' ) ): /* RTP Reception Hint Track */
400         {
401             if( !SetupRTPReceptionHintTrack( p_demux, p_track, p_sample ) )
402                 p_track->fmt.i_codec = p_sample->i_type;
403             break;
404         }
405         default:
406             p_track->fmt.i_codec = p_sample->i_type;
407             break;
408     }
409 
410 
411     /* Read extensions */
412 
413     /* Set up A/R from extension atom */
414     const MP4_Box_t *p_pasp = MP4_BoxGet( p_sample, "pasp" );
415     if( p_pasp && BOXDATA(p_pasp) && BOXDATA(p_pasp)->i_horizontal_spacing > 0 &&
416                   BOXDATA(p_pasp)->i_vertical_spacing > 0 )
417     {
418         p_track->fmt.video.i_sar_num = BOXDATA(p_pasp)->i_horizontal_spacing;
419         p_track->fmt.video.i_sar_den = BOXDATA(p_pasp)->i_vertical_spacing;
420     }
421 
422     const MP4_Box_t *p_fiel = MP4_BoxGet( p_sample, "fiel" );
423     if( p_fiel && BOXDATA(p_fiel) )
424     {
425         p_track->i_block_flags = BOXDATA(p_fiel)->i_flags;
426     }
427 
428     const MP4_Box_t *p_colr = MP4_BoxGet( p_sample, "colr" );
429     if ( p_colr != NULL )
430     {
431         if ( BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'c' ) ||
432              BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'x' ) )
433         {
434             p_track->fmt.video.primaries =
435                     iso_23001_8_cp_to_vlc_primaries( BOXDATA( p_colr )->nclc.i_primary_idx );
436             p_track->fmt.video.transfer =
437                     iso_23001_8_tc_to_vlc_xfer( BOXDATA( p_colr )->nclc.i_transfer_function_idx );
438             p_track->fmt.video.space =
439                     iso_23001_8_mc_to_vlc_coeffs( BOXDATA( p_colr )->nclc.i_matrix_idx );
440             p_track->fmt.video.b_color_range_full = BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'x' ) &&
441                     (BOXDATA(p_colr)->nclc.i_full_range >> 7) != 0;
442         }
443     }
444 
445     SetupGlobalExtensions( p_track, p_sample );
446 
447     /* now see if esds is present and if so create a data packet
448         with decoder_specific_info  */
449     MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
450     if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
451     {
452         assert(p_sample->i_type == ATOM_mp4v);
453         SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
454     }
455     else switch( p_sample->i_type )
456     {
457         /* qt decoder, send the complete chunk */
458         case VLC_FOURCC ('h', 'd', 'v', '1'): // HDV 720p30
459         case VLC_FOURCC ('h', 'd', 'v', '2'): // HDV 1080i60
460         case VLC_FOURCC ('h', 'd', 'v', '3'): // HDV 1080i50
461         case VLC_FOURCC ('h', 'd', 'v', '5'): // HDV 720p25
462         case VLC_FOURCC ('m', 'x', '5', 'n'): // MPEG2 IMX NTSC 525/60 50mb/s produced by FCP
463         case VLC_FOURCC ('m', 'x', '5', 'p'): // MPEG2 IMX PAL 625/60 50mb/s produced by FCP
464         case VLC_FOURCC ('m', 'x', '4', 'n'): // MPEG2 IMX NTSC 525/60 40mb/s produced by FCP
465         case VLC_FOURCC ('m', 'x', '4', 'p'): // MPEG2 IMX PAL 625/60 40mb/s produced by FCP
466         case VLC_FOURCC ('m', 'x', '3', 'n'): // MPEG2 IMX NTSC 525/60 30mb/s produced by FCP
467         case VLC_FOURCC ('m', 'x', '3', 'p'): // MPEG2 IMX PAL 625/50 30mb/s produced by FCP
468         case VLC_FOURCC ('x', 'd', 'v', '2'): // XDCAM HD 1080i60
469         case VLC_FOURCC ('A', 'V', 'm', 'p'): // AVID IMX PAL
470             p_track->fmt.i_codec = VLC_CODEC_MPGV;
471             break;
472         /* qt decoder, send the complete chunk */
473         case VLC_CODEC_SVQ1:
474         case VLC_CODEC_SVQ3:
475         case VLC_FOURCC( 'V', 'P', '3', '1' ):
476         case VLC_FOURCC( '3', 'I', 'V', '1' ):
477         case VLC_FOURCC( 'Z', 'y', 'G', 'o' ):
478         {
479             p_track->fmt.i_extra =
480                 p_sample->data.p_sample_vide->i_qt_image_description;
481             if( p_track->fmt.i_extra > 0 )
482             {
483                 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
484                 memcpy( p_track->fmt.p_extra,
485                         p_sample->data.p_sample_vide->p_qt_image_description,
486                         p_track->fmt.i_extra);
487             }
488             break;
489         }
490 
491         case VLC_FOURCC('j', 'p', 'e', 'g'):
492             p_track->fmt.i_codec = VLC_CODEC_MJPG;
493            break;
494 
495         case VLC_CODEC_FFV1:
496         {
497             MP4_Box_t *p_binary = MP4_BoxGet( p_sample, "glbl" );
498             if( p_binary && BOXDATA(p_binary) && BOXDATA(p_binary)->i_blob )
499             {
500                 p_track->fmt.p_extra = malloc( BOXDATA(p_binary)->i_blob );
501                 if( p_track->fmt.p_extra )
502                 {
503                     p_track->fmt.i_extra = BOXDATA(p_binary)->i_blob;
504                     memcpy( p_track->fmt.p_extra, BOXDATA(p_binary)->p_blob,
505                             p_track->fmt.i_extra );
506                 }
507             }
508             break;
509         }
510 
511         case VLC_FOURCC( 'v', 'c', '-', '1' ):
512         {
513             MP4_Box_t *p_dvc1 = MP4_BoxGet( p_sample, "dvc1" );
514             if( p_dvc1 && BOXDATA(p_dvc1) )
515             {
516                 p_track->fmt.i_extra = BOXDATA(p_dvc1)->i_vc1;
517                 if( p_track->fmt.i_extra > 0 )
518                 {
519                     p_track->fmt.p_extra = malloc( BOXDATA(p_dvc1)->i_vc1 );
520                     memcpy( p_track->fmt.p_extra, BOXDATA(p_dvc1)->p_vc1,
521                             p_track->fmt.i_extra );
522                 }
523             }
524             else
525             {
526                 msg_Err( p_demux, "missing dvc1" );
527             }
528             break;
529         }
530 
531         case ATOM_av01:
532         {
533             static_assert(ATOM_av01 == VLC_CODEC_AV1, "VLC_CODEC_AV1 != ATOM_av01");
534             MP4_Box_t *p_av1C = MP4_BoxGet( p_sample, "av1C" );
535             if( p_av1C && BOXDATA(p_av1C) )
536             {
537                 p_track->fmt.i_profile = BOXDATA(p_av1C)->i_profile;
538                 p_track->fmt.i_level = BOXDATA(p_av1C)->i_level;
539                 if( BOXDATA(p_av1C)->i_av1C )
540                 {
541                     p_track->fmt.p_extra = malloc( BOXDATA(p_av1C)->i_av1C );
542                     if( p_track->fmt.p_extra )
543                     {
544                         memcpy( p_track->fmt.p_extra, BOXDATA(p_av1C)->p_av1C,
545                                 BOXDATA(p_av1C)->i_av1C );
546                         p_track->fmt.i_extra = BOXDATA(p_av1C)->i_av1C;
547                     }
548                 }
549             }
550             break;
551         }
552 
553         /* avc1: send avcC (h264 without annexe B, ie without start code)*/
554         case VLC_FOURCC( 'a', 'v', 'c', '3' ):
555         case VLC_FOURCC( 'a', 'v', 'c', '1' ):
556         case VLC_FOURCC( 'd', 'v', 'a', '1' ): /* DolbyVision */
557         case VLC_FOURCC( 'd', 'v', 'a', 'v' ): /* DolbyVision */
558         {
559             MP4_Box_t *p_avcC = MP4_BoxGet( p_sample, "avcC" );
560 
561             if( p_avcC && BOXDATA(p_avcC) )
562             {
563                 p_track->fmt.i_extra = BOXDATA(p_avcC)->i_avcC;
564                 if( p_track->fmt.i_extra > 0 )
565                 {
566                     p_track->fmt.p_extra = malloc( BOXDATA(p_avcC)->i_avcC );
567                     memcpy( p_track->fmt.p_extra, BOXDATA(p_avcC)->p_avcC,
568                             p_track->fmt.i_extra );
569                 }
570             }
571             else
572             {
573                 msg_Err( p_demux, "missing avcC" );
574             }
575             break;
576         }
577         case VLC_FOURCC( 'h', 'v', 'c', '1' ):
578         case VLC_FOURCC( 'h', 'e', 'v', '1' ):
579         case VLC_FOURCC( 'd', 'v', 'h', 'e' ): /* DolbyVision */
580         case VLC_FOURCC( 'd', 'v', 'h', '1' ): /* DolbyVision */
581         {
582             MP4_Box_t *p_hvcC = MP4_BoxGet( p_sample, "hvcC" );
583 
584             /* Handle DV fourcc collision at demux level */
585             if( p_sample->i_type == VLC_FOURCC( 'd', 'v', 'h', '1' ) )
586                 p_track->fmt.i_codec = VLC_FOURCC( 'd', 'v', 'h', 'e' );
587 
588             if( p_hvcC && p_hvcC->data.p_binary && p_hvcC->data.p_binary->i_blob )
589             {
590                 p_track->fmt.p_extra = malloc( p_hvcC->data.p_binary->i_blob );
591                 if( p_track->fmt.p_extra )
592                 {
593                     p_track->fmt.i_extra = p_hvcC->data.p_binary->i_blob;
594                     memcpy( p_track->fmt.p_extra, p_hvcC->data.p_binary->p_blob,
595                             p_hvcC->data.p_binary->i_blob );
596                 }
597             }
598             else
599             {
600                 msg_Err( p_demux, "missing hvcC" );
601             }
602             break;
603         }
604 
605         case ATOM_vp08:
606         case ATOM_vp09:
607         case ATOM_vp10:
608         {
609             const MP4_Box_t *p_vpcC = MP4_BoxGet(  p_sample, "vpcC" );
610             if( p_vpcC && BOXDATA(p_vpcC) )
611             {
612                 const MP4_Box_data_vpcC_t *p_data = BOXDATA(p_vpcC);
613                 if( p_sample->i_type == ATOM_vp10 )
614                     p_track->fmt.i_codec = VLC_CODEC_VP10;
615                 else if( p_sample->i_type == ATOM_vp09 )
616                     p_track->fmt.i_codec = VLC_CODEC_VP9;
617                 else
618                     p_track->fmt.i_codec = VLC_CODEC_VP8;
619                 p_track->fmt.i_profile = p_data->i_profile;
620                 p_track->fmt.i_level = p_data->i_level;
621 
622                 if( p_data->i_version == 0 ) /* old deprecated */
623                 {
624                     const uint8_t colorspacesmapping[] =
625                     {
626                         COLOR_SPACE_UNDEF,
627                         COLOR_SPACE_BT601,
628                         COLOR_SPACE_BT709,
629                         COLOR_SPACE_SMPTE_170,
630                         COLOR_SPACE_SMPTE_240,
631                         COLOR_SPACE_BT2020,
632                         COLOR_SPACE_BT2020,
633                         COLOR_SPACE_SRGB,
634                     };
635                     if( p_data->i_color_primaries < ARRAY_SIZE(colorspacesmapping) )
636                         p_track->fmt.video.space = colorspacesmapping[p_data->i_color_primaries];
637 
638                     if( p_data->i_xfer_function == 0 )
639                         p_track->fmt.video.transfer = TRANSFER_FUNC_BT709;
640                     else if ( p_data->i_xfer_function == 1 )
641                         p_track->fmt.video.transfer = TRANSFER_FUNC_SMPTE_ST2084;
642                 }
643                 else
644                 {
645                     p_track->fmt.video.primaries =
646                             iso_23001_8_cp_to_vlc_primaries( p_data->i_color_primaries );
647                     p_track->fmt.video.transfer =
648                             iso_23001_8_tc_to_vlc_xfer( p_data->i_xfer_function );
649                     p_track->fmt.video.space =
650                             iso_23001_8_mc_to_vlc_coeffs( p_data->i_matrix_coeffs );
651                 }
652 
653                 p_track->fmt.video.b_color_range_full = p_data->i_fullrange;
654                 p_track->fmt.video.i_bits_per_pixel = p_data->i_bit_depth;
655 
656                 if( p_data->i_codec_init_datasize )
657                 {
658                     p_track->fmt.p_extra = malloc( p_data->i_codec_init_datasize );
659                     if( p_track->fmt.p_extra )
660                     {
661                         p_track->fmt.i_extra = p_data->i_codec_init_datasize;
662                         memcpy( p_track->fmt.p_extra, p_data->p_codec_init_data,
663                                 p_data->i_codec_init_datasize );
664                     }
665                 }
666 
667                 const MP4_Box_t *p_SmDm = MP4_BoxGet( p_sample, "SmDm" );
668                 if( p_SmDm && BOXDATA(p_SmDm) )
669                 {
670                     memcpy( p_track->fmt.video.mastering.primaries,
671                             BOXDATA(p_SmDm)->primaries, sizeof(uint16_t) * 6 );
672                     memcpy( p_track->fmt.video.mastering.white_point,
673                             BOXDATA(p_SmDm)->white_point, sizeof(uint16_t) * 2 );
674                     p_track->fmt.video.mastering.max_luminance = BOXDATA(p_SmDm)->i_luminanceMax;
675                     p_track->fmt.video.mastering.min_luminance = BOXDATA(p_SmDm)->i_luminanceMin;
676                 }
677 
678                 const MP4_Box_t *p_CoLL = MP4_BoxGet( p_sample, "CoLL" );
679                 if( p_CoLL && BOXDATA(p_CoLL) )
680                 {
681                     p_track->fmt.video.lighting.MaxCLL = BOXDATA(p_CoLL)->i_maxCLL;
682                     p_track->fmt.video.lighting.MaxFALL = BOXDATA(p_CoLL)->i_maxFALL;
683                 }
684             }
685         }
686         break;
687 
688         case ATOM_WMV3:
689             p_track->p_asf = MP4_BoxGet( p_sample, "ASF " );
690             /* fallthrough */
691         case ATOM_H264:
692         case VLC_FOURCC('W','V','C','1'):
693         {
694             MP4_Box_t *p_strf = MP4_BoxGet(  p_sample, "strf", 0 );
695             if ( p_strf && BOXDATA(p_strf) )
696             {
697                 p_track->fmt.video.i_width = BOXDATA(p_strf)->bmiHeader.biWidth;
698                 p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
699                 p_track->fmt.video.i_height = BOXDATA(p_strf)->bmiHeader.biHeight;
700                 p_track->fmt.video.i_visible_height =p_track->fmt.video.i_height;
701                 p_track->fmt.video.i_bits_per_pixel = BOXDATA(p_strf)->bmiHeader.biBitCount;
702                 p_track->fmt.i_extra = BOXDATA(p_strf)->i_extra;
703                 if( p_track->fmt.i_extra > 0 )
704                 {
705                     p_track->fmt.p_extra = malloc( BOXDATA(p_strf)->i_extra );
706                     memcpy( p_track->fmt.p_extra, BOXDATA(p_strf)->p_extra,
707                             p_track->fmt.i_extra );
708                 }
709             }
710             break;
711         }
712 
713         case VLC_FOURCC( 'a', 'i', '5', 'p' ):
714         case VLC_FOURCC( 'a', 'i', '5', 'q' ):
715         case VLC_FOURCC( 'a', 'i', '5', '2' ):
716         case VLC_FOURCC( 'a', 'i', '5', '3' ):
717         case VLC_FOURCC( 'a', 'i', '5', '5' ):
718         case VLC_FOURCC( 'a', 'i', '5', '6' ):
719         case VLC_FOURCC( 'a', 'i', '1', 'p' ):
720         case VLC_FOURCC( 'a', 'i', '1', 'q' ):
721         case VLC_FOURCC( 'a', 'i', '1', '2' ):
722         case VLC_FOURCC( 'a', 'i', '1', '3' ):
723         case VLC_FOURCC( 'a', 'i', '1', '5' ):
724         case VLC_FOURCC( 'a', 'i', '1', '6' ):
725         {
726             if( !p_track->fmt.i_extra && p_track->fmt.video.i_width < UINT16_MAX &&
727                 p_fiel && BOXDATA(p_fiel) )
728             {
729                 p_track->fmt.p_extra =
730                         AVCi_create_AnnexB( p_track->fmt.video.i_width,
731                                             !!BOXDATA(p_fiel)->i_flags, &p_track->fmt.i_extra );
732             }
733             break;
734         }
735 
736         default:
737             msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
738             break;
739     }
740 
741     return 1;
742 }
743 
SetupAudioFromWaveFormatEx(es_format_t * p_fmt,const MP4_Box_t * p_WMA2)744 static bool SetupAudioFromWaveFormatEx( es_format_t *p_fmt, const MP4_Box_t *p_WMA2 )
745 {
746     if( p_WMA2 && BOXDATA(p_WMA2) )
747     {
748         wf_tag_to_fourcc(BOXDATA(p_WMA2)->Format.wFormatTag, &p_fmt->i_codec, NULL);
749         p_fmt->audio.i_channels = BOXDATA(p_WMA2)->Format.nChannels;
750         p_fmt->audio.i_rate = BOXDATA(p_WMA2)->Format.nSamplesPerSec;
751         p_fmt->i_bitrate = BOXDATA(p_WMA2)->Format.nAvgBytesPerSec * 8;
752         p_fmt->audio.i_blockalign = BOXDATA(p_WMA2)->Format.nBlockAlign;
753         p_fmt->audio.i_bitspersample = BOXDATA(p_WMA2)->Format.wBitsPerSample;
754         p_fmt->i_extra = BOXDATA(p_WMA2)->i_extra;
755         if( p_fmt->i_extra > 0 )
756         {
757             p_fmt->p_extra = malloc( BOXDATA(p_WMA2)->i_extra );
758             memcpy( p_fmt->p_extra, BOXDATA(p_WMA2)->p_extra, p_fmt->i_extra );
759         }
760         return true;
761     }
762     return false;
763 }
764 
SetupAudioES(demux_t * p_demux,mp4_track_t * p_track,MP4_Box_t * p_sample)765 int SetupAudioES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
766 {
767     MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;
768     if(!p_soun)
769         return 0;
770 
771     p_track->fmt.audio.i_channels = p_soun->i_channelcount;
772     p_track->fmt.audio.i_rate = p_soun->i_sampleratehi;
773     p_track->fmt.i_bitrate = p_soun->i_channelcount * p_soun->i_sampleratehi *
774                              p_soun->i_samplesize;
775     p_track->fmt.audio.i_bitspersample = p_soun->i_samplesize;
776 
777     p_track->fmt.i_original_fourcc = p_sample->i_type;
778 
779     if( ( p_track->i_sample_size == 1 || p_track->i_sample_size == 2 ) )
780     {
781         if( p_soun->i_qt_version == 0 )
782         {
783             switch( p_sample->i_type )
784             {
785             case VLC_CODEC_ADPCM_IMA_QT:
786                 p_soun->i_qt_version = 1;
787                 p_soun->i_sample_per_packet = 64;
788                 p_soun->i_bytes_per_packet  = 34;
789                 p_soun->i_bytes_per_frame   = 34 * p_soun->i_channelcount;
790                 p_soun->i_bytes_per_sample  = 2;
791                 break;
792             case VLC_CODEC_MACE3:
793                 p_soun->i_qt_version = 1;
794                 p_soun->i_sample_per_packet = 6;
795                 p_soun->i_bytes_per_packet  = 2;
796                 p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;
797                 p_soun->i_bytes_per_sample  = 2;
798                 break;
799             case VLC_CODEC_MACE6:
800                 p_soun->i_qt_version = 1;
801                 p_soun->i_sample_per_packet = 12;
802                 p_soun->i_bytes_per_packet  = 2;
803                 p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;
804                 p_soun->i_bytes_per_sample  = 2;
805                 break;
806             default:
807                 p_track->fmt.i_codec = p_sample->i_type;
808                 break;
809             }
810 
811         }
812         else if( p_soun->i_qt_version == 1 && p_soun->i_sample_per_packet <= 0 )
813         {
814             p_soun->i_qt_version = 0;
815         }
816     }
817     else if( p_sample->data.p_sample_soun->i_qt_version == 1 )
818     {
819         switch( p_sample->i_type )
820         {
821         case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
822         case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
823         {
824             if( p_track->i_sample_size > 1 )
825                 p_soun->i_qt_version = 0;
826             break;
827         }
828         case( ATOM_ac3 ):
829         case( ATOM_eac3 ):
830         case( VLC_FOURCC( 'm', 's', 0x20, 0x00 ) ):
831             p_soun->i_qt_version = 0;
832             break;
833         default:
834             break;
835         }
836 
837         if ( p_sample->data.p_sample_soun->i_compressionid == 0xFFFE /* -2 */)
838         {
839             /* redefined sample tables for vbr audio */
840         }
841         else if ( p_track->i_sample_size != 0 && p_soun->i_sample_per_packet == 0 )
842         {
843             msg_Err( p_demux, "Invalid sample per packet value for qt_version 1. Broken muxer! %u %u",
844                      p_track->i_sample_size, p_soun->i_sample_per_packet );
845             p_soun->i_qt_version = 0;
846         }
847     }
848 
849     /* Endianness atom */
850     const MP4_Box_t *p_enda = MP4_BoxGet( p_sample, "wave/enda" );
851     if( !p_enda )
852         p_enda = MP4_BoxGet( p_sample, "enda" );
853 
854     /* It's a little ugly but .. there are special cases */
855     switch( p_sample->i_type )
856     {
857         case( VLC_FOURCC( 'r', 'r', 't', 'p' ) ): /* RTP Reception Hint Track */
858         {
859             if( !SetupRTPReceptionHintTrack( p_demux, p_track, p_sample ) )
860                 return 0;
861             break;
862         }
863         case ATOM_agsm: /* Apple gsm 33 bytes != MS GSM (agsm fourcc, 65 bytes) */
864             p_track->fmt.i_codec = VLC_CODEC_GSM;
865             break;
866         case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
867         case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
868         {
869             p_track->fmt.i_codec = VLC_CODEC_MP3;
870             p_track->fmt.b_packetized = false;
871             break;
872         }
873         case ATOM_XiVs:
874         {
875             const MP4_Box_t *p_vCtH = MP4_BoxGet( p_sample, "wave/vCtH" ); /* kCookieTypeVorbisHeader */
876             const MP4_Box_t *p_vCtd = MP4_BoxGet( p_sample, "wave/vCt#" ); /* kCookieTypeVorbisComments */
877             const MP4_Box_t *p_vCtC = MP4_BoxGet( p_sample, "wave/vCtC" ); /* kCookieTypeVorbisCodebooks */
878             if( p_vCtH && p_vCtH->data.p_binary &&
879                 p_vCtd && p_vCtd->data.p_binary &&
880                 p_vCtC && p_vCtC->data.p_binary )
881             {
882                 unsigned headers_sizes[3] = {
883                     p_vCtH->data.p_binary->i_blob,
884                     p_vCtd->data.p_binary->i_blob,
885                     p_vCtC->data.p_binary->i_blob
886                 };
887 
888                 const void * headers[3] = {
889                     p_vCtH->data.p_binary->p_blob,
890                     p_vCtd->data.p_binary->p_blob,
891                     p_vCtC->data.p_binary->p_blob
892                 };
893 
894                 if( xiph_PackHeaders( &p_track->fmt.i_extra, &p_track->fmt.p_extra,
895                                       headers_sizes, headers, 3 ) == VLC_SUCCESS )
896                 {
897                     p_track->fmt.i_codec = VLC_CODEC_VORBIS;
898                     p_track->fmt.b_packetized = false;
899                 }
900             }
901             break;
902         }
903         case ATOM_XiFL:
904         {
905             const MP4_Box_t *p_fCtS = MP4_BoxGet( p_sample, "wave/fCtS" ); /* kCookieTypeFLACStreaminfo */
906             if( p_fCtS && p_fCtS->data.p_binary )
907             {
908                 size_t i_extra = 8 + p_fCtS->data.p_binary->i_blob;
909                 uint8_t *p_extra = malloc(i_extra);
910                 if( p_extra )
911                 {
912                     p_track->fmt.i_extra = i_extra;
913                     p_track->fmt.p_extra = p_extra;
914                     memcpy( p_extra, "fLaC", 4 );
915                     SetDWBE( &p_extra[4], p_fCtS->data.p_binary->i_blob ); /* want the lowest 24bits */
916                     p_extra[4] = 0x80; /* 0x80 Last metablock | 0x00 StreamInfo */
917                     memcpy( &p_extra[8], p_fCtS->data.p_binary->p_blob, p_fCtS->data.p_binary->i_blob );
918 
919                     p_track->fmt.i_codec = VLC_CODEC_FLAC;
920                     p_track->fmt.b_packetized = false;
921                 }
922             }
923             break;
924         }
925         case ATOM_fLaC:
926         {
927             const MP4_Box_t *p_dfLa = MP4_BoxGet(  p_sample, "dfLa", 0 );
928             if( p_dfLa && p_dfLa->data.p_binary->i_blob > 4 &&
929                 GetDWBE(p_dfLa->data.p_binary->p_blob) == 0 ) /* fullbox header, avoids creating dedicated parser */
930             {
931                 size_t i_extra = p_dfLa->data.p_binary->i_blob;
932                 uint8_t *p_extra = malloc(i_extra);
933                 if( likely( p_extra ) )
934                 {
935                     p_track->fmt.i_extra = i_extra;
936                     p_track->fmt.p_extra = p_extra;
937                     memcpy( p_extra, p_dfLa->data.p_binary->p_blob, p_dfLa->data.p_binary->i_blob);
938                     memcpy( p_extra, "fLaC", 4 );
939                     p_track->fmt.i_codec = VLC_CODEC_FLAC;
940                 }
941             }
942             break;
943         }
944         case( ATOM_eac3 ):
945         {
946             p_track->fmt.i_codec = VLC_CODEC_EAC3;
947             /* TS 102.366. F6 The values of the ChannelCount and SampleSize fields
948              *             within the EC3SampleEntry Box shall be ignored. */
949             p_track->fmt.audio.i_channels = 0;
950             p_track->fmt.audio.i_bitspersample = 0;
951 
952             const MP4_Box_t *p_dec3 = MP4_BoxGet(  p_sample, "dec3", 0 );
953             if( p_dec3 && BOXDATA(p_dec3) )
954             {
955                 p_track->fmt.i_bitrate = BOXDATA(p_dec3)->i_data_rate * 1000;
956             }
957             break;
958         }
959         case( ATOM_AC3 ):
960         case( ATOM_ac3 ):
961         {
962             p_track->fmt.i_codec = VLC_CODEC_A52;
963             /* TS 102.366. F3 The values of the ChannelCount and SampleSize fields
964              *             within the AC3SampleEntry Box shall be ignored */
965             p_track->fmt.audio.i_channels = 0;
966             p_track->fmt.audio.i_bitspersample = 0;
967 
968             MP4_Box_t *p_dac3 = MP4_BoxGet(  p_sample, "dac3", 0 );
969             if( p_dac3 && BOXDATA(p_dac3) )
970             {
971                 static const int pi_bitrate[] = {
972                      32,  40,  48,  56,
973                      64,  80,  96, 112,
974                     128, 160, 192, 224,
975                     256, 320, 384, 448,
976                     512, 576, 640,
977                 };
978                 p_track->fmt.i_bitrate = 0;
979                 if( BOXDATA(p_dac3)->i_bitrate_code < sizeof(pi_bitrate)/sizeof(*pi_bitrate) )
980                     p_track->fmt.i_bitrate = pi_bitrate[BOXDATA(p_dac3)->i_bitrate_code] * 1000;
981             }
982             break;
983         }
984 
985         case ATOM_dtse: /* DTS‐HD Lossless formats */
986         case ATOM_dtsh: /* DTS‐HD audio formats */
987         case ATOM_dtsl: /* DTS‐HD Lossless formats */
988         {
989             p_track->fmt.i_codec = VLC_CODEC_DTS;
990             p_track->fmt.i_profile = PROFILE_DTS_HD;
991             break;
992         }
993 
994         case VLC_FOURCC( 't', 'w', 'o', 's' ):
995             p_track->fmt.i_codec = VLC_CODEC_S16B;
996             p_track->fmt.i_original_fourcc = p_sample->i_type;
997             p_track->fmt.audio.i_bitspersample = 16;
998             break;
999 
1000         case VLC_FOURCC( 's', 'o', 'w', 't' ):
1001             p_track->fmt.i_codec = VLC_CODEC_S16L;
1002             p_track->fmt.i_original_fourcc = p_sample->i_type;
1003             p_track->fmt.audio.i_bitspersample = 16;
1004             break;
1005 
1006         case 0x0000000:
1007         case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):
1008         case( VLC_FOURCC( 'N', 'O', 'N', 'E' ) ):
1009         {
1010             if( (p_soun->i_samplesize+7)/8 == 1 )
1011             {
1012                 p_track->fmt.i_codec = VLC_CODEC_U8;
1013                 p_track->fmt.audio.i_bitspersample = 8;
1014             }
1015             else
1016             {
1017                 p_track->fmt.i_codec = VLC_CODEC_S16B;
1018                 p_track->fmt.audio.i_bitspersample = 16;
1019             }
1020 
1021             /* Buggy files workaround */
1022             if( (p_track->i_timescale != p_soun->i_sampleratehi) )
1023             {
1024                 msg_Warn( p_demux, "i_timescale (%"PRId32") != i_sampleratehi "
1025                           "(%u), making both equal (report any problem).",
1026                           p_track->i_timescale, p_soun->i_sampleratehi );
1027 
1028                 if( p_soun->i_sampleratehi != 0 )
1029                     p_track->i_timescale = p_soun->i_sampleratehi;
1030                 else
1031                     p_soun->i_sampleratehi = p_track->i_timescale;
1032             }
1033             break;
1034         }
1035 
1036         case ATOM_in24:
1037             p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1038                                     VLC_CODEC_S24L : VLC_CODEC_S24B;
1039             break;
1040         case ATOM_in32:
1041             p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1042                                     VLC_CODEC_S32L : VLC_CODEC_S32B;
1043             break;
1044         case ATOM_fl32:
1045             p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1046                                     VLC_CODEC_F32L : VLC_CODEC_F32B;
1047             break;
1048         case ATOM_fl64:
1049             p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1050                                     VLC_CODEC_F64L : VLC_CODEC_F64B;
1051             break;
1052 
1053         case VLC_CODEC_DVD_LPCM:
1054         {
1055             if( p_soun->i_qt_version == 2 )
1056             {
1057                 /* Flags:
1058                  *  0x01: IsFloat
1059                  *  0x02: IsBigEndian
1060                  *  0x04: IsSigned
1061                  */
1062                 static const struct {
1063                     unsigned     i_flags;
1064                     unsigned     i_mask;
1065                     unsigned     i_bits;
1066                     vlc_fourcc_t i_codec;
1067                 } p_formats[] = {
1068                     { 0x01,           0x03, 32, VLC_CODEC_F32L },
1069                     { 0x01,           0x03, 64, VLC_CODEC_F64L },
1070                     { 0x01|0x02,      0x03, 32, VLC_CODEC_F32B },
1071                     { 0x01|0x02,      0x03, 64, VLC_CODEC_F64B },
1072 
1073                     { 0x00,           0x05,  8, VLC_CODEC_U8 },
1074                     { 0x00|     0x04, 0x05,  8, VLC_CODEC_S8 },
1075 
1076                     { 0x00,           0x07, 16, VLC_CODEC_U16L },
1077                     { 0x00|0x02,      0x07, 16, VLC_CODEC_U16B },
1078                     { 0x00     |0x04, 0x07, 16, VLC_CODEC_S16L },
1079                     { 0x00|0x02|0x04, 0x07, 16, VLC_CODEC_S16B },
1080 
1081                     { 0x00,           0x07, 24, VLC_CODEC_U24L },
1082                     { 0x00|0x02,      0x07, 24, VLC_CODEC_U24B },
1083                     { 0x00     |0x04, 0x07, 24, VLC_CODEC_S24L },
1084                     { 0x00|0x02|0x04, 0x07, 24, VLC_CODEC_S24B },
1085 
1086                     { 0x00,           0x07, 32, VLC_CODEC_U32L },
1087                     { 0x00|0x02,      0x07, 32, VLC_CODEC_U32B },
1088                     { 0x00     |0x04, 0x07, 32, VLC_CODEC_S32L },
1089                     { 0x00|0x02|0x04, 0x07, 32, VLC_CODEC_S32B },
1090 
1091                     {0, 0, 0, 0}
1092                 };
1093 
1094                 for( int i = 0; p_formats[i].i_codec; i++ )
1095                 {
1096                     if( p_formats[i].i_bits == p_soun->i_constbitsperchannel &&
1097                         (p_soun->i_formatflags & p_formats[i].i_mask) == p_formats[i].i_flags )
1098                     {
1099                         p_track->fmt.i_codec = p_formats[i].i_codec;
1100                         p_track->fmt.audio.i_bitspersample = p_soun->i_constbitsperchannel;
1101                         p_track->fmt.audio.i_blockalign =
1102                                 p_soun->i_channelcount * p_soun->i_constbitsperchannel / 8;
1103                         p_track->i_sample_size = p_track->fmt.audio.i_blockalign;
1104 
1105                         p_soun->i_qt_version = 0;
1106                         break;
1107                     }
1108                 }
1109             }
1110             break;
1111         }
1112         default:
1113             p_track->fmt.i_codec = p_sample->i_type;
1114             break;
1115     }
1116 
1117 
1118     /* Process extensions */
1119 
1120     /* Lookup for then channels extension */
1121     const MP4_Box_t *p_chan = MP4_BoxGet( p_sample, "chan" );
1122     if ( p_chan )
1123     {
1124         if ( BOXDATA(p_chan)->layout.i_channels_layout_tag == MP4_CHAN_USE_CHANNELS_BITMAP )
1125         {
1126             uint32_t rgi_chans_sequence[AOUT_CHAN_MAX + 1];
1127             memset(rgi_chans_sequence, 0, sizeof(rgi_chans_sequence));
1128             uint16_t i_vlc_mapping = 0;
1129             uint8_t i_channels = 0;
1130             const uint32_t i_bitmap = BOXDATA(p_chan)->layout.i_channels_bitmap;
1131             for (uint8_t i=0;i<MP4_CHAN_BITMAP_MAPPING_COUNT;i++)
1132             {
1133                 if ( chan_bitmap_mapping[i].i_bitmap & i_bitmap )
1134                 {
1135                     if ( (chan_bitmap_mapping[i].i_vlc & i_vlc_mapping) ||
1136                          i_channels >= AOUT_CHAN_MAX )
1137                     {
1138                         /* double mapping or unsupported number of channels */
1139                         i_vlc_mapping = 0;
1140                         msg_Warn( p_demux, "discarding chan mapping" );
1141                         break;
1142                     }
1143                     i_vlc_mapping |= chan_bitmap_mapping[i].i_vlc;
1144                     rgi_chans_sequence[i_channels++] = chan_bitmap_mapping[i].i_vlc;
1145                 }
1146             }
1147             rgi_chans_sequence[i_channels] = 0;
1148             if( aout_CheckChannelReorder( rgi_chans_sequence, NULL, i_vlc_mapping,
1149                                           p_track->rgi_chans_reordering ) &&
1150                 aout_BitsPerSample( p_track->fmt.i_codec ) )
1151             {
1152                 p_track->b_chans_reorder = true;
1153                 p_track->fmt.audio.i_channels = i_channels;
1154                 p_track->fmt.audio.i_physical_channels = i_vlc_mapping;
1155             }
1156 
1157         }
1158     }
1159 
1160     SetupGlobalExtensions( p_track, p_sample );
1161 
1162     /* now see if esds is present and if so create a data packet
1163         with decoder_specific_info  */
1164     MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
1165     if ( !p_esds ) p_esds = MP4_BoxGet( p_sample, "wave/esds" );
1166     if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
1167     {
1168         assert(p_sample->i_type == ATOM_mp4a);
1169         SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
1170     }
1171     else switch( p_sample->i_type )
1172     {
1173         case VLC_CODEC_AMR_NB:
1174             p_track->fmt.audio.i_rate = 8000;
1175             break;
1176         case VLC_CODEC_AMR_WB:
1177             p_track->fmt.audio.i_rate = 16000;
1178             break;
1179         case VLC_CODEC_QDMC:
1180         case VLC_CODEC_QDM2:
1181         case VLC_CODEC_ALAC:
1182         {
1183             p_track->fmt.i_extra =
1184                 p_sample->data.p_sample_soun->i_qt_description;
1185             if( p_track->fmt.i_extra > 0 )
1186             {
1187                 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
1188                 memcpy( p_track->fmt.p_extra,
1189                         p_sample->data.p_sample_soun->p_qt_description,
1190                         p_track->fmt.i_extra);
1191             }
1192             if( p_track->fmt.i_extra == 56 && p_sample->i_type == VLC_CODEC_ALAC )
1193             {
1194                 p_track->fmt.audio.i_channels = *((uint8_t*)p_track->fmt.p_extra + 41);
1195                 p_track->fmt.audio.i_rate = GetDWBE((uint8_t*)p_track->fmt.p_extra + 52);
1196             }
1197             break;
1198         }
1199         case VLC_CODEC_ADPCM_MS:
1200         case VLC_CODEC_ADPCM_IMA_WAV:
1201         case VLC_CODEC_QCELP:
1202         {
1203             p_track->fmt.audio.i_blockalign = p_sample->data.p_sample_soun->i_bytes_per_frame;
1204             break;
1205         }
1206         case ATOM_WMA2:
1207         {
1208             if( SetupAudioFromWaveFormatEx( &p_track->fmt,
1209                                             MP4_BoxGet( p_sample, "wave/WMA2" ) ) )
1210             {
1211                 p_track->p_asf = MP4_BoxGet( p_sample, "wave/ASF " );
1212             }
1213             else
1214             {
1215                 msg_Err( p_demux, "missing WMA2 %4.4s", (char*) &p_sample->p_father->i_type );
1216             }
1217             break;
1218         }
1219         case ATOM_wma: /* isml wmapro */
1220         {
1221             if( !SetupAudioFromWaveFormatEx( &p_track->fmt, MP4_BoxGet( p_sample, "wfex" ) ) )
1222                 msg_Err( p_demux, "missing wfex for wma" );
1223             break;
1224         }
1225 
1226         default:
1227             if(p_track->fmt.i_codec == 0)
1228                 msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
1229             break;
1230     }
1231 
1232     /* Ambisonics */
1233     const MP4_Box_t *p_SA3D = MP4_BoxGet(p_sample, "SA3D");
1234     if (p_SA3D && BOXDATA(p_SA3D))
1235         p_track->fmt.audio.channel_type = AUDIO_CHANNEL_TYPE_AMBISONICS;
1236 
1237     /* Late fixes */
1238     if ( p_soun->i_qt_version == 0 && p_track->fmt.i_codec == VLC_CODEC_QCELP )
1239     {
1240         /* Shouldn't be v0, as it is a compressed codec !*/
1241         p_soun->i_qt_version = 1;
1242         p_soun->i_compressionid = 0xFFFE;
1243     }
1244 
1245     return 1;
1246 }
1247 
SetupSpuES(demux_t * p_demux,mp4_track_t * p_track,MP4_Box_t * p_sample)1248 int SetupSpuES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
1249 {
1250     /* It's a little ugly but .. there are special cases */
1251     switch( p_sample->i_type )
1252     {
1253         case VLC_FOURCC('s','t','p','p'):
1254             p_track->fmt.i_codec = VLC_CODEC_TTML;
1255             break;
1256         case ATOM_wvtt:
1257             p_track->fmt.i_codec = VLC_CODEC_WEBVTT;
1258             break;
1259         case ATOM_c608: /* EIA608 closed captions */
1260             p_track->fmt.i_codec = VLC_CODEC_CEA608;
1261             p_track->fmt.subs.cc.i_reorder_depth = -1;
1262             break;
1263         case ATOM_c708: /* EIA708 closed captions */
1264             p_track->fmt.i_codec = VLC_CODEC_CEA708;
1265             p_track->fmt.subs.cc.i_reorder_depth = -1;
1266             break;
1267 
1268         case( VLC_FOURCC( 't', 'e', 'x', 't' ) ):
1269         case( VLC_FOURCC( 't', 'x', '3', 'g' ) ):
1270         {
1271             const MP4_Box_data_sample_text_t *p_text = p_sample->data.p_sample_text;
1272             if(!p_text)
1273                 return 0;
1274 
1275             p_track->fmt.i_codec = VLC_CODEC_TX3G;
1276 
1277             if( p_text->i_display_flags & 0xC0000000 )
1278             {
1279                 p_track->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1;
1280                 p_track->b_forced_spu = true;
1281             }
1282 
1283             text_style_t *p_style = text_style_Create( STYLE_NO_DEFAULTS );
1284             if ( p_style )
1285             {
1286                 if ( p_text->i_font_size ) /* !WARN: in % of 5% height */
1287                 {
1288                     p_style->i_font_size = p_text->i_font_size;
1289                 }
1290                 if ( p_text->i_font_color )
1291                 {
1292                     p_style->i_font_color = p_text->i_font_color >> 8;
1293                     p_style->i_font_alpha = p_text->i_font_color & 0xFF;
1294                     p_style->i_features |= (STYLE_HAS_FONT_ALPHA | STYLE_HAS_FONT_COLOR);
1295                 }
1296                 if ( p_text->i_background_color[3] >> 8 )
1297                 {
1298                     p_style->i_background_color = p_text->i_background_color[0] >> 8;
1299                     p_style->i_background_color |= p_text->i_background_color[1] >> 8;
1300                     p_style->i_background_color |= p_text->i_background_color[2] >> 8;
1301                     p_style->i_background_alpha = p_text->i_background_color[3] >> 8;
1302                     p_style->i_features |= (STYLE_HAS_BACKGROUND_ALPHA | STYLE_HAS_BACKGROUND_COLOR);
1303                 }
1304             }
1305             assert(p_track->fmt.i_cat == SPU_ES);
1306             p_track->fmt.subs.p_style = p_style;
1307 
1308             /* FIXME UTF-8 doesn't work here ? */
1309             if( p_track->b_mac_encoding )
1310                 p_track->fmt.subs.psz_encoding = strdup( "MAC" );
1311             else
1312                 p_track->fmt.subs.psz_encoding = strdup( "UTF-8" );
1313             break;
1314         }
1315 
1316         default:
1317             p_track->fmt.i_codec = p_sample->i_type;
1318             break;
1319     }
1320 
1321     SetupGlobalExtensions( p_track, p_sample );
1322 
1323     /* now see if esds is present and if so create a data packet
1324         with decoder_specific_info  */
1325     MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
1326     if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
1327     {
1328         SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
1329     }
1330 
1331     return 1;
1332 }
1333