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
15
Merge Requests
15
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
477e5dad
Commit
477e5dad
authored
Oct 11, 2015
by
François Cartegnie
🤞
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
demux: mp4: split fragment related code
parent
3f8fdb32
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
396 additions
and
205 deletions
+396
-205
modules/demux/Makefile.am
modules/demux/Makefile.am
+1
-0
modules/demux/mp4/fragments.c
modules/demux/mp4/fragments.c
+244
-0
modules/demux/mp4/fragments.h
modules/demux/mp4/fragments.h
+82
-0
modules/demux/mp4/mp4.c
modules/demux/mp4/mp4.c
+68
-190
modules/demux/mp4/mp4.h
modules/demux/mp4/mp4.h
+1
-15
No files found.
modules/demux/Makefile.am
View file @
477e5dad
...
...
@@ -193,6 +193,7 @@ demux_LTLIBRARIES += $(LTLIBmkv)
EXTRA_LTLIBRARIES
+=
libmkv_plugin.la
libmp4_plugin_la_SOURCES
=
demux/mp4/mp4.c demux/mp4/mp4.h
\
demux/mp4/fragments.c demux/mp4/fragments.h
\
demux/mp4/libmp4.c demux/mp4/libmp4.h
\
demux/mp4/id3genres.h demux/mp4/languages.h
\
demux/asf/asfpacket.c demux/asf/asfpacket.h
\
...
...
modules/demux/mp4/fragments.c
0 → 100644
View file @
477e5dad
/*****************************************************************************
* fragments.c : MP4 fragments
*****************************************************************************
* Copyright (C) 2001-2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "fragments.h"
mp4_fragment_t
*
MP4_Fragment_New
(
MP4_Box_t
*
p_atom
,
unsigned
i_tracks
)
{
mp4_fragment_t
*
p_new
=
calloc
(
1
,
sizeof
(
mp4_fragment_t
)
);
if
(
p_new
)
{
p_new
->
p_moox
=
p_atom
;
p_new
->
p_durations
=
calloc
(
i_tracks
,
sizeof
(
*
p_new
->
p_durations
)
);
if
(
!
p_new
->
p_durations
)
{
free
(
p_new
);
return
NULL
;
}
p_new
->
i_durations
=
i_tracks
;
}
return
p_new
;
}
void
MP4_Fragment_Clean
(
mp4_fragment_t
*
p_fragment
)
{
free
(
p_fragment
->
p_durations
);
}
void
MP4_Fragments_Clean
(
mp4_fragments_t
*
p_frags
)
{
while
(
p_frags
->
moov
.
p_next
)
{
mp4_fragment_t
*
p_fragment
=
p_frags
->
moov
.
p_next
->
p_next
;
MP4_Fragment_Clean
(
p_frags
->
moov
.
p_next
);
free
(
p_frags
->
moov
.
p_next
);
p_frags
->
moov
.
p_next
=
p_fragment
;
}
MP4_Fragment_Clean
(
&
p_frags
->
moov
);
}
void
MP4_Fragments_Insert
(
mp4_fragments_t
*
p_frags
,
mp4_fragment_t
*
p_new
)
{
mp4_fragment_t
*
p_fragment
=
p_frags
->
p_last
;
/* tail append lookup */
if
(
p_fragment
&&
p_fragment
->
p_moox
->
i_pos
<
p_new
->
p_moox
->
i_pos
)
{
p_new
->
p_next
=
p_fragment
->
p_next
;
p_fragment
->
p_next
=
p_new
;
p_frags
->
p_last
=
p_new
;
return
;
}
/* start from head */
p_fragment
=
MP4_Fragment_Moov
(
p_frags
)
->
p_next
;
while
(
p_fragment
&&
p_fragment
->
p_moox
->
i_pos
<
p_new
->
p_moox
->
i_pos
)
{
p_fragment
=
p_fragment
->
p_next
;
}
if
(
p_fragment
)
{
p_new
->
p_next
=
p_fragment
->
p_next
;
p_fragment
->
p_next
=
p_new
;
if
(
p_fragment
==
p_frags
->
p_last
)
p_frags
->
p_last
=
p_new
;
}
else
{
MP4_Fragment_Moov
(
p_frags
)
->
p_next
=
p_new
;
p_frags
->
p_last
=
p_new
;
}
}
bool
MP4_Fragments_Init
(
mp4_fragments_t
*
p_frags
)
{
memset
(
&
p_frags
->
moov
,
0
,
sizeof
(
mp4_fragment_t
)
);
return
true
;
}
static
stime_t
GetTrackDurationInFragment
(
const
mp4_fragment_t
*
p_fragment
,
unsigned
int
i_track_ID
)
{
for
(
unsigned
int
i
=
0
;
i
<
p_fragment
->
i_durations
;
i
++
)
{
if
(
i_track_ID
==
p_fragment
->
p_durations
[
i
].
i_track_ID
)
return
p_fragment
->
p_durations
[
i
].
i_duration
;
}
return
0
;
}
stime_t
GetTrackTotalDuration
(
mp4_fragments_t
*
p_frags
,
unsigned
int
i_track_ID
)
{
stime_t
i_duration
=
0
;
const
mp4_fragment_t
*
p_fragment
=
MP4_Fragment_Moov
(
p_frags
);
while
(
p_fragment
&&
p_fragment
->
p_durations
)
{
i_duration
+=
GetTrackDurationInFragment
(
p_fragment
,
i_track_ID
);
p_fragment
=
p_fragment
->
p_next
;
}
return
i_duration
;
}
mp4_fragment_t
*
GetFragmentByAtomPos
(
mp4_fragments_t
*
p_frags
,
uint64_t
i_pos
)
{
mp4_fragment_t
*
p_fragment
=
MP4_Fragment_Moov
(
p_frags
);
do
{
if
(
p_fragment
&&
p_fragment
->
p_moox
&&
p_fragment
->
p_moox
->
i_pos
>=
i_pos
)
{
if
(
p_fragment
->
p_moox
->
i_pos
!=
i_pos
)
p_fragment
=
NULL
;
break
;
}
p_fragment
=
p_fragment
->
p_next
;
}
while
(
p_fragment
);
return
p_fragment
;
}
mp4_fragment_t
*
GetFragmentByPos
(
mp4_fragments_t
*
p_frags
,
uint64_t
i_pos
,
bool
b_exact
)
{
mp4_fragment_t
*
p_fragment
=
MP4_Fragment_Moov
(
p_frags
);
while
(
p_fragment
)
{
if
(
i_pos
<=
p_fragment
->
i_chunk_range_max_offset
&&
(
!
b_exact
||
i_pos
>=
p_fragment
->
i_chunk_range_min_offset
)
)
{
return
p_fragment
;
}
else
{
p_fragment
=
p_fragment
->
p_next
;
}
}
return
NULL
;
}
/* Get a matching fragment data start by clock time */
mp4_fragment_t
*
GetFragmentByTime
(
mp4_fragments_t
*
p_frags
,
const
mtime_t
i_time
,
unsigned
i_tracks_id
,
unsigned
*
pi_tracks_id
,
uint32_t
i_movie_timescale
)
{
const
stime_t
i_scaled_time
=
i_time
*
i_movie_timescale
/
CLOCK_FREQ
;
mp4_fragment_t
*
p_fragment
=
MP4_Fragment_Moov
(
p_frags
);
stime_t
*
pi_tracks_fragduration_total
=
calloc
(
i_tracks_id
,
sizeof
(
stime_t
)
);
mtime_t
i_segment_start
=
0
;
if
(
p_fragment
->
i_chunk_range_max_offset
==
0
)
p_fragment
=
p_fragment
->
p_next
;
while
(
p_fragment
&&
pi_tracks_fragduration_total
)
{
mtime_t
i_segment_end
=
0
;
for
(
unsigned
int
i
=
0
;
i
<
i_tracks_id
;
i
++
)
{
pi_tracks_fragduration_total
[
i
]
+=
GetTrackDurationInFragment
(
p_fragment
,
pi_tracks_id
[
i
]
);
i_segment_end
=
__MAX
(
i_segment_end
,
pi_tracks_fragduration_total
[
i
]);
}
if
(
i_scaled_time
>=
i_segment_start
&&
i_scaled_time
<=
i_segment_end
)
{
free
(
pi_tracks_fragduration_total
);
return
p_fragment
;
}
else
{
i_segment_start
=
i_segment_end
;
/* end = next segment start */
p_fragment
=
p_fragment
->
p_next
;
}
}
free
(
pi_tracks_fragduration_total
);
return
NULL
;
}
/* Returns fragment scaled time offset */
stime_t
GetTrackFragmentTimeOffset
(
mp4_fragments_t
*
p_frags
,
mp4_fragment_t
*
p_fragment
,
unsigned
int
i_track_ID
)
{
stime_t
i_base_scaledtime
=
0
;
mp4_fragment_t
*
p_current
=
MP4_Fragment_Moov
(
p_frags
);
while
(
p_current
!=
p_fragment
)
{
if
(
p_current
!=
MP4_Fragment_Moov
(
p_frags
)
||
p_current
->
i_chunk_range_max_offset
)
{
i_base_scaledtime
+=
GetTrackDurationInFragment
(
p_current
,
i_track_ID
);
}
p_current
=
p_current
->
p_next
;
}
return
i_base_scaledtime
;
}
void
DumpFragments
(
vlc_object_t
*
p_obj
,
mp4_fragments_t
*
p_frags
,
uint32_t
i_movie_timescale
)
{
mtime_t
i_total_duration
=
0
;
const
mp4_fragment_t
*
p_fragment
=
MP4_Fragment_Moov
(
p_frags
);
while
(
p_fragment
)
{
char
*
psz_durations
=
NULL
;
mtime_t
i_frag_duration
=
0
;
for
(
unsigned
i
=
0
;
i
<
p_fragment
->
i_durations
;
i
++
)
{
if
(
i
==
0
)
i_frag_duration
+=
CLOCK_FREQ
*
p_fragment
->
p_durations
[
0
].
i_duration
/
i_movie_timescale
;
char
*
psz_duration
=
NULL
;
if
(
0
<
asprintf
(
&
psz_duration
,
"%s [%u]%"
PRId64
" "
,
(
psz_durations
)
?
psz_durations
:
""
,
p_fragment
->
p_durations
[
i
].
i_track_ID
,
CLOCK_FREQ
*
p_fragment
->
p_durations
[
i
].
i_duration
/
i_movie_timescale
)
)
{
free
(
psz_durations
);
psz_durations
=
psz_duration
;
}
}
msg_Dbg
(
p_obj
,
"fragment offset %"
PRId64
", data %"
PRIu64
"<->%"
PRIu64
" @%"
PRId64
", durations %s"
,
p_fragment
->
p_moox
->
i_pos
,
p_fragment
->
i_chunk_range_min_offset
,
p_fragment
->
i_chunk_range_max_offset
,
i_total_duration
,
psz_durations
);
free
(
psz_durations
);
i_total_duration
+=
i_frag_duration
;
p_fragment
=
p_fragment
->
p_next
;
}
}
modules/demux/mp4/fragments.h
0 → 100644
View file @
477e5dad
/*****************************************************************************
* fragments.h : MP4 fragments
*****************************************************************************
* Copyright (C) 2001-2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef _VLC_FRAGMENTS_H
#define _VLC_FRAGMENTS_H 1
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include "libmp4.h"
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
;
struct
{
unsigned
int
i_track_ID
;
stime_t
i_duration
;
// movie scaled
}
*
p_durations
;
unsigned
int
i_durations
;
MP4_Box_t
*
p_moox
;
mp4_fragment_t
*
p_next
;
};
typedef
struct
{
mp4_fragment_t
moov
;
/* known fragments (moof following moov) */
mp4_fragment_t
*
p_last
;
}
mp4_fragments_t
;
static
inline
mp4_fragment_t
*
MP4_Fragment_Moov
(
mp4_fragments_t
*
p_fragments
)
{
return
&
p_fragments
->
moov
;
}
mp4_fragment_t
*
MP4_Fragment_New
(
MP4_Box_t
*
,
unsigned
);
void
MP4_Fragment_Clean
(
mp4_fragment_t
*
);
static
inline
void
MP4_Fragment_Delete
(
mp4_fragment_t
*
p_fragment
)
{
MP4_Fragment_Clean
(
p_fragment
);
free
(
p_fragment
);
}
bool
MP4_Fragments_Init
(
mp4_fragments_t
*
);
void
MP4_Fragments_Clean
(
mp4_fragments_t
*
);
void
MP4_Fragments_Insert
(
mp4_fragments_t
*
,
mp4_fragment_t
*
);
stime_t
GetTrackTotalDuration
(
mp4_fragments_t
*
p_frags
,
unsigned
int
i_track_ID
);
mp4_fragment_t
*
GetFragmentByAtomPos
(
mp4_fragments_t
*
p_frags
,
uint64_t
i_pos
);
mp4_fragment_t
*
GetFragmentByPos
(
mp4_fragments_t
*
p_frags
,
uint64_t
i_pos
,
bool
b_exact
);
mp4_fragment_t
*
GetFragmentByTime
(
mp4_fragments_t
*
p_frags
,
const
mtime_t
i_time
,
unsigned
i_tracks_id
,
unsigned
*
pi_tracks_id
,
uint32_t
i_movie_timescale
);
stime_t
GetTrackFragmentTimeOffset
(
mp4_fragments_t
*
p_frags
,
mp4_fragment_t
*
p_fragment
,
unsigned
int
i_track_ID
);
void
DumpFragments
(
vlc_object_t
*
p_obj
,
mp4_fragments_t
*
p_frags
,
uint32_t
i_movie_timescale
);
#endif
modules/demux/mp4/mp4.c
View file @
477e5dad
...
...
@@ -88,8 +88,8 @@ struct demux_sys_t
bool
b_index_probed
;
bool
b_fragments_probed
;
mp4_fragment_t
moovfragment
;
/* moov */
mp4_fragment
_t
*
p_fragments
;
/* known fragments (moof following moov) */
mp4_fragment
s_t
fragments
;
struct
{
...
...
@@ -144,12 +144,9 @@ static void MP4_GetDefaultSizeAndDuration( demux_t *p_demux,
static
bool
AddFragment
(
demux_t
*
p_demux
,
MP4_Box_t
*
p_moox
);
static
int
ProbeFragments
(
demux_t
*
p_demux
,
bool
b_force
);
static
int
ProbeIndex
(
demux_t
*
p_demux
);
static
mp4_fragment_t
*
GetFragmentByPos
(
demux_t
*
p_demux
,
uint64_t
i_pos
,
bool
b_exact
);
static
mp4_fragment_t
*
GetFragmentByTime
(
demux_t
*
p_demux
,
const
mtime_t
i_time
);
static
int
LeafIndexGetMoofPosByTime
(
demux_t
*
p_demux
,
const
mtime_t
i_target_time
,
uint64_t
*
pi_pos
,
mtime_t
*
pi_mooftime
);
static
mtime_t
LeafGetTrackFragmentTimeOffset
(
demux_t
*
p_demux
,
mp4_fragment_t
*
,
unsigned
int
);
static
int
LeafGetTrackAndChunkByMOOVPos
(
demux_t
*
p_demux
,
uint64_t
*
pi_pos
,
mp4_track_t
**
pp_tk
,
unsigned
int
*
pi_chunk
);
static
int
LeafMapTrafTrunContextes
(
demux_t
*
p_demux
,
MP4_Box_t
*
p_moof
);
...
...
@@ -188,17 +185,6 @@ static bool MP4_stream_Tell( stream_t *s, uint64_t *pi_pos )
}
}
static
mtime_t
GetTrackDurationInFragment
(
const
mp4_fragment_t
*
p_fragment
,
unsigned
int
i_track_ID
)
{
for
(
unsigned
int
i
=
0
;
i
<
p_fragment
->
i_durations
;
i
++
)
{
if
(
i_track_ID
==
p_fragment
->
p_durations
[
i
].
i_track_ID
)
return
p_fragment
->
p_durations
[
i
].
i_duration
;
}
return
0
;
}
static
MP4_Box_t
*
MP4_GetTrexByTrackID
(
MP4_Box_t
*
p_moov
,
const
uint32_t
i_id
)
{
if
(
!
p_moov
)
...
...
@@ -606,6 +592,8 @@ static int Open( vlc_object_t * p_this )
p_sys
->
context
.
i_lastseqnumber
=
1
;
MP4_Fragments_Init
(
&
p_sys
->
fragments
);
p_demux
->
p_sys
=
p_sys
;
if
(
stream_Peek
(
p_demux
->
s
,
&
p_peek
,
24
)
<
24
)
return
VLC_EGENERIC
;
...
...
@@ -687,11 +675,11 @@ static int Open( vlc_object_t * p_this )
p_sys
->
b_fragmented
=
true
;
}
if
(
!
p_sys
->
moovfragment
.
p_moox
)
if
(
!
MP4_Fragment_Moov
(
&
p_sys
->
fragments
)
->
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
)
if
(
!
MP4_Fragment_Moov
(
&
p_sys
->
fragments
)
->
p_moox
&&
!
p_sys
->
b_smooth
)
goto
error
;
MP4_BoxDumpStructure
(
p_demux
->
s
,
p_sys
->
p_root
);
...
...
@@ -718,8 +706,8 @@ static int Open( vlc_object_t * p_this )
}
/* the file need to have one moov box */
p_sys
->
moovfragment
.
p_moox
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov"
,
0
);
if
(
!
p_sys
->
moovfragment
.
p_moox
)
MP4_Fragment_Moov
(
&
p_sys
->
fragments
)
->
p_moox
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov"
,
0
);
if
(
!
MP4_Fragment_Moov
(
&
p_sys
->
fragments
)
->
p_moox
)
{
MP4_Box_t
*
p_foov
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/foov"
);
...
...
@@ -730,7 +718,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
;
MP4_Fragment_Moov
(
&
p_sys
->
fragments
)
->
p_moox
=
p_foov
;
}
if
(
(
p_rmra
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov/rmra"
)
)
)
...
...
@@ -919,29 +907,14 @@ static int Open( vlc_object_t * p_this )
{
for
(
i
=
0
;
i
<
p_sys
->
i_tracks
;
i
++
)
{
mtime_t
i_duration
=
GetTrackDurationInFragment
(
&
p_sys
->
moovfragment
,
p_sys
->
track
[
i
].
i_track_ID
);
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
mtime_t
i_total_duration
=
0
;
mp4_fragment_t
*
p_fragment
=
&
p_sys
->
moovfragment
;
while
(
p_fragment
&&
p_sys
->
i_tracks
)
{
if
(
(
p_fragment
!=
&
p_sys
->
moovfragment
||
p_fragment
->
i_chunk_range_max_offset
)
&&
p_fragment
->
i_durations
&&
p_fragment
->
p_durations
[
0
].
i_track_ID
==
p_sys
->
track
[
0
].
i_track_ID
)
i_total_duration
+=
CLOCK_FREQ
*
p_fragment
->
p_durations
[
0
].
i_duration
/
p_sys
->
i_timescale
;
msg_Dbg
(
p_demux
,
"fragment offset %"
PRId64
", data %"
PRIu64
"<->%"
PRIu64
", "
"duration %"
PRId64
" @%"
PRId64
,
p_fragment
->
p_moox
->
i_pos
,
p_fragment
->
i_chunk_range_min_offset
,
p_fragment
->
i_chunk_range_max_offset
,
(
p_fragment
->
i_durations
&&
p_fragment
->
p_durations
[
0
].
i_track_ID
==
p_sys
->
track
[
0
].
i_track_ID
)
?
CLOCK_FREQ
*
p_fragment
->
p_durations
[
0
].
i_duration
/
p_sys
->
i_timescale
:
0
,
i_total_duration
);
p_fragment
=
p_fragment
->
p_next
;
}
DumpFragments
(
VLC_OBJECT
(
p_demux
),
&
p_sys
->
fragments
,
p_sys
->
i_timescale
);
#endif
if
(
!
p_sys
->
b_fragmented
&&
p_sys
->
i_tracks
>
1
&&
p_sys
->
b_seekable
&&
!
p_sys
->
b_seekmode
)
...
...
@@ -1268,7 +1241,7 @@ static int LeafSeekIntoFragment( demux_t *p_demux, mp4_fragment_t *p_fragment )
mtime_t
i_time_base
=
0
;
for
(
unsigned
int
i_track
=
0
;
i_track
<
p_sys
->
i_tracks
;
i_track
++
)
{
mtime_t
i_tracktime
=
LeafGetTrackFragmentTimeOffset
(
p_demux
,
p_fragment
,
stime_t
i_tracktime
=
GetTrackFragmentTimeOffset
(
&
p_sys
->
fragments
,
p_fragment
,
p_sys
->
track
[
i_track
].
i_track_ID
);
p_sys
->
track
[
i_track
].
i_time
=
i_tracktime
*
p_sys
->
track
[
i_track
].
i_timescale
/
p_sys
->
i_timescale
;
i_time_base
=
__MIN
(
i_time_base
,
i_tracktime
);
...
...
@@ -1293,7 +1266,22 @@ static int LeafSeekToTime( demux_t *p_demux, mtime_t i_nztime )
p_sys
->
b_index_probed
=
true
;
}
p_fragment
=
GetFragmentByTime
(
p_demux
,
i_nztime
);
if
(
p_demux
->
p_sys
->
b_fragments_probed
)
{
/* Fill out temp track ID list */
unsigned
*
pi_tracksid
=
(
unsigned
*
)
malloc
(
sizeof
(
unsigned
)
*
p_sys
->
i_tracks
);
if
(
pi_tracksid
)
{
for
(
unsigned
i
=
0
;
i
<
p_sys
->
i_tracks
;
i
++
)
pi_tracksid
[
i
]
=
p_sys
->
track
[
i
].
i_track_ID
;
p_fragment
=
GetFragmentByTime
(
&
p_sys
->
fragments
,
i_nztime
,
p_sys
->
i_tracks
,
pi_tracksid
,
p_sys
->
i_timescale
);
free
(
pi_tracksid
);
}
}
if
(
!
p_fragment
)
{
mtime_t
i_mooftime
;
...
...
@@ -1357,9 +1345,12 @@ static int LeafSeekToPos( demux_t *p_demux, double f )
/* Blind seek to pos only */
uint64_t
i64
=
(
uint64_t
)
stream_Size
(
p_demux
->
s
)
*
f
;
mp4_fragment_t
*
p_fragment
=
GetFragmentByPos
(
p_demux
,
i64
,
false
);
mp4_fragment_t
*
p_fragment
=
GetFragmentByPos
(
&
p_sys
->
fragments
,
i64
,
false
);
if
(
p_fragment
)
{
msg_Dbg
(
p_demux
,
"fragment matched %"
PRIu64
" << %"
PRIu64
" << %"
PRIu64
,
p_fragment
->
i_chunk_range_min_offset
,
i64
,
p_fragment
->
i_chunk_range_max_offset
);
msg_Dbg
(
p_demux
,
"Seeking to fragment data starting at %"
PRIu64
" for pos %"
PRIu64
,
p_fragment
->
i_chunk_range_min_offset
,
i64
);
return
LeafSeekIntoFragment
(
p_demux
,
p_fragment
);
...
...
@@ -1740,14 +1731,7 @@ 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_durations
);
free
(
p_sys
->
moovfragment
.
p_next
);
p_sys
->
moovfragment
.
p_next
=
p_fragment
;
}
free
(
p_sys
->
moovfragment
.
p_durations
);
MP4_Fragments_Clean
(
&
p_sys
->
fragments
);
free
(
p_sys
);
}
...
...
@@ -1955,11 +1939,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
);
mp4_fragment_t
*
p_moovfragment
=
MP4_Fragment_Moov
(
&
p_sys
->
fragments
);
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_
moovfragment
->
i_chunk_range_min_offset
==
0
||
p_
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
;
p_
moovfragment
->
i_chunk_range_min_offset
=
p_demux_track
->
chunk
[
0
].
i_offset
;
return
VLC_SUCCESS
;
}
...
...
@@ -2082,8 +2067,8 @@ static int TrackCreateSamplesIndex( demux_t *p_demux,
}
}
if
(
i_total_size
>
p_sys
->
moovfragment
.
i_chunk_range_max_offset
)
p_sys
->
moovfragment
.
i_chunk_range_max_offset
=
i_total_size
;
if
(
i_total_size
>
MP4_Fragment_Moov
(
&
p_sys
->
fragments
)
->
i_chunk_range_max_offset
)
MP4_Fragment_Moov
(
&
p_sys
->
fragments
)
->
i_chunk_range_max_offset
=
i_total_size
;
}
/* Use stts table to create a sample number -> dts table.
...
...
@@ -4152,14 +4137,8 @@ static mtime_t SumFragmentsDurations( demux_t *p_demux )
for
(
unsigned
int
i
=
0
;
i
<
p_sys
->
i_tracks
;
i
++
)
{
mtime_t
i_duration
=
0
;
const
mp4_fragment_t
*
p_fragment
=
&
p_sys
->
moovfragment
;
while
(
p_fragment
&&
p_fragment
->
p_durations
)
{
i_duration
+=
GetTrackDurationInFragment
(
p_fragment
,
p_sys
->
track
[
i
].
i_track_ID
);
p_fragment
=
p_fragment
->
p_next
;
}
stime_t
i_duration
=
GetTrackTotalDuration
(
&
p_sys
->
fragments
,
p_sys
->
track
[
i
].
i_track_ID
);
i_max_duration
=
__MAX
(
i_duration
,
i_max_duration
);
}
...
...
@@ -4170,15 +4149,16 @@ static mtime_t SumFragmentsDurations( demux_t *p_demux )
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
;
mp4_fragment_t
*
p_moovfragment
=
MP4_Fragment_Moov
(
&
p_sys
->
fragments
);
if
(
!
p_moox
)
return
false
;
if
(
p_moox
->
i_type
==
ATOM_moov
)
{
if
(
!
p_
sys
->
moovfragment
.
p_moox
)
if
(
!
p_
moovfragment
->
p_moox
)
{
p_
sys
->
moovfragment
.
p_moox
=
p_moox
;
p_
moovfragment
->
p_moox
=
p_moox
;
MP4_Box_t
*
p_mvhd
;
if
(
(
p_mvhd
=
MP4_BoxGet
(
p_moox
,
"mvhd"
))
)
{
...
...
@@ -4191,17 +4171,17 @@ static bool AddFragment( demux_t *p_demux, MP4_Box_t *p_moox )
MP4_Box_t
*
p_tkhd
;
MP4_Box_t
*
p_trak
=
MP4_BoxGet
(
p_moox
,
"trak"
);
unsigned
int
i_trakcount
=
MP4_BoxCount
(
p_moox
,
"trak"
);
p_
sys
->
moovfragment
.
p_durations
=
calloc
(
i_trakcount
,
sizeof
(
*
p_sys
->
moovfragment
.
p_durations
)
);
if
(
i_trakcount
&&
!
p_
sys
->
moovfragment
.
p_durations
)
p_
moovfragment
->
p_durations
=
calloc
(
i_trakcount
,
sizeof
(
*
p_moovfragment
->
p_durations
)
);
if
(
i_trakcount
&&
!
p_
moovfragment
->
p_durations
)
return
0
;
p_
sys
->
moovfragment
.
i_durations
=
i_trakcount
;
p_
moovfragment
->
i_durations
=
i_trakcount
;
i_trakcount
=
0
;
while
(
p_trak
)
{
if
(
p_trak
->
i_type
==
ATOM_trak
&&
(
p_tkhd
=
MP4_BoxGet
(
p_trak
,
"tkhd"
))
)
{
p_
sys
->
moovfragment
.
p_durations
[
i_trakcount
].
i_duration
=
BOXDATA
(
p_tkhd
)
->
i_duration
;
p_
sys
->
moovfragment
.
p_durations
[
i_trakcount
++
].
i_track_ID
=
BOXDATA
(
p_tkhd
)
->
i_track_ID
;
p_
moovfragment
->
p_durations
[
i_trakcount
].
i_duration
=
BOXDATA
(
p_tkhd
)
->
i_duration
;
p_
moovfragment
->
p_durations
[
i_trakcount
++
].
i_track_ID
=
BOXDATA
(
p_tkhd
)
->
i_track_ID
;
}
p_trak
=
p_trak
->
p_next
;
}
...
...
@@ -4212,39 +4192,18 @@ static bool AddFragment( demux_t *p_demux, MP4_Box_t *p_moox )
}
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
;
}
}
}
// p_moox->i_type == ATOM_moof
assert
(
p_moox
->
i_type
==
ATOM_moof
);
mp4_fragment_t
*
p_fragment
=
GetFragmentByAtomPos
(
&
p_sys
->
fragments
,
p_moox
->
i_pos
);
if
(
p_fragment
)
return
false
;
/* Already exists */
/* 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_durations
=
MP4_BoxCount
(
p_new
->
p_moox
,
"traf"
);
p_new
->
p_durations
=
calloc
(
p_new
->
i_durations
,
sizeof
(
*
p_new
->
p_durations
)
);
if
(
p_new
->
i_durations
&&
!
p_new
->
p_durations
)
{
free
(
p_new
);