1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-11-29 05:57:37 +02:00

fftools/ffmpeg_filter: handle metadata from stream group in relevant the filtergraphs

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer
2025-10-20 19:04:22 -03:00
parent dec3cc0138
commit 433d18a1d9
3 changed files with 93 additions and 7 deletions

View File

@@ -300,6 +300,8 @@ enum OFilterFlags {
// produce 24-bit audio
OFILTER_FLAG_AUDIO_24BIT = (1 << 1),
OFILTER_FLAG_AUTOSCALE = (1 << 2),
OFILTER_FLAG_AUTOROTATE = (1 << 3),
OFILTER_FLAG_CROP = (1 << 4),
};
typedef struct OutputFilterOptions {
@@ -333,6 +335,11 @@ typedef struct OutputFilterOptions {
enum AVColorRange color_range;
enum AVAlphaMode alpha_mode;
unsigned crop_top;
unsigned crop_bottom;
unsigned crop_left;
unsigned crop_right;
enum VideoSyncMethod vsync_method;
AVRational frame_rate;
AVRational max_frame_rate;
@@ -348,6 +355,9 @@ typedef struct OutputFilterOptions {
const enum AVColorRange *color_ranges;
const enum AVAlphaMode *alpha_modes;
AVFrameSideData **side_data;
int nb_side_data;
// for simple filtergraphs only, view specifier passed
// along to the decoder
const ViewSpecifier *vs;
@@ -827,7 +837,8 @@ int ofilter_bind_enc(OutputFilter *ofilter,
* @param graph_desc Graph description; an av_malloc()ed string, filtergraph
* takes ownership of it.
*/
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch);
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch,
const OutputFilterOptions *opts);
void fg_free(FilterGraph **pfg);

View File

@@ -204,6 +204,11 @@ typedef struct OutputFilterPriv {
enum AVColorRange color_range;
enum AVAlphaMode alpha_mode;
unsigned crop_top;
unsigned crop_bottom;
unsigned crop_left;
unsigned crop_right;
AVFrameSideData **side_data;
int nb_side_data;
@@ -228,6 +233,8 @@ typedef struct OutputFilterPriv {
const enum AVColorRange *color_ranges;
const enum AVAlphaMode *alpha_modes;
int32_t displaymatrix[9];
AVRational enc_timebase;
int64_t trim_start_us;
int64_t trim_duration_us;
@@ -818,7 +825,7 @@ int ofilter_bind_enc(OutputFilter *ofilter, unsigned sched_idx_enc,
ofp->needed = ofilter->bound = 1;
av_freep(&ofilter->linklabel);
ofp->flags = opts->flags;
ofp->flags |= opts->flags;
ofp->ts_offset = opts->ts_offset;
ofp->enc_timebase = opts->output_tb;
@@ -1078,7 +1085,8 @@ static const AVClass fg_class = {
.category = AV_CLASS_CATEGORY_FILTER,
};
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch,
const OutputFilterOptions *opts)
{
FilterGraphPriv *fgp;
FilterGraph *fg;
@@ -1175,11 +1183,13 @@ int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
const enum AVMediaType type = avfilter_pad_get_type(cur->filter_ctx->output_pads,
cur->pad_idx);
OutputFilter *const ofilter = ofilter_alloc(fg, type);
OutputFilterPriv *ofp;
if (!ofilter) {
ret = AVERROR(ENOMEM);
goto fail;
}
ofp = ofp_from_ofilter(ofilter);
ofilter->linklabel = cur->name;
cur->name = NULL;
@@ -1189,6 +1199,25 @@ int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
ret = AVERROR(ENOMEM);
goto fail;
}
// opts should only be needed in this function to fill fields from filtergraphs
// whose output is meant to be treated as if it was stream, e.g. merged HEIF
// tile groups.
if (opts) {
ofp->flags = opts->flags;
ofp->side_data = opts->side_data;
ofp->nb_side_data = opts->nb_side_data;
ofp->crop_top = opts->crop_top;
ofp->crop_bottom = opts->crop_bottom;
ofp->crop_left = opts->crop_left;
ofp->crop_right = opts->crop_right;
const AVFrameSideData *sd = av_frame_side_data_get(ofp->side_data, ofp->nb_side_data,
AV_FRAME_DATA_DISPLAYMATRIX);
if (sd)
memcpy(ofp->displaymatrix, sd->data, sizeof(ofp->displaymatrix));
}
}
if (!fg->nb_outputs) {
@@ -1225,7 +1254,7 @@ int fg_create_simple(FilterGraph **pfg,
FilterGraphPriv *fgp;
int ret;
ret = fg_create(pfg, graph_desc, sch);
ret = fg_create(pfg, graph_desc, sch, NULL);
if (ret < 0)
return ret;
fg = *pfg;
@@ -1603,6 +1632,53 @@ static int configure_output_video_filter(FilterGraphPriv *fgp, AVFilterGraph *gr
if (ret < 0)
return ret;
if (ofp->flags & OFILTER_FLAG_CROP) {
char crop_buf[64];
snprintf(crop_buf, sizeof(crop_buf), "w=iw-%u-%u:h=ih-%u-%u:x=%u:y=%u",
ofp->crop_left, ofp->crop_right,
ofp->crop_top, ofp->crop_bottom,
ofp->crop_left, ofp->crop_top);
ret = insert_filter(&last_filter, &pad_idx, "crop", crop_buf);
if (ret < 0)
return ret;
}
if (ofp->flags & OFILTER_FLAG_AUTOROTATE) {
int32_t *displaymatrix = ofp->displaymatrix;
double theta;
theta = get_rotation(displaymatrix);
if (fabs(theta - 90) < 1.0) {
ret = insert_filter(&last_filter, &pad_idx, "transpose",
displaymatrix[3] > 0 ? "cclock_flip" : "clock");
} else if (fabs(theta - 180) < 1.0) {
if (displaymatrix[0] < 0) {
ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
if (ret < 0)
return ret;
}
if (displaymatrix[4] < 0) {
ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
}
} else if (fabs(theta - 270) < 1.0) {
ret = insert_filter(&last_filter, &pad_idx, "transpose",
displaymatrix[3] < 0 ? "clock_flip" : "cclock");
} else if (fabs(theta) > 1.0) {
char rotate_buf[64];
snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf);
} else if (fabs(theta) < 1.0) {
if (displaymatrix && displaymatrix[4] < 0) {
ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
}
}
if (ret < 0)
return ret;
av_frame_side_data_remove(&ofp->side_data, &ofp->nb_side_data, AV_FRAME_DATA_DISPLAYMATRIX);
}
if ((ofp->width || ofp->height) && (ofp->flags & OFILTER_FLAG_AUTOSCALE)) {
char args[255];
AVFilterContext *filter;
@@ -2100,12 +2176,11 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout);
if (ret < 0)
goto fail;
av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
sd = av_buffersink_get_side_data(sink, &nb_sd);
if (nb_sd)
for (int j = 0; j < nb_sd; j++) {
ret = av_frame_side_data_clone(&ofp->side_data, &ofp->nb_side_data,
sd[j], 0);
sd[j], AV_FRAME_SIDE_DATA_FLAG_REPLACE);
if (ret < 0) {
av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
goto fail;

View File

@@ -1496,7 +1496,7 @@ int ffmpeg_parse_options(int argc, char **argv, Scheduler *sch)
/* create complex filtergraphs */
for (int i = 0; i < go.nb_filtergraphs; i++) {
ret = fg_create(NULL, go.filtergraphs[i], sch);
ret = fg_create(NULL, go.filtergraphs[i], sch, NULL);
go.filtergraphs[i] = NULL;
if (ret < 0)
goto fail;