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

« back to all changes in this revision

Viewing changes to modules/demux/mp4/libmp4.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:
2
2
 * libmp4.c : LibMP4 library for mp4 module for vlc
3
3
 *****************************************************************************
4
4
 * Copyright (C) 2001-2004 the VideoLAN team
5
 
 * $Id: 8b1acd885fba59aa0289b594b8dc7ebc95e2cf4c $
 
5
 * $Id$
6
6
 *
7
7
 * Author: Laurent Aimar <fenrir@via.ecp.fr>
8
8
 *
20
20
 * along with this program; if not, write to the Free Software
21
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22
22
 *****************************************************************************/
23
 
#include <stdlib.h>                                      /* malloc(), free() */
24
 
 
25
 
#include <vlc/vlc.h>
26
 
#include <vlc/input.h>
 
23
#ifdef HAVE_CONFIG_H
 
24
# include "config.h"
 
25
#endif
 
26
 
 
27
#include <vlc_common.h>
 
28
 
 
29
 
 
30
#include <vlc_demux.h>
27
31
 
28
32
#ifdef HAVE_ZLIB_H
29
33
#   include <zlib.h>                                  /* for compressed moov */
37
41
 *  *look* at the code.
38
42
 *
39
43
 *****************************************************************************/
40
 
#define FREENULL( p ) do { free( p ); p = NULL; } while(0)
41
 
 
42
 
#define MP4_BOX_HEADERSIZE( p_box ) \
43
 
  ( 8 + ( p_box->i_shortsize == 1 ? 8 : 0 ) \
 
44
#define MP4_BOX_HEADERSIZE( p_box )             \
 
45
  ( 8 + ( p_box->i_shortsize == 1 ? 8 : 0 )     \
44
46
      + ( p_box->i_type == FOURCC_uuid ? 16 : 0 ) )
45
47
 
46
 
#define MP4_GET1BYTE( dst ) \
47
 
    dst = *p_peek; p_peek++; i_read--
48
 
 
49
 
#define MP4_GET2BYTES( dst ) \
50
 
    dst = GetWBE( p_peek ); p_peek += 2; i_read -= 2
51
 
 
52
 
#define MP4_GET3BYTES( dst ) \
53
 
    dst = Get24bBE( p_peek ); p_peek += 3; i_read -= 3
54
 
 
55
 
#define MP4_GET4BYTES( dst ) \
56
 
    dst = GetDWBE( p_peek ); p_peek += 4; i_read -= 4
57
 
 
58
 
#define MP4_GETFOURCC( dst ) \
59
 
    dst = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] ); \
60
 
    p_peek += 4; i_read -= 4
61
 
 
62
 
#define MP4_GET8BYTES( dst ) \
63
 
    dst = GetQWBE( p_peek ); p_peek += 8; i_read -= 8
 
48
#define MP4_GETX_PRIVATE(dst, code, size) do { \
 
49
    if( (i_read) >= (size) ) { dst = (code); p_peek += (size); } \
 
50
    else { dst = 0; }   \
 
51
    i_read -= (size);   \
 
52
  } while(0)
 
53
 
 
54
#define MP4_GET1BYTE( dst )  MP4_GETX_PRIVATE( dst, *p_peek, 1 )
 
55
#define MP4_GET2BYTES( dst ) MP4_GETX_PRIVATE( dst, GetWBE(p_peek), 2 )
 
56
#define MP4_GET3BYTES( dst ) MP4_GETX_PRIVATE( dst, Get24bBE(p_peek), 3 )
 
57
#define MP4_GET4BYTES( dst ) MP4_GETX_PRIVATE( dst, GetDWBE(p_peek), 4 )
 
58
#define MP4_GET8BYTES( dst ) MP4_GETX_PRIVATE( dst, GetQWBE(p_peek), 8 )
 
59
#define MP4_GETFOURCC( dst ) MP4_GETX_PRIVATE( dst, \
 
60
                VLC_FOURCC(p_peek[0],p_peek[1],p_peek[2],p_peek[3]), 4)
64
61
 
65
62
#define MP4_GETVERSIONFLAGS( p_void ) \
66
63
    MP4_GET1BYTE( p_void->i_version ); \
67
64
    MP4_GET3BYTES( p_void->i_flags )
68
65
 
69
 
#define MP4_GETSTRINGZ( p_str ) \
70
 
    if( ( i_read > 0 )&&( p_peek[0] ) ) \
71
 
    { \
72
 
        p_str = calloc( sizeof( char ), __MIN( strlen( (char*)p_peek ), i_read )+1);\
73
 
        memcpy( p_str, p_peek, __MIN( strlen( (char*)p_peek ), i_read ) ); \
74
 
        p_str[__MIN( strlen( (char*)p_peek ), i_read )] = 0; \
75
 
        p_peek += strlen( (char *)p_str ) + 1; \
76
 
        i_read -= strlen( (char *)p_str ) + 1; \
77
 
    } \
78
 
    else \
79
 
    { \
 
66
#define MP4_GETSTRINGZ( p_str )         \
 
67
    if( (i_read > 0) && (p_peek[0]) )   \
 
68
    {       \
 
69
        const int __i_copy__ = strnlen( (char*)p_peek, i_read-1 );  \
 
70
        p_str = malloc( __i_copy__+1 );               \
 
71
        if( p_str ) \
 
72
        { \
 
73
             memcpy( p_str, p_peek, __i_copy__ ); \
 
74
             p_str[__i_copy__] = 0; \
 
75
        } \
 
76
        p_peek += __i_copy__ + 1;   \
 
77
        i_read -= __i_copy__ + 1;   \
 
78
    }       \
 
79
    else    \
 
80
    {       \
80
81
        p_str = NULL; \
81
82
    }
82
83
 
83
 
 
84
84
#define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) \
85
85
    int64_t  i_read = p_box->i_size; \
86
86
    uint8_t *p_peek, *p_buff; \
87
 
    i_read = p_box->i_size; \
 
87
    int i_actually_read; \
88
88
    if( !( p_peek = p_buff = malloc( i_read ) ) ) \
89
89
    { \
90
90
        return( 0 ); \
91
91
    } \
92
 
    if( stream_Read( p_stream, p_peek, i_read ) < i_read )\
 
92
    i_actually_read = stream_Read( p_stream, p_peek, i_read ); \
 
93
    if( i_actually_read < 0 || (int64_t)i_actually_read < i_read )\
93
94
    { \
94
95
        free( p_buff ); \
95
96
        return( 0 ); \
96
97
    } \
97
98
    p_peek += MP4_BOX_HEADERSIZE( p_box ); \
98
99
    i_read -= MP4_BOX_HEADERSIZE( p_box ); \
99
 
    if( !( p_box->data.p_data = malloc( sizeof( MP4_Box_data_TYPE_t ) ) ) ) \
 
100
    if( !( p_box->data.p_data = calloc( 1, sizeof( MP4_Box_data_TYPE_t ) ) ) ) \
100
101
    { \
101
102
      free( p_buff ); \
102
103
      return( 0 ); \
111
112
        return( i_code ); \
112
113
    } while (0)
113
114
 
114
 
#define FREE( p ) \
115
 
    if( p ) {free( p ); p = NULL; }
116
115
 
117
116
/* Some assumptions:
118
117
        * The input method HAVE to be seekable
119
118
 
120
119
*/
121
120
 
122
 
static uint32_t Get24bBE( uint8_t *p )
 
121
/* This macro is used when we want to printf the box type
 
122
 * APPLE annotation box is :
 
123
 *  either 0xA9 + 24-bit ASCII text string (and 0xA9 isn't printable)
 
124
 *  either 32-bit ASCII text string
 
125
 */
 
126
#define MP4_BOX_TYPE_ASCII() ( ((char*)&p_box->i_type)[0] != (char)0xA9 )
 
127
 
 
128
static uint32_t Get24bBE( const uint8_t *p )
123
129
{
124
130
    return( ( p[0] <<16 ) + ( p[1] <<8 ) + p[2] );
125
131
}
126
132
 
127
 
static void GetUUID( UUID_t *p_uuid, uint8_t *p_buff )
 
133
static void GetUUID( UUID_t *p_uuid, const uint8_t *p_buff )
128
134
{
129
135
    memcpy( p_uuid, p_buff, 16 );
130
136
}
134
140
    /* made by 0xXXXXXXXX-0011-0010-8000-00aa00389b71
135
141
            where XXXXXXXX is the fourcc */
136
142
    /* FIXME implement this */
 
143
    (void)p_uuid;
 
144
    (void)i_fourcc;
137
145
}
138
146
 
139
147
/* some functions for mp4 encoding of variables */
146
154
    int i_sec;
147
155
 
148
156
    /* date begin at 1 jan 1904 */
149
 
    i_date += ((I64C(1904) * 365) + 17) * 24 * 60 * 60;
 
157
    i_date += ((INT64_C(1904) * 365) + 17) * 24 * 60 * 60;
150
158
 
151
159
    i_day = i_date / ( 60*60*24);
152
160
    i_hour = ( i_date /( 60*60 ) ) % 60;
172
180
int MP4_ReadBoxCommon( stream_t *p_stream, MP4_Box_t *p_box )
173
181
{
174
182
    int      i_read;
175
 
    uint8_t  *p_peek;
 
183
    const uint8_t  *p_peek;
176
184
 
177
185
    if( ( ( i_read = stream_Peek( p_stream, &p_peek, 32 ) ) < 8 ) )
178
186
    {
215
223
#ifdef MP4_VERBOSE
216
224
    if( p_box->i_size )
217
225
    {
218
 
        msg_Dbg( p_stream, "found Box: %4.4s size "I64Fd,
219
 
                 (char*)&p_box->i_type, p_box->i_size );
 
226
        if MP4_BOX_TYPE_ASCII()
 
227
            msg_Dbg( p_stream, "found Box: %4.4s size %"PRId64,
 
228
                    (char*)&p_box->i_type, p_box->i_size );
 
229
        else
 
230
            msg_Dbg( p_stream, "found Box: c%3.3s size %"PRId64,
 
231
                    (char*)&p_box->i_type+1, p_box->i_size );
220
232
    }
221
233
#endif
222
234
 
245
257
 
246
258
    if( p_box->p_father )
247
259
    {
 
260
        const off_t i_box_end = p_box->i_size + p_box->i_pos;
 
261
        const off_t i_father_end = p_box->p_father->i_size + p_box->p_father->i_pos;
 
262
 
248
263
        /* check if it's within p-father */
249
 
        if( p_box->i_size + p_box->i_pos >=
250
 
            p_box->p_father->i_size + p_box->p_father->i_pos )
 
264
        if( i_box_end >= i_father_end )
251
265
        {
252
 
            msg_Dbg( p_stream, "out of bound child" );
 
266
            if( i_box_end > i_father_end )
 
267
                msg_Dbg( p_stream, "out of bound child" );
253
268
            return 0; /* out of bound */
254
269
        }
255
270
    }
310
325
static void MP4_FreeBox_Common( MP4_Box_t *p_box )
311
326
{
312
327
    /* Up to now do nothing */
 
328
    (void)p_box;
313
329
}
314
330
 
315
331
static int MP4_ReadBoxSkip( stream_t *p_stream, MP4_Box_t *p_box )
319
335
        p_box->p_father->i_type == VLC_FOURCC( 'r', 'o', 'o', 't' ) &&
320
336
        p_box->i_type == FOURCC_free )
321
337
    {
322
 
        uint8_t *p_peek;
 
338
        const uint8_t *p_peek;
323
339
        int     i_read;
324
340
        vlc_fourcc_t i_fcc;
325
341
 
344
360
 
345
361
    /* Nothing to do */
346
362
#ifdef MP4_VERBOSE
347
 
    msg_Dbg( p_stream, "skip box: \"%4.4s\"", (char*)&p_box->i_type );
 
363
    if MP4_BOX_TYPE_ASCII()
 
364
        msg_Dbg( p_stream, "skip box: \"%4.4s\"", (char*)&p_box->i_type );
 
365
    else
 
366
        msg_Dbg( p_stream, "skip box: \"c%3.3s\"", (char*)&p_box->i_type+1 );
348
367
#endif
349
368
    return 1;
350
369
}
368
387
 
369
388
        for( i =0; i < p_box->data.p_ftyp->i_compatible_brands_count; i++ )
370
389
        {
371
 
            MP4_GETFOURCC( p_box->data.p_ftyp->i_compatible_brands[i] );
 
390
            MP4_GETFOURCC( tab[i] );
372
391
        }
373
392
    }
374
393
    else
381
400
 
382
401
static void MP4_FreeBox_ftyp( MP4_Box_t *p_box )
383
402
{
384
 
    FREE( p_box->data.p_ftyp->i_compatible_brands );
 
403
    FREENULL( p_box->data.p_ftyp->i_compatible_brands );
385
404
}
386
405
 
387
406
 
548
567
        MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
549
568
        MP4_GET4BYTES( p_box->data.p_mdhd->i_duration );
550
569
    }
551
 
    i_language = GetWBE( p_peek );
 
570
    p_box->data.p_mdhd->i_language_code = i_language = GetWBE( p_peek );
552
571
    for( i = 0; i < 3; i++ )
553
572
    {
554
573
        p_box->data.p_mdhd->i_language[i] =
605
624
            MP4_GET1BYTE( i_len );
606
625
            i_copy = __MIN( i_read, i_len );
607
626
 
608
 
            memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_copy );
 
627
            memcpy( psz, p_peek, i_copy );
609
628
            p_box->data.p_hdlr->psz_name[i_copy] = '\0';
610
629
        }
611
630
        else
612
631
        {
613
 
            memcpy( p_box->data.p_hdlr->psz_name, p_peek, i_read );
 
632
            memcpy( psz, p_peek, i_read );
614
633
            p_box->data.p_hdlr->psz_name[i_read] = '\0';
615
634
        }
616
635
    }
617
636
 
618
637
#ifdef MP4_VERBOSE
619
 
    msg_Dbg( p_stream, "read box: \"hdlr\" handler type %4.4s name %s",
620
 
                       (char*)&p_box->data.p_hdlr->i_handler_type,
621
 
                       p_box->data.p_hdlr->psz_name );
 
638
        msg_Dbg( p_stream, "read box: \"hdlr\" handler type %4.4s name %s",
 
639
                   (char*)&p_box->data.p_hdlr->i_handler_type,
 
640
                   p_box->data.p_hdlr->psz_name );
622
641
 
623
642
#endif
624
643
    MP4_READBOX_EXIT( 1 );
626
645
 
627
646
static void MP4_FreeBox_hdlr( MP4_Box_t *p_box )
628
647
{
629
 
    FREE( p_box->data.p_hdlr->psz_name );
 
648
    FREENULL( p_box->data.p_hdlr->psz_name );
630
649
}
631
650
 
632
651
static int MP4_ReadBox_vmhd( stream_t *p_stream, MP4_Box_t *p_box )
715
734
 
716
735
static void MP4_FreeBox_url( MP4_Box_t *p_box )
717
736
{
718
 
    FREE( p_box->data.p_url->psz_location )
 
737
    FREENULL( p_box->data.p_url->psz_location );
719
738
}
720
739
 
721
740
static int MP4_ReadBox_urn( stream_t *p_stream, MP4_Box_t *p_box )
736
755
}
737
756
static void MP4_FreeBox_urn( MP4_Box_t *p_box )
738
757
{
739
 
    FREE( p_box->data.p_urn->psz_name );
740
 
    FREE( p_box->data.p_urn->psz_location );
 
758
    FREENULL( p_box->data.p_urn->psz_name );
 
759
    FREENULL( p_box->data.p_urn->psz_location );
741
760
}
742
761
 
743
762
 
781
800
    if( p_box->data.p_stts->i_sample_count == NULL
782
801
     || p_box->data.p_stts->i_sample_delta == NULL )
783
802
    {
784
 
        MP4_FreeBox_stts( p_box );
785
803
        MP4_READBOX_EXIT( 0 );
786
804
    }
787
805
 
822
840
    if( ( p_box->data.p_ctts->i_sample_count == NULL )
823
841
     || ( p_box->data.p_ctts->i_sample_offset == NULL ) )
824
842
    {
825
 
        MP4_FreeBox_ctts( p_box );
826
843
        MP4_READBOX_EXIT( 0 );
827
844
    }
828
845
 
873
890
    unsigned int i_len;
874
891
    unsigned int i_flags;
875
892
    unsigned int i_type;
876
 
    unsigned int code = 0;
877
893
 
878
894
    MP4_READBOX_ENTER( MP4_Box_data_esds_t );
879
895
 
906
922
            unsigned int i_len;
907
923
 
908
924
            MP4_GET1BYTE( i_len );
909
 
            es_descriptor.psz_URL = calloc( sizeof(char), i_len + 1 );
910
 
            memcpy( es_descriptor.psz_URL, p_peek, i_len );
911
 
            es_descriptor.psz_URL[i_len] = 0;
 
925
            es_descriptor.psz_URL = malloc( i_len + 1 );
 
926
            if( es_descriptor.psz_URL )
 
927
            {
 
928
                memcpy( es_descriptor.psz_URL, p_peek, i_len );
 
929
                es_descriptor.psz_URL[i_len] = 0;
 
930
            }
912
931
            p_peek += i_len;
913
932
            i_read -= i_len;
914
933
        }
937
956
#endif
938
957
 
939
958
    es_descriptor.p_decConfigDescr =
940
 
            malloc( sizeof( MP4_descriptor_decoder_config_t ));
 
959
            calloc( 1, sizeof( MP4_descriptor_decoder_config_t ));
941
960
    if( es_descriptor.p_decConfigDescr == NULL )
942
 
    {
943
 
        free( es_descriptor.psz_URL );
944
 
        goto error;
945
 
    }
 
961
        MP4_READBOX_EXIT( 0 );
946
962
 
947
963
    MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectTypeIndication );
948
964
    MP4_GET1BYTE( i_flags );
965
981
        msg_Dbg( p_stream, "found esds MP4DecSpecificDescr (%dBytes)",
966
982
                 i_len );
967
983
#endif
 
984
    if( i_len > i_read )
 
985
        MP4_READBOX_EXIT( 0 );
968
986
 
969
987
    es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
970
988
    es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
971
989
    if( es_descriptor.p_decConfigDescr->p_decoder_specific_info == NULL )
972
 
    {
973
 
        MP4_FreeBox_esds( p_box );
974
 
        goto error;
975
 
    }
 
990
        MP4_READBOX_EXIT( 0 );
 
991
 
976
992
    memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
977
993
            p_peek, i_len );
978
 
    code = 1;
979
 
 
980
 
error:
981
 
    MP4_READBOX_EXIT( code );
982
 
 
 
994
 
 
995
    MP4_READBOX_EXIT( 1 );
983
996
#undef es_descriptor
984
997
}
985
998
 
 
999
static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
 
1000
{
 
1001
    MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
 
1002
    int i;
 
1003
 
 
1004
    if( p_avcC->i_avcC > 0 ) FREENULL( p_avcC->p_avcC );
 
1005
 
 
1006
    if( p_avcC->sps )
 
1007
    {
 
1008
        for( i = 0; i < p_avcC->i_sps; i++ )
 
1009
            FREENULL( p_avcC->sps[i] );
 
1010
    }
 
1011
    if( p_avcC->pps )
 
1012
    {
 
1013
        for( i = 0; i < p_avcC->i_pps; i++ )
 
1014
            FREENULL( p_avcC->pps[i] );
 
1015
    }
 
1016
    if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->sps );
 
1017
    if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->i_sps_length );
 
1018
    if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->pps );
 
1019
    if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->i_pps_length );
 
1020
}
986
1021
 
987
1022
static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
988
1023
{
995
1030
    p_avcC->i_avcC = i_read;
996
1031
    if( p_avcC->i_avcC > 0 )
997
1032
    {
998
 
        p_avcC->p_avcC = malloc( p_avcC->i_avcC );
999
 
        memcpy( p_avcC->p_avcC, p_peek, i_read );
 
1033
        uint8_t * p = p_avcC->p_avcC = malloc( p_avcC->i_avcC );
 
1034
        if( p )
 
1035
            memcpy( p, p_peek, i_read );
1000
1036
    }
1001
1037
 
1002
1038
    MP4_GET1BYTE( p_avcC->i_version );
1013
1049
 
1014
1050
    if( p_avcC->i_sps > 0 )
1015
1051
    {
1016
 
        p_avcC->i_sps_length = malloc( p_avcC->i_sps * sizeof( uint16_t ) );
1017
 
        p_avcC->sps = malloc( p_avcC->i_sps * sizeof( uint8_t* ) );
 
1052
        p_avcC->i_sps_length = calloc( p_avcC->i_sps, sizeof( uint16_t ) );
 
1053
        p_avcC->sps = calloc( p_avcC->i_sps, sizeof( uint8_t* ) );
 
1054
 
 
1055
        if( !p_avcC->i_sps_length || !p_avcC->sps )
 
1056
            goto error;
1018
1057
 
1019
1058
        for( i = 0; i < p_avcC->i_sps; i++ )
1020
1059
        {
1021
1060
            MP4_GET2BYTES( p_avcC->i_sps_length[i] );
1022
1061
            p_avcC->sps[i] = malloc( p_avcC->i_sps_length[i] );
1023
 
            memcpy( p_avcC->sps[i], p_peek, p_avcC->i_sps_length[i] );
 
1062
            if( p_avcC->sps[i] )
 
1063
                memcpy( p_avcC->sps[i], p_peek, p_avcC->i_sps_length[i] );
1024
1064
 
1025
1065
            p_peek += p_avcC->i_sps_length[i];
1026
1066
            i_read -= p_avcC->i_sps_length[i];
1030
1070
    MP4_GET1BYTE( p_avcC->i_pps );
1031
1071
    if( p_avcC->i_pps > 0 )
1032
1072
    {
1033
 
        p_avcC->i_pps_length = malloc( p_avcC->i_pps * sizeof( uint16_t ) );
1034
 
        p_avcC->pps = malloc( p_avcC->i_pps * sizeof( uint8_t* ) );
 
1073
        p_avcC->i_pps_length = calloc( p_avcC->i_pps, sizeof( uint16_t ) );
 
1074
        p_avcC->pps = calloc( p_avcC->i_pps, sizeof( uint8_t* ) );
 
1075
 
 
1076
        if( !p_avcC->i_pps_length || !p_avcC->pps )
 
1077
            goto error;
1035
1078
 
1036
1079
        for( i = 0; i < p_avcC->i_pps; i++ )
1037
1080
        {
1038
1081
            MP4_GET2BYTES( p_avcC->i_pps_length[i] );
1039
1082
            p_avcC->pps[i] = malloc( p_avcC->i_pps_length[i] );
1040
 
            memcpy( p_avcC->pps[i], p_peek, p_avcC->i_pps_length[i] );
 
1083
            if( p_avcC->pps[i] )
 
1084
                memcpy( p_avcC->pps[i], p_peek, p_avcC->i_pps_length[i] );
1041
1085
 
1042
1086
            p_peek += p_avcC->i_pps_length[i];
1043
1087
            i_read -= p_avcC->i_pps_length[i];
1062
1106
 
1063
1107
#endif
1064
1108
    MP4_READBOX_EXIT( 1 );
1065
 
}
1066
 
 
1067
 
static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
1068
 
{
1069
 
    MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
1070
 
    int i;
1071
 
 
1072
 
    if( p_avcC->i_avcC > 0 )
1073
 
    {
1074
 
        if( p_avcC->p_avcC )
1075
 
             free( p_avcC->p_avcC );
1076
 
        p_avcC->p_avcC = NULL;
1077
 
    }
1078
 
    for( i = 0; i < p_avcC->i_sps; i++ )
1079
 
    {
1080
 
        FREE( p_avcC->sps[i] );
1081
 
    }
1082
 
    for( i = 0; i < p_avcC->i_pps; i++ )
1083
 
    {
1084
 
        FREE( p_avcC->pps[i] );
1085
 
    }
1086
 
    if( p_avcC->i_sps > 0 )
1087
 
    {
1088
 
        FREE( p_avcC->sps );
1089
 
        p_avcC->sps = NULL;
1090
 
        FREE( p_avcC->i_sps_length );
1091
 
        p_avcC->i_sps_length = NULL;
1092
 
    }
1093
 
    if( p_avcC->i_pps > 0 )
1094
 
    {
1095
 
        FREE( p_avcC->pps );
1096
 
        p_avcC->pps = NULL;
1097
 
        FREE( p_avcC->i_pps_length );
1098
 
        p_avcC->i_pps_length = NULL;
1099
 
    }
 
1109
 
 
1110
error:
 
1111
    MP4_READBOX_EXIT( 0 );
1100
1112
}
1101
1113
 
1102
1114
static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
1124
1136
    /*
1125
1137
     * XXX hack -> produce a copy of the nearly complete chunk
1126
1138
     */
 
1139
    p_box->data.p_sample_soun->i_qt_description = 0;
 
1140
    p_box->data.p_sample_soun->p_qt_description = NULL;
1127
1141
    if( i_read > 0 )
1128
1142
    {
1129
1143
        p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
1130
 
        if( p_box->data.p_sample_soun->p_qt_description == NULL )
1131
 
            MP4_READBOX_EXIT( 0 );
1132
 
        p_box->data.p_sample_soun->i_qt_description = i_read;
1133
 
        memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
1134
 
    }
1135
 
    else
1136
 
    {
1137
 
        p_box->data.p_sample_soun->i_qt_description = 0;
1138
 
        p_box->data.p_sample_soun->p_qt_description = NULL;
 
1144
        if( p_box->data.p_sample_soun->p_qt_description )
 
1145
        {
 
1146
            p_box->data.p_sample_soun->i_qt_description = i_read;
 
1147
            memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
 
1148
        }
1139
1149
    }
1140
1150
 
1141
1151
    MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_version );
1200
1210
        p_box->data.p_sample_soun->i_bytes_per_frame = 0;
1201
1211
        p_box->data.p_sample_soun->i_bytes_per_sample = 0;
1202
1212
 
1203
 
        msg_Dbg( p_stream, "read box: \"soun\" mp4 or qt1/2 (rest="I64Fd")",
 
1213
        msg_Dbg( p_stream, "read box: \"soun\" mp4 or qt1/2 (rest=%"PRId64")",
1204
1214
                 i_read );
1205
1215
        stream_Seek( p_stream, p_box->i_pos +
1206
1216
                        MP4_BOX_HEADERSIZE( p_box ) + 28 );
1209
1219
    if( p_box->i_type == FOURCC_drms )
1210
1220
    {
1211
1221
        p_box->data.p_sample_soun->p_drms =
1212
 
            drms_alloc( p_stream->p_vlc->psz_homedir );
 
1222
            drms_alloc( config_GetHomeDir() );
1213
1223
 
1214
1224
        if( p_box->data.p_sample_soun->p_drms == NULL )
1215
1225
        {
1223
1233
        p_box->data.p_sample_soun->i_channelcount = 1;
1224
1234
    }
1225
1235
 
1226
 
    if( p_box->i_type == FOURCC_alac )
1227
 
    {
1228
 
        free( p_box->data.p_sample_soun->p_qt_description );
1229
 
 
1230
 
        p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
1231
 
        if( p_box->data.p_sample_soun->p_qt_description == NULL )
1232
 
            MP4_READBOX_EXIT( 0 );
1233
 
        p_box->data.p_sample_soun->i_qt_description = i_read;
1234
 
        memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
1235
 
    }
1236
 
    else
1237
 
    {
1238
 
        MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
1239
 
    }
 
1236
    MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds/wave/... */
1240
1237
 
1241
1238
#ifdef MP4_VERBOSE
1242
1239
    msg_Dbg( p_stream, "read box: \"soun\" in stsd channel %d "
1253
1250
 
1254
1251
static void MP4_FreeBox_sample_soun( MP4_Box_t *p_box )
1255
1252
{
1256
 
    FREE( p_box->data.p_sample_soun->p_qt_description );
 
1253
    FREENULL( p_box->data.p_sample_soun->p_qt_description );
1257
1254
 
1258
1255
    if( p_box->i_type == FOURCC_drms )
1259
1256
    {
1334
1331
 
1335
1332
void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
1336
1333
{
1337
 
    FREE( p_box->data.p_sample_vide->p_qt_image_description );
 
1334
    FREENULL( p_box->data.p_sample_vide->p_qt_image_description );
1338
1335
}
1339
1336
 
1340
1337
static int MP4_ReadBox_sample_mp4s( stream_t *p_stream, MP4_Box_t *p_box )
1431
1428
/* We can't easily call it, and anyway ~ 20 bytes lost isn't a real problem */
1432
1429
static void MP4_FreeBox_sample_text( MP4_Box_t *p_box )
1433
1430
{
1434
 
    FREE( p_box->data.p_sample_text->psz_text_name );
 
1431
    FREENULL( p_box->data.p_sample_text->psz_text_name );
1435
1432
}
1436
1433
#endif
1437
1434
 
1524
1521
     || p_box->data.p_stsc->i_samples_per_chunk == NULL
1525
1522
     || p_box->data.p_stsc->i_sample_description_index == NULL )
1526
1523
    {
1527
 
        MP4_FreeBox_stsc( p_box );
1528
1524
        MP4_READBOX_EXIT( 0 );
1529
1525
    }
1530
1526
 
1652
1648
    if( p_box->data.p_stsh->i_shadowed_sample_number == NULL
1653
1649
     || p_box->data.p_stsh->i_sync_sample_number == NULL )
1654
1650
    {
1655
 
        MP4_FreeBox_stsh( p_box );
1656
1651
        MP4_READBOX_EXIT( 0 );
1657
1652
    }
1658
1653
 
1689
1684
    }
1690
1685
 
1691
1686
#ifdef MP4_VERBOSE
1692
 
    msg_Dbg( p_stream, "read box: \"stdp\" entry-count "I64Fd,
 
1687
    msg_Dbg( p_stream, "read box: \"stdp\" entry-count %"PRId64,
1693
1688
                      i_read / 2 );
1694
1689
 
1695
1690
#endif
1730
1725
     || p_box->data.p_padb->i_reserved2 == NULL
1731
1726
     || p_box->data.p_padb->i_pad1 == NULL )
1732
1727
    {
1733
 
        MP4_FreeBox_padb( p_box );
1734
1728
        MP4_READBOX_EXIT( 0 );
1735
1729
    }
1736
1730
 
1738
1732
    {
1739
1733
        if( i >= count )
1740
1734
        {
1741
 
            MP4_FreeBox_padb( p_box );
1742
1735
            MP4_READBOX_EXIT( 0 );
1743
1736
        }
1744
1737
        p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 7 )&0x01;
1750
1743
    }
1751
1744
 
1752
1745
#ifdef MP4_VERBOSE
1753
 
    msg_Dbg( p_stream, "read box: \"stdp\" entry-count "I64Fd,
 
1746
    msg_Dbg( p_stream, "read box: \"stdp\" entry-count %"PRId64,
1754
1747
                      i_read / 2 );
1755
1748
 
1756
1749
#endif
1789
1782
     || p_box->data.p_elst->i_media_rate_integer == NULL
1790
1783
     || p_box->data.p_elst->i_media_rate_fraction == NULL )
1791
1784
    {
1792
 
        MP4_FreeBox_elst( p_box );
1793
1785
        MP4_READBOX_EXIT( 0 );
1794
1786
    }
1795
1787
 
1817
1809
    }
1818
1810
 
1819
1811
#ifdef MP4_VERBOSE
1820
 
    msg_Dbg( p_stream, "read box: \"elst\" entry-count %u",
1821
 
             (unsigned)p_box->data.p_elst->i_entry_count );
 
1812
    msg_Dbg( p_stream, "read box: \"elst\" entry-count %lu",
 
1813
             (unsigned long)p_box->data.p_elst->i_entry_count );
1822
1814
#endif
1823
1815
    MP4_READBOX_EXIT( 1 );
1824
1816
}
1854
1846
 
1855
1847
static void MP4_FreeBox_cprt( MP4_Box_t *p_box )
1856
1848
{
1857
 
    FREE( p_box->data.p_cprt->psz_notice );
 
1849
    FREENULL( p_box->data.p_cprt->psz_notice );
1858
1850
}
1859
1851
 
1860
1852
 
1901
1893
}
1902
1894
static void MP4_FreeBox_cmvd( MP4_Box_t *p_box )
1903
1895
{
1904
 
    FREE( p_box->data.p_cmvd->p_data );
 
1896
    FREENULL( p_box->data.p_cmvd->p_data );
1905
1897
}
1906
1898
 
1907
1899
 
2014
2006
    /* now create a memory stream */
2015
2007
    p_stream_memory =
2016
2008
        stream_MemoryNew( VLC_OBJECT(p_stream), p_cmvd->data.p_cmvd->p_data,
2017
 
                          p_cmvd->data.p_cmvd->i_uncompressed_size, VLC_TRUE );
 
2009
                          p_cmvd->data.p_cmvd->i_uncompressed_size, true );
2018
2010
 
2019
2011
    /* and read uncompressd moov */
2020
2012
    p_box->data.p_cmov->p_moov = MP4_ReadBox( p_stream_memory, NULL );
2060
2052
 
2061
2053
#ifdef MP4_VERBOSE
2062
2054
    msg_Dbg( p_stream,
2063
 
             "read box: \"rdrf\" type:%4.4s ref %s",
2064
 
             (char*)&p_box->data.p_rdrf->i_ref_type,
2065
 
             p_box->data.p_rdrf->psz_ref );
2066
 
 
 
2055
            "read box: \"rdrf\" type:%4.4s ref %s",
 
2056
            (char*)&p_box->data.p_rdrf->i_ref_type,
 
2057
            p_box->data.p_rdrf->psz_ref );
2067
2058
#endif
2068
2059
    MP4_READBOX_EXIT( 1 );
2069
2060
}
2070
2061
 
2071
2062
static void MP4_FreeBox_rdrf( MP4_Box_t *p_box )
2072
2063
{
2073
 
    FREE( p_box->data.p_rdrf->psz_ref )
 
2064
    FREENULL( p_box->data.p_rdrf->psz_ref );
2074
2065
}
2075
2066
 
2076
2067
 
2142
2133
                               p_box->i_type, p_peek, i_read );
2143
2134
        if( i_ret )
2144
2135
        {
2145
 
            char *psz_error;
 
2136
            const char *psz_error;
2146
2137
 
2147
2138
            switch( i_ret )
2148
2139
            {
2154
2145
                case -6: psz_error = "invalid user key"; break;
2155
2146
                default: psz_error = "unknown error"; break;
2156
2147
            }
2157
 
 
2158
 
            msg_Err( p_stream, "drms_init(%4.4s) failed (%s)",
2159
 
                     (char *)&p_box->i_type, psz_error );
 
2148
            if MP4_BOX_TYPE_ASCII()
 
2149
                msg_Err( p_stream, "drms_init(%4.4s) failed (%s)",
 
2150
                        (char *)&p_box->i_type, psz_error );
 
2151
            else
 
2152
                msg_Err( p_stream, "drms_init(c%3.3s) failed (%s)",
 
2153
                        (char *)&p_box->i_type+1, psz_error );
2160
2154
 
2161
2155
            drms_free( p_drms_box->data.p_sample_soun->p_drms );
2162
2156
            p_drms_box->data.p_sample_soun->p_drms = NULL;
2168
2162
 
2169
2163
static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
2170
2164
{
2171
 
    int16_t i_length, i_dummy;
 
2165
    uint16_t i16;
2172
2166
 
2173
2167
    MP4_READBOX_ENTER( MP4_Box_data_0xa9xxx_t );
2174
2168
 
2175
2169
    p_box->data.p_0xa9xxx->psz_text = NULL;
2176
2170
 
2177
 
    MP4_GET2BYTES( i_length );
2178
 
    MP4_GET2BYTES( i_dummy );
 
2171
    MP4_GET2BYTES( i16 );
2179
2172
 
2180
 
    if( i_length > 0 )
 
2173
    if( i16 > 0 )
2181
2174
    {
2182
 
        if( i_length > i_read ) i_length = i_read;
2183
 
 
2184
 
        p_box->data.p_0xa9xxx->psz_text = malloc( i_length + 1 );
 
2175
        int i_length = i16;
 
2176
 
 
2177
        MP4_GET2BYTES( i16 );
 
2178
        if( i_length >= i_read ) i_length = i_read + 1;
 
2179
 
 
2180
        p_box->data.p_0xa9xxx->psz_text = malloc( i_length );
2185
2181
        if( p_box->data.p_0xa9xxx->psz_text == NULL )
2186
2182
            MP4_READBOX_EXIT( 0 );
2187
2183
 
 
2184
        i_length--;
2188
2185
        memcpy( p_box->data.p_0xa9xxx->psz_text,
2189
2186
                p_peek, i_length );
2190
2187
        p_box->data.p_0xa9xxx->psz_text[i_length] = '\0';
2191
2188
 
2192
2189
#ifdef MP4_VERBOSE
2193
2190
        msg_Dbg( p_stream,
2194
 
                 "read box: \"%4.4s\" text=`%s'",
2195
 
                 (char*)&p_box->i_type,
2196
 
                 p_box->data.p_0xa9xxx->psz_text );
2197
 
#endif
 
2191
                 "read box: \"c%3.3s\" text=`%s'",
 
2192
                 ((char*)&p_box->i_type + 1),
 
2193
                 p_box->data.p_0xa9xxx->psz_text );
 
2194
#endif
 
2195
    }
 
2196
    else
 
2197
    {
 
2198
        /* try iTune/Quicktime format, rewind to start */
 
2199
        p_peek -= 2; i_read += 2;
 
2200
        // we are expecting a 'data' box
 
2201
        uint32_t i_data_len;
 
2202
        uint32_t i_data_tag;
 
2203
 
 
2204
        MP4_GET4BYTES( i_data_len );
 
2205
        if( i_data_len > i_read ) i_data_len = i_read;
 
2206
        MP4_GETFOURCC( i_data_tag );
 
2207
        if( (i_data_len > 0) && (i_data_tag == VLC_FOURCC('d', 'a', 't', 'a')) )
 
2208
        {
 
2209
            /* data box contains a version/flags field */
 
2210
            uint32_t i_version;
 
2211
            uint32_t i_reserved;
 
2212
            MP4_GET4BYTES( i_version );
 
2213
            MP4_GET4BYTES( i_reserved );
 
2214
            // version should be 0, flags should be 1 for text, 0 for data
 
2215
            if( ( i_version == 0x00000001 ) && (i_data_len >= 12 ) )
 
2216
            {
 
2217
                // the rest is the text
 
2218
                i_data_len -= 12;
 
2219
                p_box->data.p_0xa9xxx->psz_text = malloc( i_data_len + 1 );
 
2220
                if( p_box->data.p_0xa9xxx->psz_text == NULL )
 
2221
                    MP4_READBOX_EXIT( 0 );
 
2222
 
 
2223
                memcpy( p_box->data.p_0xa9xxx->psz_text,
 
2224
                        p_peek, i_data_len );
 
2225
                p_box->data.p_0xa9xxx->psz_text[i_data_len] = '\0';
 
2226
#ifdef MP4_VERBOSE
 
2227
        msg_Dbg( p_stream,
 
2228
                 "read box: \"c%3.3s\" text=`%s'",
 
2229
                 ((char*)&p_box->i_type+1),
 
2230
                 p_box->data.p_0xa9xxx->psz_text );
 
2231
#endif
 
2232
            }
 
2233
            else
 
2234
            {
 
2235
                // TODO: handle data values for ID3 tag values, track num or cover art,etc...
 
2236
            }
 
2237
        }
2198
2238
    }
2199
2239
 
2200
2240
    MP4_READBOX_EXIT( 1 );
2201
2241
}
2202
2242
static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
2203
2243
{
2204
 
    FREE( p_box->data.p_0xa9xxx->psz_text );
 
2244
    FREENULL( p_box->data.p_0xa9xxx->psz_text );
 
2245
}
 
2246
 
 
2247
/* Chapter support */
 
2248
static void MP4_FreeBox_chpl( MP4_Box_t *p_box )
 
2249
{
 
2250
    MP4_Box_data_chpl_t *p_chpl = p_box->data.p_chpl;
 
2251
    int i;
 
2252
    for( i = 0; i < p_chpl->i_chapter; i++ )
 
2253
        free( p_chpl->chapter[i].psz_name );
 
2254
}
 
2255
 
 
2256
static int MP4_ReadBox_chpl( stream_t *p_stream, MP4_Box_t *p_box )
 
2257
{
 
2258
    MP4_Box_data_chpl_t *p_chpl;
 
2259
    uint32_t i_dummy;
 
2260
    int i;
 
2261
    MP4_READBOX_ENTER( MP4_Box_data_chpl_t );
 
2262
 
 
2263
    p_chpl = p_box->data.p_chpl;
 
2264
 
 
2265
    MP4_GETVERSIONFLAGS( p_chpl );
 
2266
 
 
2267
    MP4_GET4BYTES( i_dummy );
 
2268
 
 
2269
    MP4_GET1BYTE( p_chpl->i_chapter );
 
2270
 
 
2271
    for( i = 0; i < p_chpl->i_chapter; i++ )
 
2272
    {
 
2273
        uint64_t i_start;
 
2274
        uint8_t i_len;
 
2275
        int i_copy;
 
2276
        MP4_GET8BYTES( i_start );
 
2277
        MP4_GET1BYTE( i_len );
 
2278
 
 
2279
        p_chpl->chapter[i].psz_name = malloc( i_len + 1 );
 
2280
        if( !p_chpl->chapter[i].psz_name )
 
2281
            goto error;
 
2282
 
 
2283
        i_copy = __MIN( i_len, i_read );
 
2284
        if( i_copy > 0 )
 
2285
            memcpy( p_chpl->chapter[i].psz_name, p_peek, i_copy );
 
2286
        p_chpl->chapter[i].psz_name[i_copy] = '\0';
 
2287
        p_chpl->chapter[i].i_start = i_start;
 
2288
 
 
2289
        p_peek += i_copy;
 
2290
        i_read -= i_copy;
 
2291
    }
 
2292
    /* Bubble sort by increasing start date */
 
2293
    do
 
2294
    {
 
2295
        for( i = 0; i < p_chpl->i_chapter - 1; i++ )
 
2296
        {
 
2297
            if( p_chpl->chapter[i].i_start > p_chpl->chapter[i+1].i_start )
 
2298
            {
 
2299
                char *psz = p_chpl->chapter[i+1].psz_name;
 
2300
                int64_t i64 = p_chpl->chapter[i+1].i_start;
 
2301
 
 
2302
                p_chpl->chapter[i+1].psz_name = p_chpl->chapter[i].psz_name;
 
2303
                p_chpl->chapter[i+1].i_start = p_chpl->chapter[i].i_start;
 
2304
 
 
2305
                p_chpl->chapter[i].psz_name = psz;
 
2306
                p_chpl->chapter[i].i_start = i64;
 
2307
 
 
2308
                i = -1;
 
2309
                break;
 
2310
            }
 
2311
        }
 
2312
    } while( i == -1 );
 
2313
 
 
2314
#ifdef MP4_VERBOSE
 
2315
    msg_Dbg( p_stream, "read box: \"chpl\" %d chapters",
 
2316
                       p_chpl->i_chapter );
 
2317
#endif
 
2318
    MP4_READBOX_EXIT( 1 );
 
2319
 
 
2320
error:
 
2321
    MP4_READBOX_EXIT( 0 );
 
2322
}
 
2323
 
 
2324
static int MP4_ReadBox_tref_generic( stream_t *p_stream, MP4_Box_t *p_box )
 
2325
{
 
2326
    unsigned int i;
 
2327
    MP4_READBOX_ENTER( MP4_Box_data_tref_generic_t );
 
2328
 
 
2329
    p_box->data.p_tref_generic->i_track_ID = NULL;
 
2330
    p_box->data.p_tref_generic->i_entry_count = i_read / sizeof(uint32_t);
 
2331
    if( p_box->data.p_tref_generic->i_entry_count > 0 )
 
2332
        p_box->data.p_tref_generic->i_track_ID = calloc( p_box->data.p_tref_generic->i_entry_count, sizeof(uint32_t) );
 
2333
    if( p_box->data.p_tref_generic->i_track_ID == NULL )
 
2334
        MP4_READBOX_EXIT( 0 );
 
2335
 
 
2336
    for( i = 0; i < p_box->data.p_tref_generic->i_entry_count; i++ )
 
2337
    {
 
2338
        MP4_GET4BYTES( p_box->data.p_tref_generic->i_track_ID[i] );
 
2339
    }
 
2340
#ifdef MP4_VERBOSE
 
2341
        msg_Dbg( p_stream, "read box: \"chap\" %d references",
 
2342
                 p_box->data.p_tref_generic->i_entry_count );
 
2343
#endif
 
2344
 
 
2345
    MP4_READBOX_EXIT( 1 );
 
2346
}
 
2347
static void MP4_FreeBox_tref_generic( MP4_Box_t *p_box )
 
2348
{
 
2349
    FREENULL( p_box->data.p_tref_generic->i_track_ID );
 
2350
}
 
2351
 
 
2352
static int MP4_ReadBox_meta( stream_t *p_stream, MP4_Box_t *p_box )
 
2353
{
 
2354
    uint8_t meta_data[8];
 
2355
    int i_actually_read;
 
2356
 
 
2357
    // skip over box header
 
2358
    i_actually_read = stream_Read( p_stream, meta_data, 8 );
 
2359
    if( i_actually_read < 8 )
 
2360
        return 0;
 
2361
 
 
2362
    /* meta content starts with a 4 byte version/flags value (should be 0) */
 
2363
    i_actually_read = stream_Read( p_stream, meta_data, 4 );
 
2364
    if( i_actually_read < 4 )
 
2365
        return 0;
 
2366
 
 
2367
    /* then it behaves like a container */
 
2368
    return MP4_ReadBoxContainerRaw( p_stream, p_box );
2205
2369
}
2206
2370
 
2207
2371
/* For generic */
2239
2403
    }
2240
2404
 
2241
2405
unknown:
2242
 
    msg_Warn( p_stream,
2243
 
              "unknown box type %4.4s (incompletely loaded)",
2244
 
              (char*)&p_box->i_type );
 
2406
    if MP4_BOX_TYPE_ASCII()
 
2407
        msg_Warn( p_stream,
 
2408
                "unknown box type %4.4s (incompletely loaded)",
 
2409
                (char*)&p_box->i_type );
 
2410
    else
 
2411
        msg_Warn( p_stream,
 
2412
                "unknown box type c%3.3s (incompletely loaded)",
 
2413
                (char*)&p_box->i_type+1 );
2245
2414
 
2246
2415
    return 1;
2247
2416
}
2250
2419
/****                   "Higher level" Functions                          ****/
2251
2420
/**** ------------------------------------------------------------------- ****/
2252
2421
 
2253
 
static struct
 
2422
static const struct
2254
2423
{
2255
2424
    uint32_t i_type;
2256
2425
    int  (*MP4_ReadBox_function )( stream_t *p_stream, MP4_Box_t *p_box );
2274
2443
    { FOURCC_tref,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2275
2444
    { FOURCC_gmhd,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2276
2445
    { FOURCC_wave,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
 
2446
    { FOURCC_ilst,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
2277
2447
 
2278
2448
    /* specific box */
2279
2449
    { FOURCC_ftyp,  MP4_ReadBox_ftyp,       MP4_FreeBox_ftyp },
2366
2536
 
2367
2537
    { FOURCC_dvc,   MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2368
2538
    { FOURCC_dvp,   MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
 
2539
    { FOURCC_dv5n,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
 
2540
    { FOURCC_dv5p,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2369
2541
    { FOURCC_VP31,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2370
2542
    { FOURCC_vp31,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2371
2543
    { FOURCC_h264,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2373
2545
    { FOURCC_jpeg,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2374
2546
    { FOURCC_avc1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
2375
2547
 
 
2548
    { FOURCC_yv12,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
 
2549
    { FOURCC_yuv2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
 
2550
 
2376
2551
    { FOURCC_mp4s,  MP4_ReadBox_sample_mp4s,    MP4_FreeBox_Common },
2377
2552
 
2378
2553
    /* XXX there is 2 box where we could find this entry stbl and tref*/
2382
2557
    { FOURCC_dpnd,  MP4_ReadBox_default,   NULL },
2383
2558
    { FOURCC_ipir,  MP4_ReadBox_default,   NULL },
2384
2559
    { FOURCC_mpod,  MP4_ReadBox_default,   NULL },
 
2560
    { FOURCC_chap,  MP4_ReadBox_tref_generic,   MP4_FreeBox_tref_generic },
2385
2561
 
2386
2562
    /* found in hnti */
2387
2563
    { FOURCC_rtp,   MP4_ReadBox_default,   NULL },
2428
2604
    { FOURCC_0xa9ope,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2429
2605
    { FOURCC_0xa9com,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
2430
2606
 
 
2607
    { FOURCC_chpl,   MP4_ReadBox_chpl,          MP4_FreeBox_chpl },
 
2608
 
 
2609
    /* iTunes/Quicktime meta info */
 
2610
    { FOURCC_meta,  MP4_ReadBox_meta,       MP4_FreeBox_Common },
 
2611
 
2431
2612
    /* Last entry */
2432
2613
    { 0,             MP4_ReadBox_default,       NULL }
2433
2614
};
2440
2621
 *****************************************************************************/
2441
2622
static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father )
2442
2623
{
2443
 
    MP4_Box_t    *p_box = malloc( sizeof( MP4_Box_t ) );
 
2624
    MP4_Box_t    *p_box = calloc( 1, sizeof( MP4_Box_t ) ); /* Needed to ensure simple on error handler */
2444
2625
    unsigned int i_index;
2445
2626
 
2446
2627
    if( p_box == NULL )
2472
2653
 
2473
2654
    if( !(MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box ) )
2474
2655
    {
2475
 
        free( p_box );
 
2656
        MP4_BoxFree( p_stream, p_box );
2476
2657
        return NULL;
2477
2658
    }
2478
2659
 
2489
2670
    MP4_Box_t    *p_child;
2490
2671
 
2491
2672
    if( !p_box )
2492
 
    {
2493
2673
        return; /* hehe */
2494
 
    }
2495
2674
 
2496
2675
    for( p_child = p_box->p_first; p_child != NULL; )
2497
2676
    {
2516
2695
        if( MP4_Box_Function[i_index].MP4_FreeBox_function == NULL )
2517
2696
        {
2518
2697
            /* Should not happen */
2519
 
            msg_Warn( s,
2520
 
                      "cannot free box %4.4s, type unknown",
2521
 
                      (char*)&p_box->i_type );
 
2698
            if MP4_BOX_TYPE_ASCII()
 
2699
                msg_Warn( s,
 
2700
                        "cannot free box %4.4s, type unknown",
 
2701
                        (char*)&p_box->i_type );
 
2702
            else
 
2703
                msg_Warn( s,
 
2704
                        "cannot free box c%3.3s, type unknown",
 
2705
                        (char*)&p_box->i_type+1 );
2522
2706
        }
2523
2707
        else
2524
2708
        {
2525
2709
            MP4_Box_Function[i_index].MP4_FreeBox_function( p_box );
2526
2710
        }
2527
 
 
2528
2711
        free( p_box->data.p_data );
2529
2712
    }
2530
 
 
2531
2713
    free( p_box );
2532
2714
}
2533
2715
 
2603
2785
 
2604
2786
    if( !i_level )
2605
2787
    {
2606
 
        msg_Dbg( s, "dumping root Box \"%4.4s\"",
2607
 
                          (char*)&p_box->i_type );
 
2788
        if MP4_BOX_TYPE_ASCII()
 
2789
            msg_Dbg( s, "dumping root Box \"%4.4s\"",
 
2790
                              (char*)&p_box->i_type );
 
2791
        else
 
2792
            msg_Dbg( s, "dumping root Box \"c%3.3s\"",
 
2793
                              (char*)&p_box->i_type+1 );
2608
2794
    }
2609
2795
    else
2610
2796
    {
2615
2801
        {
2616
2802
            str[i*5] = '|';
2617
2803
        }
2618
 
        sprintf( str + i_level * 5, "+ %4.4s size %d",
2619
 
                      (char*)&p_box->i_type,
2620
 
                      (uint32_t)p_box->i_size );
2621
 
 
 
2804
        if MP4_BOX_TYPE_ASCII()
 
2805
            sprintf( str + i_level * 5, "+ %4.4s size %d",
 
2806
                        (char*)&p_box->i_type, (uint32_t)p_box->i_size );
 
2807
        else
 
2808
            sprintf( str + i_level * 5, "+ c%3.3s size %d",
 
2809
                        (char*)&p_box->i_type+1, (uint32_t)p_box->i_size );
2622
2810
        msg_Dbg( s, "%s", str );
2623
2811
    }
2624
2812
    p_child = p_box->p_first;
2694
2882
}
2695
2883
 
2696
2884
static void __MP4_BoxGet( MP4_Box_t **pp_result,
2697
 
                          MP4_Box_t *p_box, char *psz_fmt, va_list args)
 
2885
                          MP4_Box_t *p_box, const char *psz_fmt, va_list args)
2698
2886
{
 
2887
    char *psz_dup;
2699
2888
    char    *psz_path;
2700
2889
 
2701
2890
    if( !p_box )
2704
2893
        return;
2705
2894
    }
2706
2895
 
2707
 
    vasprintf( &psz_path, psz_fmt, args );
 
2896
    if( vasprintf( &psz_path, psz_fmt, args ) == -1 )
 
2897
        psz_path = NULL;
2708
2898
 
2709
2899
    if( !psz_path || !psz_path[0] )
2710
2900
    {
2711
 
        FREE( psz_path );
 
2901
        FREENULL( psz_path );
2712
2902
        *pp_result = NULL;
2713
2903
        return;
2714
2904
    }
2715
2905
 
2716
2906
//    fprintf( stderr, "path:'%s'\n", psz_path );
2717
 
    psz_fmt = psz_path; /* keep this pointer, as it need to be unallocated */
 
2907
    psz_dup = psz_path; /* keep this pointer, as it need to be unallocated */
2718
2908
    for( ; ; )
2719
2909
    {
2720
2910
        char *psz_token;
2725
2915
//                 psz_path,psz_token,i_number );
2726
2916
        if( !psz_token )
2727
2917
        {
2728
 
            FREE( psz_token );
2729
 
            free( psz_fmt );
 
2918
            FREENULL( psz_token );
 
2919
            free( psz_dup );
2730
2920
            *pp_result = p_box;
2731
2921
            return;
2732
2922
        }
2741
2931
            if( !p_box )
2742
2932
            {
2743
2933
                free( psz_token );
2744
 
                free( psz_fmt );
 
2934
                free( psz_dup );
2745
2935
                *pp_result = NULL;
2746
2936
                return;
2747
2937
            }
2758
2948
            if( !p_box )
2759
2949
            {
2760
2950
                free( psz_token );
2761
 
                free( psz_fmt );
 
2951
                free( psz_dup );
2762
2952
                *pp_result = NULL;
2763
2953
                return;
2764
2954
            }
2775
2965
                if( !p_box )
2776
2966
                {
2777
2967
                    free( psz_token );
2778
 
                    free( psz_fmt );
 
2968
                    free( psz_dup );
2779
2969
                    *pp_result = NULL;
2780
2970
                    return;
2781
2971
                }
2799
2989
                if( !p_box )
2800
2990
                {
2801
2991
                    free( psz_token );
2802
 
                    free( psz_fmt );
 
2992
                    free( psz_dup );
2803
2993
                    *pp_result = NULL;
2804
2994
                    return;
2805
2995
                }
2814
3004
        else
2815
3005
        {
2816
3006
//            fprintf( stderr, "Argg malformed token \"%s\"",psz_token );
2817
 
            FREE( psz_token );
2818
 
            free( psz_fmt );
 
3007
            FREENULL( psz_token );
 
3008
            free( psz_dup );
2819
3009
            *pp_result = NULL;
2820
3010
            return;
2821
3011
        }
2833
3023
 * ex: /moov/trak[12]
2834
3024
 *     ../mdia
2835
3025
 *****************************************************************************/
2836
 
MP4_Box_t *MP4_BoxGet( MP4_Box_t *p_box, char *psz_fmt, ... )
 
3026
MP4_Box_t *MP4_BoxGet( MP4_Box_t *p_box, const char *psz_fmt, ... )
2837
3027
{
2838
3028
    va_list args;
2839
3029
    MP4_Box_t *p_result;
2854
3044
 * ex: /moov/trak[12]
2855
3045
 *     ../mdia
2856
3046
 *****************************************************************************/
2857
 
int MP4_BoxCount( MP4_Box_t *p_box, char *psz_fmt, ... )
 
3047
int MP4_BoxCount( MP4_Box_t *p_box, const char *psz_fmt, ... )
2858
3048
{
2859
3049
    va_list args;
2860
3050
    int     i_count;