libmp4.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:98k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * libmp4.c : LibMP4 library for mp4 module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2004 the VideoLAN team
  5.  * $Id: 9bf1a9dde4ba2434003c761eba28411d5af9a4e5 $
  6.  *
  7.  * Author: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. #ifdef HAVE_CONFIG_H
  24. # include "config.h"
  25. #endif
  26. #include <vlc_common.h>
  27. #include <vlc_demux.h>
  28. #ifdef HAVE_ZLIB_H
  29. #   include <zlib.h>                                  /* for compressed moov */
  30. #endif
  31. #include "libmp4.h"
  32. #include "drms.h"
  33. /*****************************************************************************
  34.  * Here are defined some macro to make life simpler but before using it
  35.  *  *look* at the code.
  36.  *
  37.  *****************************************************************************/
  38. #define MP4_BOX_HEADERSIZE( p_box )             
  39.   ( 8 + ( p_box->i_shortsize == 1 ? 8 : 0 )     
  40.       + ( p_box->i_type == FOURCC_uuid ? 16 : 0 ) )
  41. #define MP4_GETX_PRIVATE(dst, code, size) do { 
  42.     if( (i_read) >= (size) ) { dst = (code); p_peek += (size); } 
  43.     else { dst = 0; }   
  44.     i_read -= (size);   
  45.   } while(0)
  46. #define MP4_GET1BYTE( dst )  MP4_GETX_PRIVATE( dst, *p_peek, 1 )
  47. #define MP4_GET2BYTES( dst ) MP4_GETX_PRIVATE( dst, GetWBE(p_peek), 2 )
  48. #define MP4_GET3BYTES( dst ) MP4_GETX_PRIVATE( dst, Get24bBE(p_peek), 3 )
  49. #define MP4_GET4BYTES( dst ) MP4_GETX_PRIVATE( dst, GetDWBE(p_peek), 4 )
  50. #define MP4_GET8BYTES( dst ) MP4_GETX_PRIVATE( dst, GetQWBE(p_peek), 8 )
  51. #define MP4_GETFOURCC( dst ) MP4_GETX_PRIVATE( dst, 
  52.                 VLC_FOURCC(p_peek[0],p_peek[1],p_peek[2],p_peek[3]), 4)
  53. #define MP4_GETVERSIONFLAGS( p_void ) 
  54.     MP4_GET1BYTE( p_void->i_version ); 
  55.     MP4_GET3BYTES( p_void->i_flags )
  56. #define MP4_GETSTRINGZ( p_str )         
  57.     if( (i_read > 0) && (p_peek[0]) )   
  58.     {       
  59.         const int __i_copy__ = strnlen( (char*)p_peek, i_read-1 );  
  60.         p_str = malloc( __i_copy__+1 );               
  61.         if( p_str ) 
  62.         { 
  63.              memcpy( p_str, p_peek, __i_copy__ ); 
  64.              p_str[__i_copy__] = 0; 
  65.         } 
  66.         p_peek += __i_copy__ + 1;   
  67.         i_read -= __i_copy__ + 1;   
  68.     }       
  69.     else    
  70.     {       
  71.         p_str = NULL; 
  72.     }
  73. #define MP4_READBOX_ENTER( MP4_Box_data_TYPE_t ) 
  74.     int64_t  i_read = p_box->i_size; 
  75.     uint8_t *p_peek, *p_buff; 
  76.     int i_actually_read; 
  77.     if( !( p_peek = p_buff = malloc( i_read ) ) ) 
  78.     { 
  79.         return( 0 ); 
  80.     } 
  81.     i_actually_read = stream_Read( p_stream, p_peek, i_read ); 
  82.     if( i_actually_read < 0 || (int64_t)i_actually_read < i_read )
  83.     { 
  84.         free( p_buff ); 
  85.         return( 0 ); 
  86.     } 
  87.     p_peek += MP4_BOX_HEADERSIZE( p_box ); 
  88.     i_read -= MP4_BOX_HEADERSIZE( p_box ); 
  89.     if( !( p_box->data.p_data = calloc( 1, sizeof( MP4_Box_data_TYPE_t ) ) ) ) 
  90.     { 
  91.       free( p_buff ); 
  92.       return( 0 ); 
  93.     }
  94. #define MP4_READBOX_EXIT( i_code ) 
  95.     do 
  96.     { 
  97.         free( p_buff ); 
  98.         if( i_read < 0 ) 
  99.             msg_Warn( p_stream, "Not enough data" ); 
  100.         return( i_code ); 
  101.     } while (0)
  102. /* Some assumptions:
  103.         * The input method HAVE to be seekable
  104. */
  105. /* This macro is used when we want to printf the box type
  106.  * APPLE annotation box is :
  107.  *  either 0xA9 + 24-bit ASCII text string (and 0xA9 isn't printable)
  108.  *  either 32-bit ASCII text string
  109.  */
  110. #define MP4_BOX_TYPE_ASCII() ( ((char*)&p_box->i_type)[0] != (char)0xA9 )
  111. static uint32_t Get24bBE( const uint8_t *p )
  112. {
  113.     return( ( p[0] <<16 ) + ( p[1] <<8 ) + p[2] );
  114. }
  115. static void GetUUID( UUID_t *p_uuid, const uint8_t *p_buff )
  116. {
  117.     memcpy( p_uuid, p_buff, 16 );
  118. }
  119. static void CreateUUID( UUID_t *p_uuid, uint32_t i_fourcc )
  120. {
  121.     /* made by 0xXXXXXXXX-0011-0010-8000-00aa00389b71
  122.             where XXXXXXXX is the fourcc */
  123.     /* FIXME implement this */
  124.     (void)p_uuid;
  125.     (void)i_fourcc;
  126. }
  127. /* some functions for mp4 encoding of variables */
  128. static void MP4_ConvertDate2Str( char *psz, uint64_t i_date )
  129. {
  130.     int i_day;
  131.     int i_hour;
  132.     int i_min;
  133.     int i_sec;
  134.     /* date begin at 1 jan 1904 */
  135.     i_date += ((INT64_C(1904) * 365) + 17) * 24 * 60 * 60;
  136.     i_day = i_date / ( 60*60*24);
  137.     i_hour = ( i_date /( 60*60 ) ) % 60;
  138.     i_min  = ( i_date / 60 ) % 60;
  139.     i_sec =  i_date % 60;
  140.     sprintf( psz, "%dd-%2.2dh:%2.2dm:%2.2ds", i_day, i_hour, i_min, i_sec );
  141. }
  142. /*****************************************************************************
  143.  * Some prototypes.
  144.  *****************************************************************************/
  145. static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father );
  146. /*****************************************************************************
  147.  * MP4_ReadBoxCommon : Load only common parameters for all boxes
  148.  *****************************************************************************
  149.  * p_box need to be an already allocated MP4_Box_t, and all data
  150.  *  will only be peek not read
  151.  *
  152.  * RETURN : 0 if it fail, 1 otherwise
  153.  *****************************************************************************/
  154. int MP4_ReadBoxCommon( stream_t *p_stream, MP4_Box_t *p_box )
  155. {
  156.     int      i_read;
  157.     const uint8_t  *p_peek;
  158.     if( ( ( i_read = stream_Peek( p_stream, &p_peek, 32 ) ) < 8 ) )
  159.     {
  160.         return 0;
  161.     }
  162.     p_box->i_pos = stream_Tell( p_stream );
  163.     p_box->data.p_data = NULL;
  164.     p_box->p_father = NULL;
  165.     p_box->p_first  = NULL;
  166.     p_box->p_last  = NULL;
  167.     p_box->p_next   = NULL;
  168.     MP4_GET4BYTES( p_box->i_shortsize );
  169.     MP4_GETFOURCC( p_box->i_type );
  170.     /* Now special case */
  171.     if( p_box->i_shortsize == 1 )
  172.     {
  173.         /* get the true size on 64 bits */
  174.         MP4_GET8BYTES( p_box->i_size );
  175.     }
  176.     else
  177.     {
  178.         p_box->i_size = p_box->i_shortsize;
  179.         /* XXX size of 0 means that the box extends to end of file */
  180.     }
  181.     if( p_box->i_type == FOURCC_uuid )
  182.     {
  183.         /* get extented type on 16 bytes */
  184.         GetUUID( &p_box->i_uuid, p_peek );
  185.         p_peek += 16; i_read -= 16;
  186.     }
  187.     else
  188.     {
  189.         CreateUUID( &p_box->i_uuid, p_box->i_type );
  190.     }
  191. #ifdef MP4_VERBOSE
  192.     if( p_box->i_size )
  193.     {
  194.         if MP4_BOX_TYPE_ASCII()
  195.             msg_Dbg( p_stream, "found Box: %4.4s size %"PRId64,
  196.                     (char*)&p_box->i_type, p_box->i_size );
  197.         else
  198.             msg_Dbg( p_stream, "found Box: c%3.3s size %"PRId64,
  199.                     (char*)&p_box->i_type+1, p_box->i_size );
  200.     }
  201. #endif
  202.     return 1;
  203. }
  204. /*****************************************************************************
  205.  * MP4_NextBox : Go to the next box
  206.  *****************************************************************************
  207.  * if p_box == NULL, go to the next box in which we are( at the begining ).
  208.  *****************************************************************************/
  209. static int MP4_NextBox( stream_t *p_stream, MP4_Box_t *p_box )
  210. {
  211.     MP4_Box_t box;
  212.     if( !p_box )
  213.     {
  214.         MP4_ReadBoxCommon( p_stream, &box );
  215.         p_box = &box;
  216.     }
  217.     if( !p_box->i_size )
  218.     {
  219.         return 2; /* Box with infinite size */
  220.     }
  221.     if( p_box->p_father )
  222.     {
  223.         const off_t i_box_end = p_box->i_size + p_box->i_pos;
  224.         const off_t i_father_end = p_box->p_father->i_size + p_box->p_father->i_pos;
  225.         /* check if it's within p-father */
  226.         if( i_box_end >= i_father_end )
  227.         {
  228.             if( i_box_end > i_father_end )
  229.                 msg_Dbg( p_stream, "out of bound child" );
  230.             return 0; /* out of bound */
  231.         }
  232.     }
  233.     if( stream_Seek( p_stream, p_box->i_size + p_box->i_pos ) )
  234.     {
  235.         return 0;
  236.     }
  237.     return 1;
  238. }
  239. /*****************************************************************************
  240.  * For all known box a loader is given,
  241.  *  XXX: all common struct have to be already read by MP4_ReadBoxCommon
  242.  *       after called one of theses functions, file position is unknown
  243.  *       you need to call MP4_GotoBox to go where you want
  244.  *****************************************************************************/
  245. static int MP4_ReadBoxContainerRaw( stream_t *p_stream, MP4_Box_t *p_container )
  246. {
  247.     MP4_Box_t *p_box;
  248.     if( stream_Tell( p_stream ) + 8 >
  249.         (off_t)(p_container->i_pos + p_container->i_size) )
  250.     {
  251.         /* there is no box to load */
  252.         return 0;
  253.     }
  254.     do
  255.     {
  256.         if( ( p_box = MP4_ReadBox( p_stream, p_container ) ) == NULL ) break;
  257.         /* chain this box with the father and the other at same level */
  258.         if( !p_container->p_first ) p_container->p_first = p_box;
  259.         else p_container->p_last->p_next = p_box;
  260.         p_container->p_last = p_box;
  261.     } while( MP4_NextBox( p_stream, p_box ) == 1 );
  262.     return 1;
  263. }
  264. static int MP4_ReadBoxContainer( stream_t *p_stream, MP4_Box_t *p_container )
  265. {
  266.     if( p_container->i_size <= (size_t)MP4_BOX_HEADERSIZE(p_container ) + 8 )
  267.     {
  268.         /* container is empty, 8 stand for the first header in this box */
  269.         return 1;
  270.     }
  271.     /* enter box */
  272.     stream_Seek( p_stream, p_container->i_pos +
  273.                  MP4_BOX_HEADERSIZE( p_container ) );
  274.     return MP4_ReadBoxContainerRaw( p_stream, p_container );
  275. }
  276. static void MP4_FreeBox_Common( MP4_Box_t *p_box )
  277. {
  278.     /* Up to now do nothing */
  279.     (void)p_box;
  280. }
  281. static int MP4_ReadBoxSkip( stream_t *p_stream, MP4_Box_t *p_box )
  282. {
  283.     /* XXX sometime moov is hiden in a free box */
  284.     if( p_box->p_father &&
  285.         p_box->p_father->i_type == VLC_FOURCC( 'r', 'o', 'o', 't' ) &&
  286.         p_box->i_type == FOURCC_free )
  287.     {
  288.         const uint8_t *p_peek;
  289.         int     i_read;
  290.         vlc_fourcc_t i_fcc;
  291.         i_read  = stream_Peek( p_stream, &p_peek, 44 );
  292.         p_peek += MP4_BOX_HEADERSIZE( p_box ) + 4;
  293.         i_read -= MP4_BOX_HEADERSIZE( p_box ) + 4;
  294.         if( i_read >= 8 )
  295.         {
  296.             i_fcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
  297.             if( i_fcc == FOURCC_cmov || i_fcc == FOURCC_mvhd )
  298.             {
  299.                 msg_Warn( p_stream, "detected moov hidden in a free box ..." );
  300.                 p_box->i_type = FOURCC_foov;
  301.                 return MP4_ReadBoxContainer( p_stream, p_box );
  302.             }
  303.         }
  304.     }
  305.     /* Nothing to do */
  306. #ifdef MP4_VERBOSE
  307.     if MP4_BOX_TYPE_ASCII()
  308.         msg_Dbg( p_stream, "skip box: "%4.4s"", (char*)&p_box->i_type );
  309.     else
  310.         msg_Dbg( p_stream, "skip box: "c%3.3s"", (char*)&p_box->i_type+1 );
  311. #endif
  312.     return 1;
  313. }
  314. static int MP4_ReadBox_ftyp( stream_t *p_stream, MP4_Box_t *p_box )
  315. {
  316.     MP4_READBOX_ENTER( MP4_Box_data_ftyp_t );
  317.     MP4_GETFOURCC( p_box->data.p_ftyp->i_major_brand );
  318.     MP4_GET4BYTES( p_box->data.p_ftyp->i_minor_version );
  319.     if( ( p_box->data.p_ftyp->i_compatible_brands_count = i_read / 4 ) )
  320.     {
  321.         unsigned int i;
  322.         uint32_t *tab = p_box->data.p_ftyp->i_compatible_brands =
  323.             calloc( p_box->data.p_ftyp->i_compatible_brands_count,
  324.                     sizeof(uint32_t));
  325.         if( tab == NULL )
  326.             MP4_READBOX_EXIT( 0 );
  327.         for( i =0; i < p_box->data.p_ftyp->i_compatible_brands_count; i++ )
  328.         {
  329.             MP4_GETFOURCC( tab[i] );
  330.         }
  331.     }
  332.     else
  333.     {
  334.         p_box->data.p_ftyp->i_compatible_brands = NULL;
  335.     }
  336.     MP4_READBOX_EXIT( 1 );
  337. }
  338. static void MP4_FreeBox_ftyp( MP4_Box_t *p_box )
  339. {
  340.     FREENULL( p_box->data.p_ftyp->i_compatible_brands );
  341. }
  342. static int MP4_ReadBox_mvhd(  stream_t *p_stream, MP4_Box_t *p_box )
  343. {
  344.     unsigned int i;
  345. #ifdef MP4_VERBOSE
  346.     char s_creation_time[128];
  347.     char s_modification_time[128];
  348.     char s_duration[128];
  349. #endif
  350.     MP4_READBOX_ENTER( MP4_Box_data_mvhd_t );
  351.     MP4_GETVERSIONFLAGS( p_box->data.p_mvhd );
  352.     if( p_box->data.p_mvhd->i_version )
  353.     {
  354.         MP4_GET8BYTES( p_box->data.p_mvhd->i_creation_time );
  355.         MP4_GET8BYTES( p_box->data.p_mvhd->i_modification_time );
  356.         MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
  357.         MP4_GET8BYTES( p_box->data.p_mvhd->i_duration );
  358.     }
  359.     else
  360.     {
  361.         MP4_GET4BYTES( p_box->data.p_mvhd->i_creation_time );
  362.         MP4_GET4BYTES( p_box->data.p_mvhd->i_modification_time );
  363.         MP4_GET4BYTES( p_box->data.p_mvhd->i_timescale );
  364.         MP4_GET4BYTES( p_box->data.p_mvhd->i_duration );
  365.     }
  366.     MP4_GET4BYTES( p_box->data.p_mvhd->i_rate );
  367.     MP4_GET2BYTES( p_box->data.p_mvhd->i_volume );
  368.     MP4_GET2BYTES( p_box->data.p_mvhd->i_reserved1 );
  369.     for( i = 0; i < 2; i++ )
  370.     {
  371.         MP4_GET4BYTES( p_box->data.p_mvhd->i_reserved2[i] );
  372.     }
  373.     for( i = 0; i < 9; i++ )
  374.     {
  375.         MP4_GET4BYTES( p_box->data.p_mvhd->i_matrix[i] );
  376.     }
  377.     for( i = 0; i < 6; i++ )
  378.     {
  379.         MP4_GET4BYTES( p_box->data.p_mvhd->i_predefined[i] );
  380.     }
  381.     MP4_GET4BYTES( p_box->data.p_mvhd->i_next_track_id );
  382. #ifdef MP4_VERBOSE
  383.     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
  384.     MP4_ConvertDate2Str( s_modification_time,
  385.                          p_box->data.p_mvhd->i_modification_time );
  386.     if( p_box->data.p_mvhd->i_rate )
  387.     {
  388.         MP4_ConvertDate2Str( s_duration,
  389.                  p_box->data.p_mvhd->i_duration / p_box->data.p_mvhd->i_rate );
  390.     }
  391.     else
  392.     {
  393.         s_duration[0] = 0;
  394.     }
  395.     msg_Dbg( p_stream, "read box: "mvhd" creation %s modification %s time scale %d duration %s rate %f volume %f next track id %d",
  396.                   s_creation_time,
  397.                   s_modification_time,
  398.                   (uint32_t)p_box->data.p_mvhd->i_timescale,
  399.                   s_duration,
  400.                   (float)p_box->data.p_mvhd->i_rate / (1<<16 ),
  401.                   (float)p_box->data.p_mvhd->i_volume / 256 ,
  402.                   (uint32_t)p_box->data.p_mvhd->i_next_track_id );
  403. #endif
  404.     MP4_READBOX_EXIT( 1 );
  405. }
  406. static int MP4_ReadBox_tkhd(  stream_t *p_stream, MP4_Box_t *p_box )
  407. {
  408.     unsigned int i;
  409. #ifdef MP4_VERBOSE
  410.     char s_creation_time[128];
  411.     char s_modification_time[128];
  412.     char s_duration[128];
  413. #endif
  414.     MP4_READBOX_ENTER( MP4_Box_data_tkhd_t );
  415.     MP4_GETVERSIONFLAGS( p_box->data.p_tkhd );
  416.     if( p_box->data.p_tkhd->i_version )
  417.     {
  418.         MP4_GET8BYTES( p_box->data.p_tkhd->i_creation_time );
  419.         MP4_GET8BYTES( p_box->data.p_tkhd->i_modification_time );
  420.         MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
  421.         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
  422.         MP4_GET8BYTES( p_box->data.p_tkhd->i_duration );
  423.     }
  424.     else
  425.     {
  426.         MP4_GET4BYTES( p_box->data.p_tkhd->i_creation_time );
  427.         MP4_GET4BYTES( p_box->data.p_tkhd->i_modification_time );
  428.         MP4_GET4BYTES( p_box->data.p_tkhd->i_track_ID );
  429.         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved );
  430.         MP4_GET4BYTES( p_box->data.p_tkhd->i_duration );
  431.     }
  432.     for( i = 0; i < 2; i++ )
  433.     {
  434.         MP4_GET4BYTES( p_box->data.p_tkhd->i_reserved2[i] );
  435.     }
  436.     MP4_GET2BYTES( p_box->data.p_tkhd->i_layer );
  437.     MP4_GET2BYTES( p_box->data.p_tkhd->i_predefined );
  438.     MP4_GET2BYTES( p_box->data.p_tkhd->i_volume );
  439.     MP4_GET2BYTES( p_box->data.p_tkhd->i_reserved3 );
  440.     for( i = 0; i < 9; i++ )
  441.     {
  442.         MP4_GET4BYTES( p_box->data.p_tkhd->i_matrix[i] );
  443.     }
  444.     MP4_GET4BYTES( p_box->data.p_tkhd->i_width );
  445.     MP4_GET4BYTES( p_box->data.p_tkhd->i_height );
  446. #ifdef MP4_VERBOSE
  447.     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mvhd->i_creation_time );
  448.     MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mvhd->i_modification_time );
  449.     MP4_ConvertDate2Str( s_duration, p_box->data.p_mvhd->i_duration );
  450.     msg_Dbg( p_stream, "read box: "tkhd" creation %s modification %s duration %s track ID %d layer %d volume %f width %f height %f",
  451.                   s_creation_time,
  452.                   s_modification_time,
  453.                   s_duration,
  454.                   p_box->data.p_tkhd->i_track_ID,
  455.                   p_box->data.p_tkhd->i_layer,
  456.                   (float)p_box->data.p_tkhd->i_volume / 256 ,
  457.                   (float)p_box->data.p_tkhd->i_width / 65536,
  458.                   (float)p_box->data.p_tkhd->i_height / 65536 );
  459. #endif
  460.     MP4_READBOX_EXIT( 1 );
  461. }
  462. static int MP4_ReadBox_mdhd( stream_t *p_stream, MP4_Box_t *p_box )
  463. {
  464.     unsigned int i;
  465.     uint16_t i_language;
  466. #ifdef MP4_VERBOSE
  467.     char s_creation_time[128];
  468.     char s_modification_time[128];
  469.     char s_duration[128];
  470. #endif
  471.     MP4_READBOX_ENTER( MP4_Box_data_mdhd_t );
  472.     MP4_GETVERSIONFLAGS( p_box->data.p_mdhd );
  473.     if( p_box->data.p_mdhd->i_version )
  474.     {
  475.         MP4_GET8BYTES( p_box->data.p_mdhd->i_creation_time );
  476.         MP4_GET8BYTES( p_box->data.p_mdhd->i_modification_time );
  477.         MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
  478.         MP4_GET8BYTES( p_box->data.p_mdhd->i_duration );
  479.     }
  480.     else
  481.     {
  482.         MP4_GET4BYTES( p_box->data.p_mdhd->i_creation_time );
  483.         MP4_GET4BYTES( p_box->data.p_mdhd->i_modification_time );
  484.         MP4_GET4BYTES( p_box->data.p_mdhd->i_timescale );
  485.         MP4_GET4BYTES( p_box->data.p_mdhd->i_duration );
  486.     }
  487.     p_box->data.p_mdhd->i_language_code = i_language = GetWBE( p_peek );
  488.     for( i = 0; i < 3; i++ )
  489.     {
  490.         p_box->data.p_mdhd->i_language[i] =
  491.                     ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
  492.     }
  493.     MP4_GET2BYTES( p_box->data.p_mdhd->i_predefined );
  494. #ifdef MP4_VERBOSE
  495.     MP4_ConvertDate2Str( s_creation_time, p_box->data.p_mdhd->i_creation_time );
  496.     MP4_ConvertDate2Str( s_modification_time, p_box->data.p_mdhd->i_modification_time );
  497.     MP4_ConvertDate2Str( s_duration, p_box->data.p_mdhd->i_duration );
  498.     msg_Dbg( p_stream, "read box: "mdhd" creation %s modification %s time scale %d duration %s language %c%c%c",
  499.                   s_creation_time,
  500.                   s_modification_time,
  501.                   (uint32_t)p_box->data.p_mdhd->i_timescale,
  502.                   s_duration,
  503.                   p_box->data.p_mdhd->i_language[0],
  504.                   p_box->data.p_mdhd->i_language[1],
  505.                   p_box->data.p_mdhd->i_language[2] );
  506. #endif
  507.     MP4_READBOX_EXIT( 1 );
  508. }
  509. static int MP4_ReadBox_hdlr( stream_t *p_stream, MP4_Box_t *p_box )
  510. {
  511.     int32_t i_reserved;
  512.     MP4_READBOX_ENTER( MP4_Box_data_hdlr_t );
  513.     MP4_GETVERSIONFLAGS( p_box->data.p_hdlr );
  514.     MP4_GETFOURCC( p_box->data.p_hdlr->i_predefined );
  515.     MP4_GETFOURCC( p_box->data.p_hdlr->i_handler_type );
  516.     MP4_GET4BYTES( i_reserved );
  517.     MP4_GET4BYTES( i_reserved );
  518.     MP4_GET4BYTES( i_reserved );
  519.     p_box->data.p_hdlr->psz_name = NULL;
  520.     if( i_read > 0 )
  521.     {
  522.         uint8_t *psz = p_box->data.p_hdlr->psz_name = malloc( i_read + 1 );
  523.         if( psz == NULL )
  524.             MP4_READBOX_EXIT( 0 );
  525.         /* Yes, I love .mp4 :( */
  526.         if( p_box->data.p_hdlr->i_predefined == VLC_FOURCC( 'm', 'h', 'l', 'r' ) )
  527.         {
  528.             uint8_t i_len;
  529.             int i_copy;
  530.             MP4_GET1BYTE( i_len );
  531.             i_copy = __MIN( i_read, i_len );
  532.             memcpy( psz, p_peek, i_copy );
  533.             p_box->data.p_hdlr->psz_name[i_copy] = '';
  534.         }
  535.         else
  536.         {
  537.             memcpy( psz, p_peek, i_read );
  538.             p_box->data.p_hdlr->psz_name[i_read] = '';
  539.         }
  540.     }
  541. #ifdef MP4_VERBOSE
  542.         msg_Dbg( p_stream, "read box: "hdlr" handler type %4.4s name %s",
  543.                    (char*)&p_box->data.p_hdlr->i_handler_type,
  544.                    p_box->data.p_hdlr->psz_name );
  545. #endif
  546.     MP4_READBOX_EXIT( 1 );
  547. }
  548. static void MP4_FreeBox_hdlr( MP4_Box_t *p_box )
  549. {
  550.     FREENULL( p_box->data.p_hdlr->psz_name );
  551. }
  552. static int MP4_ReadBox_vmhd( stream_t *p_stream, MP4_Box_t *p_box )
  553. {
  554.     unsigned int i;
  555.     MP4_READBOX_ENTER( MP4_Box_data_vmhd_t );
  556.     MP4_GETVERSIONFLAGS( p_box->data.p_vmhd );
  557.     MP4_GET2BYTES( p_box->data.p_vmhd->i_graphics_mode );
  558.     for( i = 0; i < 3; i++ )
  559.     {
  560.         MP4_GET2BYTES( p_box->data.p_vmhd->i_opcolor[i] );
  561.     }
  562. #ifdef MP4_VERBOSE
  563.     msg_Dbg( p_stream, "read box: "vmhd" graphics-mode %d opcolor (%d, %d, %d)",
  564.                       p_box->data.p_vmhd->i_graphics_mode,
  565.                       p_box->data.p_vmhd->i_opcolor[0],
  566.                       p_box->data.p_vmhd->i_opcolor[1],
  567.                       p_box->data.p_vmhd->i_opcolor[2] );
  568. #endif
  569.     MP4_READBOX_EXIT( 1 );
  570. }
  571. static int MP4_ReadBox_smhd( stream_t *p_stream, MP4_Box_t *p_box )
  572. {
  573.     MP4_READBOX_ENTER( MP4_Box_data_smhd_t );
  574.     MP4_GETVERSIONFLAGS( p_box->data.p_smhd );
  575.     MP4_GET2BYTES( p_box->data.p_smhd->i_balance );
  576.     MP4_GET2BYTES( p_box->data.p_smhd->i_reserved );
  577. #ifdef MP4_VERBOSE
  578.     msg_Dbg( p_stream, "read box: "smhd" balance %f",
  579.                       (float)p_box->data.p_smhd->i_balance / 256 );
  580. #endif
  581.     MP4_READBOX_EXIT( 1 );
  582. }
  583. static int MP4_ReadBox_hmhd( stream_t *p_stream, MP4_Box_t *p_box )
  584. {
  585.     MP4_READBOX_ENTER( MP4_Box_data_hmhd_t );
  586.     MP4_GETVERSIONFLAGS( p_box->data.p_hmhd );
  587.     MP4_GET2BYTES( p_box->data.p_hmhd->i_max_PDU_size );
  588.     MP4_GET2BYTES( p_box->data.p_hmhd->i_avg_PDU_size );
  589.     MP4_GET4BYTES( p_box->data.p_hmhd->i_max_bitrate );
  590.     MP4_GET4BYTES( p_box->data.p_hmhd->i_avg_bitrate );
  591.     MP4_GET4BYTES( p_box->data.p_hmhd->i_reserved );
  592. #ifdef MP4_VERBOSE
  593.     msg_Dbg( p_stream, "read box: "hmhd" maxPDU-size %d avgPDU-size %d max-bitrate %d avg-bitrate %d",
  594.                       p_box->data.p_hmhd->i_max_PDU_size,
  595.                       p_box->data.p_hmhd->i_avg_PDU_size,
  596.                       p_box->data.p_hmhd->i_max_bitrate,
  597.                       p_box->data.p_hmhd->i_avg_bitrate );
  598. #endif
  599.     MP4_READBOX_EXIT( 1 );
  600. }
  601. static int MP4_ReadBox_url( stream_t *p_stream, MP4_Box_t *p_box )
  602. {
  603.     MP4_READBOX_ENTER( MP4_Box_data_url_t );
  604.     MP4_GETVERSIONFLAGS( p_box->data.p_url );
  605.     MP4_GETSTRINGZ( p_box->data.p_url->psz_location );
  606. #ifdef MP4_VERBOSE
  607.     msg_Dbg( p_stream, "read box: "url" url: %s",
  608.                        p_box->data.p_url->psz_location );
  609. #endif
  610.     MP4_READBOX_EXIT( 1 );
  611. }
  612. static void MP4_FreeBox_url( MP4_Box_t *p_box )
  613. {
  614.     FREENULL( p_box->data.p_url->psz_location );
  615. }
  616. static int MP4_ReadBox_urn( stream_t *p_stream, MP4_Box_t *p_box )
  617. {
  618.     MP4_READBOX_ENTER( MP4_Box_data_urn_t );
  619.     MP4_GETVERSIONFLAGS( p_box->data.p_urn );
  620.     MP4_GETSTRINGZ( p_box->data.p_urn->psz_name );
  621.     MP4_GETSTRINGZ( p_box->data.p_urn->psz_location );
  622. #ifdef MP4_VERBOSE
  623.     msg_Dbg( p_stream, "read box: "urn" name %s location %s",
  624.                       p_box->data.p_urn->psz_name,
  625.                       p_box->data.p_urn->psz_location );
  626. #endif
  627.     MP4_READBOX_EXIT( 1 );
  628. }
  629. static void MP4_FreeBox_urn( MP4_Box_t *p_box )
  630. {
  631.     FREENULL( p_box->data.p_urn->psz_name );
  632.     FREENULL( p_box->data.p_urn->psz_location );
  633. }
  634. static int MP4_ReadBox_dref( stream_t *p_stream, MP4_Box_t *p_box )
  635. {
  636.     MP4_READBOX_ENTER( MP4_Box_data_dref_t );
  637.     MP4_GETVERSIONFLAGS( p_box->data.p_dref );
  638.     MP4_GET4BYTES( p_box->data.p_dref->i_entry_count );
  639.     stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
  640.     MP4_ReadBoxContainerRaw( p_stream, p_box );
  641. #ifdef MP4_VERBOSE
  642.     msg_Dbg( p_stream, "read box: "dref" entry-count %d",
  643.                       p_box->data.p_dref->i_entry_count );
  644. #endif
  645.     MP4_READBOX_EXIT( 1 );
  646. }
  647. static void MP4_FreeBox_stts( MP4_Box_t *p_box )
  648. {
  649.     FREENULL( p_box->data.p_stts->i_sample_count );
  650.     FREENULL( p_box->data.p_stts->i_sample_delta );
  651. }
  652. static int MP4_ReadBox_stts( stream_t *p_stream, MP4_Box_t *p_box )
  653. {
  654.     unsigned int i;
  655.     MP4_READBOX_ENTER( MP4_Box_data_stts_t );
  656.     MP4_GETVERSIONFLAGS( p_box->data.p_stts );
  657.     MP4_GET4BYTES( p_box->data.p_stts->i_entry_count );
  658.     p_box->data.p_stts->i_sample_count =
  659.         calloc( p_box->data.p_stts->i_entry_count, sizeof(uint32_t) );
  660.     p_box->data.p_stts->i_sample_delta =
  661.         calloc( p_box->data.p_stts->i_entry_count, sizeof(uint32_t) );
  662.     if( p_box->data.p_stts->i_sample_count == NULL
  663.      || p_box->data.p_stts->i_sample_delta == NULL )
  664.     {
  665.         MP4_READBOX_EXIT( 0 );
  666.     }
  667.     for( i = 0; (i < p_box->data.p_stts->i_entry_count )&&( i_read >=8 ); i++ )
  668.     {
  669.         MP4_GET4BYTES( p_box->data.p_stts->i_sample_count[i] );
  670.         MP4_GET4BYTES( p_box->data.p_stts->i_sample_delta[i] );
  671.     }
  672. #ifdef MP4_VERBOSE
  673.     msg_Dbg( p_stream, "read box: "stts" entry-count %d",
  674.                       p_box->data.p_stts->i_entry_count );
  675. #endif
  676.     MP4_READBOX_EXIT( 1 );
  677. }
  678. static void MP4_FreeBox_ctts( MP4_Box_t *p_box )
  679. {
  680.     FREENULL( p_box->data.p_ctts->i_sample_count );
  681.     FREENULL( p_box->data.p_ctts->i_sample_offset );
  682. }
  683. static int MP4_ReadBox_ctts( stream_t *p_stream, MP4_Box_t *p_box )
  684. {
  685.     unsigned int i;
  686.     MP4_READBOX_ENTER( MP4_Box_data_ctts_t );
  687.     MP4_GETVERSIONFLAGS( p_box->data.p_ctts );
  688.     MP4_GET4BYTES( p_box->data.p_ctts->i_entry_count );
  689.     p_box->data.p_ctts->i_sample_count =
  690.         calloc( p_box->data.p_ctts->i_entry_count, sizeof(uint32_t) );
  691.     p_box->data.p_ctts->i_sample_offset =
  692.         calloc( p_box->data.p_ctts->i_entry_count, sizeof(uint32_t) );
  693.     if( ( p_box->data.p_ctts->i_sample_count == NULL )
  694.      || ( p_box->data.p_ctts->i_sample_offset == NULL ) )
  695.     {
  696.         MP4_READBOX_EXIT( 0 );
  697.     }
  698.     for( i = 0; (i < p_box->data.p_ctts->i_entry_count )&&( i_read >=8 ); i++ )
  699.     {
  700.         MP4_GET4BYTES( p_box->data.p_ctts->i_sample_count[i] );
  701.         MP4_GET4BYTES( p_box->data.p_ctts->i_sample_offset[i] );
  702.     }
  703. #ifdef MP4_VERBOSE
  704.     msg_Dbg( p_stream, "read box: "ctts" entry-count %d",
  705.                       p_box->data.p_ctts->i_entry_count );
  706. #endif
  707.     MP4_READBOX_EXIT( 1 );
  708. }
  709. static int MP4_ReadLengthDescriptor( uint8_t **pp_peek, int64_t  *i_read )
  710. {
  711.     unsigned int i_b;
  712.     unsigned int i_len = 0;
  713.     do
  714.     {
  715.         i_b = **pp_peek;
  716.         (*pp_peek)++;
  717.         (*i_read)--;
  718.         i_len = ( i_len << 7 ) + ( i_b&0x7f );
  719.     } while( i_b&0x80 );
  720.     return( i_len );
  721. }
  722. static void MP4_FreeBox_esds( MP4_Box_t *p_box )
  723. {
  724.     FREENULL( p_box->data.p_esds->es_descriptor.psz_URL );
  725.     if( p_box->data.p_esds->es_descriptor.p_decConfigDescr )
  726.     {
  727.         FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr->p_decoder_specific_info );
  728.         FREENULL( p_box->data.p_esds->es_descriptor.p_decConfigDescr );
  729.     }
  730. }
  731. static int MP4_ReadBox_esds( stream_t *p_stream, MP4_Box_t *p_box )
  732. {
  733. #define es_descriptor p_box->data.p_esds->es_descriptor
  734.     unsigned int i_len;
  735.     unsigned int i_flags;
  736.     unsigned int i_type;
  737.     MP4_READBOX_ENTER( MP4_Box_data_esds_t );
  738.     MP4_GETVERSIONFLAGS( p_box->data.p_esds );
  739.     MP4_GET1BYTE( i_type );
  740.     if( i_type == 0x03 ) /* MP4ESDescrTag */
  741.     {
  742.         i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
  743. #ifdef MP4_VERBOSE
  744.         msg_Dbg( p_stream, "found esds MPEG4ESDescr (%dBytes)",
  745.                  i_len );
  746. #endif
  747.         MP4_GET2BYTES( es_descriptor.i_ES_ID );
  748.         MP4_GET1BYTE( i_flags );
  749.         es_descriptor.b_stream_dependence = ( (i_flags&0x80) != 0);
  750.         es_descriptor.b_url = ( (i_flags&0x40) != 0);
  751.         es_descriptor.b_OCRstream = ( (i_flags&0x20) != 0);
  752.         es_descriptor.i_stream_priority = i_flags&0x1f;
  753.         if( es_descriptor.b_stream_dependence )
  754.         {
  755.             MP4_GET2BYTES( es_descriptor.i_depend_on_ES_ID );
  756.         }
  757.         if( es_descriptor.b_url )
  758.         {
  759.             unsigned int i_len;
  760.             MP4_GET1BYTE( i_len );
  761.             es_descriptor.psz_URL = malloc( i_len + 1 );
  762.             if( es_descriptor.psz_URL )
  763.             {
  764.                 memcpy( es_descriptor.psz_URL, p_peek, i_len );
  765.                 es_descriptor.psz_URL[i_len] = 0;
  766.             }
  767.             p_peek += i_len;
  768.             i_read -= i_len;
  769.         }
  770.         else
  771.         {
  772.             es_descriptor.psz_URL = NULL;
  773.         }
  774.         if( es_descriptor.b_OCRstream )
  775.         {
  776.             MP4_GET2BYTES( es_descriptor.i_OCR_ES_ID );
  777.         }
  778.         MP4_GET1BYTE( i_type ); /* get next type */
  779.     }
  780.     if( i_type != 0x04)/* MP4DecConfigDescrTag */
  781.     {
  782.          es_descriptor.p_decConfigDescr = NULL;
  783.          MP4_READBOX_EXIT( 1 ); /* rest isn't interesting up to now */
  784.     }
  785.     i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
  786. #ifdef MP4_VERBOSE
  787.         msg_Dbg( p_stream, "found esds MP4DecConfigDescr (%dBytes)",
  788.                  i_len );
  789. #endif
  790.     es_descriptor.p_decConfigDescr =
  791.             calloc( 1, sizeof( MP4_descriptor_decoder_config_t ));
  792.     if( es_descriptor.p_decConfigDescr == NULL )
  793.         MP4_READBOX_EXIT( 0 );
  794.     MP4_GET1BYTE( es_descriptor.p_decConfigDescr->i_objectTypeIndication );
  795.     MP4_GET1BYTE( i_flags );
  796.     es_descriptor.p_decConfigDescr->i_streamType = i_flags >> 2;
  797.     es_descriptor.p_decConfigDescr->b_upStream = ( i_flags >> 1 )&0x01;
  798.     MP4_GET3BYTES( es_descriptor.p_decConfigDescr->i_buffer_sizeDB );
  799.     MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_max_bitrate );
  800.     MP4_GET4BYTES( es_descriptor.p_decConfigDescr->i_avg_bitrate );
  801.     MP4_GET1BYTE( i_type );
  802.     if( i_type !=  0x05 )/* MP4DecSpecificDescrTag */
  803.     {
  804.         es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = 0;
  805.         es_descriptor.p_decConfigDescr->p_decoder_specific_info  = NULL;
  806.         MP4_READBOX_EXIT( 1 );
  807.     }
  808.     i_len = MP4_ReadLengthDescriptor( &p_peek, &i_read );
  809. #ifdef MP4_VERBOSE
  810.         msg_Dbg( p_stream, "found esds MP4DecSpecificDescr (%dBytes)",
  811.                  i_len );
  812. #endif
  813.     if( i_len > i_read )
  814.         MP4_READBOX_EXIT( 0 );
  815.     es_descriptor.p_decConfigDescr->i_decoder_specific_info_len = i_len;
  816.     es_descriptor.p_decConfigDescr->p_decoder_specific_info = malloc( i_len );
  817.     if( es_descriptor.p_decConfigDescr->p_decoder_specific_info == NULL )
  818.         MP4_READBOX_EXIT( 0 );
  819.     memcpy( es_descriptor.p_decConfigDescr->p_decoder_specific_info,
  820.             p_peek, i_len );
  821.     MP4_READBOX_EXIT( 1 );
  822. #undef es_descriptor
  823. }
  824. static void MP4_FreeBox_avcC( MP4_Box_t *p_box )
  825. {
  826.     MP4_Box_data_avcC_t *p_avcC = p_box->data.p_avcC;
  827.     int i;
  828.     if( p_avcC->i_avcC > 0 ) FREENULL( p_avcC->p_avcC );
  829.     if( p_avcC->sps )
  830.     {
  831.         for( i = 0; i < p_avcC->i_sps; i++ )
  832.             FREENULL( p_avcC->sps[i] );
  833.     }
  834.     if( p_avcC->pps )
  835.     {
  836.         for( i = 0; i < p_avcC->i_pps; i++ )
  837.             FREENULL( p_avcC->pps[i] );
  838.     }
  839.     if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->sps );
  840.     if( p_avcC->i_sps > 0 ) FREENULL( p_avcC->i_sps_length );
  841.     if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->pps );
  842.     if( p_avcC->i_pps > 0 ) FREENULL( p_avcC->i_pps_length );
  843. }
  844. static int MP4_ReadBox_avcC( stream_t *p_stream, MP4_Box_t *p_box )
  845. {
  846.     MP4_Box_data_avcC_t *p_avcC;
  847.     int i;
  848.     MP4_READBOX_ENTER( MP4_Box_data_avcC_t );
  849.     p_avcC = p_box->data.p_avcC;
  850.     p_avcC->i_avcC = i_read;
  851.     if( p_avcC->i_avcC > 0 )
  852.     {
  853.         uint8_t * p = p_avcC->p_avcC = malloc( p_avcC->i_avcC );
  854.         if( p )
  855.             memcpy( p, p_peek, i_read );
  856.     }
  857.     MP4_GET1BYTE( p_avcC->i_version );
  858.     MP4_GET1BYTE( p_avcC->i_profile );
  859.     MP4_GET1BYTE( p_avcC->i_profile_compatibility );
  860.     MP4_GET1BYTE( p_avcC->i_level );
  861.     MP4_GET1BYTE( p_avcC->i_reserved1 );
  862.     p_avcC->i_length_size = (p_avcC->i_reserved1&0x03) + 1;
  863.     p_avcC->i_reserved1 >>= 2;
  864.     MP4_GET1BYTE( p_avcC->i_reserved2 );
  865.     p_avcC->i_sps = p_avcC->i_reserved2&0x1f;
  866.     p_avcC->i_reserved2 >>= 5;
  867.     if( p_avcC->i_sps > 0 )
  868.     {
  869.         p_avcC->i_sps_length = calloc( p_avcC->i_sps, sizeof( uint16_t ) );
  870.         p_avcC->sps = calloc( p_avcC->i_sps, sizeof( uint8_t* ) );
  871.         if( !p_avcC->i_sps_length || !p_avcC->sps )
  872.             goto error;
  873.         for( i = 0; i < p_avcC->i_sps; i++ )
  874.         {
  875.             MP4_GET2BYTES( p_avcC->i_sps_length[i] );
  876.             p_avcC->sps[i] = malloc( p_avcC->i_sps_length[i] );
  877.             if( p_avcC->sps[i] )
  878.                 memcpy( p_avcC->sps[i], p_peek, p_avcC->i_sps_length[i] );
  879.             p_peek += p_avcC->i_sps_length[i];
  880.             i_read -= p_avcC->i_sps_length[i];
  881.         }
  882.     }
  883.     MP4_GET1BYTE( p_avcC->i_pps );
  884.     if( p_avcC->i_pps > 0 )
  885.     {
  886.         p_avcC->i_pps_length = calloc( p_avcC->i_pps, sizeof( uint16_t ) );
  887.         p_avcC->pps = calloc( p_avcC->i_pps, sizeof( uint8_t* ) );
  888.         if( !p_avcC->i_pps_length || !p_avcC->pps )
  889.             goto error;
  890.         for( i = 0; i < p_avcC->i_pps; i++ )
  891.         {
  892.             MP4_GET2BYTES( p_avcC->i_pps_length[i] );
  893.             p_avcC->pps[i] = malloc( p_avcC->i_pps_length[i] );
  894.             if( p_avcC->pps[i] )
  895.                 memcpy( p_avcC->pps[i], p_peek, p_avcC->i_pps_length[i] );
  896.             p_peek += p_avcC->i_pps_length[i];
  897.             i_read -= p_avcC->i_pps_length[i];
  898.         }
  899.     }
  900. #ifdef MP4_VERBOSE
  901.     msg_Dbg( p_stream,
  902.              "read box: "avcC" version=%d profile=0x%x level=0x%x length size=%d sps=%d pps=%d",
  903.              p_avcC->i_version, p_avcC->i_profile, p_avcC->i_level,
  904.              p_avcC->i_length_size,
  905.              p_avcC->i_sps, p_avcC->i_pps );
  906.     for( i = 0; i < p_avcC->i_sps; i++ )
  907.     {
  908.         msg_Dbg( p_stream, "         - sps[%d] length=%d",
  909.                  i, p_avcC->i_sps_length[i] );
  910.     }
  911.     for( i = 0; i < p_avcC->i_pps; i++ )
  912.     {
  913.         msg_Dbg( p_stream, "         - pps[%d] length=%d",
  914.                  i, p_avcC->i_pps_length[i] );
  915.     }
  916. #endif
  917.     MP4_READBOX_EXIT( 1 );
  918. error:
  919.     MP4_READBOX_EXIT( 0 );
  920. }
  921. static int MP4_ReadBox_dac3( stream_t *p_stream, MP4_Box_t *p_box )
  922. {
  923.     MP4_Box_data_dac3_t *p_dac3;
  924.     MP4_READBOX_ENTER( MP4_Box_data_dac3_t );
  925.     p_dac3 = p_box->data.p_dac3;
  926.     unsigned i_header;
  927.     MP4_GET3BYTES( i_header );
  928.     p_dac3->i_fscod = ( i_header >> 22 ) & 0x03;
  929.     p_dac3->i_bsid  = ( i_header >> 17 ) & 0x01f;
  930.     p_dac3->i_bsmod = ( i_header >> 14 ) & 0x07;
  931.     p_dac3->i_acmod = ( i_header >> 11 ) & 0x07;
  932.     p_dac3->i_lfeon = ( i_header >> 10 ) & 0x01;
  933.     p_dac3->i_bitrate_code = ( i_header >> 5) & 0x1f;
  934. #ifdef MP4_VERBOSE
  935.     msg_Dbg( p_stream,
  936.              "read box: "dac3" fscod=0x%x bsid=0x%x bsmod=0x%x acmod=0x%x lfeon=0x%x bitrate_code=0x%x",
  937.              p_dac3->i_fscod, p_dac3->i_bsid, p_dac3->i_bsmod, p_dac3->i_acmod, p_dac3->i_lfeon, p_dac3->i_bitrate_code );
  938. #endif
  939.     MP4_READBOX_EXIT( 1 );
  940. }
  941. static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
  942. {
  943.     unsigned int i;
  944.     MP4_READBOX_ENTER( MP4_Box_data_sample_soun_t );
  945.     p_box->data.p_sample_soun->p_qt_description = NULL;
  946.     /* Sanity check needed because the "wave" box does also contain an
  947.      * "mp4a" box that we don't understand. */
  948.     if( i_read < 28 )
  949.     {
  950.         i_read -= 30;
  951.         MP4_READBOX_EXIT( 1 );
  952.     }
  953.     for( i = 0; i < 6 ; i++ )
  954.     {
  955.         MP4_GET1BYTE( p_box->data.p_sample_soun->i_reserved1[i] );
  956.     }
  957.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_data_reference_index );
  958.     /*
  959.      * XXX hack -> produce a copy of the nearly complete chunk
  960.      */
  961.     p_box->data.p_sample_soun->i_qt_description = 0;
  962.     p_box->data.p_sample_soun->p_qt_description = NULL;
  963.     if( i_read > 0 )
  964.     {
  965.         p_box->data.p_sample_soun->p_qt_description = malloc( i_read );
  966.         if( p_box->data.p_sample_soun->p_qt_description )
  967.         {
  968.             p_box->data.p_sample_soun->i_qt_description = i_read;
  969.             memcpy( p_box->data.p_sample_soun->p_qt_description, p_peek, i_read );
  970.         }
  971.     }
  972.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_version );
  973.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_qt_revision_level );
  974.     MP4_GET4BYTES( p_box->data.p_sample_soun->i_qt_vendor );
  975.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_channelcount );
  976.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_samplesize );
  977.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_predefined );
  978.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_reserved3 );
  979.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
  980.     MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
  981.     if( p_box->data.p_sample_soun->i_qt_version == 1 && i_read >= 16 )
  982.     {
  983.         /* SoundDescriptionV1 */
  984.         MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
  985.         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_packet );
  986.         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_frame );
  987.         MP4_GET4BYTES( p_box->data.p_sample_soun->i_bytes_per_sample );
  988. #ifdef MP4_VERBOSE
  989.         msg_Dbg( p_stream,
  990.                  "read box: "soun" qt3+ sample/packet=%d bytes/packet=%d "
  991.                  "bytes/frame=%d bytes/sample=%d",
  992.                  p_box->data.p_sample_soun->i_sample_per_packet,
  993.                  p_box->data.p_sample_soun->i_bytes_per_packet,
  994.                  p_box->data.p_sample_soun->i_bytes_per_frame,
  995.                  p_box->data.p_sample_soun->i_bytes_per_sample );
  996. #endif
  997.         stream_Seek( p_stream, p_box->i_pos +
  998.                         MP4_BOX_HEADERSIZE( p_box ) + 44 );
  999.     }
  1000.     else if( p_box->data.p_sample_soun->i_qt_version == 2 && i_read >= 36 )
  1001.     {
  1002.         /* SoundDescriptionV2 */
  1003.         double f_sample_rate;
  1004.         int64_t dummy;
  1005.         uint32_t i_channel;
  1006.         MP4_GET4BYTES( p_box->data.p_sample_soun->i_sample_per_packet );
  1007.         MP4_GET8BYTES( dummy );
  1008.         memcpy( &f_sample_rate, &dummy, 8 );
  1009.         msg_Dbg( p_stream, "read box: %f Hz", f_sample_rate );
  1010.         p_box->data.p_sample_soun->i_sampleratehi = (int)f_sample_rate % 65536;
  1011.         p_box->data.p_sample_soun->i_sampleratelo = f_sample_rate / 65536;
  1012.         MP4_GET4BYTES( i_channel );
  1013.         p_box->data.p_sample_soun->i_channelcount = i_channel;
  1014. #ifdef MP4_VERBOSE
  1015.         msg_Dbg( p_stream, "read box: "soun" V2" );
  1016. #endif
  1017.         stream_Seek( p_stream, p_box->i_pos +
  1018.                         MP4_BOX_HEADERSIZE( p_box ) + 28 + 36 );
  1019.     }
  1020.     else
  1021.     {
  1022.         p_box->data.p_sample_soun->i_sample_per_packet = 0;
  1023.         p_box->data.p_sample_soun->i_bytes_per_packet = 0;
  1024.         p_box->data.p_sample_soun->i_bytes_per_frame = 0;
  1025.         p_box->data.p_sample_soun->i_bytes_per_sample = 0;
  1026.         msg_Dbg( p_stream, "read box: "soun" mp4 or qt1/2 (rest=%"PRId64")",
  1027.                  i_read );
  1028.         stream_Seek( p_stream, p_box->i_pos +
  1029.                         MP4_BOX_HEADERSIZE( p_box ) + 28 );
  1030.     }
  1031.     if( p_box->i_type == FOURCC_drms )
  1032.     {
  1033.         p_box->data.p_sample_soun->p_drms =
  1034.             drms_alloc( config_GetHomeDir() );
  1035.         if( p_box->data.p_sample_soun->p_drms == NULL )
  1036.         {
  1037.             msg_Err( p_stream, "drms_alloc() failed" );
  1038.         }
  1039.     }
  1040.     if( p_box->i_type == FOURCC_samr || p_box->i_type == FOURCC_sawb )
  1041.     {
  1042.         /* Ignore channelcount for AMR (3gpp AMRSpecificBox) */
  1043.         p_box->data.p_sample_soun->i_channelcount = 1;
  1044.     }
  1045.     MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds/wave/... */
  1046. #ifdef MP4_VERBOSE
  1047.     msg_Dbg( p_stream, "read box: "soun" in stsd channel %d "
  1048.              "sample size %d sample rate %f",
  1049.              p_box->data.p_sample_soun->i_channelcount,
  1050.              p_box->data.p_sample_soun->i_samplesize,
  1051.              (float)p_box->data.p_sample_soun->i_sampleratehi +
  1052.              (float)p_box->data.p_sample_soun->i_sampleratelo / 65536 );
  1053. #endif
  1054.     MP4_READBOX_EXIT( 1 );
  1055. }
  1056. static void MP4_FreeBox_sample_soun( MP4_Box_t *p_box )
  1057. {
  1058.     FREENULL( p_box->data.p_sample_soun->p_qt_description );
  1059.     if( p_box->i_type == FOURCC_drms )
  1060.     {
  1061.         if( p_box->data.p_sample_soun->p_drms )
  1062.         {
  1063.             drms_free( p_box->data.p_sample_soun->p_drms );
  1064.         }
  1065.     }
  1066. }
  1067. int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box )
  1068. {
  1069.     unsigned int i;
  1070.     MP4_READBOX_ENTER( MP4_Box_data_sample_vide_t );
  1071.     for( i = 0; i < 6 ; i++ )
  1072.     {
  1073.         MP4_GET1BYTE( p_box->data.p_sample_vide->i_reserved1[i] );
  1074.     }
  1075.     MP4_GET2BYTES( p_box->data.p_sample_vide->i_data_reference_index );
  1076.     /*
  1077.      * XXX hack -> produce a copy of the nearly complete chunk
  1078.      */
  1079.     if( i_read > 0 )
  1080.     {
  1081.         p_box->data.p_sample_vide->p_qt_image_description = malloc( i_read );
  1082.         if( p_box->data.p_sample_vide->p_qt_image_description == NULL )
  1083.             MP4_READBOX_EXIT( 0 );
  1084.         p_box->data.p_sample_vide->i_qt_image_description = i_read;
  1085.         memcpy( p_box->data.p_sample_vide->p_qt_image_description,
  1086.                 p_peek, i_read );
  1087.     }
  1088.     else
  1089.     {
  1090.         p_box->data.p_sample_vide->i_qt_image_description = 0;
  1091.         p_box->data.p_sample_vide->p_qt_image_description = NULL;
  1092.     }
  1093.     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_version );
  1094.     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_revision_level );
  1095.     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_vendor );
  1096.     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_temporal_quality );
  1097.     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_spatial_quality );
  1098.     MP4_GET2BYTES( p_box->data.p_sample_vide->i_width );
  1099.     MP4_GET2BYTES( p_box->data.p_sample_vide->i_height );
  1100.     MP4_GET4BYTES( p_box->data.p_sample_vide->i_horizresolution );
  1101.     MP4_GET4BYTES( p_box->data.p_sample_vide->i_vertresolution );
  1102.     MP4_GET4BYTES( p_box->data.p_sample_vide->i_qt_data_size );
  1103.     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_frame_count );
  1104.     memcpy( &p_box->data.p_sample_vide->i_compressorname, p_peek, 32 );
  1105.     p_peek += 32; i_read -= 32;
  1106.     MP4_GET2BYTES( p_box->data.p_sample_vide->i_depth );
  1107.     MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_color_table );
  1108.     stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 78);
  1109.     if( p_box->i_type == FOURCC_drmi )
  1110.     {
  1111.         p_box->data.p_sample_vide->p_drms =
  1112.             drms_alloc( config_GetHomeDir() );
  1113.         if( p_box->data.p_sample_vide->p_drms == NULL )
  1114.         {
  1115.             msg_Err( p_stream, "drms_alloc() failed" );
  1116.         }
  1117.     }
  1118.     MP4_ReadBoxContainerRaw( p_stream, p_box );
  1119. #ifdef MP4_VERBOSE
  1120.     msg_Dbg( p_stream, "read box: "vide" in stsd %dx%d depth %d",
  1121.                       p_box->data.p_sample_vide->i_width,
  1122.                       p_box->data.p_sample_vide->i_height,
  1123.                       p_box->data.p_sample_vide->i_depth );
  1124. #endif
  1125.     MP4_READBOX_EXIT( 1 );
  1126. }
  1127. void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
  1128. {
  1129.     FREENULL( p_box->data.p_sample_vide->p_qt_image_description );
  1130.     if( p_box->i_type == FOURCC_drmi )
  1131.     {
  1132.         if( p_box->data.p_sample_vide->p_drms )
  1133.         {
  1134.             drms_free( p_box->data.p_sample_vide->p_drms );
  1135.         }
  1136.     }
  1137. }
  1138. static int MP4_ReadBox_sample_mp4s( stream_t *p_stream, MP4_Box_t *p_box )
  1139. {
  1140.     stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
  1141.     MP4_ReadBoxContainerRaw( p_stream, p_box );
  1142.     return 1;
  1143. }
  1144. static int MP4_ReadBox_sample_text( stream_t *p_stream, MP4_Box_t *p_box )
  1145. {
  1146.     int32_t t;
  1147.     MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
  1148.     MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
  1149.     MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
  1150.     MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
  1151.     MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
  1152.     MP4_GET4BYTES( t );
  1153.     switch( t )
  1154.     {
  1155.         /* FIXME search right signification */
  1156.         case 1: // Center
  1157.             p_box->data.p_sample_text->i_justification_horizontal = 1;
  1158.             p_box->data.p_sample_text->i_justification_vertical = 1;
  1159.             break;
  1160.         case -1:    // Flush Right
  1161.             p_box->data.p_sample_text->i_justification_horizontal = -1;
  1162.             p_box->data.p_sample_text->i_justification_vertical = -1;
  1163.             break;
  1164.         case -2:    // Flush Left
  1165.             p_box->data.p_sample_text->i_justification_horizontal = 0;
  1166.             p_box->data.p_sample_text->i_justification_vertical = 0;
  1167.             break;
  1168.         case 0: // Flush Default
  1169.         default:
  1170.             p_box->data.p_sample_text->i_justification_horizontal = 1;
  1171.             p_box->data.p_sample_text->i_justification_vertical = -1;
  1172.             break;
  1173.     }
  1174.     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[0] );
  1175.     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[1] );
  1176.     MP4_GET2BYTES( p_box->data.p_sample_text->i_background_color[2] );
  1177.     p_box->data.p_sample_text->i_background_color[3] = 0;
  1178.     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
  1179.     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
  1180.     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
  1181.     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
  1182. #ifdef MP4_VERBOSE
  1183.     msg_Dbg( p_stream, "read box: "text" in stsd text" );
  1184. #endif
  1185.     MP4_READBOX_EXIT( 1 );
  1186. }
  1187. static int MP4_ReadBox_sample_tx3g( stream_t *p_stream, MP4_Box_t *p_box )
  1188. {
  1189.     MP4_READBOX_ENTER( MP4_Box_data_sample_text_t );
  1190.     MP4_GET4BYTES( p_box->data.p_sample_text->i_reserved1 );
  1191.     MP4_GET2BYTES( p_box->data.p_sample_text->i_reserved2 );
  1192.     MP4_GET2BYTES( p_box->data.p_sample_text->i_data_reference_index );
  1193.     MP4_GET4BYTES( p_box->data.p_sample_text->i_display_flags );
  1194.     MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_horizontal );
  1195.     MP4_GET1BYTE ( p_box->data.p_sample_text->i_justification_vertical );
  1196.     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[0] );
  1197.     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[1] );
  1198.     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[2] );
  1199.     MP4_GET1BYTE ( p_box->data.p_sample_text->i_background_color[3] );
  1200.     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_top );
  1201.     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_left );
  1202.     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_bottom );
  1203.     MP4_GET2BYTES( p_box->data.p_sample_text->i_text_box_right );
  1204. #ifdef MP4_VERBOSE
  1205.     msg_Dbg( p_stream, "read box: "tx3g" in stsd text" );
  1206. #endif
  1207.     MP4_READBOX_EXIT( 1 );
  1208. }
  1209. #if 0
  1210. /* We can't easily call it, and anyway ~ 20 bytes lost isn't a real problem */
  1211. static void MP4_FreeBox_sample_text( MP4_Box_t *p_box )
  1212. {
  1213.     FREENULL( p_box->data.p_sample_text->psz_text_name );
  1214. }
  1215. #endif
  1216. static int MP4_ReadBox_stsd( stream_t *p_stream, MP4_Box_t *p_box )
  1217. {
  1218.     MP4_READBOX_ENTER( MP4_Box_data_stsd_t );
  1219.     MP4_GETVERSIONFLAGS( p_box->data.p_stsd );
  1220.     MP4_GET4BYTES( p_box->data.p_stsd->i_entry_count );
  1221.     stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 8 );
  1222.     MP4_ReadBoxContainerRaw( p_stream, p_box );
  1223. #ifdef MP4_VERBOSE
  1224.     msg_Dbg( p_stream, "read box: "stsd" entry-count %d",
  1225.                       p_box->data.p_stsd->i_entry_count );
  1226. #endif
  1227.     MP4_READBOX_EXIT( 1 );
  1228. }
  1229. static int MP4_ReadBox_stsz( stream_t *p_stream, MP4_Box_t *p_box )
  1230. {
  1231.     unsigned int i;
  1232.     MP4_READBOX_ENTER( MP4_Box_data_stsz_t );
  1233.     MP4_GETVERSIONFLAGS( p_box->data.p_stsz );
  1234.     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_size );
  1235.     MP4_GET4BYTES( p_box->data.p_stsz->i_sample_count );
  1236.     p_box->data.p_stsz->i_entry_size =
  1237.         calloc( p_box->data.p_stsz->i_sample_count, sizeof(uint32_t) );
  1238.     if( p_box->data.p_stsz->i_entry_size == NULL )
  1239.         MP4_READBOX_EXIT( 0 );
  1240.     if( !p_box->data.p_stsz->i_sample_size )
  1241.     {
  1242.         for( i=0; (i<p_box->data.p_stsz->i_sample_count)&&(i_read >= 4 ); i++ )
  1243.         {
  1244.             MP4_GET4BYTES( p_box->data.p_stsz->i_entry_size[i] );
  1245.         }
  1246.     }
  1247. #ifdef MP4_VERBOSE
  1248.     msg_Dbg( p_stream, "read box: "stsz" sample-size %d sample-count %d",
  1249.                       p_box->data.p_stsz->i_sample_size,
  1250.                       p_box->data.p_stsz->i_sample_count );
  1251. #endif
  1252.     MP4_READBOX_EXIT( 1 );
  1253. }
  1254. static void MP4_FreeBox_stsz( MP4_Box_t *p_box )
  1255. {
  1256.     FREENULL( p_box->data.p_stsz->i_entry_size );
  1257. }
  1258. static void MP4_FreeBox_stsc( MP4_Box_t *p_box )
  1259. {
  1260.     FREENULL( p_box->data.p_stsc->i_first_chunk );
  1261.     FREENULL( p_box->data.p_stsc->i_samples_per_chunk );
  1262.     FREENULL( p_box->data.p_stsc->i_sample_description_index );
  1263. }
  1264. static int MP4_ReadBox_stsc( stream_t *p_stream, MP4_Box_t *p_box )
  1265. {
  1266.     unsigned int i;
  1267.     MP4_READBOX_ENTER( MP4_Box_data_stsc_t );
  1268.     MP4_GETVERSIONFLAGS( p_box->data.p_stsc );
  1269.     MP4_GET4BYTES( p_box->data.p_stsc->i_entry_count );
  1270.     p_box->data.p_stsc->i_first_chunk =
  1271.         calloc( p_box->data.p_stsc->i_entry_count, sizeof(uint32_t) );
  1272.     p_box->data.p_stsc->i_samples_per_chunk =
  1273.         calloc( p_box->data.p_stsc->i_entry_count, sizeof(uint32_t) );
  1274.     p_box->data.p_stsc->i_sample_description_index =
  1275.         calloc( p_box->data.p_stsc->i_entry_count, sizeof(uint32_t) );
  1276.     if( p_box->data.p_stsc->i_first_chunk == NULL
  1277.      || p_box->data.p_stsc->i_samples_per_chunk == NULL
  1278.      || p_box->data.p_stsc->i_sample_description_index == NULL )
  1279.     {
  1280.         MP4_READBOX_EXIT( 0 );
  1281.     }
  1282.     for( i = 0; (i < p_box->data.p_stsc->i_entry_count )&&( i_read >= 12 );i++ )
  1283.     {
  1284.         MP4_GET4BYTES( p_box->data.p_stsc->i_first_chunk[i] );
  1285.         MP4_GET4BYTES( p_box->data.p_stsc->i_samples_per_chunk[i] );
  1286.         MP4_GET4BYTES( p_box->data.p_stsc->i_sample_description_index[i] );
  1287.     }
  1288. #ifdef MP4_VERBOSE
  1289.     msg_Dbg( p_stream, "read box: "stsc" entry-count %d",
  1290.                       p_box->data.p_stsc->i_entry_count );
  1291. #endif
  1292.     MP4_READBOX_EXIT( 1 );
  1293. }
  1294. static int MP4_ReadBox_stco_co64( stream_t *p_stream, MP4_Box_t *p_box )
  1295. {
  1296.     unsigned int i;
  1297.     MP4_READBOX_ENTER( MP4_Box_data_co64_t );
  1298.     MP4_GETVERSIONFLAGS( p_box->data.p_co64 );
  1299.     MP4_GET4BYTES( p_box->data.p_co64->i_entry_count );
  1300.     p_box->data.p_co64->i_chunk_offset =
  1301.         calloc( p_box->data.p_co64->i_entry_count, sizeof(uint64_t) );
  1302.     if( p_box->data.p_co64->i_chunk_offset == NULL )
  1303.         MP4_READBOX_EXIT( 0 );
  1304.     for( i = 0; i < p_box->data.p_co64->i_entry_count; i++ )
  1305.     {
  1306.         if( p_box->i_type == FOURCC_stco )
  1307.         {
  1308.             if( i_read < 4 )
  1309.             {
  1310.                 break;
  1311.             }
  1312.             MP4_GET4BYTES( p_box->data.p_co64->i_chunk_offset[i] );
  1313.         }
  1314.         else
  1315.         {
  1316.             if( i_read < 8 )
  1317.             {
  1318.                 break;
  1319.             }
  1320.             MP4_GET8BYTES( p_box->data.p_co64->i_chunk_offset[i] );
  1321.         }
  1322.     }
  1323. #ifdef MP4_VERBOSE
  1324.     msg_Dbg( p_stream, "read box: "co64" entry-count %d",
  1325.                       p_box->data.p_co64->i_entry_count );
  1326. #endif
  1327.     MP4_READBOX_EXIT( 1 );
  1328. }
  1329. static void MP4_FreeBox_stco_co64( MP4_Box_t *p_box )
  1330. {
  1331.     FREENULL( p_box->data.p_co64->i_chunk_offset );
  1332. }
  1333. static int MP4_ReadBox_stss( stream_t *p_stream, MP4_Box_t *p_box )
  1334. {
  1335.     unsigned int i;
  1336.     MP4_READBOX_ENTER( MP4_Box_data_stss_t );
  1337.     MP4_GETVERSIONFLAGS( p_box->data.p_stss );
  1338.     MP4_GET4BYTES( p_box->data.p_stss->i_entry_count );
  1339.     p_box->data.p_stss->i_sample_number =
  1340.         calloc( p_box->data.p_stss->i_entry_count, sizeof(uint32_t) );
  1341.     if( p_box->data.p_stss->i_sample_number == NULL )
  1342.         MP4_READBOX_EXIT( 0 );
  1343.     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 4 ); i++ )
  1344.     {
  1345.         MP4_GET4BYTES( p_box->data.p_stss->i_sample_number[i] );
  1346.         /* XXX in libmp4 sample begin at 0 */
  1347.         p_box->data.p_stss->i_sample_number[i]--;
  1348.     }
  1349. #ifdef MP4_VERBOSE
  1350.     msg_Dbg( p_stream, "read box: "stss" entry-count %d",
  1351.                       p_box->data.p_stss->i_entry_count );
  1352. #endif
  1353.     MP4_READBOX_EXIT( 1 );
  1354. }
  1355. static void MP4_FreeBox_stss( MP4_Box_t *p_box )
  1356. {
  1357.     FREENULL( p_box->data.p_stss->i_sample_number );
  1358. }
  1359. static void MP4_FreeBox_stsh( MP4_Box_t *p_box )
  1360. {
  1361.     FREENULL( p_box->data.p_stsh->i_shadowed_sample_number );
  1362.     FREENULL( p_box->data.p_stsh->i_sync_sample_number );
  1363. }
  1364. static int MP4_ReadBox_stsh( stream_t *p_stream, MP4_Box_t *p_box )
  1365. {
  1366.     unsigned int i;
  1367.     MP4_READBOX_ENTER( MP4_Box_data_stsh_t );
  1368.     MP4_GETVERSIONFLAGS( p_box->data.p_stsh );
  1369.     MP4_GET4BYTES( p_box->data.p_stsh->i_entry_count );
  1370.     p_box->data.p_stsh->i_shadowed_sample_number =
  1371.         calloc( p_box->data.p_stsh->i_entry_count, sizeof(uint32_t) );
  1372.     p_box->data.p_stsh->i_sync_sample_number =
  1373.         calloc( p_box->data.p_stsh->i_entry_count, sizeof(uint32_t) );
  1374.     if( p_box->data.p_stsh->i_shadowed_sample_number == NULL
  1375.      || p_box->data.p_stsh->i_sync_sample_number == NULL )
  1376.     {
  1377.         MP4_READBOX_EXIT( 0 );
  1378.     }
  1379.     for( i = 0; (i < p_box->data.p_stss->i_entry_count )&&( i_read >= 8 ); i++ )
  1380.     {
  1381.         MP4_GET4BYTES( p_box->data.p_stsh->i_shadowed_sample_number[i] );
  1382.         MP4_GET4BYTES( p_box->data.p_stsh->i_sync_sample_number[i] );
  1383.     }
  1384. #ifdef MP4_VERBOSE
  1385.     msg_Dbg( p_stream, "read box: "stsh" entry-count %d",
  1386.                       p_box->data.p_stsh->i_entry_count );
  1387. #endif
  1388.     MP4_READBOX_EXIT( 1 );
  1389. }
  1390. static int MP4_ReadBox_stdp( stream_t *p_stream, MP4_Box_t *p_box )
  1391. {
  1392.     unsigned int i;
  1393.     MP4_READBOX_ENTER( MP4_Box_data_stdp_t );
  1394.     MP4_GETVERSIONFLAGS( p_box->data.p_stdp );
  1395.     p_box->data.p_stdp->i_priority =
  1396.         calloc( i_read / 2, sizeof(uint16_t) );
  1397.     for( i = 0; i < i_read / 2 ; i++ )
  1398.     {
  1399.         MP4_GET2BYTES( p_box->data.p_stdp->i_priority[i] );
  1400.     }
  1401. #ifdef MP4_VERBOSE
  1402.     msg_Dbg( p_stream, "read box: "stdp" entry-count %"PRId64,
  1403.                       i_read / 2 );
  1404. #endif
  1405.     MP4_READBOX_EXIT( 1 );
  1406. }
  1407. static void MP4_FreeBox_stdp( MP4_Box_t *p_box )
  1408. {
  1409.     FREENULL( p_box->data.p_stdp->i_priority );
  1410. }
  1411. static void MP4_FreeBox_padb( MP4_Box_t *p_box )
  1412. {
  1413.     FREENULL( p_box->data.p_padb->i_reserved1 );
  1414.     FREENULL( p_box->data.p_padb->i_pad2 );
  1415.     FREENULL( p_box->data.p_padb->i_reserved2 );
  1416.     FREENULL( p_box->data.p_padb->i_pad1 );
  1417. }
  1418. static int MP4_ReadBox_padb( stream_t *p_stream, MP4_Box_t *p_box )
  1419. {
  1420.     unsigned int i;
  1421.     uint32_t count;
  1422.     MP4_READBOX_ENTER( MP4_Box_data_padb_t );
  1423.     MP4_GETVERSIONFLAGS( p_box->data.p_padb );
  1424.     MP4_GET4BYTES( p_box->data.p_padb->i_sample_count );
  1425.     count = (p_box->data.p_padb->i_sample_count + 1) / 2;
  1426.     p_box->data.p_padb->i_reserved1 = calloc( count, sizeof(uint16_t) );
  1427.     p_box->data.p_padb->i_pad2 = calloc( count, sizeof(uint16_t) );
  1428.     p_box->data.p_padb->i_reserved2 = calloc( count, sizeof(uint16_t) );
  1429.     p_box->data.p_padb->i_pad1 = calloc( count, sizeof(uint16_t) );
  1430.     if( p_box->data.p_padb->i_reserved1 == NULL
  1431.      || p_box->data.p_padb->i_pad2 == NULL
  1432.      || p_box->data.p_padb->i_reserved2 == NULL
  1433.      || p_box->data.p_padb->i_pad1 == NULL )
  1434.     {
  1435.         MP4_READBOX_EXIT( 0 );
  1436.     }
  1437.     for( i = 0; i < i_read / 2 ; i++ )
  1438.     {
  1439.         if( i >= count )
  1440.         {
  1441.             MP4_READBOX_EXIT( 0 );
  1442.         }
  1443.         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 7 )&0x01;
  1444.         p_box->data.p_padb->i_pad2[i] = ( (*p_peek) >> 4 )&0x07;
  1445.         p_box->data.p_padb->i_reserved1[i] = ( (*p_peek) >> 3 )&0x01;
  1446.         p_box->data.p_padb->i_pad1[i] = ( (*p_peek) )&0x07;
  1447.         p_peek += 1; i_read -= 1;
  1448.     }
  1449. #ifdef MP4_VERBOSE
  1450.     msg_Dbg( p_stream, "read box: "stdp" entry-count %"PRId64,
  1451.                       i_read / 2 );
  1452. #endif
  1453.     MP4_READBOX_EXIT( 1 );
  1454. }
  1455. static void MP4_FreeBox_elst( MP4_Box_t *p_box )
  1456. {
  1457.     FREENULL( p_box->data.p_elst->i_segment_duration );
  1458.     FREENULL( p_box->data.p_elst->i_media_time );
  1459.     FREENULL( p_box->data.p_elst->i_media_rate_integer );
  1460.     FREENULL( p_box->data.p_elst->i_media_rate_fraction );
  1461. }
  1462. static int MP4_ReadBox_elst( stream_t *p_stream, MP4_Box_t *p_box )
  1463. {
  1464.     unsigned int i;
  1465.     MP4_READBOX_ENTER( MP4_Box_data_elst_t );
  1466.     MP4_GETVERSIONFLAGS( p_box->data.p_elst );
  1467.     MP4_GET4BYTES( p_box->data.p_elst->i_entry_count );
  1468.     p_box->data.p_elst->i_segment_duration =
  1469.         calloc( p_box->data.p_elst->i_entry_count, sizeof(uint64_t) );
  1470.     p_box->data.p_elst->i_media_time =
  1471.         calloc( p_box->data.p_elst->i_entry_count, sizeof(uint64_t) );
  1472.     p_box->data.p_elst->i_media_rate_integer =
  1473.         calloc( p_box->data.p_elst->i_entry_count, sizeof(uint16_t) );
  1474.     p_box->data.p_elst->i_media_rate_fraction =
  1475.         calloc( p_box->data.p_elst->i_entry_count, sizeof(uint16_t) );
  1476.     if( p_box->data.p_elst->i_segment_duration == NULL
  1477.      || p_box->data.p_elst->i_media_time == NULL
  1478.      || p_box->data.p_elst->i_media_rate_integer == NULL
  1479.      || p_box->data.p_elst->i_media_rate_fraction == NULL )
  1480.     {
  1481.         MP4_READBOX_EXIT( 0 );
  1482.     }
  1483.     for( i = 0; i < p_box->data.p_elst->i_entry_count; i++ )
  1484.     {
  1485.         if( p_box->data.p_elst->i_version == 1 )
  1486.         {
  1487.             MP4_GET8BYTES( p_box->data.p_elst->i_segment_duration[i] );
  1488.             MP4_GET8BYTES( p_box->data.p_elst->i_media_time[i] );
  1489.         }
  1490.         else
  1491.         {
  1492.             MP4_GET4BYTES( p_box->data.p_elst->i_segment_duration[i] );
  1493.             MP4_GET4BYTES( p_box->data.p_elst->i_media_time[i] );
  1494.             p_box->data.p_elst->i_media_time[i] = (int32_t)p_box->data.p_elst->i_media_time[i];
  1495.         }
  1496.         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_integer[i] );
  1497.         MP4_GET2BYTES( p_box->data.p_elst->i_media_rate_fraction[i] );
  1498.     }
  1499. #ifdef MP4_VERBOSE
  1500.     msg_Dbg( p_stream, "read box: "elst" entry-count %lu",
  1501.              (unsigned long)p_box->data.p_elst->i_entry_count );
  1502. #endif
  1503.     MP4_READBOX_EXIT( 1 );
  1504. }
  1505. static int MP4_ReadBox_cprt( stream_t *p_stream, MP4_Box_t *p_box )
  1506. {
  1507.     unsigned int i_language;
  1508.     unsigned int i;
  1509.     MP4_READBOX_ENTER( MP4_Box_data_cprt_t );
  1510.     MP4_GETVERSIONFLAGS( p_box->data.p_cprt );
  1511.     i_language = GetWBE( p_peek );
  1512.     for( i = 0; i < 3; i++ )
  1513.     {
  1514.         p_box->data.p_cprt->i_language[i] =
  1515.             ( ( i_language >> ( (2-i)*5 ) )&0x1f ) + 0x60;
  1516.     }
  1517.     p_peek += 2; i_read -= 2;
  1518.     MP4_GETSTRINGZ( p_box->data.p_cprt->psz_notice );
  1519. #ifdef MP4_VERBOSE
  1520.     msg_Dbg( p_stream, "read box: "cprt" language %c%c%c notice %s",
  1521.                       p_box->data.p_cprt->i_language[0],
  1522.                       p_box->data.p_cprt->i_language[1],
  1523.                       p_box->data.p_cprt->i_language[2],
  1524.                       p_box->data.p_cprt->psz_notice );
  1525. #endif
  1526.     MP4_READBOX_EXIT( 1 );
  1527. }
  1528. static void MP4_FreeBox_cprt( MP4_Box_t *p_box )
  1529. {
  1530.     FREENULL( p_box->data.p_cprt->psz_notice );
  1531. }
  1532. static int MP4_ReadBox_dcom( stream_t *p_stream, MP4_Box_t *p_box )
  1533. {
  1534.     MP4_READBOX_ENTER( MP4_Box_data_dcom_t );
  1535.     MP4_GETFOURCC( p_box->data.p_dcom->i_algorithm );
  1536. #ifdef MP4_VERBOSE
  1537.     msg_Dbg( p_stream,
  1538.              "read box: "dcom" compression algorithm : %4.4s",
  1539.                       (char*)&p_box->data.p_dcom->i_algorithm );
  1540. #endif
  1541.     MP4_READBOX_EXIT( 1 );
  1542. }
  1543. static int MP4_ReadBox_cmvd( stream_t *p_stream, MP4_Box_t *p_box )
  1544. {
  1545.     MP4_READBOX_ENTER( MP4_Box_data_cmvd_t );
  1546.     MP4_GET4BYTES( p_box->data.p_cmvd->i_uncompressed_size );
  1547.     p_box->data.p_cmvd->i_compressed_size = i_read;
  1548.     if( !( p_box->data.p_cmvd->p_data = malloc( i_read ) ) )
  1549.         return( 1 );
  1550.     /* now copy compressed data */
  1551.     memcpy( p_box->data.p_cmvd->p_data,
  1552.             p_peek,
  1553.             i_read);
  1554.     p_box->data.p_cmvd->b_compressed = 1;
  1555. #ifdef MP4_VERBOSE
  1556.     msg_Dbg( p_stream, "read box: "cmvd" compressed data size %d",
  1557.                       p_box->data.p_cmvd->i_compressed_size );
  1558. #endif
  1559.     MP4_READBOX_EXIT( 1 );
  1560. }
  1561. static void MP4_FreeBox_cmvd( MP4_Box_t *p_box )
  1562. {
  1563.     FREENULL( p_box->data.p_cmvd->p_data );
  1564. }
  1565. static int MP4_ReadBox_cmov( stream_t *p_stream, MP4_Box_t *p_box )
  1566. {
  1567.     MP4_Box_t *p_dcom;
  1568.     MP4_Box_t *p_cmvd;
  1569. #ifdef HAVE_ZLIB_H
  1570.     stream_t *p_stream_memory;
  1571.     z_stream z_data;
  1572.     uint8_t *p_data;
  1573.     int i_result;
  1574. #endif
  1575.     if( !( p_box->data.p_cmov = malloc( sizeof( MP4_Box_data_cmov_t ) ) ) )
  1576.         return 0;
  1577.     memset( p_box->data.p_cmov, 0, sizeof( MP4_Box_data_cmov_t ) );
  1578.     if( !p_box->p_father ||
  1579.         ( p_box->p_father->i_type != FOURCC_moov &&
  1580.           p_box->p_father->i_type != FOURCC_foov ) )
  1581.     {
  1582.         msg_Warn( p_stream, "Read box: "cmov" box alone" );
  1583.         return 1;
  1584.     }
  1585.     if( !MP4_ReadBoxContainer( p_stream, p_box ) )
  1586.     {
  1587.         return 0;
  1588.     }
  1589.     if( ( p_dcom = MP4_BoxGet( p_box, "dcom" ) ) == NULL ||
  1590.         ( p_cmvd = MP4_BoxGet( p_box, "cmvd" ) ) == NULL ||
  1591.         p_cmvd->data.p_cmvd->p_data == NULL )
  1592.     {
  1593.         msg_Warn( p_stream, "read box: "cmov" incomplete" );
  1594.         return 0;
  1595.     }
  1596.     if( p_dcom->data.p_dcom->i_algorithm != FOURCC_zlib )
  1597.     {
  1598.         msg_Dbg( p_stream, "read box: "cmov" compression algorithm : %4.4s "
  1599.                  "not supported", (char*)&p_dcom->data.p_dcom->i_algorithm );
  1600.         return 0;
  1601.     }
  1602. #ifndef HAVE_ZLIB_H
  1603.     msg_Dbg( p_stream, "read box: "cmov" zlib unsupported" );
  1604.     return 0;
  1605. #else
  1606.     /* decompress data */
  1607.     /* allocate a new buffer */
  1608.     if( !( p_data = malloc( p_cmvd->data.p_cmvd->i_uncompressed_size ) ) )
  1609.         return 0;
  1610.     /* init default structures */
  1611.     z_data.next_in   = p_cmvd->data.p_cmvd->p_data;
  1612.     z_data.avail_in  = p_cmvd->data.p_cmvd->i_compressed_size;
  1613.     z_data.next_out  = p_data;
  1614.     z_data.avail_out = p_cmvd->data.p_cmvd->i_uncompressed_size;
  1615.     z_data.zalloc    = (alloc_func)Z_NULL;
  1616.     z_data.zfree     = (free_func)Z_NULL;
  1617.     z_data.opaque    = (voidpf)Z_NULL;
  1618.     /* init zlib */
  1619.     if( inflateInit( &z_data ) != Z_OK )
  1620.     {
  1621.         msg_Err( p_stream, "read box: "cmov" error while uncompressing" );
  1622.         free( p_data );
  1623.         return 0;
  1624.     }
  1625.     /* uncompress */
  1626.     i_result = inflate( &z_data, Z_NO_FLUSH );
  1627.     if( i_result != Z_OK && i_result != Z_STREAM_END )
  1628.     {
  1629.         msg_Err( p_stream, "read box: "cmov" error while uncompressing" );
  1630.         free( p_data );
  1631.         return 0;
  1632.     }
  1633.     if( p_cmvd->data.p_cmvd->i_uncompressed_size != z_data.total_out )
  1634.     {
  1635.         msg_Warn( p_stream, "read box: "cmov" uncompressing data size "
  1636.                   "mismatch" );
  1637.     }
  1638.     p_cmvd->data.p_cmvd->i_uncompressed_size = z_data.total_out;
  1639.     /* close zlib */
  1640.     if( inflateEnd( &z_data ) != Z_OK )
  1641.     {
  1642.         msg_Warn( p_stream, "read box: "cmov" error while uncompressing "
  1643.                   "data (ignored)" );
  1644.     }
  1645.     free( p_cmvd->data.p_cmvd->p_data );
  1646.     p_cmvd->data.p_cmvd->p_data = p_data;
  1647.     p_cmvd->data.p_cmvd->b_compressed = 0;
  1648.     msg_Dbg( p_stream, "read box: "cmov" box succesfully uncompressed" );
  1649.     /* now create a memory stream */
  1650.     p_stream_memory =
  1651.         stream_MemoryNew( VLC_OBJECT(p_stream), p_cmvd->data.p_cmvd->p_data,
  1652.                           p_cmvd->data.p_cmvd->i_uncompressed_size, true );
  1653.     /* and read uncompressd moov */
  1654.     p_box->data.p_cmov->p_moov = MP4_ReadBox( p_stream_memory, NULL );
  1655.     stream_Delete( p_stream_memory );
  1656. #ifdef MP4_VERBOSE
  1657.     msg_Dbg( p_stream, "read box: "cmov" compressed movie header completed");
  1658. #endif
  1659.     return p_box->data.p_cmov->p_moov ? 1 : 0;
  1660. #endif /* HAVE_ZLIB_H */
  1661. }
  1662. static int MP4_ReadBox_rdrf( stream_t *p_stream, MP4_Box_t *p_box )
  1663. {
  1664.     uint32_t i_len;
  1665.     MP4_READBOX_ENTER( MP4_Box_data_rdrf_t );
  1666.     MP4_GETVERSIONFLAGS( p_box->data.p_rdrf );
  1667.     MP4_GETFOURCC( p_box->data.p_rdrf->i_ref_type );
  1668.     MP4_GET4BYTES( i_len );
  1669.     i_len++;
  1670.     if( i_len > 0 )
  1671.     {
  1672.         uint32_t i;
  1673.         p_box->data.p_rdrf->psz_ref = malloc( i_len );
  1674.         if( p_box->data.p_rdrf->psz_ref == NULL )
  1675.             MP4_READBOX_EXIT( 0 );
  1676.         i_len--;
  1677.         for( i = 0; i < i_len; i++ )
  1678.         {
  1679.             MP4_GET1BYTE( p_box->data.p_rdrf->psz_ref[i] );
  1680.         }
  1681.         p_box->data.p_rdrf->psz_ref[i_len] = '';
  1682.     }
  1683.     else
  1684.     {
  1685.         p_box->data.p_rdrf->psz_ref = NULL;
  1686.     }
  1687. #ifdef MP4_VERBOSE
  1688.     msg_Dbg( p_stream,
  1689.             "read box: "rdrf" type:%4.4s ref %s",
  1690.             (char*)&p_box->data.p_rdrf->i_ref_type,
  1691.             p_box->data.p_rdrf->psz_ref );
  1692. #endif
  1693.     MP4_READBOX_EXIT( 1 );
  1694. }
  1695. static void MP4_FreeBox_rdrf( MP4_Box_t *p_box )
  1696. {
  1697.     FREENULL( p_box->data.p_rdrf->psz_ref );
  1698. }
  1699. static int MP4_ReadBox_rmdr( stream_t *p_stream, MP4_Box_t *p_box )
  1700. {
  1701.     MP4_READBOX_ENTER( MP4_Box_data_rmdr_t );
  1702.     MP4_GETVERSIONFLAGS( p_box->data.p_rmdr );
  1703.     MP4_GET4BYTES( p_box->data.p_rmdr->i_rate );
  1704. #ifdef MP4_VERBOSE
  1705.     msg_Dbg( p_stream,
  1706.              "read box: "rmdr" rate:%d",
  1707.              p_box->data.p_rmdr->i_rate );
  1708. #endif
  1709.     MP4_READBOX_EXIT( 1 );
  1710. }
  1711. static int MP4_ReadBox_rmqu( stream_t *p_stream, MP4_Box_t *p_box )
  1712. {
  1713.     MP4_READBOX_ENTER( MP4_Box_data_rmqu_t );
  1714.     MP4_GET4BYTES( p_box->data.p_rmqu->i_quality );
  1715. #ifdef MP4_VERBOSE
  1716.     msg_Dbg( p_stream,
  1717.              "read box: "rmqu" quality:%d",
  1718.              p_box->data.p_rmqu->i_quality );
  1719. #endif
  1720.     MP4_READBOX_EXIT( 1 );
  1721. }
  1722. static int MP4_ReadBox_rmvc( stream_t *p_stream, MP4_Box_t *p_box )
  1723. {
  1724.     MP4_READBOX_ENTER( MP4_Box_data_rmvc_t );
  1725.     MP4_GETVERSIONFLAGS( p_box->data.p_rmvc );
  1726.     MP4_GETFOURCC( p_box->data.p_rmvc->i_gestaltType );
  1727.     MP4_GET4BYTES( p_box->data.p_rmvc->i_val1 );
  1728.     MP4_GET4BYTES( p_box->data.p_rmvc->i_val2 );
  1729.     MP4_GET2BYTES( p_box->data.p_rmvc->i_checkType );
  1730. #ifdef MP4_VERBOSE
  1731.     msg_Dbg( p_stream,
  1732.              "read box: "rmvc" gestaltType:%4.4s val1:0x%x val2:0x%x checkType:0x%x",
  1733.              (char*)&p_box->data.p_rmvc->i_gestaltType,
  1734.              p_box->data.p_rmvc->i_val1,p_box->data.p_rmvc->i_val2,
  1735.              p_box->data.p_rmvc->i_checkType );
  1736. #endif
  1737.     MP4_READBOX_EXIT( 1 );
  1738. }
  1739. static int MP4_ReadBox_frma( stream_t *p_stream, MP4_Box_t *p_box )
  1740. {
  1741.     MP4_READBOX_ENTER( MP4_Box_data_frma_t );
  1742.     MP4_GETFOURCC( p_box->data.p_frma->i_type );
  1743. #ifdef MP4_VERBOSE
  1744.     msg_Dbg( p_stream, "read box: "frma" i_type:%4.4s",
  1745.              (char *)&p_box->data.p_frma->i_type );
  1746. #endif
  1747.     MP4_READBOX_EXIT( 1 );
  1748. }
  1749. static int MP4_ReadBox_skcr( stream_t *p_stream, MP4_Box_t *p_box )
  1750. {
  1751.     MP4_READBOX_ENTER( MP4_Box_data_frma_t );
  1752.     MP4_GET4BYTES( p_box->data.p_skcr->i_init );
  1753.     MP4_GET4BYTES( p_box->data.p_skcr->i_encr );
  1754.     MP4_GET4BYTES( p_box->data.p_skcr->i_decr );
  1755. #ifdef MP4_VERBOSE
  1756.     msg_Dbg( p_stream, "read box: "skcr" i_init:%d i_encr:%d i_decr:%d",
  1757.              p_box->data.p_skcr->i_init,
  1758.              p_box->data.p_skcr->i_encr,
  1759.              p_box->data.p_skcr->i_decr );
  1760. #endif
  1761.     MP4_READBOX_EXIT( 1 );
  1762. }
  1763. static int MP4_ReadBox_drms( stream_t *p_stream, MP4_Box_t *p_box )
  1764. {
  1765.     MP4_Box_t *p_drms_box = p_box;
  1766.     void *p_drms = NULL;
  1767.     MP4_READBOX_ENTER( uint8_t );
  1768.     do
  1769.     {
  1770.         p_drms_box = p_drms_box->p_father;
  1771.     } while( p_drms_box && p_drms_box->i_type != FOURCC_drms
  1772.                         && p_drms_box->i_type != FOURCC_drmi );
  1773.     if( p_drms_box && p_drms_box->i_type == FOURCC_drms )
  1774.         p_drms = p_drms_box->data.p_sample_soun->p_drms;
  1775.     else if( p_drms_box && p_drms_box->i_type == FOURCC_drmi )
  1776.         p_drms = p_drms_box->data.p_sample_vide->p_drms;
  1777.     if( p_drms_box && p_drms )
  1778.     {
  1779.         int i_ret = drms_init( p_drms, p_box->i_type, p_peek, i_read );
  1780.         if( i_ret )
  1781.         {
  1782.             const char *psz_error;
  1783.             switch( i_ret )
  1784.             {
  1785.                 case -1: psz_error = "unimplemented"; break;
  1786.                 case -2: psz_error = "invalid argument"; break;
  1787.                 case -3: psz_error = "could not get system key"; break;
  1788.                 case -4: psz_error = "could not get SCI data"; break;
  1789.                 case -5: psz_error = "no user key found in SCI data"; break;
  1790.                 case -6: psz_error = "invalid user key"; break;
  1791.                 default: psz_error = "unknown error"; break;
  1792.             }
  1793.             if MP4_BOX_TYPE_ASCII()
  1794.                 msg_Err( p_stream, "drms_init(%4.4s) failed (%s)",
  1795.                         (char *)&p_box->i_type, psz_error );
  1796.             else
  1797.                 msg_Err( p_stream, "drms_init(c%3.3s) failed (%s)",
  1798.                         (char *)&p_box->i_type+1, psz_error );
  1799.             drms_free( p_drms );
  1800.             if( p_drms_box->i_type == FOURCC_drms )
  1801.                 p_drms_box->data.p_sample_soun->p_drms = NULL;
  1802.             else if( p_drms_box->i_type == FOURCC_drmi )
  1803.                 p_drms_box->data.p_sample_vide->p_drms = NULL;
  1804.         }
  1805.     }
  1806.     MP4_READBOX_EXIT( 1 );
  1807. }
  1808. static int MP4_ReadBox_0xa9xxx( stream_t *p_stream, MP4_Box_t *p_box )
  1809. {
  1810.     uint16_t i16;
  1811.     MP4_READBOX_ENTER( MP4_Box_data_0xa9xxx_t );
  1812.     p_box->data.p_0xa9xxx->psz_text = NULL;
  1813.     MP4_GET2BYTES( i16 );
  1814.     if( i16 > 0 )
  1815.     {
  1816.         int i_length = i16;
  1817.         MP4_GET2BYTES( i16 );
  1818.         if( i_length >= i_read ) i_length = i_read + 1;
  1819.         p_box->data.p_0xa9xxx->psz_text = malloc( i_length );
  1820.         if( p_box->data.p_0xa9xxx->psz_text == NULL )
  1821.             MP4_READBOX_EXIT( 0 );
  1822.         i_length--;
  1823.         memcpy( p_box->data.p_0xa9xxx->psz_text,
  1824.                 p_peek, i_length );
  1825.         p_box->data.p_0xa9xxx->psz_text[i_length] = '';
  1826. #ifdef MP4_VERBOSE
  1827.         msg_Dbg( p_stream,
  1828.                  "read box: "c%3.3s" text=`%s'",
  1829.                  ((char*)&p_box->i_type + 1),
  1830.                  p_box->data.p_0xa9xxx->psz_text );
  1831. #endif
  1832.     }
  1833.     else
  1834.     {
  1835.         /* try iTune/Quicktime format, rewind to start */
  1836.         p_peek -= 2; i_read += 2;
  1837.         // we are expecting a 'data' box
  1838.         uint32_t i_data_len;
  1839.         uint32_t i_data_tag;
  1840.         MP4_GET4BYTES( i_data_len );
  1841.         if( i_data_len > i_read ) i_data_len = i_read;
  1842.         MP4_GETFOURCC( i_data_tag );
  1843.         if( (i_data_len > 0) && (i_data_tag == VLC_FOURCC('d', 'a', 't', 'a')) )
  1844.         {
  1845.             /* data box contains a version/flags field */
  1846.             uint32_t i_version;
  1847.             uint32_t i_reserved;
  1848.             MP4_GET4BYTES( i_version );
  1849.             MP4_GET4BYTES( i_reserved );
  1850.             // version should be 0, flags should be 1 for text, 0 for data
  1851.             if( ( i_version == 0x00000001 ) && (i_data_len >= 12 ) )
  1852.             {
  1853.                 // the rest is the text
  1854.                 i_data_len -= 12;
  1855.                 p_box->data.p_0xa9xxx->psz_text = malloc( i_data_len + 1 );
  1856.                 if( p_box->data.p_0xa9xxx->psz_text == NULL )
  1857.                     MP4_READBOX_EXIT( 0 );
  1858.                 memcpy( p_box->data.p_0xa9xxx->psz_text,
  1859.                         p_peek, i_data_len );
  1860.                 p_box->data.p_0xa9xxx->psz_text[i_data_len] = '';
  1861. #ifdef MP4_VERBOSE
  1862.         msg_Dbg( p_stream,
  1863.                  "read box: "c%3.3s" text=`%s'",
  1864.                  ((char*)&p_box->i_type+1),
  1865.                  p_box->data.p_0xa9xxx->psz_text );
  1866. #endif
  1867.             }
  1868.             else
  1869.             {
  1870.                 // TODO: handle data values for ID3 tag values, track num or cover art,etc...
  1871.             }
  1872.         }
  1873.     }
  1874.     MP4_READBOX_EXIT( 1 );
  1875. }
  1876. static void MP4_FreeBox_0xa9xxx( MP4_Box_t *p_box )
  1877. {
  1878.     FREENULL( p_box->data.p_0xa9xxx->psz_text );
  1879. }
  1880. /* Chapter support */
  1881. static void MP4_FreeBox_chpl( MP4_Box_t *p_box )
  1882. {
  1883.     MP4_Box_data_chpl_t *p_chpl = p_box->data.p_chpl;
  1884.     int i;
  1885.     for( i = 0; i < p_chpl->i_chapter; i++ )
  1886.         free( p_chpl->chapter[i].psz_name );
  1887. }
  1888. static int MP4_ReadBox_chpl( stream_t *p_stream, MP4_Box_t *p_box )
  1889. {
  1890.     MP4_Box_data_chpl_t *p_chpl;
  1891.     uint32_t i_dummy;
  1892.     int i;
  1893.     MP4_READBOX_ENTER( MP4_Box_data_chpl_t );
  1894.     p_chpl = p_box->data.p_chpl;
  1895.     MP4_GETVERSIONFLAGS( p_chpl );
  1896.     MP4_GET4BYTES( i_dummy );
  1897.     MP4_GET1BYTE( p_chpl->i_chapter );
  1898.     for( i = 0; i < p_chpl->i_chapter; i++ )
  1899.     {
  1900.         uint64_t i_start;
  1901.         uint8_t i_len;
  1902.         int i_copy;
  1903.         MP4_GET8BYTES( i_start );
  1904.         MP4_GET1BYTE( i_len );
  1905.         p_chpl->chapter[i].psz_name = malloc( i_len + 1 );
  1906.         if( !p_chpl->chapter[i].psz_name )
  1907.             goto error;
  1908.         i_copy = __MIN( i_len, i_read );
  1909.         if( i_copy > 0 )
  1910.             memcpy( p_chpl->chapter[i].psz_name, p_peek, i_copy );
  1911.         p_chpl->chapter[i].psz_name[i_copy] = '';
  1912.         p_chpl->chapter[i].i_start = i_start;
  1913.         p_peek += i_copy;
  1914.         i_read -= i_copy;
  1915.     }
  1916.     /* Bubble sort by increasing start date */
  1917.     do
  1918.     {
  1919.         for( i = 0; i < p_chpl->i_chapter - 1; i++ )
  1920.         {
  1921.             if( p_chpl->chapter[i].i_start > p_chpl->chapter[i+1].i_start )
  1922.             {
  1923.                 char *psz = p_chpl->chapter[i+1].psz_name;
  1924.                 int64_t i64 = p_chpl->chapter[i+1].i_start;
  1925.                 p_chpl->chapter[i+1].psz_name = p_chpl->chapter[i].psz_name;
  1926.                 p_chpl->chapter[i+1].i_start = p_chpl->chapter[i].i_start;
  1927.                 p_chpl->chapter[i].psz_name = psz;
  1928.                 p_chpl->chapter[i].i_start = i64;
  1929.                 i = -1;
  1930.                 break;
  1931.             }
  1932.         }
  1933.     } while( i == -1 );
  1934. #ifdef MP4_VERBOSE
  1935.     msg_Dbg( p_stream, "read box: "chpl" %d chapters",
  1936.                        p_chpl->i_chapter );
  1937. #endif
  1938.     MP4_READBOX_EXIT( 1 );
  1939. error:
  1940.     MP4_READBOX_EXIT( 0 );
  1941. }
  1942. static int MP4_ReadBox_tref_generic( stream_t *p_stream, MP4_Box_t *p_box )
  1943. {
  1944.     unsigned int i;
  1945.     MP4_READBOX_ENTER( MP4_Box_data_tref_generic_t );
  1946.     p_box->data.p_tref_generic->i_track_ID = NULL;
  1947.     p_box->data.p_tref_generic->i_entry_count = i_read / sizeof(uint32_t);
  1948.     if( p_box->data.p_tref_generic->i_entry_count > 0 )
  1949.         p_box->data.p_tref_generic->i_track_ID = calloc( p_box->data.p_tref_generic->i_entry_count, sizeof(uint32_t) );
  1950.     if( p_box->data.p_tref_generic->i_track_ID == NULL )
  1951.         MP4_READBOX_EXIT( 0 );
  1952.     for( i = 0; i < p_box->data.p_tref_generic->i_entry_count; i++ )
  1953.     {
  1954.         MP4_GET4BYTES( p_box->data.p_tref_generic->i_track_ID[i] );
  1955.     }
  1956. #ifdef MP4_VERBOSE
  1957.         msg_Dbg( p_stream, "read box: "chap" %d references",
  1958.                  p_box->data.p_tref_generic->i_entry_count );
  1959. #endif
  1960.     MP4_READBOX_EXIT( 1 );
  1961. }
  1962. static void MP4_FreeBox_tref_generic( MP4_Box_t *p_box )
  1963. {
  1964.     FREENULL( p_box->data.p_tref_generic->i_track_ID );
  1965. }
  1966. static int MP4_ReadBox_meta( stream_t *p_stream, MP4_Box_t *p_box )
  1967. {
  1968.     uint8_t meta_data[8];
  1969.     int i_actually_read;
  1970.     // skip over box header
  1971.     i_actually_read = stream_Read( p_stream, meta_data, 8 );
  1972.     if( i_actually_read < 8 )
  1973.         return 0;
  1974.     /* meta content starts with a 4 byte version/flags value (should be 0) */
  1975.     i_actually_read = stream_Read( p_stream, meta_data, 4 );
  1976.     if( i_actually_read < 4 )
  1977.         return 0;
  1978.     /* then it behaves like a container */
  1979.     return MP4_ReadBoxContainerRaw( p_stream, p_box );
  1980. }
  1981. /* For generic */
  1982. static int MP4_ReadBox_default( stream_t *p_stream, MP4_Box_t *p_box )
  1983. {
  1984.     if( !p_box->p_father )
  1985.     {
  1986.         goto unknown;
  1987.     }
  1988.     if( p_box->p_father->i_type == FOURCC_stsd )
  1989.     {
  1990.         MP4_Box_t *p_mdia = MP4_BoxGet( p_box, "../../../.." );
  1991.         MP4_Box_t *p_hdlr;
  1992.         if( p_mdia == NULL || p_mdia->i_type != FOURCC_mdia ||
  1993.             (p_hdlr = MP4_BoxGet( p_mdia, "hdlr" )) == NULL )
  1994.         {
  1995.             goto unknown;
  1996.         }
  1997.         switch( p_hdlr->data.p_hdlr->i_handler_type )
  1998.         {
  1999.             case FOURCC_soun:
  2000.                 return MP4_ReadBox_sample_soun( p_stream, p_box );
  2001.             case FOURCC_vide:
  2002.                 return MP4_ReadBox_sample_vide( p_stream, p_box );
  2003.             case FOURCC_text:
  2004.                 return MP4_ReadBox_sample_text( p_stream, p_box );
  2005.             case FOURCC_tx3g:
  2006.             case FOURCC_sbtl:
  2007.                 return MP4_ReadBox_sample_tx3g( p_stream, p_box );
  2008.             default:
  2009.                 msg_Warn( p_stream,
  2010.                           "unknown handler type in stsd (incompletely loaded)" );
  2011.                 return 1;
  2012.         }
  2013.     }
  2014. unknown:
  2015.     if MP4_BOX_TYPE_ASCII()
  2016.         msg_Warn( p_stream,
  2017.                 "unknown box type %4.4s (incompletely loaded)",
  2018.                 (char*)&p_box->i_type );
  2019.     else
  2020.         msg_Warn( p_stream,
  2021.                 "unknown box type c%3.3s (incompletely loaded)",
  2022.                 (char*)&p_box->i_type+1 );
  2023.     return 1;
  2024. }
  2025. /**** ------------------------------------------------------------------- ****/
  2026. /****                   "Higher level" Functions                          ****/
  2027. /**** ------------------------------------------------------------------- ****/
  2028. static const struct
  2029. {
  2030.     uint32_t i_type;
  2031.     int  (*MP4_ReadBox_function )( stream_t *p_stream, MP4_Box_t *p_box );
  2032.     void (*MP4_FreeBox_function )( MP4_Box_t *p_box );
  2033. } MP4_Box_Function [] =
  2034. {
  2035.     /* Containers */
  2036.     { FOURCC_moov,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2037.     { FOURCC_trak,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2038.     { FOURCC_mdia,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2039.     { FOURCC_moof,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2040.     { FOURCC_minf,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2041.     { FOURCC_stbl,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2042.     { FOURCC_dinf,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2043.     { FOURCC_edts,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2044.     { FOURCC_udta,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2045.     { FOURCC_nmhd,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2046.     { FOURCC_hnti,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2047.     { FOURCC_rmra,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2048.     { FOURCC_rmda,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2049.     { FOURCC_tref,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2050.     { FOURCC_gmhd,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2051.     { FOURCC_wave,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2052.     { FOURCC_ilst,  MP4_ReadBoxContainer,   MP4_FreeBox_Common },
  2053.     /* specific box */
  2054.     { FOURCC_ftyp,  MP4_ReadBox_ftyp,       MP4_FreeBox_ftyp },
  2055.     { FOURCC_cmov,  MP4_ReadBox_cmov,       MP4_FreeBox_Common },
  2056.     { FOURCC_mvhd,  MP4_ReadBox_mvhd,       MP4_FreeBox_Common },
  2057.     { FOURCC_tkhd,  MP4_ReadBox_tkhd,       MP4_FreeBox_Common },
  2058.     { FOURCC_mdhd,  MP4_ReadBox_mdhd,       MP4_FreeBox_Common },
  2059.     { FOURCC_hdlr,  MP4_ReadBox_hdlr,       MP4_FreeBox_hdlr },
  2060.     { FOURCC_vmhd,  MP4_ReadBox_vmhd,       MP4_FreeBox_Common },
  2061.     { FOURCC_smhd,  MP4_ReadBox_smhd,       MP4_FreeBox_Common },
  2062.     { FOURCC_hmhd,  MP4_ReadBox_hmhd,       MP4_FreeBox_Common },
  2063.     { FOURCC_url,   MP4_ReadBox_url,        MP4_FreeBox_url },
  2064.     { FOURCC_urn,   MP4_ReadBox_urn,        MP4_FreeBox_urn },
  2065.     { FOURCC_dref,  MP4_ReadBox_dref,       MP4_FreeBox_Common },
  2066.     { FOURCC_stts,  MP4_ReadBox_stts,       MP4_FreeBox_stts },
  2067.     { FOURCC_ctts,  MP4_ReadBox_ctts,       MP4_FreeBox_ctts },
  2068.     { FOURCC_stsd,  MP4_ReadBox_stsd,       MP4_FreeBox_Common },
  2069.     { FOURCC_stsz,  MP4_ReadBox_stsz,       MP4_FreeBox_stsz },
  2070.     { FOURCC_stsc,  MP4_ReadBox_stsc,       MP4_FreeBox_stsc },
  2071.     { FOURCC_stco,  MP4_ReadBox_stco_co64,  MP4_FreeBox_stco_co64 },
  2072.     { FOURCC_co64,  MP4_ReadBox_stco_co64,  MP4_FreeBox_stco_co64 },
  2073.     { FOURCC_stss,  MP4_ReadBox_stss,       MP4_FreeBox_stss },
  2074.     { FOURCC_stsh,  MP4_ReadBox_stsh,       MP4_FreeBox_stsh },
  2075.     { FOURCC_stdp,  MP4_ReadBox_stdp,       MP4_FreeBox_stdp },
  2076.     { FOURCC_padb,  MP4_ReadBox_padb,       MP4_FreeBox_padb },
  2077.     { FOURCC_elst,  MP4_ReadBox_elst,       MP4_FreeBox_elst },
  2078.     { FOURCC_cprt,  MP4_ReadBox_cprt,       MP4_FreeBox_cprt },
  2079.     { FOURCC_esds,  MP4_ReadBox_esds,       MP4_FreeBox_esds },
  2080.     { FOURCC_dcom,  MP4_ReadBox_dcom,       MP4_FreeBox_Common },
  2081.     { FOURCC_cmvd,  MP4_ReadBox_cmvd,       MP4_FreeBox_cmvd },
  2082.     { FOURCC_avcC,  MP4_ReadBox_avcC,       MP4_FreeBox_avcC },
  2083.     { FOURCC_dac3,  MP4_ReadBox_dac3,       MP4_FreeBox_Common },
  2084.     /* Nothing to do with this box */
  2085.     { FOURCC_mdat,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
  2086.     { FOURCC_skip,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
  2087.     { FOURCC_free,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
  2088.     { FOURCC_wide,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
  2089.     /* for codecs */
  2090.     { FOURCC_soun,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2091.     { FOURCC_ms02,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2092.     { FOURCC_ms11,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2093.     { FOURCC_ms55,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2094.     { FOURCC__mp3,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2095.     { FOURCC_mp4a,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2096.     { FOURCC_twos,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2097.     { FOURCC_sowt,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2098.     { FOURCC_QDMC,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2099.     { FOURCC_QDM2,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2100.     { FOURCC_ima4,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2101.     { FOURCC_IMA4,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2102.     { FOURCC_dvi,   MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2103.     { FOURCC_alaw,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2104.     { FOURCC_ulaw,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2105.     { FOURCC_raw,   MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2106.     { FOURCC_MAC3,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2107.     { FOURCC_MAC6,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2108.     { FOURCC_Qclp,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2109.     { FOURCC_samr,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2110.     { FOURCC_sawb,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2111.     { FOURCC_OggS,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2112.     { FOURCC_alac,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2113.     { FOURCC_drmi,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2114.     { FOURCC_vide,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2115.     { FOURCC_mp4v,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2116.     { FOURCC_SVQ1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2117.     { FOURCC_SVQ3,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2118.     { FOURCC_ZyGo,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2119.     { FOURCC_DIVX,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2120.     { FOURCC_XVID,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2121.     { FOURCC_h263,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2122.     { FOURCC_s263,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2123.     { FOURCC_cvid,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2124.     { FOURCC_3IV1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2125.     { FOURCC_3iv1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2126.     { FOURCC_3IV2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2127.     { FOURCC_3iv2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2128.     { FOURCC_3IVD,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2129.     { FOURCC_3ivd,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2130.     { FOURCC_3VID,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2131.     { FOURCC_3vid,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2132.     { FOURCC_mjpa,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2133.     { FOURCC_mjpb,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2134.     { FOURCC_qdrw,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2135.     { FOURCC_mp2v,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2136.     { FOURCC_hdv2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2137.     { FOURCC_mjqt,  MP4_ReadBox_default,        NULL }, /* found in mjpa/b */
  2138.     { FOURCC_mjht,  MP4_ReadBox_default,        NULL },
  2139.     { FOURCC_dvc,   MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2140.     { FOURCC_dvp,   MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2141.     { FOURCC_dv5n,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2142.     { FOURCC_dv5p,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2143.     { FOURCC_VP31,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2144.     { FOURCC_vp31,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2145.     { FOURCC_h264,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2146.     { FOURCC_jpeg,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2147.     { FOURCC_avc1,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2148.     { FOURCC_yv12,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2149.     { FOURCC_yuv2,  MP4_ReadBox_sample_vide,    MP4_FreeBox_sample_vide },
  2150.     { FOURCC_mp4s,  MP4_ReadBox_sample_mp4s,    MP4_FreeBox_Common },
  2151.     /* XXX there is 2 box where we could find this entry stbl and tref*/
  2152.     { FOURCC_hint,  MP4_ReadBox_default,        MP4_FreeBox_Common },
  2153.     /* found in tref box */
  2154.     { FOURCC_dpnd,  MP4_ReadBox_default,   NULL },
  2155.     { FOURCC_ipir,  MP4_ReadBox_default,   NULL },
  2156.     { FOURCC_mpod,  MP4_ReadBox_default,   NULL },
  2157.     { FOURCC_chap,  MP4_ReadBox_tref_generic,   MP4_FreeBox_tref_generic },
  2158.     /* found in hnti */
  2159.     { FOURCC_rtp,   MP4_ReadBox_default,   NULL },
  2160.     /* found in rmra */
  2161.     { FOURCC_rdrf,  MP4_ReadBox_rdrf,           MP4_FreeBox_rdrf   },
  2162.     { FOURCC_rmdr,  MP4_ReadBox_rmdr,           MP4_FreeBox_Common },
  2163.     { FOURCC_rmqu,  MP4_ReadBox_rmqu,           MP4_FreeBox_Common },
  2164.     { FOURCC_rmvc,  MP4_ReadBox_rmvc,           MP4_FreeBox_Common },
  2165.     { FOURCC_drms,  MP4_ReadBox_sample_soun,    MP4_FreeBox_sample_soun },
  2166.     { FOURCC_sinf,  MP4_ReadBoxContainer,       MP4_FreeBox_Common },
  2167.     { FOURCC_schi,  MP4_ReadBoxContainer,       MP4_FreeBox_Common },
  2168.     { FOURCC_user,  MP4_ReadBox_drms,           MP4_FreeBox_Common },
  2169.     { FOURCC_key,   MP4_ReadBox_drms,           MP4_FreeBox_Common },
  2170.     { FOURCC_iviv,  MP4_ReadBox_drms,           MP4_FreeBox_Common },
  2171.     { FOURCC_name,  MP4_ReadBox_drms,           MP4_FreeBox_Common },
  2172.     { FOURCC_priv,  MP4_ReadBox_drms,           MP4_FreeBox_Common },
  2173.     { FOURCC_frma,  MP4_ReadBox_frma,           MP4_FreeBox_Common },
  2174.     { FOURCC_skcr,  MP4_ReadBox_skcr,           MP4_FreeBox_Common },
  2175.     /* found in udta */
  2176.     { FOURCC_0xa9nam,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2177.     { FOURCC_0xa9aut,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2178.     { FOURCC_0xa9cpy,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2179.     { FOURCC_0xa9swr,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2180.     { FOURCC_0xa9inf,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2181.     { FOURCC_0xa9ART,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2182.     { FOURCC_0xa9dir,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2183.     { FOURCC_0xa9cmt,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2184.     { FOURCC_0xa9req,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2185.     { FOURCC_0xa9day,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2186.     { FOURCC_0xa9des,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2187.     { FOURCC_0xa9fmt,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2188.     { FOURCC_0xa9prd,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2189.     { FOURCC_0xa9prf,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2190.     { FOURCC_0xa9src,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2191.     { FOURCC_0xa9alb,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2192.     { FOURCC_0xa9dis,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2193.     { FOURCC_0xa9enc,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2194.     { FOURCC_0xa9gen,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2195.     { FOURCC_0xa9trk,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2196.     { FOURCC_0xa9dsa,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2197.     { FOURCC_0xa9hst,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2198.     { FOURCC_0xa9url,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2199.     { FOURCC_0xa9ope,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2200.     { FOURCC_0xa9com,MP4_ReadBox_0xa9xxx,       MP4_FreeBox_0xa9xxx },
  2201.     { FOURCC_chpl,   MP4_ReadBox_chpl,          MP4_FreeBox_chpl },
  2202.     /* iTunes/Quicktime meta info */
  2203.     { FOURCC_meta,  MP4_ReadBox_meta,       MP4_FreeBox_Common },
  2204.     /* Last entry */
  2205.     { 0,             MP4_ReadBox_default,       NULL }
  2206. };
  2207. /*****************************************************************************
  2208.  * MP4_ReadBox : parse the actual box and the children
  2209.  *  XXX : Do not go to the next box
  2210.  *****************************************************************************/
  2211. static MP4_Box_t *MP4_ReadBox( stream_t *p_stream, MP4_Box_t *p_father )
  2212. {
  2213.     MP4_Box_t    *p_box = calloc( 1, sizeof( MP4_Box_t ) ); /* Needed to ensure simple on error handler */
  2214.     unsigned int i_index;
  2215.     if( p_box == NULL )
  2216.         return NULL;
  2217.     if( !MP4_ReadBoxCommon( p_stream, p_box ) )
  2218.     {
  2219.         msg_Warn( p_stream, "cannot read one box" );
  2220.         free( p_box );
  2221.         return NULL;
  2222.     }
  2223.     if( !p_box->i_size )
  2224.     {
  2225.         msg_Dbg( p_stream, "found an empty box (null size)" );
  2226.         free( p_box );
  2227.         return NULL;
  2228.     }
  2229.     p_box->p_father = p_father;
  2230.     /* Now search function to call */
  2231.     for( i_index = 0; ; i_index++ )
  2232.     {
  2233.         if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
  2234.             ( MP4_Box_Function[i_index].i_type == 0 ) )
  2235.         {
  2236.             break;
  2237.         }
  2238.     }
  2239.     if( !(MP4_Box_Function[i_index].MP4_ReadBox_function)( p_stream, p_box ) )
  2240.     {
  2241.         MP4_BoxFree( p_stream, p_box );
  2242.         return NULL;
  2243.     }
  2244.     return p_box;
  2245. }
  2246. /*****************************************************************************
  2247.  * MP4_FreeBox : free memory after read with MP4_ReadBox and all
  2248.  * the children
  2249.  *****************************************************************************/
  2250. void MP4_BoxFree( stream_t *s, MP4_Box_t *p_box )
  2251. {
  2252.     unsigned int i_index;
  2253.     MP4_Box_t    *p_child;
  2254.     if( !p_box )
  2255.         return; /* hehe */
  2256.     for( p_child = p_box->p_first; p_child != NULL; )
  2257.     {
  2258.         MP4_Box_t *p_next;
  2259.         p_next = p_child->p_next;
  2260.         MP4_BoxFree( s, p_child );
  2261.         p_child = p_next;
  2262.     }
  2263.     /* Now search function to call */
  2264.     if( p_box->data.p_data )
  2265.     {
  2266.         for( i_index = 0; ; i_index++ )
  2267.         {
  2268.             if( ( MP4_Box_Function[i_index].i_type == p_box->i_type )||
  2269.                 ( MP4_Box_Function[i_index].i_type == 0 ) )
  2270.             {
  2271.                 break;
  2272.             }
  2273.         }
  2274.         if( MP4_Box_Function[i_index].MP4_FreeBox_function == NULL )
  2275.         {
  2276.             /* Should not happen */
  2277.             if MP4_BOX_TYPE_ASCII()
  2278.                 msg_Warn( s,
  2279.                         "cannot free box %4.4s, type unknown",
  2280.                         (char*)&p_box->i_type );
  2281.             else
  2282.                 msg_Warn( s,
  2283.                         "cannot free box c%3.3s, type unknown",
  2284.                         (char*)&p_box->i_type+1 );
  2285.         }
  2286.         else
  2287.         {
  2288.             MP4_Box_Function[i_index].MP4_FreeBox_function( p_box );
  2289.         }
  2290.         free( p_box->data.p_data );
  2291.     }
  2292.     free( p_box );
  2293. }
  2294. /*****************************************************************************
  2295.  * MP4_BoxGetRoot : Parse the entire file, and create all boxes in memory
  2296.  *****************************************************************************
  2297.  *  The first box is a virtual box "root" and is the father for all first
  2298.  *  level boxes for the file, a sort of virtual contener
  2299.  *****************************************************************************/
  2300. MP4_Box_t *MP4_BoxGetRoot( stream_t *s )
  2301. {
  2302.     MP4_Box_t *p_root;
  2303.     stream_t *p_stream;
  2304.     int i_result;
  2305.     p_root = malloc( sizeof( MP4_Box_t ) );
  2306.     if( p_root == NULL )
  2307.         return NULL;
  2308.     p_root->i_pos = 0;
  2309.     p_root->i_type = VLC_FOURCC( 'r', 'o', 'o', 't' );
  2310.     p_root->i_shortsize = 1;
  2311.     p_root->i_size = stream_Size( s );
  2312.     CreateUUID( &p_root->i_uuid, p_root->i_type );
  2313.     p_root->data.p_data = NULL;
  2314.     p_root->p_father = NULL;
  2315.     p_root->p_first  = NULL;
  2316.     p_root->p_last  = NULL;
  2317.     p_root->p_next   = NULL;
  2318.     p_stream = s;
  2319.     i_result = MP4_ReadBoxContainerRaw( p_stream, p_root );
  2320.     if( i_result )
  2321.     {
  2322.         MP4_Box_t *p_child;
  2323.         MP4_Box_t *p_moov;
  2324.         MP4_Box_t *p_cmov;
  2325.         /* check if there is a cmov, if so replace
  2326.           compressed moov by  uncompressed one */
  2327.         if( ( ( p_moov = MP4_BoxGet( p_root, "moov" ) ) &&
  2328.               ( p_cmov = MP4_BoxGet( p_root, "moov/cmov" ) ) ) ||
  2329.             ( ( p_moov = MP4_BoxGet( p_root, "foov" ) ) &&
  2330.               ( p_cmov = MP4_BoxGet( p_root, "foov/cmov" ) ) ) )
  2331.         {
  2332.             /* rename the compressed moov as a box to skip */
  2333.             p_moov->i_type = FOURCC_skip;
  2334.             /* get uncompressed p_moov */
  2335.             p_moov = p_cmov->data.p_cmov->p_moov;
  2336.             p_cmov->data.p_cmov->p_moov = NULL;
  2337.             /* make p_root father of this new moov */
  2338.             p_moov->p_father = p_root;
  2339.             /* insert this new moov box as first child of p_root */
  2340.             p_moov->p_next = p_child = p_root->p_first;
  2341.             p_root->p_first = p_moov;
  2342.         }
  2343.     }
  2344.     return p_root;
  2345. }
  2346. static void __MP4_BoxDumpStructure( stream_t *s,
  2347.                                     MP4_Box_t *p_box, unsigned int i_level )
  2348. {
  2349.     MP4_Box_t *p_child;
  2350.     if( !i_level )
  2351.     {
  2352.         if MP4_BOX_TYPE_ASCII()
  2353.             msg_Dbg( s, "dumping root Box "%4.4s"",
  2354.                               (char*)&p_box->i_type );
  2355.         else
  2356.             msg_Dbg( s, "dumping root Box "c%3.3s"",
  2357.                               (char*)&p_box->i_type+1 );
  2358.     }
  2359.     else
  2360.     {
  2361.         unsigned int i;
  2362.         char str[512];
  2363.         if( i_level * 5 + 1 >= sizeof(str) )
  2364.             return;
  2365.         memset( str, ' ', sizeof(str) );
  2366.         for( i = 0; i < i_level; i++ )
  2367.         {
  2368.             str[i*5] = '|';
  2369.         }
  2370.         if( MP4_BOX_TYPE_ASCII() )
  2371.             snprintf( &str[i_level * 5], sizeof(str) - 5*i_level,
  2372.                       "+ %4.4s size %d",
  2373.                         (char*)&p_box->i_type, (uint32_t)p_box->i_size );
  2374.         else
  2375.             snprintf( &str[i_level * 5], sizeof(str) - 5*i_level,
  2376.                       "+ c%3.3s size %d",
  2377.                         (char*)&p_box->i_type+1, (uint32_t)p_box->i_size );
  2378.         msg_Dbg( s, "%s", str );
  2379.     }
  2380.     p_child = p_box->p_first;
  2381.     while( p_child )
  2382.     {
  2383.         __MP4_BoxDumpStructure( s, p_child, i_level + 1 );
  2384.         p_child = p_child->p_next;
  2385.     }
  2386. }
  2387. void MP4_BoxDumpStructure( stream_t *s, MP4_Box_t *p_box )
  2388. {
  2389.     __MP4_BoxDumpStructure( s, p_box, 0 );
  2390. }
  2391. /*****************************************************************************
  2392.  *****************************************************************************
  2393.  **
  2394.  **  High level methods to acces an MP4 file
  2395.  **
  2396.  *****************************************************************************
  2397.  *****************************************************************************/
  2398. static void __get_token( char **ppsz_path, char **ppsz_token, int *pi_number )
  2399. {
  2400.     size_t i_len ;
  2401.     if( !*ppsz_path[0] )
  2402.     {
  2403.         *ppsz_token = NULL;
  2404.         *pi_number = 0;
  2405.         return;
  2406.     }
  2407.     i_len = 0;
  2408.     while(  (*ppsz_path)[i_len] &&
  2409.             (*ppsz_path)[i_len] != '/' && (*ppsz_path)[i_len] != '[' )
  2410.     {
  2411.         i_len++;
  2412.     }
  2413.     if( !i_len && **ppsz_path == '/' )
  2414.     {
  2415.         i_len = 1;
  2416.     }
  2417.     *ppsz_token = malloc( i_len + 1 );
  2418.     memcpy( *ppsz_token, *ppsz_path, i_len );
  2419.     (*ppsz_token)[i_len] = '';
  2420.     *ppsz_path += i_len;
  2421.     if( **ppsz_path == '[' )
  2422.     {
  2423.         (*ppsz_path)++;
  2424.         *pi_number = strtol( *ppsz_path, NULL, 10 );
  2425.         while( **ppsz_path && **ppsz_path != ']' )
  2426.         {
  2427.             (*ppsz_path)++;
  2428.         }
  2429.         if( **ppsz_path == ']' )
  2430.         {
  2431.             (*ppsz_path)++;
  2432.         }
  2433.     }
  2434.     else
  2435.     {
  2436.         *pi_number = 0;
  2437.     }
  2438.     while( **ppsz_path == '/' )
  2439.     {
  2440.         (*ppsz_path)++;
  2441.     }
  2442. }
  2443. static void __MP4_BoxGet( MP4_Box_t **pp_result,
  2444.                           MP4_Box_t *p_box, const char *psz_fmt, va_list args)
  2445. {
  2446.     char *psz_dup;
  2447.     char *psz_path;
  2448.     if( !p_box )
  2449.     {
  2450.         *pp_result = NULL;
  2451.         return;
  2452.     }
  2453.     if( vasprintf( &psz_path, psz_fmt, args ) == -1 )
  2454.         psz_path = NULL;
  2455.     if( !psz_path || !psz_path[0] )
  2456.     {
  2457.         free( psz_path );
  2458.         *pp_result = NULL;
  2459.         return;
  2460.     }
  2461. //    fprintf( stderr, "path:'%s'n", psz_path );
  2462.     psz_dup = psz_path; /* keep this pointer, as it need to be unallocated */
  2463.     for( ; ; )
  2464.     {
  2465.         char *psz_token;
  2466.         int i_number;
  2467.         __get_token( &psz_path, &psz_token, &i_number );
  2468. //        fprintf( stderr, "path:'%s', token:'%s' n:%dn",
  2469. //                 psz_path,psz_token,i_number );
  2470.         if( !psz_token )
  2471.         {
  2472.             free( psz_dup );
  2473.             *pp_result = p_box;
  2474.             return;
  2475.         }
  2476.         else
  2477.         if( !strcmp( psz_token, "/" ) )
  2478.         {
  2479.             /* Find root box */
  2480.             while( p_box && p_box->i_type != VLC_FOURCC( 'r', 'o', 'o', 't' ) )
  2481.             {
  2482.                 p_box = p_box->p_father;
  2483.             }
  2484.             if( !p_box )
  2485.             {
  2486.                 free( psz_token );
  2487.                 free( psz_dup );
  2488.                 *pp_result = NULL;
  2489.                 return;
  2490.             }
  2491.         }
  2492.         else
  2493.         if( !strcmp( psz_token, "." ) )
  2494.         {
  2495.             /* Do nothing */
  2496.         }
  2497.         else
  2498.         if( !strcmp( psz_token, ".." ) )
  2499.         {
  2500.             p_box = p_box->p_father;
  2501.             if( !p_box )
  2502.             {
  2503.                 free( psz_token );
  2504.                 free( psz_dup );
  2505.                 *pp_result = NULL;
  2506.                 return;
  2507.             }
  2508.         }
  2509.         else
  2510.         if( strlen( psz_token ) == 4 )
  2511.         {
  2512.             uint32_t i_fourcc;
  2513.             i_fourcc = VLC_FOURCC( psz_token[0], psz_token[1],
  2514.                                    psz_token[2], psz_token[3] );
  2515.             p_box = p_box->p_first;
  2516.             for( ; ; )
  2517.             {
  2518.                 if( !p_box )
  2519.                 {
  2520.                     free( psz_token );
  2521.                     free( psz_dup );
  2522.                     *pp_result = NULL;
  2523.                     return;
  2524.                 }
  2525.                 if( p_box->i_type == i_fourcc )
  2526.                 {
  2527.                     if( !i_number )
  2528.                     {
  2529.                         break;
  2530.                     }
  2531.                     i_number--;
  2532.                 }
  2533.                 p_box = p_box->p_next;
  2534.             }
  2535.         }
  2536.         else
  2537.         if( strlen( psz_token ) == 0 )
  2538.         {
  2539.             p_box = p_box->p_first;
  2540.             for( ; ; )
  2541.             {
  2542.                 if( !p_box )
  2543.                 {
  2544.                     free( psz_token );
  2545.                     free( psz_dup );
  2546.                     *pp_result = NULL;
  2547.                     return;
  2548.                 }
  2549.                 if( !i_number )
  2550.                 {
  2551.                     break;
  2552.                 }
  2553.                 i_number--;
  2554.                 p_box = p_box->p_next;
  2555.             }
  2556.         }
  2557.         else
  2558.         {
  2559. //            fprintf( stderr, "Argg malformed token "%s"",psz_token );
  2560.             FREENULL( psz_token );
  2561.             free( psz_dup );
  2562.             *pp_result = NULL;
  2563.             return;
  2564.         }
  2565.         free( psz_token );
  2566.     }
  2567. }
  2568. /*****************************************************************************
  2569.  * MP4_BoxGet: find a box given a path relative to p_box
  2570.  *****************************************************************************
  2571.  * Path Format: . .. / as usual
  2572.  *              [number] to specifie box number ex: trak[12]
  2573.  *
  2574.  * ex: /moov/trak[12]
  2575.  *     ../mdia
  2576.  *****************************************************************************/
  2577. MP4_Box_t *MP4_BoxGet( MP4_Box_t *p_box, const char *psz_fmt, ... )
  2578. {
  2579.     va_list args;
  2580.     MP4_Box_t *p_result;
  2581.     va_start( args, psz_fmt );
  2582.     __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
  2583.     va_end( args );
  2584.     return( p_result );
  2585. }
  2586. /*****************************************************************************
  2587.  * MP4_BoxCount: count box given a path relative to p_box
  2588.  *****************************************************************************
  2589.  * Path Format: . .. / as usual
  2590.  *              [number] to specifie box number ex: trak[12]
  2591.  *
  2592.  * ex: /moov/trak[12]
  2593.  *     ../mdia
  2594.  *****************************************************************************/
  2595. int MP4_BoxCount( MP4_Box_t *p_box, const char *psz_fmt, ... )
  2596. {
  2597.     va_list args;
  2598.     int     i_count;
  2599.     MP4_Box_t *p_result, *p_next;
  2600.     va_start( args, psz_fmt );
  2601.     __MP4_BoxGet( &p_result, p_box, psz_fmt, args );
  2602.     va_end( args );
  2603.     if( !p_result )
  2604.     {
  2605.         return( 0 );
  2606.     }
  2607.     i_count = 1;
  2608.     for( p_next = p_result->p_next; p_next != NULL; p_next = p_next->p_next)
  2609.     {
  2610.         if( p_next->i_type == p_result->i_type)
  2611.         {
  2612.             i_count++;
  2613.         }
  2614.     }
  2615.     return( i_count );
  2616. }