Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
d2a33f66
Commit
d2a33f66
authored
Jan 10, 2020
by
James Almer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avformat/dashenc: add Trick Mode support for AdaptationSets
Signed-off-by:
James Almer
<
jamrial@gmail.com
>
parent
4d27def5
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
64 additions
and
11 deletions
+64
-11
muxers.texi
doc/muxers.texi
+2
-0
dashenc.c
libavformat/dashenc.c
+61
-10
version.h
libavformat/version.h
+1
-1
No files found.
doc/muxers.texi
View file @
d2a33f66
...
...
@@ -286,6 +286,8 @@ For example, -adaptation_sets "id=0,descriptor=<SupplementalProperty schemeIdUri
Please note that descriptor string should be a self-closing xml tag.
seg_duration, frag_duration and frag_type override the global option values for each adaptation set.
For example, -adaptation_sets "id=0,seg_duration=2,frag_duration=1,frag_type=duration,streams=v id=1,seg_duration=2,frag_type=none,streams=a"
type_id marks an adaptation set as containing streams meant to be used for Trick Mode for the referenced adaptation set.
For example, -adaptation_sets "id=0,seg_duration=2,frag_type=none,streams=0 id=1,seg_duration=10,frag_type=none,trick_id=0,streams=1"
@item timeout @var{timeout}
Set timeout for socket I/O operations. Applicable only for HTTP output.
@item index_correction @var{index_correction}
...
...
libavformat/dashenc.c
View file @
d2a33f66
...
...
@@ -93,6 +93,7 @@ typedef struct AdaptationSet {
int
max_width
,
max_height
;
int
nb_streams
;
AVRational
par
;
int
trick_idx
;
}
AdaptationSet
;
typedef
struct
OutputStream
{
...
...
@@ -135,6 +136,7 @@ typedef struct OutputStream {
int
frag_type
;
int64_t
gop_size
;
AVRational
sar
;
int
coding_dependency
;
}
OutputStream
;
typedef
struct
DASHContext
{
...
...
@@ -819,6 +821,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
if
(
!
final
&&
c
->
ldash
&&
as
->
max_frag_duration
)
avio_printf
(
out
,
"
\t\t\t
<Resync dT=
\"
%"
PRId64
"
\"
type=
\"
0
\"
/>
\n
"
,
as
->
max_frag_duration
);
if
(
as
->
trick_idx
>=
0
)
avio_printf
(
out
,
"
\t\t\t
<EssentialProperty id=
\"
%d
\"
schemeIdUri=
\"
http://dashif.org/guidelines/trickmode
\"
value=
\"
%d
\"
/>
\n
"
,
as
->
id
,
as
->
trick_idx
);
role
=
av_dict_get
(
as
->
metadata
,
"role"
,
NULL
,
0
);
if
(
role
)
avio_printf
(
out
,
"
\t\t\t
<Role schemeIdUri=
\"
urn:mpeg:dash:role:2011
\"
value=
\"
%s
\"
/>
\n
"
,
role
->
value
);
...
...
@@ -846,6 +850,13 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
avio_printf
(
out
,
" sar=
\"
%d:%d
\"
"
,
os
->
sar
.
num
,
os
->
sar
.
den
);
if
(
st
->
avg_frame_rate
.
num
&&
av_cmp_q
(
as
->
min_frame_rate
,
as
->
max_frame_rate
)
<
0
)
avio_printf
(
out
,
" frameRate=
\"
%d/%d
\"
"
,
st
->
avg_frame_rate
.
num
,
st
->
avg_frame_rate
.
den
);
if
(
as
->
trick_idx
>=
0
)
{
AdaptationSet
*
tas
=
&
c
->
as
[
as
->
trick_idx
];
if
(
!
as
->
ambiguous_frame_rate
&&
!
tas
->
ambiguous_frame_rate
)
avio_printf
(
out
,
" maxPlayoutRate=
\"
%d
\"
"
,
FFMAX
((
int
)
av_q2d
(
av_div_q
(
tas
->
min_frame_rate
,
as
->
min_frame_rate
)),
1
));
}
if
(
!
os
->
coding_dependency
)
avio_printf
(
out
,
" codingDependency=
\"
false
\"
"
);
avio_printf
(
out
,
">
\n
"
);
}
else
{
avio_printf
(
out
,
"
\t\t\t
<Representation id=
\"
%d
\"
mimeType=
\"
audio/%s
\"
codecs=
\"
%s
\"
%s audioSamplingRate=
\"
%d
\"
>
\n
"
,
...
...
@@ -889,6 +900,7 @@ static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMed
memset
(
*
as
,
0
,
sizeof
(
**
as
));
(
*
as
)
->
media_type
=
type
;
(
*
as
)
->
frag_type
=
-
1
;
(
*
as
)
->
trick_idx
=
-
1
;
return
0
;
}
...
...
@@ -939,7 +951,8 @@ static int parse_adaptation_sets(AVFormatContext *s)
// syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
// option id=0,descriptor=descriptor_str,streams=0,1,2 and so on
// option id=0,seg_duration=2.5,frag_duration=0.5,streams=0,1,2 and so on
// option id=0,seg_duration=2.5,frag_duration=0.5,streams=0,1,2
// id=1,trick_id=0,seg_duration=10,frag_type=none,streams=3 and so on
// descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015
// descriptor_str should be a self-closing xml tag.
// seg_duration and frag_duration have the same syntax as the global options of
...
...
@@ -1025,6 +1038,20 @@ static int parse_adaptation_sets(AVFormatContext *s)
return
AVERROR
(
EINVAL
);
}
p
+=
n
;
if
(
*
p
)
p
++
;
state
=
parse_default
;
}
else
if
((
state
!=
new_set
)
&&
av_strstart
(
p
,
"trick_id="
,
&
p
))
{
char
trick_id_str
[
10
],
*
end_str
;
n
=
strcspn
(
p
,
","
);
snprintf
(
trick_id_str
,
sizeof
(
trick_id_str
),
"%.*s"
,
n
,
p
);
p
+=
n
;
as
->
trick_idx
=
strtol
(
trick_id_str
,
&
end_str
,
10
);
if
(
trick_id_str
==
end_str
||
as
->
trick_idx
<
0
)
return
AVERROR
(
EINVAL
);
if
(
*
p
)
p
++
;
state
=
parse_default
;
...
...
@@ -1086,6 +1113,22 @@ end:
return
AVERROR
(
EINVAL
);
}
}
// check references for trick mode AdaptationSet
for
(
i
=
0
;
i
<
c
->
nb_as
;
i
++
)
{
as
=
&
c
->
as
[
i
];
if
(
as
->
trick_idx
<
0
)
continue
;
for
(
n
=
0
;
n
<
c
->
nb_as
;
n
++
)
{
if
(
c
->
as
[
n
].
id
==
as
->
trick_idx
)
break
;
}
if
(
n
>=
c
->
nb_as
)
{
av_log
(
s
,
AV_LOG_ERROR
,
"reference AdaptationSet id
\"
%d
\"
not found for trick mode AdaptationSet id
\"
%d
\"\n
"
,
as
->
trick_idx
,
as
->
id
);
return
AVERROR
(
EINVAL
);
}
}
return
0
;
}
...
...
@@ -1476,7 +1519,8 @@ static int dash_init(AVFormatContext *s)
return
ret
;
// We only want to parse frame headers
os
->
parser
->
flags
|=
PARSER_FLAG_COMPLETE_FRAMES
;
}
}
else
os
->
coding_dependency
=
1
;
if
(
c
->
single_file
)
{
if
(
os
->
single_file_name
)
...
...
@@ -2014,6 +2058,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
if
(
!
os
->
availability_time_offset
&&
((
os
->
frag_type
==
FRAG_TYPE_DURATION
&&
os
->
seg_duration
!=
os
->
frag_duration
)
||
(
os
->
frag_type
==
FRAG_TYPE_EVERY_FRAME
&&
pkt
->
duration
)))
{
AdaptationSet
*
as
=
&
c
->
as
[
os
->
as_idx
-
1
];
int64_t
frame_duration
=
0
;
switch
(
os
->
frag_type
)
{
...
...
@@ -2038,6 +2083,19 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
seg_end_duration
=
os
->
seg_duration
;
}
if
(
os
->
parser
&&
(
os
->
frag_type
==
FRAG_TYPE_PFRAMES
||
as
->
trick_idx
>=
0
))
{
// Parse the packets only in scenarios where it's needed
uint8_t
*
data
;
int
size
;
av_parser_parse2
(
os
->
parser
,
os
->
parser_avctx
,
&
data
,
&
size
,
pkt
->
data
,
pkt
->
size
,
pkt
->
pts
,
pkt
->
dts
,
pkt
->
pos
);
os
->
coding_dependency
|=
os
->
parser
->
pict_type
!=
AV_PICTURE_TYPE_I
;
}
if
(
pkt
->
flags
&
AV_PKT_FLAG_KEY
&&
os
->
packets_written
&&
av_compare_ts
(
elapsed_duration
,
st
->
time_base
,
seg_end_duration
,
AV_TIME_BASE_Q
)
>=
0
)
{
...
...
@@ -2085,14 +2143,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
if
(
st
->
codecpar
->
codec_type
==
AVMEDIA_TYPE_VIDEO
&&
os
->
frag_type
==
FRAG_TYPE_PFRAMES
&&
os
->
packets_written
)
{
uint8_t
*
data
;
int
size
;
av_assert0
(
os
->
parser
);
av_parser_parse2
(
os
->
parser
,
os
->
parser_avctx
,
&
data
,
&
size
,
pkt
->
data
,
pkt
->
size
,
pkt
->
pts
,
pkt
->
dts
,
pkt
->
pos
);
if
((
os
->
parser
->
pict_type
==
AV_PICTURE_TYPE_P
&&
st
->
codecpar
->
video_delay
&&
!
(
os
->
last_flags
&
AV_PKT_FLAG_KEY
))
||
...
...
@@ -2111,7 +2162,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
}
}
if
(
pkt
->
flags
&
AV_PKT_FLAG_KEY
&&
(
os
->
packets_written
||
os
->
nb_segments
)
&&
!
os
->
gop_size
)
{
if
(
pkt
->
flags
&
AV_PKT_FLAG_KEY
&&
(
os
->
packets_written
||
os
->
nb_segments
)
&&
!
os
->
gop_size
&&
as
->
trick_idx
<
0
)
{
os
->
gop_size
=
os
->
last_duration
+
av_rescale_q
(
os
->
total_pkt_duration
,
st
->
time_base
,
AV_TIME_BASE_Q
);
c
->
max_gop_size
=
FFMAX
(
c
->
max_gop_size
,
os
->
gop_size
);
}
...
...
libavformat/version.h
View file @
d2a33f66
...
...
@@ -33,7 +33,7 @@
// Also please add any ticket numbers that you believe might be affected here
#define LIBAVFORMAT_VERSION_MAJOR 58
#define LIBAVFORMAT_VERSION_MINOR 38
#define LIBAVFORMAT_VERSION_MICRO 10
0
#define LIBAVFORMAT_VERSION_MICRO 10
1
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
...
...
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