Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
94cc1649
Commit
94cc1649
authored
Jan 14, 2018
by
sfan5
Committed by
Steven Liu
Jan 14, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashdec: Support for multiple video/audio streams
Signed-off-by:
Steven Liu
<
lq@chinaffmpeg.org
>
parent
66e551ea
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
223 additions
and
129 deletions
+223
-129
demuxers.texi
doc/demuxers.texi
+10
-0
dashdec.c
libavformat/dashdec.c
+213
-129
No files found.
doc/demuxers.texi
View file @
94cc1649
...
@@ -244,6 +244,16 @@ file subdir/file-2.wav
...
@@ -244,6 +244,16 @@ file subdir/file-2.wav
@end example
@end example
@end itemize
@end itemize
@section dash
Dynamic Adaptive Streaming over HTTP demuxer.
This demuxer presents all AVStreams found in the manifest.
By setting the discard flags on AVStreams the caller can decide
which streams to actually receive.
Each stream mirrors the @code{id} and @code{bandwidth} properties from the
@code{<Representation>} as metadata keys named "id" and "variant_bitrate" respectively.
@section flv, live_flv
@section flv, live_flv
Adobe Flash Video Format demuxer.
Adobe Flash Video Format demuxer.
...
...
libavformat/dashdec.c
View file @
94cc1649
...
@@ -86,6 +86,7 @@ struct representation {
...
@@ -86,6 +86,7 @@ struct representation {
enum
AVMediaType
type
;
enum
AVMediaType
type
;
char
id
[
20
];
char
id
[
20
];
int
bandwidth
;
int
bandwidth
;
AVStream
*
assoc_stream
;
/* demuxer stream associated with this representation */
int
n_fragments
;
int
n_fragments
;
struct
fragment
**
fragments
;
/* VOD list of fragment for profile */
struct
fragment
**
fragments
;
/* VOD list of fragment for profile */
...
@@ -120,8 +121,11 @@ struct representation {
...
@@ -120,8 +121,11 @@ struct representation {
typedef
struct
DASHContext
{
typedef
struct
DASHContext
{
const
AVClass
*
class
;
const
AVClass
*
class
;
char
*
base_url
;
char
*
base_url
;
struct
representation
*
cur_video
;
struct
representation
*
cur_audio
;
int
n_videos
;
struct
representation
**
videos
;
int
n_audios
;
struct
representation
**
audios
;
/* MediaPresentationDescription Attribute */
/* MediaPresentationDescription Attribute */
uint64_t
media_presentation_duration
;
uint64_t
media_presentation_duration
;
...
@@ -333,6 +337,28 @@ static void free_representation(struct representation *pls)
...
@@ -333,6 +337,28 @@ static void free_representation(struct representation *pls)
av_freep
(
&
pls
);
av_freep
(
&
pls
);
}
}
static
void
free_video_list
(
DASHContext
*
c
)
{
int
i
;
for
(
i
=
0
;
i
<
c
->
n_videos
;
i
++
)
{
struct
representation
*
pls
=
c
->
videos
[
i
];
free_representation
(
pls
);
}
av_freep
(
&
c
->
videos
);
c
->
n_videos
=
0
;
}
static
void
free_audio_list
(
DASHContext
*
c
)
{
int
i
;
for
(
i
=
0
;
i
<
c
->
n_audios
;
i
++
)
{
struct
representation
*
pls
=
c
->
audios
[
i
];
free_representation
(
pls
);
}
av_freep
(
&
c
->
audios
);
c
->
n_audios
=
0
;
}
static
void
set_httpheader_options
(
DASHContext
*
c
,
AVDictionary
**
opts
)
static
void
set_httpheader_options
(
DASHContext
*
c
,
AVDictionary
**
opts
)
{
{
// broker prior HTTP options that should be consistent across requests
// broker prior HTTP options that should be consistent across requests
...
@@ -658,7 +684,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
...
@@ -658,7 +684,7 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
type
=
get_content_type
(
adaptionset_node
);
type
=
get_content_type
(
adaptionset_node
);
if
(
type
==
AVMEDIA_TYPE_UNKNOWN
)
{
if
(
type
==
AVMEDIA_TYPE_UNKNOWN
)
{
av_log
(
s
,
AV_LOG_VERBOSE
,
"Parsing '%s' - skipp not supported representation type
\n
"
,
url
);
av_log
(
s
,
AV_LOG_VERBOSE
,
"Parsing '%s' - skipp not supported representation type
\n
"
,
url
);
}
else
if
(
(
type
==
AVMEDIA_TYPE_VIDEO
&&
!
c
->
cur_video
)
||
(
type
==
AVMEDIA_TYPE_AUDIO
&&
!
c
->
cur_audio
)
)
{
}
else
if
(
type
==
AVMEDIA_TYPE_VIDEO
||
type
==
AVMEDIA_TYPE_AUDIO
)
{
// convert selected representation to our internal struct
// convert selected representation to our internal struct
rep
=
av_mallocz
(
sizeof
(
struct
representation
));
rep
=
av_mallocz
(
sizeof
(
struct
representation
));
if
(
!
rep
)
{
if
(
!
rep
)
{
...
@@ -807,10 +833,10 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
...
@@ -807,10 +833,10 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
strncpy
(
rep
->
id
,
rep_id_val
?
rep_id_val
:
""
,
sizeof
(
rep
->
id
));
strncpy
(
rep
->
id
,
rep_id_val
?
rep_id_val
:
""
,
sizeof
(
rep
->
id
));
if
(
type
==
AVMEDIA_TYPE_VIDEO
)
{
if
(
type
==
AVMEDIA_TYPE_VIDEO
)
{
rep
->
rep_idx
=
video_rep_idx
;
rep
->
rep_idx
=
video_rep_idx
;
c
->
cur_video
=
rep
;
dynarray_add
(
&
c
->
videos
,
&
c
->
n_videos
,
rep
)
;
}
else
{
}
else
{
rep
->
rep_idx
=
audio_rep_idx
;
rep
->
rep_idx
=
audio_rep_idx
;
c
->
cur_audio
=
rep
;
dynarray_add
(
&
c
->
audios
,
&
c
->
n_audios
,
rep
)
;
}
}
}
}
}
}
...
@@ -883,8 +909,6 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
...
@@ -883,8 +909,6 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
char
*
val
=
NULL
;
char
*
val
=
NULL
;
uint32_t
perdiod_duration_sec
=
0
;
uint32_t
perdiod_duration_sec
=
0
;
uint32_t
perdiod_start_sec
=
0
;
uint32_t
perdiod_start_sec
=
0
;
int32_t
audio_rep_idx
=
0
;
int32_t
video_rep_idx
=
0
;
if
(
!
in
)
{
if
(
!
in
)
{
close_in
=
1
;
close_in
=
1
;
...
@@ -1014,14 +1038,6 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
...
@@ -1014,14 +1038,6 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
}
}
adaptionset_node
=
xmlNextElementSibling
(
adaptionset_node
);
adaptionset_node
=
xmlNextElementSibling
(
adaptionset_node
);
}
}
if
(
c
->
cur_video
)
{
c
->
cur_video
->
rep_count
=
video_rep_idx
;
av_log
(
s
,
AV_LOG_VERBOSE
,
"rep_idx[%d]
\n
"
,
(
int
)
c
->
cur_video
->
rep_idx
);
av_log
(
s
,
AV_LOG_VERBOSE
,
"rep_count[%d]
\n
"
,
(
int
)
video_rep_idx
);
}
if
(
c
->
cur_audio
)
{
c
->
cur_audio
->
rep_count
=
audio_rep_idx
;
}
cleanup:
cleanup:
/*free the document */
/*free the document */
xmlFreeDoc
(
doc
);
xmlFreeDoc
(
doc
);
...
@@ -1139,48 +1155,69 @@ static void move_segments(struct representation *rep_src, struct representation
...
@@ -1139,48 +1155,69 @@ static void move_segments(struct representation *rep_src, struct representation
static
int
refresh_manifest
(
AVFormatContext
*
s
)
static
int
refresh_manifest
(
AVFormatContext
*
s
)
{
{
int
ret
=
0
;
int
ret
=
0
,
i
;
DASHContext
*
c
=
s
->
priv_data
;
DASHContext
*
c
=
s
->
priv_data
;
// save current context
// save current context
struct
representation
*
cur_video
=
c
->
cur_video
;
int
n_videos
=
c
->
n_videos
;
struct
representation
*
cur_audio
=
c
->
cur_audio
;
struct
representation
**
videos
=
c
->
videos
;
int
n_audios
=
c
->
n_audios
;
struct
representation
**
audios
=
c
->
audios
;
char
*
base_url
=
c
->
base_url
;
char
*
base_url
=
c
->
base_url
;
c
->
base_url
=
NULL
;
c
->
base_url
=
NULL
;
c
->
cur_video
=
NULL
;
c
->
n_videos
=
0
;
c
->
cur_audio
=
NULL
;
c
->
videos
=
NULL
;
c
->
n_audios
=
0
;
c
->
audios
=
NULL
;
ret
=
parse_manifest
(
s
,
s
->
filename
,
NULL
);
ret
=
parse_manifest
(
s
,
s
->
filename
,
NULL
);
if
(
ret
)
if
(
ret
)
goto
finish
;
goto
finish
;
if
(
cur_video
&&
cur_video
->
timelines
||
cur_audio
&&
cur_audio
->
timelines
)
{
if
(
c
->
n_videos
!=
n_videos
)
{
// calc current time
av_log
(
c
,
AV_LOG_ERROR
,
int64_t
currentVideoTime
=
0
;
"new manifest has mismatched no. of video representations, %d -> %d
\n
"
,
int64_t
currentAudioTime
=
0
;
n_videos
,
c
->
n_videos
);
if
(
cur_video
&&
cur_video
->
timelines
)
return
AVERROR_INVALIDDATA
;
currentVideoTime
=
get_segment_start_time_based_on_timeline
(
cur_video
,
cur_video
->
cur_seq_no
)
/
cur_video
->
fragment_timescale
;
}
if
(
cur_audio
&&
cur_audio
->
timelines
)
if
(
c
->
n_audios
!=
n_audios
)
{
currentAudioTime
=
get_segment_start_time_based_on_timeline
(
cur_audio
,
cur_audio
->
cur_seq_no
)
/
cur_audio
->
fragment_timescale
;
av_log
(
c
,
AV_LOG_ERROR
,
// update segments
"new manifest has mismatched no. of audio representations, %d -> %d
\n
"
,
if
(
cur_video
&&
cur_video
->
timelines
)
{
n_audios
,
c
->
n_audios
);
c
->
cur_video
->
cur_seq_no
=
calc_next_seg_no_from_timelines
(
c
->
cur_video
,
currentVideoTime
*
cur_video
->
fragment_timescale
-
1
);
return
AVERROR_INVALIDDATA
;
if
(
c
->
cur_video
->
cur_seq_no
>=
0
)
{
}
move_timelines
(
c
->
cur_video
,
cur_video
,
c
);
for
(
i
=
0
;
i
<
n_videos
;
i
++
)
{
struct
representation
*
cur_video
=
videos
[
i
];
struct
representation
*
ccur_video
=
c
->
videos
[
i
];
if
(
cur_video
->
timelines
)
{
// calc current time
int64_t
currentTime
=
get_segment_start_time_based_on_timeline
(
cur_video
,
cur_video
->
cur_seq_no
)
/
cur_video
->
fragment_timescale
;
// update segments
ccur_video
->
cur_seq_no
=
calc_next_seg_no_from_timelines
(
ccur_video
,
currentTime
*
cur_video
->
fragment_timescale
-
1
);
if
(
ccur_video
->
cur_seq_no
>=
0
)
{
move_timelines
(
ccur_video
,
cur_video
,
c
);
}
}
}
}
if
(
cur_audio
&&
cur_audio
->
timelines
)
{
if
(
cur_video
->
fragments
)
{
c
->
cur_audio
->
cur_seq_no
=
calc_next_seg_no_from_timelines
(
c
->
cur_audio
,
currentAudioTime
*
cur_audio
->
fragment_timescale
-
1
);
move_segments
(
ccur_video
,
cur_video
,
c
);
if
(
c
->
cur_audio
->
cur_seq_no
>=
0
)
{
move_timelines
(
c
->
cur_audio
,
cur_audio
,
c
);
}
}
}
}
}
if
(
cur_video
&&
cur_video
->
fragments
)
{
for
(
i
=
0
;
i
<
n_audios
;
i
++
)
{
move_segments
(
c
->
cur_video
,
cur_video
,
c
);
struct
representation
*
cur_audio
=
audios
[
i
];
}
struct
representation
*
ccur_audio
=
c
->
audios
[
i
];
if
(
cur_audio
&&
cur_audio
->
fragments
)
{
if
(
cur_audio
->
timelines
)
{
move_segments
(
c
->
cur_audio
,
cur_audio
,
c
);
// calc current time
int64_t
currentTime
=
get_segment_start_time_based_on_timeline
(
cur_audio
,
cur_audio
->
cur_seq_no
)
/
cur_audio
->
fragment_timescale
;
// update segments
ccur_audio
->
cur_seq_no
=
calc_next_seg_no_from_timelines
(
ccur_audio
,
currentTime
*
cur_audio
->
fragment_timescale
-
1
);
if
(
ccur_audio
->
cur_seq_no
>=
0
)
{
move_timelines
(
ccur_audio
,
cur_audio
,
c
);
}
}
if
(
cur_audio
->
fragments
)
{
move_segments
(
ccur_audio
,
cur_audio
,
c
);
}
}
}
finish:
finish:
...
@@ -1189,12 +1226,14 @@ finish:
...
@@ -1189,12 +1226,14 @@ finish:
av_free
(
base_url
);
av_free
(
base_url
);
else
else
c
->
base_url
=
base_url
;
c
->
base_url
=
base_url
;
if
(
c
->
cur_audio
)
if
(
c
->
audios
)
free_representation
(
c
->
cur_audio
);
free_audio_list
(
c
);
if
(
c
->
cur_video
)
if
(
c
->
videos
)
free_representation
(
c
->
cur_video
);
free_video_list
(
c
);
c
->
cur_audio
=
cur_audio
;
c
->
n_audios
=
n_audios
;
c
->
cur_video
=
cur_video
;
c
->
audios
=
audios
;
c
->
n_videos
=
n_videos
;
c
->
videos
=
videos
;
return
ret
;
return
ret
;
}
}
...
@@ -1493,6 +1532,16 @@ static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url,
...
@@ -1493,6 +1532,16 @@ static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url,
return
AVERROR
(
EPERM
);
return
AVERROR
(
EPERM
);
}
}
static
void
close_demux_for_component
(
struct
representation
*
pls
)
{
/* note: the internal buffer could have changed */
av_freep
(
&
pls
->
pb
.
buffer
);
memset
(
&
pls
->
pb
,
0x00
,
sizeof
(
AVIOContext
));
pls
->
ctx
->
pb
=
NULL
;
avformat_close_input
(
&
pls
->
ctx
);
pls
->
ctx
=
NULL
;
}
static
int
reopen_demux_for_component
(
AVFormatContext
*
s
,
struct
representation
*
pls
)
static
int
reopen_demux_for_component
(
AVFormatContext
*
s
,
struct
representation
*
pls
)
{
{
DASHContext
*
c
=
s
->
priv_data
;
DASHContext
*
c
=
s
->
priv_data
;
...
@@ -1502,12 +1551,7 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation
...
@@ -1502,12 +1551,7 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation
int
ret
=
0
;
int
ret
=
0
;
if
(
pls
->
ctx
)
{
if
(
pls
->
ctx
)
{
/* note: the internal buffer could have changed, and be != avio_ctx_buffer */
close_demux_for_component
(
pls
);
av_freep
(
&
pls
->
pb
.
buffer
);
memset
(
&
pls
->
pb
,
0x00
,
sizeof
(
AVIOContext
));
pls
->
ctx
->
pb
=
NULL
;
avformat_close_input
(
&
pls
->
ctx
);
pls
->
ctx
=
NULL
;
}
}
if
(
!
(
pls
->
ctx
=
avformat_alloc_context
()))
{
if
(
!
(
pls
->
ctx
=
avformat_alloc_context
()))
{
ret
=
AVERROR
(
ENOMEM
);
ret
=
AVERROR
(
ENOMEM
);
...
@@ -1596,6 +1640,7 @@ static int dash_read_header(AVFormatContext *s)
...
@@ -1596,6 +1640,7 @@ static int dash_read_header(AVFormatContext *s)
DASHContext
*
c
=
s
->
priv_data
;
DASHContext
*
c
=
s
->
priv_data
;
int
ret
=
0
;
int
ret
=
0
;
int
stream_index
=
0
;
int
stream_index
=
0
;
int
i
;
c
->
interrupt_callback
=
&
s
->
interrupt_callback
;
c
->
interrupt_callback
=
&
s
->
interrupt_callback
;
// if the URL context is good, read important options we must broker later
// if the URL context is good, read important options we must broker later
...
@@ -1617,27 +1662,23 @@ static int dash_read_header(AVFormatContext *s)
...
@@ -1617,27 +1662,23 @@ static int dash_read_header(AVFormatContext *s)
s
->
duration
=
(
int64_t
)
c
->
media_presentation_duration
*
AV_TIME_BASE
;
s
->
duration
=
(
int64_t
)
c
->
media_presentation_duration
*
AV_TIME_BASE
;
}
}
/* Open the demuxer for curent video and current audio components if available */
/* Open the demuxer for video and audio components if available */
if
(
!
ret
&&
c
->
cur_video
)
{
for
(
i
=
0
;
i
<
c
->
n_videos
;
i
++
)
{
ret
=
open_demux_for_component
(
s
,
c
->
cur_video
);
struct
representation
*
cur_video
=
c
->
videos
[
i
];
if
(
!
ret
)
{
ret
=
open_demux_for_component
(
s
,
cur_video
);
c
->
cur_video
->
stream_index
=
stream_index
;
if
(
ret
)
++
stream_index
;
goto
fail
;
}
else
{
cur_video
->
stream_index
=
stream_index
;
free_representation
(
c
->
cur_video
);
++
stream_index
;
c
->
cur_video
=
NULL
;
}
}
}
if
(
!
ret
&&
c
->
cur_audio
)
{
for
(
i
=
0
;
i
<
c
->
n_audios
;
i
++
)
{
ret
=
open_demux_for_component
(
s
,
c
->
cur_audio
);
struct
representation
*
cur_audio
=
c
->
audios
[
i
];
if
(
!
ret
)
{
ret
=
open_demux_for_component
(
s
,
cur_audio
);
c
->
cur_audio
->
stream_index
=
stream_index
;
if
(
ret
)
++
stream_index
;
goto
fail
;
}
else
{
cur_audio
->
stream_index
=
stream_index
;
free_representation
(
c
->
cur_audio
);
++
stream_index
;
c
->
cur_audio
=
NULL
;
}
}
}
if
(
!
stream_index
)
{
if
(
!
stream_index
)
{
...
@@ -1653,21 +1694,25 @@ static int dash_read_header(AVFormatContext *s)
...
@@ -1653,21 +1694,25 @@ static int dash_read_header(AVFormatContext *s)
goto
fail
;
goto
fail
;
}
}
if
(
c
->
cur_video
)
{
for
(
i
=
0
;
i
<
c
->
n_videos
;
i
++
)
{
int
stream_index
=
c
->
cur_video
->
stream_index
;
struct
representation
*
pls
=
c
->
videos
[
i
];
av_program_add_stream_index
(
s
,
0
,
stream_index
);
if
(
c
->
cur_video
->
bandwidth
>
0
)
av_program_add_stream_index
(
s
,
0
,
pls
->
stream_index
);
av_dict_set_int
(
&
s
->
streams
[
stream_index
]
->
metadata
,
"variant_bitrate"
,
c
->
cur_video
->
bandwidth
,
0
);
pls
->
assoc_stream
=
s
->
streams
[
pls
->
stream_index
];
if
(
c
->
cur_video
->
id
[
0
])
if
(
pls
->
bandwidth
>
0
)
av_dict_set
(
&
s
->
streams
[
stream_index
]
->
metadata
,
"id"
,
c
->
cur_video
->
id
,
0
);
av_dict_set_int
(
&
pls
->
assoc_stream
->
metadata
,
"variant_bitrate"
,
pls
->
bandwidth
,
0
);
}
if
(
pls
->
id
[
0
])
if
(
c
->
cur_audio
)
{
av_dict_set
(
&
pls
->
assoc_stream
->
metadata
,
"id"
,
pls
->
id
,
0
);
int
stream_index
=
c
->
cur_audio
->
stream_index
;
}
av_program_add_stream_index
(
s
,
0
,
stream_index
);
for
(
i
=
0
;
i
<
c
->
n_audios
;
i
++
)
{
if
(
c
->
cur_audio
->
bandwidth
>
0
)
struct
representation
*
pls
=
c
->
audios
[
i
];
av_dict_set_int
(
&
s
->
streams
[
stream_index
]
->
metadata
,
"variant_bitrate"
,
c
->
cur_audio
->
bandwidth
,
0
);
if
(
c
->
cur_audio
->
id
[
0
])
av_program_add_stream_index
(
s
,
0
,
pls
->
stream_index
);
av_dict_set
(
&
s
->
streams
[
stream_index
]
->
metadata
,
"id"
,
c
->
cur_audio
->
id
,
0
);
pls
->
assoc_stream
=
s
->
streams
[
pls
->
stream_index
];
if
(
pls
->
bandwidth
>
0
)
av_dict_set_int
(
&
pls
->
assoc_stream
->
metadata
,
"variant_bitrate"
,
pls
->
bandwidth
,
0
);
if
(
pls
->
id
[
0
])
av_dict_set
(
&
pls
->
assoc_stream
->
metadata
,
"id"
,
pls
->
id
,
0
);
}
}
}
}
...
@@ -1676,43 +1721,79 @@ fail:
...
@@ -1676,43 +1721,79 @@ fail:
return
ret
;
return
ret
;
}
}
static
void
recheck_discard_flags
(
AVFormatContext
*
s
,
struct
representation
**
p
,
int
n
)
{
int
i
,
j
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
struct
representation
*
pls
=
p
[
i
];
int
needed
=
!
pls
->
assoc_stream
||
pls
->
assoc_stream
->
discard
<
AVDISCARD_ALL
;
if
(
needed
&&
!
pls
->
ctx
)
{
pls
->
cur_seg_offset
=
0
;
pls
->
init_sec_buf_read_offset
=
0
;
/* Catch up */
for
(
j
=
0
;
j
<
n
;
j
++
)
{
pls
->
cur_seq_no
=
FFMAX
(
pls
->
cur_seq_no
,
p
[
j
]
->
cur_seq_no
);
}
reopen_demux_for_component
(
s
,
pls
);
av_log
(
s
,
AV_LOG_INFO
,
"Now receiving stream_index %d
\n
"
,
pls
->
stream_index
);
}
else
if
(
!
needed
&&
pls
->
ctx
)
{
close_demux_for_component
(
pls
);
if
(
pls
->
input
)
ff_format_io_close
(
pls
->
parent
,
&
pls
->
input
);
av_log
(
s
,
AV_LOG_INFO
,
"No longer receiving stream_index %d
\n
"
,
pls
->
stream_index
);
}
}
}
static
int
dash_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
static
int
dash_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
{
{
DASHContext
*
c
=
s
->
priv_data
;
DASHContext
*
c
=
s
->
priv_data
;
int
ret
=
0
;
int
ret
=
0
,
i
;
int64_t
mints
=
0
;
struct
representation
*
cur
=
NULL
;
struct
representation
*
cur
=
NULL
;
if
(
!
c
->
cur_audio
&&
!
c
->
cur_video
)
{
recheck_discard_flags
(
s
,
c
->
videos
,
c
->
n_videos
);
return
AVERROR_INVALIDDATA
;
recheck_discard_flags
(
s
,
c
->
audios
,
c
->
n_audios
);
for
(
i
=
0
;
i
<
c
->
n_videos
;
i
++
)
{
struct
representation
*
pls
=
c
->
videos
[
i
];
if
(
!
pls
->
ctx
)
continue
;
if
(
!
cur
||
pls
->
cur_timestamp
<
mints
)
{
cur
=
pls
;
mints
=
pls
->
cur_timestamp
;
}
}
}
if
(
c
->
cur_audio
&&
!
c
->
cur_video
)
{
for
(
i
=
0
;
i
<
c
->
n_audios
;
i
++
)
{
cur
=
c
->
cur_audio
;
struct
representation
*
pls
=
c
->
audios
[
i
]
;
}
else
if
(
!
c
->
cur_audio
&&
c
->
cur_video
)
{
if
(
!
pls
->
ctx
)
cur
=
c
->
cur_video
;
continue
;
}
else
if
(
c
->
cur_video
->
cur_timestamp
<
c
->
cur_audio
->
cur_timestamp
)
{
if
(
!
cur
||
pls
->
cur_timestamp
<
mints
)
{
cur
=
c
->
cur_video
;
cur
=
pls
;
}
else
{
mints
=
pls
->
cur_timestamp
;
cur
=
c
->
cur_audio
;
}
}
}
if
(
cur
->
ctx
)
{
if
(
!
cur
)
{
while
(
!
ff_check_interrupt
(
c
->
interrupt_callback
)
&&
!
ret
)
{
return
AVERROR_INVALIDDATA
;
ret
=
av_read_frame
(
cur
->
ctx
,
pkt
);
}
if
(
ret
>=
0
)
{
while
(
!
ff_check_interrupt
(
c
->
interrupt_callback
)
&&
!
ret
)
{
/* If we got a packet, return it */
ret
=
av_read_frame
(
cur
->
ctx
,
pkt
);
cur
->
cur_timestamp
=
av_rescale
(
pkt
->
pts
,
(
int64_t
)
cur
->
ctx
->
streams
[
0
]
->
time_base
.
num
*
90000
,
cur
->
ctx
->
streams
[
0
]
->
time_base
.
den
);
if
(
ret
>=
0
)
{
pkt
->
stream_index
=
cur
->
stream_index
;
/* If we got a packet, return it */
return
0
;
cur
->
cur_timestamp
=
av_rescale
(
pkt
->
pts
,
(
int64_t
)
cur
->
ctx
->
streams
[
0
]
->
time_base
.
num
*
90000
,
cur
->
ctx
->
streams
[
0
]
->
time_base
.
den
)
;
}
pkt
->
stream_index
=
cur
->
stream_index
;
if
(
cur
->
is_restart_needed
)
{
return
0
;
cur
->
cur_seg_offset
=
0
;
}
cur
->
init_sec_buf_read_offset
=
0
;
if
(
cur
->
is_restart_needed
)
{
if
(
cur
->
input
)
cur
->
cur_seg_offset
=
0
;
ff_format_io_close
(
cur
->
parent
,
&
cur
->
input
)
;
cur
->
init_sec_buf_read_offset
=
0
;
ret
=
reopen_demux_for_component
(
s
,
cur
);
if
(
cur
->
input
)
cur
->
is_restart_needed
=
0
;
ff_format_io_close
(
cur
->
parent
,
&
cur
->
input
)
;
}
ret
=
reopen_demux_for_component
(
s
,
cur
);
cur
->
is_restart_needed
=
0
;
}
}
}
}
return
AVERROR_EOF
;
return
AVERROR_EOF
;
...
@@ -1721,12 +1802,8 @@ static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
...
@@ -1721,12 +1802,8 @@ static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
static
int
dash_close
(
AVFormatContext
*
s
)
static
int
dash_close
(
AVFormatContext
*
s
)
{
{
DASHContext
*
c
=
s
->
priv_data
;
DASHContext
*
c
=
s
->
priv_data
;
if
(
c
->
cur_audio
)
{
free_audio_list
(
c
);
free_representation
(
c
->
cur_audio
);
free_video_list
(
c
);
}
if
(
c
->
cur_video
)
{
free_representation
(
c
->
cur_video
);
}
av_freep
(
&
c
->
cookies
);
av_freep
(
&
c
->
cookies
);
av_freep
(
&
c
->
user_agent
);
av_freep
(
&
c
->
user_agent
);
...
@@ -1799,7 +1876,7 @@ set_seq_num:
...
@@ -1799,7 +1876,7 @@ set_seq_num:
static
int
dash_read_seek
(
AVFormatContext
*
s
,
int
stream_index
,
int64_t
timestamp
,
int
flags
)
static
int
dash_read_seek
(
AVFormatContext
*
s
,
int
stream_index
,
int64_t
timestamp
,
int
flags
)
{
{
int
ret
=
0
;
int
ret
,
i
;
DASHContext
*
c
=
s
->
priv_data
;
DASHContext
*
c
=
s
->
priv_data
;
int64_t
seek_pos_msec
=
av_rescale_rnd
(
timestamp
,
1000
,
int64_t
seek_pos_msec
=
av_rescale_rnd
(
timestamp
,
1000
,
s
->
streams
[
stream_index
]
->
time_base
.
den
,
s
->
streams
[
stream_index
]
->
time_base
.
den
,
...
@@ -1807,12 +1884,19 @@ static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestam
...
@@ -1807,12 +1884,19 @@ static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestam
AV_ROUND_DOWN
:
AV_ROUND_UP
);
AV_ROUND_DOWN
:
AV_ROUND_UP
);
if
((
flags
&
AVSEEK_FLAG_BYTE
)
||
c
->
is_live
)
if
((
flags
&
AVSEEK_FLAG_BYTE
)
||
c
->
is_live
)
return
AVERROR
(
ENOSYS
);
return
AVERROR
(
ENOSYS
);
if
(
c
->
cur_audio
)
{
ret
=
dash_seek
(
s
,
c
->
cur_audio
,
seek_pos_msec
,
flags
);
ret
=
AVERROR_EOF
;
for
(
i
=
0
;
i
<
c
->
n_videos
;
i
++
)
{
if
(
c
->
videos
[
i
]
->
stream_index
==
stream_index
)
{
ret
=
dash_seek
(
s
,
c
->
videos
[
i
],
seek_pos_msec
,
flags
);
}
}
}
if
(
!
ret
&&
c
->
cur_video
)
{
for
(
i
=
0
;
i
<
c
->
n_audios
;
i
++
)
{
ret
=
dash_seek
(
s
,
c
->
cur_video
,
seek_pos_msec
,
flags
);
if
(
c
->
audios
[
i
]
->
stream_index
==
stream_index
)
{
ret
=
dash_seek
(
s
,
c
->
audios
[
i
],
seek_pos_msec
,
flags
);
}
}
}
return
ret
;
return
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