avformat/hls: Use an array instead of stream offset for stream mapping
This will be useful when the amount of streams per subdemuxer is not known at hls_read_header time in a following commit. (cherry picked from commit 9884f17e343b37aef442fafa05bd0113cdf47087) Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
3586c68687
commit
309fa24f36
@ -98,7 +98,11 @@ struct playlist {
|
|||||||
int index;
|
int index;
|
||||||
AVFormatContext *ctx;
|
AVFormatContext *ctx;
|
||||||
AVPacket pkt;
|
AVPacket pkt;
|
||||||
int stream_offset;
|
|
||||||
|
/* main demuxer streams associated with this playlist
|
||||||
|
* indexed by the subdemuxer stream indexes */
|
||||||
|
AVStream **main_streams;
|
||||||
|
int n_main_streams;
|
||||||
|
|
||||||
int finished;
|
int finished;
|
||||||
enum PlaylistType type;
|
enum PlaylistType type;
|
||||||
@ -239,6 +243,7 @@ static void free_playlist_list(HLSContext *c)
|
|||||||
struct playlist *pls = c->playlists[i];
|
struct playlist *pls = c->playlists[i];
|
||||||
free_segment_list(pls);
|
free_segment_list(pls);
|
||||||
free_init_section_list(pls);
|
free_init_section_list(pls);
|
||||||
|
av_freep(&pls->main_streams);
|
||||||
av_freep(&pls->renditions);
|
av_freep(&pls->renditions);
|
||||||
av_freep(&pls->id3_buf);
|
av_freep(&pls->id3_buf);
|
||||||
av_dict_free(&pls->id3_initial);
|
av_dict_free(&pls->id3_initial);
|
||||||
@ -1248,13 +1253,13 @@ restart:
|
|||||||
|
|
||||||
/* Check that the playlist is still needed before opening a new
|
/* Check that the playlist is still needed before opening a new
|
||||||
* segment. */
|
* segment. */
|
||||||
if (v->ctx && v->ctx->nb_streams &&
|
if (v->ctx && v->ctx->nb_streams) {
|
||||||
v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) {
|
|
||||||
v->needed = 0;
|
v->needed = 0;
|
||||||
for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams;
|
for (i = 0; i < v->n_main_streams; i++) {
|
||||||
i++) {
|
if (v->main_streams[i]->discard < AVDISCARD_ALL) {
|
||||||
if (v->parent->streams[i]->discard < AVDISCARD_ALL)
|
|
||||||
v->needed = 1;
|
v->needed = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!v->needed) {
|
if (!v->needed) {
|
||||||
@ -1392,8 +1397,8 @@ static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pl
|
|||||||
int rend_idx = 0;
|
int rend_idx = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < pls->ctx->nb_streams; i++) {
|
for (i = 0; i < pls->n_main_streams; i++) {
|
||||||
AVStream *st = s->streams[pls->stream_offset + i];
|
AVStream *st = pls->main_streams[i];
|
||||||
|
|
||||||
if (st->codecpar->codec_type != type)
|
if (st->codecpar->codec_type != type)
|
||||||
continue;
|
continue;
|
||||||
@ -1519,7 +1524,7 @@ static int hls_read_header(AVFormatContext *s)
|
|||||||
{
|
{
|
||||||
void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
|
void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
|
||||||
HLSContext *c = s->priv_data;
|
HLSContext *c = s->priv_data;
|
||||||
int ret = 0, i, j, stream_offset = 0;
|
int ret = 0, i, j;
|
||||||
int highest_cur_seq_no = 0;
|
int highest_cur_seq_no = 0;
|
||||||
|
|
||||||
c->ctx = s;
|
c->ctx = s;
|
||||||
@ -1659,7 +1664,6 @@ static int hls_read_header(AVFormatContext *s)
|
|||||||
}
|
}
|
||||||
pls->ctx->pb = &pls->pb;
|
pls->ctx->pb = &pls->pb;
|
||||||
pls->ctx->io_open = nested_io_open;
|
pls->ctx->io_open = nested_io_open;
|
||||||
pls->stream_offset = stream_offset;
|
|
||||||
|
|
||||||
if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
|
if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1699,13 +1703,13 @@ static int hls_read_header(AVFormatContext *s)
|
|||||||
avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE);
|
avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE);
|
||||||
else
|
else
|
||||||
avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
|
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_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO);
|
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_VIDEO);
|
||||||
add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE);
|
add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE);
|
||||||
|
|
||||||
stream_offset += pls->ctx->nb_streams;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a program for each variant */
|
/* Create a program for each variant */
|
||||||
@ -1723,10 +1727,10 @@ static int hls_read_header(AVFormatContext *s)
|
|||||||
int is_shared = playlist_in_multiple_variants(c, pls);
|
int is_shared = playlist_in_multiple_variants(c, pls);
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
for (k = 0; k < pls->ctx->nb_streams; k++) {
|
for (k = 0; k < pls->n_main_streams; k++) {
|
||||||
struct AVStream *st = s->streams[pls->stream_offset + k];
|
struct AVStream *st = pls->main_streams[k];
|
||||||
|
|
||||||
av_program_add_stream_index(s, i, pls->stream_offset + k);
|
av_program_add_stream_index(s, i, st->index);
|
||||||
|
|
||||||
/* Set variant_bitrate for streams unique to this variant */
|
/* Set variant_bitrate for streams unique to this variant */
|
||||||
if (!is_shared && v->bandwidth)
|
if (!is_shared && v->bandwidth)
|
||||||
@ -1905,8 +1909,17 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
/* If we got a packet, return it */
|
/* If we got a packet, return it */
|
||||||
if (minplaylist >= 0) {
|
if (minplaylist >= 0) {
|
||||||
struct playlist *pls = c->playlists[minplaylist];
|
struct playlist *pls = c->playlists[minplaylist];
|
||||||
|
|
||||||
|
if (pls->pkt.stream_index >= pls->n_main_streams) {
|
||||||
|
av_log(s, AV_LOG_ERROR, "stream index inconsistency: index %d, %d main streams, %d subdemuxer streams\n",
|
||||||
|
pls->pkt.stream_index, pls->n_main_streams, pls->ctx->nb_streams);
|
||||||
|
av_packet_unref(&pls->pkt);
|
||||||
|
reset_packet(&pls->pkt);
|
||||||
|
return AVERROR_BUG;
|
||||||
|
}
|
||||||
|
|
||||||
*pkt = pls->pkt;
|
*pkt = pls->pkt;
|
||||||
pkt->stream_index += pls->stream_offset;
|
pkt->stream_index = pls->main_streams[pls->pkt.stream_index]->index;
|
||||||
reset_packet(&c->playlists[minplaylist]->pkt);
|
reset_packet(&c->playlists[minplaylist]->pkt);
|
||||||
|
|
||||||
if (pkt->dts != AV_NOPTS_VALUE)
|
if (pkt->dts != AV_NOPTS_VALUE)
|
||||||
@ -1938,6 +1951,8 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
|
|||||||
HLSContext *c = s->priv_data;
|
HLSContext *c = s->priv_data;
|
||||||
struct playlist *seek_pls = NULL;
|
struct playlist *seek_pls = NULL;
|
||||||
int i, seq_no;
|
int i, seq_no;
|
||||||
|
int j;
|
||||||
|
int stream_subdemuxer_index;
|
||||||
int64_t first_timestamp, seek_timestamp, duration;
|
int64_t first_timestamp, seek_timestamp, duration;
|
||||||
|
|
||||||
if ((flags & AVSEEK_FLAG_BYTE) ||
|
if ((flags & AVSEEK_FLAG_BYTE) ||
|
||||||
@ -1961,10 +1976,12 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
|
|||||||
/* find the playlist with the specified stream */
|
/* find the playlist with the specified stream */
|
||||||
for (i = 0; i < c->n_playlists; i++) {
|
for (i = 0; i < c->n_playlists; i++) {
|
||||||
struct playlist *pls = c->playlists[i];
|
struct playlist *pls = c->playlists[i];
|
||||||
if (stream_index >= pls->stream_offset &&
|
for (j = 0; j < pls->n_main_streams; j++) {
|
||||||
stream_index - pls->stream_offset < pls->ctx->nb_streams) {
|
if (pls->main_streams[j] == s->streams[stream_index]) {
|
||||||
seek_pls = pls;
|
seek_pls = pls;
|
||||||
break;
|
stream_subdemuxer_index = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* check if the timestamp is valid for the playlist with the
|
/* check if the timestamp is valid for the playlist with the
|
||||||
@ -1974,7 +1991,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
|
|||||||
|
|
||||||
/* set segment now so we do not need to search again below */
|
/* set segment now so we do not need to search again below */
|
||||||
seek_pls->cur_seq_no = seq_no;
|
seek_pls->cur_seq_no = seq_no;
|
||||||
seek_pls->seek_stream_index = stream_index - seek_pls->stream_offset;
|
seek_pls->seek_stream_index = stream_subdemuxer_index;
|
||||||
|
|
||||||
for (i = 0; i < c->n_playlists; i++) {
|
for (i = 0; i < c->n_playlists; i++) {
|
||||||
/* Reset reading */
|
/* Reset reading */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user