avformat/hls: Move stream propagation to a separate function
Creation of main demuxer streams from subdemuxer streams is moved to update_streams_from_subdemuxer() which can be called repeatedly. There should be no functional changes.
This commit is contained in:
parent
9884f17e34
commit
83db3c84fa
@ -1348,25 +1348,6 @@ reload:
|
||||
goto restart;
|
||||
}
|
||||
|
||||
static int playlist_in_multiple_variants(HLSContext *c, struct playlist *pls)
|
||||
{
|
||||
int variant_count = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < c->n_variants && variant_count < 2; i++) {
|
||||
struct variant *v = c->variants[i];
|
||||
|
||||
for (j = 0; j < v->n_playlists; j++) {
|
||||
if (v->playlists[j] == pls) {
|
||||
variant_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return variant_count >= 2;
|
||||
}
|
||||
|
||||
static void add_renditions_to_variant(HLSContext *c, struct variant *var,
|
||||
enum AVMediaType type, const char *group_id)
|
||||
{
|
||||
@ -1520,11 +1501,65 @@ static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url,
|
||||
return AVERROR(EPERM);
|
||||
}
|
||||
|
||||
static void add_stream_to_programs(AVFormatContext *s, struct playlist *pls, AVStream *stream)
|
||||
{
|
||||
HLSContext *c = s->priv_data;
|
||||
int i, j;
|
||||
int bandwidth = -1;
|
||||
|
||||
for (i = 0; i < c->n_variants; i++) {
|
||||
struct variant *v = c->variants[i];
|
||||
|
||||
for (j = 0; j < v->n_playlists; j++) {
|
||||
if (v->playlists[j] != pls)
|
||||
continue;
|
||||
|
||||
av_program_add_stream_index(s, i, stream->index);
|
||||
|
||||
if (bandwidth < 0)
|
||||
bandwidth = v->bandwidth;
|
||||
else if (bandwidth != v->bandwidth)
|
||||
bandwidth = -1; /* stream in multiple variants with different bandwidths */
|
||||
}
|
||||
}
|
||||
|
||||
if (bandwidth >= 0)
|
||||
av_dict_set_int(&stream->metadata, "variant_bitrate", bandwidth, 0);
|
||||
}
|
||||
|
||||
/* add new subdemuxer streams to our context, if any */
|
||||
static int update_streams_from_subdemuxer(AVFormatContext *s, struct playlist *pls)
|
||||
{
|
||||
while (pls->n_main_streams < pls->ctx->nb_streams) {
|
||||
int ist_idx = pls->n_main_streams;
|
||||
AVStream *st = avformat_new_stream(s, NULL);
|
||||
AVStream *ist = pls->ctx->streams[ist_idx];
|
||||
|
||||
if (!st)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
st->id = pls->index;
|
||||
|
||||
avcodec_parameters_copy(st->codecpar, ist->codecpar);
|
||||
|
||||
if (pls->is_id3_timestamped) /* custom timestamps via id3 */
|
||||
avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE);
|
||||
else
|
||||
avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
|
||||
|
||||
dynarray_add(&pls->main_streams, &pls->n_main_streams, st);
|
||||
|
||||
add_stream_to_programs(s, pls, st);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hls_read_header(AVFormatContext *s)
|
||||
{
|
||||
void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
|
||||
HLSContext *c = s->priv_data;
|
||||
int ret = 0, i, j;
|
||||
int ret = 0, i;
|
||||
int highest_cur_seq_no = 0;
|
||||
|
||||
c->ctx = s;
|
||||
@ -1600,6 +1635,17 @@ static int hls_read_header(AVFormatContext *s)
|
||||
add_renditions_to_variant(c, var, AVMEDIA_TYPE_SUBTITLE, var->subtitles_group);
|
||||
}
|
||||
|
||||
/* Create a program for each variant */
|
||||
for (i = 0; i < c->n_variants; i++) {
|
||||
struct variant *v = c->variants[i];
|
||||
AVProgram *program;
|
||||
|
||||
program = av_new_program(s, i);
|
||||
if (!program)
|
||||
goto fail;
|
||||
av_dict_set_int(&program->metadata, "variant_bitrate", v->bandwidth, 0);
|
||||
}
|
||||
|
||||
/* Select the starting segments */
|
||||
for (i = 0; i < c->n_playlists; i++) {
|
||||
struct playlist *pls = c->playlists[i];
|
||||
@ -1688,57 +1734,15 @@ static int hls_read_header(AVFormatContext *s)
|
||||
av_log(s, AV_LOG_WARNING, "No expected HTTP requests have been made\n");
|
||||
|
||||
/* Create new AVStreams for each stream in this playlist */
|
||||
for (j = 0; j < pls->ctx->nb_streams; j++) {
|
||||
AVStream *st = avformat_new_stream(s, NULL);
|
||||
AVStream *ist = pls->ctx->streams[j];
|
||||
if (!st) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
st->id = i;
|
||||
|
||||
avcodec_parameters_copy(st->codecpar, pls->ctx->streams[j]->codecpar);
|
||||
|
||||
if (pls->is_id3_timestamped) /* custom timestamps via id3 */
|
||||
avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE);
|
||||
else
|
||||
avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
|
||||
|
||||
dynarray_add(&pls->main_streams, &pls->n_main_streams, st);
|
||||
}
|
||||
ret = update_streams_from_subdemuxer(s, pls);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO);
|
||||
add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO);
|
||||
add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE);
|
||||
}
|
||||
|
||||
/* Create a program for each variant */
|
||||
for (i = 0; i < c->n_variants; i++) {
|
||||
struct variant *v = c->variants[i];
|
||||
AVProgram *program;
|
||||
|
||||
program = av_new_program(s, i);
|
||||
if (!program)
|
||||
goto fail;
|
||||
av_dict_set_int(&program->metadata, "variant_bitrate", v->bandwidth, 0);
|
||||
|
||||
for (j = 0; j < v->n_playlists; j++) {
|
||||
struct playlist *pls = v->playlists[j];
|
||||
int is_shared = playlist_in_multiple_variants(c, pls);
|
||||
int k;
|
||||
|
||||
for (k = 0; k < pls->n_main_streams; k++) {
|
||||
struct AVStream *st = pls->main_streams[k];
|
||||
|
||||
av_program_add_stream_index(s, i, st->index);
|
||||
|
||||
/* Set variant_bitrate for streams unique to this variant */
|
||||
if (!is_shared && v->bandwidth)
|
||||
av_dict_set_int(&st->metadata, "variant_bitrate", v->bandwidth, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
free_playlist_list(c);
|
||||
|
Loading…
x
Reference in New Issue
Block a user