demux: mp4: use struct for coreaudio layout params
[vlc.git] / modules / demux / mp4 / essetup.c
blob637d2d670c017b45eb5456829585c9b9732083f8
1 /*****************************************************************************
2 * essetup.h: es setup from stsd and extensions parsing
3 *****************************************************************************
4 * Copyright (C) 2001-2004, 2010, 2014 VLC authors and VideoLAN
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include "mp4.h"
28 #include "avci.h"
29 #include "../xiph.h"
30 #include "../../packetizer/dts_header.h"
31 #include "../../packetizer/iso_color_tables.h"
33 #include <vlc_demux.h>
34 #include <vlc_aout.h>
35 #include <assert.h>
40 static void SetupGlobalExtensions( mp4_track_t *p_track, MP4_Box_t *p_sample )
42 if( !p_track->fmt.i_bitrate )
44 const MP4_Box_t *p_btrt = MP4_BoxGet( p_sample, "btrt" );
45 if( p_btrt && BOXDATA(p_btrt) )
47 p_track->fmt.i_bitrate = BOXDATA(p_btrt)->i_avg_bitrate;
52 static void SetupESDS( demux_t *p_demux, mp4_track_t *p_track, const MP4_descriptor_decoder_config_t *p_decconfig )
54 /* First update information based on i_objectTypeIndication */
55 /* See 14496-1 and http://www.mp4ra.org/object.html */
56 switch( p_decconfig->i_objectProfileIndication )
58 case( 0x20 ): /* MPEG4 VIDEO */
59 p_track->fmt.i_codec = VLC_CODEC_MP4V;
60 break;
61 case( 0x21 ): /* H.264 */
62 p_track->fmt.i_codec = VLC_CODEC_H264;
63 break;
64 case( 0x40):
65 case( 0x41):
66 p_track->fmt.i_codec = VLC_CODEC_MP4A;
67 if( p_decconfig->i_decoder_specific_info_len >= 2 &&
68 p_decconfig->p_decoder_specific_info[0] == 0xF8 &&
69 (p_decconfig->p_decoder_specific_info[1]&0xE0) == 0x80 )
71 p_track->fmt.i_codec = VLC_CODEC_ALS;
73 break;
74 case( 0x60):
75 case( 0x61):
76 case( 0x62):
77 case( 0x63):
78 case( 0x64):
79 case( 0x65): /* MPEG2 video */
80 p_track->fmt.i_codec = VLC_CODEC_MPGV;
81 break;
82 /* Theses are MPEG2-AAC */
83 case( 0x66): /* main profile */
84 case( 0x67): /* Low complexity profile */
85 case( 0x68): /* Scaleable Sampling rate profile */
86 p_track->fmt.i_codec = VLC_CODEC_MP4A;
87 break;
88 /* True MPEG 2 audio */
89 case( 0x69):
90 p_track->fmt.i_codec = VLC_CODEC_MPGA;
91 break;
92 case( 0x6a): /* MPEG1 video */
93 p_track->fmt.i_codec = VLC_CODEC_MPGV;
94 break;
95 case( 0x6b): /* MPEG1 audio */
96 p_track->fmt.i_codec = VLC_CODEC_MPGA;
97 break;
98 case( 0x6c ): /* jpeg */
99 p_track->fmt.i_codec = VLC_CODEC_JPEG;
100 break;
101 case( 0x6d ): /* png */
102 p_track->fmt.i_codec = VLC_CODEC_PNG;
103 break;
104 case( 0x6e ): /* jpeg2000 */
105 p_track->fmt.i_codec = VLC_FOURCC( 'M','J','2','C' );
106 break;
107 case( 0xa3 ): /* vc1 */
108 p_track->fmt.i_codec = VLC_CODEC_VC1;
109 break;
110 case( 0xa4 ):
111 p_track->fmt.i_codec = VLC_CODEC_DIRAC;
112 break;
113 case( 0xa5 ):
114 p_track->fmt.i_codec = VLC_CODEC_A52;
115 break;
116 case( 0xa6 ):
117 p_track->fmt.i_codec = VLC_CODEC_EAC3;
118 break;
119 case( 0xaa ): /* DTS-HD HRA */
120 case( 0xab ): /* DTS-HD Master Audio */
121 p_track->fmt.i_profile = PROFILE_DTS_HD;
122 /* fallthrough */
123 case( 0xa9 ): /* dts */
124 p_track->fmt.i_codec = VLC_CODEC_DTS;
125 break;
126 case( 0xDD ):
127 p_track->fmt.i_codec = VLC_CODEC_VORBIS;
128 break;
130 /* Private ID */
131 case( 0xe0 ): /* NeroDigital: dvd subs */
132 if( p_track->fmt.i_cat == SPU_ES )
134 p_track->fmt.i_codec = VLC_CODEC_SPU;
135 if( p_track->i_width > 0 )
136 p_track->fmt.subs.spu.i_original_frame_width = p_track->i_width;
137 if( p_track->i_height > 0 )
138 p_track->fmt.subs.spu.i_original_frame_height = p_track->i_height;
140 break;
141 case( 0xe1 ): /* QCelp for 3gp */
142 if( p_track->fmt.i_cat == AUDIO_ES )
144 p_track->fmt.i_codec = VLC_CODEC_QCELP;
146 break;
148 /* Fallback */
149 default:
150 /* Unknown entry, but don't touch i_fourcc */
151 msg_Warn( p_demux,
152 "unknown objectProfileIndication(0x%x) (Track[ID 0x%x])",
153 p_decconfig->i_objectProfileIndication,
154 p_track->i_track_ID );
155 return;
158 p_track->fmt.i_original_fourcc = 0; /* so we don't have MP4A as original fourcc */
159 p_track->fmt.i_bitrate = p_decconfig->i_avg_bitrate;
161 p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len;
162 if( p_track->fmt.i_extra > 0 )
164 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
165 memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info,
166 p_track->fmt.i_extra );
168 if( p_track->fmt.i_codec == VLC_CODEC_SPU &&
169 p_track->fmt.i_extra >= 16 * 4 )
171 for( int i = 0; i < 16; i++ )
173 p_track->fmt.subs.spu.palette[1 + i] =
174 GetDWBE((char*)p_track->fmt.p_extra + i * 4);
176 p_track->fmt.subs.spu.palette[0] = SPU_PALETTE_DEFINED;
180 static int SetupRTPReceptionHintTrack( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
182 p_track->fmt.i_original_fourcc = p_sample->i_type;
184 if( !p_track->p_sdp )
186 msg_Err(p_demux, "Required 'sdp '-box not found");
187 return 0;
189 MP4_Box_t *p_sdp = p_track->p_sdp;
190 char *strtok_state;
191 char * pch = strtok_r(BOXDATA(p_sdp)->psz_text, " =\n", &strtok_state); /* media entry */
192 if( pch && pch[0] != 'm' )
194 msg_Err(p_demux, "No Media entry found in SDP:%s", pch);
195 return 0;
198 if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* media type */
199 return 0;
200 /* media type has already been checked */
201 msg_Dbg(p_demux, "sdp: media type:%s", pch);
202 if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* port */
203 return 0;
204 msg_Dbg(p_demux, "sdp: port:%s", pch);
205 if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* protocol */
206 return 0;
207 msg_Dbg(p_demux, "sdp: protocol:%s", pch);
209 if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* fmt */
210 return 0;
212 bool codec_set = false;
213 /* process rtp types until we get an attribute field or end of sdp */
214 while( pch && pch[0] != 'a' )
216 int rtp_payload = atoi(pch);
217 msg_Dbg(p_demux, "sdp: payload type:%d", rtp_payload);
219 if( !codec_set )
221 /* Payload types 34 and under have a set type and can be identified here */
222 switch( rtp_payload )
224 case 3:
225 p_track->fmt.i_codec = VLC_CODEC_GSM;
226 codec_set = true;
227 break;
228 default:
229 break;
232 pch = strtok_r(NULL, " =\n", &strtok_state); /* attribute or additional payload type */
233 if( !pch && !codec_set )
234 return 0;
237 while( pch && pch[0] == 'a' )
239 if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* attribute type */
240 return 0;
241 msg_Dbg(p_demux, "sdp: atrribute type:%s", pch);
243 if( !strcmp(pch, "rtpmap") )
245 if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* payload type */
246 return 0;
247 msg_Dbg(p_demux, "sdp: payload type:%s", pch);
248 if( !(pch = strtok_r(NULL, " /:=\n", &strtok_state) ) ) /* encoding name */
249 return 0;
250 msg_Dbg(p_demux, "sdp: encoding name:%s", pch);
252 /* Simply adding codec recognition should work for most codecs */
253 /* Codecs using slices need their picture constructed from sample */
254 if( !strcmp(pch, "H264") )
256 p_track->fmt.i_codec = VLC_CODEC_H264;
257 /* ******* sending AnnexB ! */
258 p_track->fmt.b_packetized = false;
260 else if( !strcmp(pch, "GSM") )
262 p_track->fmt.i_codec = VLC_CODEC_GSM;
264 else if( !strcmp(pch, "Speex") )
266 p_track->fmt.i_codec = VLC_CODEC_SPEEX;
268 else if( !codec_set )
270 msg_Err(p_demux, "Support for codec contained in RTP \
271 Reception Hint Track RTP stream has not been added");
272 return 0;
275 if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* clock rate */
276 return 0;
277 int clock_rate = atoi(pch);
278 msg_Dbg(p_demux, "sdp clock rate:%d", clock_rate);
279 if( p_track->fmt.i_cat == AUDIO_ES )
280 p_track->fmt.audio.i_rate = clock_rate;
282 pch = strtok_r(NULL, " =\n", &strtok_state); /* next attribute */
285 const MP4_Box_t *p_tims = MP4_BoxGet(p_sample, "tims");
286 if( p_tims && BOXDATA(p_tims) && BOXDATA(p_tims)->i_timescale )
288 p_track->i_timescale = BOXDATA(p_tims)->i_timescale;
290 else
292 msg_Warn(p_demux, "Missing mandatory box tims");
293 return 0;
296 const MP4_Box_t *p_tssy = MP4_BoxGet(p_sample, "tssy");
297 if( p_tssy && BOXDATA(p_tssy) )
299 /* take the 2 last bits which indicate the synchronization mode */
300 p_track->sync_mode = (RTP_timstamp_synchronization_t)
301 BOXDATA(p_tssy)->i_reserved_timestamp_sync & 0x03;
304 const MP4_Box_t *p_tsro = MP4_BoxGet(p_sample, "tsro");
305 if( p_tsro && BOXDATA(p_tsro) )
306 p_track->i_tsro_offset = BOXDATA(p_tsro)->i_offset;
307 else
308 msg_Dbg(p_demux, "No tsro box present");
309 msg_Dbg(p_demux, "setting tsro: %" PRId32, p_track->i_tsro_offset);
311 return 1;
315 int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
317 MP4_Box_data_sample_vide_t *p_vide = p_sample->data.p_sample_vide;
318 if(!p_vide)
319 return 0;
321 p_track->fmt.video.i_width = p_vide->i_width;
322 p_track->fmt.video.i_height = p_vide->i_height;
323 p_track->fmt.video.i_bits_per_pixel = p_vide->i_depth;
325 /* fall on display size */
326 if( p_track->fmt.video.i_width <= 0 )
327 p_track->fmt.video.i_width = p_track->i_width;
328 if( p_track->fmt.video.i_height <= 0 )
329 p_track->fmt.video.i_height = p_track->i_height;
331 /* Find out apect ratio from display size */
332 if( p_track->i_width > 0 && p_track->i_height > 0 &&
333 /* Work-around buggy muxed files */
334 p_vide->i_width != p_track->i_width )
336 p_track->fmt.video.i_sar_num = p_track->i_width * p_track->fmt.video.i_height;
337 p_track->fmt.video.i_sar_den = p_track->i_height * p_track->fmt.video.i_width;
340 /* Support for cropping (eg. in H263 files) */
341 p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
342 p_track->fmt.video.i_visible_height = p_track->fmt.video.i_height;
344 /* Rotation */
345 switch( (int)p_track->f_rotation ) {
346 case 90:
347 p_track->fmt.video.orientation = ORIENT_ROTATED_90;
348 break;
349 case 180:
350 p_track->fmt.video.orientation = ORIENT_ROTATED_180;
351 break;
352 case 270:
353 p_track->fmt.video.orientation = ORIENT_ROTATED_270;
354 break;
357 /* Set 360 video mode */
358 p_track->fmt.video.projection_mode = PROJECTION_MODE_RECTANGULAR;
359 const MP4_Box_t *p_uuid = MP4_BoxGet( p_track->p_track, "uuid" );
360 for( ; p_uuid; p_uuid = p_uuid->p_next)
362 if( p_uuid->i_type == ATOM_uuid
363 && !CmpUUID( &p_uuid->i_uuid, &XML360BoxUUID )
364 && p_uuid->data.p_360 )
366 p_track->fmt.video.projection_mode = p_uuid->data.p_360->i_projection_mode;
367 switch (p_uuid->data.p_360->e_stereo_mode)
369 case XML360_STEREOSCOPIC_TOP_BOTTOM:
370 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;
371 break;
372 case XML360_STEREOSCOPIC_LEFT_RIGHT:
373 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS;
374 break;
375 default:
376 p_track->fmt.video.multiview_mode = MULTIVIEW_2D;
377 break;
382 const MP4_Box_t *p_st3d = MP4_BoxGet( p_sample, "st3d" );
383 if (p_st3d && BOXDATA(p_st3d))
385 switch( BOXDATA(p_st3d)->i_stereo_mode )
387 case ST3D_MONOSCOPIC:
388 p_track->fmt.video.multiview_mode = MULTIVIEW_2D;
389 break;
390 case ST3D_STEREOSCOPIC_TOP_BOTTOM:
391 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;
392 break;
393 case ST3D_STEREOSCOPIC_LEFT_RIGHT:
394 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS;
395 break;
396 default:
397 msg_Warn( p_demux, "Unknown stereo mode %d", BOXDATA(p_st3d)->i_stereo_mode );
398 break;
401 else
403 for( p_uuid = MP4_BoxGet( p_sample, "uuid" ); p_uuid;
404 p_uuid = p_uuid->p_next )
406 if( p_uuid->i_type == ATOM_uuid &&
407 !CmpUUID( &p_uuid->i_uuid, &PS3DDSBoxUUID ) &&
408 p_uuid->data.p_binary &&
409 p_uuid->data.p_binary->i_blob == 4 &&
410 !memcmp( p_uuid->data.p_binary->p_blob, "\x82\x81\x10\x02", 4 ) )
412 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_FRAME;
413 break;
418 const MP4_Box_t *p_prhd = MP4_BoxGet( p_sample, "sv3d/proj/prhd" );
419 if (p_prhd && BOXDATA(p_prhd))
421 p_track->fmt.video.pose.yaw = BOXDATA(p_prhd)->f_pose_yaw_degrees;
422 p_track->fmt.video.pose.pitch = BOXDATA(p_prhd)->f_pose_pitch_degrees;
423 p_track->fmt.video.pose.roll = BOXDATA(p_prhd)->f_pose_roll_degrees;
426 const MP4_Box_t *p_equi = MP4_BoxGet( p_sample, "sv3d/proj/equi" );
427 const MP4_Box_t *p_cbmp = MP4_BoxGet( p_sample, "sv3d/proj/cbmp" );
428 if (p_equi && BOXDATA(p_equi))
429 p_track->fmt.video.projection_mode = PROJECTION_MODE_EQUIRECTANGULAR;
430 else if (p_cbmp && BOXDATA(p_cbmp))
431 p_track->fmt.video.projection_mode = PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD;
433 /* It's a little ugly but .. there are special cases */
434 switch( p_sample->i_type )
436 case( VLC_FOURCC( 's', '2', '6', '3' ) ):
437 p_track->fmt.i_codec = VLC_CODEC_H263;
438 break;
439 case VLC_FOURCC('y','v','1','2'):
440 p_track->fmt.i_codec = VLC_CODEC_YV12;
441 break;
442 case VLC_FOURCC('y','u','v','2'):
443 p_track->fmt.i_codec = VLC_CODEC_YUYV;
444 break;
445 case VLC_FOURCC('r','a','w',' '):
446 switch( p_vide->i_depth ) {
447 case 16:
448 p_track->fmt.i_codec = VLC_CODEC_RGB15;
449 break;
450 case 24:
451 p_track->fmt.i_codec = VLC_CODEC_RGB24;
452 break;
453 case 32:
454 p_track->fmt.i_codec = VLC_CODEC_ARGB;
455 break;
456 case 32 + 8:
457 p_track->fmt.i_codec = VLC_CODEC_GREY;
458 break;
459 default:
460 msg_Dbg( p_demux, "Unrecognized raw video format (depth = %d)",
461 p_vide->i_depth );
462 p_track->fmt.i_codec = p_sample->i_type;
463 break;
465 break;
466 case( VLC_FOURCC( 'r', 'r', 't', 'p' ) ): /* RTP Reception Hint Track */
468 if( !SetupRTPReceptionHintTrack( p_demux, p_track, p_sample ) )
469 p_track->fmt.i_codec = p_sample->i_type;
470 break;
472 default:
473 p_track->fmt.i_codec = p_sample->i_type;
474 break;
478 /* Read extensions */
480 /* Set up A/R from extension atom */
481 const MP4_Box_t *p_pasp = MP4_BoxGet( p_sample, "pasp" );
482 if( p_pasp && BOXDATA(p_pasp) && BOXDATA(p_pasp)->i_horizontal_spacing > 0 &&
483 BOXDATA(p_pasp)->i_vertical_spacing > 0 )
485 p_track->fmt.video.i_sar_num = BOXDATA(p_pasp)->i_horizontal_spacing;
486 p_track->fmt.video.i_sar_den = BOXDATA(p_pasp)->i_vertical_spacing;
489 const MP4_Box_t *p_fiel = MP4_BoxGet( p_sample, "fiel" );
490 if( p_fiel && BOXDATA(p_fiel) )
492 p_track->i_block_flags = BOXDATA(p_fiel)->i_flags;
495 const MP4_Box_t *p_colr = MP4_BoxGet( p_sample, "colr" );
496 if ( p_colr != NULL )
498 if ( BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'c' ) ||
499 BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'x' ) )
501 p_track->fmt.video.primaries =
502 iso_23001_8_cp_to_vlc_primaries( BOXDATA( p_colr )->nclc.i_primary_idx );
503 p_track->fmt.video.transfer =
504 iso_23001_8_tc_to_vlc_xfer( BOXDATA( p_colr )->nclc.i_transfer_function_idx );
505 p_track->fmt.video.space =
506 iso_23001_8_mc_to_vlc_coeffs( BOXDATA( p_colr )->nclc.i_matrix_idx );
507 if ( BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'x' ) &&
508 (BOXDATA(p_colr)->nclc.i_full_range >> 7) != 0 )
509 p_track->fmt.video.color_range = COLOR_RANGE_FULL;
510 else
511 p_track->fmt.video.color_range = COLOR_RANGE_LIMITED;
515 SetupGlobalExtensions( p_track, p_sample );
517 /* now see if esds is present and if so create a data packet
518 with decoder_specific_info */
519 MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
520 if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
522 assert(p_sample->i_type == ATOM_mp4v);
523 SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
525 else switch( p_sample->i_type )
527 /* qt decoder, send the complete chunk */
528 case VLC_FOURCC ('h', 'd', 'v', '1'): // HDV 720p30
529 case VLC_FOURCC ('h', 'd', 'v', '2'): // HDV 1080i60
530 case VLC_FOURCC ('h', 'd', 'v', '3'): // HDV 1080i50
531 case VLC_FOURCC ('h', 'd', 'v', '5'): // HDV 720p25
532 case VLC_FOURCC ('m', 'x', '5', 'n'): // MPEG2 IMX NTSC 525/60 50mb/s produced by FCP
533 case VLC_FOURCC ('m', 'x', '5', 'p'): // MPEG2 IMX PAL 625/60 50mb/s produced by FCP
534 case VLC_FOURCC ('m', 'x', '4', 'n'): // MPEG2 IMX NTSC 525/60 40mb/s produced by FCP
535 case VLC_FOURCC ('m', 'x', '4', 'p'): // MPEG2 IMX PAL 625/60 40mb/s produced by FCP
536 case VLC_FOURCC ('m', 'x', '3', 'n'): // MPEG2 IMX NTSC 525/60 30mb/s produced by FCP
537 case VLC_FOURCC ('m', 'x', '3', 'p'): // MPEG2 IMX PAL 625/50 30mb/s produced by FCP
538 case VLC_FOURCC ('x', 'd', 'v', '2'): // XDCAM HD 1080i60
539 case VLC_FOURCC ('A', 'V', 'm', 'p'): // AVID IMX PAL
540 p_track->fmt.i_codec = VLC_CODEC_MPGV;
541 break;
542 /* qt decoder, send the complete chunk */
543 case VLC_CODEC_SVQ1:
544 case VLC_CODEC_SVQ3:
545 case VLC_FOURCC( 'V', 'P', '3', '1' ):
546 case VLC_FOURCC( '3', 'I', 'V', '1' ):
547 case VLC_FOURCC( 'Z', 'y', 'G', 'o' ):
549 p_track->fmt.i_extra =
550 p_sample->data.p_sample_vide->i_qt_image_description;
551 if( p_track->fmt.i_extra > 0 )
553 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
554 memcpy( p_track->fmt.p_extra,
555 p_sample->data.p_sample_vide->p_qt_image_description,
556 p_track->fmt.i_extra);
558 break;
561 case VLC_FOURCC( 'A', 'V', 'j', '2' ):
562 p_track->fmt.i_codec = VLC_CODEC_JPEG2000;
563 /* final decoded resolution stored in ARES w, h, nbfields to group
564 * but since avcodec can't tell... */
565 break;
567 case VLC_FOURCC('j', 'p', 'e', 'g'):
568 p_track->fmt.i_codec = VLC_CODEC_MJPG;
569 break;
571 case VLC_CODEC_FFV1:
573 MP4_Box_t *p_binary = MP4_BoxGet( p_sample, "glbl" );
574 if( p_binary && BOXDATA(p_binary) && BOXDATA(p_binary)->i_blob )
576 p_track->fmt.p_extra = malloc( BOXDATA(p_binary)->i_blob );
577 if( p_track->fmt.p_extra )
579 p_track->fmt.i_extra = BOXDATA(p_binary)->i_blob;
580 memcpy( p_track->fmt.p_extra, BOXDATA(p_binary)->p_blob,
581 p_track->fmt.i_extra );
584 break;
587 case VLC_FOURCC( 'v', 'c', '-', '1' ):
589 MP4_Box_t *p_dvc1 = MP4_BoxGet( p_sample, "dvc1" );
590 if( p_dvc1 && BOXDATA(p_dvc1) )
592 p_track->fmt.i_extra = BOXDATA(p_dvc1)->i_vc1;
593 if( p_track->fmt.i_extra > 0 )
595 p_track->fmt.p_extra = malloc( BOXDATA(p_dvc1)->i_vc1 );
596 memcpy( p_track->fmt.p_extra, BOXDATA(p_dvc1)->p_vc1,
597 p_track->fmt.i_extra );
600 else
602 msg_Err( p_demux, "missing dvc1" );
604 break;
607 case ATOM_av01:
609 static_assert(ATOM_av01 == VLC_CODEC_AV1, "VLC_CODEC_AV1 != ATOM_av01");
610 MP4_Box_t *p_av1C = MP4_BoxGet( p_sample, "av1C" );
611 if( p_av1C && BOXDATA(p_av1C) )
613 p_track->fmt.i_profile = BOXDATA(p_av1C)->i_profile;
614 p_track->fmt.i_level = BOXDATA(p_av1C)->i_level;
615 if( BOXDATA(p_av1C)->i_av1C )
617 p_track->fmt.p_extra = malloc( BOXDATA(p_av1C)->i_av1C );
618 if( p_track->fmt.p_extra )
620 memcpy( p_track->fmt.p_extra, BOXDATA(p_av1C)->p_av1C,
621 BOXDATA(p_av1C)->i_av1C );
622 p_track->fmt.i_extra = BOXDATA(p_av1C)->i_av1C;
626 break;
629 /* avc1: send avcC (h264 without annexe B, ie without start code)*/
630 case VLC_FOURCC( 'a', 'v', 'c', '3' ):
631 case VLC_FOURCC( 'a', 'v', 'c', '1' ):
632 case VLC_FOURCC( 'd', 'v', 'a', '1' ): /* DolbyVision */
633 case VLC_FOURCC( 'd', 'v', 'a', 'v' ): /* DolbyVision */
635 MP4_Box_t *p_avcC = MP4_BoxGet( p_sample, "avcC" );
637 if( p_avcC && BOXDATA(p_avcC) )
639 p_track->fmt.i_profile = BOXDATA(p_avcC)->i_profile;
640 p_track->fmt.i_level = BOXDATA(p_avcC)->i_level;
641 p_track->fmt.i_extra = BOXDATA(p_avcC)->i_avcC;
642 if( p_track->fmt.i_extra > 0 )
644 p_track->fmt.p_extra = malloc( BOXDATA(p_avcC)->i_avcC );
645 memcpy( p_track->fmt.p_extra, BOXDATA(p_avcC)->p_avcC,
646 p_track->fmt.i_extra );
649 else
651 msg_Err( p_demux, "missing avcC" );
653 break;
655 case VLC_FOURCC( 'h', 'v', 'c', '1' ):
656 case VLC_FOURCC( 'h', 'e', 'v', '1' ):
657 case VLC_FOURCC( 'd', 'v', 'h', 'e' ): /* DolbyVision */
658 case VLC_FOURCC( 'd', 'v', 'h', '1' ): /* DolbyVision */
660 MP4_Box_t *p_hvcC = MP4_BoxGet( p_sample, "hvcC" );
662 /* Handle DV fourcc collision at demux level */
663 if( p_sample->i_type == VLC_FOURCC( 'd', 'v', 'h', '1' ) )
664 p_track->fmt.i_codec = VLC_FOURCC( 'd', 'v', 'h', 'e' );
666 if( p_hvcC && p_hvcC->data.p_binary && p_hvcC->data.p_binary->i_blob )
668 p_track->fmt.p_extra = malloc( p_hvcC->data.p_binary->i_blob );
669 if( p_track->fmt.p_extra )
671 p_track->fmt.i_extra = p_hvcC->data.p_binary->i_blob;
672 memcpy( p_track->fmt.p_extra, p_hvcC->data.p_binary->p_blob,
673 p_hvcC->data.p_binary->i_blob );
676 else
678 msg_Err( p_demux, "missing hvcC" );
680 break;
683 case ATOM_vp08:
684 case ATOM_vp09:
685 case ATOM_vp10:
687 const MP4_Box_t *p_vpcC = MP4_BoxGet( p_sample, "vpcC" );
688 if( p_vpcC && BOXDATA(p_vpcC) )
690 const MP4_Box_data_vpcC_t *p_data = BOXDATA(p_vpcC);
691 if( p_sample->i_type == ATOM_vp10 )
692 p_track->fmt.i_codec = VLC_CODEC_VP10;
693 else if( p_sample->i_type == ATOM_vp09 )
694 p_track->fmt.i_codec = VLC_CODEC_VP9;
695 else
696 p_track->fmt.i_codec = VLC_CODEC_VP8;
697 p_track->fmt.i_profile = p_data->i_profile;
698 p_track->fmt.i_level = p_data->i_level;
700 if( p_data->i_version == 0 ) /* old deprecated */
702 const uint8_t colorspacesmapping[] =
704 COLOR_SPACE_UNDEF,
705 COLOR_SPACE_BT601,
706 COLOR_SPACE_BT709,
707 COLOR_SPACE_SMPTE_170,
708 COLOR_SPACE_SMPTE_240,
709 COLOR_SPACE_BT2020,
710 COLOR_SPACE_BT2020,
711 COLOR_SPACE_SRGB,
713 if( p_data->i_color_primaries < ARRAY_SIZE(colorspacesmapping) )
714 p_track->fmt.video.space = colorspacesmapping[p_data->i_color_primaries];
716 if( p_data->i_xfer_function == 0 )
717 p_track->fmt.video.transfer = TRANSFER_FUNC_BT709;
718 else if ( p_data->i_xfer_function == 1 )
719 p_track->fmt.video.transfer = TRANSFER_FUNC_SMPTE_ST2084;
721 else
723 p_track->fmt.video.primaries =
724 iso_23001_8_cp_to_vlc_primaries( p_data->i_color_primaries );
725 p_track->fmt.video.transfer =
726 iso_23001_8_tc_to_vlc_xfer( p_data->i_xfer_function );
727 p_track->fmt.video.space =
728 iso_23001_8_mc_to_vlc_coeffs( p_data->i_matrix_coeffs );
731 p_track->fmt.video.color_range = p_data->i_fullrange ? COLOR_RANGE_FULL : COLOR_RANGE_LIMITED;
732 p_track->fmt.video.i_bits_per_pixel = p_data->i_bit_depth;
734 if( p_data->i_codec_init_datasize )
736 p_track->fmt.p_extra = malloc( p_data->i_codec_init_datasize );
737 if( p_track->fmt.p_extra )
739 p_track->fmt.i_extra = p_data->i_codec_init_datasize;
740 memcpy( p_track->fmt.p_extra, p_data->p_codec_init_data,
741 p_data->i_codec_init_datasize );
745 const MP4_Box_t *p_SmDm = MP4_BoxGet( p_sample, "SmDm" );
746 if( !p_SmDm )
747 p_SmDm = MP4_BoxGet( p_sample, "mdcv" );
748 if( p_SmDm && BOXDATA(p_SmDm) )
750 memcpy( p_track->fmt.video.mastering.primaries,
751 BOXDATA(p_SmDm)->primaries, sizeof(uint16_t) * 6 );
752 memcpy( p_track->fmt.video.mastering.white_point,
753 BOXDATA(p_SmDm)->white_point, sizeof(uint16_t) * 2 );
754 p_track->fmt.video.mastering.max_luminance = BOXDATA(p_SmDm)->i_luminanceMax;
755 p_track->fmt.video.mastering.min_luminance = BOXDATA(p_SmDm)->i_luminanceMin;
758 const MP4_Box_t *p_CoLL = MP4_BoxGet( p_sample, "CoLL" );
759 if( !p_CoLL )
760 p_CoLL = MP4_BoxGet( p_sample, "clli" );
761 if( p_CoLL && BOXDATA(p_CoLL) )
763 p_track->fmt.video.lighting.MaxCLL = BOXDATA(p_CoLL)->i_maxCLL;
764 p_track->fmt.video.lighting.MaxFALL = BOXDATA(p_CoLL)->i_maxFALL;
768 break;
770 case ATOM_WMV3:
771 p_track->p_asf = MP4_BoxGet( p_sample, "ASF " );
772 /* fallthrough */
773 case ATOM_H264:
774 case VLC_FOURCC('W','V','C','1'):
776 MP4_Box_t *p_strf = MP4_BoxGet( p_sample, "strf", 0 );
777 if ( p_strf && BOXDATA(p_strf) )
779 p_track->fmt.video.i_width = BOXDATA(p_strf)->bmiHeader.biWidth;
780 p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
781 p_track->fmt.video.i_height = BOXDATA(p_strf)->bmiHeader.biHeight;
782 p_track->fmt.video.i_visible_height =p_track->fmt.video.i_height;
783 p_track->fmt.video.i_bits_per_pixel = BOXDATA(p_strf)->bmiHeader.biBitCount;
784 p_track->fmt.i_extra = BOXDATA(p_strf)->i_extra;
785 if( p_track->fmt.i_extra > 0 )
787 p_track->fmt.p_extra = malloc( BOXDATA(p_strf)->i_extra );
788 memcpy( p_track->fmt.p_extra, BOXDATA(p_strf)->p_extra,
789 p_track->fmt.i_extra );
792 break;
795 case VLC_FOURCC( 'a', 'i', '5', 'p' ):
796 case VLC_FOURCC( 'a', 'i', '5', 'q' ):
797 case VLC_FOURCC( 'a', 'i', '5', '2' ):
798 case VLC_FOURCC( 'a', 'i', '5', '3' ):
799 case VLC_FOURCC( 'a', 'i', '5', '5' ):
800 case VLC_FOURCC( 'a', 'i', '5', '6' ):
801 case VLC_FOURCC( 'a', 'i', '1', 'p' ):
802 case VLC_FOURCC( 'a', 'i', '1', 'q' ):
803 case VLC_FOURCC( 'a', 'i', '1', '2' ):
804 case VLC_FOURCC( 'a', 'i', '1', '3' ):
805 case VLC_FOURCC( 'a', 'i', '1', '5' ):
806 case VLC_FOURCC( 'a', 'i', '1', '6' ):
808 if( !p_track->fmt.i_extra && p_track->fmt.video.i_width < UINT16_MAX &&
809 p_fiel && BOXDATA(p_fiel) )
811 p_track->fmt.p_extra =
812 AVCi_create_AnnexB( p_track->fmt.video.i_width,
813 !!BOXDATA(p_fiel)->i_flags, &p_track->fmt.i_extra );
815 break;
818 default:
819 msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
820 break;
823 return 1;
826 static bool SetupAudioFromWaveFormatEx( es_format_t *p_fmt, const MP4_Box_t *p_WMA2 )
828 if( p_WMA2 && BOXDATA(p_WMA2) )
830 wf_tag_to_fourcc(BOXDATA(p_WMA2)->Format.wFormatTag, &p_fmt->i_codec, NULL);
831 p_fmt->audio.i_channels = BOXDATA(p_WMA2)->Format.nChannels;
832 p_fmt->audio.i_rate = BOXDATA(p_WMA2)->Format.nSamplesPerSec;
833 p_fmt->i_bitrate = BOXDATA(p_WMA2)->Format.nAvgBytesPerSec * 8;
834 p_fmt->audio.i_blockalign = BOXDATA(p_WMA2)->Format.nBlockAlign;
835 p_fmt->audio.i_bitspersample = BOXDATA(p_WMA2)->Format.wBitsPerSample;
836 p_fmt->i_extra = BOXDATA(p_WMA2)->i_extra;
837 if( p_fmt->i_extra > 0 )
839 p_fmt->p_extra = malloc( BOXDATA(p_WMA2)->i_extra );
840 memcpy( p_fmt->p_extra, BOXDATA(p_WMA2)->p_extra, p_fmt->i_extra );
842 return true;
844 return false;
847 int SetupAudioES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
849 MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;
850 if(!p_soun)
851 return 0;
853 p_track->fmt.audio.i_channels = p_soun->i_channelcount;
854 p_track->fmt.audio.i_rate = p_soun->i_sampleratehi;
855 p_track->fmt.i_bitrate = p_soun->i_channelcount * p_soun->i_sampleratehi *
856 p_soun->i_samplesize;
857 p_track->fmt.audio.i_bitspersample = p_soun->i_samplesize;
859 p_track->fmt.i_original_fourcc = p_sample->i_type;
861 if( ( p_track->i_sample_size == 1 || p_track->i_sample_size == 2 ) )
863 if( p_soun->i_qt_version == 0 )
865 switch( p_sample->i_type )
867 case VLC_CODEC_ADPCM_IMA_QT:
868 p_soun->i_qt_version = 1;
869 p_soun->i_sample_per_packet = 64;
870 p_soun->i_bytes_per_packet = 34;
871 p_soun->i_bytes_per_frame = 34 * p_soun->i_channelcount;
872 p_soun->i_bytes_per_sample = 2;
873 break;
874 case VLC_CODEC_MACE3:
875 p_soun->i_qt_version = 1;
876 p_soun->i_sample_per_packet = 6;
877 p_soun->i_bytes_per_packet = 2;
878 p_soun->i_bytes_per_frame = 2 * p_soun->i_channelcount;
879 p_soun->i_bytes_per_sample = 2;
880 break;
881 case VLC_CODEC_MACE6:
882 p_soun->i_qt_version = 1;
883 p_soun->i_sample_per_packet = 12;
884 p_soun->i_bytes_per_packet = 2;
885 p_soun->i_bytes_per_frame = 2 * p_soun->i_channelcount;
886 p_soun->i_bytes_per_sample = 2;
887 break;
888 default:
889 p_track->fmt.i_codec = p_sample->i_type;
890 break;
894 else if( p_soun->i_qt_version == 1 && p_soun->i_sample_per_packet <= 0 )
896 p_soun->i_qt_version = 0;
899 else if( p_sample->data.p_sample_soun->i_qt_version == 1 )
901 switch( p_sample->i_type )
903 case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
904 case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
906 if( p_track->i_sample_size > 1 )
907 p_soun->i_qt_version = 0;
908 break;
910 case( ATOM_ac3 ):
911 case( ATOM_eac3 ):
912 case( VLC_FOURCC( 'm', 's', 0x20, 0x00 ) ):
913 p_soun->i_qt_version = 0;
914 break;
915 default:
916 break;
919 if ( p_sample->data.p_sample_soun->i_compressionid == 0xFFFE /* -2 */)
921 /* redefined sample tables for vbr audio */
923 else if ( p_track->i_sample_size != 0 && p_soun->i_sample_per_packet == 0 )
925 msg_Err( p_demux, "Invalid sample per packet value for qt_version 1. Broken muxer! %u %u",
926 p_track->i_sample_size, p_soun->i_sample_per_packet );
927 p_soun->i_qt_version = 0;
931 /* Endianness atom */
932 const MP4_Box_t *p_enda = MP4_BoxGet( p_sample, "wave/enda" );
933 if( !p_enda )
934 p_enda = MP4_BoxGet( p_sample, "enda" );
936 /* It's a little ugly but .. there are special cases */
937 switch( p_sample->i_type )
939 case( VLC_FOURCC( 'r', 'r', 't', 'p' ) ): /* RTP Reception Hint Track */
941 if( !SetupRTPReceptionHintTrack( p_demux, p_track, p_sample ) )
942 return 0;
943 break;
945 case ATOM_agsm: /* Apple gsm 33 bytes != MS GSM (agsm fourcc, 65 bytes) */
946 p_track->fmt.i_codec = VLC_CODEC_GSM;
947 break;
948 case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
949 case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
951 p_track->fmt.i_codec = VLC_CODEC_MPGA;
952 break;
954 case ATOM_XiVs:
956 const MP4_Box_t *p_vCtH = MP4_BoxGet( p_sample, "wave/vCtH" ); /* kCookieTypeVorbisHeader */
957 const MP4_Box_t *p_vCtd = MP4_BoxGet( p_sample, "wave/vCt#" ); /* kCookieTypeVorbisComments */
958 const MP4_Box_t *p_vCtC = MP4_BoxGet( p_sample, "wave/vCtC" ); /* kCookieTypeVorbisCodebooks */
959 if( p_vCtH && p_vCtH->data.p_binary &&
960 p_vCtd && p_vCtd->data.p_binary &&
961 p_vCtC && p_vCtC->data.p_binary )
963 unsigned headers_sizes[3] = {
964 p_vCtH->data.p_binary->i_blob,
965 p_vCtd->data.p_binary->i_blob,
966 p_vCtC->data.p_binary->i_blob
969 const void * headers[3] = {
970 p_vCtH->data.p_binary->p_blob,
971 p_vCtd->data.p_binary->p_blob,
972 p_vCtC->data.p_binary->p_blob
975 if( xiph_PackHeaders( &p_track->fmt.i_extra, &p_track->fmt.p_extra,
976 headers_sizes, headers, 3 ) == VLC_SUCCESS )
978 p_track->fmt.i_codec = VLC_CODEC_VORBIS;
979 p_track->fmt.b_packetized = false;
982 break;
984 case ATOM_XiFL:
986 const MP4_Box_t *p_fCtS = MP4_BoxGet( p_sample, "wave/fCtS" ); /* kCookieTypeFLACStreaminfo */
987 if( p_fCtS && p_fCtS->data.p_binary )
989 size_t i_extra = 8 + p_fCtS->data.p_binary->i_blob;
990 uint8_t *p_extra = malloc(i_extra);
991 if( p_extra )
993 p_track->fmt.i_extra = i_extra;
994 p_track->fmt.p_extra = p_extra;
995 memcpy( p_extra, "fLaC", 4 );
996 SetDWBE( &p_extra[4], p_fCtS->data.p_binary->i_blob ); /* want the lowest 24bits */
997 p_extra[4] = 0x80; /* 0x80 Last metablock | 0x00 StreamInfo */
998 memcpy( &p_extra[8], p_fCtS->data.p_binary->p_blob, p_fCtS->data.p_binary->i_blob );
1000 p_track->fmt.i_codec = VLC_CODEC_FLAC;
1001 p_track->fmt.b_packetized = false;
1004 break;
1006 case ATOM_fLaC:
1008 const MP4_Box_t *p_dfLa = MP4_BoxGet( p_sample, "dfLa", 0 );
1009 if( p_dfLa && p_dfLa->data.p_binary->i_blob > 4 &&
1010 GetDWBE(p_dfLa->data.p_binary->p_blob) == 0 ) /* fullbox header, avoids creating dedicated parser */
1012 size_t i_extra = p_dfLa->data.p_binary->i_blob;
1013 uint8_t *p_extra = malloc(i_extra);
1014 if( likely( p_extra ) )
1016 p_track->fmt.i_extra = i_extra;
1017 p_track->fmt.p_extra = p_extra;
1018 memcpy( p_extra, p_dfLa->data.p_binary->p_blob, p_dfLa->data.p_binary->i_blob);
1019 memcpy( p_extra, "fLaC", 4 );
1020 p_track->fmt.i_codec = VLC_CODEC_FLAC;
1023 break;
1025 case( ATOM_eac3 ):
1027 p_track->fmt.i_codec = VLC_CODEC_EAC3;
1028 /* TS 102.366. F6 The values of the ChannelCount and SampleSize fields
1029 * within the EC3SampleEntry Box shall be ignored. */
1030 p_track->fmt.audio.i_channels = 0;
1031 p_track->fmt.audio.i_bitspersample = 0;
1033 const MP4_Box_t *p_dec3 = MP4_BoxGet( p_sample, "dec3", 0 );
1034 if( p_dec3 && BOXDATA(p_dec3) )
1036 p_track->fmt.i_bitrate = BOXDATA(p_dec3)->i_data_rate * 1000;
1038 break;
1040 case( ATOM_AC3 ):
1041 case( ATOM_ac3 ):
1043 p_track->fmt.i_codec = VLC_CODEC_A52;
1044 /* TS 102.366. F3 The values of the ChannelCount and SampleSize fields
1045 * within the AC3SampleEntry Box shall be ignored */
1046 p_track->fmt.audio.i_channels = 0;
1047 p_track->fmt.audio.i_bitspersample = 0;
1049 MP4_Box_t *p_dac3 = MP4_BoxGet( p_sample, "dac3", 0 );
1050 if( p_dac3 && BOXDATA(p_dac3) )
1052 static const int pi_bitrate[] = {
1053 32, 40, 48, 56,
1054 64, 80, 96, 112,
1055 128, 160, 192, 224,
1056 256, 320, 384, 448,
1057 512, 576, 640,
1059 p_track->fmt.i_bitrate = 0;
1060 if( BOXDATA(p_dac3)->i_bitrate_code < sizeof(pi_bitrate)/sizeof(*pi_bitrate) )
1061 p_track->fmt.i_bitrate = pi_bitrate[BOXDATA(p_dac3)->i_bitrate_code] * 1000;
1063 break;
1066 case ATOM_dtse: /* DTS‐HD Lossless formats */
1067 case ATOM_dtsh: /* DTS‐HD audio formats */
1068 case ATOM_dtsl: /* DTS‐HD Lossless formats */
1070 p_track->fmt.i_codec = VLC_CODEC_DTS;
1071 p_track->fmt.i_profile = PROFILE_DTS_HD;
1072 break;
1075 case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):
1076 case( VLC_FOURCC( 'N', 'O', 'N', 'E' ) ):
1078 if( (p_soun->i_samplesize+7)/8 == 1 )
1079 p_track->fmt.i_codec = VLC_CODEC_U8;
1080 else
1081 p_track->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
1083 /* Buggy files workaround */
1084 if( (p_track->i_timescale != p_soun->i_sampleratehi) )
1086 msg_Warn( p_demux, "i_timescale (%"PRId32") != i_sampleratehi "
1087 "(%u), making both equal (report any problem).",
1088 p_track->i_timescale, p_soun->i_sampleratehi );
1090 if( p_soun->i_sampleratehi != 0 )
1091 p_track->i_timescale = p_soun->i_sampleratehi;
1092 else
1093 p_soun->i_sampleratehi = p_track->i_timescale;
1095 break;
1098 case ATOM_in24:
1099 p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1100 VLC_CODEC_S24L : VLC_CODEC_S24B;
1101 break;
1102 case ATOM_in32:
1103 p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1104 VLC_CODEC_S32L : VLC_CODEC_S32B;
1105 break;
1106 case ATOM_fl32:
1107 p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1108 VLC_CODEC_F32L : VLC_CODEC_F32B;
1109 break;
1110 case ATOM_fl64:
1111 p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1112 VLC_CODEC_F64L : VLC_CODEC_F64B;
1113 break;
1115 case VLC_CODEC_DVD_LPCM:
1117 if( p_soun->i_qt_version == 2 )
1119 /* Flags:
1120 * 0x01: IsFloat
1121 * 0x02: IsBigEndian
1122 * 0x04: IsSigned
1124 static const struct {
1125 unsigned i_flags;
1126 unsigned i_mask;
1127 unsigned i_bits;
1128 vlc_fourcc_t i_codec;
1129 } p_formats[] = {
1130 { 0x01, 0x03, 32, VLC_CODEC_F32L },
1131 { 0x01, 0x03, 64, VLC_CODEC_F64L },
1132 { 0x01|0x02, 0x03, 32, VLC_CODEC_F32B },
1133 { 0x01|0x02, 0x03, 64, VLC_CODEC_F64B },
1135 { 0x00, 0x05, 8, VLC_CODEC_U8 },
1136 { 0x00| 0x04, 0x05, 8, VLC_CODEC_S8 },
1138 { 0x00, 0x07, 16, VLC_CODEC_U16L },
1139 { 0x00|0x02, 0x07, 16, VLC_CODEC_U16B },
1140 { 0x00 |0x04, 0x07, 16, VLC_CODEC_S16L },
1141 { 0x00|0x02|0x04, 0x07, 16, VLC_CODEC_S16B },
1143 { 0x00, 0x07, 24, VLC_CODEC_U24L },
1144 { 0x00|0x02, 0x07, 24, VLC_CODEC_U24B },
1145 { 0x00 |0x04, 0x07, 24, VLC_CODEC_S24L },
1146 { 0x00|0x02|0x04, 0x07, 24, VLC_CODEC_S24B },
1148 { 0x00, 0x07, 32, VLC_CODEC_U32L },
1149 { 0x00|0x02, 0x07, 32, VLC_CODEC_U32B },
1150 { 0x00 |0x04, 0x07, 32, VLC_CODEC_S32L },
1151 { 0x00|0x02|0x04, 0x07, 32, VLC_CODEC_S32B },
1153 {0, 0, 0, 0}
1156 for( int i = 0; p_formats[i].i_codec; i++ )
1158 if( p_formats[i].i_bits == p_soun->i_constbitsperchannel &&
1159 (p_soun->i_formatflags & p_formats[i].i_mask) == p_formats[i].i_flags )
1161 p_track->fmt.i_codec = p_formats[i].i_codec;
1162 p_track->fmt.audio.i_bitspersample = p_soun->i_constbitsperchannel;
1163 p_track->fmt.audio.i_blockalign =
1164 p_soun->i_channelcount * p_soun->i_constbitsperchannel / 8;
1165 p_track->i_sample_size = p_track->fmt.audio.i_blockalign;
1167 p_soun->i_qt_version = 0;
1168 break;
1172 break;
1174 default:
1175 p_track->fmt.i_codec = p_sample->i_type;
1176 break;
1180 /* Process extensions */
1182 /* Lookup for then channels extension */
1183 const MP4_Box_t *p_chan = MP4_BoxGet( p_sample, "chan" );
1184 if ( p_chan )
1186 uint16_t i_vlc_mapping = 0;
1187 uint8_t i_channels = 0;
1188 const uint32_t *p_rg_chans_order = NULL;
1190 if ( BOXDATA(p_chan)->layout.i_channels_layout_tag == CoreAudio_Layout_BITMAP &&
1191 CoreAudio_Bitmap_to_vlc_bitmap( &BOXDATA(p_chan)->layout,
1192 &i_vlc_mapping, &i_channels,
1193 &p_rg_chans_order ) != VLC_SUCCESS )
1195 msg_Warn( p_demux, "discarding chan mapping" );
1198 if( i_vlc_mapping )
1200 const unsigned i_bps = aout_BitsPerSample( p_track->fmt.i_codec );
1201 /* Uncompressed audio */
1202 if( i_bps && aout_CheckChannelReorder( p_rg_chans_order, NULL,
1203 i_vlc_mapping,
1204 p_track->rgi_chans_reordering ) )
1205 p_track->b_chans_reorder = true;
1207 /* we can only set bitmap for VLC mapping or [re]mapped pcm audio
1208 * as vlc can't enumerate channels for compressed content */
1209 if( i_bps || p_track->rgi_chans_reordering == NULL )
1211 p_track->fmt.audio.i_channels = i_channels;
1212 p_track->fmt.audio.i_physical_channels = i_vlc_mapping;
1217 SetupGlobalExtensions( p_track, p_sample );
1219 /* now see if esds is present and if so create a data packet
1220 with decoder_specific_info */
1221 MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
1222 if ( !p_esds ) p_esds = MP4_BoxGet( p_sample, "wave/esds" );
1223 if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
1225 assert(p_sample->i_type == ATOM_mp4a);
1226 SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
1228 else switch( p_sample->i_type )
1230 case VLC_CODEC_AMR_NB:
1231 p_track->fmt.audio.i_rate = 8000;
1232 break;
1233 case VLC_CODEC_AMR_WB:
1234 p_track->fmt.audio.i_rate = 16000;
1235 break;
1236 case VLC_CODEC_QDMC:
1237 case VLC_CODEC_QDM2:
1238 case VLC_CODEC_ALAC:
1240 p_track->fmt.i_extra =
1241 p_sample->data.p_sample_soun->i_qt_description;
1242 if( p_track->fmt.i_extra > 0 )
1244 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
1245 memcpy( p_track->fmt.p_extra,
1246 p_sample->data.p_sample_soun->p_qt_description,
1247 p_track->fmt.i_extra);
1249 if( p_track->fmt.i_extra == 56 && p_sample->i_type == VLC_CODEC_ALAC )
1251 p_track->fmt.audio.i_channels = *((uint8_t*)p_track->fmt.p_extra + 41);
1252 p_track->fmt.audio.i_rate = GetDWBE((uint8_t*)p_track->fmt.p_extra + 52);
1254 break;
1256 case VLC_CODEC_ADPCM_MS:
1257 case VLC_CODEC_ADPCM_IMA_WAV:
1258 case VLC_CODEC_QCELP:
1260 p_track->fmt.audio.i_blockalign = p_sample->data.p_sample_soun->i_bytes_per_frame;
1261 break;
1263 case ATOM_WMA2:
1265 if( SetupAudioFromWaveFormatEx( &p_track->fmt,
1266 MP4_BoxGet( p_sample, "wave/WMA2" ) ) )
1268 p_track->p_asf = MP4_BoxGet( p_sample, "wave/ASF " );
1270 else
1272 msg_Err( p_demux, "missing WMA2 %4.4s", (char*) &p_sample->p_father->i_type );
1274 break;
1276 case ATOM_wma: /* isml wmapro */
1278 if( !SetupAudioFromWaveFormatEx( &p_track->fmt, MP4_BoxGet( p_sample, "wfex" ) ) )
1279 msg_Err( p_demux, "missing wfex for wma" );
1280 break;
1283 default:
1284 if(p_track->fmt.i_codec == 0)
1285 msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
1286 break;
1289 /* Ambisonics */
1290 const MP4_Box_t *p_SA3D = MP4_BoxGet(p_sample, "SA3D");
1291 if (p_SA3D && BOXDATA(p_SA3D))
1292 p_track->fmt.audio.channel_type = AUDIO_CHANNEL_TYPE_AMBISONICS;
1294 /* Late fixes */
1295 if ( p_soun->i_qt_version == 0 && p_track->fmt.i_codec == VLC_CODEC_QCELP )
1297 /* Shouldn't be v0, as it is a compressed codec !*/
1298 p_soun->i_qt_version = 1;
1299 p_soun->i_compressionid = 0xFFFE;
1302 return 1;
1305 int SetupSpuES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
1307 /* It's a little ugly but .. there are special cases */
1308 switch( p_sample->i_type )
1310 case VLC_FOURCC('s','t','p','p'):
1311 p_track->fmt.i_codec = VLC_CODEC_TTML;
1312 break;
1313 case ATOM_wvtt:
1314 p_track->fmt.i_codec = VLC_CODEC_WEBVTT;
1315 break;
1316 case ATOM_c608: /* EIA608 closed captions */
1317 p_track->fmt.i_codec = VLC_CODEC_CEA608;
1318 p_track->fmt.subs.cc.i_reorder_depth = -1;
1319 break;
1320 case ATOM_c708: /* EIA708 closed captions */
1321 p_track->fmt.i_codec = VLC_CODEC_CEA708;
1322 p_track->fmt.subs.cc.i_reorder_depth = -1;
1323 break;
1325 case( VLC_FOURCC( 't', 'e', 'x', 't' ) ):
1326 case( VLC_FOURCC( 't', 'x', '3', 'g' ) ):
1328 const MP4_Box_data_sample_text_t *p_text = p_sample->data.p_sample_text;
1329 if(!p_text)
1330 return 0;
1332 if( p_sample->i_type == VLC_FOURCC( 't', 'e', 'x', 't' ) )
1333 p_track->fmt.i_codec = VLC_CODEC_QTXT;
1334 else
1335 p_track->fmt.i_codec = VLC_CODEC_TX3G;
1337 if( GetDWBE(p_text->p_data) & 0xC0000000 )
1339 p_track->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1;
1340 p_track->b_forced_spu = true;
1343 p_track->fmt.p_extra = malloc( p_text->i_data );
1344 if( p_track->fmt.p_extra )
1346 memcpy( p_track->fmt.p_extra, p_text->p_data, p_text->i_data );
1347 p_track->fmt.i_extra = p_text->i_data;
1350 /* FIXME UTF-8 doesn't work here ? */
1351 if( p_track->b_mac_encoding )
1352 p_track->fmt.subs.psz_encoding = strdup( "MAC" );
1353 else
1354 p_track->fmt.subs.psz_encoding = strdup( "UTF-8" );
1355 break;
1358 default:
1359 p_track->fmt.i_codec = p_sample->i_type;
1360 break;
1363 SetupGlobalExtensions( p_track, p_sample );
1365 /* now see if esds is present and if so create a data packet
1366 with decoder_specific_info */
1367 MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
1368 if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
1370 SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
1373 return 1;