[vlc-devel] [PATCH 2/3] demux/mp4: prepare next patch

Frédéric Yhuel fyhuel at viotech.net
Fri Mar 16 15:23:31 CET 2012


- move inline functions and structure definitions in a new file mp4.h
- rename a mp4_track_t attribute (chunk -> chunks)
---
 modules/demux/mp4/Modules.am |    1 +
 modules/demux/mp4/mp4.c      |  315 +++++++++--------------------------------
 modules/demux/mp4/mp4.h      |  218 +++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+), 246 deletions(-)
 create mode 100644 modules/demux/mp4/mp4.h

diff --git a/modules/demux/mp4/Modules.am b/modules/demux/mp4/Modules.am
index 17fdb73..7c2c3d8 100644
--- a/modules/demux/mp4/Modules.am
+++ b/modules/demux/mp4/Modules.am
@@ -2,6 +2,7 @@ SOURCES_mp4 = \
 	mp4.c \
 	libmp4.c \
 	libmp4.h \
+	mp4.h \
 	drms.c \
 	drms.h \
 	drmstables.h \
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 6fc3721..d565254 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -28,15 +28,7 @@
 # include "config.h"
 #endif
 
-#include <vlc_common.h>
-#include <vlc_plugin.h>
-
-#include <vlc_demux.h>
-#include <vlc_charset.h>                           /* EnsureUTF8 */
-#include <vlc_meta.h>                              /* vlc_meta_t, vlc_meta_ */
-#include <vlc_input.h>
-
-#include "libmp4.h"
+#include "mp4.h"
 #include "drms.h"
 #include "id3genres.h"                             /* for ATOM_gnre */
 
@@ -63,106 +55,6 @@ static int   DemuxRef( demux_t *p_demux ){ (void)p_demux; return 0;}
 static int   Seek    ( demux_t *, mtime_t );
 static int   Control ( demux_t *, int, va_list );
 
-/* Contain all information about a chunk */
-typedef struct
-{
-    uint64_t     i_offset; /* absolute position of this chunk in the file */
-    uint32_t     i_sample_description_index; /* index for SampleEntry to use */
-    uint32_t     i_sample_count; /* how many samples in this chunk */
-    uint32_t     i_sample_first; /* index of the first sample in this chunk */
-
-    /* now provide way to calculate pts, dts, and offset without too
-        much memory and with fast access */
-
-    /* with this we can calculate dts/pts without waste memory */
-    uint64_t     i_first_dts;   /* DTS of the first sample */
-    uint64_t     i_last_dts;    /* DTS of the last sample */
-    uint32_t     *p_sample_count_dts;
-    uint32_t     *p_sample_delta_dts;   /* dts delta */
-
-    uint32_t     *p_sample_count_pts;
-    int32_t      *p_sample_offset_pts;  /* pts-dts */
-
-    /* TODO if needed add pts
-        but quickly *add* support for edts and seeking */
-
-} mp4_chunk_t;
-
- /* Contain all needed information for read all track with vlc */
-typedef struct
-{
-    unsigned int i_track_ID;/* this should be unique */
-
-    int b_ok;               /* The track is usable */
-    int b_enable;           /* is the trak enable by default */
-    bool b_selected;  /* is the trak being played */
-    bool b_chapter;   /* True when used for chapter only */
-
-    bool b_mac_encoding;
-
-    es_format_t fmt;
-    es_out_id_t *p_es;
-
-    /* display size only ! */
-    int i_width;
-    int i_height;
-
-    /* more internal data */
-    uint64_t        i_timescale;    /* time scale for this track only */
-
-    /* elst */
-    int             i_elst;         /* current elst */
-    int64_t         i_elst_time;    /* current elst start time (in movie time scale)*/
-    MP4_Box_t       *p_elst;        /* elst (could be NULL) */
-
-    /* give the next sample to read, i_chunk is to find quickly where
-      the sample is located */
-    uint32_t         i_sample;       /* next sample to read */
-    uint32_t         i_chunk;        /* chunk where next sample is stored */
-    /* total count of chunk and sample */
-    uint32_t         i_chunk_count;
-    uint32_t         i_sample_count;
-
-    mp4_chunk_t    *chunk; /* always defined  for each chunk */
-
-    /* sample size, p_sample_size defined only if i_sample_size == 0
-        else i_sample_size is size for all sample */
-    uint32_t         i_sample_size;
-    uint32_t         *p_sample_size; /* XXX perhaps add file offset if take
-                                    too much time to do sumations each time*/
-
-    MP4_Box_t *p_stbl;  /* will contain all timing information */
-    MP4_Box_t *p_stsd;  /* will contain all data to initialize decoder */
-    MP4_Box_t *p_sample;/* point on actual sdsd */
-
-    bool b_drms;
-    void      *p_drms;
-    MP4_Box_t *p_skcr;
-
-} mp4_track_t;
-
-
-struct demux_sys_t
-{
-    MP4_Box_t    *p_root;      /* container for the whole file */
-
-    mtime_t      i_pcr;
-
-    uint64_t     i_time;         /* time position of the presentation
-                                  * in movie timescale */
-    uint64_t     i_timescale;    /* movie time scale */
-    uint64_t     i_duration;     /* movie duration */
-    unsigned int i_tracks;       /* number of tracks */
-    mp4_track_t  *track;         /* array of track */
-    float        f_fps;          /* number of frame per seconds */
-
-    /* */
-    MP4_Box_t    *p_tref_chap;
-
-    /* */
-    input_title_t *p_title;
-};
-
 /*****************************************************************************
  * Declaration of local function
  *****************************************************************************/
@@ -170,8 +62,6 @@ static void MP4_TrackCreate ( demux_t *, mp4_track_t *, MP4_Box_t  *, bool b_for
 static void MP4_TrackDestroy(  mp4_track_t * );
 
 static int  MP4_TrackSelect ( demux_t *, mp4_track_t *, mtime_t );
-static void MP4_TrackUnselect(demux_t *, mp4_track_t * );
-
 static int  MP4_TrackSeek   ( demux_t *, mp4_track_t *, mtime_t );
 
 static uint64_t MP4_TrackGetPos    ( mp4_track_t * );
@@ -182,81 +72,6 @@ static void     MP4_TrackSetELST( demux_t *, mp4_track_t *, int64_t );
 static void     MP4_UpdateSeekpoint( demux_t * );
 static const char *MP4_ConvertMacCode( uint16_t );
 
-/* Return time in s of a track */
-static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
-{
-#define chunk p_track->chunk[p_track->i_chunk]
-
-    unsigned int i_index = 0;
-    unsigned int i_sample = p_track->i_sample - chunk.i_sample_first;
-    int64_t i_dts = chunk.i_first_dts;
-
-    while( i_sample > 0 )
-    {
-        if( i_sample > chunk.p_sample_count_dts[i_index] )
-        {
-            i_dts += chunk.p_sample_count_dts[i_index] *
-                chunk.p_sample_delta_dts[i_index];
-            i_sample -= chunk.p_sample_count_dts[i_index];
-            i_index++;
-        }
-        else
-        {
-            i_dts += i_sample * chunk.p_sample_delta_dts[i_index];
-            break;
-        }
-    }
-
-#undef chunk
-
-    /* now handle elst */
-    if( p_track->p_elst )
-    {
-        demux_sys_t         *p_sys = p_demux->p_sys;
-        MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
-
-        /* convert to offset */
-        if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
-              elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
-            elst->i_media_time[p_track->i_elst] > 0 )
-        {
-            i_dts -= elst->i_media_time[p_track->i_elst];
-        }
-
-        /* add i_elst_time */
-        i_dts += p_track->i_elst_time * p_track->i_timescale /
-            p_sys->i_timescale;
-
-        if( i_dts < 0 ) i_dts = 0;
-    }
-
-    return INT64_C(1000000) * i_dts / p_track->i_timescale;
-}
-
-static inline int64_t MP4_TrackGetPTSDelta( mp4_track_t *p_track )
-{
-    mp4_chunk_t *ck = &p_track->chunk[p_track->i_chunk];
-    unsigned int i_index = 0;
-    unsigned int i_sample = p_track->i_sample - ck->i_sample_first;
-
-    if( ck->p_sample_count_pts == NULL || ck->p_sample_offset_pts == NULL )
-        return -1;
-
-    for( i_index = 0;; i_index++ )
-    {
-        if( i_sample < ck->p_sample_count_pts[i_index] )
-            return ck->p_sample_offset_pts[i_index] * INT64_C(1000000) /
-                   (int64_t)p_track->i_timescale;
-
-        i_sample -= ck->p_sample_count_pts[i_index];
-    }
-}
-
-static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
-{
-    return INT64_C(1000000) * p_sys->i_time / p_sys->i_timescale;
-}
-
 static void LoadChapter( demux_t  *p_demux );
 
 /*****************************************************************************
@@ -737,7 +552,7 @@ static int Demux( demux_t *p_demux )
                 /* dts */
                 p_block->i_dts = VLC_TS_0 + MP4_TrackGetDTS( p_demux, tk );
                 /* pts */
-                i_delta = MP4_TrackGetPTSDelta( tk );
+                i_delta = MP4_TrackGetPTSDelta( p_demux, tk );
                 if( i_delta != -1 )
                     p_block->i_pts = p_block->i_dts + i_delta;
                 else if( tk->fmt.i_cat != VIDEO_ES )
@@ -1101,7 +916,7 @@ static void LoadChapterApple( demux_t  *p_demux, mp4_track_t *tk )
     for( tk->i_sample = 0; tk->i_sample < tk->i_sample_count; tk->i_sample++ )
     {
         const int64_t i_dts = MP4_TrackGetDTS( p_demux, tk );
-        const int64_t i_pts_delta = MP4_TrackGetPTSDelta( tk );
+        const int64_t i_pts_delta = MP4_TrackGetPTSDelta( p_demux, tk );
         const unsigned int i_size = MP4_TrackSampleSize( tk );
 
         if( i_size > 0 && !stream_Seek( p_demux->s, MP4_TrackGetPos( tk ) ) )
@@ -1124,8 +939,8 @@ static void LoadChapterApple( demux_t  *p_demux, mp4_track_t *tk )
                 TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
             }
         }
-        if( tk->i_sample+1 >= tk->chunk[tk->i_chunk].i_sample_first +
-                              tk->chunk[tk->i_chunk].i_sample_count )
+        if( tk->i_sample+1 >= tk->chunks[tk->i_chunk].i_sample_first +
+                              tk->chunks[tk->i_chunk].i_sample_count )
             tk->i_chunk++;
     }
 }
@@ -1192,9 +1007,9 @@ static int TrackCreateChunksIndex( demux_t *p_demux,
         msg_Warn( p_demux, "no chunk defined" );
         return( VLC_EGENERIC );
     }
-    p_demux_track->chunk = calloc( p_demux_track->i_chunk_count,
+    p_demux_track->chunks = calloc( p_demux_track->i_chunk_count,
                                    sizeof( mp4_chunk_t ) );
-    if( p_demux_track->chunk == NULL )
+    if( p_demux_track->chunks == NULL )
     {
         return VLC_ENOMEM;
     }
@@ -1202,7 +1017,7 @@ static int TrackCreateChunksIndex( demux_t *p_demux,
     /* first we read chunk offset */
     for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
     {
-        mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
+        mp4_chunk_t *ck = &p_demux_track->chunks[i_chunk];
 
         ck->i_offset = p_co64->data.p_co64->i_chunk_offset[i_chunk];
 
@@ -1235,20 +1050,20 @@ static int TrackCreateChunksIndex( demux_t *p_demux,
                 return VLC_EGENERIC;
             }
 
-            p_demux_track->chunk[i_chunk].i_sample_description_index =
+            p_demux_track->chunks[i_chunk].i_sample_description_index =
                     p_stsc->data.p_stsc->i_sample_description_index[i_index];
-            p_demux_track->chunk[i_chunk].i_sample_count =
+            p_demux_track->chunks[i_chunk].i_sample_count =
                     p_stsc->data.p_stsc->i_samples_per_chunk[i_index];
         }
         i_last = p_stsc->data.p_stsc->i_first_chunk[i_index] - 1;
     }
 
-    p_demux_track->chunk[0].i_sample_first = 0;
+    p_demux_track->chunks[0].i_sample_first = 0;
     for( i_chunk = 1; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
     {
-        p_demux_track->chunk[i_chunk].i_sample_first =
-            p_demux_track->chunk[i_chunk-1].i_sample_first +
-                p_demux_track->chunk[i_chunk-1].i_sample_count;
+        p_demux_track->chunks[i_chunk].i_sample_first =
+            p_demux_track->chunks[i_chunk-1].i_sample_first +
+                p_demux_track->chunks[i_chunk-1].i_sample_count;
     }
 
     msg_Dbg( p_demux, "track[Id 0x%x] read %d chunk",
@@ -1330,7 +1145,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
     i_index = 0; i_index_sample_used = 0;
     for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
     {
-        mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
+        mp4_chunk_t *ck = &p_demux_track->chunks[i_chunk];
         int64_t i_entry, i_sample_count, i;
 
         /* save first dts */
@@ -1401,7 +1216,7 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
         i_index = 0; i_index_sample_used = 0;
         for( i_chunk = 0; i_chunk < p_demux_track->i_chunk_count; i_chunk++ )
         {
-            mp4_chunk_t *ck = &p_demux_track->chunk[i_chunk];
+            mp4_chunk_t *ck = &p_demux_track->chunks[i_chunk];
             int64_t i_entry, i_sample_count, i;
 
             /* count how many entries are needed for this chunk
@@ -1476,8 +1291,8 @@ static void TrackGetESSampleRate( unsigned *pi_num, unsigned *pi_den,
         return;
 
     /* */
-    const mp4_chunk_t *p_chunk = &p_track->chunk[i_chunk];
-    while( p_chunk > &p_track->chunk[0] &&
+    const mp4_chunk_t *p_chunk = &p_track->chunks[i_chunk];
+    while( p_chunk > &p_track->chunks[0] &&
            p_chunk[-1].i_sample_description_index == i_sd_index )
     {
         p_chunk--;
@@ -1492,7 +1307,7 @@ static void TrackGetESSampleRate( unsigned *pi_num, unsigned *pi_den,
         i_last_dts = p_chunk->i_last_dts;
         p_chunk++;
     }
-    while( p_chunk < &p_track->chunk[p_track->i_chunk_count] &&
+    while( p_chunk < &p_track->chunks[p_track->i_chunk_count] &&
            p_chunk->i_sample_description_index == i_sd_index );
 
     if( i_sample > 1 && i_first_dts < i_last_dts )
@@ -1509,8 +1324,15 @@ static void TrackGetESSampleRate( unsigned *pi_num, unsigned *pi_den,
 static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
                           unsigned int i_chunk, es_out_id_t **pp_es )
 {
-    const unsigned i_sample_description_index =
-        p_track->chunk[i_chunk].i_sample_description_index;
+    demux_sys_t *p_sys = p_demux->p_sys;
+    unsigned int i_sample_description_index;
+
+    if( p_sys->b_fragmented )
+        i_sample_description_index = 1; /* XXX */
+    else
+        i_sample_description_index =
+                p_track->chunks[i_chunk].i_sample_description_index;
+
     MP4_Box_t   *p_sample;
     MP4_Box_t   *p_esds;
     MP4_Box_t   *p_frma;
@@ -2118,37 +1940,37 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
             break;
         }
 
-        if( (uint64_t)i_start >= p_track->chunk[i_chunk].i_first_dts &&
-            (uint64_t)i_start <  p_track->chunk[i_chunk + 1].i_first_dts )
+        if( (uint64_t)i_start >= p_track->chunks[i_chunk].i_first_dts &&
+            (uint64_t)i_start <  p_track->chunks[i_chunk + 1].i_first_dts )
         {
             break;
         }
     }
 
     /* *** find sample in the chunk *** */
-    i_sample = p_track->chunk[i_chunk].i_sample_first;
-    i_dts    = p_track->chunk[i_chunk].i_first_dts;
-    for( i_index = 0; i_sample < p_track->chunk[i_chunk].i_sample_count; )
+    i_sample = p_track->chunks[i_chunk].i_sample_first;
+    i_dts    = p_track->chunks[i_chunk].i_first_dts;
+    for( i_index = 0; i_sample < p_track->chunks[i_chunk].i_sample_count; )
     {
         if( i_dts +
-            p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
-            p_track->chunk[i_chunk].p_sample_delta_dts[i_index] < (uint64_t)i_start )
+            p_track->chunks[i_chunk].p_sample_count_dts[i_index] *
+            p_track->chunks[i_chunk].p_sample_delta_dts[i_index] < (uint64_t)i_start )
         {
             i_dts    +=
-                p_track->chunk[i_chunk].p_sample_count_dts[i_index] *
-                p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
+                p_track->chunks[i_chunk].p_sample_count_dts[i_index] *
+                p_track->chunks[i_chunk].p_sample_delta_dts[i_index];
 
-            i_sample += p_track->chunk[i_chunk].p_sample_count_dts[i_index];
+            i_sample += p_track->chunks[i_chunk].p_sample_count_dts[i_index];
             i_index++;
         }
         else
         {
-            if( p_track->chunk[i_chunk].p_sample_delta_dts[i_index] <= 0 )
+            if( p_track->chunks[i_chunk].p_sample_delta_dts[i_index] <= 0 )
             {
                 break;
             }
             i_sample += ( i_start - i_dts ) /
-                p_track->chunk[i_chunk].p_sample_delta_dts[i_index];
+                p_track->chunks[i_chunk].p_sample_delta_dts[i_index];
             break;
         }
     }
@@ -2180,14 +2002,14 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
                 if( i_sync_sample <= i_sample )
                 {
                     while( i_chunk > 0 &&
-                           i_sync_sample < p_track->chunk[i_chunk].i_sample_first )
+                           i_sync_sample < p_track->chunks[i_chunk].i_sample_first )
                         i_chunk--;
                 }
                 else
                 {
                     while( i_chunk < p_track->i_chunk_count - 1 &&
-                           i_sync_sample >= p_track->chunk[i_chunk].i_sample_first +
-                                            p_track->chunk[i_chunk].i_sample_count )
+                           i_sync_sample >= p_track->chunks[i_chunk].i_sample_first +
+                                            p_track->chunks[i_chunk].i_sample_count )
                         i_chunk++;
                 }
                 i_sample = i_sync_sample;
@@ -2214,8 +2036,8 @@ static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
 
     /* now see if actual es is ok */
     if( p_track->i_chunk >= p_track->i_chunk_count ||
-        p_track->chunk[p_track->i_chunk].i_sample_description_index !=
-            p_track->chunk[i_chunk].i_sample_description_index )
+        p_track->chunks[p_track->i_chunk].i_sample_description_index !=
+            p_track->chunks[i_chunk].i_sample_description_index )
     {
         msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",
                   p_track->i_track_ID );
@@ -2492,8 +2314,8 @@ static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
         for( i = 0; i < p_track->i_chunk_count; i++ )
         {
             fprintf( stderr, "%-5d sample_count=%d pts=%lld\n",
-                     i, p_track->chunk[i].i_sample_count,
-                     p_track->chunk[i].i_first_dts );
+                     i, p_track->chunks[i].i_sample_count,
+                     p_track->chunks[i].i_first_dts );
 
         }
     }
@@ -2517,16 +2339,16 @@ static void MP4_TrackDestroy( mp4_track_t *p_track )
 
     for( i_chunk = 0; i_chunk < p_track->i_chunk_count; i_chunk++ )
     {
-        if( p_track->chunk )
+        if( p_track->chunks )
         {
-           FREENULL(p_track->chunk[i_chunk].p_sample_count_dts);
-           FREENULL(p_track->chunk[i_chunk].p_sample_delta_dts );
+           FREENULL(p_track->chunks[i_chunk].p_sample_count_dts);
+           FREENULL(p_track->chunks[i_chunk].p_sample_delta_dts );
 
-           FREENULL(p_track->chunk[i_chunk].p_sample_count_pts);
-           FREENULL(p_track->chunk[i_chunk].p_sample_offset_pts );
+           FREENULL(p_track->chunks[i_chunk].p_sample_count_pts);
+           FREENULL(p_track->chunks[i_chunk].p_sample_offset_pts );
         }
     }
-    FREENULL( p_track->chunk );
+    FREENULL( p_track->chunks );
 
     if( !p_track->i_sample_size )
     {
@@ -2552,7 +2374,7 @@ static int MP4_TrackSelect( demux_t *p_demux, mp4_track_t *p_track,
     return MP4_TrackSeek( p_demux, p_track, i_start );
 }
 
-static void MP4_TrackUnselect( demux_t *p_demux, mp4_track_t *p_track )
+void MP4_TrackUnselect( demux_t *p_demux, mp4_track_t *p_track )
 {
     if( !p_track->b_ok || p_track->b_chapter )
     {
@@ -2626,7 +2448,7 @@ static int MP4_TrackSampleSize( mp4_track_t *p_track )
 
     if( p_soun->i_qt_version == 1 )
     {
-        int i_samples = p_track->chunk[p_track->i_chunk].i_sample_count;
+        int i_samples = p_track->chunks[p_track->i_chunk].i_sample_count;
         if( p_track->fmt.audio.i_blockalign > 1 )
             i_samples = p_soun->i_sample_per_packet;
 
@@ -2641,9 +2463,9 @@ static int MP4_TrackSampleSize( mp4_track_t *p_track )
     else
     {
         /* Read a bunch of samples at once */
-        int i_samples = p_track->chunk[p_track->i_chunk].i_sample_count -
+        int i_samples = p_track->chunks[p_track->i_chunk].i_sample_count -
             ( p_track->i_sample -
-              p_track->chunk[p_track->i_chunk].i_sample_first );
+              p_track->chunks[p_track->i_chunk].i_sample_first );
 
         i_samples = __MIN( QT_V0_MAX_SAMPLES, i_samples );
         i_size = i_samples * p_track->i_sample_size;
@@ -2658,7 +2480,7 @@ static uint64_t MP4_TrackGetPos( mp4_track_t *p_track )
     unsigned int i_sample;
     uint64_t i_pos;
 
-    i_pos = p_track->chunk[p_track->i_chunk].i_offset;
+    i_pos = p_track->chunks[p_track->i_chunk].i_offset;
 
     if( p_track->i_sample_size )
     {
@@ -2668,20 +2490,20 @@ static uint64_t MP4_TrackGetPos( mp4_track_t *p_track )
         if( p_track->fmt.i_cat != AUDIO_ES || p_soun->i_qt_version == 0 )
         {
             i_pos += ( p_track->i_sample -
-                       p_track->chunk[p_track->i_chunk].i_sample_first ) *
+                       p_track->chunks[p_track->i_chunk].i_sample_first ) *
                      p_track->i_sample_size;
         }
         else
         {
             /* we read chunk by chunk unless a blockalign is requested */
             if( p_track->fmt.audio.i_blockalign > 1 )
-                i_pos += ( p_track->i_sample - p_track->chunk[p_track->i_chunk].i_sample_first ) /
+                i_pos += ( p_track->i_sample - p_track->chunks[p_track->i_chunk].i_sample_first ) /
                                 p_soun->i_sample_per_packet * p_soun->i_bytes_per_frame;
         }
     }
     else
     {
-        for( i_sample = p_track->chunk[p_track->i_chunk].i_sample_first;
+        for( i_sample = p_track->chunks[p_track->i_chunk].i_sample_first;
              i_sample < p_track->i_sample; i_sample++ )
         {
             i_pos += p_track->p_sample_size[i_sample];
@@ -2705,7 +2527,7 @@ static int MP4_TrackNextSample( demux_t *p_demux, mp4_track_t *p_track )
             if( p_track->fmt.audio.i_blockalign > 1 )
                 p_track->i_sample += p_soun->i_sample_per_packet;
             else
-                p_track->i_sample += p_track->chunk[p_track->i_chunk].i_sample_count;
+                p_track->i_sample += p_track->chunks[p_track->i_chunk].i_sample_count;
         }
         else if( p_track->i_sample_size > 256 )
         {
@@ -2718,12 +2540,12 @@ static int MP4_TrackNextSample( demux_t *p_demux, mp4_track_t *p_track )
             /* FIXME */
             p_track->i_sample += QT_V0_MAX_SAMPLES;
             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 )
+                p_track->chunks[p_track->i_chunk].i_sample_first +
+                p_track->chunks[p_track->i_chunk].i_sample_count )
             {
                 p_track->i_sample =
-                    p_track->chunk[p_track->i_chunk].i_sample_first +
-                    p_track->chunk[p_track->i_chunk].i_sample_count;
+                    p_track->chunks[p_track->i_chunk].i_sample_first +
+                    p_track->chunks[p_track->i_chunk].i_sample_count;
             }
         }
     }
@@ -2736,9 +2558,10 @@ static int MP4_TrackNextSample( demux_t *p_demux, mp4_track_t *p_track )
         return VLC_EGENERIC;
 
     /* Have we changed chunk ? */
+
     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 )
+            p_track->chunks[p_track->i_chunk].i_sample_first +
+            p_track->chunks[p_track->i_chunk].i_sample_count )
     {
         if( TrackGotoChunkSample( p_demux, p_track, p_track->i_chunk + 1,
                                   p_track->i_sample ) )
diff --git a/modules/demux/mp4/mp4.h b/modules/demux/mp4/mp4.h
new file mode 100644
index 0000000..c533322
--- /dev/null
+++ b/modules/demux/mp4/mp4.h
@@ -0,0 +1,218 @@
+#ifndef _MP4_H
+#define _MP4_H 1
+
+#include <assert.h>
+#include <vlc_demux.h>
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+
+#include <vlc_charset.h>                           /* EnsureUTF8 */
+#include <vlc_meta.h>                              /* vlc_meta_t, vlc_meta_ */
+#include <vlc_input.h>
+#include <vlc_modules.h>
+#include "libmp4.h"
+
+
+/* Contain all information about a chunk */
+typedef struct
+{
+    uint64_t     i_offset; /* absolute position of this chunk in the file */
+    uint32_t     i_sample_description_index; /* index for SampleEntry to use */
+    uint32_t     i_sample_count; /* how many samples in this chunk */
+    uint32_t     i_sample_first; /* index of the first sample in this chunk */
+    uint32_t     i_sample; /* index of the next sample to read in this chunk */
+
+    /* now provide way to calculate pts, dts, and offset without too
+        much memory and with fast access */
+
+    /* with this we can calculate dts/pts without waste memory */
+    uint64_t     i_first_dts;   /* DTS of the first sample */
+    uint64_t     i_last_dts;    /* DTS of the last sample */
+    uint32_t     *p_sample_count_dts;
+    uint32_t     *p_sample_delta_dts;   /* dts delta */
+
+    uint32_t     *p_sample_count_pts;
+    int32_t      *p_sample_offset_pts;  /* pts-dts */
+
+    uint8_t      **p_sample_data;     /* set when b_fragmented is true */
+    uint32_t     *p_sample_size;
+    /* TODO if needed add pts
+        but quickly *add* support for edts and seeking */
+
+} mp4_chunk_t;
+
+ /* Contain all needed information for read all track with vlc */
+typedef struct
+{
+    unsigned int i_track_ID;/* this should be unique */
+
+    int b_ok;               /* The track is usable */
+    int b_enable;           /* is the trak enable by default */
+    bool b_selected;  /* is the trak being played */
+    bool b_chapter;   /* True when used for chapter only */
+
+    bool b_mac_encoding;
+
+    es_format_t fmt;
+    es_out_id_t *p_es;
+
+    /* display size only ! */
+    int i_width;
+    int i_height;
+
+    /* more internal data */
+    uint64_t        i_timescale;    /* time scale for this track only */
+    uint16_t        current_qid;    /* Smooth Streaming quality level ID */
+
+    /* elst */
+    int             i_elst;         /* current elst */
+    int64_t         i_elst_time;    /* current elst start time (in movie time scale)*/
+    MP4_Box_t       *p_elst;        /* elst (could be NULL) */
+
+    /* give the next sample to read, i_chunk is to find quickly where
+      the sample is located */
+    uint32_t         i_sample;       /* next sample to read */
+    uint32_t         i_chunk;        /* chunk where next sample is stored */
+    /* total count of chunk and sample */
+    uint32_t         i_chunk_count;
+    uint32_t         i_sample_count;
+
+    mp4_chunk_t    *chunks; /* always defined  for each chunk */
+    mp4_chunk_t    *cchunk; /* current chunk if b_fragmented is true */
+
+    /* sample size, p_sample_size defined only if i_sample_size == 0
+        else i_sample_size is size for all sample */
+    uint32_t         i_sample_size;
+    uint32_t         *p_sample_size; /* XXX perhaps add file offset if take
+                                    too much time to do sumations each time*/
+
+    uint32_t     i_sample_first; /* i_sample_first value
+                                                   of the next chunk */
+    uint64_t     i_first_dts;    /* i_first_dts value
+                                                   of the next chunk */
+
+    MP4_Box_t *p_stbl;  /* will contain all timing information */
+    MP4_Box_t *p_stsd;  /* will contain all data to initialize decoder */
+    MP4_Box_t *p_sample;/* point on actual sdsd */
+
+    bool b_drms;
+    bool b_end_of_chunk;
+    void      *p_drms;
+    MP4_Box_t *p_skcr;
+
+} mp4_track_t;
+
+struct demux_sys_t
+{
+    MP4_Box_t    *p_root;      /* container for the whole file */
+
+    mtime_t      i_pcr;
+
+    uint64_t     i_time;         /* time position of the presentation
+                                    in movie timescale */
+    uint64_t     i_timescale;    /* movie time scale */
+    uint64_t     i_duration;     /* movie duration */
+    unsigned int i_tracks;       /* number of tracks */
+    mp4_track_t  *track;         /* array of track */
+    float        f_fps;          /* number of frame per seconds */
+
+    bool         b_smooth;       /* Smooth Streaming => no moov box */
+    bool         b_dash;         /* DASH */
+    bool         b_fragmented;   /* fMP4 */
+
+    /* */
+    MP4_Box_t    *p_tref_chap;
+
+    /* */
+    input_title_t *p_title;
+};
+
+/* PTS is in micro-seconds */
+static inline int64_t MP4_GetMoviePTS(demux_sys_t *p_sys )
+{
+    return INT64_C(1000000) * p_sys->i_time / p_sys->i_timescale;
+}
+
+static inline int64_t MP4_TrackGetPTSDelta( demux_t *p_demux, mp4_track_t *p_track )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    mp4_chunk_t *ck;
+    if( p_sys->b_fragmented )
+        ck = p_track->cchunk;
+    else
+        ck = &p_track->chunks[p_track->i_chunk];
+
+    unsigned int i_index = 0;
+    unsigned int i_sample = p_track->i_sample - ck->i_sample_first;
+
+    if( ck->p_sample_count_pts == NULL || ck->p_sample_offset_pts == NULL )
+        return -1;
+
+    for( i_index = 0;; i_index++ )
+    {
+        if( i_sample < ck->p_sample_count_pts[i_index] )
+            return ck->p_sample_offset_pts[i_index] * INT64_C(1000000) /
+                   (int64_t)p_track->i_timescale;
+
+        i_sample -= ck->p_sample_count_pts[i_index];
+    }
+}
+
+/* Return time in s of a track */
+static inline int64_t MP4_TrackGetDTS( demux_t *p_demux, mp4_track_t *p_track )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    mp4_chunk_t *chunk;
+    if( p_sys->b_fragmented )
+        chunk = p_track->cchunk;
+    else
+        chunk = &p_track->chunks[p_track->i_chunk];
+
+    unsigned int i_index = 0;
+    assert( p_track->i_sample >= chunk->i_sample_first );
+    unsigned int i_sample = p_track->i_sample - chunk->i_sample_first;
+    int64_t i_dts = chunk->i_first_dts;
+
+    while( i_sample > 0 )
+    {
+        if( i_sample > chunk->p_sample_count_dts[i_index] )
+        {
+            i_dts += chunk->p_sample_count_dts[i_index] *
+                chunk->p_sample_delta_dts[i_index];
+            i_sample -= chunk->p_sample_count_dts[i_index];
+            i_index++;
+        }
+        else
+        {
+            i_dts += i_sample * chunk->p_sample_delta_dts[i_index];
+            break;
+        }
+    }
+
+    /* now handle elst */
+    if( p_track->p_elst )
+    {
+        demux_sys_t         *p_sys = p_demux->p_sys;
+        MP4_Box_data_elst_t *elst = p_track->p_elst->data.p_elst;
+
+        /* convert to offset */
+        if( ( elst->i_media_rate_integer[p_track->i_elst] > 0 ||
+              elst->i_media_rate_fraction[p_track->i_elst] > 0 ) &&
+            elst->i_media_time[p_track->i_elst] > 0 )
+        {
+            i_dts -= elst->i_media_time[p_track->i_elst];
+        }
+
+        /* add i_elst_time */
+        i_dts += p_track->i_elst_time * p_track->i_timescale /
+            p_sys->i_timescale;
+
+        if( i_dts < 0 ) i_dts = 0;
+    }
+
+    return INT64_C(1000000) * i_dts / p_track->i_timescale;
+}
+
+void MP4_TrackUnselect( demux_t *, mp4_track_t * );
+
+#endif
-- 
1.7.5.4




More information about the vlc-devel mailing list