~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/demux/mp4/mp4.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
/*****************************************************************************
24
24
 * Preamble
25
25
 *****************************************************************************/
26
 
#include <stdlib.h>                                      /* malloc(), free() */
27
 
 
28
 
#include <vlc/vlc.h>
29
 
#include <vlc/input.h>
30
 
#include <vlc_playlist.h>
 
26
 
 
27
#ifdef HAVE_CONFIG_H
 
28
# include "config.h"
 
29
#endif
 
30
 
 
31
#include <vlc_common.h>
 
32
#include <vlc_plugin.h>
 
33
 
 
34
 
 
35
#include <vlc_demux.h>
31
36
#include <vlc_md5.h>
32
 
#include "charset.h"
33
 
#include "iso_lang.h"
34
 
#include "vlc_meta.h"
 
37
#include <vlc_charset.h>
 
38
#include <vlc_iso_lang.h>
 
39
#include <vlc_meta.h>
 
40
#include <vlc_input.h>
35
41
 
36
42
#include "libmp4.h"
37
43
#include "drms.h"
49
55
vlc_module_begin();
50
56
    set_category( CAT_INPUT );
51
57
    set_subcategory( SUBCAT_INPUT_DEMUX );
52
 
    set_description( _("MP4 stream demuxer") );
53
 
    set_capability( "demux2", 242 );
 
58
    set_description( N_("MP4 stream demuxer") );
 
59
    set_capability( "demux", 242 );
54
60
    set_callbacks( Open, Close );
55
61
vlc_module_end();
56
62
 
58
64
 * Local prototypes
59
65
 *****************************************************************************/
60
66
static int   Demux   ( demux_t * );
61
 
static int   DemuxRef( demux_t *p_demux ){ return 0;}
 
67
static int   DemuxRef( demux_t *p_demux ){ (void)p_demux; return 0;}
62
68
static int   Seek    ( demux_t *, mtime_t );
63
69
static int   Control ( demux_t *, int, va_list );
64
70
 
89
95
 /* Contain all needed information for read all track with vlc */
90
96
typedef struct
91
97
{
92
 
    int i_track_ID;     /* this should be unique */
93
 
 
94
 
    int b_ok;           /* The track is usable */
95
 
    int b_enable;       /* is the trak enable by default */
96
 
    vlc_bool_t b_selected;     /* is the trak being played */
 
98
    unsigned int i_track_ID;/* this should be unique */
 
99
 
 
100
    int b_ok;               /* The track is usable */
 
101
    int b_enable;           /* is the trak enable by default */
 
102
    bool b_selected;  /* is the trak being played */
 
103
    bool b_chapter;   /* True when used for chapter only */
 
104
 
 
105
    bool b_mac_encoding;
97
106
 
98
107
    es_format_t fmt;
99
108
    es_out_id_t *p_es;
130
139
    MP4_Box_t *p_stsd;  /* will contain all data to initialize decoder */
131
140
    MP4_Box_t *p_sample;/* point on actual sdsd */
132
141
 
133
 
    vlc_bool_t b_drms;
 
142
    bool b_drms;
134
143
    void      *p_drms;
135
144
 
136
145
} mp4_track_t;
142
151
 
143
152
    mtime_t      i_pcr;
144
153
 
145
 
    uint64_t     i_time;        /* time position of the presentation
146
 
                                 * in movie timescale */
147
 
    uint64_t     i_timescale;   /* movie time scale */
148
 
    uint64_t     i_duration;    /* movie duration */
149
 
    unsigned int i_tracks;      /* number of tracks */
150
 
    mp4_track_t *track;    /* array of track */
 
154
    uint64_t     i_time;         /* time position of the presentation
 
155
                                  * in movie timescale */
 
156
    uint64_t     i_timescale;    /* movie time scale */
 
157
    uint64_t     i_duration;     /* movie duration */
 
158
    unsigned int i_tracks;       /* number of tracks */
 
159
    mp4_track_t  *track;         /* array of track */
 
160
 
 
161
    /* */
 
162
    MP4_Box_t    *p_tref_chap;
 
163
 
 
164
    /* */
 
165
    input_title_t *p_title;
151
166
};
152
167
 
153
168
/*****************************************************************************
154
169
 * Declaration of local function
155
170
 *****************************************************************************/
156
 
static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *);
157
 
static void MP4_TrackDestroy( demux_t *, mp4_track_t * );
 
171
static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *, bool b_force_enable );
 
172
static void MP4_TrackDestroy(  mp4_track_t * );
158
173
 
159
174
static int  MP4_TrackSelect ( demux_t *, mp4_track_t *, mtime_t );
160
175
static void MP4_TrackUnselect(demux_t *, mp4_track_t * );
166
181
static int      MP4_TrackNextSample( demux_t *, mp4_track_t * );
167
182
static void     MP4_TrackSetELST( demux_t *, mp4_track_t *, int64_t );
168
183
 
 
184
static void     MP4_UpdateSeekpoint( demux_t * );
 
185
static const char *MP4_ConvertMacCode( uint16_t );
 
186
 
169
187
/* Return time in s of a track */
170
188
static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
171
189
{
215
233
        if( i_dts < 0 ) i_dts = 0;
216
234
    }
217
235
 
218
 
    return I64C(1000000) * i_dts / p_track->i_timescale;
 
236
    return INT64_C(1000000) * i_dts / p_track->i_timescale;
219
237
}
220
238
 
221
 
static inline int64_t MP4_TrackGetPTSDelta( demux_t *p_demux, mp4_track_t *p_track )
 
239
static inline int64_t MP4_TrackGetPTSDelta( mp4_track_t *p_track )
222
240
{
223
241
    mp4_chunk_t *ck = &p_track->chunk[p_track->i_chunk];
224
242
    unsigned int i_index = 0;
230
248
    for( i_index = 0;; i_index++ )
231
249
    {
232
250
        if( i_sample < ck->p_sample_count_pts[i_index] )
233
 
            return ck->p_sample_offset_pts[i_index] * I64C(1000000) /
 
251
            return ck->p_sample_offset_pts[i_index] * INT64_C(1000000) /
234
252
                   (int64_t)p_track->i_timescale;
235
253
 
236
254
        i_sample -= ck->p_sample_count_pts[i_index];
239
257
 
240
258
static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
241
259
{
242
 
    return I64C(1000000) * p_sys->i_time / p_sys->i_timescale;
 
260
    return INT64_C(1000000) * p_sys->i_time / p_sys->i_timescale;
243
261
}
244
262
 
245
 
#define FREE( p ) if( p ) { free( p ); (p) = NULL;}
 
263
static void LoadChapter( demux_t  *p_demux );
246
264
 
247
265
/*****************************************************************************
248
266
 * Open: check file and initializes MP4 structures
252
270
    demux_t  *p_demux = (demux_t *)p_this;
253
271
    demux_sys_t     *p_sys;
254
272
 
255
 
    uint8_t         *p_peek;
 
273
    const uint8_t   *p_peek;
256
274
 
257
275
    MP4_Box_t       *p_ftyp;
258
276
    MP4_Box_t       *p_rmra;
260
278
    MP4_Box_t       *p_trak;
261
279
 
262
280
    unsigned int    i;
263
 
    vlc_bool_t      b_seekable;
 
281
    bool      b_seekable;
 
282
    bool      b_enabled_es;
264
283
 
265
284
    /* A little test to see if it could be a mp4 */
266
285
    if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 ) return VLC_EGENERIC;
344
363
 
345
364
    if( ( p_rmra = MP4_BoxGet( p_sys->p_root,  "/moov/rmra" ) ) )
346
365
    {
347
 
        playlist_t *p_playlist;
348
 
        playlist_item_t *p_item;
349
366
        int        i_count = MP4_BoxCount( p_rmra, "rmda" );
350
367
        int        i;
351
 
        vlc_bool_t b_play = VLC_FALSE;
352
368
 
353
369
        msg_Dbg( p_demux, "detected playlist mov file (%d ref)", i_count );
354
370
 
355
 
        p_playlist =
356
 
            (playlist_t *)vlc_object_find( p_demux,
357
 
                                           VLC_OBJECT_PLAYLIST,
358
 
                                           FIND_ANYWHERE );
359
 
        if( p_playlist )
 
371
        input_thread_t * p_input = vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
 
372
        input_item_t * p_current = input_GetItem( p_input );
 
373
        p_current->i_type = ITEM_TYPE_PLAYLIST;
 
374
 
 
375
        for( i = 0; i < i_count; i++ )
360
376
        {
361
 
            p_item = playlist_LockItemGetByInput( p_playlist,
362
 
                      ((input_thread_t *)p_demux->p_parent)->input.p_item );
363
 
            playlist_ItemToNode( p_playlist, p_item );
364
 
 
365
 
            for( i = 0; i < i_count; i++ )
366
 
            {
367
 
                MP4_Box_t *p_rdrf = MP4_BoxGet( p_rmra, "rmda[%d]/rdrf", i );
368
 
                char      *psz_ref;
369
 
                uint32_t  i_ref_type;
370
 
 
371
 
                if( !p_rdrf || !( psz_ref = strdup( p_rdrf->data.p_rdrf->psz_ref ) ) )
 
377
            MP4_Box_t *p_rdrf = MP4_BoxGet( p_rmra, "rmda[%d]/rdrf", i );
 
378
            char      *psz_ref;
 
379
            uint32_t  i_ref_type;
 
380
 
 
381
            if( !p_rdrf || !( psz_ref = strdup( p_rdrf->data.p_rdrf->psz_ref ) ) )
 
382
            {
 
383
                continue;
 
384
            }
 
385
            i_ref_type = p_rdrf->data.p_rdrf->i_ref_type;
 
386
 
 
387
            msg_Dbg( p_demux, "new ref=`%s' type=%4.4s",
 
388
                     psz_ref, (char*)&i_ref_type );
 
389
 
 
390
            if( i_ref_type == VLC_FOURCC( 'u', 'r', 'l', ' ' ) )
 
391
            {
 
392
                if( strstr( psz_ref, "qt5gateQT" ) )
372
393
                {
 
394
                    msg_Dbg( p_demux, "ignoring pseudo ref =`%s'", psz_ref );
373
395
                    continue;
374
396
                }
375
 
                i_ref_type = p_rdrf->data.p_rdrf->i_ref_type;
376
 
 
377
 
                msg_Dbg( p_demux, "new ref=`%s' type=%4.4s",
378
 
                         psz_ref, (char*)&i_ref_type );
379
 
 
380
 
                if( i_ref_type == VLC_FOURCC( 'u', 'r', 'l', ' ' ) )
 
397
                if( !strncmp( psz_ref, "http://", 7 ) ||
 
398
                    !strncmp( psz_ref, "rtsp://", 7 ) )
381
399
                {
382
 
                    if( strstr( psz_ref, "qt5gateQT" ) )
383
 
                    {
384
 
                        msg_Dbg( p_demux, "ignoring pseudo ref =`%s'", psz_ref );
385
 
                        continue;
386
 
                    }
387
 
                    if( !strncmp( psz_ref, "http://", 7 ) ||
388
 
                        !strncmp( psz_ref, "rtsp://", 7 ) )
389
 
                    {
390
 
                        ;
391
 
                    }
392
 
                    else
393
 
                    {
394
 
                        char *psz_absolute;
395
 
                        char *psz_path = strdup( p_demux->psz_path );
396
 
                        char *end = strrchr( psz_path, '/' );
397
 
 
398
 
                        if( end ) end[1] = '\0';
399
 
                        else *psz_path = '\0';
400
 
 
401
 
                        asprintf( &psz_absolute, "%s://%s%s",
402
 
                                       p_demux->psz_access, psz_path, psz_ref );
403
 
 
404
 
                        if( psz_ref ) free( psz_ref );
405
 
                        psz_ref = psz_absolute;
406
 
                        free( psz_path );
407
 
                    }
408
 
                    msg_Dbg( p_demux, "adding ref = `%s'", psz_ref );
409
 
                    if( p_item )
410
 
                    {
411
 
                        playlist_item_t *p_child =
412
 
                                    playlist_ItemNew( p_playlist,
413
 
                                                      psz_ref, psz_ref );
414
 
                        if( p_child )
415
 
                        {
416
 
                            playlist_NodeAddItem( p_playlist, p_child,
417
 
                                             p_item->pp_parents[0]->i_view,
418
 
                                             p_item, PLAYLIST_APPEND,
419
 
                                             PLAYLIST_END );
420
 
                            playlist_CopyParents( p_item, p_child );
421
 
                            b_play = VLC_TRUE;
422
 
                        }
423
 
                    }
 
400
                    ;
424
401
                }
425
402
                else
426
403
                {
427
 
                    msg_Err( p_demux, "unknown ref type=%4.4s FIXME (send a bug report)",
428
 
                             (char*)&p_rdrf->data.p_rdrf->i_ref_type );
 
404
                    char *psz_absolute;
 
405
                    char *psz_path = strdup( p_demux->psz_path );
 
406
                    char *end = strrchr( psz_path, '/' );
 
407
                    if( end ) end[1] = '\0';
 
408
                    else *psz_path = '\0';
 
409
 
 
410
                    if( asprintf( &psz_absolute, "%s://%s%s",
 
411
                                  p_demux->psz_access, psz_path, psz_ref ) < 0 )
 
412
                        return VLC_ENOMEM;
 
413
 
 
414
                    free( psz_ref );
 
415
                    psz_ref = psz_absolute;
 
416
                    free( psz_path );
429
417
                }
430
 
                if( psz_ref ) free( psz_ref );
 
418
                input_item_t *p_input;
 
419
                msg_Dbg( p_demux, "adding ref = `%s'", psz_ref );
 
420
                p_input = input_item_NewExt( p_demux, psz_ref, NULL,
 
421
                                    0, NULL, -1 );
 
422
                input_item_CopyOptions( p_current, p_input );
 
423
                input_item_AddSubItem( p_current, p_input );
 
424
                vlc_gc_decref( p_input );
431
425
            }
432
 
            if( b_play == VLC_TRUE )
 
426
            else
433
427
            {
434
 
                 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
435
 
                                   p_playlist->status.i_view,
436
 
                                   p_playlist->status.p_item, NULL );
 
428
                msg_Err( p_demux, "unknown ref type=%4.4s FIXME (send a bug report)",
 
429
                         (char*)&p_rdrf->data.p_rdrf->i_ref_type );
437
430
            }
438
 
            vlc_object_release( p_playlist );
439
 
        }
440
 
        else
441
 
        {
442
 
            msg_Err( p_demux, "can't find playlist" );
443
 
        }
 
431
            free( psz_ref );
 
432
        }
 
433
        vlc_object_release( p_input );
444
434
    }
445
435
 
446
436
    if( !(p_mvhd = MP4_BoxGet( p_sys->p_root, "/moov/mvhd" ) ) )
483
473
        goto error;
484
474
    memset( p_sys->track, 0, p_sys->i_tracks * sizeof( mp4_track_t ) );
485
475
 
 
476
    /* Search the first chap reference (like quicktime) and
 
477
     * check that at least 1 stream is enabled */
 
478
    p_sys->p_tref_chap = NULL;
 
479
    b_enabled_es = false;
 
480
    for( i = 0; i < p_sys->i_tracks; i++ )
 
481
    {
 
482
        MP4_Box_t *p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i );
 
483
 
 
484
 
 
485
        MP4_Box_t *p_tkhd = MP4_BoxGet( p_trak, "tkhd" );
 
486
        if( p_tkhd && (p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED) )
 
487
            b_enabled_es = true;
 
488
 
 
489
        MP4_Box_t *p_chap = MP4_BoxGet( p_trak, "tref/chap", i );
 
490
        if( p_chap && p_chap->data.p_tref_generic->i_entry_count > 0 && !p_sys->p_tref_chap )
 
491
            p_sys->p_tref_chap = p_chap;
 
492
    }
 
493
 
486
494
    /* now process each track and extract all usefull information */
487
495
    for( i = 0; i < p_sys->i_tracks; i++ )
488
496
    {
489
497
        p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i );
490
 
        MP4_TrackCreate( p_demux, &p_sys->track[i], p_trak );
 
498
        MP4_TrackCreate( p_demux, &p_sys->track[i], p_trak, !b_enabled_es );
491
499
 
492
 
        if( p_sys->track[i].b_ok )
 
500
        if( p_sys->track[i].b_ok && !p_sys->track[i].b_chapter )
493
501
        {
494
 
            char *psz_cat;
 
502
            const char *psz_cat;
495
503
            switch( p_sys->track[i].fmt.i_cat )
496
504
            {
497
505
                case( VIDEO_ES ):
515
523
                     p_sys->track[i].fmt.psz_language ?
516
524
                     p_sys->track[i].fmt.psz_language : "undef" );
517
525
        }
 
526
        else if( p_sys->track[i].b_ok && p_sys->track[i].b_chapter )
 
527
        {
 
528
            msg_Dbg( p_demux, "using track[Id 0x%x] for chapter language %s",
 
529
                     p_sys->track[i].i_track_ID,
 
530
                     p_sys->track[i].fmt.psz_language ?
 
531
                     p_sys->track[i].fmt.psz_language : "undef" );
 
532
        }
518
533
        else
519
534
        {
520
535
            msg_Dbg( p_demux, "ignoring track[Id 0x%x]",
521
536
                     p_sys->track[i].i_track_ID );
522
537
        }
523
 
 
524
538
    }
 
539
 
 
540
    /* */
 
541
    LoadChapter( p_demux );
 
542
 
525
543
    return VLC_SUCCESS;
526
544
 
527
545
error:
551
569
         i_track++ )
552
570
    {
553
571
        mp4_track_t *tk = &p_sys->track[i_track];
554
 
        vlc_bool_t b;
 
572
        bool b;
555
573
 
556
 
        if( !tk->b_ok ||
 
574
        if( !tk->b_ok || tk->b_chapter ||
557
575
            ( tk->b_selected && tk->i_sample >= tk->i_sample_count ) )
558
576
        {
559
577
            continue;
593
611
        return 0;
594
612
    }
595
613
 
 
614
    /* */
 
615
    MP4_UpdateSeekpoint( p_demux );
 
616
 
596
617
    /* first wait for the good time to read a packet */
597
618
    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr + 1 );
598
619
 
605
626
    {
606
627
        mp4_track_t *tk = &p_sys->track[i_track];
607
628
 
608
 
        if( !tk->b_ok || !tk->b_selected || tk->i_sample >= tk->i_sample_count )
609
 
        {
 
629
        if( !tk->b_ok || tk->b_chapter || !tk->b_selected || tk->i_sample >= tk->i_sample_count )
610
630
            continue;
611
 
        }
612
631
 
613
632
        while( MP4_TrackGetDTS( p_demux, tk ) < MP4_GetMoviePTS( p_sys ) )
614
633
        {
664
683
                            p_block->i_buffer = i_size + 1;
665
684
 
666
685
                            /* convert \r -> \n */
667
 
                            while( ( p = strchr( (char*)p_block->p_buffer, '\r' ) ) )
 
686
                            while( ( p = strchr((char *) p_block->p_buffer, '\r' ) ) )
668
687
                            {
669
688
                                *p = '\n';
670
689
                            }
679
698
                /* dts */
680
699
                p_block->i_dts = MP4_TrackGetDTS( p_demux, tk ) + 1;
681
700
                /* pts */
682
 
                i_delta = MP4_TrackGetPTSDelta( p_demux, tk );
 
701
                i_delta = MP4_TrackGetPTSDelta( tk );
683
702
                if( i_delta != -1 )
684
703
                    p_block->i_pts = p_block->i_dts + i_delta;
685
704
                else if( tk->fmt.i_cat != VIDEO_ES )
693
712
 
694
713
            /* Next sample */
695
714
            if( MP4_TrackNextSample( p_demux, tk ) )
696
 
            {
697
715
                break;
698
 
            }
699
716
        }
700
717
    }
701
718
 
702
719
    return 1;
703
720
}
 
721
 
 
722
static void MP4_UpdateSeekpoint( demux_t *p_demux )
 
723
{
 
724
    demux_sys_t *p_sys = p_demux->p_sys;
 
725
    int64_t i_time;
 
726
    int i;
 
727
    if( !p_sys->p_title )
 
728
        return;
 
729
    i_time = MP4_GetMoviePTS( p_sys );
 
730
    for( i = 0; i < p_sys->p_title->i_seekpoint; i++ )
 
731
    {
 
732
        if( i_time < p_sys->p_title->seekpoint[i]->i_time_offset )
 
733
            break;
 
734
    }
 
735
    i--;
 
736
 
 
737
    if( i != p_demux->info.i_seekpoint && i >= 0 )
 
738
    {
 
739
        p_demux->info.i_seekpoint = i;
 
740
        p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
 
741
    }
 
742
}
704
743
/*****************************************************************************
705
744
 * Seek: Got to i_date
706
745
******************************************************************************/
719
758
        mp4_track_t *tk = &p_sys->track[i_track];
720
759
        MP4_TrackSeek( p_demux, tk, i_date );
721
760
    }
 
761
    MP4_UpdateSeekpoint( p_demux );
722
762
    return VLC_SUCCESS;
723
763
}
724
764
 
789
829
 
790
830
        case DEMUX_GET_META:
791
831
        {
792
 
            vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
793
 
            vlc_meta_t *meta;
794
 
            MP4_Box_t  *p_udta   = MP4_BoxGet( p_sys->p_root, "/moov/udta" );
 
832
            vlc_meta_t *p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t*);
795
833
            MP4_Box_t  *p_0xa9xxx;
 
834
 
 
835
            MP4_Box_t  *p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta/meta/ilst" );
796
836
            if( p_udta == NULL )
797
837
            {
798
 
                return VLC_EGENERIC;
 
838
                p_udta = MP4_BoxGet( p_sys->p_root, "/moov/udta" );
 
839
                if( p_udta == NULL )
 
840
                {
 
841
                    return VLC_EGENERIC;
 
842
                }
799
843
            }
800
 
            *pp_meta = meta = vlc_meta_New();
 
844
 
801
845
            for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;
802
846
                 p_0xa9xxx = p_0xa9xxx->p_next )
803
847
            {
804
 
                char *psz_utf;
 
848
 
805
849
                if( !p_0xa9xxx || !p_0xa9xxx->data.p_0xa9xxx )
806
850
                    continue;
807
 
                psz_utf = strdup( p_0xa9xxx->data.p_0xa9xxx->psz_text );
808
 
                if( psz_utf == NULL )
809
 
                    continue;
 
851
 
810
852
                /* FIXME FIXME: should convert from whatever the character
811
853
                 * encoding of MP4 meta data is to UTF-8. */
812
 
                EnsureUTF8( psz_utf );
 
854
#define SET(fct) do { char *psz_utf = strdup( p_0xa9xxx->data.p_0xa9xxx->psz_text ? p_0xa9xxx->data.p_0xa9xxx->psz_text : "" ); \
 
855
    if( psz_utf ) { EnsureUTF8( psz_utf );  \
 
856
                    fct( p_meta, psz_utf ); free( psz_utf ); } } while(0)
813
857
 
 
858
                /* XXX Becarefull p_udta can have box that are not 0xa9xx */
814
859
                switch( p_0xa9xxx->i_type )
815
860
                {
816
861
                case FOURCC_0xa9nam: /* Full name */
817
 
                    vlc_meta_Add( meta, VLC_META_TITLE, psz_utf );
 
862
                    SET( vlc_meta_SetTitle );
818
863
                    break;
819
864
                case FOURCC_0xa9aut:
820
 
                    vlc_meta_Add( meta, VLC_META_AUTHOR, psz_utf );
 
865
                    SET( vlc_meta_SetArtist );
821
866
                    break;
822
867
                case FOURCC_0xa9ART:
823
 
                    vlc_meta_Add( meta, VLC_META_ARTIST, psz_utf );
 
868
                    SET( vlc_meta_SetArtist );
824
869
                    break;
825
870
                case FOURCC_0xa9cpy:
826
 
                    vlc_meta_Add( meta, VLC_META_COPYRIGHT, psz_utf );
 
871
                    SET( vlc_meta_SetCopyright );
827
872
                    break;
828
873
                case FOURCC_0xa9day: /* Creation Date */
829
 
                    vlc_meta_Add( meta, VLC_META_DATE, psz_utf );
 
874
                    SET( vlc_meta_SetDate );
830
875
                    break;
831
876
                case FOURCC_0xa9des: /* Description */
832
 
                    vlc_meta_Add( meta, VLC_META_DESCRIPTION, psz_utf );
 
877
                    SET( vlc_meta_SetDescription );
833
878
                    break;
834
879
                case FOURCC_0xa9gen: /* Genre */
835
 
                    vlc_meta_Add( meta, VLC_META_GENRE, psz_utf );
836
 
                    break;
837
 
 
 
880
                    SET( vlc_meta_SetGenre );
 
881
                    break;
 
882
 
 
883
                case FOURCC_0xa9alb: /* Album */
 
884
                    SET( vlc_meta_SetAlbum );
 
885
                    break;
 
886
 
 
887
                case FOURCC_0xa9trk: /* Track */
 
888
                    SET( vlc_meta_SetTracknum );
 
889
                    break;
 
890
 
 
891
                case FOURCC_0xa9cmt: /* Commment */
 
892
                    SET( vlc_meta_SetDescription );
 
893
                    break;
 
894
 
 
895
                case FOURCC_0xa9url: /* URL */
 
896
                    SET( vlc_meta_SetURL );
 
897
                    break;
 
898
 
 
899
                case FOURCC_0xa9enc: /* Encoded By */
 
900
                    SET( vlc_meta_SetEncodedBy );
 
901
                    break;
 
902
                    
838
903
                case FOURCC_0xa9swr:
839
904
                case FOURCC_0xa9inf: /* Information */
840
 
                case FOURCC_0xa9alb: /* Album */
841
905
                case FOURCC_0xa9dir: /* Director */
842
906
                case FOURCC_0xa9dis: /* Disclaimer */
843
 
                case FOURCC_0xa9enc: /* Encoded By */
844
 
                case FOURCC_0xa9trk: /* Track */
845
 
                case FOURCC_0xa9cmt: /* Commment */
846
 
                case FOURCC_0xa9url: /* URL */
847
907
                case FOURCC_0xa9req: /* Requirements */
848
908
                case FOURCC_0xa9fmt: /* Original Format */
849
909
                case FOURCC_0xa9dsa: /* Display Source As */
857
917
                case FOURCC_WLOC:    /* Window Location */
858
918
                    /* TODO one day, but they aren't really meaningfull */
859
919
                    break;
 
920
#undef SET
860
921
 
861
922
                default:
862
923
                    break;
863
924
                }
864
 
                free( psz_utf );
865
925
            }
866
926
            return VLC_SUCCESS;
867
927
        }
868
928
 
869
929
        case DEMUX_GET_TITLE_INFO:
 
930
        {
 
931
            input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
 
932
            int *pi_int    = (int*)va_arg( args, int* );
 
933
            int *pi_title_offset = (int*)va_arg( args, int* );
 
934
            int *pi_seekpoint_offset = (int*)va_arg( args, int* );
 
935
 
 
936
            if( !p_sys->p_title )
 
937
                return VLC_EGENERIC;
 
938
 
 
939
            *pi_int = 1;
 
940
            *ppp_title = malloc( sizeof( input_title_t**) );
 
941
            (*ppp_title)[0] = vlc_input_title_Duplicate( p_sys->p_title );
 
942
            *pi_title_offset = 0;
 
943
            *pi_seekpoint_offset = 0;
 
944
            return VLC_SUCCESS;
 
945
        }
 
946
        case DEMUX_SET_TITLE:
 
947
        {
 
948
            const int i_title = (int)va_arg( args, int );
 
949
            if( !p_sys->p_title || i_title != 0 )
 
950
                return VLC_EGENERIC;
 
951
            return VLC_SUCCESS;
 
952
        }
 
953
        case DEMUX_SET_SEEKPOINT:
 
954
        {
 
955
            const int i_seekpoint = (int)va_arg( args, int );
 
956
            if( !p_sys->p_title )
 
957
                return VLC_EGENERIC;
 
958
            return Seek( p_demux, p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset );
 
959
        }
 
960
 
870
961
        case DEMUX_SET_NEXT_DEMUX_TIME:
871
962
        case DEMUX_SET_GROUP:
 
963
        case DEMUX_HAS_UNSUPPORTED_META:
 
964
        case DEMUX_GET_ATTACHMENTS:
872
965
            return VLC_EGENERIC;
873
966
 
874
967
        default:
882
975
 *****************************************************************************/
883
976
static void Close ( vlc_object_t * p_this )
884
977
{
885
 
    unsigned int i_track;
886
978
    demux_t *  p_demux = (demux_t *)p_this;
887
979
    demux_sys_t *p_sys = p_demux->p_sys;
 
980
    unsigned int i_track;
888
981
 
889
982
    msg_Dbg( p_demux, "freeing all memory" );
890
983
 
891
984
    MP4_BoxFree( p_demux->s, p_sys->p_root );
892
985
    for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
893
986
    {
894
 
        MP4_TrackDestroy( p_demux, &p_sys->track[i_track] );
 
987
        MP4_TrackDestroy(  &p_sys->track[i_track] );
895
988
    }
896
 
    FREE( p_sys->track );
 
989
    FREENULL( p_sys->track );
 
990
 
 
991
    if( p_sys->p_title )
 
992
        vlc_input_title_Delete( p_sys->p_title );
897
993
 
898
994
    free( p_sys );
899
995
}
903
999
/****************************************************************************
904
1000
 * Local functions, specific to vlc
905
1001
 ****************************************************************************/
 
1002
/* Chapters */
 
1003
static void LoadChapterGpac( demux_t  *p_demux, MP4_Box_t *p_chpl )
 
1004
{
 
1005
    demux_sys_t *p_sys = p_demux->p_sys;
 
1006
    int i;
 
1007
 
 
1008
    p_sys->p_title = vlc_input_title_New();
 
1009
    for( i = 0; i < p_chpl->data.p_chpl->i_chapter; i++ )
 
1010
    {
 
1011
        seekpoint_t *s = vlc_seekpoint_New();
 
1012
 
 
1013
        s->psz_name = strdup( p_chpl->data.p_chpl->chapter[i].psz_name );
 
1014
        EnsureUTF8( s->psz_name );
 
1015
        s->i_time_offset = p_chpl->data.p_chpl->chapter[i].i_start / 10;
 
1016
        TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
 
1017
    }
 
1018
}
 
1019
static void LoadChapterApple( demux_t  *p_demux, mp4_track_t *tk )
 
1020
{
 
1021
    demux_sys_t *p_sys = p_demux->p_sys;
 
1022
 
 
1023
    for( tk->i_sample = 0; tk->i_sample < tk->i_sample_count; tk->i_sample++ )
 
1024
    {
 
1025
        const int64_t i_dts = MP4_TrackGetDTS( p_demux, tk );
 
1026
        const int64_t i_pts_delta = MP4_TrackGetPTSDelta( tk );
 
1027
        const unsigned int i_size = MP4_TrackSampleSize( tk );
 
1028
 
 
1029
        if( i_size > 0 && !stream_Seek( p_demux->s, MP4_TrackGetPos( tk ) ) )
 
1030
        {
 
1031
            char p_buffer[256];
 
1032
            const int i_read = stream_Read( p_demux->s, p_buffer, __MIN( sizeof(p_buffer), i_size ) );
 
1033
            const int i_len = __MIN( GetWBE(p_buffer), i_read-2 );
 
1034
 
 
1035
            if( i_len > 0 )
 
1036
            {
 
1037
                seekpoint_t *s = vlc_seekpoint_New();
 
1038
 
 
1039
                s->psz_name = strndup( &p_buffer[2], i_len );
 
1040
                EnsureUTF8( s->psz_name );
 
1041
 
 
1042
                s->i_time_offset = i_dts + __MAX( i_pts_delta, 0 );
 
1043
 
 
1044
                if( !p_sys->p_title )
 
1045
                    p_sys->p_title = vlc_input_title_New();
 
1046
                TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
 
1047
            }
 
1048
        }
 
1049
        if( tk->i_sample+1 >= tk->chunk[tk->i_chunk].i_sample_first +
 
1050
                              tk->chunk[tk->i_chunk].i_sample_count )
 
1051
            tk->i_chunk++;
 
1052
    }
 
1053
}
 
1054
static void LoadChapter( demux_t  *p_demux )
 
1055
{
 
1056
    demux_sys_t *p_sys = p_demux->p_sys;
 
1057
    MP4_Box_t *p_chpl;
 
1058
 
 
1059
    if( ( p_chpl = MP4_BoxGet( p_sys->p_root, "/moov/udta/chpl" ) ) && p_chpl->data.p_chpl->i_chapter > 0 )
 
1060
    {
 
1061
        LoadChapterGpac( p_demux, p_chpl );
 
1062
    }
 
1063
    else if( p_sys->p_tref_chap )
 
1064
    {
 
1065
        MP4_Box_data_tref_generic_t *p_chap = p_sys->p_tref_chap->data.p_tref_generic;
 
1066
        unsigned int i, j;
 
1067
 
 
1068
        /* Load the first subtitle track like quicktime */
 
1069
        for( i = 0; i < p_chap->i_entry_count; i++ )
 
1070
        {
 
1071
            for( j = 0; j < p_sys->i_tracks; j++ )
 
1072
            {
 
1073
                mp4_track_t *tk = &p_sys->track[j];
 
1074
                if( tk->b_ok && tk->i_track_ID == p_chap->i_track_ID[i] &&
 
1075
                    tk->fmt.i_cat == SPU_ES && tk->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) )
 
1076
                    break;
 
1077
            }
 
1078
            if( j < p_sys->i_tracks )
 
1079
            {
 
1080
                LoadChapterApple( p_demux, &p_sys->track[j] );
 
1081
                break;
 
1082
            }
 
1083
        }
 
1084
    }
 
1085
}
906
1086
 
907
1087
/* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */
908
1088
static int TrackCreateChunksIndex( demux_t *p_demux,
1090
1270
        ck->p_sample_count_dts = calloc( i_entry, sizeof( uint32_t ) );
1091
1271
        ck->p_sample_delta_dts = calloc( i_entry, sizeof( uint32_t ) );
1092
1272
 
 
1273
        if( !ck->p_sample_count_dts || !ck->p_sample_delta_dts )
 
1274
            return VLC_ENOMEM;
 
1275
 
1093
1276
        /* now copy */
1094
1277
        i_sample_count = ck->i_sample_count;
1095
1278
        for( i = 0; i < i_entry; i++ )
1153
1336
            /* allocate them */
1154
1337
            ck->p_sample_count_pts = calloc( i_entry, sizeof( uint32_t ) );
1155
1338
            ck->p_sample_offset_pts = calloc( i_entry, sizeof( int32_t ) );
 
1339
            if( !ck->p_sample_count_pts || !ck->p_sample_offset_pts )
 
1340
                return VLC_ENOMEM;
1156
1341
 
1157
1342
            /* now copy */
1158
1343
            i_sample_count = ck->i_sample_count;
1181
1366
        }
1182
1367
    }
1183
1368
 
1184
 
    msg_Dbg( p_demux, "track[Id 0x%x] read %d samples length:"I64Fd"s",
 
1369
    msg_Dbg( p_demux, "track[Id 0x%x] read %d samples length:%"PRId64"s",
1185
1370
             p_demux_track->i_track_ID, p_demux_track->i_sample_count,
1186
1371
             i_last_dts / p_demux_track->i_timescale );
1187
1372
 
1199
1384
    MP4_Box_t   *p_esds;
1200
1385
    MP4_Box_t   *p_box;
1201
1386
 
1202
 
    *pp_es = NULL;
 
1387
    if( pp_es )
 
1388
        *pp_es = NULL;
1203
1389
 
1204
1390
    if( !p_track->chunk[i_chunk].i_sample_description_index )
1205
1391
    {
1221
1407
 
1222
1408
    p_track->p_sample = p_sample;
1223
1409
 
1224
 
    if( p_track->fmt.i_cat == AUDIO_ES && p_track->i_sample_size == 1 )
 
1410
    if( p_track->fmt.i_cat == AUDIO_ES && ( p_track->i_sample_size == 1 || p_track->i_sample_size == 2 ) )
1225
1411
    {
1226
1412
        MP4_Box_data_sample_soun_t *p_soun;
1227
1413
 
1256
1442
                case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
1257
1443
                    p_soun->i_samplesize = 8;
1258
1444
                    break;
 
1445
                case VLC_FOURCC( 'N', 'O', 'N', 'E' ):
 
1446
                case VLC_FOURCC( 'r', 'a', 'w', ' ' ):
 
1447
                case VLC_FOURCC( 't', 'w', 'o', 's' ):
 
1448
                case VLC_FOURCC( 's', 'o', 'w', 't' ):
 
1449
                    /* What would be the fun if you could trust the .mov */
 
1450
                    p_track->i_sample_size = ((p_soun->i_samplesize+7)/8) * p_soun->i_channelcount;
 
1451
                    break;
1259
1452
                default:
1260
1453
                    break;
1261
1454
            }
1267
1460
        }
1268
1461
    }
1269
1462
 
1270
 
 
1271
1463
    /* It's a little ugly but .. there are special cases */
1272
1464
    switch( p_sample->i_type )
1273
1465
    {
1274
1466
        case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
1275
1467
        case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
 
1468
        {
 
1469
            MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;
1276
1470
            p_track->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
 
1471
            if( p_track->i_sample_size > 1 )
 
1472
                p_soun->i_qt_version = 0;
1277
1473
            break;
 
1474
        }
1278
1475
 
1279
1476
        case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):
1280
 
            p_track->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
 
1477
        case( VLC_FOURCC( 'N', 'O', 'N', 'E' ) ):
 
1478
        {
 
1479
            MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;
 
1480
 
 
1481
            if(p_soun && (p_soun->i_samplesize+7)/8 == 1 )
 
1482
                p_track->fmt.i_codec = VLC_FOURCC( 'u', '8', ' ', ' ' );
 
1483
            else
 
1484
                p_track->fmt.i_codec = VLC_FOURCC( 't', 'w', 'o', 's' );
1281
1485
 
1282
1486
            /* Buggy files workaround */
1283
1487
            if( p_sample->data.p_sample_soun && (p_track->i_timescale !=
1286
1490
                MP4_Box_data_sample_soun_t *p_soun =
1287
1491
                    p_sample->data.p_sample_soun;
1288
1492
 
1289
 
                msg_Warn( p_demux, "i_timescale ("I64Fu") != i_sampleratehi "
 
1493
                msg_Warn( p_demux, "i_timescale (%"PRIu64") != i_sampleratehi "
1290
1494
                          "(%u), making both equal (report any problem).",
1291
1495
                          p_track->i_timescale, p_soun->i_sampleratehi );
1292
1496
 
1296
1500
                    p_soun->i_sampleratehi = p_track->i_timescale;
1297
1501
            }
1298
1502
            break;
 
1503
        }
1299
1504
 
1300
1505
        case( VLC_FOURCC( 's', '2', '6', '3' ) ):
1301
1506
            p_track->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '3' );
1306
1511
            p_track->fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
1307
1512
            /* FIXME: Not true, could be UTF-16 with a Byte Order Mark (0xfeff) */
1308
1513
            /* FIXME UTF-8 doesn't work here ? */
1309
 
            p_track->fmt.subs.psz_encoding = strdup( "UTF-8" );
 
1514
            if( p_track->b_mac_encoding )
 
1515
                p_track->fmt.subs.psz_encoding = strdup( "MAC" );
 
1516
            else
 
1517
                p_track->fmt.subs.psz_encoding = strdup( "UTF-8" );
 
1518
            break;
 
1519
 
 
1520
        case VLC_FOURCC('y','v','1','2'):
 
1521
            p_track->fmt.i_codec = VLC_FOURCC('Y','V','1','2');
 
1522
            break;
 
1523
        case VLC_FOURCC('y','u','v','2'):
 
1524
            p_track->fmt.i_codec = VLC_FOURCC('Y','U','Y','2');
 
1525
            break;
 
1526
 
 
1527
        case VLC_FOURCC('i','n','2','4'):
 
1528
            /* in in24/in32 there's enda-atom to tell it's little-endian (if present) */
 
1529
            if( ( MP4_BoxGet( p_sample, "wave/enda" ) ) ||
 
1530
                ( MP4_BoxGet( p_sample, "enda" ) ) )
 
1531
            {
 
1532
                p_track->fmt.i_codec = VLC_FOURCC('4','2','n','i');
 
1533
            } else {
 
1534
                p_track->fmt.i_codec = p_sample->i_type;
 
1535
            }
1310
1536
            break;
1311
1537
 
1312
1538
        default:
1358
1584
            case( 0x6c ): /* jpeg */
1359
1585
                p_track->fmt.i_codec = VLC_FOURCC( 'j','p','e','g' );
1360
1586
                break;
 
1587
            case( 0x6d ): /* png */
 
1588
                p_track->fmt.i_codec = VLC_FOURCC( 'p','n','g',' ' );
 
1589
                break;
 
1590
            case( 0x6e ): /* jpeg200 */
 
1591
                p_track->fmt.i_codec = VLC_FOURCC( 'M','J','2','C' );
 
1592
                break;
 
1593
            case( 0xa3 ): /* vc1 */
 
1594
                p_track->fmt.i_codec = VLC_FOURCC( 'W','V','C','1' );
 
1595
                break;
1361
1596
 
1362
1597
            /* Private ID */
1363
1598
            case( 0xe0 ): /* NeroDigital: dvd subs */
1370
1605
                        p_track->fmt.subs.spu.i_original_frame_height = p_track->i_height;
1371
1606
                    break;
1372
1607
                }
 
1608
            case( 0xe1 ): /* QCelp for 3gp */
 
1609
                if( p_track->fmt.i_cat == AUDIO_ES )
 
1610
                {
 
1611
                    p_track->fmt.i_codec = VLC_FOURCC( 'Q','c','l','p' );
 
1612
                }
 
1613
                break;
 
1614
 
1373
1615
            /* Fallback */
1374
1616
            default:
1375
1617
                /* Unknown entry, but don't touch i_fourcc */
1457
1699
                break;
1458
1700
            }
1459
1701
 
 
1702
            case VLC_FOURCC('m','s',0x00,0x02):
 
1703
            case VLC_FOURCC('m','s',0x00,0x11):
 
1704
                p_track->fmt.audio.i_blockalign = p_sample->data.p_sample_soun->i_bytes_per_frame;
 
1705
                break;
 
1706
 
1460
1707
            default:
1461
1708
                break;
1462
1709
        }
1467
1714
    /* some last initialisation */
1468
1715
    switch( p_track->fmt.i_cat )
1469
1716
    {
1470
 
    case( VIDEO_ES ):
 
1717
    case VIDEO_ES:
1471
1718
        p_track->fmt.video.i_width = p_sample->data.p_sample_vide->i_width;
1472
1719
        p_track->fmt.video.i_height = p_sample->data.p_sample_vide->i_height;
1473
1720
        p_track->fmt.video.i_bits_per_pixel =
1504
1751
 
1505
1752
        break;
1506
1753
 
1507
 
    case( AUDIO_ES ):
 
1754
    case AUDIO_ES:
1508
1755
        p_track->fmt.audio.i_channels =
1509
1756
            p_sample->data.p_sample_soun->i_channelcount;
1510
1757
        p_track->fmt.audio.i_rate =
1514
1761
                p_sample->data.p_sample_soun->i_samplesize;
1515
1762
        p_track->fmt.audio.i_bitspersample =
1516
1763
            p_sample->data.p_sample_soun->i_samplesize;
 
1764
 
 
1765
        if( p_track->i_sample_size != 0 &&
 
1766
            p_sample->data.p_sample_soun->i_qt_version == 1 && p_sample->data.p_sample_soun->i_sample_per_packet <= 0 )
 
1767
        {
 
1768
            msg_Err( p_demux, "Invalid sample per packet value for qt_version 1" );
 
1769
            return VLC_EGENERIC;
 
1770
        }
1517
1771
        break;
1518
1772
 
1519
1773
    default:
1520
1774
        break;
1521
1775
    }
1522
1776
 
1523
 
    *pp_es = es_out_Add( p_demux->out, &p_track->fmt );
 
1777
    if( pp_es )
 
1778
        *pp_es = es_out_Add( p_demux->out, &p_track->fmt );
1524
1779
 
1525
1780
    return VLC_SUCCESS;
1526
1781
}
1540
1795
    int          i_index;
1541
1796
 
1542
1797
    /* FIXME see if it's needed to check p_track->i_chunk_count */
1543
 
    if( !p_track->b_ok || p_track->i_chunk_count == 0 )
1544
 
    {
 
1798
    if( p_track->i_chunk_count == 0 )
1545
1799
        return( VLC_EGENERIC );
1546
 
    }
1547
1800
 
1548
1801
    /* handle elst (find the correct one) */
1549
1802
    MP4_TrackSetELST( p_demux, p_track, i_start );
1554
1807
 
1555
1808
        /* now calculate i_start for this elst */
1556
1809
        /* offset */
1557
 
        i_start -= p_track->i_elst_time * I64C(1000000) / p_sys->i_timescale;
 
1810
        i_start -= p_track->i_elst_time * INT64_C(1000000) / p_sys->i_timescale;
1558
1811
        if( i_start < 0 )
1559
1812
        {
1560
1813
            *pi_chunk = 0;
1572
1825
            i_start += elst->i_media_time[p_track->i_elst];
1573
1826
        }
1574
1827
 
1575
 
        msg_Dbg( p_demux, "elst (%d) gives "I64Fd"ms (movie)-> "I64Fd
 
1828
        msg_Dbg( p_demux, "elst (%d) gives %"PRId64"ms (movie)-> %"PRId64
1576
1829
                 "ms (track)", p_track->i_elst,
1577
1830
                 i_mvt * 1000 / p_sys->i_timescale,
1578
1831
                 i_start * 1000 / p_track->i_timescale );
1696
1949
static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
1697
1950
                                 unsigned int i_chunk, unsigned int i_sample )
1698
1951
{
1699
 
    vlc_bool_t b_reselect = VLC_FALSE;
 
1952
    bool b_reselect = false;
1700
1953
 
1701
1954
    /* now see if actual es is ok */
1702
 
    if( p_track->i_chunk < 0 ||
1703
 
        p_track->i_chunk >= p_track->i_chunk_count - 1 ||
1704
 
        p_track->chunk[p_track->i_chunk].i_sample_description_index !=
1705
 
            p_track->chunk[i_chunk].i_sample_description_index )
 
1955
    if( (p_track->i_chunk >= p_track->i_chunk_count - 1) ||
 
1956
        (p_track->chunk[p_track->i_chunk].i_sample_description_index !=
 
1957
            p_track->chunk[i_chunk].i_sample_description_index) )
1706
1958
    {
1707
1959
        msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",
1708
1960
                  p_track->i_track_ID );
1719
1971
            msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
1720
1972
                     p_track->i_track_ID );
1721
1973
 
1722
 
            p_track->b_ok       = VLC_FALSE;
1723
 
            p_track->b_selected = VLC_FALSE;
 
1974
            p_track->b_ok       = false;
 
1975
            p_track->b_selected = false;
1724
1976
            return VLC_EGENERIC;
1725
1977
        }
1726
1978
    }
1744
1996
 * If it succeed b_ok is set to 1 else to 0
1745
1997
 ****************************************************************************/
1746
1998
static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
1747
 
                             MP4_Box_t *p_box_trak )
 
1999
                             MP4_Box_t *p_box_trak,
 
2000
                             bool b_force_enable )
1748
2001
{
1749
2002
    demux_sys_t *p_sys = p_demux->p_sys;
1750
2003
 
1767
2020
    /* hint track unsupported */
1768
2021
 
1769
2022
    /* set default value (-> track unusable) */
1770
 
    p_track->b_ok       = VLC_FALSE;
1771
 
    p_track->b_enable   = VLC_FALSE;
1772
 
    p_track->b_selected = VLC_FALSE;
 
2023
    p_track->b_ok       = false;
 
2024
    p_track->b_enable   = false;
 
2025
    p_track->b_selected = false;
 
2026
    p_track->b_chapter  = false;
 
2027
    p_track->b_mac_encoding = false;
1773
2028
 
1774
2029
    es_format_Init( &p_track->fmt, UNKNOWN_ES, 0 );
1775
2030
 
1781
2036
    /* do we launch this track by default ? */
1782
2037
    p_track->b_enable =
1783
2038
        ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
 
2039
    if( !p_track->b_enable )
 
2040
        p_track->fmt.i_priority = -1;
1784
2041
 
1785
2042
    p_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;
1786
2043
    p_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;
1803
2060
    if( !p_track->i_timescale )
1804
2061
        return;
1805
2062
 
1806
 
    for( i = 0; i < 3; i++ )
1807
 
    {
1808
 
        language[i] = p_mdhd->data.p_mdhd->i_language[i];
1809
 
    }
1810
 
    language[3] = '\0';
 
2063
    if( p_mdhd->data.p_mdhd->i_language_code < 0x800 )
 
2064
    {
 
2065
        /* We can convert i_language_code into iso 639 code,
 
2066
         * I won't */
 
2067
        strcpy( language, MP4_ConvertMacCode( p_mdhd->data.p_mdhd->i_language_code ) );
 
2068
        p_track->b_mac_encoding = true;
 
2069
    }
 
2070
    else
 
2071
    {
 
2072
        for( i = 0; i < 3; i++ )
 
2073
            language[i] = p_mdhd->data.p_mdhd->i_language[i];
 
2074
        language[3] = '\0';
 
2075
    }
1811
2076
 
1812
2077
    switch( p_hdlr->data.p_hdlr->i_handler_type )
1813
2078
    {
1847
2112
        msg_Warn( p_demux, "elst box found" );
1848
2113
        for( i = 0; i < elst->i_entry_count; i++ )
1849
2114
        {
1850
 
            msg_Dbg( p_demux, "   - [%d] duration="I64Fd"ms media time="I64Fd
 
2115
            msg_Dbg( p_demux, "   - [%d] duration=%"PRId64"ms media time=%"PRId64
1851
2116
                     "ms) rate=%d.%d", i,
1852
2117
                     elst->i_segment_duration[i] * 1000 / p_sys->i_timescale,
1853
2118
                     elst->i_media_time[i] >= 0 ?
1854
2119
                     (int64_t)(elst->i_media_time[i] * 1000 / p_track->i_timescale) :
1855
 
                     I64C(-1),
 
2120
                     INT64_C(-1),
1856
2121
                     elst->i_media_rate_integer[i],
1857
2122
                     elst->i_media_rate_fraction[i] );
1858
2123
        }
1875
2140
        p_drms->data.p_sample_soun->p_drms : NULL;
1876
2141
 
1877
2142
    /* Set language */
1878
 
    if( strcmp( language, "```" ) && strcmp( language, "und" ) )
 
2143
    if( *language && strcmp( language, "```" ) && strcmp( language, "und" ) )
1879
2144
    {
1880
2145
        p_track->fmt.psz_language = strdup( language );
1881
2146
    }
1907
2172
    p_track->i_chunk  = 0;
1908
2173
    p_track->i_sample = 0;
1909
2174
 
 
2175
    /* Mark chapter only track */
 
2176
    if( p_sys->p_tref_chap )
 
2177
    {
 
2178
        MP4_Box_data_tref_generic_t *p_chap = p_sys->p_tref_chap->data.p_tref_generic;
 
2179
        unsigned int i;
 
2180
 
 
2181
        for( i = 0; i < p_chap->i_entry_count; i++ )
 
2182
        {
 
2183
            if( p_track->i_track_ID == p_chap->i_track_ID[i] )
 
2184
            {
 
2185
                p_track->b_chapter = true;
 
2186
                p_track->b_enable = false;
 
2187
                break;
 
2188
            }
 
2189
        }
 
2190
    }
 
2191
 
1910
2192
    /* now create es */
 
2193
    if( b_force_enable &&
 
2194
        ( p_track->fmt.i_cat == VIDEO_ES || p_track->fmt.i_cat == AUDIO_ES ) )
 
2195
    {
 
2196
        msg_Warn( p_demux, "Enabling track[Id 0x%x] (buggy file without enabled track)",
 
2197
                  p_track->i_track_ID );
 
2198
        p_track->b_enable = true;
 
2199
        p_track->fmt.i_priority = 0;
 
2200
    }
 
2201
 
 
2202
    p_track->p_es = NULL;
1911
2203
    if( TrackCreateES( p_demux,
1912
2204
                       p_track, p_track->i_chunk,
1913
 
                       &p_track->p_es ) )
 
2205
                       p_track->b_chapter ? NULL : &p_track->p_es ) )
1914
2206
    {
1915
2207
        msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
1916
2208
                 p_track->i_track_ID );
1917
2209
        return;
1918
2210
    }
1919
 
 
 
2211
    p_track->b_ok = true;
1920
2212
#if 0
1921
2213
    {
1922
2214
        int i;
1929
2221
        }
1930
2222
    }
1931
2223
#endif
1932
 
    p_track->b_ok = VLC_TRUE;
1933
2224
}
1934
2225
 
1935
2226
/****************************************************************************
1937
2228
 ****************************************************************************
1938
2229
 * Destroy a track created by MP4_TrackCreate.
1939
2230
 ****************************************************************************/
1940
 
static void MP4_TrackDestroy( demux_t *p_demux, mp4_track_t *p_track )
 
2231
static void MP4_TrackDestroy( mp4_track_t *p_track )
1941
2232
{
1942
2233
    unsigned int i_chunk;
1943
2234
 
1944
 
    p_track->b_ok = VLC_FALSE;
1945
 
    p_track->b_enable   = VLC_FALSE;
1946
 
    p_track->b_selected = VLC_FALSE;
 
2235
    p_track->b_ok = false;
 
2236
    p_track->b_enable   = false;
 
2237
    p_track->b_selected = false;
1947
2238
 
1948
2239
    es_format_Clean( &p_track->fmt );
1949
2240
 
1951
2242
    {
1952
2243
        if( p_track->chunk )
1953
2244
        {
1954
 
           FREE(p_track->chunk[i_chunk].p_sample_count_dts);
1955
 
           FREE(p_track->chunk[i_chunk].p_sample_delta_dts );
 
2245
           FREENULL(p_track->chunk[i_chunk].p_sample_count_dts);
 
2246
           FREENULL(p_track->chunk[i_chunk].p_sample_delta_dts );
1956
2247
 
1957
 
           FREE(p_track->chunk[i_chunk].p_sample_count_pts);
1958
 
           FREE(p_track->chunk[i_chunk].p_sample_offset_pts );
 
2248
           FREENULL(p_track->chunk[i_chunk].p_sample_count_pts);
 
2249
           FREENULL(p_track->chunk[i_chunk].p_sample_offset_pts );
1959
2250
        }
1960
2251
    }
1961
 
    FREE( p_track->chunk );
 
2252
    FREENULL( p_track->chunk );
1962
2253
 
1963
2254
    if( !p_track->i_sample_size )
1964
2255
    {
1965
 
        FREE( p_track->p_sample_size );
 
2256
        FREENULL( p_track->p_sample_size );
1966
2257
    }
1967
2258
}
1968
2259
 
1969
2260
static int MP4_TrackSelect( demux_t *p_demux, mp4_track_t *p_track,
1970
2261
                            mtime_t i_start )
1971
2262
{
1972
 
    if( !p_track->b_ok )
 
2263
    if( !p_track->b_ok || p_track->b_chapter )
1973
2264
    {
1974
2265
        return VLC_EGENERIC;
1975
2266
    }
1986
2277
 
1987
2278
static void MP4_TrackUnselect( demux_t *p_demux, mp4_track_t *p_track )
1988
2279
{
1989
 
    if( !p_track->b_ok )
 
2280
    if( !p_track->b_ok || p_track->b_chapter )
1990
2281
    {
1991
2282
        return;
1992
2283
    }
2000
2291
    if( p_track->p_es )
2001
2292
    {
2002
2293
        es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE,
2003
 
                        p_track->p_es, VLC_FALSE );
 
2294
                        p_track->p_es, false );
2004
2295
    }
2005
2296
 
2006
 
    p_track->b_selected = VLC_FALSE;
 
2297
    p_track->b_selected = false;
2007
2298
}
2008
2299
 
2009
2300
static int MP4_TrackSeek( demux_t *p_demux, mp4_track_t *p_track,
2012
2303
    uint32_t i_chunk;
2013
2304
    uint32_t i_sample;
2014
2305
 
2015
 
    if( !p_track->b_ok )
2016
 
    {
2017
 
        return( VLC_EGENERIC );
2018
 
    }
 
2306
    if( !p_track->b_ok || p_track->b_chapter )
 
2307
        return VLC_EGENERIC;
2019
2308
 
2020
 
    p_track->b_selected = VLC_FALSE;
 
2309
    p_track->b_selected = false;
2021
2310
 
2022
2311
    if( TrackTimeToSampleChunk( p_demux, p_track, i_start,
2023
2312
                                &i_chunk, &i_sample ) )
2024
2313
    {
2025
2314
        msg_Warn( p_demux, "cannot select track[Id 0x%x]",
2026
2315
                  p_track->i_track_ID );
2027
 
        return( VLC_EGENERIC );
 
2316
        return VLC_EGENERIC;
2028
2317
    }
2029
2318
 
2030
 
    p_track->b_selected = VLC_TRUE;
 
2319
    p_track->b_selected = true;
2031
2320
 
2032
2321
    if( TrackGotoChunkSample( p_demux, p_track, i_chunk, i_sample ) ==
2033
2322
        VLC_SUCCESS )
2034
2323
    {
2035
 
        p_track->b_selected = VLC_TRUE;
 
2324
        p_track->b_selected = true;
2036
2325
 
2037
2326
        es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
2038
2327
                        p_track->p_es, i_start );
2039
2328
    }
2040
2329
 
2041
 
    return( p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC );
 
2330
    return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;
2042
2331
}
2043
2332
 
2044
2333
 
2045
2334
/*
2046
2335
 * 3 types: for audio
2047
 
 * 
 
2336
 *
2048
2337
 */
2049
2338
#define QT_V0_MAX_SAMPLES 1024
2050
2339
static int MP4_TrackSampleSize( mp4_track_t *p_track )
2247
2536
        msg_Warn( p_demux, "elst old=%d new=%d", i_elst_last, tk->i_elst );
2248
2537
    }
2249
2538
}
 
2539
 
 
2540
/* */
 
2541
static const char *MP4_ConvertMacCode( uint16_t i_code )
 
2542
{
 
2543
    static const struct { const char *psz_iso639_1; uint16_t i_code; } p_cvt[] = {
 
2544
        { "en",   0 }, { "fr",   1 }, { "de",   2 }, { "it",   3 }, { "nl",   4 },
 
2545
        { "sv",   5 }, { "es",   6 }, { "da",   7 }, { "pt",   8 }, { "no",   9 },
 
2546
        { "he",  10 }, { "ja",  11 }, { "ar",  12 }, { "fi",  13 }, { "el",  14 },
 
2547
        { "is",  15 }, { "mt",  16 }, { "tr",  17 }, { "hr",  18 }, { "zh",  19 },
 
2548
        { "ur",  20 }, { "hi",  21 }, { "th",  22 }, { "ko",  23 }, { "lt",  24 },
 
2549
        { "pl",  25 }, { "hu",  26 }, { "et",  27 }, { "lv",  28 }, //{ "??",  29 },
 
2550
        { "fo",  30 }, { "fa",  31 }, { "ru",  32 }, { "zh",  33 }, { "nl",  34 },
 
2551
        { "ga",  35 }, { "sq",  36 }, { "ro",  37 }, { "cs",  38 }, { "sk",  39 },
 
2552
        { "sl",  40 }, { "yi",  41 }, { "sr",  42 }, { "mk",  43 }, { "bg",  44 },
 
2553
        { "uk",  45 }, { "be",  46 }, { "uz",  47 }, { "az",  48 }, { "kk",  48 },
 
2554
        { "az",  50 }, { "hy",  51 }, { "ka",  52 }, { "mo",  53 }, { "ky",  54 },
 
2555
        { "tg",  55 }, { "tk",  56 }, { "mn",  57 }, { "mn",  58 }, { "ps",  59 },
 
2556
        { "ku",  60 }, { "ks",  61 }, { "sd",  62 }, { "bo",  63 }, { "ne",  64 },
 
2557
        { "sa",  65 }, { "mr",  66 }, { "bn",  67 }, { "as",  68 }, { "gu",  69 },
 
2558
        { "pa",  70 }, { "or",  71 }, { "ml",  72 }, { "kn",  73 }, { "ta",  74 },
 
2559
        { "te",  75 }, { "si",  76 }, { "my",  77 }, { "km",  78 }, { "lo",  79 },
 
2560
        { "vi",  80 }, { "id",  81 }, { "tl",  82 }, { "ms",  83 }, { "ms",  84 },
 
2561
        { "am",  85 }, { "ti",  86 }, { "om",  87 }, { "so",  88 }, { "sw",  89 },
 
2562
        { "rw",  90 }, { "rn",  91 }, { "ny",  92 }, { "mg",  93 }, { "eo",  94 },
 
2563
 
 
2564
                                                     { "cy", 128 }, { "eu", 129 },
 
2565
        { "ca", 130 }, { "la", 131 }, { "qu", 132 }, { "gn", 133 }, { "ay", 134 },
 
2566
        { "tt", 135 }, { "ug", 136 }, { "dz", 137 }, { "jv", 138 }, { "su", 139 },
 
2567
        { "gl", 140 }, { "af", 141 }, { "br", 142 }, { "iu", 143 }, { "gd", 144 },
 
2568
        { "gv", 145 }, { "ga", 146 }, { "to", 147 }, { "el", 148 },
 
2569
        /* */
 
2570
        { NULL, 0 }
 
2571
    };
 
2572
    int i;
 
2573
    for( i = 0; p_cvt[i].psz_iso639_1 != NULL; i++ )
 
2574
    {
 
2575
        if( p_cvt[i].i_code == i_code )
 
2576
            return p_cvt[i].psz_iso639_1;
 
2577
    }
 
2578
    return "";
 
2579
}