This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 5a75d905cb avformat/mpegts: create stream groups after having parsed
the entire PMT
5a75d905cb is described below
commit 5a75d905cb24572d14c4e37ad68e3965bfdacd84
Author: James Almer <[email protected]>
AuthorDate: Thu Mar 26 14:44:49 2026 -0300
Commit: James Almer <[email protected]>
CommitDate: Sat Mar 28 18:13:36 2026 -0300
avformat/mpegts: create stream groups after having parsed the entire PMT
Some faulty files have an LCEVC descriptor with a single stream, resulting
in
a group being created but never fully populated with the current
implementation.
Signed-off-by: James Almer <[email protected]>
---
libavformat/mpegts.c | 107 ++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 80 insertions(+), 27 deletions(-)
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 6f58e52e70..8eb3bae720 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -116,12 +116,22 @@ struct Stream {
#define MAX_STREAMS_PER_PROGRAM 128
#define MAX_PIDS_PER_PROGRAM (MAX_STREAMS_PER_PROGRAM + 2)
+
+struct StreamGroup {
+ enum AVStreamGroupParamsType type;
+ int id;
+ unsigned int nb_streams;
+ AVStream *streams[MAX_STREAMS_PER_PROGRAM];
+};
+
struct Program {
unsigned int id; // program id/service id
unsigned int nb_pids;
unsigned int pids[MAX_PIDS_PER_PROGRAM];
unsigned int nb_streams;
struct Stream streams[MAX_STREAMS_PER_PROGRAM];
+ unsigned int nb_stream_groups;
+ struct StreamGroup stream_groups[MAX_STREAMS_PER_PROGRAM];
/** have we found pmt for this program */
int pmt_found;
@@ -309,6 +319,8 @@ static void clear_program(struct Program *p)
return;
p->nb_pids = 0;
p->nb_streams = 0;
+ p->nb_stream_groups = 0;
+ memset(p->stream_groups, 0, sizeof(p->stream_groups));
p->pmt_found = 0;
}
@@ -1917,82 +1929,87 @@ static int
parse_mpeg2_extension_descriptor(AVFormatContext *fc, AVStream *st, i
break;
case LCEVC_VIDEO_DESCRIPTOR:
{
- AVStreamGroup *stg = NULL;
+ struct Program *p = get_program(ts, prg_id);
+ struct StreamGroup *stg;
int lcevc_stream_tag = get8(pp, desc_end);
- int ret, i;
+ int i;
- if (!get_program(ts, prg_id))
+ if (!p)
return 0;
if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC)
return AVERROR_INVALIDDATA;
- for (i = 0; i < fc->nb_stream_groups; i++) {
- stg = fc->stream_groups[i];
+ for (i = 0; i < p->nb_stream_groups; i++) {
+ stg = &p->stream_groups[i];
if (stg->type != AV_STREAM_GROUP_PARAMS_LCEVC)
continue;
if (stg->id == lcevc_stream_tag)
break;
}
- if (i == fc->nb_stream_groups)
- stg = avformat_stream_group_create(fc,
AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
- if (!stg)
- return AVERROR(ENOMEM);
+ if (i == p->nb_stream_groups) {
+ if (p->nb_stream_groups == MAX_STREAMS_PER_PROGRAM)
+ return AVERROR(EINVAL);
+ p->nb_stream_groups++;
+ }
+ stg = &p->stream_groups[i];
stg->id = lcevc_stream_tag;
+ stg->type = AV_STREAM_GROUP_PARAMS_LCEVC;
for (i = 0; i < stg->nb_streams; i++) {
if (stg->streams[i]->codecpar->codec_id == AV_CODEC_ID_LCEVC)
break;
}
if (i == stg->nb_streams) {
- ret = avformat_stream_group_add_stream(stg, st);
- av_assert0(ret != AVERROR(EEXIST));
- if (ret < 0)
- return ret;
+ if (stg->nb_streams == MAX_STREAMS_PER_PROGRAM)
+ return AVERROR(EINVAL);
+ stg->streams[stg->nb_streams++] = st;
} else
stg->streams[i] = st;
av_assert0(i < stg->nb_streams);
- stg->params.lcevc->lcevc_index = i;
}
break;
case LCEVC_LINKAGE_DESCRIPTOR:
{
+ struct Program *p = get_program(ts, prg_id);
int num_lcevc_stream_tags = get8(pp, desc_end);
- if (!get_program(ts, prg_id))
+ if (!p)
return 0;
if (st->codecpar->codec_id == AV_CODEC_ID_LCEVC)
return AVERROR_INVALIDDATA;
for (int i = 0; i < num_lcevc_stream_tags; i++) {
- AVStreamGroup *stg = NULL;
+ struct StreamGroup *stg = NULL;
int lcevc_stream_tag = get8(pp, desc_end);;
- int ret, j;
+ int j;
- for (j = 0; j < fc->nb_stream_groups; j++) {
- stg = fc->stream_groups[j];
+ for (j = 0; j < p->nb_stream_groups; j++) {
+ stg = &p->stream_groups[j];
if (stg->type != AV_STREAM_GROUP_PARAMS_LCEVC)
continue;
if (stg->id == lcevc_stream_tag)
break;
}
- if (j == fc->nb_stream_groups)
- stg = avformat_stream_group_create(fc,
AV_STREAM_GROUP_PARAMS_LCEVC, NULL);
- if (!stg)
- return AVERROR(ENOMEM);
+ if (j == p->nb_stream_groups) {
+ if (p->nb_stream_groups == MAX_STREAMS_PER_PROGRAM)
+ return AVERROR(EINVAL);
+ p->nb_stream_groups++;
+ }
+ stg = &p->stream_groups[j];
stg->id = lcevc_stream_tag;
+ stg->type = AV_STREAM_GROUP_PARAMS_LCEVC;
for (j = 0; j < stg->nb_streams; j++) {
if (stg->streams[j]->index == st->index)
break;
}
if (j == stg->nb_streams) {
- ret = avformat_stream_group_add_stream(stg, st);
- av_assert0(ret != AVERROR(EEXIST));
- if (ret < 0)
- return ret;
+ if (stg->nb_streams == MAX_STREAMS_PER_PROGRAM)
+ return AVERROR(EINVAL);
+ stg->streams[stg->nb_streams++] = st;
}
}
}
@@ -2529,6 +2546,39 @@ static int is_pes_stream(int stream_type, uint32_t
prog_reg_desc)
}
}
+static void create_stream_groups(MpegTSContext *ts, const struct Program *prg)
+{
+ for (int i = 0; i < prg->nb_stream_groups; i++) {
+ const struct StreamGroup *grp = &prg->stream_groups[i];
+ AVStreamGroup *stg;
+ int j;
+ if (grp->nb_streams < 2)
+ continue;
+ for (j = 0; j < ts->stream->nb_stream_groups; j++) {
+ stg = ts->stream->stream_groups[j];
+ if (stg->id == grp->id)
+ break;
+ }
+ if (j == ts->stream->nb_stream_groups)
+ stg = avformat_stream_group_create(ts->stream, grp->type, NULL);
+ else
+ continue;
+ if (!stg)
+ continue;
+ av_assert0(grp->type == AV_STREAM_GROUP_PARAMS_LCEVC);
+ stg->id = grp->id;
+ for (int j = 0; j < grp->nb_streams; j++) {
+ int ret = avformat_stream_group_add_stream(stg, grp->streams[j]);
+ if (ret < 0) {
+ ff_remove_stream_group(ts->stream, stg);
+ continue;
+ }
+ if (grp->streams[j]->codecpar->codec_id == AV_CODEC_ID_LCEVC)
+ stg->params.lcevc->lcevc_index = stg->nb_streams - 1;
+ }
+ }
+}
+
static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int
section_len)
{
MpegTSContext *ts = filter->u.section_filter.opaque;
@@ -2746,6 +2796,9 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t
*section, int section_len
mpegts_open_pcr_filter(ts, pcr_pid);
out:
+ if (prg)
+ create_stream_groups(ts, prg);
+
for (i = 0; i < mp4_descr_count; i++)
av_free(mp4_descr[i].dec_config_descr);
}
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]