Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
Steve Lhomme
VLC
Commits
c26b4106
Commit
c26b4106
authored
Jun 13, 2015
by
François Cartegnie
🤞
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
demux: mp4: rewrite and strengthen the restart stuff
Also adds the missing restart on MP4Leaf demux mode
parent
acc5cdf9
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
144 additions
and
82 deletions
+144
-82
modules/demux/mp4/mp4.c
modules/demux/mp4/mp4.c
+144
-82
No files found.
modules/demux/mp4/mp4.c
View file @
c26b4106
...
...
@@ -113,8 +113,9 @@ struct demux_sys_t
/*****************************************************************************
* Declaration of local function
*****************************************************************************/
static
void
MP4_TrackCreate
(
demux_t
*
,
mp4_track_t
*
,
MP4_Box_t
*
,
bool
b_force_enable
);
static
int
MP4_SmoothTrackCreate
(
demux_t
*
,
mp4_track_t
*
,
const
MP4_Box_t
*
);
static
void
MP4_TrackCreate
(
demux_t
*
,
mp4_track_t
*
,
MP4_Box_t
*
,
bool
,
bool
);
static
int
MP4_SmoothTrackCreate
(
demux_t
*
,
mp4_track_t
*
,
const
mp4_chunk_t
*
,
const
MP4_Box_t
*
,
bool
);
static
void
MP4_TrackDestroy
(
demux_t
*
,
mp4_track_t
*
);
static
block_t
*
MP4_Block_Read
(
demux_t
*
,
const
mp4_track_t
*
,
int
);
...
...
@@ -417,7 +418,7 @@ static int CreateTracksFromSmooBox( demux_t *p_demux )
BOXDATA
(
p_stra
)
&&
BOXDATA
(
p_stra
)
->
i_track_ID
>
0
)
{
mp4_track_t
*
p_track
=
&
p_sys
->
track
[
j
++
];
MP4_SmoothTrackCreate
(
p_demux
,
p_track
,
p_
s
tra
);
MP4_SmoothTrackCreate
(
p_demux
,
p_track
,
p_tra
ck
->
cchunk
,
p_stra
,
true
);
}
p_stra
=
p_stra
->
p_next
;
}
...
...
@@ -863,7 +864,7 @@ static int Open( vlc_object_t * p_this )
for
(
i
=
0
;
i
<
p_sys
->
i_tracks
;
i
++
)
{
p_trak
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov/trak[%d]"
,
i
);
MP4_TrackCreate
(
p_demux
,
&
p_sys
->
track
[
i
],
p_trak
,
!
b_enabled_es
);
MP4_TrackCreate
(
p_demux
,
&
p_sys
->
track
[
i
],
p_trak
,
true
,
!
b_enabled_es
);
if
(
p_sys
->
track
[
i
].
b_ok
&&
!
p_sys
->
track
[
i
].
b_chapter
)
{
...
...
@@ -2617,6 +2618,84 @@ static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
return
p_track
->
b_selected
?
VLC_SUCCESS
:
VLC_EGENERIC
;
}
static
void
MP4_TrackRestart
(
demux_t
*
p_demux
,
mp4_track_t
*
p_track
,
MP4_Box_t
*
p_params_box
)
{
bool
b_reselect
=
false
;
if
(
p_track
->
p_es
)
{
es_out_Control
(
p_demux
->
out
,
ES_OUT_GET_ES_STATE
,
p_track
->
p_es
,
&
b_reselect
);
}
/* Save previous fragmented pos */
uint32_t
i_sample_pos_backup
=
p_track
->
i_sample
;
mp4_chunk_t
*
cchunk_backup
=
p_track
->
cchunk
;
p_track
->
cchunk
=
NULL
;
mtime_t
time_backup
=
p_track
->
i_time
*
p_track
->
i_timescale
;
/* Save previous format and ES */
es_format_t
fmtbackup
;
es_out_id_t
*
p_es_backup
=
p_track
->
p_es
;
p_track
->
p_es
=
NULL
;
es_format_Init
(
&
fmtbackup
,
UNKNOWN_ES
,
0
);
es_format_Copy
(
&
fmtbackup
,
&
p_track
->
fmt
);
es_format_Clean
(
&
p_track
->
fmt
);
/* do the cleanup and recycle track / restart */
MP4_TrackDestroy
(
p_demux
,
p_track
);
memset
(
p_track
,
0
,
sizeof
(
*
p_track
)
);
if
(
p_demux
->
p_sys
->
b_smooth
)
{
assert
(
p_params_box
->
i_type
==
ATOM_uuid
&&
!
CmpUUID
(
&
p_params_box
->
i_uuid
,
&
StraBoxUUID
)
);
MP4_SmoothTrackCreate
(
p_demux
,
p_track
,
cchunk_backup
,
p_params_box
,
false
);
}
else
{
assert
(
p_params_box
->
i_type
==
ATOM_trak
);
MP4_TrackCreate
(
p_demux
,
p_track
,
p_params_box
,
false
,
true
);
}
if
(
p_track
->
b_ok
)
{
if
(
!
es_format_IsSimilar
(
&
fmtbackup
,
&
p_track
->
fmt
)
||
fmtbackup
.
i_extra
!=
p_track
->
fmt
.
i_extra
||
memcmp
(
&
fmtbackup
.
p_extra
,
&
p_track
->
fmt
.
p_extra
,
fmtbackup
.
i_extra
)
)
{
if
(
p_es_backup
)
es_out_Del
(
p_demux
->
out
,
p_es_backup
);
if
(
!
p_track
->
b_chapter
)
{
p_track
->
p_es
=
es_out_Add
(
p_demux
->
out
,
&
p_track
->
fmt
);
p_track
->
b_ok
=
!!
p_track
->
p_es
;
}
}
else
{
p_track
->
p_es
=
p_es_backup
;
}
}
else
if
(
p_es_backup
)
{
es_out_Del
(
p_demux
->
out
,
p_es_backup
);
}
/* select again the new decoder */
if
(
b_reselect
&&
p_track
->
p_es
)
es_out_Control
(
p_demux
->
out
,
ES_OUT_SET_ES
,
p_track
->
p_es
);
es_format_Clean
(
&
fmtbackup
);
/* Restore fragmented pos */
p_track
->
cchunk
=
cchunk_backup
;
p_track
->
i_sample
=
i_sample_pos_backup
;
if
(
p_track
->
i_timescale
)
p_track
->
i_time
=
time_backup
/
p_track
->
i_timescale
;
}
/****************************************************************************
* MP4_TrackCreate:
****************************************************************************
...
...
@@ -2625,7 +2704,7 @@ static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
****************************************************************************/
static
void
MP4_TrackCreate
(
demux_t
*
p_demux
,
mp4_track_t
*
p_track
,
MP4_Box_t
*
p_box_trak
,
bool
b_force_enable
)
bool
b_create_es
,
bool
b_force_enable
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
...
...
@@ -2633,15 +2712,6 @@ static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
char
language
[
4
]
=
{
'\0'
};
/* hint track unsupported */
/* set default value (-> track unusable) */
p_track
->
b_ok
=
false
;
p_track
->
b_enable
=
false
;
p_track
->
b_selected
=
false
;
p_track
->
b_chapter
=
false
;
p_track
->
b_mac_encoding
=
false
;
es_format_Init
(
&
p_track
->
fmt
,
UNKNOWN_ES
,
0
);
const
MP4_Box_t
*
p_tkhd
=
MP4_BoxGet
(
p_box_trak
,
"tkhd"
);
...
...
@@ -2850,17 +2920,16 @@ static void MP4_TrackCreate( demux_t *p_demux, mp4_track_t *p_track,
}
}
p_track
->
p_es
=
NULL
;
if
(
TrackCreateES
(
p_demux
,
p_track
,
p_track
->
i_chunk
,
p_track
->
b_chapter
?
NULL
:
&
p_track
->
p_es
)
)
(
p_track
->
b_chapter
||
!
b_create_es
)
?
NULL
:
&
p_track
->
p_es
)
)
{
msg_Err
(
p_demux
,
"cannot create es for track[Id 0x%x]"
,
p_track
->
i_track_ID
);
return
;
}
p_track
->
b_ok
=
p_track
->
b_chapter
||
!!
p_track
->
p_es
;
p_track
->
b_ok
=
true
;
}
static
void
DestroyChunk
(
mp4_chunk_t
*
ck
)
...
...
@@ -3313,24 +3382,22 @@ static void MP4_TrackSetELST( demux_t *p_demux, mp4_track_t *tk,
* It computes the sample rate for a video track using current video chunk
*/
static
void
ChunkGetESSampleRate
(
unsigned
*
pi_num
,
unsigned
*
pi_den
,
const
mp4_track_t
*
p_track
)
const
mp4_chunk_t
*
p_cchunk
,
uint32_t
i_timescale
)
{
if
(
p_
track
->
cchunk
->
i_last_dts
==
0
)
if
(
!
p_
cchunk
||
p_
cchunk
->
i_last_dts
==
0
||
i_timescale
==
0
)
return
;
*
pi_num
=
0
;
*
pi_den
=
0
;
/* */
const
mp4_chunk_t
*
p_chunk
=
p_track
->
cchunk
;
uint32_t
i_sample
=
p_chunk
->
i_sample_count
;
uint64_t
i_first_dts
=
p_chunk
->
i_first_dts
;
uint64_t
i_last_dts
=
p_chunk
->
i_last_dts
;
uint32_t
i_sample
=
p_cchunk
->
i_sample_count
;
uint64_t
i_first_dts
=
p_cchunk
->
i_first_dts
;
uint64_t
i_last_dts
=
p_cchunk
->
i_last_dts
;
if
(
i_sample
>
1
&&
i_first_dts
<
i_last_dts
)
vlc_ureduce
(
pi_num
,
pi_den
,
(
i_sample
-
1
)
*
p_track
->
i_timescale
,
(
i_sample
-
1
)
*
i_timescale
,
i_last_dts
-
i_first_dts
,
UINT16_MAX
);
}
...
...
@@ -3416,12 +3483,13 @@ static inline int MP4_SetCodecExtraData( es_format_t *fmt, const MP4_Box_data_st
return
VLC_SUCCESS
;
}
static
int
MP4_SmoothFormatFill
(
const
MP4_Box_data_stra_t
*
p_data
,
const
mp4_track_t
*
p_track
,
static
int
MP4_SmoothFormatFill
(
const
MP4_Box_data_stra_t
*
p_data
,
es_format_t
*
fmt
)
{
/* Set language FIXME */
fmt
->
psz_language
=
strdup
(
"en"
);
fmt
->
i_cat
=
p_data
->
i_es_cat
;
fmt
->
i_original_fourcc
=
p_data
->
FourCC
;
fmt
->
i_codec
=
vlc_fourcc_GetCodec
(
fmt
->
i_cat
,
p_data
->
FourCC
);
...
...
@@ -3449,11 +3517,6 @@ static int MP4_SmoothFormatFill( const MP4_Box_data_stra_t *p_data, const mp4_tr
fmt
->
video
.
i_bits_per_pixel
=
0x18
;
fmt
->
video
.
i_visible_width
=
p_data
->
MaxWidth
;
fmt
->
video
.
i_visible_height
=
p_data
->
MaxHeight
;
/* Frame rate */
ChunkGetESSampleRate
(
&
fmt
->
video
.
i_frame_rate
,
&
fmt
->
video
.
i_frame_rate_base
,
p_track
);
break
;
case
AUDIO_ES
:
...
...
@@ -3476,14 +3539,13 @@ static int MP4_SmoothFormatFill( const MP4_Box_data_stra_t *p_data, const mp4_tr
return
VLC_SUCCESS
;
}
static
int
MP4_SmoothTrackCreate
(
demux_t
*
p_demux
,
mp4_track_t
*
p_track
,
const
MP4_Box_t
*
p_stra
)
static
int
MP4_SmoothTrackCreate
(
demux_t
*
p_demux
,
mp4_track_t
*
p_track
,
const
mp4_chunk_t
*
p_cchunk
,
const
MP4_Box_t
*
p_stra
,
bool
b_create_es
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
es_format_t
*
fmt
=
&
p_track
->
fmt
;
p_track
->
b_ok
=
false
;
p_track
->
b_selected
=
false
;
MP4_Box_data_stra_t
*
p_data
=
BOXDATA
(
p_stra
);
if
(
!
p_data
)
return
VLC_EGENERIC
;
...
...
@@ -3495,37 +3557,21 @@ static int MP4_SmoothTrackCreate( demux_t *p_demux, mp4_track_t *p_track, const
p_track
->
i_width
=
0
;
p_track
->
i_height
=
0
;
es_format_t
newfmt
;
es_format_Init
(
&
newfmt
,
p_data
->
i_es_cat
,
0
);
if
(
MP4_SmoothFormatFill
(
BOXDATA
(
p_stra
),
p_track
,
&
newfmt
)
!=
VLC_SUCCESS
)
{
es_format_Clean
(
&
newfmt
);
if
(
p_track
->
p_es
)
{
es_out_Del
(
p_demux
->
out
,
p_track
->
p_es
);
p_track
->
p_es
=
NULL
;
}
return
VLC_EGENERIC
;
}
es_format_Init
(
fmt
,
p_data
->
i_es_cat
,
0
);
/* If format now differs from current (new or updated) */
if
(
!
es_format_IsSimilar
(
&
newfmt
,
fmt
)
||
newfmt
.
i_extra
!=
fmt
->
i_extra
||
memcmp
(
&
newfmt
.
p_extra
,
fmt
->
p_extra
,
newfmt
.
i_extra
)
)
{
es_format_Clean
(
fmt
);
es_format_Copy
(
fmt
,
&
newfmt
);
if
(
p_track
->
p_es
)
es_out_Del
(
p_demux
->
out
,
p_track
->
p_es
);
p_track
->
p_es
=
es_out_Add
(
p_demux
->
out
,
fmt
);
}
es_format_Clean
(
&
newfmt
);
if
(
MP4_SmoothFormatFill
(
p_data
,
fmt
)
!=
VLC_SUCCESS
)
return
VLC_EGENERIC
;
if
(
fmt
->
i_cat
==
VIDEO_ES
)
{
p_track
->
i_width
=
fmt
->
video
.
i_visible_width
;
p_track
->
i_height
=
fmt
->
video
.
i_visible_height
;
/* Frame rate */
ChunkGetESSampleRate
(
&
fmt
->
video
.
i_frame_rate
,
&
fmt
->
video
.
i_frame_rate_base
,
p_cchunk
,
p_track
->
i_timescale
);
if
(
fmt
->
video
.
i_frame_rate_base
!=
0
)
{
p_demux
->
p_sys
->
f_fps
=
(
float
)
fmt
->
video
.
i_frame_rate
/
...
...
@@ -3535,7 +3581,14 @@ static int MP4_SmoothTrackCreate( demux_t *p_demux, mp4_track_t *p_track, const
p_demux
->
p_sys
->
f_fps
=
24
;
}
p_track
->
b_ok
=
!!
p_track
->
p_es
;
if
(
b_create_es
)
{
p_track
->
p_es
=
es_out_Add
(
p_demux
->
out
,
fmt
);
if
(
!
p_track
->
p_es
)
return
VLC_EGENERIC
;
}
p_track
->
b_ok
=
true
;
return
VLC_SUCCESS
;
}
...
...
@@ -3602,40 +3655,30 @@ static void FlushChunk( demux_t *p_demux, mp4_track_t *tk )
* before the track has been selected by MP4_TrackSelect
* (during the first execution of Demux), then the track gets disabled
*/
static
int
ReInitDecoder
(
demux_t
*
p_demux
,
mp4_track_t
*
p_track
)
static
int
ReInitDecoder
(
demux_t
*
p_demux
,
const
MP4_Box_t
*
p_root
,
mp4_track_t
*
p_track
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
uint32_t
i_sample
=
p_track
->
i_sample
;
MP4_Box_t
*
p_paramsbox
;
/* trak or stra */
if
(
p_sys
->
b_smooth
)
{
MP4_Box_t
*
p_stra
=
MP4_BoxGet
(
p_sys
->
p_root
,
"uuid/uuid[0]"
);
if
(
!
p_stra
||
CmpUUID
(
&
p_stra
->
i_uuid
,
&
StraBoxUUID
)
||
MP4_SmoothTrackCreate
(
p_demux
,
p_track
,
p_stra
)
!=
VLC_SUCCESS
)
p_paramsbox
=
MP4_BoxGet
(
p_root
,
"uuid/uuid[0]"
);
if
(
!
p_paramsbox
||
CmpUUID
(
&
p_paramsbox
->
i_uuid
,
&
StraBoxUUID
)
)
return
VLC_EGENERIC
;
}
else
/* DASH */
{
MP4_Box_t
*
p_trak
=
MP4_BoxGet
(
p_sys
->
p_root
,
"/moov/trak[0]"
);
if
(
!
p_
trak
)
p_paramsbox
=
MP4_BoxGet
(
p_root
,
"/moov/trak[0]"
);
if
(
!
p_
paramsbox
)
return
VLC_EGENERIC
;
es_out_Del
(
p_demux
->
out
,
p_track
->
p_es
);
p_track
->
p_es
=
NULL
;
es_format_Clean
(
&
p_track
->
fmt
);
MP4_TrackCreate
(
p_demux
,
p_track
,
p_trak
,
true
);
if
(
!
p_track
->
p_es
)
p_track
->
p_es
=
es_out_Add
(
p_demux
->
out
,
&
p_track
->
fmt
);
p_track
->
b_ok
=
!!
p_track
->
p_es
;
}
p_track
->
i_sample
=
i_sample
;
MP4_TrackRestart
(
p_demux
,
p_track
,
p_paramsbox
)
;
/* Temporary hack until we support track selection */
p_track
->
b_selected
=
true
;
p_track
->
b_enable
=
true
;
p_track
->
b_codec_need_restart
=
false
;
return
VLC_SUCCESS
;
}
...
...
@@ -3799,9 +3842,11 @@ static int MP4_frg_GetChunk( demux_t *p_demux, MP4_Box_t *p_chunk, unsigned *i_t
ret
->
i_last_dts
=
ret
->
i_first_dts
+
chunk_duration
-
dur
;
p_track
->
i_first_dts
=
chunk_duration
+
ret
->
i_first_dts
;
if
(
p_track
->
b_codec_need_restart
&&
p_track
->
fmt
.
i_cat
==
VIDEO_ES
)
ReInitDecoder
(
p_demux
,
p_track
);
if
(
p_track
->
b_codec_need_restart
)
{
ReInitDecoder
(
p_demux
,
p_demux
->
p_sys
->
p_root
,
p_track
);
p_track
->
b_codec_need_restart
=
false
;
}
/* Skip if we didn't reach the end of mdat box */
if
(
chunk_size
<
(
i_mdatlen
-
8
)
)
...
...
@@ -5092,6 +5137,20 @@ end:
return
VLC_SUCCESS
;
}
static
void
RestartAllTracks
(
demux_t
*
p_demux
,
const
MP4_Box_t
*
p_root
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
for
(
unsigned
i_track
=
0
;
i_track
<
p_sys
->
i_tracks
;
i_track
++
)
{
mp4_track_t
*
tk
=
&
p_sys
->
track
[
i_track
];
if
(
!
tk
->
b_ok
||
tk
->
b_chapter
)
continue
;
ReInitDecoder
(
p_demux
,
p_root
,
tk
);
}
}
static
int
DemuxAsLeaf
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
...
...
@@ -5143,7 +5202,10 @@ static int DemuxAsLeaf( demux_t *p_demux )
MP4_Box_t
*
p_fragbox
=
MP4_BoxGet
(
p_vroot
,
"moof"
);
if
(
!
p_fragbox
)
{
p_fragbox
=
MP4_BoxGet
(
p_vroot
,
"moov"
);
RestartAllTracks
(
p_demux
,
p_vroot
);
}
if
(
!
p_fragbox
)
{
...
...
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