fftools/ffmpeg_demux: automatically apply Alpha layer on Alpha Stream Group input

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer committed 2026-10-23 11:22:12 -03:00
1 parent c2c30b7b30
commit bd030344b7
3 files changed
+99 -13

No files matched your search

Vendored
+1 -1
View File
@@ -4355,7 +4355,7 @@ avutil_extralibs="d3d11va_extralibs d3d12va_extralibs mediacodec_extralibs nanos
# programs
ffmpeg_deps="avcodec avfilter avformat threads"
ffmpeg_select="aformat_filter anull_filter atrim_filter crop_filter
ffmpeg_select="aformat_filter alphamerge_filter anull_filter atrim_filter crop_filter
format_filter hflip_filter null_filter rotate_filter
transpose_filter trim_filter vflip_filter"
ffmpeg_suggest="ole32 psapi shell32"
+62
View File
@@ -1942,6 +1942,63 @@ static DemuxStreamGroup *demux_stream_group_alloc(Demuxer *d, AVStreamGroup *stg
return dsg;
}
static int istg_parse_alpha(const OptionsContext *o, Demuxer *d, InputStreamGroup *istg)
{
InputFile *f = &d->f;
AVStreamGroup *stg = istg->stg;
const AVStreamGroupLayeredVideo *layered_video = stg->params.layered_video;
OutputFilterOptions opts;
AVBPrint bp;
char *graph_str;
int ret;
if (stg->nb_entries != 2) {
av_log(istg, AV_LOG_FATAL, "A demuxer exported an invalid Alpha stream group. "
"This is a bug, please report it.\n");
return AVERROR_BUG;
}
memset(&opts, 0, sizeof(opts));
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
if (stg->entries[!layered_video->el_index]->type == AV_STREAM_GROUP_ENTRY_STREAM)
av_bprintf(&bp, "[%d:g:%d:%d]", f->index, stg->index, !layered_video->el_index);
else
av_bprintf(&bp, "[%d:g:%d]", f->index,
stg->entries[!layered_video->el_index]->stream_group->index);
if (stg->entries[layered_video->el_index]->type == AV_STREAM_GROUP_ENTRY_STREAM)
av_bprintf(&bp, "[%d:g:%d:%d]", f->index, stg->index, layered_video->el_index);
else
av_bprintf(&bp, "[%d:g:%d]", f->index,
stg->entries[layered_video->el_index]->stream_group->index);
av_bprintf(&bp, "alphamerge[%d:g:%d]", f->index, stg->index);
ret = av_bprint_finalize(&bp, &graph_str);
if (ret < 0)
return ret;
for (int i = 0; i < stg->nb_coded_side_data; i++) {
const AVPacketSideData *sd = &stg->coded_side_data[i];
ret = av_packet_side_data_to_frame(&opts.side_data, &opts.nb_side_data, sd, 0);
if (ret < 0 && ret != AVERROR(EINVAL))
goto fail;
}
ret = fg_create(NULL, &graph_str, d->sch, &opts);
if (ret < 0)
goto fail;
istg->fg = filtergraphs[nb_filtergraphs-1];
istg->fg->is_internal = 1;
ret = 0;
fail:
if (ret < 0)
av_freep(&graph_str);
return ret;
}
static int istg_parse_tile_grid(const OptionsContext *o, Demuxer *d, InputStreamGroup *istg)
{
InputFile *f = &d->f;
@@ -2114,6 +2171,11 @@ static int istg_add(const OptionsContext *o, Demuxer *d, AVStreamGroup *stg)
}
switch (stg->type) {
case AV_STREAM_GROUP_PARAMS_ALPHA:
ret = istg_parse_alpha(o, d, istg);
if (ret < 0)
return ret;
break;
case AV_STREAM_GROUP_PARAMS_TILE_GRID:
ret = istg_parse_tile_grid(o, d, istg);
if (ret < 0)
+36 -12
View File
@@ -1663,6 +1663,25 @@ fail:
return ret;
}
static int64_t score_new_packets_event_flag(const AVStreamGroup *stg)
{
int64_t score = 0;
for (int j = 0; j < stg->nb_entries; j++) {
if (stg->entries[j]->type != AV_STREAM_GROUP_ENTRY_STREAM)
continue;
AVStream *st = stg->entries[j]->stream;
if (st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) {
score += 100000000;
break;
}
}
return score;
}
static int map_auto_video(Muxer *mux, const OptionsContext *o)
{
AVFormatContext *oc = mux->fc;
@@ -1683,22 +1702,12 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
int64_t file_best_score = 0;
for (int i = 0; i < ifile->nb_stream_groups; i++) {
InputStreamGroup *istg = ifile->stream_groups[i];
int64_t score = 0;
int64_t score;
if (!istg->fg)
continue;
for (int j = 0; j < istg->stg->nb_entries; j++) {
if (istg->stg->entries[j]->type != AV_STREAM_GROUP_ENTRY_STREAM)
continue;
AVStream *st = istg->stg->entries[j]->stream;
if (st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) {
score = 100000000;
break;
}
}
score = score_new_packets_event_flag(istg->stg);
switch (istg->stg->type) {
case AV_STREAM_GROUP_PARAMS_TILE_GRID: {
@@ -1707,6 +1716,21 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
+ 5000000*!!(istg->stg->disposition & AV_DISPOSITION_DEFAULT);
break;
}
case AV_STREAM_GROUP_PARAMS_ALPHA: {
const AVStreamGroupLayeredVideo *layered_video = istg->stg->params.layered_video;
for (int k = 0; k < istg->stg->nb_entries; k++) {
const AVStreamGroupEntry *entry = istg->stg->entries[k];
int disposition = entry->type == AV_STREAM_GROUP_ENTRY_STREAM
? entry->stream->disposition
: entry->stream_group->disposition;
if (istg->stg->entries[k]->type == AV_STREAM_GROUP_ENTRY_STREAM_GROUP)
score += score_new_packets_event_flag(entry->stream_group);
score += 5000000*!!(disposition & AV_DISPOSITION_DEFAULT);
}
score += layered_video->width * (int64_t)layered_video->height
+ 5000000*!!(istg->stg->disposition & AV_DISPOSITION_DEFAULT);
break;
}
default:
continue;
}