Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
Steve Lhomme
VLC
Commits
da897185
Commit
da897185
authored
Jan 05, 2018
by
François Cartegnie
🤞
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mux: mp4: split stream muxing
parent
d92bb2cc
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
155 additions
and
142 deletions
+155
-142
modules/mux/mp4/mp4.c
modules/mux/mp4/mp4.c
+155
-142
No files found.
modules/mux/mp4/mp4.c
View file @
da897185
...
...
@@ -583,111 +583,105 @@ static inline mtime_t dts_fb_pts( const block_t *p_data )
return
p_data
->
i_dts
>
VLC_TS_INVALID
?
p_data
->
i_dts
:
p_data
->
i_pts
;
}
static
int
Mux
(
sout_mux_t
*
p_mux
)
static
int
Mux
Stream
(
sout_mux_t
*
p_mux
,
sout_input_t
*
p_input
,
mp4_stream_t
*
p_stream
)
{
sout_mux_sys_t
*
p_sys
=
p_mux
->
p_sys
;
for
(;;)
{
int
i_stream
=
sout_MuxGetStream
(
p_mux
,
2
,
NULL
);
if
(
i_stream
<
0
)
return
(
VLC_SUCCESS
);
sout_input_t
*
p_input
=
p_mux
->
pp_inputs
[
i_stream
];
mp4_stream_t
*
p_stream
=
(
mp4_stream_t
*
)
p_input
->
p_sys
;
block_t
*
p_data
=
BlockDequeue
(
p_input
,
p_stream
);
if
(
!
p_data
)
return
VLC_SUCCESS
;
block_t
*
p_data
=
BlockDequeue
(
p_input
,
p_stream
);
if
(
!
p_data
)
return
VLC_SUCCESS
;
/* Reset reference dts in case of discontinuity (ex: gather sout) */
if
(
p_data
->
i_flags
&
BLOCK_FLAG_DISCONTINUITY
&&
p_stream
->
mux
.
i_entry_count
)
/* Reset reference dts in case of discontinuity (ex: gather sout) */
if
(
p_data
->
i_flags
&
BLOCK_FLAG_DISCONTINUITY
&&
p_stream
->
mux
.
i_entry_count
)
{
if
(
p_stream
->
i_first_dts
!=
VLC_TS_INVALID
)
{
if
(
p_stream
->
i_first_dts
!=
VLC_TS_INVALID
)
if
(
!
CreateCurrentEdit
(
p_stream
,
p_sys
->
i_start_dts
,
p_sys
->
b_fragmented
)
)
{
if
(
!
CreateCurrentEdit
(
p_stream
,
p_sys
->
i_start_dts
,
p_sys
->
b_fragmented
))
{
block_Release
(
p_data
);
return
VLC_ENOMEM
;
}
block_Release
(
p_data
);
return
VLC_ENOMEM
;
}
p_stream
->
i_length_neg
=
0
;
p_stream
->
i_first_dts
=
VLC_TS_INVALID
;
p_stream
->
i_last_dts
=
VLC_TS_INVALID
;
p_stream
->
i_last_pts
=
VLC_TS_INVALID
;
}
/* XXX: -1 to always have 2 entry for easy adding of empty SPU */
if
(
p_stream
->
mux
.
i_entry_count
>=
p_stream
->
mux
.
i_entry_max
-
2
)
{
p_stream
->
mux
.
i_entry_max
+=
1000
;
p_stream
->
mux
.
entry
=
xrealloc
(
p_stream
->
mux
.
entry
,
p_stream
->
mux
.
i_entry_max
*
sizeof
(
mp4mux_entry_t
));
}
p_stream
->
i_length_neg
=
0
;
p_stream
->
i_first_dts
=
VLC_TS_INVALID
;
p_stream
->
i_last_dts
=
VLC_TS_INVALID
;
p_stream
->
i_last_pts
=
VLC_TS_INVALID
;
}
/* Set current segment ranges */
if
(
p_stream
->
i_first_dts
==
VLC_TS_INVALID
)
{
p_stream
->
i_first_dts
=
dts_fb_pts
(
p_data
);
if
(
p_sys
->
i_start_dts
==
VLC_TS_INVALID
)
p_sys
->
i_start_dts
=
p_stream
->
i_first_dts
;
}
/* XXX: -1 to always have 2 entry for easy adding of empty SPU */
if
(
p_stream
->
mux
.
i_entry_count
>=
p_stream
->
mux
.
i_entry_max
-
2
)
{
p_stream
->
mux
.
i_entry_max
+=
1000
;
p_stream
->
mux
.
entry
=
xrealloc
(
p_stream
->
mux
.
entry
,
p_stream
->
mux
.
i_entry_max
*
sizeof
(
mp4mux_entry_t
));
}
if
(
p_stream
->
mux
.
fmt
.
i_cat
!=
SPU_ES
)
{
/* Fix length of the sample */
if
(
block_FifoCount
(
p_input
->
p_fifo
)
>
0
)
{
block_t
*
p_next
=
block_FifoShow
(
p_input
->
p_fifo
);
if
(
p_next
->
i_flags
&
BLOCK_FLAG_DISCONTINUITY
)
{
/* we have no way to know real length except by decoding */
if
(
p_stream
->
mux
.
fmt
.
i_cat
==
VIDEO_ES
)
{
p_data
->
i_length
=
CLOCK_FREQ
*
p_stream
->
mux
.
fmt
.
video
.
i_frame_rate_base
/
p_stream
->
mux
.
fmt
.
video
.
i_frame_rate
;
if
(
p_data
->
i_flags
&
BLOCK_FLAG_SINGLE_FIELD
)
p_data
->
i_length
>>=
1
;
msg_Dbg
(
p_mux
,
"video track %u fixup to %"
PRId64
" for sample %u"
,
p_stream
->
mux
.
i_track_id
,
p_data
->
i_length
,
p_stream
->
mux
.
i_entry_count
);
}
else
if
(
p_stream
->
mux
.
fmt
.
i_cat
==
AUDIO_ES
&&
p_stream
->
mux
.
fmt
.
audio
.
i_rate
&&
p_data
->
i_nb_samples
)
{
p_data
->
i_length
=
CLOCK_FREQ
*
p_data
->
i_nb_samples
/
p_stream
->
mux
.
fmt
.
audio
.
i_rate
;
msg_Dbg
(
p_mux
,
"audio track %u fixup to %"
PRId64
" for sample %u"
,
p_stream
->
mux
.
i_track_id
,
p_data
->
i_length
,
p_stream
->
mux
.
i_entry_count
);
}
else
if
(
p_data
->
i_length
<=
0
)
{
msg_Warn
(
p_mux
,
"unknown length for track %u sample %u"
,
p_stream
->
mux
.
i_track_id
,
p_stream
->
mux
.
i_entry_count
);
p_data
->
i_length
=
1
;
}
/* Set current segment ranges */
if
(
p_stream
->
i_first_dts
==
VLC_TS_INVALID
)
{
p_stream
->
i_first_dts
=
dts_fb_pts
(
p_data
);
if
(
p_sys
->
i_start_dts
==
VLC_TS_INVALID
)
p_sys
->
i_start_dts
=
p_stream
->
i_first_dts
;
}
if
(
p_stream
->
mux
.
fmt
.
i_cat
!=
SPU_ES
)
{
/* Fix length of the sample */
if
(
block_FifoCount
(
p_input
->
p_fifo
)
>
0
)
{
block_t
*
p_next
=
block_FifoShow
(
p_input
->
p_fifo
);
if
(
p_next
->
i_flags
&
BLOCK_FLAG_DISCONTINUITY
)
{
/* we have no way to know real length except by decoding */
if
(
p_stream
->
mux
.
fmt
.
i_cat
==
VIDEO_ES
)
{
p_data
->
i_length
=
CLOCK_FREQ
*
p_stream
->
mux
.
fmt
.
video
.
i_frame_rate_base
/
p_stream
->
mux
.
fmt
.
video
.
i_frame_rate
;
if
(
p_data
->
i_flags
&
BLOCK_FLAG_SINGLE_FIELD
)
p_data
->
i_length
>>=
1
;
msg_Dbg
(
p_mux
,
"video track %u fixup to %"
PRId64
" for sample %u"
,
p_stream
->
mux
.
i_track_id
,
p_data
->
i_length
,
p_stream
->
mux
.
i_entry_count
);
}
else
else
if
(
p_stream
->
mux
.
fmt
.
i_cat
==
AUDIO_ES
&&
p_stream
->
mux
.
fmt
.
audio
.
i_rate
&&
p_data
->
i_nb_samples
)
{
int64_t
i_diff
=
dts_fb_pts
(
p_next
)
-
dts_fb_pts
(
p_data
);
if
(
i_diff
<
CLOCK_FREQ
)
/* protection */
p_data
->
i_length
=
i_diff
;
p_data
->
i_length
=
CLOCK_FREQ
*
p_data
->
i_nb_samples
/
p_stream
->
mux
.
fmt
.
audio
.
i_rate
;
msg_Dbg
(
p_mux
,
"audio track %u fixup to %"
PRId64
" for sample %u"
,
p_stream
->
mux
.
i_track_id
,
p_data
->
i_length
,
p_stream
->
mux
.
i_entry_count
);
}
else
if
(
p_data
->
i_length
<=
0
)
{
msg_Warn
(
p_mux
,
"unknown length for track %u sample %u"
,
p_stream
->
mux
.
i_track_id
,
p_stream
->
mux
.
i_entry_count
);
p_data
->
i_length
=
1
;
}
}
if
(
p_data
->
i_length
<=
0
)
{
msg_Warn
(
p_mux
,
"i_length <= 0"
);
p_stream
->
i_length_neg
+=
p_data
->
i_length
-
1
;
p_data
->
i_length
=
1
;
}
else
if
(
p_stream
->
i_length_neg
<
0
)
{
int64_t
i_recover
=
__MIN
(
p_data
->
i_length
/
4
,
-
p_stream
->
i_length_neg
);
p_data
->
i_length
-=
i_recover
;
p_stream
->
i_length_neg
+=
i_recover
;
else
{
int64_t
i_diff
=
dts_fb_pts
(
p_next
)
-
dts_fb_pts
(
p_data
);
if
(
i_diff
<
CLOCK_FREQ
)
/* protection */
p_data
->
i_length
=
i_diff
;
}
}
if
(
p_stream
->
mux
.
fmt
.
i_cat
==
SPU_ES
&&
p_stream
->
mux
.
i_entry_count
>
0
&&
if
(
p_data
->
i_length
<=
0
)
{
msg_Warn
(
p_mux
,
"i_length <= 0"
);
p_stream
->
i_length_neg
+=
p_data
->
i_length
-
1
;
p_data
->
i_length
=
1
;
}
else
if
(
p_stream
->
i_length_neg
<
0
)
{
int64_t
i_recover
=
__MIN
(
p_data
->
i_length
/
4
,
-
p_stream
->
i_length_neg
);
p_data
->
i_length
-=
i_recover
;
p_stream
->
i_length_neg
+=
i_recover
;
}
}
else
/* SPU_ES */
{
if
(
p_stream
->
mux
.
i_entry_count
>
0
&&
p_stream
->
mux
.
entry
[
p_stream
->
mux
.
i_entry_count
-
1
].
i_length
==
0
)
{
/* length of previous spu, stored in spu clearer */
/* length of previous spu, stored in spu clearer */
int64_t
i_length
=
dts_fb_pts
(
p_data
)
-
p_stream
->
i_last_dts
;
if
(
i_length
<
0
)
i_length
=
0
;
...
...
@@ -695,77 +689,96 @@ static int Mux(sout_mux_t *p_mux)
p_stream
->
mux
.
entry
[
p_stream
->
mux
.
i_entry_count
-
1
].
i_length
=
i_length
;
p_stream
->
mux
.
i_read_duration
+=
i_length
;
}
}
/* Update (Not earlier for SPU!) */
p_stream
->
i_last_dts
=
dts_fb_pts
(
p_data
);
if
(
p_data
->
i_pts
>
p_stream
->
i_last_pts
)
p_stream
->
i_last_pts
=
p_data
->
i_pts
;
/* Update (Not earlier for SPU!) */
p_stream
->
i_last_dts
=
dts_fb_pts
(
p_data
);
if
(
p_data
->
i_pts
>
p_stream
->
i_last_pts
)
p_stream
->
i_last_pts
=
p_data
->
i_pts
;
/* add index entry */
mp4mux_entry_t
*
e
=
&
p_stream
->
mux
.
entry
[
p_stream
->
mux
.
i_entry_count
++
];
e
->
i_pos
=
p_sys
->
i_pos
;
e
->
i_size
=
p_data
->
i_buffer
;
/* add index entry */
mp4mux_entry_t
*
e
=
&
p_stream
->
mux
.
entry
[
p_stream
->
mux
.
i_entry_count
++
];
e
->
i_pos
=
p_sys
->
i_pos
;
e
->
i_size
=
p_data
->
i_buffer
;
if
(
p_data
->
i_dts
>
VLC_TS_INVALID
&&
p_data
->
i_pts
>
p_data
->
i_dts
)
{
e
->
i_pts_dts
=
p_data
->
i_pts
-
p_data
->
i_dts
;
if
(
!
p_stream
->
mux
.
b_hasbframes
)
p_stream
->
mux
.
b_hasbframes
=
true
;
}
else
e
->
i_pts_dts
=
0
;
if
(
p_data
->
i_dts
>
VLC_TS_INVALID
&&
p_data
->
i_pts
>
p_data
->
i_dts
)
{
e
->
i_pts_dts
=
p_data
->
i_pts
-
p_data
->
i_dts
;
if
(
!
p_stream
->
mux
.
b_hasbframes
)
p_stream
->
mux
.
b_hasbframes
=
true
;
}
else
e
->
i_pts_dts
=
0
;
e
->
i_length
=
p_data
->
i_length
;
e
->
i_flags
=
p_data
->
i_flags
;
e
->
i_length
=
p_data
->
i_length
;
e
->
i_flags
=
p_data
->
i_flags
;
/* update */
p_stream
->
mux
.
i_read_duration
+=
__MAX
(
0
,
p_data
->
i_length
);
p_stream
->
i_last_dts
=
dts_fb_pts
(
p_data
);
/* update */
p_stream
->
mux
.
i_read_duration
+=
__MAX
(
0
,
p_data
->
i_length
);
p_stream
->
i_last_dts
=
dts_fb_pts
(
p_data
);
/* write data */
p_sys
->
i_pos
+=
p_data
->
i_buffer
;
sout_AccessOutWrite
(
p_mux
->
p_access
,
p_data
);
/* write data */
p_sys
->
i_pos
+=
p_data
->
i_buffer
;
sout_AccessOutWrite
(
p_mux
->
p_access
,
p_data
);
/* Add SPU clearing tag (duration tb fixed on next SPU or stream end )*/
if
(
p_stream
->
mux
.
fmt
.
i_cat
==
SPU_ES
)
/* Add SPU clearing tag (duration tb fixed on next SPU or stream end )*/
if
(
p_stream
->
mux
.
fmt
.
i_cat
==
SPU_ES
)
{
block_t
*
p_empty
=
NULL
;
if
(
p_stream
->
mux
.
fmt
.
i_codec
==
VLC_CODEC_SUBT
)
{
block_t
*
p_empty
=
NULL
;
if
(
p_stream
->
mux
.
fmt
.
i_codec
==
VLC_CODEC_SUBT
)
{
p_empty
=
block_Alloc
(
3
);
if
(
p_empty
)
{
/* point to start of our empty */
p_stream
->
i_last_dts
+=
e
->
i_length
;
/* Write a " " */
p_empty
->
p_buffer
[
0
]
=
0
;
p_empty
->
p_buffer
[
1
]
=
1
;
p_empty
->
p_buffer
[
2
]
=
' '
;
}
}
p_empty
=
block_Alloc
(
3
);
if
(
p_empty
)
{
/* Append a idx entry */
/* XXX: No need to grow the entry here */
mp4mux_entry_t
*
e_empty
=
&
p_stream
->
mux
.
entry
[
p_stream
->
mux
.
i_entry_count
++
];
e_empty
->
i_pos
=
p_sys
->
i_pos
;
e_empty
->
i_size
=
p_empty
->
i_buffer
;
e_empty
->
i_pts_dts
=
0
;
e_empty
->
i_length
=
0
;
/* will add dts diff later*/
e_empty
->
i_flags
=
0
;
p_sys
->
i_pos
+=
p_empty
->
i_buffer
;
sout_AccessOutWrite
(
p_mux
->
p_access
,
p_empty
);
/* point to start of our empty */
p_stream
->
i_last_dts
+=
e
->
i_length
;
/* Write a " " */
p_empty
->
p_buffer
[
0
]
=
0
;
p_empty
->
p_buffer
[
1
]
=
1
;
p_empty
->
p_buffer
[
2
]
=
' '
;
}
}
/* Update the global segment/media duration */
if
(
p_stream
->
mux
.
i_read_duration
>
p_sys
->
i_read_duration
)
p_sys
->
i_read_duration
=
p_stream
->
mux
.
i_read_duration
;
if
(
p_empty
)
{
/* Append a idx entry */
/* XXX: No need to grow the entry here */
mp4mux_entry_t
*
e_empty
=
&
p_stream
->
mux
.
entry
[
p_stream
->
mux
.
i_entry_count
++
];
e_empty
->
i_pos
=
p_sys
->
i_pos
;
e_empty
->
i_size
=
p_empty
->
i_buffer
;
e_empty
->
i_pts_dts
=
0
;
e_empty
->
i_length
=
0
;
/* will add dts diff later*/
e_empty
->
i_flags
=
0
;
p_sys
->
i_pos
+=
p_empty
->
i_buffer
;
sout_AccessOutWrite
(
p_mux
->
p_access
,
p_empty
);
}
}
return
(
VLC_SUCCESS
);
/* Update the global segment/media duration */
if
(
p_stream
->
mux
.
i_read_duration
>
p_sys
->
i_read_duration
)
p_sys
->
i_read_duration
=
p_stream
->
mux
.
i_read_duration
;
return
VLC_SUCCESS
;
}
static
int
Mux
(
sout_mux_t
*
p_mux
)
{
int
i_ret
=
VLC_SUCCESS
;
do
{
int
i_stream
=
sout_MuxGetStream
(
p_mux
,
2
,
NULL
);
if
(
i_stream
<
0
)
break
;
sout_input_t
*
p_input
=
p_mux
->
pp_inputs
[
i_stream
];
mp4_stream_t
*
p_stream
=
(
mp4_stream_t
*
)
p_input
->
p_sys
;
i_ret
=
MuxStream
(
p_mux
,
p_input
,
p_stream
);
}
while
(
i_ret
==
VLC_SUCCESS
);
return
i_ret
;
}
/*****************************************************************************
...
...
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