Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
b1702cbd
Commit
b1702cbd
authored
May 25, 2014
by
Francois Cartegnie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
demux: mp4: add fragments tracking
parent
fafd0af1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
362 additions
and
38 deletions
+362
-38
modules/demux/mp4/libmp4.h
modules/demux/mp4/libmp4.h
+1
-0
modules/demux/mp4/mp4.c
modules/demux/mp4/mp4.c
+361
-38
No files found.
modules/demux/mp4/libmp4.h
View file @
b1702cbd
...
...
@@ -925,6 +925,7 @@ typedef struct MP4_Box_data_sidx_s
#define MP4_TFHD_DFLT_SAMPLE_SIZE (1LL<<4)
#define MP4_TFHD_DFLT_SAMPLE_FLAGS (1LL<<5)
#define MP4_TFHD_DURATION_IS_EMPTY (1LL<<16)
#define MP4_TFHD_DEFAULT_BASE_IS_MOOF (1LL<<17)
typedef
struct
MP4_Box_data_tfhd_s
{
uint8_t
i_version
;
...
...
modules/demux/mp4/mp4.c
View file @
b1702cbd
...
...
@@ -64,12 +64,23 @@ static int DemuxFrg( demux_t * );
static
int
Seek
(
demux_t
*
,
mtime_t
);
static
int
Control
(
demux_t
*
,
int
,
va_list
);
typedef
struct
mp4_fragment_t
mp4_fragment_t
;
struct
mp4_fragment_t
{
uint64_t
i_chunk_range_min_offset
;
uint64_t
i_chunk_range_max_offset
;
uint64_t
i_duration
;
MP4_Box_t
*
p_moox
;
mp4_fragment_t
*
p_next
;
};
struct
demux_sys_t
{
MP4_Box_t
*
p_root
;
/* container for the whole file */
mtime_t
i_pcr
;
uint64_t
i_overall_duration
;
/* Full duration, including all fragments */
uint64_t
i_time
;
/* time position of the presentation
* in movie timescale */
uint32_t
i_timescale
;
/* movie time scale */
...
...
@@ -83,6 +94,10 @@ struct demux_sys_t
bool
b_fastseekable
;
bool
b_smooth
;
/* Is it Smooth Streaming? */
bool
b_fragments_probed
;
mp4_fragment_t
moovfragment
;
/* moov */
mp4_fragment_t
*
p_fragments
;
/* known fragments (moof following moov) */
/* */
MP4_Box_t
*
p_tref_chap
;
...
...
@@ -114,6 +129,11 @@ static const char *MP4_ConvertMacCode( uint16_t );
static
MP4_Box_t
*
MP4_GetTrexByTrackID
(
MP4_Box_t
*
p_moov
,
const
uint32_t
i_id
);
static
bool
AddFragment
(
demux_t
*
p_demux
,
MP4_Box_t
*
p_moox
);
static
int
ProbeFragments
(
demux_t
*
p_demux
);
/* Helpers */
static
uint32_t
stream_ReadU32
(
stream_t
*
s
,
void
*
p_read
,
uint32_t
i_toread
)
{
uint32_t
i_return
=
0
;
...
...
@@ -142,6 +162,22 @@ static MP4_Box_t * MP4_GetTrexByTrackID( MP4_Box_t *p_moov, const uint32_t i_id
return
p_trex
;
}
static
MP4_Box_t
*
MP4_GetTrakByTrackID
(
MP4_Box_t
*
p_moov
,
const
uint32_t
i_id
)
{
MP4_Box_t
*
p_trak
=
MP4_BoxGet
(
p_moov
,
"trak"
);
MP4_Box_t
*
p_tkhd
;
while
(
p_trak
)
{
if
(
p_trak
->
i_type
==
ATOM_trak
&&
(
p_tkhd
=
MP4_BoxGet
(
p_trak
,
"tkhd"
))
&&
BOXDATA
(
p_tkhd
)
->
i_track_ID
==
i_id
)
break
;
else
p_trak
=
p_trak
->
p_next
;
}
return
p_trak
;
}
/* Return time in microsecond of a track */
static
inline
int64_t
MP4_TrackGetDTS
(
demux_t
*
p_demux
,
mp4_track_t
*
p_track
)
{
...
...
@@ -279,18 +315,6 @@ LoadInitFragError:
return
VLC_EGENERIC
;
}
/* Does lookup for remaining boxes */
static
int
ProbeFragments
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
msg_Dbg
(
p_demux
,
"probing fragments from %"
PRId64
,
stream_Tell
(
p_demux
->
s
)
);
MP4_ReadBoxContainerRaw
(
p_demux
->
s
,
p_sys
->
p_root
);
return
VLC_SUCCESS
;
}
static
int
InitTracks
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
...
...
@@ -411,7 +435,6 @@ static int Open( vlc_object_t * p_this )
if
(
LoadInitFrag
(
p_demux
)
!=
VLC_SUCCESS
)
goto
error
;
/* LoadInitFrag early failed */
if
(
MP4_BoxCount
(
p_sys
->
p_root
,
"/moov/mvex"
)
>
0
)
{
if
(
p_sys
->
b_seekable
)
...
...
@@ -425,7 +448,16 @@ static int Open( vlc_object_t * p_this )
p_sys
->
b_fragmented
=
true
;
}
if
(
p_sys
->
b_fragmented
)
if
(
!
p_sys
->
moovfragment
.
p_moox
)
AddFragment
(
p_demux
,
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov"
)
);
/* we always need a moov entry, but smooth has a workaround */
if
(
!
p_sys
->
moovfragment
.
p_moox
&&
!
p_sys
->
b_smooth
)
{
goto
error
;
}
if
(
p_sys
->
b_fragmented
||
p_sys
->
b_smooth
)
{
p_demux
->
pf_demux
=
DemuxFrg
;
}
...
...
@@ -489,7 +521,8 @@ static int Open( vlc_object_t * p_this )
}
/* the file need to have one moov box */
if
(
MP4_BoxCount
(
p_sys
->
p_root
,
"/moov"
)
<=
0
)
p_sys
->
moovfragment
.
p_moox
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov"
,
0
);
if
(
!
p_sys
->
moovfragment
.
p_moox
)
{
MP4_Box_t
*
p_foov
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/foov"
);
...
...
@@ -500,6 +533,7 @@ static int Open( vlc_object_t * p_this )
}
/* we have a free box as a moov, rename it */
p_foov
->
i_type
=
ATOM_moov
;
p_sys
->
moovfragment
.
p_moox
=
p_foov
;
}
if
(
(
p_rmra
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov/rmra"
)
)
)
...
...
@@ -602,15 +636,16 @@ static int Open( vlc_object_t * p_this )
msg_Err
(
p_this
,
"bad timescale"
);
goto
error
;
}
p_sys
->
i_duration
=
BOXDATA
(
p_mvhd
)
->
i_duration
;
}
/* Try in mehd if fragmented */
if
(
p_sys
->
i_duration
==
0
)
if
(
p_sys
->
i_overall_duration
==
0
)
{
/* Try in mehd if fragmented */
MP4_Box_t
*
p_mehd
=
MP4_BoxGet
(
p_demux
->
p_sys
->
p_root
,
"moov/mvex/mehd"
);
if
(
p_mehd
)
p_sys
->
i_duration
=
BOXDATA
(
p_mehd
)
->
i_fragment_duration
;
p_sys
->
i_overall_duration
=
p_mehd
->
data
.
p_mehd
->
i_fragment_duration
;
else
p_sys
->
i_overall_duration
=
p_sys
->
moovfragment
.
i_duration
;
}
if
(
!
(
p_sys
->
i_tracks
=
MP4_BoxCount
(
p_sys
->
p_root
,
"/moov/trak"
)
)
)
...
...
@@ -689,6 +724,15 @@ static int Open( vlc_object_t * p_this )
}
}
mp4_fragment_t
*
p_fragment
=
&
p_sys
->
moovfragment
;
while
(
p_fragment
)
{
msg_Dbg
(
p_demux
,
"fragment offset %"
PRId64
", data %"
PRId64
"<->%"
PRId64
", time %"
PRId64
,
p_fragment
->
p_moox
->
i_pos
,
p_fragment
->
i_chunk_range_min_offset
,
p_fragment
->
i_chunk_range_max_offset
,
p_fragment
->
i_duration
);
p_fragment
=
p_fragment
->
p_next
;
}
/* */
LoadChapter
(
p_demux
);
...
...
@@ -752,7 +796,7 @@ static int Demux( demux_t *p_demux )
if
(
p_sys
->
i_timescale
>
0
)
{
int64_t
i_length
=
CLOCK_FREQ
*
(
mtime_t
)
p_sys
->
i_duration
/
(
mtime_t
)
p_sys
->
moovfragment
.
i_duration
/
(
mtime_t
)
p_sys
->
i_timescale
;
if
(
MP4_GetMoviePTS
(
p_sys
)
>=
i_length
)
return
0
;
...
...
@@ -930,7 +974,7 @@ static int MP4_frg_Seek( demux_t *p_demux, double f )
else
{
/* update global time */
p_sys
->
i_time
=
(
uint64_t
)(
f
*
(
double
)
p_sys
->
i_duration
);
p_sys
->
i_time
=
(
uint64_t
)(
f
*
(
double
)
p_sys
->
moovfragment
.
i_duration
);
p_sys
->
i_pcr
=
MP4_GetMoviePTS
(
p_sys
);
for
(
unsigned
i_track
=
0
;
i_track
<
p_sys
->
i_tracks
;
i_track
++
)
...
...
@@ -966,9 +1010,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
{
case
DEMUX_GET_POSITION
:
pf
=
(
double
*
)
va_arg
(
args
,
double
*
);
if
(
p_sys
->
i_duration
>
0
)
if
(
p_sys
->
i_
overall_
duration
>
0
)
{
*
pf
=
(
double
)
p_sys
->
i_time
/
(
double
)
p_sys
->
i_duration
;
*
pf
=
(
double
)
p_sys
->
i_time
/
(
double
)
p_sys
->
i_
overall_
duration
;
}
else
{
...
...
@@ -985,7 +1029,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
else
if
(
p_sys
->
i_timescale
>
0
)
{
i64
=
(
int64_t
)(
f
*
CLOCK_FREQ
*
(
double
)
p_sys
->
i_duration
/
(
double
)
p_sys
->
i_
overall_
duration
/
(
double
)
p_sys
->
i_timescale
);
return
Seek
(
p_demux
,
i64
);
}
...
...
@@ -1011,7 +1055,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
if
(
p_sys
->
i_timescale
>
0
)
{
*
pi64
=
CLOCK_FREQ
*
(
mtime_t
)
p_sys
->
i_duration
/
(
mtime_t
)
p_sys
->
i_
overall_
duration
/
(
mtime_t
)
p_sys
->
i_timescale
;
}
else
*
pi64
=
0
;
...
...
@@ -1317,6 +1361,13 @@ static void Close ( vlc_object_t * p_this )
if
(
p_sys
->
p_title
)
vlc_input_title_Delete
(
p_sys
->
p_title
);
while
(
p_sys
->
moovfragment
.
p_next
)
{
mp4_fragment_t
*
p_fragment
=
p_sys
->
moovfragment
.
p_next
->
p_next
;
free
(
p_sys
->
moovfragment
.
p_next
);
p_sys
->
moovfragment
.
p_next
=
p_fragment
;
}
free
(
p_sys
);
}
...
...
@@ -1415,7 +1466,7 @@ static void LoadChapter( demux_t *p_demux )
if
(
p_sys
->
p_title
)
{
p_sys
->
p_title
->
i_length
=
CLOCK_FREQ
*
(
uint64_t
)
p_sys
->
i_duration
/
(
uint64_t
)
p_sys
->
i_timescale
;
(
uint64_t
)
p_sys
->
i_
overall_
duration
/
(
uint64_t
)
p_sys
->
i_timescale
;
}
}
...
...
@@ -1424,8 +1475,6 @@ static int TrackCreateChunksIndex( demux_t *p_demux,
mp4_track_t
*
p_demux_track
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
if
(
p_sys
->
b_fragmented
)
return
VLC_SUCCESS
;
MP4_Box_t
*
p_co64
;
/* give offset for each chunk, same for stco and co64 */
MP4_Box_t
*
p_stsc
;
...
...
@@ -1444,7 +1493,6 @@ static int TrackCreateChunksIndex( demux_t *p_demux,
if
(
!
p_demux_track
->
i_chunk_count
)
{
msg_Warn
(
p_demux
,
"no chunk defined"
);
return
(
VLC_EGENERIC
);
}
p_demux_track
->
chunk
=
calloc
(
p_demux_track
->
i_chunk_count
,
sizeof
(
mp4_chunk_t
)
);
...
...
@@ -1472,13 +1520,8 @@ static int TrackCreateChunksIndex( demux_t *p_demux,
We construct it begining at the end */
i_last
=
p_demux_track
->
i_chunk_count
;
/* last chunk proceded */
i_index
=
BOXDATA
(
p_stsc
)
->
i_entry_count
;
if
(
!
i_index
)
{
msg_Warn
(
p_demux
,
"cannot read chunk table or table empty"
);
return
(
VLC_EGENERIC
);
}
while
(
i_index
--
)
while
(
i_index
--
>
0
)
{
for
(
i_chunk
=
BOXDATA
(
p_stsc
)
->
i_first_chunk
[
i_index
]
-
1
;
i_chunk
<
i_last
;
i_chunk
++
)
...
...
@@ -1508,6 +1551,12 @@ static int TrackCreateChunksIndex( demux_t *p_demux,
msg_Dbg
(
p_demux
,
"track[Id 0x%x] read %d chunk"
,
p_demux_track
->
i_track_ID
,
p_demux_track
->
i_chunk_count
);
if
(
p_demux_track
->
i_chunk_count
&&
(
p_sys
->
moovfragment
.
i_chunk_range_min_offset
==
0
||
p_sys
->
moovfragment
.
i_chunk_range_min_offset
>
p_demux_track
->
chunk
[
0
].
i_offset
)
)
p_sys
->
moovfragment
.
i_chunk_range_min_offset
=
p_demux_track
->
chunk
[
0
].
i_offset
;
return
VLC_SUCCESS
;
}
...
...
@@ -1563,8 +1612,6 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
mp4_track_t
*
p_demux_track
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
if
(
p_sys
->
b_fragmented
)
return
VLC_SUCCESS
;
MP4_Box_t
*
p_box
;
MP4_Box_data_stsz_t
*
stsz
;
...
...
@@ -1607,6 +1654,22 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
}
}
if
(
p_demux_track
->
i_chunk_count
)
{
mp4_chunk_t
*
lastchunk
=
&
p_demux_track
->
chunk
[
p_demux_track
->
i_chunk_count
-
1
];
uint64_t
i_total_size
=
lastchunk
->
i_offset
;
for
(
uint32_t
i
=
0
;
i
<
lastchunk
->
i_sample_count
;
i
++
)
{
if
(
p_demux_track
->
i_sample_size
==
0
)
i_total_size
+=
stsz
->
i_entry_size
[
i
];
else
i_total_size
+=
p_demux_track
->
i_sample_size
;
}
if
(
i_total_size
>
p_sys
->
moovfragment
.
i_chunk_range_max_offset
)
p_sys
->
moovfragment
.
i_chunk_range_max_offset
=
i_total_size
;
}
/* Use stts table to create a sample number -> dts table.
* XXX: if we don't want to waste too much memory, we can't expand
* the box! so each chunk will contain an "extract" of this table
...
...
@@ -2920,6 +2983,7 @@ static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
if
(
TrackCreateChunksIndex
(
p_demux
,
p_track
)
||
TrackCreateSamplesIndex
(
p_demux
,
p_track
)
)
{
msg_Err
(
p_demux
,
"cannot create chunks index"
);
return
;
/* cannot create chunks index */
}
...
...
@@ -3962,6 +4026,265 @@ static int MP4_frg_TrackSelect( demux_t *p_demux, mp4_track_t *p_track )
return
VLC_SUCCESS
;
}
/* Keeps an ordered chain of all fragments */
static
bool
AddFragment
(
demux_t
*
p_demux
,
MP4_Box_t
*
p_moox
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
mp4_fragment_t
*
p_base_fragment
=
&
p_sys
->
moovfragment
;
if
(
!
p_moox
)
return
false
;
if
(
p_moox
->
i_type
==
ATOM_moov
)
{
if
(
!
p_sys
->
moovfragment
.
p_moox
)
{
p_sys
->
moovfragment
.
p_moox
=
p_moox
;
MP4_Box_t
*
p_mvhd
;
if
(
(
p_mvhd
=
MP4_BoxGet
(
p_moox
,
"mvhd"
))
)
{
p_sys
->
i_timescale
=
BOXDATA
(
p_mvhd
)
->
i_timescale
;
p_sys
->
moovfragment
.
i_duration
=
BOXDATA
(
p_mvhd
)
->
i_duration
;
}
msg_Dbg
(
p_demux
,
"added fragment %4.4s"
,
(
char
*
)
&
p_moox
->
i_type
);
return
true
;
}
return
false
;
}
else
// p_moox->i_type == ATOM_moof
{
assert
(
p_moox
->
i_type
==
ATOM_moof
);
mp4_fragment_t
*
p_fragment
=
p_sys
->
moovfragment
.
p_next
;
while
(
p_fragment
)
{
if
(
!
p_base_fragment
->
p_moox
||
p_moox
->
i_pos
>
p_base_fragment
->
p_moox
->
i_pos
)
{
p_base_fragment
=
p_fragment
;
p_fragment
=
p_fragment
->
p_next
;
}
else
if
(
p_moox
->
i_pos
==
p_base_fragment
->
p_moox
->
i_pos
)
{
/* already exists */
return
false
;
}
}
}
/* Add the moof fragment */
mp4_fragment_t
*
p_new
=
malloc
(
sizeof
(
mp4_fragment_t
));
if
(
!
p_new
)
return
false
;
p_new
->
p_moox
=
p_moox
;
p_new
->
i_duration
=
0
;
p_new
->
p_next
=
p_base_fragment
->
p_next
;
p_base_fragment
->
p_next
=
p_new
;
msg_Dbg
(
p_demux
,
"added fragment %4.4s"
,
(
char
*
)
&
p_moox
->
i_type
);
/* we have to probe all fragments :/ */
uint64_t
i_traf_base_data_offset
=
0
;
uint64_t
i_traf_min_offset
=
0
;
uint32_t
i_traf
=
0
;
uint32_t
i_traf_total_size
=
0
;
uint32_t
i_trafs_total_size
=
0
;
MP4_Box_t
*
p_traf
=
MP4_BoxGet
(
p_new
->
p_moox
,
"traf"
);
while
(
p_traf
)
{
if
(
p_traf
->
i_type
!=
ATOM_traf
)
{
p_traf
=
p_traf
->
p_next
;
continue
;
}
const
MP4_Box_t
*
p_tfhd
=
MP4_BoxGet
(
p_traf
,
"tfhd"
);
const
MP4_Box_t
*
p_trun
=
MP4_BoxGet
(
p_traf
,
"trun"
);
if
(
!
p_tfhd
||
!
p_trun
)
{
p_traf
=
p_traf
->
p_next
;
continue
;
}
uint32_t
i_track_timescale
=
0
;
uint32_t
i_track_defaultsamplesize
=
0
;
uint32_t
i_track_defaultsampleduration
=
0
;
if
(
p_sys
->
b_smooth
)
{
/* stra sets identical timescales */
i_track_timescale
=
p_sys
->
i_timescale
;
i_track_defaultsamplesize
=
1
;
i_track_defaultsampleduration
=
1
;
}
else
{
/* set trex for defaults */
MP4_Box_t
*
p_trex
=
MP4_GetTrexByTrackID
(
p_sys
->
moovfragment
.
p_moox
,
BOXDATA
(
p_tfhd
)
->
i_track_ID
);
if
(
p_trex
)
{
i_track_defaultsamplesize
=
BOXDATA
(
p_trex
)
->
i_default_sample_size
;
i_track_defaultsampleduration
=
BOXDATA
(
p_trex
)
->
i_default_sample_duration
;
}
MP4_Box_t
*
p_trak
=
MP4_GetTrakByTrackID
(
p_sys
->
moovfragment
.
p_moox
,
BOXDATA
(
p_tfhd
)
->
i_track_ID
);
if
(
p_trak
)
{
MP4_Box_t
*
p_mdhd
=
MP4_BoxGet
(
p_trak
,
"mdia/mdhd"
);
if
(
p_mdhd
)
i_track_timescale
=
BOXDATA
(
p_mdhd
)
->
i_timescale
;
}
}
if
(
!
i_track_timescale
)
{
p_traf
=
p_traf
->
p_next
;
continue
;
}
if
(
BOXDATA
(
p_tfhd
)
->
i_flags
&
MP4_TFHD_BASE_DATA_OFFSET
)
{
i_traf_base_data_offset
=
BOXDATA
(
p_tfhd
)
->
i_base_data_offset
;
}
else
if
(
BOXDATA
(
p_tfhd
)
->
i_flags
&
MP4_TFHD_DEFAULT_BASE_IS_MOOF
)
{
i_traf_base_data_offset
=
p_new
->
p_moox
->
i_pos
+
8
;
}
else
{
if
(
i_traf
==
0
)
i_traf_base_data_offset
=
p_new
->
p_moox
->
i_pos
/*+ 8*/
;
else
i_traf_base_data_offset
+=
i_traf_total_size
;
}
i_traf_total_size
=
0
;
uint64_t
i_trun_data_offset
=
i_traf_base_data_offset
;
uint64_t
i_traf_duration
=
0
;
uint32_t
i_trun_size
=
0
;
while
(
p_trun
&&
p_tfhd
)
{
if
(
p_trun
->
i_type
!=
ATOM_trun
)
{
p_trun
=
p_trun
->
p_next
;
continue
;
}
const
MP4_Box_data_trun_t
*
p_trundata
=
p_trun
->
data
.
p_trun
;
/* Get data offset */
if
(
p_trundata
->
i_flags
&
MP4_TRUN_DATA_OFFSET
)
i_trun_data_offset
+=
__MAX
(
p_trundata
->
i_data_offset
,
0
);
else
i_trun_data_offset
+=
i_trun_size
;
i_trun_size
=
0
;
/* Sum total time */
if
(
p_trundata
->
i_flags
&
MP4_TRUN_SAMPLE_DURATION
)
{
for
(
uint32_t
i
=
0
;
i
<
p_trundata
->
i_sample_count
;
i
++
)
i_traf_duration
+=
p_trundata
->
p_samples
[
i
].
i_duration
;
}
else
if
(
BOXDATA
(
p_tfhd
)
->
i_flags
&
MP4_TFHD_DFLT_SAMPLE_DURATION
)
{
i_traf_duration
+=
p_trundata
->
i_sample_count
*
BOXDATA
(
p_tfhd
)
->
i_default_sample_duration
;
}
else
{
i_traf_duration
+=
p_trundata
->
i_sample_count
*
i_track_defaultsampleduration
;
}
/* Get total traf size */
if
(
p_trundata
->
i_flags
&
MP4_TRUN_SAMPLE_SIZE
)
{
for
(
uint32_t
i
=
0
;
i
<
p_trundata
->
i_sample_count
;
i
++
)
i_trun_size
+=
p_trundata
->
p_samples
[
i
].
i_size
;
}
else
if
(
BOXDATA
(
p_tfhd
)
->
i_flags
&
MP4_TFHD_DFLT_SAMPLE_SIZE
)
{
i_trun_size
+=
p_trundata
->
i_sample_count
*
BOXDATA
(
p_tfhd
)
->
i_default_sample_size
;
}
else
{
i_trun_size
+=
p_trundata
->
i_sample_count
*
i_track_defaultsamplesize
;
}
i_traf_total_size
+=
i_trun_size
;
if
(
i_traf_min_offset
)
i_traf_min_offset
=
__MIN
(
i_trun_data_offset
,
i_traf_min_offset
);
else
i_traf_min_offset
=
i_trun_data_offset
;
p_trun
=
p_trun
->
p_next
;
}
i_trafs_total_size
+=
i_traf_total_size
;
p_new
->
i_duration
=
__MAX
(
p_new
->
i_duration
,
i_traf_duration
*
p_sys
->
i_timescale
/
i_track_timescale
);
p_traf
=
p_traf
->
p_next
;
i_traf
++
;
}
p_new
->
i_chunk_range_min_offset
=
i_traf_min_offset
;
p_new
->
i_chunk_range_max_offset
=
i_traf_min_offset
+
i_trafs_total_size
;
msg_Err
(
p_demux
,
"new fragment is %"
PRId64
" %"
PRId64
,
p_new
->
i_chunk_range_min_offset
,
p_new
->
i_chunk_range_max_offset
);
/* compute total duration with that new fragment if no overall provided */
MP4_Box_t
*
p_mehd
=
MP4_BoxGet
(
p_sys
->
moovfragment
.
p_moox
,
"mvex/mehd"
);
if
(
!
p_mehd
)
{
p_sys
->
i_overall_duration
=
0
;
p_new
=
&
p_sys
->
moovfragment
;
while
(
p_new
)
{
p_sys
->
i_overall_duration
+=
p_new
->
i_duration
;
p_new
=
p_new
->
p_next
;
}
}
else
p_sys
->
i_overall_duration
=
BOXDATA
(
p_mehd
)
->
i_fragment_duration
;
msg_Err
(
p_demux
,
"total fragments duration %"
PRId64
,
CLOCK_FREQ
*
p_sys
->
i_overall_duration
/
p_sys
->
i_timescale
);
return
true
;
}
static
int
ProbeFragments
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
msg_Dbg
(
p_demux
,
"probing fragments from %"
PRId64
,
stream_Tell
(
p_demux
->
s
)
);
assert
(
p_sys
->
p_root
);
MP4_ReadBoxContainerRaw
(
p_demux
->
s
,
p_sys
->
p_root
);
/* Get the rest of the file */
MP4_Box_t
*
p_moov
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov"
);
if
(
!
p_moov
)
{
MP4_BoxDumpStructure
(
p_demux
->
s
,
p_sys
->
p_root
);
return
VLC_EGENERIC
;
}
AddFragment
(
p_demux
,
p_moov
);
MP4_Box_t
*
p_moof
=
MP4_BoxGet
(
p_sys
->
p_root
,
"moof"
);
while
(
p_moof
)
{
if
(
p_moof
->
i_type
==
ATOM_moof
)
AddFragment
(
p_demux
,
p_moof
);
p_moof
=
p_moof
->
p_next
;
}
p_sys
->
b_fragments_probed
=
true
;
MP4_Box_t
*
p_mdat
=
MP4_BoxGet
(
p_sys
->
p_root
,
"mdat"
);
assert
(
p_mdat
);
stream_Seek
(
p_demux
->
s
,
p_mdat
->
i_pos
);
msg_Dbg
(
p_demux
,
"rewinding to mdat %"
PRId64
,
p_mdat
->
i_pos
);
return
VLC_SUCCESS
;
}
/**
* DemuxFrg: read packet and send them to decoders
* \return 1 on success, 0 on error.
...
...
@@ -4004,7 +4327,7 @@ int DemuxFrg( demux_t *p_demux )
if
(
p_sys
->
i_timescale
>
0
)
{
int64_t
i_length
=
CLOCK_FREQ
*
(
mtime_t
)
p_sys
->
i_duration
/
(
mtime_t
)
p_sys
->
moovfragment
.
i_duration
/
(
mtime_t
)
p_sys
->
i_timescale
;
if
(
MP4_GetMoviePTS
(
p_sys
)
>=
i_length
)
return
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment