es: pass no cc reorder in es fmt
[vlc.git] / modules / demux / mp4 / essetup.c
blob1ff001602d18780977c13215c2dd26c23b3f9607
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"
31 #include <vlc_demux.h>
32 #include <vlc_aout.h>
33 #include <assert.h>
38 static void SetupGlobalExtensions( mp4_track_t *p_track, MP4_Box_t *p_sample )
40 if( !p_track->fmt.i_bitrate )
42 const MP4_Box_t *p_btrt = MP4_BoxGet( p_sample, "btrt" );
43 if( p_btrt && BOXDATA(p_btrt) )
45 p_track->fmt.i_bitrate = BOXDATA(p_btrt)->i_avg_bitrate;
50 static void SetupESDS( demux_t *p_demux, mp4_track_t *p_track, const MP4_descriptor_decoder_config_t *p_decconfig )
52 /* First update information based on i_objectTypeIndication */
53 switch( p_decconfig->i_objectProfileIndication )
55 case( 0x20 ): /* MPEG4 VIDEO */
56 p_track->fmt.i_codec = VLC_CODEC_MP4V;
57 break;
58 case( 0x21 ): /* H.264 */
59 p_track->fmt.i_codec = VLC_CODEC_H264;
60 break;
61 case( 0x40):
62 case( 0x41):
63 p_track->fmt.i_codec = VLC_CODEC_MP4A;
64 if( p_decconfig->i_decoder_specific_info_len >= 2 &&
65 p_decconfig->p_decoder_specific_info[0] == 0xF8 &&
66 (p_decconfig->p_decoder_specific_info[1]&0xE0) == 0x80 )
68 p_track->fmt.i_codec = VLC_CODEC_ALS;
70 break;
71 case( 0x60):
72 case( 0x61):
73 case( 0x62):
74 case( 0x63):
75 case( 0x64):
76 case( 0x65): /* MPEG2 video */
77 p_track->fmt.i_codec = VLC_CODEC_MPGV;
78 break;
79 /* Theses are MPEG2-AAC */
80 case( 0x66): /* main profile */
81 case( 0x67): /* Low complexity profile */
82 case( 0x68): /* Scaleable Sampling rate profile */
83 p_track->fmt.i_codec = VLC_CODEC_MP4A;
84 break;
85 /* True MPEG 2 audio */
86 case( 0x69):
87 p_track->fmt.i_codec = VLC_CODEC_MPGA;
88 break;
89 case( 0x6a): /* MPEG1 video */
90 p_track->fmt.i_codec = VLC_CODEC_MPGV;
91 break;
92 case( 0x6b): /* MPEG1 audio */
93 p_track->fmt.i_codec = VLC_CODEC_MPGA;
94 break;
95 case( 0x6c ): /* jpeg */
96 p_track->fmt.i_codec = VLC_CODEC_JPEG;
97 break;
98 case( 0x6d ): /* png */
99 p_track->fmt.i_codec = VLC_CODEC_PNG;
100 break;
101 case( 0x6e ): /* jpeg2000 */
102 p_track->fmt.i_codec = VLC_FOURCC( 'M','J','2','C' );
103 break;
104 case( 0xa3 ): /* vc1 */
105 p_track->fmt.i_codec = VLC_CODEC_VC1;
106 break;
107 case( 0xa4 ):
108 p_track->fmt.i_codec = VLC_CODEC_DIRAC;
109 break;
110 case( 0xa5 ):
111 p_track->fmt.i_codec = VLC_CODEC_A52;
112 break;
113 case( 0xa6 ):
114 p_track->fmt.i_codec = VLC_CODEC_EAC3;
115 break;
116 case( 0xa9 ): /* dts */
117 case( 0xaa ): /* DTS-HD HRA */
118 case( 0xab ): /* DTS-HD Master Audio */
119 p_track->fmt.i_codec = VLC_CODEC_DTS;
120 break;
121 case( 0xDD ):
122 p_track->fmt.i_codec = VLC_CODEC_VORBIS;
123 break;
125 /* Private ID */
126 case( 0xe0 ): /* NeroDigital: dvd subs */
127 if( p_track->fmt.i_cat == SPU_ES )
129 p_track->fmt.i_codec = VLC_CODEC_SPU;
130 if( p_track->i_width > 0 )
131 p_track->fmt.subs.spu.i_original_frame_width = p_track->i_width;
132 if( p_track->i_height > 0 )
133 p_track->fmt.subs.spu.i_original_frame_height = p_track->i_height;
134 break;
136 case( 0xe1 ): /* QCelp for 3gp */
137 if( p_track->fmt.i_cat == AUDIO_ES )
139 p_track->fmt.i_codec = VLC_CODEC_QCELP;
141 break;
143 /* Fallback */
144 default:
145 /* Unknown entry, but don't touch i_fourcc */
146 msg_Warn( p_demux,
147 "unknown objectProfileIndication(0x%x) (Track[ID 0x%x])",
148 p_decconfig->i_objectProfileIndication,
149 p_track->i_track_ID );
150 break;
153 p_track->fmt.i_bitrate = p_decconfig->i_avg_bitrate;
155 p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len;
156 if( p_track->fmt.i_extra > 0 )
158 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
159 memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info,
160 p_track->fmt.i_extra );
162 if( p_track->fmt.i_codec == VLC_CODEC_SPU &&
163 p_track->fmt.i_extra >= 16 * 4 )
165 for( int i = 0; i < 16; i++ )
167 p_track->fmt.subs.spu.palette[1 + i] =
168 GetDWBE((char*)p_track->fmt.p_extra + i * 4);
170 p_track->fmt.subs.spu.palette[0] = SPU_PALETTE_DEFINED;
174 static int SetupRTPReceptionHintTrack( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
176 p_track->fmt.i_original_fourcc = p_sample->i_type;
178 if( !p_track->p_sdp )
180 msg_Err(p_demux, "Required 'sdp '-box not found");
181 return 0;
183 MP4_Box_t *p_sdp = p_track->p_sdp;
184 char *strtok_state;
185 char * pch = strtok_r(BOXDATA(p_sdp)->psz_text, " =\n", &strtok_state); /* media entry */
186 if( pch && pch[0] != 'm' )
188 msg_Err(p_demux, "No Media entry found in SDP:%s", pch);
189 return 0;
192 if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* media type */
193 return 0;
194 /* media type has already been checked */
195 msg_Dbg(p_demux, "sdp: media type:%s", pch);
196 if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* port */
197 return 0;
198 msg_Dbg(p_demux, "sdp: port:%s", pch);
199 if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* protocol */
200 return 0;
201 msg_Dbg(p_demux, "sdp: protocol:%s", pch);
203 if( !( pch = strtok_r(NULL, " =\n", &strtok_state) ) ) /* fmt */
204 return 0;
206 bool codec_set = false;
207 /* process rtp types until we get an attribute field or end of sdp */
208 while( pch && pch[0] != 'a' )
210 int rtp_payload = atoi(pch);
211 msg_Dbg(p_demux, "sdp: payload type:%d", rtp_payload);
213 if( !codec_set )
215 /* Payload types 34 and under have a set type and can be identified here */
216 switch( rtp_payload )
218 case 3:
219 p_track->fmt.i_codec = VLC_CODEC_GSM;
220 codec_set = true;
221 break;
222 default:
223 break;
226 pch = strtok_r(NULL, " =\n", &strtok_state); /* attribute or additional payload type */
227 if( !pch && !codec_set )
228 return 0;
231 while( pch && pch[0] == 'a' )
233 if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* attribute type */
234 return 0;
235 msg_Dbg(p_demux, "sdp: atrribute type:%s", pch);
237 if( !strcmp(pch, "rtpmap") )
239 if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* payload type */
240 return 0;
241 msg_Dbg(p_demux, "sdp: payload type:%s", pch);
242 if( !(pch = strtok_r(NULL, " /:=\n", &strtok_state) ) ) /* encoding name */
243 return 0;
244 msg_Dbg(p_demux, "sdp: encoding name:%s", pch);
246 /* Simply adding codec recognition should work for most codecs */
247 /* Codecs using slices need their picture constructed from sample */
248 if( !strcmp(pch, "H264") )
250 p_track->fmt.i_codec = VLC_CODEC_H264;
251 /* ******* sending AnnexB ! */
252 p_track->fmt.b_packetized = false;
254 else if( !strcmp(pch, "GSM") )
256 p_track->fmt.i_codec = VLC_CODEC_GSM;
258 else if( !strcmp(pch, "Speex") )
260 p_track->fmt.i_codec = VLC_CODEC_SPEEX;
262 else if( !codec_set )
264 msg_Err(p_demux, "Support for codec contained in RTP \
265 Reception Hint Track RTP stream has not been added");
266 return 0;
269 if( !( pch = strtok_r(NULL, " :=\n", &strtok_state) ) ) /* clock rate */
270 return 0;
271 int clock_rate = atoi(pch);
272 msg_Dbg(p_demux, "sdp clock rate:%d", clock_rate);
273 if( p_track->fmt.i_cat == AUDIO_ES )
274 p_track->fmt.audio.i_rate = clock_rate;
276 pch = strtok_r(NULL, " =\n", &strtok_state); /* next attribute */
279 const MP4_Box_t *p_tims = MP4_BoxGet(p_sample, "tims");
280 if( p_tims && BOXDATA(p_tims) && BOXDATA(p_tims)->i_timescale )
282 p_track->i_timescale = BOXDATA(p_tims)->i_timescale;
284 else
286 msg_Warn(p_demux, "Missing mandatory box tims");
287 return 0;
290 const MP4_Box_t *p_tssy = MP4_BoxGet(p_sample, "tssy");
291 if( p_tssy && BOXDATA(p_tssy) )
293 /* take the 2 last bits which indicate the synchronization mode */
294 p_track->sync_mode = (RTP_timstamp_synchronization_t)
295 BOXDATA(p_tssy)->i_reserved_timestamp_sync & 0x03;
298 const MP4_Box_t *p_tsro = MP4_BoxGet(p_sample, "tsro");
299 if( p_tsro && BOXDATA(p_tsro) )
300 p_track->i_tsro_offset = BOXDATA(p_tsro)->i_offset;
301 else
302 msg_Dbg(p_demux, "No tsro box present");
303 msg_Dbg(p_demux, "setting tsro: %" PRId32, p_track->i_tsro_offset);
305 return 1;
309 int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
311 MP4_Box_data_sample_vide_t *p_vide = p_sample->data.p_sample_vide;
312 if(!p_vide)
313 return 0;
315 p_track->fmt.video.i_width = p_vide->i_width;
316 p_track->fmt.video.i_height = p_vide->i_height;
317 p_track->fmt.video.i_bits_per_pixel = p_vide->i_depth;
319 /* fall on display size */
320 if( p_track->fmt.video.i_width <= 0 )
321 p_track->fmt.video.i_width = p_track->i_width;
322 if( p_track->fmt.video.i_height <= 0 )
323 p_track->fmt.video.i_height = p_track->i_height;
325 /* Find out apect ratio from display size */
326 if( p_track->i_width > 0 && p_track->i_height > 0 &&
327 /* Work-around buggy muxed files */
328 p_vide->i_width != p_track->i_width )
330 p_track->fmt.video.i_sar_num = p_track->i_width * p_track->fmt.video.i_height;
331 p_track->fmt.video.i_sar_den = p_track->i_height * p_track->fmt.video.i_width;
334 /* Support for cropping (eg. in H263 files) */
335 p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
336 p_track->fmt.video.i_visible_height = p_track->fmt.video.i_height;
338 /* Rotation */
339 switch( (int)p_track->f_rotation ) {
340 case 90:
341 p_track->fmt.video.orientation = ORIENT_ROTATED_90;
342 break;
343 case 180:
344 p_track->fmt.video.orientation = ORIENT_ROTATED_180;
345 break;
346 case 270:
347 p_track->fmt.video.orientation = ORIENT_ROTATED_270;
348 break;
351 /* Set 360 video mode */
352 p_track->fmt.video.projection_mode = PROJECTION_MODE_RECTANGULAR;
353 const MP4_Box_t *p_uuid = MP4_BoxGet( p_track->p_track, "uuid" );
354 for( ; p_uuid; p_uuid = p_uuid->p_next)
356 if( p_uuid->i_type == ATOM_uuid
357 && !CmpUUID( &p_uuid->i_uuid, &XML360BoxUUID )
358 && p_uuid->data.p_360 )
360 p_track->fmt.video.projection_mode = p_uuid->data.p_360->i_projection_mode;
361 switch (p_uuid->data.p_360->e_stereo_mode)
363 case XML360_STEREOSCOPIC_TOP_BOTTOM:
364 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;
365 break;
366 case XML360_STEREOSCOPIC_LEFT_RIGHT:
367 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS;
368 break;
369 default:
370 p_track->fmt.video.multiview_mode = MULTIVIEW_2D;
371 break;
376 const MP4_Box_t *p_st3d = MP4_BoxGet( p_sample, "st3d" );
377 if (p_st3d && BOXDATA(p_st3d))
379 switch( BOXDATA(p_st3d)->i_stereo_mode )
381 case ST3D_MONOSCOPIC:
382 p_track->fmt.video.multiview_mode = MULTIVIEW_2D;
383 break;
384 case ST3D_STEREOSCOPIC_TOP_BOTTOM:
385 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_TB;
386 break;
387 case ST3D_STEREOSCOPIC_LEFT_RIGHT:
388 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_SBS;
389 break;
390 default:
391 msg_Warn( p_demux, "Unknown stereo mode %d", BOXDATA(p_st3d)->i_stereo_mode );
392 break;
395 else
397 for( p_uuid = MP4_BoxGet( p_sample, "uuid" ); p_uuid;
398 p_uuid = p_uuid->p_next )
400 if( p_uuid->i_type == ATOM_uuid &&
401 !CmpUUID( &p_uuid->i_uuid, &PS3DDSBoxUUID ) &&
402 p_uuid->data.p_binary &&
403 p_uuid->data.p_binary->i_blob == 4 &&
404 !memcmp( p_uuid->data.p_binary->p_blob, "\x82\x81\x10\x02", 4 ) )
406 p_track->fmt.video.multiview_mode = MULTIVIEW_STEREO_FRAME;
407 break;
412 const MP4_Box_t *p_prhd = MP4_BoxGet( p_sample, "sv3d/proj/prhd" );
413 if (p_prhd && BOXDATA(p_prhd))
415 p_track->fmt.video.pose.yaw = BOXDATA(p_prhd)->f_pose_yaw_degrees;
416 p_track->fmt.video.pose.pitch = BOXDATA(p_prhd)->f_pose_pitch_degrees;
417 p_track->fmt.video.pose.roll = BOXDATA(p_prhd)->f_pose_roll_degrees;
420 const MP4_Box_t *p_equi = MP4_BoxGet( p_sample, "sv3d/proj/equi" );
421 const MP4_Box_t *p_cbmp = MP4_BoxGet( p_sample, "sv3d/proj/cbmp" );
422 if (p_equi && BOXDATA(p_equi))
423 p_track->fmt.video.projection_mode = PROJECTION_MODE_EQUIRECTANGULAR;
424 else if (p_cbmp && BOXDATA(p_cbmp))
425 p_track->fmt.video.projection_mode = PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD;
427 /* It's a little ugly but .. there are special cases */
428 switch( p_sample->i_type )
430 case( VLC_FOURCC( 's', '2', '6', '3' ) ):
431 p_track->fmt.i_codec = VLC_CODEC_H263;
432 break;
433 case VLC_FOURCC('y','v','1','2'):
434 p_track->fmt.i_codec = VLC_CODEC_YV12;
435 break;
436 case VLC_FOURCC('y','u','v','2'):
437 p_track->fmt.i_codec = VLC_CODEC_YUYV;
438 break;
439 case VLC_FOURCC('r','a','w',' '):
440 switch( p_vide->i_depth ) {
441 case 16:
442 p_track->fmt.i_codec = VLC_CODEC_RGB15;
443 break;
444 case 24:
445 p_track->fmt.i_codec = VLC_CODEC_RGB24;
446 break;
447 case 32:
448 p_track->fmt.i_codec = VLC_CODEC_ARGB;
449 break;
450 case 32 + 8:
451 p_track->fmt.i_codec = VLC_CODEC_GREY;
452 break;
453 default:
454 msg_Dbg( p_demux, "Unrecognized raw video format (depth = %d)",
455 p_vide->i_depth );
456 p_track->fmt.i_codec = p_sample->i_type;
457 break;
459 break;
460 case( VLC_FOURCC( 'r', 'r', 't', 'p' ) ): /* RTP Reception Hint Track */
462 if( !SetupRTPReceptionHintTrack( p_demux, p_track, p_sample ) )
463 p_track->fmt.i_codec = p_sample->i_type;
464 break;
466 default:
467 p_track->fmt.i_codec = p_sample->i_type;
468 break;
472 /* Read extensions */
474 /* Set up A/R from extension atom */
475 const MP4_Box_t *p_pasp = MP4_BoxGet( p_sample, "pasp" );
476 if( p_pasp && BOXDATA(p_pasp) && BOXDATA(p_pasp)->i_horizontal_spacing > 0 &&
477 BOXDATA(p_pasp)->i_vertical_spacing > 0 )
479 p_track->fmt.video.i_sar_num = BOXDATA(p_pasp)->i_horizontal_spacing;
480 p_track->fmt.video.i_sar_den = BOXDATA(p_pasp)->i_vertical_spacing;
483 const MP4_Box_t *p_fiel = MP4_BoxGet( p_sample, "fiel" );
484 if( p_fiel && BOXDATA(p_fiel) )
486 p_track->i_block_flags = BOXDATA(p_fiel)->i_flags;
489 const MP4_Box_t *p_colr = MP4_BoxGet( p_sample, "colr" );
490 if ( p_colr != NULL )
492 if ( BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'c' ) ||
493 BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'x' ) )
495 switch ( BOXDATA( p_colr )->nclc.i_primary_idx )
497 case 1: p_track->fmt.video.primaries = COLOR_PRIMARIES_BT709; break;
498 case 5: p_track->fmt.video.primaries = COLOR_PRIMARIES_BT601_625; break;
499 case 6: p_track->fmt.video.primaries = COLOR_PRIMARIES_BT601_525; break;
501 switch ( BOXDATA( p_colr )->nclc.i_transfer_function_idx )
503 case 1: p_track->fmt.video.transfer = TRANSFER_FUNC_BT709; break;
505 switch ( BOXDATA( p_colr )->nclc.i_matrix_idx )
507 case 1: p_track->fmt.video.space = COLOR_SPACE_BT709; break;
508 case 2: p_track->fmt.video.space = COLOR_SPACE_BT601; break;
510 p_track->fmt.video.b_color_range_full = BOXDATA(p_colr)->i_type == VLC_FOURCC( 'n', 'c', 'l', 'x' ) &&
511 (BOXDATA(p_colr)->nclc.i_full_range >> 7) != 0;
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('j', 'p', 'e', 'g'):
562 p_track->fmt.i_codec = VLC_CODEC_MJPG;
563 break;
565 case VLC_CODEC_FFV1:
567 MP4_Box_t *p_binary = MP4_BoxGet( p_sample, "glbl" );
568 if( p_binary && BOXDATA(p_binary) && BOXDATA(p_binary)->i_blob )
570 p_track->fmt.p_extra = malloc( BOXDATA(p_binary)->i_blob );
571 if( p_track->fmt.p_extra )
573 p_track->fmt.i_extra = BOXDATA(p_binary)->i_blob;
574 memcpy( p_track->fmt.p_extra, BOXDATA(p_binary)->p_blob,
575 p_track->fmt.i_extra );
578 break;
581 case VLC_FOURCC( 'v', 'c', '-', '1' ):
583 MP4_Box_t *p_dvc1 = MP4_BoxGet( p_sample, "dvc1" );
584 if( p_dvc1 && BOXDATA(p_dvc1) )
586 p_track->fmt.i_extra = BOXDATA(p_dvc1)->i_vc1;
587 if( p_track->fmt.i_extra > 0 )
589 p_track->fmt.p_extra = malloc( BOXDATA(p_dvc1)->i_vc1 );
590 memcpy( p_track->fmt.p_extra, BOXDATA(p_dvc1)->p_vc1,
591 p_track->fmt.i_extra );
594 else
596 msg_Err( p_demux, "missing dvc1" );
598 break;
601 /* avc1: send avcC (h264 without annexe B, ie without start code)*/
602 case VLC_FOURCC( 'a', 'v', 'c', '3' ):
603 case VLC_FOURCC( 'a', 'v', 'c', '1' ):
604 case VLC_FOURCC( 'd', 'v', 'a', '1' ): /* DolbyVision */
605 case VLC_FOURCC( 'd', 'v', 'a', 'v' ): /* DolbyVision */
607 MP4_Box_t *p_avcC = MP4_BoxGet( p_sample, "avcC" );
609 if( p_avcC && BOXDATA(p_avcC) )
611 p_track->fmt.i_extra = BOXDATA(p_avcC)->i_avcC;
612 if( p_track->fmt.i_extra > 0 )
614 p_track->fmt.p_extra = malloc( BOXDATA(p_avcC)->i_avcC );
615 memcpy( p_track->fmt.p_extra, BOXDATA(p_avcC)->p_avcC,
616 p_track->fmt.i_extra );
619 else
621 msg_Err( p_demux, "missing avcC" );
623 break;
625 case VLC_FOURCC( 'h', 'v', 'c', '1' ):
626 case VLC_FOURCC( 'h', 'e', 'v', '1' ):
627 case VLC_FOURCC( 'd', 'v', 'h', 'e' ): /* DolbyVision */
628 case VLC_FOURCC( 'd', 'v', 'h', '1' ): /* DolbyVision */
630 MP4_Box_t *p_hvcC = MP4_BoxGet( p_sample, "hvcC" );
632 /* Handle DV fourcc collision at demux level */
633 if( p_sample->i_type == VLC_FOURCC( 'd', 'v', 'h', '1' ) )
634 p_track->fmt.i_codec = VLC_FOURCC( 'd', 'v', 'h', 'e' );
636 if( p_hvcC && p_hvcC->data.p_binary && p_hvcC->data.p_binary->i_blob )
638 p_track->fmt.p_extra = malloc( p_hvcC->data.p_binary->i_blob );
639 if( p_track->fmt.p_extra )
641 p_track->fmt.i_extra = p_hvcC->data.p_binary->i_blob;
642 memcpy( p_track->fmt.p_extra, p_hvcC->data.p_binary->p_blob,
643 p_hvcC->data.p_binary->i_blob );
646 else
648 msg_Err( p_demux, "missing hvcC" );
650 break;
653 case ATOM_vp08:
654 case ATOM_vp09:
655 case ATOM_vp10:
657 const MP4_Box_t *p_vpcC = MP4_BoxGet( p_sample, "vpcC" );
658 if( p_vpcC && BOXDATA(p_vpcC) )
660 const MP4_Box_data_vpcC_t *p_data = BOXDATA(p_vpcC);
661 if( p_sample->i_type == ATOM_vp10 )
662 p_track->fmt.i_codec = VLC_CODEC_VP10;
663 else if( p_sample->i_type == ATOM_vp09 )
664 p_track->fmt.i_codec = VLC_CODEC_VP9;
665 else
666 p_track->fmt.i_codec = VLC_CODEC_VP8;
667 p_track->fmt.i_profile = p_data->i_profile;
668 p_track->fmt.i_level = p_data->i_level;
669 const uint8_t colorspacesmapping[] =
671 COLOR_SPACE_UNDEF,
672 COLOR_SPACE_BT601,
673 COLOR_SPACE_BT709,
674 COLOR_SPACE_SMPTE_170,
675 COLOR_SPACE_SMPTE_240,
676 COLOR_SPACE_BT2020,
677 COLOR_SPACE_BT2020,
678 COLOR_SPACE_SRGB,
680 if( p_data->i_color_space < ARRAY_SIZE(colorspacesmapping) )
681 p_track->fmt.video.space = colorspacesmapping[p_data->i_color_space];
683 if( p_data->i_xfer_function == 0 )
684 p_track->fmt.video.transfer = TRANSFER_FUNC_BT709;
685 else if ( p_data->i_xfer_function == 1 )
686 p_track->fmt.video.transfer = TRANSFER_FUNC_SMPTE_ST2084;
688 p_track->fmt.video.b_color_range_full = p_data->i_fullrange;
689 p_track->fmt.video.i_bits_per_pixel = p_data->i_bit_depth;
691 if( p_data->i_codec_init_datasize )
693 p_track->fmt.p_extra = malloc( p_data->i_codec_init_datasize );
694 if( p_track->fmt.p_extra )
696 p_track->fmt.i_extra = p_data->i_codec_init_datasize;
697 memcpy( p_track->fmt.p_extra, p_data->p_codec_init_data,
698 p_data->i_codec_init_datasize );
703 break;
705 case ATOM_WMV3:
707 MP4_Box_t *p_strf = MP4_BoxGet( p_sample, "strf", 0 );
708 if ( p_strf && BOXDATA(p_strf) )
710 p_track->fmt.i_codec = VLC_CODEC_WMV3;
711 p_track->fmt.video.i_width = BOXDATA(p_strf)->bmiHeader.biWidth;
712 p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
713 p_track->fmt.video.i_height = BOXDATA(p_strf)->bmiHeader.biHeight;
714 p_track->fmt.video.i_visible_height =p_track->fmt.video.i_height;
715 p_track->fmt.video.i_bits_per_pixel = BOXDATA(p_strf)->bmiHeader.biBitCount;
716 p_track->fmt.i_extra = BOXDATA(p_strf)->i_extra;
717 if( p_track->fmt.i_extra > 0 )
719 p_track->fmt.p_extra = malloc( BOXDATA(p_strf)->i_extra );
720 memcpy( p_track->fmt.p_extra, BOXDATA(p_strf)->p_extra,
721 p_track->fmt.i_extra );
723 p_track->p_asf = MP4_BoxGet( p_sample, "ASF " );
725 break;
728 case VLC_FOURCC( 'a', 'i', '5', 'p' ):
729 case VLC_FOURCC( 'a', 'i', '5', 'q' ):
730 case VLC_FOURCC( 'a', 'i', '5', '2' ):
731 case VLC_FOURCC( 'a', 'i', '5', '3' ):
732 case VLC_FOURCC( 'a', 'i', '5', '5' ):
733 case VLC_FOURCC( 'a', 'i', '5', '6' ):
734 case VLC_FOURCC( 'a', 'i', '1', 'p' ):
735 case VLC_FOURCC( 'a', 'i', '1', 'q' ):
736 case VLC_FOURCC( 'a', 'i', '1', '2' ):
737 case VLC_FOURCC( 'a', 'i', '1', '3' ):
738 case VLC_FOURCC( 'a', 'i', '1', '5' ):
739 case VLC_FOURCC( 'a', 'i', '1', '6' ):
741 if( !p_track->fmt.i_extra && p_track->fmt.video.i_width < UINT16_MAX )
743 const MP4_Box_t *p_fiel = MP4_BoxGet( p_sample, "fiel" );
744 if( p_fiel && BOXDATA(p_fiel) )
746 p_track->fmt.p_extra =
747 AVCi_create_AnnexB( p_track->fmt.video.i_width,
748 !!BOXDATA(p_fiel)->i_flags, &p_track->fmt.i_extra );
751 break;
754 default:
755 msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
756 break;
759 return 1;
762 static bool SetupAudioFromWaveFormatEx( es_format_t *p_fmt, const MP4_Box_t *p_WMA2 )
764 if( p_WMA2 && BOXDATA(p_WMA2) )
766 wf_tag_to_fourcc(BOXDATA(p_WMA2)->Format.wFormatTag, &p_fmt->i_codec, NULL);
767 p_fmt->audio.i_channels = BOXDATA(p_WMA2)->Format.nChannels;
768 p_fmt->audio.i_rate = BOXDATA(p_WMA2)->Format.nSamplesPerSec;
769 p_fmt->i_bitrate = BOXDATA(p_WMA2)->Format.nAvgBytesPerSec * 8;
770 p_fmt->audio.i_blockalign = BOXDATA(p_WMA2)->Format.nBlockAlign;
771 p_fmt->audio.i_bitspersample = BOXDATA(p_WMA2)->Format.wBitsPerSample;
772 p_fmt->i_extra = BOXDATA(p_WMA2)->i_extra;
773 if( p_fmt->i_extra > 0 )
775 p_fmt->p_extra = malloc( BOXDATA(p_WMA2)->i_extra );
776 memcpy( p_fmt->p_extra, BOXDATA(p_WMA2)->p_extra, p_fmt->i_extra );
778 return true;
780 return false;
783 int SetupAudioES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
785 MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;
786 if(!p_soun)
787 return 0;
789 p_track->fmt.audio.i_channels = p_soun->i_channelcount;
790 p_track->fmt.audio.i_rate = p_soun->i_sampleratehi;
791 p_track->fmt.i_bitrate = p_soun->i_channelcount * p_soun->i_sampleratehi *
792 p_soun->i_samplesize;
793 p_track->fmt.audio.i_bitspersample = p_soun->i_samplesize;
795 p_track->fmt.i_original_fourcc = p_sample->i_type;
797 if( ( p_track->i_sample_size == 1 || p_track->i_sample_size == 2 ) )
799 if( p_soun->i_qt_version == 0 )
801 switch( p_sample->i_type )
803 case VLC_CODEC_ADPCM_IMA_QT:
804 p_soun->i_qt_version = 1;
805 p_soun->i_sample_per_packet = 64;
806 p_soun->i_bytes_per_packet = 34;
807 p_soun->i_bytes_per_frame = 34 * p_soun->i_channelcount;
808 p_soun->i_bytes_per_sample = 2;
809 break;
810 case VLC_CODEC_MACE3:
811 p_soun->i_qt_version = 1;
812 p_soun->i_sample_per_packet = 6;
813 p_soun->i_bytes_per_packet = 2;
814 p_soun->i_bytes_per_frame = 2 * p_soun->i_channelcount;
815 p_soun->i_bytes_per_sample = 2;
816 break;
817 case VLC_CODEC_MACE6:
818 p_soun->i_qt_version = 1;
819 p_soun->i_sample_per_packet = 12;
820 p_soun->i_bytes_per_packet = 2;
821 p_soun->i_bytes_per_frame = 2 * p_soun->i_channelcount;
822 p_soun->i_bytes_per_sample = 2;
823 break;
824 default:
825 p_track->fmt.i_codec = p_sample->i_type;
826 break;
830 else if( p_soun->i_qt_version == 1 && p_soun->i_sample_per_packet <= 0 )
832 p_soun->i_qt_version = 0;
835 else if( p_sample->data.p_sample_soun->i_qt_version == 1 )
837 switch( p_sample->i_type )
839 case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
840 case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
842 if( p_track->i_sample_size > 1 )
843 p_soun->i_qt_version = 0;
844 break;
846 case( ATOM_ac3 ):
847 case( ATOM_eac3 ):
848 case( VLC_FOURCC( 'm', 's', 0x20, 0x00 ) ):
849 p_soun->i_qt_version = 0;
850 break;
851 default:
852 break;
855 if ( p_sample->data.p_sample_soun->i_compressionid == 0xFFFE /* -2 */)
857 /* redefined sample tables for vbr audio */
859 else if ( p_track->i_sample_size != 0 && p_soun->i_sample_per_packet == 0 )
861 msg_Err( p_demux, "Invalid sample per packet value for qt_version 1. Broken muxer! %u %u",
862 p_track->i_sample_size, p_soun->i_sample_per_packet );
863 p_soun->i_qt_version = 0;
867 /* Endianness atom */
868 const MP4_Box_t *p_enda = MP4_BoxGet( p_sample, "wave/enda" );
869 if( !p_enda )
870 p_enda = MP4_BoxGet( p_sample, "enda" );
872 /* It's a little ugly but .. there are special cases */
873 switch( p_sample->i_type )
875 case( VLC_FOURCC( 'r', 'r', 't', 'p' ) ): /* RTP Reception Hint Track */
877 if( !SetupRTPReceptionHintTrack( p_demux, p_track, p_sample ) )
878 return 0;
879 break;
881 case ATOM_agsm: /* Apple gsm 33 bytes != MS GSM (agsm fourcc, 65 bytes) */
882 p_track->fmt.i_codec = VLC_CODEC_GSM;
883 break;
884 case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
885 case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
887 p_track->fmt.i_codec = VLC_CODEC_MPGA;
888 break;
890 case ATOM_XiVs:
892 const MP4_Box_t *p_vCtH = MP4_BoxGet( p_sample, "wave/vCtH" ); /* kCookieTypeVorbisHeader */
893 const MP4_Box_t *p_vCtd = MP4_BoxGet( p_sample, "wave/vCt#" ); /* kCookieTypeVorbisComments */
894 const MP4_Box_t *p_vCtC = MP4_BoxGet( p_sample, "wave/vCtC" ); /* kCookieTypeVorbisCodebooks */
895 if( p_vCtH && p_vCtH->data.p_binary &&
896 p_vCtd && p_vCtd->data.p_binary &&
897 p_vCtC && p_vCtC->data.p_binary )
899 unsigned headers_sizes[3] = {
900 p_vCtH->data.p_binary->i_blob,
901 p_vCtd->data.p_binary->i_blob,
902 p_vCtC->data.p_binary->i_blob
905 const void * headers[3] = {
906 p_vCtH->data.p_binary->p_blob,
907 p_vCtd->data.p_binary->p_blob,
908 p_vCtC->data.p_binary->p_blob
911 if( xiph_PackHeaders( &p_track->fmt.i_extra, &p_track->fmt.p_extra,
912 headers_sizes, headers, 3 ) == VLC_SUCCESS )
914 p_track->fmt.i_codec = VLC_CODEC_VORBIS;
915 p_track->fmt.b_packetized = false;
918 break;
920 case ATOM_XiFL:
922 const MP4_Box_t *p_fCtS = MP4_BoxGet( p_sample, "wave/fCtS" ); /* kCookieTypeFLACStreaminfo */
923 if( p_fCtS && p_fCtS->data.p_binary )
925 size_t i_extra = 8 + p_fCtS->data.p_binary->i_blob;
926 uint8_t *p_extra = malloc(i_extra);
927 if( p_extra )
929 p_track->fmt.i_extra = i_extra;
930 p_track->fmt.p_extra = p_extra;
931 memcpy( p_extra, "fLaC", 4 );
932 SetDWBE( &p_extra[4], p_fCtS->data.p_binary->i_blob ); /* want the lowest 24bits */
933 p_extra[4] = 0x80; /* 0x80 Last metablock | 0x00 StreamInfo */
934 memcpy( &p_extra[8], p_fCtS->data.p_binary->p_blob, p_fCtS->data.p_binary->i_blob );
936 p_track->fmt.i_codec = VLC_CODEC_FLAC;
937 p_track->fmt.b_packetized = false;
940 break;
942 case ATOM_fLaC:
944 const MP4_Box_t *p_dfLa = MP4_BoxGet( p_sample, "dfLa", 0 );
945 if( p_dfLa && p_dfLa->data.p_binary->i_blob > 4 &&
946 GetDWBE(p_dfLa->data.p_binary->p_blob) == 0 ) /* fullbox header, avoids creating dedicated parser */
948 size_t i_extra = p_dfLa->data.p_binary->i_blob;
949 uint8_t *p_extra = malloc(i_extra);
950 if( likely( p_extra ) )
952 p_track->fmt.i_extra = i_extra;
953 p_track->fmt.p_extra = p_extra;
954 memcpy( p_extra, p_dfLa->data.p_binary->p_blob, p_dfLa->data.p_binary->i_blob);
955 memcpy( p_extra, "fLaC", 4 );
956 p_track->fmt.i_codec = VLC_CODEC_FLAC;
959 break;
961 case( ATOM_eac3 ):
963 p_track->fmt.i_codec = VLC_CODEC_EAC3;
964 /* TS 102.366. F6 The values of the ChannelCount and SampleSize fields
965 * within the EC3SampleEntry Box shall be ignored. */
966 p_track->fmt.audio.i_channels = 0;
967 p_track->fmt.audio.i_bitspersample = 0;
969 const MP4_Box_t *p_dec3 = MP4_BoxGet( p_sample, "dec3", 0 );
970 if( p_dec3 && BOXDATA(p_dec3) )
972 p_track->fmt.i_bitrate = BOXDATA(p_dec3)->i_data_rate * 1000;
974 break;
976 case( ATOM_ac3 ):
978 p_track->fmt.i_codec = VLC_CODEC_A52;
979 /* TS 102.366. F3 The values of the ChannelCount and SampleSize fields
980 * within the AC3SampleEntry Box shall be ignored */
981 p_track->fmt.audio.i_channels = 0;
982 p_track->fmt.audio.i_bitspersample = 0;
984 MP4_Box_t *p_dac3 = MP4_BoxGet( p_sample, "dac3", 0 );
985 if( p_dac3 && BOXDATA(p_dac3) )
987 static const int pi_bitrate[] = {
988 32, 40, 48, 56,
989 64, 80, 96, 112,
990 128, 160, 192, 224,
991 256, 320, 384, 448,
992 512, 576, 640,
994 p_track->fmt.i_bitrate = 0;
995 if( BOXDATA(p_dac3)->i_bitrate_code < sizeof(pi_bitrate)/sizeof(*pi_bitrate) )
996 p_track->fmt.i_bitrate = pi_bitrate[BOXDATA(p_dac3)->i_bitrate_code] * 1000;
998 break;
1001 case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):
1002 case( VLC_FOURCC( 'N', 'O', 'N', 'E' ) ):
1004 if( (p_soun->i_samplesize+7)/8 == 1 )
1005 p_track->fmt.i_codec = VLC_CODEC_U8;
1006 else
1007 p_track->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
1009 /* Buggy files workaround */
1010 if( (p_track->i_timescale != p_soun->i_sampleratehi) )
1012 msg_Warn( p_demux, "i_timescale (%"PRId32") != i_sampleratehi "
1013 "(%u), making both equal (report any problem).",
1014 p_track->i_timescale, p_soun->i_sampleratehi );
1016 if( p_soun->i_sampleratehi != 0 )
1017 p_track->i_timescale = p_soun->i_sampleratehi;
1018 else
1019 p_soun->i_sampleratehi = p_track->i_timescale;
1021 break;
1024 case ATOM_in24:
1025 p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1026 VLC_CODEC_S24L : VLC_CODEC_S24B;
1027 break;
1028 case ATOM_in32:
1029 p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1030 VLC_CODEC_S32L : VLC_CODEC_S32B;
1031 break;
1032 case ATOM_fl32:
1033 p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1034 VLC_CODEC_F32L : VLC_CODEC_F32B;
1035 break;
1036 case ATOM_fl64:
1037 p_track->fmt.i_codec = p_enda && BOXDATA(p_enda)->i_little_endian == 1 ?
1038 VLC_CODEC_F64L : VLC_CODEC_F64B;
1039 break;
1041 case VLC_CODEC_DVD_LPCM:
1043 if( p_soun->i_qt_version == 2 )
1045 /* Flags:
1046 * 0x01: IsFloat
1047 * 0x02: IsBigEndian
1048 * 0x04: IsSigned
1050 static const struct {
1051 unsigned i_flags;
1052 unsigned i_mask;
1053 unsigned i_bits;
1054 vlc_fourcc_t i_codec;
1055 } p_formats[] = {
1056 { 0x01, 0x03, 32, VLC_CODEC_F32L },
1057 { 0x01, 0x03, 64, VLC_CODEC_F64L },
1058 { 0x01|0x02, 0x03, 32, VLC_CODEC_F32B },
1059 { 0x01|0x02, 0x03, 64, VLC_CODEC_F64B },
1061 { 0x00, 0x05, 8, VLC_CODEC_U8 },
1062 { 0x00| 0x04, 0x05, 8, VLC_CODEC_S8 },
1064 { 0x00, 0x07, 16, VLC_CODEC_U16L },
1065 { 0x00|0x02, 0x07, 16, VLC_CODEC_U16B },
1066 { 0x00 |0x04, 0x07, 16, VLC_CODEC_S16L },
1067 { 0x00|0x02|0x04, 0x07, 16, VLC_CODEC_S16B },
1069 { 0x00, 0x07, 24, VLC_CODEC_U24L },
1070 { 0x00|0x02, 0x07, 24, VLC_CODEC_U24B },
1071 { 0x00 |0x04, 0x07, 24, VLC_CODEC_S24L },
1072 { 0x00|0x02|0x04, 0x07, 24, VLC_CODEC_S24B },
1074 { 0x00, 0x07, 32, VLC_CODEC_U32L },
1075 { 0x00|0x02, 0x07, 32, VLC_CODEC_U32B },
1076 { 0x00 |0x04, 0x07, 32, VLC_CODEC_S32L },
1077 { 0x00|0x02|0x04, 0x07, 32, VLC_CODEC_S32B },
1079 {0, 0, 0, 0}
1082 for( int i = 0; p_formats[i].i_codec; i++ )
1084 if( p_formats[i].i_bits == p_soun->i_constbitsperchannel &&
1085 (p_soun->i_formatflags & p_formats[i].i_mask) == p_formats[i].i_flags )
1087 p_track->fmt.i_codec = p_formats[i].i_codec;
1088 p_track->fmt.audio.i_bitspersample = p_soun->i_constbitsperchannel;
1089 p_track->fmt.audio.i_blockalign =
1090 p_soun->i_channelcount * p_soun->i_constbitsperchannel / 8;
1091 p_track->i_sample_size = p_track->fmt.audio.i_blockalign;
1093 p_soun->i_qt_version = 0;
1094 break;
1098 break;
1100 default:
1101 p_track->fmt.i_codec = p_sample->i_type;
1102 break;
1106 /* Process extensions */
1108 /* Lookup for then channels extension */
1109 const MP4_Box_t *p_chan = MP4_BoxGet( p_sample, "chan" );
1110 if ( p_chan )
1112 if ( BOXDATA(p_chan)->layout.i_channels_layout_tag == MP4_CHAN_USE_CHANNELS_BITMAP )
1114 uint32_t rgi_chans_sequence[AOUT_CHAN_MAX + 1];
1115 memset(rgi_chans_sequence, 0, sizeof(rgi_chans_sequence));
1116 uint16_t i_vlc_mapping = 0;
1117 uint8_t i_channels = 0;
1118 const uint32_t i_bitmap = BOXDATA(p_chan)->layout.i_channels_bitmap;
1119 for (uint8_t i=0;i<MP4_CHAN_BITMAP_MAPPING_COUNT;i++)
1121 if ( chan_bitmap_mapping[i].i_bitmap & i_bitmap )
1123 if ( (chan_bitmap_mapping[i].i_vlc & i_vlc_mapping) ||
1124 i_channels >= AOUT_CHAN_MAX )
1126 /* double mapping or unsupported number of channels */
1127 i_vlc_mapping = 0;
1128 msg_Warn( p_demux, "discarding chan mapping" );
1129 break;
1131 i_vlc_mapping |= chan_bitmap_mapping[i].i_vlc;
1132 rgi_chans_sequence[i_channels++] = chan_bitmap_mapping[i].i_vlc;
1135 rgi_chans_sequence[i_channels] = 0;
1136 if( aout_CheckChannelReorder( rgi_chans_sequence, NULL, i_vlc_mapping,
1137 p_track->rgi_chans_reordering ) &&
1138 aout_BitsPerSample( p_track->fmt.i_codec ) )
1140 p_track->b_chans_reorder = true;
1141 p_track->fmt.audio.i_channels = i_channels;
1142 p_track->fmt.audio.i_physical_channels = i_vlc_mapping;
1148 SetupGlobalExtensions( p_track, p_sample );
1150 /* now see if esds is present and if so create a data packet
1151 with decoder_specific_info */
1152 MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
1153 if ( !p_esds ) p_esds = MP4_BoxGet( p_sample, "wave/esds" );
1154 if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
1156 assert(p_sample->i_type == ATOM_mp4a);
1157 SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
1159 else switch( p_sample->i_type )
1161 case VLC_CODEC_AMR_NB:
1162 p_track->fmt.audio.i_rate = 8000;
1163 break;
1164 case VLC_CODEC_AMR_WB:
1165 p_track->fmt.audio.i_rate = 16000;
1166 break;
1167 case VLC_CODEC_QDMC:
1168 case VLC_CODEC_QDM2:
1169 case VLC_CODEC_ALAC:
1171 p_track->fmt.i_extra =
1172 p_sample->data.p_sample_soun->i_qt_description;
1173 if( p_track->fmt.i_extra > 0 )
1175 p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
1176 memcpy( p_track->fmt.p_extra,
1177 p_sample->data.p_sample_soun->p_qt_description,
1178 p_track->fmt.i_extra);
1180 if( p_track->fmt.i_extra == 56 && p_sample->i_type == VLC_CODEC_ALAC )
1182 p_track->fmt.audio.i_channels = *((uint8_t*)p_track->fmt.p_extra + 41);
1183 p_track->fmt.audio.i_rate = GetDWBE((uint8_t*)p_track->fmt.p_extra + 52);
1185 break;
1187 case VLC_CODEC_ADPCM_MS:
1188 case VLC_CODEC_ADPCM_IMA_WAV:
1189 case VLC_CODEC_QCELP:
1191 p_track->fmt.audio.i_blockalign = p_sample->data.p_sample_soun->i_bytes_per_frame;
1192 break;
1194 case ATOM_WMA2:
1196 if( SetupAudioFromWaveFormatEx( &p_track->fmt,
1197 MP4_BoxGet( p_sample, "wave/WMA2" ) ) )
1199 p_track->p_asf = MP4_BoxGet( p_sample, "wave/ASF " );
1201 else
1203 msg_Err( p_demux, "missing WMA2 %4.4s", (char*) &p_sample->p_father->i_type );
1205 break;
1207 case ATOM_wma: /* isml wmapro */
1209 if( !SetupAudioFromWaveFormatEx( &p_track->fmt, MP4_BoxGet( p_sample, "wfex" ) ) )
1210 msg_Err( p_demux, "missing wfex for wma" );
1211 break;
1214 default:
1215 if(p_track->fmt.i_codec == 0)
1216 msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
1217 break;
1220 /* Ambisonics */
1221 const MP4_Box_t *p_SA3D = MP4_BoxGet(p_sample, "SA3D");
1222 if (p_SA3D && BOXDATA(p_SA3D))
1223 p_track->fmt.audio.channel_type = AUDIO_CHANNEL_TYPE_AMBISONICS;
1225 /* Late fixes */
1226 if ( p_soun->i_qt_version == 0 && p_track->fmt.i_codec == VLC_CODEC_QCELP )
1228 /* Shouldn't be v0, as it is a compressed codec !*/
1229 p_soun->i_qt_version = 1;
1230 p_soun->i_compressionid = 0xFFFE;
1233 return 1;
1236 int SetupSpuES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
1238 /* It's a little ugly but .. there are special cases */
1239 switch( p_sample->i_type )
1241 case VLC_FOURCC('s','t','p','p'):
1242 p_track->fmt.i_codec = VLC_CODEC_TTML;
1243 break;
1244 case ATOM_wvtt:
1245 p_track->fmt.i_codec = VLC_CODEC_SUBT;
1246 p_track->fmt.i_original_fourcc = ATOM_wvtt;
1247 break;
1248 case ATOM_c608: /* EIA608 closed captions */
1249 //case ATOM_c708: /* EIA708 closed captions */
1250 p_track->fmt.i_codec = VLC_CODEC_CEA608;
1251 p_track->fmt.subs.cc.i_reorder_depth = -1;
1252 break;
1254 case( VLC_FOURCC( 't', 'e', 'x', 't' ) ):
1255 case( VLC_FOURCC( 't', 'x', '3', 'g' ) ):
1257 const MP4_Box_data_sample_text_t *p_text = p_sample->data.p_sample_text;
1258 if(!p_text)
1259 return 0;
1261 p_track->fmt.i_codec = VLC_CODEC_TX3G;
1263 if( p_text->i_display_flags & 0xC0000000 )
1265 p_track->fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1;
1266 p_track->b_forced_spu = true;
1269 text_style_t *p_style = text_style_Create( STYLE_NO_DEFAULTS );
1270 if ( p_style )
1272 if ( p_text->i_font_size ) /* !WARN: in % of 5% height */
1274 p_style->i_font_size = p_text->i_font_size;
1276 if ( p_text->i_font_color )
1278 p_style->i_font_color = p_text->i_font_color >> 8;
1279 p_style->i_font_alpha = p_text->i_font_color & 0xFF;
1280 p_style->i_features |= (STYLE_HAS_FONT_ALPHA | STYLE_HAS_FONT_COLOR);
1282 if ( p_text->i_background_color[3] >> 8 )
1284 p_style->i_background_color = p_text->i_background_color[0] >> 8;
1285 p_style->i_background_color |= p_text->i_background_color[1] >> 8;
1286 p_style->i_background_color |= p_text->i_background_color[2] >> 8;
1287 p_style->i_background_alpha = p_text->i_background_color[3] >> 8;
1288 p_style->i_features |= (STYLE_HAS_BACKGROUND_ALPHA | STYLE_HAS_BACKGROUND_COLOR);
1291 assert(p_track->fmt.i_cat == SPU_ES);
1292 p_track->fmt.subs.p_style = p_style;
1294 /* FIXME UTF-8 doesn't work here ? */
1295 if( p_track->b_mac_encoding )
1296 p_track->fmt.subs.psz_encoding = strdup( "MAC" );
1297 else
1298 p_track->fmt.subs.psz_encoding = strdup( "UTF-8" );
1299 break;
1302 default:
1303 p_track->fmt.i_codec = p_sample->i_type;
1304 break;
1307 SetupGlobalExtensions( p_track, p_sample );
1309 /* now see if esds is present and if so create a data packet
1310 with decoder_specific_info */
1311 MP4_Box_t *p_esds = MP4_BoxGet( p_sample, "esds" );
1312 if ( p_esds && BOXDATA(p_esds) && BOXDATA(p_esds)->es_descriptor.p_decConfigDescr )
1314 SetupESDS( p_demux, p_track, BOXDATA(p_esds)->es_descriptor.p_decConfigDescr );
1317 return 1;