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