[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