mp4.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:68k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * mp4.c : MP4 file input module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2004 VideoLAN
  5.  * $Id: mp4.c 9142 2004-11-04 22:32:40Z hartman $
  6.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  21.  *****************************************************************************/
  22. /*****************************************************************************
  23.  * Preamble
  24.  *****************************************************************************/
  25. #include <stdlib.h>                                      /* malloc(), free() */
  26. #include <vlc/vlc.h>
  27. #include <vlc/input.h>
  28. #include <vlc_playlist.h>
  29. #include "iso_lang.h"
  30. #include "vlc_meta.h"
  31. #include "libmp4.h"
  32. #include "drms.h"
  33. #ifdef UNDER_CE
  34. #define uint64_t int64_t
  35. #endif
  36. /*****************************************************************************
  37.  * Module descriptor
  38.  *****************************************************************************/
  39. static int  Open ( vlc_object_t * );
  40. static void Close( vlc_object_t * );
  41. vlc_module_begin();
  42.     set_description( _("MP4 stream demuxer") );
  43.     set_capability( "demux2", 242 );
  44.     set_callbacks( Open, Close );
  45. vlc_module_end();
  46. /*****************************************************************************
  47.  * Local prototypes
  48.  *****************************************************************************/
  49. static int    Demux   ( demux_t * );
  50. static int    DemuxRef( demux_t *p_demux )
  51. {
  52.     return 0;
  53. }
  54. static int   Seek     ( demux_t *, mtime_t );
  55. static int   Control  ( demux_t *, int, va_list );
  56. /* Contain all information about a chunk */
  57. typedef struct
  58. {
  59.     uint64_t     i_offset; /* absolute position of this chunk in the file */
  60.     uint32_t     i_sample_description_index; /* index for SampleEntry to use */
  61.     uint32_t     i_sample_count; /* how many samples in this chunk */
  62.     uint32_t     i_sample_first; /* index of the first sample in this chunk */
  63.     /* now provide way to calculate pts, dts, and offset without to
  64.         much memory and with fast acces */
  65.     /* with this we can calculate dts/pts without waste memory */
  66.     uint64_t     i_first_dts;
  67.     uint32_t     *p_sample_count_dts;
  68.     uint32_t     *p_sample_delta_dts; /* dts delta */
  69.     /* TODO if needed add pts
  70.         but quickly *add* support for edts and seeking */
  71. } mp4_chunk_t;
  72.  /* Contain all needed information for read all track with vlc */
  73. typedef struct
  74. {
  75.     int i_track_ID;     /* this should be unique */
  76.     int b_ok;           /* The track is usable */
  77.     int b_enable;       /* is the trak enable by default */
  78.     vlc_bool_t b_selected;     /* is the trak being played */
  79.     es_format_t fmt;
  80.     es_out_id_t *p_es;
  81.     /* display size only ! */
  82.     int i_width;
  83.     int i_height;
  84.     /* more internal data */
  85.     uint64_t        i_timescale;    /* time scale for this track only */
  86.     /* elst */
  87.     int             i_elst;         /* current elst */
  88.     int64_t         i_elst_time;    /* current elst start time (in movie time scale)*/
  89.     MP4_Box_t       *p_elst;        /* elst (could be NULL) */
  90.     /* give the next sample to read, i_chunk is to find quickly where
  91.       the sample is located */
  92.     uint32_t         i_sample;       /* next sample to read */
  93.     uint32_t         i_chunk;        /* chunk where next sample is stored */
  94.     /* total count of chunk and sample */
  95.     uint32_t         i_chunk_count;
  96.     uint32_t         i_sample_count;
  97.     mp4_chunk_t    *chunk; /* always defined  for each chunk */
  98.     /* sample size, p_sample_size defined only if i_sample_size == 0
  99.         else i_sample_size is size for all sample */
  100.     uint32_t         i_sample_size;
  101.     uint32_t         *p_sample_size; /* XXX perhaps add file offset if take
  102.                                     too much time to do sumations each time*/
  103.     MP4_Box_t *p_stbl;  /* will contain all timing information */
  104.     MP4_Box_t *p_stsd;  /* will contain all data to initialize decoder */
  105.     MP4_Box_t *p_sample;/* point on actual sdsd */
  106.     vlc_bool_t b_drms;
  107.     void      *p_drms;
  108. } mp4_track_t;
  109. struct demux_sys_t
  110. {
  111.     MP4_Box_t    *p_root;      /* container for the whole file */
  112.     mtime_t      i_pcr;
  113.     uint64_t     i_time;        /* time position of the presentation
  114.                                  * in movie timescale */
  115.     uint64_t     i_timescale;   /* movie time scale */
  116.     uint64_t     i_duration;    /* movie duration */
  117.     unsigned int i_tracks;      /* number of tracks */
  118.     mp4_track_t *track;    /* array of track */
  119. };
  120. /*****************************************************************************
  121.  * Declaration of local function
  122.  *****************************************************************************/
  123. static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *);
  124. static void MP4_TrackDestroy( demux_t *, mp4_track_t * );
  125. static int  MP4_TrackSelect ( demux_t *, mp4_track_t *, mtime_t );
  126. static void MP4_TrackUnselect(demux_t *, mp4_track_t * );
  127. static int  MP4_TrackSeek   ( demux_t *, mp4_track_t *, mtime_t );
  128. static uint64_t MP4_TrackGetPos    ( mp4_track_t * );
  129. static int      MP4_TrackSampleSize( mp4_track_t * );
  130. static int      MP4_TrackNextSample( demux_t *, mp4_track_t * );
  131. static void     MP4_TrackSetELST( demux_t *, mp4_track_t *, int64_t );
  132. /* Return time in 祍 of a track */
  133. static inline int64_t MP4_TrackGetPTS( demux_t *p_demux, mp4_track_t *p_track )
  134. {
  135.     unsigned int i_sample;
  136.     unsigned int i_index;
  137.     int64_t i_dts;
  138.     i_sample = p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first;
  139.     i_dts = p_track->chunk[p_track->i_chunk].i_first_dts;
  140.     i_index = 0;
  141.     while( i_sample > 0 )
  142.     {
  143.         if( i_sample > p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index] )
  144.         {
  145.             i_dts += p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index] *
  146.                         p_track->chunk[p_track->i_chunk].p_sample_delta_dts[i_index];
  147.             i_sample -= p_track->chunk[p_track->i_chunk].p_sample_count_dts[i_index];
  148.             i_index++;
  149.         }
  150.         else
  151.         {
  152.             i_dts += i_sample *
  153.                         p_track->chunk[p_track->i_chunk].p_sample_delta_dts[i_index];
  154.             i_sample = 0;
  155.             break;
  156.         }
  157.     }
  158.     /* now handle elst */
  159.     if( p_track->p_elst )
  160.     {
  161.         demux_sys_t         *p_sys = p_demux->p_sys;
  162.         MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
  163.         /* convert to offset */
  164.         if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
  165.               elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
  166.             elst->i_media_time[p_track->i_elst] > 0 )
  167.         {
  168.             i_dts -= elst->i_media_time[p_track->i_elst];
  169.         }
  170.         /* add i_elst_time */
  171.         i_dts += p_track->i_elst_time * p_track->i_timescale / p_sys->i_timescale;
  172.         if( i_dts < 0 ) i_dts = 0;
  173.     }
  174.     return (int64_t)1000000 * i_dts / p_track->i_timescale;
  175. }
  176. static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
  177. {
  178.     return (int64_t)1000000 * p_sys->i_time / p_sys->i_timescale;
  179. }
  180. #define FREE( p ) if( p ) { free( p ); (p) = NULL;}
  181. /*****************************************************************************
  182.  * Open: check file and initializes MP4 structures
  183.  *****************************************************************************/
  184. static int Open( vlc_object_t * p_this )
  185. {
  186.     demux_t  *p_demux = (demux_t *)p_this;
  187.     demux_sys_t     *p_sys;
  188.     uint8_t         *p_peek;
  189.     MP4_Box_t       *p_ftyp;
  190.     MP4_Box_t       *p_rmra;
  191.     MP4_Box_t       *p_mvhd;
  192.     MP4_Box_t       *p_trak;
  193.     unsigned int    i;
  194.     vlc_bool_t      b_seekable;
  195.     /* a little test to see if it could be a mp4 */
  196.     if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 )
  197.     {
  198.         msg_Warn( p_demux, "MP4 plugin discarded (cannot peek)" );
  199.         return VLC_EGENERIC;
  200.     }
  201.     switch( VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] ) )
  202.     {
  203.         case FOURCC_ftyp:
  204.         case FOURCC_moov:
  205.         case FOURCC_foov:
  206.         case FOURCC_moof:
  207.         case FOURCC_mdat:
  208.         case FOURCC_udta:
  209.         case FOURCC_free:
  210.         case FOURCC_skip:
  211.         case FOURCC_wide:
  212.         case VLC_FOURCC( 'p', 'n', 'o', 't' ):
  213.             break;
  214.          default:
  215.             msg_Warn( p_demux, "MP4 plugin discarded (not a valid file)" );
  216.             return VLC_EGENERIC;
  217.     }
  218.     /* I need to seek */
  219.     stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );
  220.     if( !b_seekable )
  221.     {
  222.         msg_Warn( p_demux, "MP4 plugin discarded (unseekable)" );
  223.         return VLC_EGENERIC;
  224.     }
  225.     /*Set exported functions */
  226.     p_demux->pf_demux = Demux;
  227.     p_demux->pf_control = Control;
  228.     /* create our structure that will contains all data */
  229.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  230.     memset( p_sys, 0, sizeof( demux_sys_t ) );
  231.     /* Now load all boxes ( except raw data ) */
  232.     if( ( p_sys->p_root = MP4_BoxGetRoot( p_demux->s ) ) == NULL )
  233.     {
  234.         msg_Warn( p_demux, "MP4 plugin discarded (not a valid file)" );
  235.         goto error;
  236.     }
  237.     MP4_BoxDumpStructure( p_demux->s, p_sys->p_root );
  238.     if( ( p_ftyp = MP4_BoxGet( p_sys->p_root, "/ftyp" ) ) )
  239.     {
  240.         switch( p_ftyp->data.p_ftyp->i_major_brand )
  241.         {
  242.             case( FOURCC_isom ):
  243.                 msg_Dbg( p_demux,
  244.                          "ISO Media file (isom) version %d.",
  245.                          p_ftyp->data.p_ftyp->i_minor_version );
  246.                 break;
  247.             default:
  248.                 msg_Dbg( p_demux,
  249.                          "unrecognized major file specification (%4.4s).",
  250.                           (char*)&p_ftyp->data.p_ftyp->i_major_brand );
  251.                 break;
  252.         }
  253.     }
  254.     else
  255.     {
  256.         msg_Dbg( p_demux, "file type box missing (assuming ISO Media file)" );
  257.     }
  258.     /* the file need to have one moov box */
  259.     if( MP4_BoxCount( p_sys->p_root, "/moov" ) <= 0 )
  260.     {
  261.         MP4_Box_t *p_foov = MP4_BoxGet( p_sys->p_root, "/foov" );
  262.         if( !p_foov )
  263.         {
  264.             msg_Err( p_demux, "MP4 plugin discarded (no moov box)" );
  265.             goto error;
  266.         }
  267.         /* we have a free box as a moov, rename it */
  268.         p_foov->i_type = FOURCC_moov;
  269.     }
  270.     if( ( p_rmra = MP4_BoxGet( p_sys->p_root,  "/moov/rmra" ) ) )
  271.     {
  272.         playlist_t *p_playlist;
  273.         int        i_count = MP4_BoxCount( p_rmra, "rmda" );
  274.         int        i;
  275.         msg_Dbg( p_demux, "detected playlist mov file (%d ref)", i_count );
  276.         p_playlist =
  277.             (playlist_t *)vlc_object_find( p_demux,
  278.                                            VLC_OBJECT_PLAYLIST,
  279.                                            FIND_ANYWHERE );
  280.         if( p_playlist )
  281.         {
  282.             //p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
  283.             for( i = 0; i < i_count; i++ )
  284.             {
  285.                 MP4_Box_t *p_rdrf = MP4_BoxGet( p_rmra, "rmda[%d]/rdrf", i );
  286.                 char      *psz_ref;
  287.                 uint32_t  i_ref_type;
  288.                 int       i_position = p_playlist->i_index;
  289.                 if( !p_rdrf || !( psz_ref = p_rdrf->data.p_rdrf->psz_ref ) )
  290.                 {
  291.                     continue;
  292.                 }
  293.                 i_ref_type = p_rdrf->data.p_rdrf->i_ref_type;
  294.                 msg_Dbg( p_demux, "new ref=`%s' type=%4.4s",
  295.                          psz_ref, (char*)&i_ref_type );
  296.                 if( i_ref_type == VLC_FOURCC( 'u', 'r', 'l', ' ' ) )
  297.                 {
  298.                     if( strstr( psz_ref, "qt5gateQT" ) )
  299.                     {
  300.                         msg_Dbg( p_demux, "ignoring pseudo ref =`%s'", psz_ref );
  301.                         continue;
  302.                     }
  303.                     if( !strncmp( psz_ref, "http://", 7 ) ||
  304.                         !strncmp( psz_ref, "rtsp://", 7 ) )
  305.                     {
  306.                         msg_Dbg( p_demux, "adding ref = `%s'", psz_ref );
  307.                         playlist_Add( p_playlist, psz_ref, psz_ref,
  308.                                       PLAYLIST_APPEND, i_position );
  309.                     }
  310.                     else
  311.                     {
  312.                         /* msg dbg relative ? */
  313.                         char *psz_absolute = alloca( strlen( p_demux->psz_access ) + 3 + strlen( p_demux->psz_path ) + strlen( psz_ref ) + 1);
  314.                         char *end = strrchr( p_demux->psz_path, '/' );
  315.                         if( end )
  316.                         {
  317.                             int i_len = end + 1 - p_demux->psz_path;
  318.                             strcpy( psz_absolute, p_demux->psz_access );
  319.                             strcat( psz_absolute, "://" );
  320.                             strncat( psz_absolute, p_demux->psz_path, i_len);
  321.                         }
  322.                         else
  323.                         {
  324.                             strcpy( psz_absolute, "" );
  325.                         }
  326.                         strcat( psz_absolute, psz_ref );
  327.                         msg_Dbg( p_demux, "adding ref = `%s'", psz_absolute );
  328.                         playlist_Add( p_playlist, psz_absolute, psz_absolute,
  329.                                       PLAYLIST_APPEND, i_position );
  330.                     }
  331.                 }
  332.                 else
  333.                 {
  334.                     msg_Err( p_demux, "unknown ref type=%4.4s FIXME (send a bug report)",
  335.                              (char*)&p_rdrf->data.p_rdrf->i_ref_type );
  336.                 }
  337.             }
  338.             vlc_object_release( p_playlist );
  339.         }
  340.         else
  341.         {
  342.             msg_Err( p_demux, "can't find playlist" );
  343.         }
  344.     }
  345.     if( !(p_mvhd = MP4_BoxGet( p_sys->p_root, "/moov/mvhd" ) ) )
  346.     {
  347.         if( !p_rmra )
  348.         {
  349.             msg_Err( p_demux, "cannot find /moov/mvhd" );
  350.             goto error;
  351.         }
  352.         else
  353.         {
  354.             msg_Warn( p_demux, "cannot find /moov/mvhd (pure ref file)" );
  355.             p_demux->pf_demux = DemuxRef;
  356.             return VLC_SUCCESS;
  357.         }
  358.     }
  359.     else
  360.     {
  361.         p_sys->i_timescale = p_mvhd->data.p_mvhd->i_timescale;
  362.         p_sys->i_duration = p_mvhd->data.p_mvhd->i_duration;
  363.     }
  364.     if( !( p_sys->i_tracks = MP4_BoxCount( p_sys->p_root, "/moov/trak" ) ) )
  365.     {
  366.         msg_Err( p_demux, "cannot find any /moov/trak" );
  367.         goto error;
  368.     }
  369.     msg_Dbg( p_demux, "find %d track%c",
  370.                         p_sys->i_tracks,
  371.                         p_sys->i_tracks ? 's':' ' );
  372.     /* allocate memory */
  373.     p_sys->track = calloc( p_sys->i_tracks, sizeof( mp4_track_t ) );
  374.     memset( p_sys->track, 0, p_sys->i_tracks * sizeof( mp4_track_t ) );
  375.     /* now process each track and extract all usefull information */
  376.     for( i = 0; i < p_sys->i_tracks; i++ )
  377.     {
  378.         p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i );
  379.         MP4_TrackCreate( p_demux, &p_sys->track[i], p_trak );
  380.         if( p_sys->track[i].b_ok )
  381.         {
  382.             char *psz_cat;
  383.             switch( p_sys->track[i].fmt.i_cat )
  384.             {
  385.                 case( VIDEO_ES ):
  386.                     psz_cat = "video";
  387.                     break;
  388.                 case( AUDIO_ES ):
  389.                     psz_cat = "audio";
  390.                     break;
  391.                 case( SPU_ES ):
  392.                     psz_cat = "subtitle";
  393.                     break;
  394.                 default:
  395.                     psz_cat = "unknown";
  396.                     break;
  397.             }
  398.             msg_Dbg( p_demux, "adding track[Id 0x%x] %s (%s) language %s",
  399.                             p_sys->track[i].i_track_ID,
  400.                             psz_cat,
  401.                             p_sys->track[i].b_enable ? "enable":"disable",
  402.                             p_sys->track[i].fmt.psz_language ? p_sys->track[i].fmt.psz_language : "undef" );
  403.         }
  404.         else
  405.         {
  406.             msg_Dbg( p_demux, "ignoring track[Id 0x%x]", p_sys->track[i].i_track_ID );
  407.         }
  408.     }
  409.     return VLC_SUCCESS;
  410. error:
  411.     if( p_sys->p_root )
  412.     {
  413.         MP4_BoxFree( p_demux->s, p_sys->p_root );
  414.     }
  415.     free( p_sys );
  416.     return VLC_EGENERIC;
  417. }
  418. /*****************************************************************************
  419.  * Demux: read packet and send them to decoders
  420.  *****************************************************************************
  421.  * TODO check for newly selected track (ie audio upt to now )
  422.  *****************************************************************************/
  423. static int Demux( demux_t *p_demux )
  424. {
  425.     demux_sys_t *p_sys = p_demux->p_sys;
  426.     unsigned int i_track;
  427.     unsigned int i_track_selected;
  428.     /* check for newly selected/unselected track */
  429.     for( i_track = 0, i_track_selected = 0; i_track < p_sys->i_tracks;
  430.          i_track++ )
  431.     {
  432.         mp4_track_t *tk = &p_sys->track[i_track];
  433.         if( tk->b_selected && tk->i_sample >= tk->i_sample_count )
  434.         {
  435.             msg_Warn( p_demux, "track[0x%x] will be disabled", tk->i_track_ID );
  436.             MP4_TrackUnselect( p_demux, tk);
  437.         }
  438.         else if( tk->b_ok )
  439.         {
  440.             vlc_bool_t b;
  441.             es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
  442.             if( tk->b_selected && !b )
  443.             {
  444.                 MP4_TrackUnselect( p_demux, tk );
  445.             }
  446.             else if( !tk->b_selected && b)
  447.             {
  448.                 MP4_TrackSelect( p_demux, tk, MP4_GetMoviePTS( p_sys ) );
  449.             }
  450.             if( tk->b_selected )
  451.             {
  452.                 i_track_selected++;
  453.             }
  454.         }
  455.     }
  456.     if( i_track_selected <= 0 )
  457.     {
  458.         p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
  459.         if( p_sys->i_timescale > 0 )
  460.         {
  461.             int64_t i_length = (mtime_t)1000000 *
  462.                                (mtime_t)p_sys->i_duration /
  463.                                (mtime_t)p_sys->i_timescale;
  464.             if( MP4_GetMoviePTS( p_sys ) >= i_length )
  465.                 return 0;
  466.             return 1;
  467.         }
  468.         msg_Warn( p_demux, "no track selected, exiting..." );
  469.         return 0;
  470.     }
  471.     /* first wait for the good time to read a packet */
  472.     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr + 1 );
  473.     p_sys->i_pcr = MP4_GetMoviePTS( p_sys );
  474.     /* we will read 100ms for each stream so ...*/
  475.     p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 );
  476.     for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
  477.     {
  478.         mp4_track_t *tk = &p_sys->track[i_track];
  479.         if( !tk->b_ok || !tk->b_selected )
  480.         {
  481.             continue;
  482.         }
  483.         while( MP4_TrackGetPTS( p_demux, tk ) < MP4_GetMoviePTS( p_sys ) )
  484.         {
  485. #if 0
  486.             msg_Dbg( p_demux, "tk=%lld mv=%lld",
  487.                      MP4_TrackGetPTS( p_demux, tk ),
  488.                      MP4_GetMoviePTS( p_sys ) );
  489. #endif
  490.             if( MP4_TrackSampleSize( tk ) > 0 )
  491.             {
  492.                 block_t *p_block;
  493.                 /* go,go go ! */
  494.                 if( stream_Seek( p_demux->s, MP4_TrackGetPos( tk ) ) )
  495.                 {
  496.                     msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)", tk->i_track_ID );
  497.                     MP4_TrackUnselect( p_demux, tk );
  498.                     break;
  499.                 }
  500.                 /* now read pes */
  501.                 if( ( p_block = stream_Block( p_demux->s,
  502.                                               MP4_TrackSampleSize( tk ) ) ) == NULL )
  503.                 {
  504.                     msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)", tk->i_track_ID );
  505.                     MP4_TrackUnselect( p_demux, tk );
  506.                     break;
  507.                 }
  508.                 if( tk->b_drms && tk->p_drms )
  509.                 {
  510.                     drms_decrypt( tk->p_drms,
  511.                                   (uint32_t*)p_block->p_buffer,
  512.                                   p_block->i_buffer );
  513.                 }
  514.                 else if( tk->fmt.i_cat == SPU_ES )
  515.                 {
  516.                     if( tk->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) && p_block->i_buffer >= 2 )
  517.                     {
  518.                         uint16_t i_size = GetWBE( p_block->p_buffer );
  519.                         if( i_size + 2 <= p_block->i_buffer )
  520.                         {
  521.                             char *p;
  522.                             /* remove the length field, and append a '' */
  523.                             memmove( &p_block->p_buffer[0], &p_block->p_buffer[2], i_size );
  524.                             p_block->p_buffer[i_size] = '';
  525.                             p_block->i_buffer = i_size + 1;
  526.                             /* convert r -> n */
  527.                             while( ( p = strchr( p_block->p_buffer, 'r' ) ) )
  528.                             {
  529.                                 *p = 'n';
  530.                             }
  531.                         }
  532.                         else
  533.                         {
  534.                             /* Invalid */
  535.                             p_block->i_buffer = 0;
  536.                         }
  537.                     }
  538.                 }
  539.                 p_block->i_dts = MP4_TrackGetPTS( p_demux, tk ) + 1;
  540.                 p_block->i_pts = tk->fmt.i_cat == VIDEO_ES ? 0 : p_block->i_dts + 1;
  541.                 if( !tk->b_drms || ( tk->b_drms && tk->p_drms ) )
  542.                 {
  543.                     es_out_Send( p_demux->out, tk->p_es, p_block );
  544.                 }
  545.             }
  546.             /* Next sample */
  547.             if( MP4_TrackNextSample( p_demux, tk ) )
  548.             {
  549.                 break;
  550.             }
  551.         }
  552.     }
  553.     return 1;
  554. }
  555. /*****************************************************************************
  556.  * Seek: Got to i_date
  557. ******************************************************************************/
  558. static int Seek( demux_t *p_demux, mtime_t i_date )
  559. {
  560.     demux_sys_t *p_sys = p_demux->p_sys;
  561.     unsigned int i_track;
  562.     /* First update update global time */
  563.     p_sys->i_time = i_date * p_sys->i_timescale / 1000000;
  564.     p_sys->i_pcr  = i_date;
  565.     /* Now for each stream try to go to this time */
  566.     for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
  567.     {
  568.         mp4_track_t *tk = &p_sys->track[i_track];
  569.         MP4_TrackSeek( p_demux, tk, i_date );
  570.     }
  571.     return VLC_SUCCESS;
  572. }
  573. /*****************************************************************************
  574.  * Control:
  575.  *****************************************************************************/
  576. static int Control( demux_t *p_demux, int i_query, va_list args )
  577. {
  578.     demux_sys_t *p_sys = p_demux->p_sys;
  579.     double f, *pf;
  580.     int64_t i64, *pi64;
  581.     switch( i_query )
  582.     {
  583.         case DEMUX_GET_POSITION:
  584.             pf = (double*)va_arg( args, double * );
  585.             if( p_sys->i_duration > 0 )
  586.             {
  587.                 *pf = (double)p_sys->i_time / (double)p_sys->i_duration;
  588.             }
  589.             else
  590.             {
  591.                 *pf = 0.0;
  592.             }
  593.             return VLC_SUCCESS;
  594.         case DEMUX_SET_POSITION:
  595.             f = (double)va_arg( args, double );
  596.             if( p_sys->i_timescale > 0 )
  597.             {
  598.                 i64 = (int64_t)( f * (double)1000000 *
  599.                                  (double)p_sys->i_duration /
  600.                                  (double)p_sys->i_timescale );
  601.                 return Seek( p_demux, i64 );
  602.             }
  603.             else return VLC_SUCCESS;
  604.         case DEMUX_GET_TIME:
  605.             pi64 = (int64_t*)va_arg( args, int64_t * );
  606.             if( p_sys->i_timescale > 0 )
  607.             {
  608.                 *pi64 = (mtime_t)1000000 *
  609.                         (mtime_t)p_sys->i_time /
  610.                         (mtime_t)p_sys->i_timescale;
  611.             }
  612.             else *pi64 = 0;
  613.             return VLC_SUCCESS;
  614.         case DEMUX_SET_TIME:
  615.             i64 = (int64_t)va_arg( args, int64_t );
  616.             return Seek( p_demux, i64 );
  617.         case DEMUX_GET_LENGTH:
  618.             pi64 = (int64_t*)va_arg( args, int64_t * );
  619.             if( p_sys->i_timescale > 0 )
  620.             {
  621.                 *pi64 = (mtime_t)1000000 *
  622.                         (mtime_t)p_sys->i_duration /
  623.                         (mtime_t)p_sys->i_timescale;
  624.             }
  625.             else *pi64 = 0;
  626.             return VLC_SUCCESS;
  627.         case DEMUX_GET_FPS:
  628.             msg_Warn( p_demux, "DEMUX_GET_FPS unimplemented !!" );
  629.             return VLC_EGENERIC;
  630.         case DEMUX_GET_META:
  631.         {
  632.             vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
  633.             vlc_meta_t *meta;
  634.             MP4_Box_t  *p_udta   = MP4_BoxGet( p_sys->p_root, "/moov/udta" );
  635.             MP4_Box_t  *p_0xa9xxx;
  636.             if( p_udta == NULL )
  637.             {
  638.                 return VLC_EGENERIC;
  639.             }
  640.             *pp_meta = meta = vlc_meta_New();
  641.             for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;
  642.                  p_0xa9xxx = p_0xa9xxx->p_next )
  643.             {
  644.                 switch( p_0xa9xxx->i_type )
  645.                 {
  646.                 case FOURCC_0xa9nam: /* Full name */
  647.                     vlc_meta_Add( meta, VLC_META_TITLE,
  648.                                   p_0xa9xxx->data.p_0xa9xxx->psz_text );
  649.                     break;
  650.                 case FOURCC_0xa9aut:
  651.                     vlc_meta_Add( meta, VLC_META_AUTHOR,
  652.                                   p_0xa9xxx->data.p_0xa9xxx->psz_text );
  653.                     break;
  654.                 case FOURCC_0xa9ART:
  655.                     vlc_meta_Add( meta, VLC_META_ARTIST,
  656.                                   p_0xa9xxx->data.p_0xa9xxx->psz_text );
  657.                     break;
  658.                 case FOURCC_0xa9cpy:
  659.                     vlc_meta_Add( meta, VLC_META_COPYRIGHT,
  660.                                   p_0xa9xxx->data.p_0xa9xxx->psz_text );
  661.                     break;
  662.                 case FOURCC_0xa9day: /* Creation Date */
  663.                     vlc_meta_Add( meta, VLC_META_DATE,
  664.                                   p_0xa9xxx->data.p_0xa9xxx->psz_text );
  665.                     break;
  666.                 case FOURCC_0xa9des: /* Description */
  667.                     vlc_meta_Add( meta, VLC_META_DESCRIPTION,
  668.                                   p_0xa9xxx->data.p_0xa9xxx->psz_text );
  669.                     break;
  670.                 case FOURCC_0xa9gen: /* Genre */
  671.                     vlc_meta_Add( meta, VLC_META_GENRE,
  672.                                   p_0xa9xxx->data.p_0xa9xxx->psz_text );
  673.                     break;
  674.                 case FOURCC_0xa9swr:
  675.                 case FOURCC_0xa9inf: /* Information */
  676.                 case FOURCC_0xa9alb: /* Album */
  677.                 case FOURCC_0xa9dir: /* Director */
  678.                 case FOURCC_0xa9dis: /* Disclaimer */
  679.                 case FOURCC_0xa9enc: /* Encoded By */
  680.                 case FOURCC_0xa9trk: /* Track */
  681.                 case FOURCC_0xa9cmt: /* Commment */
  682.                 case FOURCC_0xa9url: /* URL */
  683.                 case FOURCC_0xa9req: /* Requirements */
  684.                 case FOURCC_0xa9fmt: /* Original Format */
  685.                 case FOURCC_0xa9dsa: /* Display Source As */
  686.                 case FOURCC_0xa9hst: /* Host Computer */
  687.                 case FOURCC_0xa9prd: /* Producer */
  688.                 case FOURCC_0xa9prf: /* Performers */
  689.                 case FOURCC_0xa9ope: /* Original Performer */
  690.                 case FOURCC_0xa9src: /* Providers Source Content */
  691.                 case FOURCC_0xa9wrt: /* Writer */
  692.                 case FOURCC_0xa9com: /* Composer */
  693.                 case FOURCC_WLOC:    /* Window Location */
  694.                     /* TODO one day, but they aren't really meaningfull */
  695.                     break;
  696.                 default:
  697.                     break;
  698.                 }
  699.             }
  700.             return VLC_SUCCESS;
  701.         }
  702.         case DEMUX_GET_TITLE_INFO:
  703.         case DEMUX_SET_NEXT_DEMUX_TIME:
  704.         case DEMUX_SET_GROUP:
  705.             return VLC_EGENERIC;
  706.         default:
  707.             msg_Warn( p_demux, "control query unimplemented !!!" );
  708.             return VLC_EGENERIC;
  709.     }
  710. }
  711. /*****************************************************************************
  712.  * Close: frees unused data
  713.  *****************************************************************************/
  714. static void Close ( vlc_object_t * p_this )
  715. {
  716.     unsigned int i_track;
  717.     demux_t *  p_demux = (demux_t *)p_this;
  718.     demux_sys_t *p_sys = p_demux->p_sys;
  719.     msg_Dbg( p_demux, "freeing all memory" );
  720.     MP4_BoxFree( p_demux->s, p_sys->p_root );
  721.     for( i_track = 0; i_track < p_sys->i_tracks; i_track++ )
  722.     {
  723.         MP4_TrackDestroy( p_demux, &p_sys->track[i_track] );
  724.     }
  725.     FREE( p_sys->track );
  726.     free( p_sys );
  727. }
  728. /****************************************************************************
  729.  * Local functions, specific to vlc
  730.  ****************************************************************************/
  731. /* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */
  732. static int TrackCreateChunksIndex( demux_t *p_demux,
  733.                                    mp4_track_t *p_demux_track )
  734. {
  735.     MP4_Box_t *p_co64; /* give offset for each chunk, same for stco and co64 */
  736.     MP4_Box_t *p_stsc;
  737.     unsigned int i_chunk;
  738.     unsigned int i_index, i_last;
  739.     if( ( !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "stco" ) )&&
  740.           !(p_co64 = MP4_BoxGet( p_demux_track->p_stbl, "co64" ) ) )||
  741.         ( !(p_stsc = MP4_BoxGet( p_demux_track->p_stbl, "stsc" ) ) ))
  742.     {
  743.         return( VLC_EGENERIC );
  744.     }
  745.     p_demux_track->i_chunk_count = p_co64->data.p_co64->i_entry_count;
  746.     if( !p_demux_track->i_chunk_count )
  747.     {
  748.         msg_Warn( p_demux, "no chunk defined" );
  749.         return( VLC_EGENERIC );
  750.     }
  751.     p_demux_track->chunk = calloc( p_demux_track->i_chunk_count,
  752.                                    sizeof( mp4_chunk_t ) );
  753.     /* first we read chunk offset */
  754.     for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
  755.     {
  756.         p_demux_track->chunk[i_chunk].i_offset =
  757.                 p_co64->data.p_co64->i_chunk_offset[i_chunk];
  758.     }
  759.     /* now we read index for SampleEntry( soun vide mp4a mp4v ...)
  760.         to be used for the sample XXX begin to 1
  761.         We construct it begining at the end */
  762.     i_last = p_demux_track->i_chunk_count; /* last chunk proceded */
  763.     i_index = p_stsc->data.p_stsc->i_entry_count;
  764.     if( !i_index )
  765.     {
  766.         msg_Warn( p_demux, "cannot read chunk table or table empty" );
  767.         return( VLC_EGENERIC );
  768.     }
  769.     while( i_index )
  770.     {
  771.         i_index--;
  772.         for( i_chunk = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
  773.                 i_chunk < i_last; i_chunk++ )
  774.         {
  775.             p_demux_track->chunk[i_chunk].i_sample_description_index =
  776.                     p_stsc->data.p_stsc->i_sample_description_index[i_index];
  777.             p_demux_track->chunk[i_chunk].i_sample_count =
  778.                     p_stsc->data.p_stsc->i_samples_per_chunk[i_index];
  779.         }
  780.         i_last = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
  781.     }
  782.     p_demux_track->chunk[0].i_sample_first = 0;
  783.     for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
  784.     {
  785.         p_demux_track->chunk[i_chunk].i_sample_first =
  786.             p_demux_track->chunk[i_chunk-1].i_sample_first +
  787.                 p_demux_track->chunk[i_chunk-1].i_sample_count;
  788.     }
  789.     msg_Dbg( p_demux,
  790.              "track[Id 0x%x] read %d chunk",
  791.              p_demux_track->i_track_ID,
  792.              p_demux_track->i_chunk_count );
  793.     return( VLC_SUCCESS );
  794. }
  795. static int TrackCreateSamplesIndex( demux_t *p_demux,
  796.                                     mp4_track_t *p_demux_track )
  797. {
  798.     MP4_Box_t *p_stts; /* makes mapping between sample and decoding time,
  799.                           ctts make same mapping but for composition time,
  800.                           not yet used and probably not usefull */
  801.     MP4_Box_t *p_stsz; /* gives sample size of each samples, there is also stz2
  802.                           that uses a compressed form FIXME make them in libmp4
  803.                           as a unique type */
  804.     /* TODO use also stss and stsh table for seeking */
  805.     /* FIXME use edit table */
  806.     int64_t i_sample;
  807.     int64_t i_chunk;
  808.     int64_t i_index;
  809.     int64_t i_index_sample_used;
  810.     int64_t i_last_dts;
  811.     p_stts = MP4_BoxGet( p_demux_track->p_stbl, "stts" );
  812.     p_stsz = MP4_BoxGet( p_demux_track->p_stbl, "stsz" ); /* FIXME and stz2 */
  813.     if( ( !p_stts )||( !p_stsz ) )
  814.     {
  815.         msg_Warn( p_demux, "cannot read sample table" );
  816.         return( VLC_EGENERIC );
  817.     }
  818.     p_demux_track->i_sample_count = p_stsz->data.p_stsz->i_sample_count;
  819.     /* for sample size, there are 2 case */
  820.     if( p_stsz->data.p_stsz->i_sample_size )
  821.     {
  822.         /* 1: all sample have the same size, so no need to construct a table */
  823.         p_demux_track->i_sample_size = p_stsz->data.p_stsz->i_sample_size;
  824.         p_demux_track->p_sample_size = NULL;
  825.     }
  826.     else
  827.     {
  828.         /* 2: each sample can have a different size */
  829.         p_demux_track->i_sample_size = 0;
  830.         p_demux_track->p_sample_size =
  831.             calloc( p_demux_track->i_sample_count, sizeof( uint32_t ) );
  832.         for( i_sample = 0; i_sample < p_demux_track->i_sample_count; i_sample++ )
  833.         {
  834.             p_demux_track->p_sample_size[i_sample] =
  835.                     p_stsz->data.p_stsz->i_entry_size[i_sample];
  836.         }
  837.     }
  838.     /* we have extract all information from stsz,
  839.         now use stts */
  840.     /* if we don't want to waste too much memory, we can't expand
  841.        the box !, so each chunk will contain an "extract" of this table
  842.        for fast research */
  843.     i_last_dts = 0;
  844.     i_index = 0; i_index_sample_used =0;
  845.     /* create and init last data for each chunk */
  846.     for(i_chunk = 0 ; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
  847.     {
  848.         int64_t i_entry, i_sample_count, i;
  849.         /* save last dts */
  850.         p_demux_track->chunk[i_chunk].i_first_dts = i_last_dts;
  851.     /* count how many entries needed for this chunk
  852.        for p_sample_delta_dts and p_sample_count_dts */
  853.         i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
  854.         i_entry = 0;
  855.         while( i_sample_count > 0 )
  856.         {
  857.             i_sample_count -= p_stts->data.p_stts->i_sample_count[i_index+i_entry];
  858.             if( i_entry == 0 )
  859.             {
  860.                 i_sample_count += i_index_sample_used; /* don't count already used sample
  861.                                                    int this entry */
  862.             }
  863.             i_entry++;
  864.         }
  865.         /* allocate them */
  866.         p_demux_track->chunk[i_chunk].p_sample_count_dts =
  867.             calloc( i_entry, sizeof( uint32_t ) );
  868.         p_demux_track->chunk[i_chunk].p_sample_delta_dts =
  869.             calloc( i_entry, sizeof( uint32_t ) );
  870.         /* now copy */
  871.         i_sample_count = p_demux_track->chunk[i_chunk].i_sample_count;
  872.         for( i = 0; i < i_entry; i++ )
  873.         {
  874.             int64_t i_used;
  875.             int64_t i_rest;
  876.             i_rest = p_stts->data.p_stts->i_sample_count[i_index] - i_index_sample_used;
  877.             i_used = __MIN( i_rest, i_sample_count );
  878.             i_index_sample_used += i_used;
  879.             i_sample_count -= i_used;
  880.             p_demux_track->chunk[i_chunk].p_sample_count_dts[i] = i_used;
  881.             p_demux_track->chunk[i_chunk].p_sample_delta_dts[i] =
  882.                         p_stts->data.p_stts->i_sample_delta[i_index];
  883.             i_last_dts += i_used *
  884.                     p_demux_track->chunk[i_chunk].p_sample_delta_dts[i];
  885.             if( i_index_sample_used >=
  886.                              p_stts->data.p_stts->i_sample_count[i_index] )
  887.             {
  888.                 i_index++;
  889.                 i_index_sample_used = 0;
  890.             }
  891.         }
  892.     }
  893.     msg_Dbg( p_demux, "track[Id 0x%x] read %d samples length:"I64Fd"s",
  894.              p_demux_track->i_track_ID,
  895.              p_demux_track->i_sample_count,
  896.              i_last_dts / p_demux_track->i_timescale );
  897.     return( VLC_SUCCESS );
  898. }
  899. /*
  900.  * TrackCreateES:
  901.  * Create ES and PES to init decoder if needed, for a track starting at i_chunk
  902.  */
  903. static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
  904.                           unsigned int i_chunk, es_out_id_t **pp_es )
  905. {
  906.     MP4_Box_t   *p_sample;
  907.     MP4_Box_t   *p_esds;
  908.     *pp_es = NULL;
  909.     if( !p_track->chunk[i_chunk].i_sample_description_index )
  910.     {
  911.         msg_Warn( p_demux,
  912.                   "invalid SampleEntry index (track[Id 0x%x])",
  913.                   p_track->i_track_ID );
  914.         return VLC_EGENERIC;
  915.     }
  916.     p_sample = MP4_BoxGet(  p_track->p_stsd, "[%d]",
  917.                 p_track->chunk[i_chunk].i_sample_description_index - 1 );
  918.     if( !p_sample || ( !p_sample->data.p_data && p_track->fmt.i_cat != SPU_ES ) )
  919.     {
  920.         msg_Warn( p_demux,
  921.                   "cannot find SampleEntry (track[Id 0x%x])",
  922.                   p_track->i_track_ID );
  923.         return( VLC_EGENERIC );
  924.     }
  925.     p_track->p_sample = p_sample;
  926.     if( p_track->fmt.i_cat == AUDIO_ES && p_track->i_sample_size == 1 )
  927.     {
  928.         MP4_Box_data_sample_soun_t *p_soun;
  929.         p_soun = p_sample->data.p_sample_soun;
  930.         if( p_soun->i_qt_version == 0 )
  931.         {
  932.             switch( p_sample->i_type )
  933.             {
  934.                 case VLC_FOURCC( 'i', 'm', 'a', '4' ):
  935.                     p_soun->i_qt_version = 1;
  936.                     p_soun->i_sample_per_packet = 64;
  937.                     p_soun->i_bytes_per_packet  = 34;
  938.                     p_soun->i_bytes_per_frame   = 34 * p_soun->i_channelcount;
  939.                     p_soun->i_bytes_per_sample  = 2;
  940.                     break;
  941.                 case VLC_FOURCC( 'M', 'A', 'C', '3' ):
  942.                     p_soun->i_qt_version = 1;
  943.                     p_soun->i_sample_per_packet = 6;
  944.                     p_soun->i_bytes_per_packet  = 2;
  945.                     p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;
  946.                     p_soun->i_bytes_per_sample  = 2;
  947.                     break;
  948.                 case VLC_FOURCC( 'M', 'A', 'C', '6' ):
  949.                     p_soun->i_qt_version = 1;
  950.                     p_soun->i_sample_per_packet = 12;
  951.                     p_soun->i_bytes_per_packet  = 2;
  952.                     p_soun->i_bytes_per_frame   = 2 * p_soun->i_channelcount;
  953.                     p_soun->i_bytes_per_sample  = 2;
  954.                     break;
  955.                 case VLC_FOURCC( 'a', 'l', 'a', 'w' ):
  956.                 case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
  957.                     p_soun->i_samplesize = 8;
  958.                     break;
  959.                 default:
  960.                     break;
  961.             }
  962.         }
  963.         else if( p_soun->i_qt_version == 1 && p_soun->i_sample_per_packet <= 0 )
  964.         {
  965.             p_soun->i_qt_version = 0;
  966.         }
  967.     }
  968.     /* It's a little ugly but .. there are special cases */
  969.     switch( p_sample->i_type )
  970.     {
  971.         case( VLC_FOURCC( '.', 'm', 'p', '3' ) ):
  972.         case( VLC_FOURCC( 'm', 's', 0x00, 0x55 ) ):
  973.             p_track->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'a' );
  974.             break;
  975.         case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):
  976.             p_track->fmt.i_codec = VLC_FOURCC( 'a', 'r', 'a', 'w' );
  977.             break;
  978.         case( VLC_FOURCC( 's', '2', '6', '3' ) ):
  979.             p_track->fmt.i_codec = VLC_FOURCC( 'h', '2', '6', '3' );
  980.             break;
  981.         case( VLC_FOURCC( 't', 'e', 'x', 't' ) ):
  982.             p_track->fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
  983.             /* FIXME: Not true, could be UTF-16 with a Byte Order Mark (0xfeff) */
  984.             /* FIXME UTF-8 doesn't work here ? */
  985.             /* p_track->fmt.subs.psz_encoding = strdup( "UTF-8" ); */
  986.             break;
  987.         default:
  988.             p_track->fmt.i_codec = p_sample->i_type;
  989.             break;
  990.     }
  991.     /* now see if esds is present and if so create a data packet
  992.         with decoder_specific_info  */
  993. #define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr
  994.     if( ( ( p_esds = MP4_BoxGet( p_sample, "esds" ) ) ||
  995.           ( p_esds = MP4_BoxGet( p_sample, "wave/esds" ) ) )&&
  996.         ( p_esds->data.p_esds )&&
  997.         ( p_decconfig ) )
  998.     {
  999.         /* First update information based on i_objectTypeIndication */
  1000.         switch( p_decconfig->i_objectTypeIndication )
  1001.         {
  1002.             case( 0x20 ): /* MPEG4 VIDEO */
  1003.                 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','v' );
  1004.                 break;
  1005.             case( 0x40):
  1006.                 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','a' );
  1007.                 break;
  1008.             case( 0x60):
  1009.             case( 0x61):
  1010.             case( 0x62):
  1011.             case( 0x63):
  1012.             case( 0x64):
  1013.             case( 0x65): /* MPEG2 video */
  1014.                 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' );
  1015.                 break;
  1016.             /* Theses are MPEG2-AAC */
  1017.             case( 0x66): /* main profile */
  1018.             case( 0x67): /* Low complexity profile */
  1019.             case( 0x68): /* Scaleable Sampling rate profile */
  1020.                 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','4','a' );
  1021.                 break;
  1022.             /* true MPEG 2 audio */
  1023.             case( 0x69):
  1024.                 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','a' );
  1025.                 break;
  1026.             case( 0x6a): /* MPEG1 video */
  1027.                 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' );
  1028.                 break;
  1029.             case( 0x6b): /* MPEG1 audio */
  1030.                 p_track->fmt.i_codec = VLC_FOURCC( 'm','p','g','a' );
  1031.                 break;
  1032.             case( 0x6c ): /* jpeg */
  1033.                 p_track->fmt.i_codec = VLC_FOURCC( 'j','p','e','g' );
  1034.                 break;
  1035.             /* Private ID */
  1036.             case( 0xe0 ): /* NeroDigital: dvd subs */
  1037.                 if( p_track->fmt.i_cat == SPU_ES )
  1038.                 {
  1039.                     p_track->fmt.i_codec = VLC_FOURCC( 's','p','u',' ' );
  1040.                     break;
  1041.                 }
  1042.             /* Fallback */
  1043.             default:
  1044.                 /* Unknown entry, but don't touch i_fourcc */
  1045.                 msg_Warn( p_demux,
  1046.                           "unknown objectTypeIndication(0x%x) (Track[ID 0x%x])",
  1047.                           p_decconfig->i_objectTypeIndication,
  1048.                           p_track->i_track_ID );
  1049.                 break;
  1050.         }
  1051.         p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len;
  1052.         if( p_track->fmt.i_extra > 0 )
  1053.         {
  1054.             p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
  1055.             memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info,
  1056.                     p_track->fmt.i_extra );
  1057.         }
  1058.     }
  1059.     else
  1060.     {
  1061.         switch( p_sample->i_type )
  1062.         {
  1063.             /* qt decoder, send the complete chunk */
  1064.             case VLC_FOURCC( 'S', 'V', 'Q', '3' ):
  1065.             case VLC_FOURCC( 'S', 'V', 'Q', '1' ):
  1066.             case VLC_FOURCC( 'V', 'P', '3', '1' ):
  1067.             case VLC_FOURCC( '3', 'I', 'V', '1' ):
  1068.             case VLC_FOURCC( 'Z', 'y', 'G', 'o' ):
  1069.                 p_track->fmt.i_extra =
  1070.                     p_sample->data.p_sample_vide->i_qt_image_description;
  1071.                 if( p_track->fmt.i_extra > 0 )
  1072.                 {
  1073.                     p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
  1074.                     memcpy( p_track->fmt.p_extra,
  1075.                             p_sample->data.p_sample_vide->p_qt_image_description,
  1076.                             p_track->fmt.i_extra);
  1077.                 }
  1078.                 break;
  1079.             case VLC_FOURCC( 'Q', 'D', 'M', 'C' ):
  1080.             case VLC_FOURCC( 'Q', 'D', 'M', '2' ):
  1081.             case VLC_FOURCC( 'Q', 'c', 'l', 'p' ):
  1082.             case VLC_FOURCC( 's', 'a', 'm', 'r' ):
  1083.                 p_track->fmt.i_extra =
  1084.                     p_sample->data.p_sample_soun->i_qt_description;
  1085.                 if( p_track->fmt.i_extra > 0 )
  1086.                 {
  1087.                     p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
  1088.                     memcpy( p_track->fmt.p_extra,
  1089.                             p_sample->data.p_sample_soun->p_qt_description,
  1090.                             p_track->fmt.i_extra);
  1091.                 }
  1092.                 break;
  1093.             /* avc1: send avcC (h264 without annexe B, ie without start code)*/
  1094.             case VLC_FOURCC( 'a', 'v', 'c', '1' ):
  1095.             {
  1096.                 MP4_Box_t *p_avcC = MP4_BoxGet( p_sample, "avcC" );
  1097.                 if( p_avcC )
  1098.                 {
  1099.                     /* Hack: use a packetizer to reecampsulate data in anexe B format */
  1100.                     msg_Dbg( p_demux, "avcC: size=%d", p_avcC->data.p_avcC->i_avcC );
  1101.                     p_track->fmt.i_extra = p_avcC->data.p_avcC->i_avcC;
  1102.                     p_track->fmt.p_extra = malloc( p_avcC->data.p_avcC->i_avcC );
  1103.                     memcpy( p_track->fmt.p_extra, p_avcC->data.p_avcC->p_avcC, p_track->fmt.i_extra );
  1104.                     p_track->fmt.b_packetized = VLC_FALSE;
  1105.                 }
  1106.                 else
  1107.                 {
  1108.                     msg_Err( p_demux, "missing avcC" );
  1109.                 }
  1110.                 break;
  1111.             }
  1112.             default:
  1113.                 break;
  1114.         }
  1115.     }
  1116. #undef p_decconfig
  1117.     /* some last initialisation */
  1118.     switch( p_track->fmt.i_cat )
  1119.     {
  1120.     case( VIDEO_ES ):
  1121.         p_track->fmt.video.i_width = p_sample->data.p_sample_vide->i_width;
  1122.         p_track->fmt.video.i_height = p_sample->data.p_sample_vide->i_height;
  1123.         /* fall on display size */
  1124.         if( p_track->fmt.video.i_width <= 0 )
  1125.             p_track->fmt.video.i_width = p_track->i_width;
  1126.         if( p_track->fmt.video.i_height <= 0 )
  1127.             p_track->fmt.video.i_height = p_track->i_height;
  1128.         /* Find out apect ratio from display size */
  1129.         if( p_track->i_width > 0 && p_track->i_height > 0 &&
  1130.             /* Work-around buggy muxed files */
  1131.             p_sample->data.p_sample_vide->i_width != p_track->i_width )
  1132.             p_track->fmt.video.i_aspect =
  1133.                 VOUT_ASPECT_FACTOR * p_track->i_width / p_track->i_height;
  1134.         break;
  1135.     case( AUDIO_ES ):
  1136.         p_track->fmt.audio.i_channels =
  1137.             p_sample->data.p_sample_soun->i_channelcount;
  1138.         p_track->fmt.audio.i_rate =
  1139.             p_sample->data.p_sample_soun->i_sampleratehi;
  1140.         p_track->fmt.i_bitrate = p_sample->data.p_sample_soun->i_channelcount *
  1141.             p_sample->data.p_sample_soun->i_sampleratehi *
  1142.                 p_sample->data.p_sample_soun->i_samplesize;
  1143.         p_track->fmt.audio.i_bitspersample =
  1144.             p_sample->data.p_sample_soun->i_samplesize;
  1145.         break;
  1146.     default:
  1147.         break;
  1148.     }
  1149.     *pp_es = es_out_Add( p_demux->out, &p_track->fmt );
  1150.     return VLC_SUCCESS;
  1151. }
  1152. /* given a time it return sample/chunk
  1153.  * it also update elst field of the track
  1154.  */
  1155. static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
  1156.                                    int64_t i_start, uint32_t *pi_chunk,
  1157.                                    uint32_t *pi_sample )
  1158. {
  1159.     demux_sys_t *p_sys = p_demux->p_sys;
  1160.     MP4_Box_t   *p_stss;
  1161.     uint64_t     i_dts;
  1162.     unsigned int i_sample;
  1163.     unsigned int i_chunk;
  1164.     int          i_index;
  1165.     /* FIXME see if it's needed to check p_track->i_chunk_count */
  1166.     if( !p_track->b_ok || p_track->i_chunk_count == 0 )
  1167.     {
  1168.         return( VLC_EGENERIC );
  1169.     }
  1170.     /* handle elst (find the correct one) */
  1171.     MP4_TrackSetELST( p_demux, p_track, i_start );
  1172.     if( p_track->p_elst && p_track->p_elst->data.p_elst->i_entry_count > 0 )
  1173.     {
  1174.         MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
  1175.         int64_t i_mvt= i_start * p_sys->i_timescale / (int64_t)1000000;
  1176.         /* now calculate i_start for this elst */
  1177.         /* offset */
  1178.         i_start -= p_track->i_elst_time * I64C(1000000) / p_sys->i_timescale;
  1179.         if( i_start < 0 )
  1180.         {
  1181.             *pi_chunk = 0;
  1182.             *pi_sample= 0;
  1183.             return VLC_SUCCESS;
  1184.         }
  1185.         /* to track time scale */
  1186.         i_start  = i_start * p_track->i_timescale / (int64_t)1000000;
  1187.         /* add elst offset */
  1188.         if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
  1189.              elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
  1190.             elst->i_media_time[p_track->i_elst] > 0 )
  1191.         {
  1192.             i_start += elst->i_media_time[p_track->i_elst];
  1193.         }
  1194.         msg_Dbg( p_demux, "elst (%d) gives "I64Fd"ms (movie)-> "I64Fd
  1195.                  "ms (track)", p_track->i_elst,
  1196.                  i_mvt * 1000 / p_sys->i_timescale,
  1197.                  i_start * 1000 / p_track->i_timescale );
  1198.     }
  1199.     else
  1200.     {
  1201.         /* convert absolute time to in timescale unit */
  1202.         i_start = i_start * p_track->i_timescale / (int64_t)1000000;
  1203.     }
  1204.     /* we start from sample 0/chunk 0, hope it won't take too much time */
  1205.     /* *** find good chunk *** */
  1206.     for( i_chunk = 0; ; i_chunk++ )
  1207.     {
  1208.         if( i_chunk + 1 >= p_track->i_chunk_count )
  1209.         {
  1210.             /* at the end and can't check if i_start in this chunk,
  1211.                it will be check while searching i_sample */
  1212.             i_chunk = p_track->i_chunk_count - 1;
  1213.             break;
  1214.         }
  1215.         if( i_start >= p_track->chunk[i_chunk].i_first_dts &&
  1216.             i_start <  p_track->chunk[i_chunk + 1].i_first_dts )
  1217.         {
  1218.             break;
  1219.         }
  1220.     }
  1221.     /* *** find sample in the chunk *** */
  1222.     i_sample = p_track->chunk[i_chunk].i_sample_first;
  1223.     i_dts    = p_track->chunk[i_chunk].i_first_dts;
  1224.     for( i_index = 0; i_sample < p_track->chunk[i_chunk].i_sample_count; )
  1225.     {
  1226.         if( i_dts +
  1227.             p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
  1228.             p_track->chunk[i_chunk].p_sample_delta_dts[i_index] < i_start )
  1229.         {
  1230.             i_dts    +=
  1231.                 p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
  1232.                 p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
  1233.             i_sample += p_track->chunk[i_chunk].p_sample_count_dts[i_index];
  1234.             i_index++;
  1235.         }
  1236.         else
  1237.         {
  1238.             if( p_track->chunk[i_chunk].p_sample_delta_dts[i_index] <= 0 )
  1239.             {
  1240.                 break;
  1241.             }
  1242.             i_sample += ( i_start - i_dts ) /
  1243.                 p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
  1244.             break;
  1245.         }
  1246.     }
  1247.     if( i_sample >= p_track->i_sample_count )
  1248.     {
  1249.         msg_Warn( p_demux, "track[Id 0x%x] will be disabled "
  1250.                   "(seeking too far) chunk=%d sample=%d",
  1251.                   p_track->i_track_ID, i_chunk, i_sample );
  1252.         return( VLC_EGENERIC );
  1253.     }
  1254.     /* *** Try to find nearest sync points *** */
  1255.     if( ( p_stss = MP4_BoxGet( p_track->p_stbl, "stss" ) ) )
  1256.     {
  1257.         unsigned int i_index;
  1258.         msg_Dbg( p_demux,
  1259.                     "track[Id 0x%x] using Sync Sample Box (stss)",
  1260.                     p_track->i_track_ID );
  1261.         for( i_index = 0; i_index < p_stss->data.p_stss->i_entry_count; i_index++ )
  1262.         {
  1263.             if( p_stss->data.p_stss->i_sample_number[i_index] >= i_sample )
  1264.             {
  1265.                 if( i_index > 0 )
  1266.                 {
  1267.                     msg_Dbg( p_demux, "stts gives %d --> %d (sample number)",
  1268.                             i_sample,
  1269.                             p_stss->data.p_stss->i_sample_number[i_index-1] );
  1270.                     i_sample = p_stss->data.p_stss->i_sample_number[i_index-1];
  1271.                     /* new i_sample is less than old so i_chunk can only decreased */
  1272.                     while( i_chunk > 0 &&
  1273.                             i_sample < p_track->chunk[i_chunk].i_sample_first )
  1274.                     {
  1275.                         i_chunk--;
  1276.                     }
  1277.                 }
  1278.                 else
  1279.                 {
  1280.                     msg_Dbg( p_demux, "stts gives %d --> %d (sample number)",
  1281.                             i_sample,
  1282.                             p_stss->data.p_stss->i_sample_number[i_index] );
  1283.                     i_sample = p_stss->data.p_stss->i_sample_number[i_index];
  1284.                     /* new i_sample is more than old so i_chunk can only increased */
  1285.                     while( i_chunk < p_track->i_chunk_count - 1 &&
  1286.                            i_sample >= p_track->chunk[i_chunk].i_sample_first +
  1287.                              p_track->chunk[i_chunk].i_sample_count )
  1288.                     {
  1289.                         i_chunk++;
  1290.                     }
  1291.                 }
  1292.                 break;
  1293.             }
  1294.         }
  1295.     }
  1296.     else
  1297.     {
  1298.         msg_Dbg( p_demux, "track[Id 0x%x] does not provide Sync "
  1299.                  "Sample Box (stss)", p_track->i_track_ID );
  1300.     }
  1301.     *pi_chunk  = i_chunk;
  1302.     *pi_sample = i_sample;
  1303.     return VLC_SUCCESS;
  1304. }
  1305. static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
  1306.                                  unsigned int i_chunk, unsigned int i_sample )
  1307. {
  1308.     vlc_bool_t b_reselect = VLC_FALSE;
  1309.     /* now see if actual es is ok */
  1310.     if( p_track->i_chunk < 0 ||
  1311.         p_track->i_chunk >= p_track->i_chunk_count - 1 ||
  1312.         p_track->chunk[p_track->i_chunk].i_sample_description_index !=
  1313.             p_track->chunk[i_chunk].i_sample_description_index )
  1314.     {
  1315.         msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",
  1316.                   p_track->i_track_ID );
  1317.         es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
  1318.                         p_track->p_es, &b_reselect );
  1319.         es_out_Del( p_demux->out, p_track->p_es );
  1320.         p_track->p_es = NULL;
  1321.         if( TrackCreateES( p_demux, p_track, i_chunk, &p_track->p_es ) )
  1322.         {
  1323.             msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
  1324.                      p_track->i_track_ID );
  1325.             p_track->b_ok       = VLC_FALSE;
  1326.             p_track->b_selected = VLC_FALSE;
  1327.             return VLC_EGENERIC;
  1328.         }
  1329.     }
  1330.     /* select again the new decoder */
  1331.     if( b_reselect )
  1332.     {
  1333.         es_out_Control( p_demux->out, ES_OUT_SET_ES, p_track->p_es );
  1334.     }
  1335.     p_track->i_chunk    = i_chunk;
  1336.     p_track->i_sample   = i_sample;
  1337.     return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;
  1338. }
  1339. /****************************************************************************
  1340.  * MP4_TrackCreate:
  1341.  ****************************************************************************
  1342.  * Parse track information and create all needed data to run a track
  1343.  * If it succeed b_ok is set to 1 else to 0
  1344.  ****************************************************************************/
  1345. static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
  1346.                              MP4_Box_t *p_box_trak )
  1347. {
  1348.     demux_sys_t *p_sys = p_demux->p_sys;
  1349.     MP4_Box_t *p_tkhd = MP4_BoxGet( p_box_trak, "tkhd" );
  1350.     MP4_Box_t *p_tref = MP4_BoxGet( p_box_trak, "tref" );
  1351.     MP4_Box_t *p_elst;
  1352.     MP4_Box_t *p_mdhd;
  1353.     MP4_Box_t *p_udta;
  1354.     MP4_Box_t *p_hdlr;
  1355.     MP4_Box_t *p_vmhd;
  1356.     MP4_Box_t *p_smhd;
  1357.     MP4_Box_t *p_drms;
  1358.     unsigned int i;
  1359.     char language[4];
  1360.     /* hint track unsuported */
  1361.     /* set default value (-> track unusable) */
  1362.     p_track->b_ok       = VLC_FALSE;
  1363.     p_track->b_enable   = VLC_FALSE;
  1364.     p_track->b_selected = VLC_FALSE;
  1365.     es_format_Init( &p_track->fmt, UNKNOWN_ES, 0 );
  1366.     if( !p_tkhd )
  1367.     {
  1368.         return;
  1369.     }
  1370.     /* do we launch this track by default ? */
  1371.     p_track->b_enable =
  1372.         ( ( p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED ) != 0 );
  1373.     p_track->i_track_ID = p_tkhd->data.p_tkhd->i_track_ID;
  1374.     p_track->i_width = p_tkhd->data.p_tkhd->i_width / 65536;
  1375.     p_track->i_height = p_tkhd->data.p_tkhd->i_height / 65536;
  1376.     if( p_tref )
  1377.     {
  1378. /*        msg_Warn( p_demux, "unhandled box: tref --> FIXME" ); */
  1379.     }
  1380.     p_mdhd = MP4_BoxGet( p_box_trak, "mdia/mdhd" );
  1381.     p_hdlr = MP4_BoxGet( p_box_trak, "mdia/hdlr" );
  1382.     if( ( !p_mdhd )||( !p_hdlr ) )
  1383.     {
  1384.         return;
  1385.     }
  1386.     p_track->i_timescale = p_mdhd->data.p_mdhd->i_timescale;
  1387.     for( i = 0; i < 3; i++ )
  1388.     {
  1389.         language[i] = p_mdhd->data.p_mdhd->i_language[i];
  1390.     }
  1391.     language[3] = '';
  1392.     switch( p_hdlr->data.p_hdlr->i_handler_type )
  1393.     {
  1394.         case( FOURCC_soun ):
  1395.             if( !( p_smhd = MP4_BoxGet( p_box_trak, "mdia/minf/smhd" ) ) )
  1396.             {
  1397.                 return;
  1398.             }
  1399.             p_track->fmt.i_cat = AUDIO_ES;
  1400.             break;
  1401.         case( FOURCC_vide ):
  1402.             if( !( p_vmhd = MP4_BoxGet( p_box_trak, "mdia/minf/vmhd" ) ) )
  1403.             {
  1404.                 return;
  1405.             }
  1406.             p_track->fmt.i_cat = VIDEO_ES;
  1407.             break;
  1408.         case( FOURCC_text ):
  1409.         case( FOURCC_subp ):
  1410.             p_track->fmt.i_cat = SPU_ES;
  1411.             break;
  1412.         default:
  1413.             return;
  1414.     }
  1415.     p_track->i_elst = 0;
  1416.     p_track->i_elst_time = 0;
  1417.     if( ( p_track->p_elst = p_elst = MP4_BoxGet( p_box_trak, "edts/elst" ) ) )
  1418.     {
  1419.         MP4_Box_data_elst_t *elst = p_elst->data.p_elst;
  1420.         int i;
  1421.         msg_Warn( p_demux, "elst box found" );
  1422.         for( i = 0; i < elst->i_entry_count; i++ )
  1423.         {
  1424.             msg_Dbg( p_demux, "   - [%d] duration="I64Fd"ms media time="I64Fd"ms) rate=%d.%d",
  1425.                      i,
  1426.                      elst->i_segment_duration[i] * 1000 / p_sys->i_timescale,
  1427.                      elst->i_media_time[i] >= 0 ?
  1428.                         elst->i_media_time[i] * 1000 / p_track->i_timescale : -1,
  1429.                      elst->i_media_rate_integer[i],
  1430.                      elst->i_media_rate_fraction[i] );
  1431.         }
  1432.     }
  1433. /*  TODO
  1434.     add support for:
  1435.     p_dinf = MP4_BoxGet( p_minf, "dinf" );
  1436. */
  1437.     if( !( p_track->p_stbl = MP4_BoxGet( p_box_trak,"mdia/minf/stbl" ) ) ||
  1438.         !( p_track->p_stsd = MP4_BoxGet( p_box_trak,"mdia/minf/stbl/stsd") ) )
  1439.     {
  1440.         return;
  1441.     }
  1442.     p_drms = MP4_BoxGet( p_track->p_stsd, "drms" );
  1443.     p_track->b_drms = p_drms != NULL;
  1444.     p_track->p_drms = p_track->b_drms ?
  1445.         p_drms->data.p_sample_soun->p_drms : NULL;
  1446.     /* Set language */
  1447.     if( strcmp( language, "```" ) && strcmp( language, "und" ) )
  1448.     {
  1449.         p_track->fmt.psz_language = strdup( language );
  1450.     }
  1451.     p_udta = MP4_BoxGet( p_box_trak, "udta" );
  1452.     if( p_udta )
  1453.     {
  1454.         MP4_Box_t *p_0xa9xxx;
  1455.         for( p_0xa9xxx = p_udta->p_first; p_0xa9xxx != NULL;
  1456.                  p_0xa9xxx = p_0xa9xxx->p_next )
  1457.         {
  1458.             switch( p_0xa9xxx->i_type )
  1459.             {
  1460.                 case FOURCC_0xa9nam:
  1461.                     p_track->fmt.psz_description = strdup( p_0xa9xxx->data.p_0xa9xxx->psz_text );
  1462.                     break;
  1463.             }
  1464.         }
  1465.     }
  1466.     /* fxi i_timescale for AUDIO_ES with i_qt_version == 0 */
  1467.     if( p_track->fmt.i_cat == AUDIO_ES ) //&& p_track->i_sample_size == 1 )
  1468.     {
  1469.         MP4_Box_t *p_sample;
  1470.         p_sample = MP4_BoxGet(  p_track->p_stsd, "[0]" );
  1471.         if( p_sample && p_sample->data.p_sample_soun)
  1472.         {
  1473.             MP4_Box_data_sample_soun_t *p_soun = p_sample->data.p_sample_soun;
  1474.             if( p_soun->i_qt_version == 0 &&
  1475.                 p_track->i_timescale != p_soun->i_sampleratehi )
  1476.             {
  1477.                 msg_Warn( p_demux,
  1478.                           "i_timescale ("I64Fu") != i_sampleratehi (%u) with "
  1479.                           "qt_version == 0n"
  1480.                           "Making both equal. (report any problem)",
  1481.                           p_track->i_timescale, p_soun->i_sampleratehi );
  1482.                 if( p_soun->i_sampleratehi )
  1483.                     p_track->i_timescale = p_soun->i_sampleratehi;
  1484.                 else
  1485.                     p_soun->i_sampleratehi = p_track->i_timescale;
  1486.             }
  1487.         }
  1488.     }
  1489.     /* Create chunk index table and sample index table */
  1490.     if( TrackCreateChunksIndex( p_demux,p_track  ) ||
  1491.         TrackCreateSamplesIndex( p_demux, p_track ) )
  1492.     {
  1493.         return; /* cannot create chunks index */
  1494.     }
  1495.     p_track->i_chunk  = 0;
  1496.     p_track->i_sample = 0;
  1497.     /* now create es */
  1498.     if( TrackCreateES( p_demux,
  1499.                        p_track, p_track->i_chunk,
  1500.                        &p_track->p_es ) )
  1501.     {
  1502.         msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
  1503.                  p_track->i_track_ID );
  1504.         return;
  1505.     }
  1506. #if 0
  1507.     {
  1508.         int i;
  1509.         for( i = 0; i < p_track->i_chunk_count; i++ )
  1510.         {
  1511.             fprintf( stderr, "%-5d sample_count=%d pts=%lldn",
  1512.                      i, p_track->chunk[i].i_sample_count,
  1513.                      p_track->chunk[i].i_first_dts );
  1514.         }
  1515.     }
  1516. #endif
  1517.     p_track->b_ok = VLC_TRUE;
  1518. }
  1519. /****************************************************************************
  1520.  * MP4_TrackDestroy:
  1521.  ****************************************************************************
  1522.  * Destroy a track created by MP4_TrackCreate.
  1523.  ****************************************************************************/
  1524. static void MP4_TrackDestroy( demux_t *p_demux, mp4_track_t *p_track )
  1525. {
  1526.     unsigned int i_chunk;
  1527.     p_track->b_ok = VLC_FALSE;
  1528.     p_track->b_enable   = VLC_FALSE;
  1529.     p_track->b_selected = VLC_FALSE;
  1530.     es_format_Clean( &p_track->fmt );
  1531.     for( i_chunk = 0; i_chunk < p_track->i_chunk_count; i_chunk++ )
  1532.     {
  1533.         if( p_track->chunk )
  1534.         {
  1535.            FREE(p_track->chunk[i_chunk].p_sample_count_dts);
  1536.            FREE(p_track->chunk[i_chunk].p_sample_delta_dts );
  1537.         }
  1538.     }
  1539.     FREE( p_track->chunk );
  1540.     if( !p_track->i_sample_size )
  1541.     {
  1542.         FREE( p_track->p_sample_size );
  1543.     }
  1544. }
  1545. static int MP4_TrackSelect( demux_t *p_demux, mp4_track_t *p_track,
  1546.                             mtime_t i_start )
  1547. {
  1548.     if( !p_track->b_ok )
  1549.     {
  1550.         return VLC_EGENERIC;
  1551.     }
  1552.     if( p_track->b_selected )
  1553.     {
  1554.         msg_Warn( p_demux, "track[Id 0x%x] already selected",
  1555.                   p_track->i_track_ID );
  1556.         return VLC_SUCCESS;
  1557.     }
  1558.     return MP4_TrackSeek( p_demux, p_track, i_start );
  1559. }
  1560. static void MP4_TrackUnselect( demux_t *p_demux, mp4_track_t *p_track )
  1561. {
  1562.     if( !p_track->b_ok )
  1563.     {
  1564.         return;
  1565.     }
  1566.     if( !p_track->b_selected )
  1567.     {
  1568.         msg_Warn( p_demux, "track[Id 0x%x] already unselected",
  1569.                   p_track->i_track_ID );
  1570.         return;
  1571.     }
  1572.     if( p_track->p_es )
  1573.     {
  1574.         es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE,
  1575.                         p_track->p_es, VLC_FALSE );
  1576.     }
  1577.     p_track->b_selected = VLC_FALSE;
  1578. }
  1579. static int MP4_TrackSeek( demux_t *p_demux, mp4_track_t *p_track,
  1580.                           mtime_t i_start )
  1581. {
  1582.     uint32_t i_chunk;
  1583.     uint32_t i_sample;
  1584.     if( !p_track->b_ok )
  1585.     {
  1586.         return( VLC_EGENERIC );
  1587.     }
  1588.     p_track->b_selected = VLC_FALSE;
  1589.     if( TrackTimeToSampleChunk( p_demux, p_track, i_start,
  1590.                                 &i_chunk, &i_sample ) )
  1591.     {
  1592.         msg_Warn( p_demux, "cannot select track[Id 0x%x]",
  1593.                   p_track->i_track_ID );
  1594.         return( VLC_EGENERIC );
  1595.     }
  1596.     p_track->b_selected = VLC_TRUE;
  1597.     if( TrackGotoChunkSample( p_demux, p_track, i_chunk, i_sample ) ==
  1598.         VLC_SUCCESS )
  1599.     {
  1600.         p_track->b_selected = VLC_TRUE;
  1601.     }
  1602.     return( p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC );
  1603. }
  1604. /*
  1605.  * 3 types: for audio
  1606.  * 
  1607.  */
  1608. #define QT_V0_MAX_SAMPLES    1500
  1609. static int MP4_TrackSampleSize( mp4_track_t *p_track )
  1610. {
  1611.     int i_size;
  1612.     MP4_Box_data_sample_soun_t *p_soun;
  1613.     if( p_track->i_sample_size == 0 )
  1614.     {
  1615.         /* most simple case */
  1616.         return( p_track->p_sample_size[p_track->i_sample] );
  1617.     }
  1618.     if( p_track->fmt.i_cat != AUDIO_ES )
  1619.     {
  1620.         return( p_track->i_sample_size );
  1621.     }
  1622.     if( p_track->i_sample_size != 1 )
  1623.     {
  1624.         //msg_Warn( p_demux, "SampleSize != 1" );
  1625.         return( p_track->i_sample_size );
  1626.     }
  1627.     p_soun = p_track->p_sample->data.p_sample_soun;
  1628.     if( p_soun->i_qt_version == 1 )
  1629.     {
  1630.         i_size = p_track->chunk[p_track->i_chunk].i_sample_count / p_soun->i_sample_per_packet * p_soun->i_bytes_per_frame;
  1631.     }
  1632.     else
  1633.     {
  1634.         /* FIXME */
  1635.         int i_samples = p_track->chunk[p_track->i_chunk].i_sample_count -
  1636.                 ( p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first );
  1637.         if( i_samples > QT_V0_MAX_SAMPLES )
  1638.         {
  1639.             i_samples = QT_V0_MAX_SAMPLES;
  1640.         }
  1641.         i_size = i_samples * p_soun->i_channelcount * p_soun->i_samplesize / 8;
  1642.     }
  1643.     //fprintf( stderr, "size=%dn", i_size );
  1644.     return( i_size );
  1645. }
  1646. static uint64_t MP4_TrackGetPos( mp4_track_t *p_track )
  1647. {
  1648.     unsigned int i_sample;
  1649.     uint64_t i_pos;
  1650.     i_pos = p_track->chunk[p_track->i_chunk].i_offset;
  1651.     if( p_track->i_sample_size )
  1652.     {
  1653.         MP4_Box_data_sample_soun_t *p_soun = p_track->p_sample->data.p_sample_soun;
  1654.         if( p_soun->i_qt_version == 0 )
  1655.         {
  1656.             i_pos += ( p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first ) *
  1657.                         p_soun->i_channelcount * p_soun->i_samplesize / 8;
  1658.         }
  1659.         else
  1660.         {
  1661.             /* we read chunk by chunk */
  1662.             i_pos += 0;
  1663.         }
  1664.     }
  1665.     else
  1666.     {
  1667.         for( i_sample = p_track->chunk[p_track->i_chunk].i_sample_first;
  1668.                 i_sample < p_track->i_sample; i_sample++ )
  1669.         {
  1670.             i_pos += p_track->p_sample_size[i_sample];
  1671.         }
  1672.     }
  1673.     return( i_pos );
  1674. }
  1675. static int  MP4_TrackNextSample( demux_t     *p_demux,
  1676.                                  mp4_track_t   *p_track )
  1677. {
  1678.     if( p_track->fmt.i_cat == AUDIO_ES &&
  1679.         p_track->i_sample_size != 0 )
  1680.     {
  1681.         MP4_Box_data_sample_soun_t *p_soun;
  1682.         p_soun = p_track->p_sample->data.p_sample_soun;
  1683.         if( p_soun->i_qt_version == 1 )
  1684.         {
  1685.             /* chunk by chunk */
  1686.             p_track->i_sample =
  1687.                 p_track->chunk[p_track->i_chunk].i_sample_first +
  1688.                 p_track->chunk[p_track->i_chunk].i_sample_count;
  1689.         }
  1690.         else
  1691.         {
  1692.             /* FIXME */
  1693.             p_track->i_sample += QT_V0_MAX_SAMPLES;
  1694.             if( p_track->i_sample > p_track->chunk[p_track->i_chunk].i_sample_first + p_track->chunk[p_track->i_chunk].i_sample_count )
  1695.             {
  1696.                 p_track->i_sample =
  1697.                     p_track->chunk[p_track->i_chunk].i_sample_first +
  1698.                     p_track->chunk[p_track->i_chunk].i_sample_count;
  1699.             }
  1700.         }
  1701.     }
  1702.     else
  1703.     {
  1704.         p_track->i_sample++;
  1705.     }
  1706.     if( p_track->i_sample >= p_track->i_sample_count )
  1707.     {
  1708.         /* we have reach end of the track so free decoder stuff */
  1709.         msg_Warn( p_demux, "track[0x%x] will be disabled", p_track->i_track_ID );
  1710.         MP4_TrackUnselect( p_demux, p_track );
  1711.         return VLC_EGENERIC;
  1712.     }
  1713.     /* Have we changed chunk ? */
  1714.     if( p_track->i_sample >=
  1715.             p_track->chunk[p_track->i_chunk].i_sample_first +
  1716.             p_track->chunk[p_track->i_chunk].i_sample_count )
  1717.     {
  1718.         if( TrackGotoChunkSample( p_demux, p_track, p_track->i_chunk + 1,
  1719.                                   p_track->i_sample ) )
  1720.         {
  1721.             msg_Warn( p_demux, "track[0x%x] will be disabled "
  1722.                       "(cannot restart decoder)", p_track->i_track_ID );
  1723.             MP4_TrackUnselect( p_demux, p_track );
  1724.             return VLC_EGENERIC;
  1725.         }
  1726.     }
  1727.     /* Have we changed elst */
  1728.     if( p_track->p_elst && p_track->p_elst->data.p_elst->i_entry_count > 0 )
  1729.     {
  1730.         demux_sys_t *p_sys = p_demux->p_sys;
  1731.         MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
  1732.         int64_t i_mvt = MP4_TrackGetPTS( p_demux, p_track ) *
  1733.                         p_sys->i_timescale / (int64_t)1000000;
  1734.         if( p_track->i_elst < elst->i_entry_count &&
  1735.             i_mvt >= p_track->i_elst_time +
  1736.                      elst->i_segment_duration[p_track->i_elst] )
  1737.         {
  1738.             MP4_TrackSetELST( p_demux, p_track,
  1739.                               MP4_TrackGetPTS( p_demux, p_track ) );
  1740.         }
  1741.     }
  1742.     return VLC_SUCCESS;
  1743. }
  1744. static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk,
  1745.                               int64_t i_time )
  1746. {
  1747.     demux_sys_t *p_sys = p_demux->p_sys;
  1748.     int         i_elst_last = tk->i_elst;
  1749.     /* handle elst (find the correct one) */
  1750.     tk->i_elst      = 0;
  1751.     tk->i_elst_time = 0;
  1752.     if( tk->p_elst && tk->p_elst->data.p_elst->i_entry_count > 0 )
  1753.     {
  1754.         MP4_Box_data_elst_t *elst = tk->p_elst->data.p_elst;
  1755.         int64_t i_mvt= i_time * p_sys->i_timescale / (int64_t)1000000;
  1756.         for( tk->i_elst = 0; tk->i_elst < elst->i_entry_count; tk->i_elst++ )
  1757.         {
  1758.             mtime_t i_dur = elst->i_segment_duration[tk->i_elst];
  1759.             if( tk->i_elst_time <= i_mvt && i_mvt < tk->i_elst_time + i_dur )
  1760.             {
  1761.                 break;
  1762.             }
  1763.             tk->i_elst_time += i_dur;
  1764.         }
  1765.         if( tk->i_elst >= elst->i_entry_count )
  1766.         {
  1767.             /* msg_Dbg( p_demux, "invalid number of entry in elst" ); */
  1768.             tk->i_elst = elst->i_entry_count - 1;
  1769.             tk->i_elst_time -= elst->i_segment_duration[tk->i_elst];
  1770.         }
  1771.         if( elst->i_media_time[tk->i_elst] < 0 )
  1772.         {
  1773.             /* track offset */
  1774.             tk->i_elst_time += elst->i_segment_duration[tk->i_elst];
  1775.         }
  1776.     }
  1777.     if( i_elst_last != tk->i_elst )
  1778.     {
  1779.         msg_Warn( p_demux, "elst old=%d new=%d", i_elst_last, tk->i_elst );
  1780.     }
  1781. }