Coverage Report

Created: 2025-12-31 07:55

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