Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
VLC
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
13
Merge Requests
13
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
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
Steve Lhomme
VLC
Commits
e133d979
Commit
e133d979
authored
Feb 06, 2017
by
François Cartegnie
🤞
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
demux: mp4: rework durations handling
parent
b4bb0efb
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
77 additions
and
49 deletions
+77
-49
modules/demux/mp4/mp4.c
modules/demux/mp4/mp4.c
+77
-49
No files found.
modules/demux/mp4/mp4.c
View file @
e133d979
...
...
@@ -76,7 +76,9 @@ struct demux_sys_t
mtime_t
i_pcr
;
uint64_t
i_overall_duration
;
/* Full duration, including all fragments */
uint64_t
i_moov_duration
;
uint64_t
i_duration
;
/* Declared fragmented duration */
uint64_t
i_cumulated_duration
;
/* Same as above, but not from probing */
uint64_t
i_time
;
/* time position of the presentation
* in movie timescale */
uint32_t
i_timescale
;
/* movie time scale */
...
...
@@ -148,7 +150,7 @@ static void MP4_GetDefaultSizeAndDuration( demux_t *p_demux,
uint32_t
*
pi_default_duration
);
static
bool
AddFragment
(
demux_t
*
p_demux
,
MP4_Box_t
*
p_moox
);
static
int
ProbeFragments
(
demux_t
*
p_demux
,
bool
b_force
);
static
int
ProbeFragments
(
demux_t
*
p_demux
,
bool
b_force
,
bool
*
pb_fragmented
);
static
int
ProbeIndex
(
demux_t
*
p_demux
);
static
int
LeafIndexGetMoofPosByTime
(
demux_t
*
p_demux
,
const
mtime_t
i_target_time
,
...
...
@@ -629,9 +631,11 @@ static int Open( vlc_object_t * p_this )
const
uint8_t
*
p_peek
;
MP4_Box_t
*
p_ftyp
;
MP4_Box_t
*
p_moov
;
MP4_Box_t
*
p_rmra
;
MP4_Box_t
*
p_mvhd
;
MP4_Box_t
*
p_trak
;
const
MP4_Box_t
*
p_mvhd
=
NULL
;
const
MP4_Box_t
*
p_mvex
=
NULL
;
unsigned
int
i
;
bool
b_enabled_es
;
...
...
@@ -739,19 +743,36 @@ static int Open( vlc_object_t * p_this )
msg_Dbg
(
p_demux
,
"file type box missing (assuming ISO Media)"
);
}
if
(
MP4_BoxCount
(
p_sys
->
p_root
,
"/moov/mvex"
)
>
0
)
p_moov
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov"
);
if
(
likely
(
p_moov
)
)
{
const
MP4_Box_t
*
p_moov
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov"
);
if
(
p_sys
->
b_seekable
)
p_mvhd
=
MP4_BoxGet
(
p_moov
,
"mvhd"
);
if
(
p_mvhd
&&
BOXDATA
(
p_mvhd
)
)
p_sys
->
i_moov_duration
=
p_sys
->
i_duration
=
BOXDATA
(
p_mvhd
)
->
i_duration
;
p_mvex
=
MP4_BoxGet
(
p_moov
,
"mvex"
);
}
if
(
p_mvex
!=
NULL
)
{
const
MP4_Box_t
*
p_mehd
=
MP4_BoxGet
(
p_mvex
,
"mehd"
);
if
(
p_mehd
&&
BOXDATA
(
p_mehd
)
)
{
/* Probe remaining to check if there's really fragments
or if that file is just ready to append fragments */
ProbeFragments
(
p_demux
,
false
);
const
MP4_Box_t
*
p_moof
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moof"
);
p_sys
->
b_fragmented
=
!!
p_moof
;
if
(
BOXDATA
(
p_mehd
)
->
i_fragment_duration
>
p_sys
->
i_duration
)
{
p_sys
->
b_fragmented
=
true
;
p_sys
->
i_duration
=
BOXDATA
(
p_mehd
)
->
i_fragment_duration
;
}
}
if
(
p_sys
->
b_fragmented
&&
!
p_sys
->
i_overall_duration
)
ProbeFragments
(
p_demux
,
true
);
if
(
p_sys
->
b_seekable
)
{
if
(
!
p_sys
->
b_fragmented
/* as unknown */
)
{
/* Probe remaining to check if there's really fragments
or if that file is just ready to append fragments */
ProbeFragments
(
p_demux
,
(
p_sys
->
i_duration
==
0
),
&
p_sys
->
b_fragmented
);
p_sys
->
b_fragmented
=
!!
MP4_BoxGet
(
p_sys
->
p_root
,
"/moof"
);
}
if
(
vlc_stream_Seek
(
p_demux
->
s
,
p_moov
->
i_pos
)
!=
VLC_SUCCESS
)
goto
error
;
...
...
@@ -977,22 +998,6 @@ static int Open( vlc_object_t * p_this )
}
}
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_mehd
->
data
.
p_mehd
)
p_sys
->
i_overall_duration
=
p_mehd
->
data
.
p_mehd
->
i_fragment_duration
;
else
{
for
(
i
=
0
;
i
<
p_sys
->
i_tracks
;
i
++
)
{
mtime_t
i_duration
=
GetTrackTotalDuration
(
&
p_sys
->
fragments
,
p_sys
->
track
[
i
].
i_track_ID
);
p_sys
->
i_overall_duration
=
__MAX
(
p_sys
->
i_overall_duration
,
(
uint64_t
)
i_duration
);
}
}
}
#ifdef MP4_VERBOSE
DumpFragments
(
VLC_OBJECT
(
p_demux
),
&
p_sys
->
fragments
,
p_sys
->
i_timescale
);
#endif
...
...
@@ -1478,7 +1483,8 @@ static int LeafSeekToTime( demux_t *p_demux, mtime_t i_nztime )
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
mp4_fragment_t
*
p_fragment
=
NULL
;
uint64_t
i64
=
0
;
if
(
!
p_sys
->
i_timescale
||
!
p_sys
->
i_overall_duration
||
!
p_sys
->
b_seekable
)
const
uint64_t
i_duration
=
__MAX
(
p_sys
->
i_duration
,
p_sys
->
i_cumulated_duration
);
if
(
!
p_sys
->
i_timescale
||
!
i_duration
||
!
p_sys
->
b_seekable
)
return
VLC_EGENERIC
;
if
(
!
p_sys
->
b_fragments_probed
&&
!
p_sys
->
b_index_probed
&&
p_sys
->
b_seekable
)
...
...
@@ -1507,7 +1513,17 @@ static int LeafSeekToTime( demux_t *p_demux, mtime_t i_nztime )
{
mtime_t
i_mooftime
;
msg_Dbg
(
p_demux
,
"seek can't find matching fragment for %"
PRId64
", trying index"
,
i_nztime
);
if
(
LeafIndexGetMoofPosByTime
(
p_demux
,
i_nztime
,
&
i64
,
&
i_mooftime
)
==
VLC_SUCCESS
)
if
(
(
uint64_t
)
MP4_rescale
(
i_nztime
,
CLOCK_FREQ
,
p_sys
->
i_timescale
)
<
p_sys
->
i_moov_duration
)
{
i64
=
p_sys
->
fragments
.
moov
.
p_moox
->
i_pos
;
i_mooftime
=
i_nztime
;
}
else
if
(
LeafIndexGetMoofPosByTime
(
p_demux
,
i_nztime
,
&
i64
,
&
i_mooftime
)
!=
VLC_SUCCESS
)
{
i64
=
UINT64_MAX
;
}
if
(
i64
!=
UINT64_MAX
)
{
msg_Dbg
(
p_demux
,
"seek trying to go to unknown but indexed fragment at %"
PRId64
,
i64
);
if
(
vlc_stream_Seek
(
p_demux
->
s
,
i64
)
)
...
...
@@ -1551,11 +1567,12 @@ static int LeafSeekToPos( demux_t *p_demux, double f )
if
(
!
p_sys
->
b_seekable
)
return
VLC_EGENERIC
;
if
(
p_sys
->
i_timescale
&&
p_sys
->
i_overall_duration
)
const
uint64_t
i_duration
=
__MAX
(
p_sys
->
i_duration
,
p_sys
->
i_cumulated_duration
);
if
(
p_sys
->
i_timescale
&&
i_duration
)
{
return
LeafSeekToTime
(
p_demux
,
(
mtime_t
)(
f
*
MP4_rescale
(
p_sys
->
i_overall
_duration
,
p_sys
->
i_timescale
,
CLOCK_FREQ
)
)
);
MP4_rescale
(
i
_duration
,
p_sys
->
i_timescale
,
CLOCK_FREQ
)
)
);
}
if
(
!
p_sys
->
b_fragments_probed
&&
!
p_sys
->
b_index_probed
&&
p_sys
->
b_seekable
)
...
...
@@ -1595,7 +1612,8 @@ 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_overall_duration
);
const
uint64_t
i_duration
=
__MAX
(
p_sys
->
i_duration
,
p_sys
->
i_cumulated_duration
);
p_sys
->
i_time
=
(
uint64_t
)(
f
*
(
double
)
i_duration
);
p_sys
->
i_pcr
=
MP4_GetMoviePTS
(
p_sys
);
for
(
unsigned
i_track
=
0
;
i_track
<
p_sys
->
i_tracks
;
i_track
++
)
...
...
@@ -1643,6 +1661,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
"/udta"
,
NULL
};
const
uint32_t
rgi_pict_atoms
[
2
]
=
{
ATOM_PICT
,
ATOM_pict
};
const
uint64_t
i_duration
=
__MAX
(
p_sys
->
i_duration
,
p_sys
->
i_cumulated_duration
);
switch
(
i_query
)
{
...
...
@@ -1652,9 +1671,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_overall
_duration
>
0
)
if
(
i
_duration
>
0
)
{
*
pf
=
(
double
)
p_sys
->
i_time
/
(
double
)
p_sys
->
i_overall
_duration
;
*
pf
=
(
double
)
p_sys
->
i_time
/
(
double
)
i
_duration
;
}
else
{
...
...
@@ -1670,7 +1689,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return
MP4_frg_Seek
(
p_demux
,
f
);
else
if
(
p_sys
->
i_timescale
>
0
)
{
i64
=
(
int64_t
)(
f
*
MP4_rescale
(
p_sys
->
i_
overall_
duration
,
i64
=
(
int64_t
)(
f
*
MP4_rescale
(
p_sys
->
i_duration
,
p_sys
->
i_timescale
,
CLOCK_FREQ
)
);
return
Seek
(
p_demux
,
i64
);
}
...
...
@@ -1697,7 +1716,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
if
(
p_sys
->
i_timescale
>
0
)
{
*
pi64
=
MP4_rescale
(
p_sys
->
i_overall
_duration
,
*
pi64
=
MP4_rescale
(
i
_duration
,
p_sys
->
i_timescale
,
CLOCK_FREQ
);
}
else
*
pi64
=
0
;
...
...
@@ -2101,8 +2120,9 @@ static void LoadChapter( demux_t *p_demux )
/* Add duration if titles are enabled */
if
(
p_sys
->
p_title
)
{
const
uint64_t
i_duration
=
__MAX
(
p_sys
->
i_duration
,
p_sys
->
i_cumulated_duration
);
p_sys
->
p_title
->
i_length
=
MP4_rescale
(
p_sys
->
i_overall
_duration
,
MP4_rescale
(
i
_duration
,
p_sys
->
i_timescale
,
CLOCK_FREQ
);
}
}
...
...
@@ -4139,7 +4159,8 @@ int DemuxFrg( demux_t *p_demux )
p_sys
->
i_time
+=
__MAX
(
p_sys
->
i_timescale
/
10
,
1
);
if
(
p_sys
->
i_timescale
>
0
)
{
int64_t
i_length
=
MP4_rescale
(
p_sys
->
i_overall_duration
,
const
uint64_t
i_duration
=
__MAX
(
p_sys
->
i_duration
,
p_sys
->
i_cumulated_duration
);
int64_t
i_length
=
MP4_rescale
(
i_duration
,
p_sys
->
i_timescale
,
CLOCK_FREQ
);
if
(
MP4_GetMoviePTS
(
p_sys
)
>=
i_length
)
return
VLC_DEMUXER_EOF
;
...
...
@@ -4253,12 +4274,12 @@ static bool AddFragment( demux_t *p_demux, MP4_Box_t *p_moox )
if
(
(
p_mvhd
=
MP4_BoxGet
(
p_moox
,
"mvhd"
))
)
{
p_sys
->
i_timescale
=
BOXDATA
(
p_mvhd
)
->
i_timescale
;
p_sys
->
i_
overall
_duration
=
BOXDATA
(
p_mvhd
)
->
i_duration
;
p_sys
->
i_
cumulated
_duration
=
BOXDATA
(
p_mvhd
)
->
i_duration
;
}
else
{
p_sys
->
i_timescale
=
CLOCK_FREQ
;
p_sys
->
i_
overall
_duration
=
CLOCK_FREQ
;
p_sys
->
i_
cumulated
_duration
=
CLOCK_FREQ
;
msg_Warn
(
p_demux
,
"No valid mvhd found"
);
}
...
...
@@ -4471,13 +4492,12 @@ static bool AddFragment( demux_t *p_demux, MP4_Box_t *p_moox )
if
(
!
p_mehd
)
{
if
(
p_sys
->
b_fragments_probed
)
p_sys
->
i_
overall
_duration
=
SumFragmentsDurations
(
p_demux
);
p_sys
->
i_
cumulated
_duration
=
SumFragmentsDurations
(
p_demux
);
}
else
p_sys
->
i_overall_duration
=
BOXDATA
(
p_mehd
)
->
i_fragment_duration
;
msg_Dbg
(
p_demux
,
"total fragments duration %"
PRId64
,
MP4_rescale
(
p_sys
->
i_overall_duration
,
p_sys
->
i_timescale
,
CLOCK_FREQ
)
);
const
uint64_t
i_duration
=
__MAX
(
p_sys
->
i_duration
,
p_sys
->
i_cumulated_duration
);
msg_Dbg
(
p_demux
,
"total fragments duration %"
PRId64
,
MP4_rescale
(
i_duration
,
p_sys
->
i_timescale
,
CLOCK_FREQ
)
);
return
true
;
}
...
...
@@ -4520,7 +4540,7 @@ static int ProbeIndex( demux_t *p_demux )
return
vlc_stream_Seek
(
p_demux
->
s
,
i_backup_pos
);
}
static
int
ProbeFragments
(
demux_t
*
p_demux
,
bool
b_force
)
static
int
ProbeFragments
(
demux_t
*
p_demux
,
bool
b_force
,
bool
*
pb_fragmented
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
uint64_t
i_current_pos
=
vlc_stream_Tell
(
p_demux
->
s
);
...
...
@@ -4533,6 +4553,7 @@ static int ProbeFragments( demux_t *p_demux, bool b_force )
{
MP4_ReadBoxContainerChildren
(
p_demux
->
s
,
p_sys
->
p_root
,
NULL
);
/* Get the rest of the file */
p_sys
->
b_fragments_probed
=
true
;
*
pb_fragmented
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moof"
);
}
else
{
...
...
@@ -4540,6 +4561,12 @@ static int ProbeFragments( demux_t *p_demux, bool b_force )
* and we'll find others while reading. */
const
uint32_t
excllist
[]
=
{
ATOM_moof
,
0
};
MP4_ReadBoxContainerRestricted
(
p_demux
->
s
,
p_sys
->
p_root
,
NULL
,
excllist
);
/* Peek since we stopped before restriction */
const
uint8_t
*
p_peek
;
if
(
vlc_stream_Peek
(
p_demux
->
s
,
&
p_peek
,
8
)
==
8
)
*
pb_fragmented
=
(
VLC_FOURCC
(
p_peek
[
4
],
p_peek
[
5
],
p_peek
[
6
],
p_peek
[
7
]
)
==
ATOM_moof
);
else
*
pb_fragmented
=
false
;
}
if
(
!
MP4_Fragment_Moov
(
&
p_sys
->
fragments
)
->
p_moox
)
...
...
@@ -5012,6 +5039,7 @@ static int LeafIndexGetMoofPosByTime( demux_t *p_demux, const mtime_t i_target_t
mp4_track_t
*
p_track
=
MP4_frg_GetTrackByID
(
p_demux
,
p_data
->
i_track_ID
);
if
(
p_track
&&
(
p_track
->
fmt
.
i_cat
==
AUDIO_ES
||
p_track
->
fmt
.
i_cat
==
VIDEO_ES
)
)
{
uint64_t
i_track_target_time
=
MP4_rescale
(
i_target_time
,
CLOCK_FREQ
,
p_track
->
i_timescale
);
for
(
uint32_t
i
=
0
;
i
<
p_data
->
i_number_of_entries
;
i
+=
(
p_data
->
i_version
==
1
)
?
2
:
1
)
{
mtime_t
i_time
;
...
...
@@ -5027,7 +5055,7 @@ static int LeafIndexGetMoofPosByTime( demux_t *p_demux, const mtime_t i_target_t
i_offset
=
p_data
->
p_moof_offset
[
i
];
}
if
(
MP4_rescale
(
i_time
,
p_track
->
i_timescale
,
CLOCK_FREQ
)
>=
i
_target_time
)
if
(
(
uint64_t
)
i_time
>=
i_track
_target_time
)
{
if
(
i_pos
==
-
1
)
/* Not in this traf */
break
;
...
...
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