You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-11-23 21:54:53 +02:00
fftools/ffmpeg_mux_init: allow creating streams from filtergraphs created out of stream groups
Several formats are being designed where more than one independent video or audio stream within a container are part of what should be a single combined output. This is the case for HEIF (Defining a grid where the decoded output of several separate video streams are to be placed to generate a single output image) and IAMF (Defining audio streams where channels are present in separate coded stream). AVStreamGroup was designed and implemented in libavformat to convey this information, but the actual merging is left to the caller. This change allows the FFmpeg CLI to take said information, parse it, and create filtergraphs to merge the streams, making the combined output be usable automatically further in the process. Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
@@ -500,6 +500,7 @@ typedef struct InputStreamGroup {
|
||||
|
||||
int index;
|
||||
|
||||
FilterGraph *fg;
|
||||
AVStreamGroup *stg;
|
||||
} InputStreamGroup;
|
||||
|
||||
|
||||
@@ -1598,6 +1598,7 @@ fail:
|
||||
static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
||||
{
|
||||
AVFormatContext *oc = mux->fc;
|
||||
InputStreamGroup *best_istg = NULL;
|
||||
InputStream *best_ist = NULL;
|
||||
int64_t best_score = 0;
|
||||
int qcr;
|
||||
@@ -1609,8 +1610,35 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
||||
qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
|
||||
for (int j = 0; j < nb_input_files; j++) {
|
||||
InputFile *ifile = input_files[j];
|
||||
InputStreamGroup *file_best_istg = NULL;
|
||||
InputStream *file_best_ist = NULL;
|
||||
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;
|
||||
|
||||
if (!istg->fg)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < istg->stg->nb_streams; j++) {
|
||||
AVStream *st = istg->stg->streams[j];
|
||||
|
||||
if (st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) {
|
||||
score = 100000000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (istg->stg->type) {
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (score > file_best_score) {
|
||||
file_best_score = score;
|
||||
file_best_istg = istg;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ifile->nb_streams; i++) {
|
||||
InputStream *ist = ifile->streams[i];
|
||||
int64_t score;
|
||||
@@ -1630,6 +1658,15 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
||||
continue;
|
||||
file_best_score = score;
|
||||
file_best_ist = ist;
|
||||
file_best_istg = NULL;
|
||||
}
|
||||
}
|
||||
if (file_best_istg) {
|
||||
file_best_score -= 5000000*!!(file_best_istg->stg->disposition & AV_DISPOSITION_DEFAULT);
|
||||
if (file_best_score > best_score) {
|
||||
best_score = file_best_score;
|
||||
best_istg = file_best_istg;
|
||||
best_ist = NULL;
|
||||
}
|
||||
}
|
||||
if (file_best_ist) {
|
||||
@@ -1639,9 +1676,19 @@ static int map_auto_video(Muxer *mux, const OptionsContext *o)
|
||||
if (file_best_score > best_score) {
|
||||
best_score = file_best_score;
|
||||
best_ist = file_best_ist;
|
||||
best_istg = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_istg) {
|
||||
FilterGraph *fg = best_istg->fg;
|
||||
OutputFilter *ofilter = fg->outputs[0];
|
||||
|
||||
av_assert0(fg->nb_outputs == 1);
|
||||
av_log(mux, AV_LOG_VERBOSE, "Creating output stream from stream group derived complex filtergraph %d.\n", fg->index);
|
||||
|
||||
return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, NULL, ofilter, NULL, NULL);
|
||||
}
|
||||
if (best_ist)
|
||||
return ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL, NULL, NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user