* [FFmpeg-devel] [PATCH 02/31] lavfi/avfilter: add an "auto" constant to the threads option
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 03/31] fftools/ffmpeg_filter: do not pass OutputStream to set_channel_layout() Anton Khirnov
` (28 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Analogous to the same constant in avfiltergraph and avcodec.
Cf. f599ae88c25.
---
libavfilter/avfilter.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 7f94e71fbc..049e4f62ca 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -652,7 +652,8 @@ static const AVOption avfilter_options[] = {
{ "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = FLAGS, .unit = "thread_type" },
{ "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = TFLAGS },
{ "threads", "Allowed number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT,
- { .i64 = 0 }, 0, INT_MAX, FLAGS },
+ { .i64 = 0 }, 0, INT_MAX, FLAGS, .unit = "threads" },
+ {"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = FLAGS, .unit = "threads"},
{ "extra_hw_frames", "Number of extra hardware frames to allocate for the user",
OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS },
{ NULL },
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 03/31] fftools/ffmpeg_filter: do not pass OutputStream to set_channel_layout()
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 02/31] lavfi/avfilter: add an "auto" constant to the threads option Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 04/31] fftools/ffmpeg_filter: stop accessing AVCodecContext.codec Anton Khirnov
` (27 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
It only needs a list of allowed layouts and the requested layout.
---
fftools/ffmpeg_filter.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 2308abf82a..ba6c6c7673 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -722,42 +722,42 @@ static int ifilter_bind_dec(InputFilterPriv *ifp, Decoder *dec)
return 0;
}
-static int set_channel_layout(OutputFilterPriv *f, OutputStream *ost)
+static int set_channel_layout(OutputFilterPriv *f, const AVChannelLayout *layouts_allowed,
+ const AVChannelLayout *layout_requested)
{
- const AVCodec *c = ost->enc_ctx->codec;
int i, err;
- if (ost->enc_ctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
+ if (layout_requested->order != AV_CHANNEL_ORDER_UNSPEC) {
/* Pass the layout through for all orders but UNSPEC */
- err = av_channel_layout_copy(&f->ch_layout, &ost->enc_ctx->ch_layout);
+ err = av_channel_layout_copy(&f->ch_layout, layout_requested);
if (err < 0)
return err;
return 0;
}
/* Requested layout is of order UNSPEC */
- if (!c->ch_layouts) {
+ if (!layouts_allowed) {
/* Use the default native layout for the requested amount of channels when the
encoder doesn't have a list of supported layouts */
- av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels);
+ av_channel_layout_default(&f->ch_layout, layout_requested->nb_channels);
return 0;
}
/* Encoder has a list of supported layouts. Pick the first layout in it with the
same amount of channels as the requested layout */
- for (i = 0; c->ch_layouts[i].nb_channels; i++) {
- if (c->ch_layouts[i].nb_channels == ost->enc_ctx->ch_layout.nb_channels)
+ for (i = 0; layouts_allowed[i].nb_channels; i++) {
+ if (layouts_allowed[i].nb_channels == layout_requested->nb_channels)
break;
}
- if (c->ch_layouts[i].nb_channels) {
+ if (layouts_allowed[i].nb_channels) {
/* Use it if one is found */
- err = av_channel_layout_copy(&f->ch_layout, &c->ch_layouts[i]);
+ err = av_channel_layout_copy(&f->ch_layout, &layouts_allowed[i]);
if (err < 0)
return err;
return 0;
}
/* If no layout for the amount of channels requested was found, use the default
native layout for it. */
- av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels);
+ av_channel_layout_default(&f->ch_layout, layout_requested->nb_channels);
return 0;
}
@@ -844,7 +844,7 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofp->sample_rates = c->supported_samplerates;
}
if (ost->enc_ctx->ch_layout.nb_channels) {
- int ret = set_channel_layout(ofp, ost);
+ int ret = set_channel_layout(ofp, c->ch_layouts, &ost->enc_ctx->ch_layout);
if (ret < 0)
return ret;
} else if (c->ch_layouts) {
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 04/31] fftools/ffmpeg_filter: stop accessing AVCodecContext.codec
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 02/31] lavfi/avfilter: add an "auto" constant to the threads option Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 03/31] fftools/ffmpeg_filter: do not pass OutputStream to set_channel_layout() Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 05/31] fftools/ffmpeg_filter: check that filter type matches output stream type Anton Khirnov
` (26 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Instead pass the encoder through a newly-added output options struct,
analogous to previously added input options.
Will allow decoupling filtering from encoding in future commits.
---
fftools/ffmpeg.h | 11 +++++++++--
fftools/ffmpeg_filter.c | 36 +++++++++++++++++++-----------------
fftools/ffmpeg_mux_init.c | 8 ++++++--
3 files changed, 34 insertions(+), 21 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index a575ee70d5..8455cb23e4 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -263,6 +263,11 @@ typedef struct InputFilterOptions {
AVFrame *fallback;
} InputFilterOptions;
+typedef struct OutputFilterOptions {
+ // Codec used for encoding, may be NULL
+ const AVCodec *enc;
+} OutputFilterOptions;
+
typedef struct InputFilter {
struct FilterGraph *graph;
uint8_t *name;
@@ -684,7 +689,8 @@ int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_id
int filtergraph_is_simple(const FilterGraph *fg);
int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
char *graph_desc,
- Scheduler *sch, unsigned sch_idx_enc);
+ Scheduler *sch, unsigned sch_idx_enc,
+ const OutputFilterOptions *opts);
int fg_finalise_bindings(FilterGraph *fg);
/**
@@ -699,7 +705,8 @@ FrameData *packet_data (AVPacket *pkt);
const FrameData *packet_data_c(AVPacket *pkt);
int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
- unsigned sched_idx_enc);
+ unsigned sched_idx_enc,
+ const OutputFilterOptions *opts);
/**
* Create a new filtergraph in the global filtergraph list.
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index ba6c6c7673..0d359303f7 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -763,13 +763,13 @@ static int set_channel_layout(OutputFilterPriv *f, const AVChannelLayout *layout
}
int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
- unsigned sched_idx_enc)
+ unsigned sched_idx_enc,
+ const OutputFilterOptions *opts)
{
const OutputFile *of = ost->file;
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
FilterGraph *fg = ofilter->graph;
FilterGraphPriv *fgp = fgp_from_fg(fg);
- const AVCodec *c = ost->enc_ctx->codec;
int ret;
av_assert0(!ofilter->ost);
@@ -786,14 +786,14 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofp->height = ost->enc_ctx->height;
if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
ofp->format = ost->enc_ctx->pix_fmt;
- } else {
- ofp->formats = c->pix_fmts;
+ } else if (opts->enc) {
+ ofp->formats = opts->enc->pix_fmts;
// MJPEG encoder exports a full list of supported pixel formats,
// but the full-range ones are experimental-only.
// Restrict the auto-conversion list unless -strict experimental
// has been specified.
- if (!strcmp(c->name, "mjpeg")) {
+ if (!strcmp(opts->enc->name, "mjpeg")) {
// FIXME: YUV420P etc. are actually supported with full color range,
// yet the latter information isn't available here.
static const enum AVPixelFormat mjpeg_formats[] =
@@ -822,11 +822,11 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofp->fps.framerate = ost->frame_rate;
ofp->fps.framerate_max = ost->max_frame_rate;
- ofp->fps.framerate_supported = ost->force_fps ?
- NULL : c->supported_framerates;
+ ofp->fps.framerate_supported = ost->force_fps && opts->enc ?
+ NULL : opts->enc->supported_framerates;
// reduce frame rate for mpeg4 to be within the spec limits
- if (c->id == AV_CODEC_ID_MPEG4)
+ if (opts->enc && opts->enc->id == AV_CODEC_ID_MPEG4)
ofp->fps.framerate_clip = 65535;
ofp->fps.dup_warning = 1000;
@@ -835,20 +835,21 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
case AVMEDIA_TYPE_AUDIO:
if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) {
ofp->format = ost->enc_ctx->sample_fmt;
- } else {
- ofp->formats = c->sample_fmts;
+ } else if (opts->enc) {
+ ofp->formats = opts->enc->sample_fmts;
}
if (ost->enc_ctx->sample_rate) {
ofp->sample_rate = ost->enc_ctx->sample_rate;
- } else {
- ofp->sample_rates = c->supported_samplerates;
+ } else if (opts->enc) {
+ ofp->sample_rates = opts->enc->supported_samplerates;
}
if (ost->enc_ctx->ch_layout.nb_channels) {
- int ret = set_channel_layout(ofp, c->ch_layouts, &ost->enc_ctx->ch_layout);
+ int ret = set_channel_layout(ofp, opts->enc ? opts->enc->ch_layouts : NULL,
+ &ost->enc_ctx->ch_layout);
if (ret < 0)
return ret;
- } else if (c->ch_layouts) {
- ofp->ch_layouts = c->ch_layouts;
+ } else if (opts->enc) {
+ ofp->ch_layouts = opts->enc->ch_layouts;
}
break;
}
@@ -1079,7 +1080,8 @@ fail:
int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
char *graph_desc,
- Scheduler *sch, unsigned sched_idx_enc)
+ Scheduler *sch, unsigned sched_idx_enc,
+ const OutputFilterOptions *opts)
{
FilterGraph *fg;
FilterGraphPriv *fgp;
@@ -1111,7 +1113,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
if (ret < 0)
return ret;
- ret = ofilter_bind_ost(fg->outputs[0], ost, sched_idx_enc);
+ ret = ofilter_bind_ost(fg->outputs[0], ost, sched_idx_enc, opts);
if (ret < 0)
return ret;
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index d3d7d022ff..b5869feb80 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1371,14 +1371,18 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
if (ost->enc &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
+ OutputFilterOptions opts = {
+ .enc = enc,
+ };
+
if (ofilter) {
ost->filter = ofilter;
- ret = ofilter_bind_ost(ofilter, ost, ms->sch_idx_enc);
+ ret = ofilter_bind_ost(ofilter, ost, ms->sch_idx_enc, &opts);
if (ret < 0)
return ret;
} else {
ret = init_simple_filtergraph(ost->ist, ost, filters,
- mux->sch, ms->sch_idx_enc);
+ mux->sch, ms->sch_idx_enc, &opts);
if (ret < 0) {
av_log(ost, AV_LOG_ERROR,
"Error initializing a simple filtergraph\n");
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 05/31] fftools/ffmpeg_filter: check that filter type matches output stream type
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (2 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 04/31] fftools/ffmpeg_filter: stop accessing AVCodecContext.codec Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 06/31] fftools/ffmpeg_filter: pass ts offset through OutputFilterOptions Anton Khirnov
` (25 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
For simple filtergraphs. For complex filtergraphs they always match.
---
fftools/ffmpeg_filter.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 0d359303f7..a59c61b312 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -773,6 +773,7 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
int ret;
av_assert0(!ofilter->ost);
+ av_assert0(ofilter->type == ost->type);
ofilter->ost = ost;
av_freep(&ofilter->linklabel);
@@ -1106,6 +1107,13 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
graph_desc, fg->nb_inputs, fg->nb_outputs);
return AVERROR(EINVAL);
}
+ if (fg->outputs[0]->type != ost->type) {
+ av_log(fg, AV_LOG_ERROR, "Filtergraph has a %s output, cannot connect "
+ "it to %s output stream\n",
+ av_get_media_type_string(fg->outputs[0]->type),
+ av_get_media_type_string(ost->type));
+ return AVERROR(EINVAL);
+ }
ost->filter = fg->outputs[0];
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 06/31] fftools/ffmpeg_filter: pass ts offset through OutputFilterOptions
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (3 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 05/31] fftools/ffmpeg_filter: check that filter type matches output stream type Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 07/31] fftools/ffmpeg_filter: pass keep_pix_fmt " Anton Khirnov
` (24 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Reduces the need to access OutputFile, which will allow decoupling
filtering from encoding in future commits.
---
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_filter.c | 3 +--
fftools/ffmpeg_mux_init.c | 2 ++
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 8455cb23e4..7288a48aa1 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -266,6 +266,8 @@ typedef struct InputFilterOptions {
typedef struct OutputFilterOptions {
// Codec used for encoding, may be NULL
const AVCodec *enc;
+
+ int64_t ts_offset;
} OutputFilterOptions;
typedef struct InputFilter {
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index a59c61b312..8b05262622 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -766,7 +766,6 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
unsigned sched_idx_enc,
const OutputFilterOptions *opts)
{
- const OutputFile *of = ost->file;
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
FilterGraph *fg = ofilter->graph;
FilterGraphPriv *fgp = fgp_from_fg(fg);
@@ -778,7 +777,7 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofilter->ost = ost;
av_freep(&ofilter->linklabel);
- ofp->ts_offset = of->start_time == AV_NOPTS_VALUE ? 0 : of->start_time;
+ ofp->ts_offset = opts->ts_offset;
ofp->enc_timebase = ost->enc_timebase;
switch (ost->enc_ctx->codec_type) {
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index b5869feb80..83eab4276e 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1373,6 +1373,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
OutputFilterOptions opts = {
.enc = enc,
+ .ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
+ 0 : mux->of.start_time,
};
if (ofilter) {
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 07/31] fftools/ffmpeg_filter: pass keep_pix_fmt through OutputFilterOptions
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (4 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 06/31] fftools/ffmpeg_filter: pass ts offset through OutputFilterOptions Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 08/31] fftools/ffmpeg: warn about ignored -enc_time_base for subtitles earlier Anton Khirnov
` (23 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Reduces the need to access OutputStream, which will allow decoupling
filtering from encoding in future commits.
---
fftools/ffmpeg.h | 9 +++++++--
fftools/ffmpeg_filter.c | 8 +++++---
fftools/ffmpeg_mux_init.c | 9 +++++----
3 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 7288a48aa1..300ad8a987 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -263,11 +263,18 @@ typedef struct InputFilterOptions {
AVFrame *fallback;
} InputFilterOptions;
+enum OFilterFlags {
+ OFILTER_FLAG_DISABLE_CONVERT = (1 << 0),
+};
+
typedef struct OutputFilterOptions {
// Codec used for encoding, may be NULL
const AVCodec *enc;
int64_t ts_offset;
+
+ // A combination of OFilterFlags.
+ unsigned flags;
} OutputFilterOptions;
typedef struct InputFilter {
@@ -556,8 +563,6 @@ typedef struct OutputStream {
char *attachment_filename;
- int keep_pix_fmt;
-
/* stats */
// number of packets send to the muxer
atomic_uint_least64_t packets_written;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 8b05262622..5f2dbc387e 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -214,6 +214,8 @@ typedef struct OutputFilterPriv {
int64_t ts_offset;
int64_t next_pts;
FPSConvContext fps;
+
+ unsigned flags;
} OutputFilterPriv;
static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter)
@@ -355,11 +357,10 @@ static int choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint,
const char **dst)
{
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
- OutputStream *ost = ofilter->ost;
*dst = NULL;
- if (ost->keep_pix_fmt || ofp->format != AV_PIX_FMT_NONE) {
+ if (ofp->flags & OFILTER_FLAG_DISABLE_CONVERT || ofp->format != AV_PIX_FMT_NONE) {
*dst = ofp->format == AV_PIX_FMT_NONE ? NULL :
av_get_pix_fmt_name(ofp->format);
} else if (ofp->formats) {
@@ -777,6 +778,7 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofilter->ost = ost;
av_freep(&ofilter->linklabel);
+ ofp->flags = opts->flags;
ofp->ts_offset = opts->ts_offset;
ofp->enc_timebase = ost->enc_timebase;
@@ -814,7 +816,7 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
}
}
- fgp->disable_conversions |= ost->keep_pix_fmt;
+ fgp->disable_conversions |= !!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT);
ofp->fps.last_frame = av_frame_alloc();
if (!ofp->fps.last_frame)
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 83eab4276e..d79ae1f491 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -580,7 +580,7 @@ static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name)
}
static int new_stream_video(Muxer *mux, const OptionsContext *o,
- OutputStream *ost)
+ OutputStream *ost, int *keep_pix_fmt)
{
AVFormatContext *oc = mux->fc;
AVStream *st;
@@ -638,7 +638,7 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st);
if (frame_pix_fmt && *frame_pix_fmt == '+') {
- ost->keep_pix_fmt = 1;
+ *keep_pix_fmt = 1;
if (!*++frame_pix_fmt)
frame_pix_fmt = NULL;
}
@@ -1041,7 +1041,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
OutputStream *ost;
const AVCodec *enc;
AVStream *st;
- int ret = 0;
+ int ret = 0, keep_pix_fmt = 0;
const char *bsfs = NULL, *time_base = NULL;
char *filters = NULL, *next, *codec_tag = NULL;
double qscale = -1;
@@ -1356,7 +1356,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
ms->copy_initial_nonkeyframes, oc, st);
switch (type) {
- case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost); break;
+ case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost, &keep_pix_fmt); break;
case AVMEDIA_TYPE_AUDIO: ret = new_stream_audio (mux, o, ost); break;
case AVMEDIA_TYPE_SUBTITLE: ret = new_stream_subtitle (mux, o, ost); break;
}
@@ -1375,6 +1375,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
.enc = enc,
.ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
0 : mux->of.start_time,
+ .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt,
};
if (ofilter) {
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 08/31] fftools/ffmpeg: warn about ignored -enc_time_base for subtitles earlier
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (5 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 07/31] fftools/ffmpeg_filter: pass keep_pix_fmt " Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 09/31] fftools/ffmpeg_filter: pass enc_timebase through OutputFilterOptions Anton Khirnov
` (22 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Can do it as soon as that option is parsed, no need to postpone it until
opening the encoder.
---
fftools/ffmpeg_enc.c | 3 ---
fftools/ffmpeg_mux_init.c | 6 +++++-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index d1d1526830..618ba193ff 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -280,9 +280,6 @@ int enc_open(void *opaque, const AVFrame *frame)
break;
}
case AVMEDIA_TYPE_SUBTITLE:
- if (ost->enc_timebase.num)
- av_log(ost, AV_LOG_WARNING,
- "-enc_time_base not supported for subtitles, ignoring\n");
enc_ctx->time_base = AV_TIME_BASE_Q;
if (!enc_ctx->width) {
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index d79ae1f491..8b03d3b108 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1233,8 +1233,12 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
}
MATCH_PER_STREAM_OPT(enc_time_bases, str, enc_time_base, oc, st);
- if (enc_time_base) {
+ if (enc_time_base && type == AVMEDIA_TYPE_SUBTITLE)
+ av_log(ost, AV_LOG_WARNING,
+ "-enc_time_base not supported for subtitles, ignoring\n");
+ else if (enc_time_base) {
AVRational q;
+
if (!strcmp(enc_time_base, "demux")) {
q = (AVRational){ ENC_TIME_BASE_DEMUX, 0 };
} else if (!strcmp(enc_time_base, "filter")) {
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 09/31] fftools/ffmpeg_filter: pass enc_timebase through OutputFilterOptions
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (6 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 08/31] fftools/ffmpeg: warn about ignored -enc_time_base for subtitles earlier Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 10/31] fftools/ffmpeg_filter: move the MJPEG format selection hack to muxer setup Anton Khirnov
` (21 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Reduces the need to access OutputStream, which will allow decoupling
filtering from encoding in future commits.
---
fftools/ffmpeg.h | 7 +++++--
fftools/ffmpeg_filter.c | 2 +-
fftools/ffmpeg_mux_init.c | 4 +++-
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 300ad8a987..56c2fedcc4 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -273,6 +273,11 @@ typedef struct OutputFilterOptions {
int64_t ts_offset;
+ /* Desired output timebase.
+ * Numerator can be one of EncTimeBase values, or 0 when no preference.
+ */
+ AVRational output_tb;
+
// A combination of OFilterFlags.
unsigned flags;
} OutputFilterOptions;
@@ -529,8 +534,6 @@ typedef struct OutputStream {
AVStream *st; /* stream in the output file */
- AVRational enc_timebase;
-
Encoder *enc;
AVCodecContext *enc_ctx;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 5f2dbc387e..0b78898af0 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -780,7 +780,7 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofp->flags = opts->flags;
ofp->ts_offset = opts->ts_offset;
- ofp->enc_timebase = ost->enc_timebase;
+ ofp->enc_timebase = opts->output_tb;
switch (ost->enc_ctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 8b03d3b108..28090423c6 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1042,6 +1042,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
const AVCodec *enc;
AVStream *st;
int ret = 0, keep_pix_fmt = 0;
+ AVRational enc_tb = { 0, 0 };
const char *bsfs = NULL, *time_base = NULL;
char *filters = NULL, *next, *codec_tag = NULL;
double qscale = -1;
@@ -1260,7 +1261,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
#endif
}
- ost->enc_timebase = q;
+ enc_tb = q;
}
} else {
ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st,
@@ -1377,6 +1378,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
OutputFilterOptions opts = {
.enc = enc,
+ .output_tb = enc_tb,
.ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
0 : mux->of.start_time,
.flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt,
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 10/31] fftools/ffmpeg_filter: move the MJPEG format selection hack to muxer setup
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (7 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 09/31] fftools/ffmpeg_filter: pass enc_timebase through OutputFilterOptions Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 11/31] fftools/ffmpeg_filter: stop accessing encoder AVCodecContext Anton Khirnov
` (20 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
That, if anywhere, is a more appropriate place for it.
---
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_filter.c | 29 +++--------------------------
fftools/ffmpeg_mux_init.c | 24 ++++++++++++++++++++++++
3 files changed, 29 insertions(+), 26 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 56c2fedcc4..d0e896dbe7 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -270,6 +270,8 @@ enum OFilterFlags {
typedef struct OutputFilterOptions {
// Codec used for encoding, may be NULL
const AVCodec *enc;
+ // Overrides encoder pixel formats when set.
+ const enum AVPixelFormat *pix_fmts;
int64_t ts_offset;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 0b78898af0..5661dc960a 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -788,34 +788,11 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofp->height = ost->enc_ctx->height;
if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
ofp->format = ost->enc_ctx->pix_fmt;
- } else if (opts->enc) {
+ } else if (opts->pix_fmts)
+ ofp->formats = opts->pix_fmts;
+ else if (opts->enc)
ofp->formats = opts->enc->pix_fmts;
- // MJPEG encoder exports a full list of supported pixel formats,
- // but the full-range ones are experimental-only.
- // Restrict the auto-conversion list unless -strict experimental
- // has been specified.
- if (!strcmp(opts->enc->name, "mjpeg")) {
- // FIXME: YUV420P etc. are actually supported with full color range,
- // yet the latter information isn't available here.
- static const enum AVPixelFormat mjpeg_formats[] =
- { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
- AV_PIX_FMT_NONE };
-
- const AVDictionaryEntry *strict = av_dict_get(ost->encoder_opts, "strict", NULL, 0);
- int strict_val = ost->enc_ctx->strict_std_compliance;
-
- if (strict) {
- const AVOption *o = av_opt_find(ost->enc_ctx, strict->key, NULL, 0, 0);
- av_assert0(o);
- av_opt_eval_int(ost->enc_ctx, o, strict->value, &strict_val);
- }
-
- if (strict_val > FF_COMPLIANCE_UNOFFICIAL)
- ofp->formats = mjpeg_formats;
- }
- }
-
fgp->disable_conversions |= !!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT);
ofp->fps.last_frame = av_frame_alloc();
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 28090423c6..04642f5c8b 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1384,6 +1384,30 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
.flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt,
};
+ // MJPEG encoder exports a full list of supported pixel formats,
+ // but the full-range ones are experimental-only.
+ // Restrict the auto-conversion list unless -strict experimental
+ // has been specified.
+ if (!strcmp(enc->name, "mjpeg")) {
+ // FIXME: YUV420P etc. are actually supported with full color range,
+ // yet the latter information isn't available here.
+ static const enum AVPixelFormat mjpeg_formats[] =
+ { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
+ AV_PIX_FMT_NONE };
+
+ const AVDictionaryEntry *strict = av_dict_get(ost->encoder_opts, "strict", NULL, 0);
+ int strict_val = ost->enc_ctx->strict_std_compliance;
+
+ if (strict) {
+ const AVOption *o = av_opt_find(ost->enc_ctx, strict->key, NULL, 0, 0);
+ av_assert0(o);
+ av_opt_eval_int(ost->enc_ctx, o, strict->value, &strict_val);
+ }
+
+ if (strict_val > FF_COMPLIANCE_UNOFFICIAL)
+ opts.pix_fmts = mjpeg_formats;
+ }
+
if (ofilter) {
ost->filter = ofilter;
ret = ofilter_bind_ost(ofilter, ost, ms->sch_idx_enc, &opts);
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 11/31] fftools/ffmpeg_filter: stop accessing encoder AVCodecContext
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (8 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 10/31] fftools/ffmpeg_filter: move the MJPEG format selection hack to muxer setup Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:50 ` Dennis Mungai
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 12/31] fftools/ffmpeg_filter: pass vsync method through OutputFilterOptions Anton Khirnov
` (19 subsequent siblings)
29 siblings, 1 reply; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Pass all the necessary value through OutputFilterOptions.
Will allow decoupling filtering from encoding in future commits.
---
fftools/ffmpeg.h | 7 +++++++
fftools/ffmpeg_filter.c | 22 +++++++++++-----------
fftools/ffmpeg_mux_init.c | 6 ++++++
3 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index d0e896dbe7..598ca2fa96 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -282,6 +282,13 @@ typedef struct OutputFilterOptions {
// A combination of OFilterFlags.
unsigned flags;
+
+ int format;
+ int width;
+ int height;
+
+ int sample_rate;
+ AVChannelLayout ch_layout;
} OutputFilterOptions;
typedef struct InputFilter {
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 5661dc960a..3c25d2ed65 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -782,12 +782,12 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofp->ts_offset = opts->ts_offset;
ofp->enc_timebase = opts->output_tb;
- switch (ost->enc_ctx->codec_type) {
+ switch (ofilter->type) {
case AVMEDIA_TYPE_VIDEO:
- ofp->width = ost->enc_ctx->width;
- ofp->height = ost->enc_ctx->height;
- if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
- ofp->format = ost->enc_ctx->pix_fmt;
+ ofp->width = opts->width;
+ ofp->height = opts->height;
+ if (opts->format != AV_PIX_FMT_NONE) {
+ ofp->format = opts->format;
} else if (opts->pix_fmts)
ofp->formats = opts->pix_fmts;
else if (opts->enc)
@@ -812,19 +812,19 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
break;
case AVMEDIA_TYPE_AUDIO:
- if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) {
- ofp->format = ost->enc_ctx->sample_fmt;
+ if (opts->format != AV_SAMPLE_FMT_NONE) {
+ ofp->format = opts->format;
} else if (opts->enc) {
ofp->formats = opts->enc->sample_fmts;
}
- if (ost->enc_ctx->sample_rate) {
- ofp->sample_rate = ost->enc_ctx->sample_rate;
+ if (opts->sample_rate) {
+ ofp->sample_rate = opts->sample_rate;
} else if (opts->enc) {
ofp->sample_rates = opts->enc->supported_samplerates;
}
- if (ost->enc_ctx->ch_layout.nb_channels) {
+ if (opts->ch_layout.nb_channels) {
int ret = set_channel_layout(ofp, opts->enc ? opts->enc->ch_layouts : NULL,
- &ost->enc_ctx->ch_layout);
+ &opts->ch_layout);
if (ret < 0)
return ret;
} else if (opts->enc) {
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 04642f5c8b..b031cc59d2 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1378,6 +1378,12 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
OutputFilterOptions opts = {
.enc = enc,
+ .format = (type == AVMEDIA_TYPE_VIDEO) ?
+ ost->enc_ctx->pix_fmt : ost->enc_ctx->sample_fmt,
+ .width = ost->enc_ctx->width,
+ .height = ost->enc_ctx->height,
+ .sample_rate = ost->enc_ctx->sample_rate,
+ .ch_layout = ost->enc_ctx->ch_layout,
.output_tb = enc_tb,
.ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
0 : mux->of.start_time,
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [FFmpeg-devel] [PATCH 11/31] fftools/ffmpeg_filter: stop accessing encoder AVCodecContext
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 11/31] fftools/ffmpeg_filter: stop accessing encoder AVCodecContext Anton Khirnov
@ 2024-04-05 16:50 ` Dennis Mungai
2024-04-05 16:54 ` Gyan Doshi
0 siblings, 1 reply; 35+ messages in thread
From: Dennis Mungai @ 2024-04-05 16:50 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Fri, 5 Apr 2024, 19:14 Anton Khirnov, <anton@khirnov.net> wrote:
> Pass all the necessary value through OutputFilterOptions.
>
> Will allow decoupling filtering from encoding in future commits.
> ---
> fftools/ffmpeg.h | 7 +++++++
> fftools/ffmpeg_filter.c | 22 +++++++++++-----------
> fftools/ffmpeg_mux_init.c | 6 ++++++
> 3 files changed, 24 insertions(+), 11 deletions(-)
>
> diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
> index d0e896dbe7..598ca2fa96 100644
> --- a/fftools/ffmpeg.h
> +++ b/fftools/ffmpeg.h
> @@ -282,6 +282,13 @@ typedef struct OutputFilterOptions {
>
> // A combination of OFilterFlags.
> unsigned flags;
> +
> + int format;
> + int width;
> + int height;
> +
> + int sample_rate;
> + AVChannelLayout ch_layout;
> } OutputFilterOptions;
>
> typedef struct InputFilter {
> diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
> index 5661dc960a..3c25d2ed65 100644
> --- a/fftools/ffmpeg_filter.c
> +++ b/fftools/ffmpeg_filter.c
> @@ -782,12 +782,12 @@ int ofilter_bind_ost(OutputFilter *ofilter,
> OutputStream *ost,
> ofp->ts_offset = opts->ts_offset;
> ofp->enc_timebase = opts->output_tb;
>
> - switch (ost->enc_ctx->codec_type) {
> + switch (ofilter->type) {
> case AVMEDIA_TYPE_VIDEO:
> - ofp->width = ost->enc_ctx->width;
> - ofp->height = ost->enc_ctx->height;
> - if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
> - ofp->format = ost->enc_ctx->pix_fmt;
> + ofp->width = opts->width;
> + ofp->height = opts->height;
> + if (opts->format != AV_PIX_FMT_NONE) {
> + ofp->format = opts->format;
> } else if (opts->pix_fmts)
> ofp->formats = opts->pix_fmts;
> else if (opts->enc)
> @@ -812,19 +812,19 @@ int ofilter_bind_ost(OutputFilter *ofilter,
> OutputStream *ost,
>
> break;
> case AVMEDIA_TYPE_AUDIO:
> - if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) {
> - ofp->format = ost->enc_ctx->sample_fmt;
> + if (opts->format != AV_SAMPLE_FMT_NONE) {
> + ofp->format = opts->format;
> } else if (opts->enc) {
> ofp->formats = opts->enc->sample_fmts;
> }
> - if (ost->enc_ctx->sample_rate) {
> - ofp->sample_rate = ost->enc_ctx->sample_rate;
> + if (opts->sample_rate) {
> + ofp->sample_rate = opts->sample_rate;
> } else if (opts->enc) {
> ofp->sample_rates = opts->enc->supported_samplerates;
> }
> - if (ost->enc_ctx->ch_layout.nb_channels) {
> + if (opts->ch_layout.nb_channels) {
> int ret = set_channel_layout(ofp, opts->enc ?
> opts->enc->ch_layouts : NULL,
> - &ost->enc_ctx->ch_layout);
> + &opts->ch_layout);
> if (ret < 0)
> return ret;
> } else if (opts->enc) {
> diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
> index 04642f5c8b..b031cc59d2 100644
> --- a/fftools/ffmpeg_mux_init.c
> +++ b/fftools/ffmpeg_mux_init.c
> @@ -1378,6 +1378,12 @@ static int ost_add(Muxer *mux, const OptionsContext
> *o, enum AVMediaType type,
> (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
> OutputFilterOptions opts = {
> .enc = enc,
> + .format = (type == AVMEDIA_TYPE_VIDEO) ?
> + ost->enc_ctx->pix_fmt :
> ost->enc_ctx->sample_fmt,
> + .width = ost->enc_ctx->width,
> + .height = ost->enc_ctx->height,
> + .sample_rate = ost->enc_ctx->sample_rate,
> + .ch_layout = ost->enc_ctx->ch_layout,
> .output_tb = enc_tb,
> .ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
> 0 : mux->of.start_time,
> --
> 2.43.0
>
Does this imply that down the line, with this and additional patchsets,
that FFmpeg can handle tasks such as stream copy and filtering in the same
invocation?
>
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [FFmpeg-devel] [PATCH 11/31] fftools/ffmpeg_filter: stop accessing encoder AVCodecContext
2024-04-05 16:50 ` Dennis Mungai
@ 2024-04-05 16:54 ` Gyan Doshi
2024-04-05 17:07 ` Dennis Mungai
0 siblings, 1 reply; 35+ messages in thread
From: Gyan Doshi @ 2024-04-05 16:54 UTC (permalink / raw)
To: ffmpeg-devel
On 2024-04-05 10:20 pm, Dennis Mungai wrote:
>
> Does this imply that down the line, with this and additional patchsets,
> that FFmpeg can handle tasks such as stream copy and filtering in the same
> invocation?
What do you mean? If you map a stream twice, you already can do that now.
Regards,
Gyan
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [FFmpeg-devel] [PATCH 11/31] fftools/ffmpeg_filter: stop accessing encoder AVCodecContext
2024-04-05 16:54 ` Gyan Doshi
@ 2024-04-05 17:07 ` Dennis Mungai
2024-04-05 17:09 ` Anton Khirnov
0 siblings, 1 reply; 35+ messages in thread
From: Dennis Mungai @ 2024-04-05 17:07 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Fri, 5 Apr 2024 at 19:54, Gyan Doshi <ffmpeg@gyani.pro> wrote:
>
>
> On 2024-04-05 10:20 pm, Dennis Mungai wrote:
> >
> > Does this imply that down the line, with this and additional patchsets,
> > that FFmpeg can handle tasks such as stream copy and filtering in the
> same
> > invocation?
>
> What do you mean? If you map a stream twice, you already can do that now.
>
> Regards,
> Gyan
>
What of doing the same *without* mapping the stream twice?
A complex filtergraph could have a stream mapped, split and then passed to
a copy codec operation, for example, without needing the double re-map
implied above.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [FFmpeg-devel] [PATCH 11/31] fftools/ffmpeg_filter: stop accessing encoder AVCodecContext
2024-04-05 17:07 ` Dennis Mungai
@ 2024-04-05 17:09 ` Anton Khirnov
0 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 17:09 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Dennis Mungai (2024-04-05 19:07:19)
> On Fri, 5 Apr 2024 at 19:54, Gyan Doshi <ffmpeg@gyani.pro> wrote:
>
> >
> >
> > On 2024-04-05 10:20 pm, Dennis Mungai wrote:
> > >
> > > Does this imply that down the line, with this and additional patchsets,
> > > that FFmpeg can handle tasks such as stream copy and filtering in the
> > same
> > > invocation?
> >
> > What do you mean? If you map a stream twice, you already can do that now.
> >
> > Regards,
> > Gyan
> >
>
> What of doing the same *without* mapping the stream twice?
What's the issue with mapping a stream twice?
> A complex filtergraph could have a stream mapped, split and then passed to
> a copy codec operation, for example, without needing the double re-map
> implied above.
Filtergraphs process decoded frames, streamcopy bypasses them entirely.
None of this affects streamcopy.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 12/31] fftools/ffmpeg_filter: pass vsync method through OutputFilterOptions
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (9 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 11/31] fftools/ffmpeg_filter: stop accessing encoder AVCodecContext Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 13/31] fftools/ffmpeg: drop OutputStream.is_cfr Anton Khirnov
` (18 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Do not read it from OutputStream directly.
Will allow decoupling filtering from encoding in future commits.
---
fftools/ffmpeg.h | 3 ++-
fftools/ffmpeg_filter.c | 9 +++++---
fftools/ffmpeg_mux.c | 2 +-
fftools/ffmpeg_mux.h | 3 +++
fftools/ffmpeg_mux_init.c | 45 ++++++++++++++++++++++-----------------
5 files changed, 38 insertions(+), 24 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 598ca2fa96..fa8f7d8324 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -287,6 +287,8 @@ typedef struct OutputFilterOptions {
int width;
int height;
+ enum VideoSyncMethod vsync_method;
+
int sample_rate;
AVChannelLayout ch_layout;
} OutputFilterOptions;
@@ -549,7 +551,6 @@ typedef struct OutputStream {
/* video only */
AVRational frame_rate;
AVRational max_frame_rate;
- enum VideoSyncMethod vsync_method;
int is_cfr;
int force_fps;
#if FFMPEG_OPT_TOP
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 3c25d2ed65..d906b72576 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -175,6 +175,8 @@ typedef struct FPSConvContext {
int last_dropped;
int dropped_keyframe;
+ enum VideoSyncMethod vsync_method;
+
AVRational framerate;
AVRational framerate_max;
const AVRational *framerate_supported;
@@ -799,6 +801,7 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
if (!ofp->fps.last_frame)
return AVERROR(ENOMEM);
+ ofp->fps.vsync_method = opts->vsync_method;
ofp->fps.framerate = ost->frame_rate;
ofp->fps.framerate_max = ost->max_frame_rate;
ofp->fps.framerate_supported = ost->force_fps && opts->enc ?
@@ -2072,9 +2075,9 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
if (delta0 < 0 &&
delta > 0 &&
- ost->vsync_method != VSYNC_PASSTHROUGH
+ fps->vsync_method != VSYNC_PASSTHROUGH
#if FFMPEG_OPT_VSYNC_DROP
- && ost->vsync_method != VSYNC_DROP
+ && fps->vsync_method != VSYNC_DROP
#endif
) {
if (delta0 < -0.6) {
@@ -2086,7 +2089,7 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
delta0 = 0;
}
- switch (ost->vsync_method) {
+ switch (fps->vsync_method) {
case VSYNC_VSCFR:
if (fps->frame_number == 0 && delta0 >= 0.5) {
av_log(ost, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0));
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index e8e5c677b8..253c2e58d4 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -140,7 +140,7 @@ static int mux_fixup_ts(Muxer *mux, MuxStream *ms, AVPacket *pkt)
OutputStream *ost = &ms->ost;
#if FFMPEG_OPT_VSYNC_DROP
- if (ost->type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP)
+ if (ost->type == AVMEDIA_TYPE_VIDEO && ms->ts_drop)
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
#endif
diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h
index 16af6d38ba..f8b6f7a790 100644
--- a/fftools/ffmpeg_mux.h
+++ b/fftools/ffmpeg_mux.h
@@ -75,6 +75,9 @@ typedef struct MuxStream {
int copy_initial_nonkeyframes;
int copy_prior_start;
int streamcopy_started;
+#if FFMPEG_OPT_VSYNC_DROP
+ int ts_drop;
+#endif
} MuxStream;
typedef struct Muxer {
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index b031cc59d2..6ffa4b7491 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -580,8 +580,10 @@ static enum AVPixelFormat pix_fmt_parse(OutputStream *ost, const char *name)
}
static int new_stream_video(Muxer *mux, const OptionsContext *o,
- OutputStream *ost, int *keep_pix_fmt)
+ OutputStream *ost, int *keep_pix_fmt,
+ enum VideoSyncMethod *vsync_method)
{
+ MuxStream *ms = ms_from_ost(ost);
AVFormatContext *oc = mux->fc;
AVStream *st;
char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL;
@@ -773,49 +775,52 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
#endif
#if FFMPEG_OPT_VSYNC
- ost->vsync_method = video_sync_method;
+ *vsync_method = video_sync_method;
#else
- ost->vsync_method = VSYNC_AUTO;
+ *vsync_method = VSYNC_AUTO;
#endif
MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st);
if (fps_mode) {
- ret = parse_and_set_vsync(fps_mode, &ost->vsync_method, ost->file->index, ost->index, 0);
+ ret = parse_and_set_vsync(fps_mode, vsync_method, ost->file->index, ost->index, 0);
if (ret < 0)
return ret;
}
if ((ost->frame_rate.num || ost->max_frame_rate.num) &&
- !(ost->vsync_method == VSYNC_AUTO ||
- ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR)) {
+ !(*vsync_method == VSYNC_AUTO ||
+ *vsync_method == VSYNC_CFR || *vsync_method == VSYNC_VSCFR)) {
av_log(ost, AV_LOG_FATAL, "One of -r/-fpsmax was specified "
"together a non-CFR -vsync/-fps_mode. This is contradictory.\n");
return AVERROR(EINVAL);
}
- if (ost->vsync_method == VSYNC_AUTO) {
+ if (*vsync_method == VSYNC_AUTO) {
if (ost->frame_rate.num || ost->max_frame_rate.num) {
- ost->vsync_method = VSYNC_CFR;
+ *vsync_method = VSYNC_CFR;
} else if (!strcmp(oc->oformat->name, "avi")) {
- ost->vsync_method = VSYNC_VFR;
+ *vsync_method = VSYNC_VFR;
} else {
- ost->vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ?
- ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ?
- VSYNC_PASSTHROUGH : VSYNC_VFR) :
- VSYNC_CFR;
+ *vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ?
+ ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ?
+ VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR;
}
- if (ost->ist && ost->vsync_method == VSYNC_CFR) {
+ if (ost->ist && *vsync_method == VSYNC_CFR) {
const InputFile *ifile = ost->ist->file;
if (ifile->nb_streams == 1 && ifile->input_ts_offset == 0)
- ost->vsync_method = VSYNC_VSCFR;
+ *vsync_method = VSYNC_VSCFR;
}
- if (ost->vsync_method == VSYNC_CFR && copy_ts) {
- ost->vsync_method = VSYNC_VSCFR;
+ if (*vsync_method == VSYNC_CFR && copy_ts) {
+ *vsync_method = VSYNC_VSCFR;
}
}
- ost->is_cfr = (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR);
+ ost->is_cfr = (*vsync_method == VSYNC_CFR || *vsync_method == VSYNC_VSCFR);
+#if FFMPEG_OPT_VSYNC_DROP
+ if (*vsync_method == VSYNC_DROP)
+ ms->ts_drop = 1;
+#endif
}
return 0;
@@ -1043,6 +1048,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
AVStream *st;
int ret = 0, keep_pix_fmt = 0;
AVRational enc_tb = { 0, 0 };
+ enum VideoSyncMethod vsync_method = VSYNC_AUTO;
const char *bsfs = NULL, *time_base = NULL;
char *filters = NULL, *next, *codec_tag = NULL;
double qscale = -1;
@@ -1361,7 +1367,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
ms->copy_initial_nonkeyframes, oc, st);
switch (type) {
- case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost, &keep_pix_fmt); break;
+ case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost, &keep_pix_fmt, &vsync_method); break;
case AVMEDIA_TYPE_AUDIO: ret = new_stream_audio (mux, o, ost); break;
case AVMEDIA_TYPE_SUBTITLE: ret = new_stream_subtitle (mux, o, ost); break;
}
@@ -1382,6 +1388,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
ost->enc_ctx->pix_fmt : ost->enc_ctx->sample_fmt,
.width = ost->enc_ctx->width,
.height = ost->enc_ctx->height,
+ .vsync_method = vsync_method,
.sample_rate = ost->enc_ctx->sample_rate,
.ch_layout = ost->enc_ctx->ch_layout,
.output_tb = enc_tb,
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 13/31] fftools/ffmpeg: drop OutputStream.is_cfr
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (10 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 12/31] fftools/ffmpeg_filter: pass vsync method through OutputFilterOptions Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 14/31] fftools/ffmpeg_filter: accept a caller-provided output name Anton Khirnov
` (17 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
It is used in a single place in the filtering code, so it is better to
inline it there.
---
fftools/ffmpeg.h | 1 -
fftools/ffmpeg_filter.c | 2 +-
fftools/ffmpeg_mux_init.c | 1 -
3 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index fa8f7d8324..16497105e1 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -551,7 +551,6 @@ typedef struct OutputStream {
/* video only */
AVRational frame_rate;
AVRational max_frame_rate;
- int is_cfr;
int force_fps;
#if FFMPEG_OPT_TOP
int top_field_first;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index d906b72576..022c42e9c7 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1956,7 +1956,7 @@ static int choose_out_timebase(OutputFilterPriv *ofp, AVFrame *frame)
fr = fr_sink;
}
- if (ofilter->ost->is_cfr) {
+ if (fps->vsync_method == VSYNC_CFR || fps->vsync_method == VSYNC_VSCFR) {
if (!fr.num && !fps->framerate_max.num) {
fr = (AVRational){25, 1};
av_log(ofilter->ost, AV_LOG_WARNING,
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 6ffa4b7491..1791905d7e 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -816,7 +816,6 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
*vsync_method = VSYNC_VSCFR;
}
}
- ost->is_cfr = (*vsync_method == VSYNC_CFR || *vsync_method == VSYNC_VSCFR);
#if FFMPEG_OPT_VSYNC_DROP
if (*vsync_method == VSYNC_DROP)
ms->ts_drop = 1;
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 14/31] fftools/ffmpeg_filter: accept a caller-provided output name
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (11 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 13/31] fftools/ffmpeg: drop OutputStream.is_cfr Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 15/31] fftools/ffmpeg_filter: drop a redundant check Anton Khirnov
` (16 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Do not construct it from OutputStream manually.
Will allow decoupling filtering from encoding in future commits.
---
fftools/ffmpeg.h | 3 +++
fftools/ffmpeg_filter.c | 36 +++++++++++++++++++-----------------
fftools/ffmpeg_mux_init.c | 4 ++++
3 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 16497105e1..3c196c25e5 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -268,6 +268,9 @@ enum OFilterFlags {
};
typedef struct OutputFilterOptions {
+ // Caller-provided name for this output
+ char *name;
+
// Codec used for encoding, may be NULL
const AVCodec *enc;
// Overrides encoder pixel formats when set.
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 022c42e9c7..ceab58da19 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -188,6 +188,8 @@ typedef struct OutputFilterPriv {
int index;
+ char *name;
+
AVFilterContext *filter;
/* desired output stream properties */
@@ -784,6 +786,10 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofp->ts_offset = opts->ts_offset;
ofp->enc_timebase = opts->output_tb;
+ ofp->name = av_strdup(opts->name);
+ if (!ofp->name)
+ return AVERROR(EINVAL);
+
switch (ofilter->type) {
case AVMEDIA_TYPE_VIDEO:
ofp->width = opts->width;
@@ -911,6 +917,7 @@ void fg_free(FilterGraph **pfg)
av_freep(&ofilter->linklabel);
av_freep(&ofilter->name);
+ av_freep(&ofp->name);
av_channel_layout_uninit(&ofp->ch_layout);
av_freep(&fg->outputs[j]);
}
@@ -1076,9 +1083,8 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
fgp->is_simple = 1;
- snprintf(fgp->log_name, sizeof(fgp->log_name), "%cf#%d:%d",
- av_get_media_type_string(ost->type)[0],
- ost->file->index, ost->index);
+ snprintf(fgp->log_name, sizeof(fgp->log_name), "%cf%s",
+ av_get_media_type_string(ost->type)[0], opts->name);
if (fg->nb_inputs != 1 || fg->nb_outputs != 1) {
av_log(fg, AV_LOG_ERROR, "Simple filtergraph '%s' was expected "
@@ -1305,7 +1311,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
const char *pix_fmts;
char name[255];
- snprintf(name, sizeof(name), "out_%d_%d", ost->file->index, ost->index);
+ snprintf(name, sizeof(name), "out_%s", ofp->name);
ret = avfilter_graph_create_filter(&ofp->filter,
avfilter_get_by_name("buffersink"),
name, NULL, NULL, graph);
@@ -1325,8 +1331,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value);
}
- snprintf(name, sizeof(name), "scaler_out_%d_%d",
- ost->file->index, ost->index);
+ snprintf(name, sizeof(name), "scaler_out_%s", ofp->name);
if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
name, args, NULL, graph)) < 0)
return ret;
@@ -1358,8 +1363,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
pad_idx = 0;
}
- snprintf(name, sizeof(name), "trim_out_%d_%d",
- ost->file->index, ost->index);
+ snprintf(name, sizeof(name), "trim_out_%s", ofp->name);
ret = insert_trim(of->start_time, of->recording_time,
&last_filter, &pad_idx, name);
if (ret < 0)
@@ -1384,7 +1388,7 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
char name[255];
int ret;
- snprintf(name, sizeof(name), "out_%d_%d", ost->file->index, ost->index);
+ snprintf(name, sizeof(name), "out_%s", ofp->name);
ret = avfilter_graph_create_filter(&ofp->filter,
avfilter_get_by_name("abuffersink"),
name, NULL, NULL, graph);
@@ -1424,8 +1428,7 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
if (args.len) {
AVFilterContext *format;
- snprintf(name, sizeof(name), "format_out_%d_%d",
- ost->file->index, ost->index);
+ snprintf(name, sizeof(name), "format_out_%s", ofp->name);
ret = avfilter_graph_create_filter(&format,
avfilter_get_by_name("aformat"),
name, args.str, NULL, graph);
@@ -1452,8 +1455,7 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
}
}
- snprintf(name, sizeof(name), "trim for output stream %d:%d",
- ost->file->index, ost->index);
+ snprintf(name, sizeof(name), "trim for output %s", ofp->name);
ret = insert_trim(of->start_time, of->recording_time,
&last_filter, &pad_idx, name);
if (ret < 0)
@@ -2699,10 +2701,10 @@ static void fg_thread_set_name(const FilterGraph *fg)
{
char name[16];
if (filtergraph_is_simple(fg)) {
- OutputStream *ost = fg->outputs[0]->ost;
- snprintf(name, sizeof(name), "%cf#%d:%d",
- av_get_media_type_string(ost->type)[0],
- ost->file->index, ost->index);
+ OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[0]);
+ snprintf(name, sizeof(name), "%cf%s",
+ av_get_media_type_string(ofp->ofilter.type)[0],
+ ofp->name);
} else {
snprintf(name, sizeof(name), "fc%d", fg->index);
}
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 1791905d7e..219be5f965 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1381,8 +1381,10 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
if (ost->enc &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
+ char name[16];
OutputFilterOptions opts = {
.enc = enc,
+ .name = name,
.format = (type == AVMEDIA_TYPE_VIDEO) ?
ost->enc_ctx->pix_fmt : ost->enc_ctx->sample_fmt,
.width = ost->enc_ctx->width,
@@ -1396,6 +1398,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
.flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt,
};
+ snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index);
+
// MJPEG encoder exports a full list of supported pixel formats,
// but the full-range ones are experimental-only.
// Restrict the auto-conversion list unless -strict experimental
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 15/31] fftools/ffmpeg_filter: drop a redundant check
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (12 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 14/31] fftools/ffmpeg_filter: accept a caller-provided output name Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 16/31] fftools/ffmpeg_filter: simplify retrieving filter type Anton Khirnov
` (15 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
fg_finalise_bindings() already checks that all filtergraph outputs are
connected.
---
fftools/ffmpeg_filter.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index ceab58da19..41d96267bc 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1472,11 +1472,6 @@ fail:
static int configure_output_filter(FilterGraph *fg, AVFilterGraph *graph,
OutputFilter *ofilter, AVFilterInOut *out)
{
- if (!ofilter->ost) {
- av_log(fg, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name);
- return AVERROR(EINVAL);
- }
-
switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) {
case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, graph, ofilter, out);
case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, graph, ofilter, out);
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 16/31] fftools/ffmpeg_filter: simplify retrieving filter type
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (13 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 15/31] fftools/ffmpeg_filter: drop a redundant check Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 17/31] fftools/ffmpeg_filter: add an AVClass to OutputFilter Anton Khirnov
` (14 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_filter.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 41d96267bc..ffbc13eb70 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1472,7 +1472,7 @@ fail:
static int configure_output_filter(FilterGraph *fg, AVFilterGraph *graph,
OutputFilter *ofilter, AVFilterInOut *out)
{
- switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) {
+ switch (ofilter->type) {
case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, graph, ofilter, out);
case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, graph, ofilter, out);
default: av_assert0(0); return 0;
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 17/31] fftools/ffmpeg_filter: add an AVClass to OutputFilter
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (14 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 16/31] fftools/ffmpeg_filter: simplify retrieving filter type Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 18/31] fftools/ffmpeg_filter: drop an unnecessary use of OutputStream Anton Khirnov
` (13 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
Use it for logging where appropriate, avoid logging to OutputStream as
we do not own it.
This is a step towards decoupling filtering from encoding.
---
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_filter.c | 68 +++++++++++++++++++++++++++++------------
2 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 3c196c25e5..786f925bc6 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -302,6 +302,8 @@ typedef struct InputFilter {
} InputFilter;
typedef struct OutputFilter {
+ const AVClass *class;
+
struct OutputStream *ost;
struct FilterGraph *graph;
uint8_t *name;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index ffbc13eb70..840502bd62 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -188,6 +188,9 @@ typedef struct OutputFilterPriv {
int index;
+ void *log_parent;
+ char log_name[32];
+
char *name;
AVFilterContext *filter;
@@ -629,7 +632,21 @@ static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in)
avfilter_pad_get_name(pads, inout->pad_idx));
}
-static OutputFilter *ofilter_alloc(FilterGraph *fg)
+static const char *ofilter_item_name(void *obj)
+{
+ OutputFilterPriv *ofp = obj;
+ return ofp->log_name;
+}
+
+static const AVClass ofilter_class = {
+ .class_name = "OutputFilter",
+ .version = LIBAVUTIL_VERSION_INT,
+ .item_name = ofilter_item_name,
+ .parent_log_context_offset = offsetof(OutputFilterPriv, log_parent),
+ .category = AV_CLASS_CATEGORY_FILTER,
+};
+
+static OutputFilter *ofilter_alloc(FilterGraph *fg, enum AVMediaType type)
{
OutputFilterPriv *ofp;
OutputFilter *ofilter;
@@ -639,10 +656,16 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg)
return NULL;
ofilter = &ofp->ofilter;
+ ofilter->class = &ofilter_class;
+ ofp->log_parent = fg;
ofilter->graph = fg;
+ ofilter->type = type;
ofp->format = -1;
ofp->index = fg->nb_outputs - 1;
+ snprintf(ofp->log_name, sizeof(ofp->log_name), "%co%d",
+ av_get_media_type_string(type)[0], ofp->index);
+
return ofilter;
}
@@ -790,6 +813,14 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
if (!ofp->name)
return AVERROR(EINVAL);
+ if (fgp->is_simple) {
+ // for simple filtergraph there is just one output,
+ // so use only graph-level information for logging
+ ofp->log_parent = NULL;
+ av_strlcpy(ofp->log_name, fgp->log_name, sizeof(ofp->log_name));
+ } else
+ av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofp->name);
+
switch (ofilter->type) {
case AVMEDIA_TYPE_VIDEO:
ofp->width = opts->width;
@@ -1025,7 +1056,9 @@ int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
}
for (AVFilterInOut *cur = outputs; cur; cur = cur->next) {
- OutputFilter *const ofilter = ofilter_alloc(fg);
+ const enum AVMediaType type = avfilter_pad_get_type(cur->filter_ctx->output_pads,
+ cur->pad_idx);
+ OutputFilter *const ofilter = ofilter_alloc(fg, type);
if (!ofilter) {
ret = AVERROR(ENOMEM);
@@ -1035,8 +1068,6 @@ int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
ofilter->linklabel = cur->name;
cur->name = NULL;
- ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads,
- cur->pad_idx);
ofilter->name = describe_filter_link(fg, cur, 0);
if (!ofilter->name) {
ret = AVERROR(ENOMEM);
@@ -1400,7 +1431,7 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
#define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \
AVFilterContext *filt_ctx; \
\
- av_log(fg, AV_LOG_INFO, opt_name " is forwarded to lavfi " \
+ av_log(ofilter, AV_LOG_INFO, opt_name " is forwarded to lavfi " \
"similarly to -af " filter_name "=%s.\n", arg); \
\
ret = avfilter_graph_create_filter(&filt_ctx, \
@@ -1929,7 +1960,7 @@ static int choose_out_timebase(OutputFilterPriv *ofp, AVFrame *frame)
// apply -enc_time_base
if (ofp->enc_timebase.num == ENC_TIME_BASE_DEMUX &&
(fd->dec.tb.num <= 0 || fd->dec.tb.den <= 0)) {
- av_log(ofilter->ost, AV_LOG_ERROR,
+ av_log(ofp, AV_LOG_ERROR,
"Demuxing timebase not available - cannot use it for encoding\n");
return AVERROR(EINVAL);
}
@@ -1956,7 +1987,7 @@ static int choose_out_timebase(OutputFilterPriv *ofp, AVFrame *frame)
if (fps->vsync_method == VSYNC_CFR || fps->vsync_method == VSYNC_VSCFR) {
if (!fr.num && !fps->framerate_max.num) {
fr = (AVRational){25, 1};
- av_log(ofilter->ost, AV_LOG_WARNING,
+ av_log(ofp, AV_LOG_WARNING,
"No information "
"about the input framerate is available. Falling "
"back to a default value of 25fps. Use the -r option "
@@ -2039,7 +2070,6 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
int64_t *nb_frames, int64_t *nb_frames_prev)
{
OutputFilter *ofilter = &ofp->ofilter;
- OutputStream *ost = ofilter->ost;
FPSConvContext *fps = &ofp->fps;
double delta0, delta, sync_ipts, duration;
@@ -2078,9 +2108,9 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
#endif
) {
if (delta0 < -0.6) {
- av_log(ost, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0);
+ av_log(ofp, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0);
} else
- av_log(ost, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0);
+ av_log(ofp, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0);
sync_ipts = ofp->next_pts;
duration += delta0;
delta0 = 0;
@@ -2089,7 +2119,7 @@ static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
switch (fps->vsync_method) {
case VSYNC_VSCFR:
if (fps->frame_number == 0 && delta0 >= 0.5) {
- av_log(ost, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0));
+ av_log(ofp, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0));
delta = duration;
delta0 = 0;
ofp->next_pts = llrint(sync_ipts);
@@ -2133,23 +2163,23 @@ finish:
if (*nb_frames_prev == 0 && fps->last_dropped) {
atomic_fetch_add(&ofilter->nb_frames_drop, 1);
- av_log(ost, AV_LOG_VERBOSE,
+ av_log(ofp, AV_LOG_VERBOSE,
"*** dropping frame %"PRId64" at ts %"PRId64"\n",
fps->frame_number, fps->last_frame->pts);
}
if (*nb_frames > (*nb_frames_prev && fps->last_dropped) + (*nb_frames > *nb_frames_prev)) {
uint64_t nb_frames_dup;
if (*nb_frames > dts_error_threshold * 30) {
- av_log(ost, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", *nb_frames - 1);
+ av_log(ofp, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", *nb_frames - 1);
atomic_fetch_add(&ofilter->nb_frames_drop, 1);
*nb_frames = 0;
return;
}
nb_frames_dup = atomic_fetch_add(&ofilter->nb_frames_dup,
*nb_frames - (*nb_frames_prev && fps->last_dropped) - (*nb_frames > *nb_frames_prev));
- av_log(ost, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", *nb_frames - 1);
+ av_log(ofp, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", *nb_frames - 1);
if (nb_frames_dup > fps->dup_warning) {
- av_log(ost, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", fps->dup_warning);
+ av_log(ofp, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", fps->dup_warning);
fps->dup_warning *= 10;
}
}
@@ -2191,7 +2221,7 @@ static int close_output(OutputFilterPriv *ofp, FilterGraphThread *fgt)
av_assert0(!frame->buf[0]);
- av_log(ofp->ofilter.ost, AV_LOG_WARNING,
+ av_log(ofp, AV_LOG_WARNING,
"No filtered frames for output stream, trying to "
"initialize anyway.\n");
@@ -2308,7 +2338,7 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
} else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 1;
} else if (ret < 0) {
- av_log(fgp, AV_LOG_WARNING,
+ av_log(ofp, AV_LOG_WARNING,
"Error in retrieving a frame from the filtergraph: %s\n",
av_err2str(ret));
return ret;
@@ -2322,7 +2352,7 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
frame->time_base = av_buffersink_get_time_base(filter);
if (debug_ts)
- av_log(fgp, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n",
+ av_log(ofp, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n",
av_ts2str(frame->pts), av_ts2timestr(frame->pts, &frame->time_base),
frame->time_base.num, frame->time_base.den);
@@ -2330,7 +2360,7 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
if (!ofp->tb_out_locked) {
ret = choose_out_timebase(ofp, frame);
if (ret < 0) {
- av_log(ost, AV_LOG_ERROR, "Could not choose an output time base\n");
+ av_log(ofp, AV_LOG_ERROR, "Could not choose an output time base\n");
av_frame_unref(frame);
return ret;
}
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 18/31] fftools/ffmpeg_filter: drop an unnecessary use of OutputStream
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (15 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 17/31] fftools/ffmpeg_filter: add an AVClass to OutputFilter Anton Khirnov
@ 2024-04-05 16:11 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 19/31] fftools/ffmpeg_filter: pass sws/swr opts through OutputFilterOptions Anton Khirnov
` (12 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:11 UTC (permalink / raw)
To: ffmpeg-devel
OutputFilter.type contains the same information.
---
fftools/ffmpeg_filter.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 840502bd62..d2fd26af7e 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -2325,7 +2325,6 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
AVFrame *frame)
{
FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph);
- OutputStream *ost = ofp->ofilter.ost;
AVFilterContext *filter = ofp->filter;
FrameData *fd;
int ret;
@@ -2379,7 +2378,7 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
if (!fgp->is_meta)
fd->bits_per_raw_sample = 0;
- if (ost->type == AVMEDIA_TYPE_VIDEO) {
+ if (ofp->ofilter.type == AVMEDIA_TYPE_VIDEO) {
if (!frame->duration) {
AVRational fr = av_buffersink_get_frame_rate(filter);
if (fr.num > 0 && fr.den > 0)
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 19/31] fftools/ffmpeg_filter: pass sws/swr opts through OutputFilterOptions
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (16 preceding siblings ...)
2024-04-05 16:11 ` [FFmpeg-devel] [PATCH 18/31] fftools/ffmpeg_filter: drop an unnecessary use of OutputStream Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 20/31] fftools/ffmpeg_filter: pass autoscale " Anton Khirnov
` (11 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
Do not read them from OutputStream directly.
Will allow decoupling filtering from encoding in future commits.
---
fftools/ffmpeg.h | 7 +++++--
fftools/ffmpeg_filter.c | 27 ++++++++++++++++++++++-----
fftools/ffmpeg_mux.c | 3 ---
fftools/ffmpeg_mux_init.c | 11 ++++-------
4 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 786f925bc6..c61a670103 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -265,6 +265,8 @@ typedef struct InputFilterOptions {
enum OFilterFlags {
OFILTER_FLAG_DISABLE_CONVERT = (1 << 0),
+ // produce 24-bit audio
+ OFILTER_FLAG_AUDIO_24BIT = (1 << 1),
};
typedef struct OutputFilterOptions {
@@ -283,6 +285,9 @@ typedef struct OutputFilterOptions {
*/
AVRational output_tb;
+ AVDictionary *sws_opts;
+ AVDictionary *swr_opts;
+
// A combination of OFilterFlags.
unsigned flags;
@@ -574,8 +579,6 @@ typedef struct OutputStream {
OutputFilter *filter;
AVDictionary *encoder_opts;
- AVDictionary *sws_dict;
- AVDictionary *swr_opts;
char *apad;
char *attachment_filename;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index d2fd26af7e..8aa4053716 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -210,6 +210,9 @@ typedef struct OutputFilterPriv {
AVRational sample_aspect_ratio;
+ AVDictionary *sws_opts;
+ AVDictionary *swr_opts;
+
// those are only set if no format is specified and the encoder gives us multiple options
// They point directly to the relevant lists of the encoder.
const int *formats;
@@ -813,6 +816,17 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
if (!ofp->name)
return AVERROR(EINVAL);
+ ret = av_dict_copy(&ofp->sws_opts, opts->sws_opts, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = av_dict_copy(&ofp->swr_opts, opts->swr_opts, 0);
+ if (ret < 0)
+ return ret;
+
+ if (opts->flags & OFILTER_FLAG_AUDIO_24BIT)
+ av_dict_set(&ofp->swr_opts, "output_sample_bits", "24", 0);
+
if (fgp->is_simple) {
// for simple filtergraph there is just one output,
// so use only graph-level information for logging
@@ -945,6 +959,8 @@ void fg_free(FilterGraph **pfg)
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
av_frame_free(&ofp->fps.last_frame);
+ av_dict_free(&ofp->sws_opts);
+ av_dict_free(&ofp->swr_opts);
av_freep(&ofilter->linklabel);
av_freep(&ofilter->name);
@@ -1358,7 +1374,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
snprintf(args, sizeof(args), "%d:%d",
ofp->width, ofp->height);
- while ((e = av_dict_iterate(ost->sws_dict, e))) {
+ while ((e = av_dict_iterate(ofp->sws_opts, e))) {
av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value);
}
@@ -1725,6 +1741,7 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
return AVERROR(ENOMEM);
if (simple) {
+ OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[0]);
OutputStream *ost = fg->outputs[0]->ost;
if (filter_nbthreads) {
@@ -1738,17 +1755,17 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
av_opt_set(fgt->graph, "threads", e->value, 0);
}
- if (av_dict_count(ost->sws_dict)) {
- ret = av_dict_get_string(ost->sws_dict,
+ if (av_dict_count(ofp->sws_opts)) {
+ ret = av_dict_get_string(ofp->sws_opts,
&fgt->graph->scale_sws_opts,
'=', ':');
if (ret < 0)
goto fail;
}
- if (av_dict_count(ost->swr_opts)) {
+ if (av_dict_count(ofp->swr_opts)) {
char *args;
- ret = av_dict_get_string(ost->swr_opts, &args, '=', ':');
+ ret = av_dict_get_string(ofp->swr_opts, &args, '=', ':');
if (ret < 0)
goto fail;
av_opt_set(fgt->graph, "aresample_swr_opts", args, 0);
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 253c2e58d4..557f08b3a5 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -819,9 +819,6 @@ static void ost_free(OutputStream **post)
av_freep(&ost->attachment_filename);
- av_dict_free(&ost->sws_dict);
- av_dict_free(&ost->swr_opts);
-
if (ost->enc_ctx)
av_freep(&ost->enc_ctx->stats_in);
avcodec_free_context(&ost->enc_ctx);
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 219be5f965..8f4b73f8a7 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1356,12 +1356,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx)
ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
- av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0);
-
- av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0);
- if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24)
- av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0);
-
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i,
ms->copy_initial_nonkeyframes, oc, st);
@@ -1392,10 +1386,13 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
.vsync_method = vsync_method,
.sample_rate = ost->enc_ctx->sample_rate,
.ch_layout = ost->enc_ctx->ch_layout,
+ .sws_opts = o->g->sws_dict,
+ .swr_opts = o->g->swr_opts,
.output_tb = enc_tb,
.ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
0 : mux->of.start_time,
- .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt,
+ .flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt |
+ OFILTER_FLAG_AUDIO_24BIT * !!(av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24),
};
snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index);
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 20/31] fftools/ffmpeg_filter: pass autoscale through OutputFilterOptions
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (17 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 19/31] fftools/ffmpeg_filter: pass sws/swr opts through OutputFilterOptions Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 21/31] fftools/ffmpeg_filter: pass trim parameters " Anton Khirnov
` (10 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
Do not read it from OutputStream directly.
Will allow decoupling filtering from encoding in future commits.
---
fftools/ffmpeg.h | 2 +-
fftools/ffmpeg_filter.c | 2 +-
fftools/ffmpeg_mux_init.c | 7 ++++---
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index c61a670103..4059b1dcc3 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -267,6 +267,7 @@ enum OFilterFlags {
OFILTER_FLAG_DISABLE_CONVERT = (1 << 0),
// produce 24-bit audio
OFILTER_FLAG_AUDIO_24BIT = (1 << 1),
+ OFILTER_FLAG_AUTOSCALE = (1 << 2),
};
typedef struct OutputFilterOptions {
@@ -565,7 +566,6 @@ typedef struct OutputStream {
#if FFMPEG_OPT_TOP
int top_field_first;
#endif
- int autoscale;
int bitexact;
int bits_per_raw_sample;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 8aa4053716..dc9556bbc1 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1366,7 +1366,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
if (ret < 0)
return ret;
- if ((ofp->width || ofp->height) && ofilter->ost->autoscale) {
+ if ((ofp->width || ofp->height) && (ofp->flags & OFILTER_FLAG_AUTOSCALE)) {
char args[255];
AVFilterContext *filter;
const AVDictionaryEntry *e = NULL;
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 8f4b73f8a7..51c31eeb72 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1045,7 +1045,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
OutputStream *ost;
const AVCodec *enc;
AVStream *st;
- int ret = 0, keep_pix_fmt = 0;
+ int ret = 0, keep_pix_fmt = 0, autoscale = 1;
AVRational enc_tb = { 0, 0 };
enum VideoSyncMethod vsync_method = VSYNC_AUTO;
const char *bsfs = NULL, *time_base = NULL;
@@ -1170,8 +1170,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
return ret;
MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
- ost->autoscale = 1;
- MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st);
+
+ MATCH_PER_STREAM_OPT(autoscale, i, autoscale, oc, st);
if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) {
AVBPrint bprint;
av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
@@ -1392,6 +1392,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
.ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
0 : mux->of.start_time,
.flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt |
+ OFILTER_FLAG_AUTOSCALE * !!autoscale |
OFILTER_FLAG_AUDIO_24BIT * !!(av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24),
};
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 21/31] fftools/ffmpeg_filter: pass trim parameters through OutputFilterOptions
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (18 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 20/31] fftools/ffmpeg_filter: pass autoscale " Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 22/31] fftools/ffmpeg_filter: move most of -apad logic to the muxer Anton Khirnov
` (9 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
Do not read them from OutputStream directly.
Will allow decoupling filtering from encoding in future commits.
---
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_filter.c | 11 +++++++----
fftools/ffmpeg_mux_init.c | 2 ++
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 4059b1dcc3..8e773165da 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -279,6 +279,8 @@ typedef struct OutputFilterOptions {
// Overrides encoder pixel formats when set.
const enum AVPixelFormat *pix_fmts;
+ int64_t trim_start_us;
+ int64_t trim_duration_us;
int64_t ts_offset;
/* Desired output timebase.
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index dc9556bbc1..225fa4bda2 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -220,6 +220,8 @@ typedef struct OutputFilterPriv {
const int *sample_rates;
AVRational enc_timebase;
+ int64_t trim_start_us;
+ int64_t trim_duration_us;
// offset for output timestamps, in AV_TIME_BASE_Q
int64_t ts_offset;
int64_t next_pts;
@@ -812,6 +814,9 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
ofp->ts_offset = opts->ts_offset;
ofp->enc_timebase = opts->output_tb;
+ ofp->trim_start_us = opts->trim_start_us;
+ ofp->trim_duration_us = opts->trim_duration_us;
+
ofp->name = av_strdup(opts->name);
if (!ofp->name)
return AVERROR(EINVAL);
@@ -1349,8 +1354,6 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
OutputFilter *ofilter, AVFilterInOut *out)
{
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
- OutputStream *ost = ofilter->ost;
- OutputFile *of = ost->file;
AVFilterContext *last_filter = out->filter_ctx;
AVBPrint bprint;
int pad_idx = out->pad_idx;
@@ -1411,7 +1414,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
}
snprintf(name, sizeof(name), "trim_out_%s", ofp->name);
- ret = insert_trim(of->start_time, of->recording_time,
+ ret = insert_trim(ofp->trim_start_us, ofp->trim_duration_us,
&last_filter, &pad_idx, name);
if (ret < 0)
return ret;
@@ -1503,7 +1506,7 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
}
snprintf(name, sizeof(name), "trim for output %s", ofp->name);
- ret = insert_trim(of->start_time, of->recording_time,
+ ret = insert_trim(ofp->trim_start_us, ofp->trim_duration_us,
&last_filter, &pad_idx, name);
if (ret < 0)
goto fail;
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 51c31eeb72..6e19b98abd 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1389,6 +1389,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
.sws_opts = o->g->sws_dict,
.swr_opts = o->g->swr_opts,
.output_tb = enc_tb,
+ .trim_start_us = mux->of.start_time,
+ .trim_duration_us = mux->of.recording_time,
.ts_offset = mux->of.start_time == AV_NOPTS_VALUE ?
0 : mux->of.start_time,
.flags = OFILTER_FLAG_DISABLE_CONVERT * !!keep_pix_fmt |
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 22/31] fftools/ffmpeg_filter: move most of -apad logic to the muxer
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (19 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 21/31] fftools/ffmpeg_filter: pass trim parameters " Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 23/31] fftools/ffmpeg_mux: drop OutputFile.shortest Anton Khirnov
` (8 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
The decision whether -apad actually does anything is made based on muxer
properties, and so more properly belongs there. Filtering code only
receives the result.
---
fftools/ffmpeg.h | 3 ++-
fftools/ffmpeg_filter.c | 16 +++-------------
fftools/ffmpeg_mux.c | 1 -
fftools/ffmpeg_mux.h | 2 ++
fftools/ffmpeg_mux_init.c | 36 +++++++++++++++++++++++++++++-------
5 files changed, 36 insertions(+), 22 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 8e773165da..26b42a3fcd 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -320,6 +320,8 @@ typedef struct OutputFilter {
* this stores the output linklabel, if any */
uint8_t *linklabel;
+ char *apad;
+
enum AVMediaType type;
atomic_uint_least64_t nb_frames_dup;
@@ -581,7 +583,6 @@ typedef struct OutputStream {
OutputFilter *filter;
AVDictionary *encoder_opts;
- char *apad;
char *attachment_filename;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 225fa4bda2..ec17e99494 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -969,6 +969,7 @@ void fg_free(FilterGraph **pfg)
av_freep(&ofilter->linklabel);
av_freep(&ofilter->name);
+ av_freep(&ofilter->apad);
av_freep(&ofp->name);
av_channel_layout_uninit(&ofp->ch_layout);
av_freep(&fg->outputs[j]);
@@ -1430,8 +1431,6 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
OutputFilter *ofilter, AVFilterInOut *out)
{
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
- OutputStream *ost = ofilter->ost;
- OutputFile *of = ost->file;
AVFilterContext *last_filter = out->filter_ctx;
int pad_idx = out->pad_idx;
AVBPrint args;
@@ -1493,17 +1492,8 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
pad_idx = 0;
}
- if (ost->apad && of->shortest) {
- int i;
-
- for (i = 0; i < of->nb_streams; i++)
- if (of->streams[i]->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
- break;
-
- if (i < of->nb_streams) {
- AUTO_INSERT_FILTER("-apad", "apad", ost->apad);
- }
- }
+ if (ofilter->apad)
+ AUTO_INSERT_FILTER("-apad", "apad", ofilter->apad);
snprintf(name, sizeof(name), "trim for output %s", ofp->name);
ret = insert_trim(ofp->trim_start_us, ofp->trim_duration_us,
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 557f08b3a5..6a64cba72d 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -815,7 +815,6 @@ static void ost_free(OutputStream **post)
av_expr_free(ost->kf.pexpr);
av_freep(&ost->logfile_prefix);
- av_freep(&ost->apad);
av_freep(&ost->attachment_filename);
diff --git a/fftools/ffmpeg_mux.h b/fftools/ffmpeg_mux.h
index f8b6f7a790..1e9ea35412 100644
--- a/fftools/ffmpeg_mux.h
+++ b/fftools/ffmpeg_mux.h
@@ -78,6 +78,8 @@ typedef struct MuxStream {
#if FFMPEG_OPT_VSYNC_DROP
int ts_drop;
#endif
+
+ char *apad;
} MuxStream;
typedef struct Muxer {
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 6e19b98abd..a483fffa6e 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -828,6 +828,7 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
static int new_stream_audio(Muxer *mux, const OptionsContext *o,
OutputStream *ost)
{
+ MuxStream *ms = ms_from_ost(ost);
AVFormatContext *oc = mux->fc;
AVStream *st = ost->st;
@@ -836,7 +837,6 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
int channels = 0;
char *layout = NULL;
char *sample_fmt = NULL;
- const char *apad = NULL;
MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st);
if (channels) {
@@ -859,12 +859,7 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st);
- MATCH_PER_STREAM_OPT(apad, str, apad, oc, st);
- if (apad) {
- ost->apad = av_strdup(apad);
- if (!ost->apad)
- return AVERROR(ENOMEM);
- }
+ MATCH_PER_STREAM_OPT(apad, str, ms->apad, oc, st);
}
return 0;
@@ -1890,6 +1885,33 @@ static int create_streams(Muxer *mux, const OptionsContext *o)
}
}
+ // handle -apad
+ if (mux->of.shortest) {
+ int have_video = 0;
+
+ for (unsigned i = 0; i < mux->of.nb_streams; i++)
+ if (mux->of.streams[i]->type == AVMEDIA_TYPE_VIDEO) {
+ have_video = 1;
+ break;
+ }
+
+ for (unsigned i = 0; have_video && i < mux->of.nb_streams; i++) {
+ MuxStream *ms = ms_from_ost(mux->of.streams[i]);
+ OutputFilter *ofilter = ms->ost.filter;
+
+ if (ms->ost.type != AVMEDIA_TYPE_AUDIO || !ms->apad || !ofilter)
+ continue;
+
+ ofilter->apad = av_strdup(ms->apad);
+ if (!ofilter->apad)
+ return AVERROR(ENOMEM);
+ }
+ }
+ for (unsigned i = 0; i < mux->of.nb_streams; i++) {
+ MuxStream *ms = ms_from_ost(mux->of.streams[i]);
+ ms->apad = NULL;
+ }
+
if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
av_dump_format(oc, nb_output_files - 1, oc->url, 1);
av_log(mux, AV_LOG_ERROR, "Output file does not contain any stream\n");
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 23/31] fftools/ffmpeg_mux: drop OutputFile.shortest
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (20 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 22/31] fftools/ffmpeg_filter: move most of -apad logic to the muxer Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 24/31] fftools/ffmpeg_mux: drop OutputFile.format Anton Khirnov
` (7 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
It is no longer needed outside of of_open() and its children.
---
fftools/ffmpeg.h | 1 -
fftools/ffmpeg_mux_init.c | 17 +++++++++--------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 26b42a3fcd..1d32009f90 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -620,7 +620,6 @@ typedef struct OutputFile {
int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units
int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units
- int shortest;
int bitexact;
} OutputFile;
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index a483fffa6e..9aad19a85d 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1886,7 +1886,7 @@ static int create_streams(Muxer *mux, const OptionsContext *o)
}
// handle -apad
- if (mux->of.shortest) {
+ if (o->shortest) {
int have_video = 0;
for (unsigned i = 0; i < mux->of.nb_streams; i++)
@@ -1921,7 +1921,8 @@ static int create_streams(Muxer *mux, const OptionsContext *o)
return 0;
}
-static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_us)
+static int setup_sync_queues(Muxer *mux, AVFormatContext *oc,
+ int64_t buf_size_us, int shortest)
{
OutputFile *of = &mux->of;
int nb_av_enc = 0, nb_audio_fs = 0, nb_interleaved = 0;
@@ -1947,7 +1948,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u
limit_frames_av_enc |= (ms->max_frames < INT64_MAX) && IS_AV_ENC(ost, type);
}
- if (!((nb_interleaved > 1 && of->shortest) ||
+ if (!((nb_interleaved > 1 && shortest) ||
(nb_interleaved > 0 && limit_frames) ||
nb_audio_fs))
return 0;
@@ -1963,7 +1964,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u
* different encoders run in different threads and need external
* synchronization, while muxer sync queues can be handled inside the muxer
*/
- if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) {
+ if ((shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) {
int sq_idx, ret;
sq_idx = sch_add_sq_enc(mux->sch, buf_size_us, mux);
@@ -1979,7 +1980,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u
continue;
ret = sch_sq_add_enc(mux->sch, sq_idx, ms->sch_idx_enc,
- of->shortest || ms->max_frames < INT64_MAX,
+ shortest || ms->max_frames < INT64_MAX,
ms->max_frames);
if (ret < 0)
return ret;
@@ -2006,7 +2007,7 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u
continue;
ms->sq_idx_mux = sq_add_stream(mux->sq_mux,
- of->shortest || ms->max_frames < INT64_MAX);
+ shortest || ms->max_frames < INT64_MAX);
if (ms->sq_idx_mux < 0)
return ms->sq_idx_mux;
@@ -3043,7 +3044,6 @@ int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
of->recording_time = recording_time;
of->start_time = o->start_time;
- of->shortest = o->shortest;
mux->limit_filesize = o->limit_filesize;
av_dict_copy(&mux->opts, o->g->format_opts, 0);
@@ -3159,7 +3159,8 @@ int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
return err;
}
- err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE);
+ err = setup_sync_queues(mux, oc, o->shortest_buf_duration * AV_TIME_BASE,
+ o->shortest);
if (err < 0) {
av_log(mux, AV_LOG_FATAL, "Error setting up output sync queues\n");
return err;
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 24/31] fftools/ffmpeg_mux: drop OutputFile.format
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (21 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 23/31] fftools/ffmpeg_mux: drop OutputFile.shortest Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 25/31] fftools/ffmpeg_filter: accept encoder thread count through OutputFilterOptions Anton Khirnov
` (6 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
It is no longer used outside of the muxing code (where we can access the
muxer directly).
---
fftools/ffmpeg.h | 1 -
fftools/ffmpeg_mux.c | 15 +++++++++------
fftools/ffmpeg_mux_init.c | 1 -
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 1d32009f90..7135d9563c 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -611,7 +611,6 @@ typedef struct OutputFile {
int index;
- const AVOutputFormat *format;
const char *url;
OutputStream **streams;
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 6a64cba72d..2b7a733501 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -370,10 +370,11 @@ fail:
return ret;
}
-static void thread_set_name(OutputFile *of)
+static void thread_set_name(Muxer *mux)
{
char name[16];
- snprintf(name, sizeof(name), "mux%d:%s", of->index, of->format->name);
+ snprintf(name, sizeof(name), "mux%d:%s",
+ mux->of.index, mux->fc->oformat->name);
ff_thread_setname(name);
}
@@ -417,7 +418,7 @@ int muxer_thread(void *arg)
if (ret < 0)
goto finish;
- thread_set_name(of);
+ thread_set_name(mux);
while (1) {
OutputStream *ost;
@@ -515,8 +516,10 @@ int print_sdp(const char *filename)
if (!avc)
return AVERROR(ENOMEM);
for (int i = 0; i < nb_output_files; i++) {
- if (!strcmp(output_files[i]->format->name, "rtp")) {
- avc[j] = mux_from_of(output_files[i])->fc;
+ Muxer *mux = mux_from_of(output_files[i]);
+
+ if (!strcmp(mux->fc->oformat->name, "rtp")) {
+ avc[j] = mux->fc;
j++;
}
}
@@ -756,7 +759,7 @@ int of_write_trailer(OutputFile *of)
mux->last_filesize = filesize(fc->pb);
- if (!(of->format->flags & AVFMT_NOFILE)) {
+ if (!(fc->oformat->flags & AVFMT_NOFILE)) {
ret = avio_closep(&fc->pb);
if (ret < 0) {
av_log(mux, AV_LOG_ERROR, "Error closing file: %s\n", av_err2str(ret));
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 9aad19a85d..ffcc20a504 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -3063,7 +3063,6 @@ int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
av_strlcat(mux->log_name, oc->oformat->name, sizeof(mux->log_name));
- of->format = oc->oformat;
if (recording_time != INT64_MAX)
oc->duration = recording_time;
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 25/31] fftools/ffmpeg_filter: accept encoder thread count through OutputFilterOptions
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (22 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 24/31] fftools/ffmpeg_mux: drop OutputFile.format Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 26/31] fftools/ffmpeg_filter: drop OutputFilter.ost Anton Khirnov
` (5 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
Stop digging through encoder options manually.
Will allow decoupling filtering from encoding in future commits.
---
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_filter.c | 20 ++++++++++++++------
fftools/ffmpeg_mux_init.c | 5 +++++
3 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 7135d9563c..f77ec956b3 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -291,6 +291,8 @@ typedef struct OutputFilterOptions {
AVDictionary *sws_opts;
AVDictionary *swr_opts;
+ const char *nb_threads;
+
// A combination of OFilterFlags.
unsigned flags;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index ec17e99494..9fc6e32960 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -59,6 +59,8 @@ typedef struct FilterGraphPriv {
const char *graph_desc;
+ char *nb_threads;
+
// frame for temporarily holding output from the filtergraph
AVFrame *frame;
// frame for sending output to the encoder
@@ -976,6 +978,7 @@ void fg_free(FilterGraph **pfg)
}
av_freep(&fg->outputs);
av_freep(&fgp->graph_desc);
+ av_freep(&fgp->nb_threads);
av_frame_free(&fgp->frame);
av_frame_free(&fgp->frame_enc);
@@ -1165,6 +1168,13 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
if (ret < 0)
return ret;
+ if (opts->nb_threads) {
+ av_freep(&fgp->nb_threads);
+ fgp->nb_threads = av_strdup(opts->nb_threads);
+ if (!fgp->nb_threads)
+ return AVERROR(ENOMEM);
+ }
+
return 0;
}
@@ -1735,17 +1745,15 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
if (simple) {
OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[0]);
- OutputStream *ost = fg->outputs[0]->ost;
if (filter_nbthreads) {
ret = av_opt_set(fgt->graph, "threads", filter_nbthreads, 0);
if (ret < 0)
goto fail;
- } else {
- const AVDictionaryEntry *e = NULL;
- e = av_dict_get(ost->encoder_opts, "threads", NULL, 0);
- if (e)
- av_opt_set(fgt->graph, "threads", e->value, 0);
+ } else if (fgp->nb_threads) {
+ ret = av_opt_set(fgt->graph, "threads", fgp->nb_threads, 0);
+ if (ret < 0)
+ return ret;
}
if (av_dict_count(ofp->sws_opts)) {
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index ffcc20a504..10421ae1b0 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1370,6 +1370,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
if (ost->enc &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
+ const AVDictionaryEntry *e;
char name[16];
OutputFilterOptions opts = {
.enc = enc,
@@ -1395,6 +1396,10 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index);
+ e = av_dict_get(ost->encoder_opts, "threads", NULL, 0);
+ if (e)
+ opts.nb_threads = e->value;
+
// MJPEG encoder exports a full list of supported pixel formats,
// but the full-range ones are experimental-only.
// Restrict the auto-conversion list unless -strict experimental
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 26/31] fftools/ffmpeg_filter: drop OutputFilter.ost
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (23 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 25/31] fftools/ffmpeg_filter: accept encoder thread count through OutputFilterOptions Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 27/31] fftools/ffmpeg_filter: only store complex filtergraphs in global array Anton Khirnov
` (4 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
All remaining code accessing it only needs to know whether this
filtergraph output has been bound or not.
---
fftools/ffmpeg.h | 2 +-
fftools/ffmpeg_filter.c | 6 +++---
fftools/ffmpeg_mux_init.c | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index f77ec956b3..6446a141b5 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -314,12 +314,12 @@ typedef struct InputFilter {
typedef struct OutputFilter {
const AVClass *class;
- struct OutputStream *ost;
struct FilterGraph *graph;
uint8_t *name;
/* for filters that are not yet bound to an output stream,
* this stores the output linklabel, if any */
+ int bound;
uint8_t *linklabel;
char *apad;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 9fc6e32960..3988cf5fc2 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -806,10 +806,10 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
FilterGraphPriv *fgp = fgp_from_fg(fg);
int ret;
- av_assert0(!ofilter->ost);
+ av_assert0(!ofilter->bound);
av_assert0(ofilter->type == ost->type);
- ofilter->ost = ost;
+ ofilter->bound = 1;
av_freep(&ofilter->linklabel);
ofp->flags = opts->flags;
@@ -1279,7 +1279,7 @@ int fg_finalise_bindings(FilterGraph *fg)
for (int i = 0; i < fg->nb_outputs; i++) {
OutputFilter *output = fg->outputs[i];
- if (!output->ost) {
+ if (!output->bound) {
av_log(filtergraphs[i], AV_LOG_FATAL,
"Filter %s has an unconnected output\n", output->name);
return AVERROR(EINVAL);
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 10421ae1b0..6d8bd5bcdf 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1827,7 +1827,7 @@ static int create_streams(Muxer *mux, const OptionsContext *o)
for (int j = 0; j < fg->nb_outputs; j++) {
OutputFilter *ofilter = fg->outputs[j];
- if (ofilter->linklabel || ofilter->ost)
+ if (ofilter->linklabel || ofilter->bound)
continue;
auto_disable |= 1 << ofilter->type;
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 27/31] fftools/ffmpeg_filter: only store complex filtergraphs in global array
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (24 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 26/31] fftools/ffmpeg_filter: drop OutputFilter.ost Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 28/31] fftools/ffmpeg_filter: change processing order in fg_finalise_bindings() Anton Khirnov
` (3 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
Store simple filtergraphs in the stream they feed. Keeping the two
separate will be useful in following commits.
---
fftools/ffmpeg.c | 5 +++++
fftools/ffmpeg.h | 3 +++
fftools/ffmpeg_filter.c | 16 +++++++++++++---
fftools/ffmpeg_mux.c | 1 +
4 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 0ee76d69b5..1f50ed6805 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -787,6 +787,11 @@ static int check_keyboard_interaction(int64_t cur_time)
(n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
target, time, command, arg);
+ for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
+ if (ost->fg_simple)
+ fg_send_command(ost->fg_simple, time, target, command, arg,
+ key == 'C');
+ }
for (i = 0; i < nb_filtergraphs; i++)
fg_send_command(filtergraphs[i], time, target, command, arg,
key == 'C');
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 6446a141b5..882d241bdb 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -582,6 +582,8 @@ typedef struct OutputStream {
char *logfile_prefix;
FILE *logfile;
+ // simple filtergraph feeding this stream, if any
+ FilterGraph *fg_simple;
OutputFilter *filter;
AVDictionary *encoder_opts;
@@ -653,6 +655,7 @@ extern int nb_input_files;
extern OutputFile **output_files;
extern int nb_output_files;
+// complex filtergraphs
extern FilterGraph **filtergraphs;
extern int nb_filtergraphs;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 3988cf5fc2..388c8919fd 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1009,16 +1009,25 @@ int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch)
AVFilterGraph *graph;
int ret = 0;
- fgp = allocate_array_elem(&filtergraphs, sizeof(*fgp), &nb_filtergraphs);
+ fgp = av_mallocz(sizeof(*fgp));
if (!fgp)
return AVERROR(ENOMEM);
fg = &fgp->fg;
- if (pfg)
+ if (pfg) {
*pfg = fg;
+ fg->index = -1;
+ } else {
+ ret = av_dynarray_add_nofree(&filtergraphs, &nb_filtergraphs, fgp);
+ if (ret < 0) {
+ av_freep(&fgp);
+ return ret;
+ }
+
+ fg->index = nb_filtergraphs - 1;
+ }
fg->class = &fg_class;
- fg->index = nb_filtergraphs - 1;
fgp->graph_desc = graph_desc;
fgp->disable_conversions = !auto_conversion_filters;
fgp->sch = sch;
@@ -1135,6 +1144,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
ret = fg_create(&fg, graph_desc, sch);
if (ret < 0)
return ret;
+ ost->fg_simple = fg;
fgp = fgp_from_fg(fg);
fgp->is_simple = 1;
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 2b7a733501..a1583edd61 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -797,6 +797,7 @@ static void ost_free(OutputStream **post)
ms = ms_from_ost(ost);
enc_free(&ost->enc);
+ fg_free(&ost->fg_simple);
if (ost->logfile) {
if (fclose(ost->logfile))
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 28/31] fftools/ffmpeg_filter: change processing order in fg_finalise_bindings()
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (25 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 27/31] fftools/ffmpeg_filter: only store complex filtergraphs in global array Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 29/31] fftools/ffmpeg_sched: allow filtergraphs to send to filtergraphs Anton Khirnov
` (2 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
First bind all inputs in all filtergraphs, only then check that all
outputs are bound.
Needed by the following commit.
---
fftools/ffmpeg.h | 2 +-
fftools/ffmpeg_filter.c | 33 ++++++++++++++++++++++++++-------
fftools/ffmpeg_opt.c | 10 ++++------
3 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 882d241bdb..885a7c0c10 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -724,7 +724,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
char *graph_desc,
Scheduler *sch, unsigned sch_idx_enc,
const OutputFilterOptions *opts);
-int fg_finalise_bindings(FilterGraph *fg);
+int fg_finalise_bindings(void);
/**
* Get our axiliary frame data attached to the frame, allocating it
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 388c8919fd..1e14962f41 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1272,7 +1272,7 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter)
return 0;
}
-int fg_finalise_bindings(FilterGraph *fg)
+static int bind_inputs(FilterGraph *fg)
{
// bind filtergraph inputs to input streams
for (int i = 0; i < fg->nb_inputs; i++) {
@@ -1287,14 +1287,33 @@ int fg_finalise_bindings(FilterGraph *fg)
return ret;
}
- for (int i = 0; i < fg->nb_outputs; i++) {
- OutputFilter *output = fg->outputs[i];
- if (!output->bound) {
- av_log(filtergraphs[i], AV_LOG_FATAL,
- "Filter %s has an unconnected output\n", output->name);
- return AVERROR(EINVAL);
+ return 0;
+}
+
+int fg_finalise_bindings(void)
+{
+ int ret;
+
+ for (int i = 0; i < nb_filtergraphs; i++) {
+ ret = bind_inputs(filtergraphs[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ // check that all outputs were bound
+ for (int i = 0; i < nb_filtergraphs; i++) {
+ FilterGraph *fg = filtergraphs[i];
+
+ for (int j = 0; j < fg->nb_outputs; j++) {
+ OutputFilter *output = fg->outputs[j];
+ if (!output->bound) {
+ av_log(filtergraphs[j], AV_LOG_FATAL,
+ "Filter %s has an unconnected output\n", output->name);
+ return AVERROR(EINVAL);
+ }
}
}
+
return 0;
}
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index f764da1ed4..6526e8e3e8 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1264,12 +1264,10 @@ int ffmpeg_parse_options(int argc, char **argv, Scheduler *sch)
}
// bind unbound filtegraph inputs/outputs and check consistency
- for (int i = 0; i < nb_filtergraphs; i++) {
- ret = fg_finalise_bindings(filtergraphs[i]);
- if (ret < 0) {
- errmsg = "binding filtergraph inputs/outputs";
- goto fail;
- }
+ ret = fg_finalise_bindings();
+ if (ret < 0) {
+ errmsg = "binding filtergraph inputs/outputs";
+ goto fail;
}
correct_input_start_times();
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 29/31] fftools/ffmpeg_sched: allow filtergraphs to send to filtergraphs
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (26 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 28/31] fftools/ffmpeg_filter: change processing order in fg_finalise_bindings() Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 30/31] fftools/ffmpeg_filter: implement filtergraph chaining Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 31/31] doc/ffmpeg: document that there can be multiple complex filtergraphs Anton Khirnov
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
Will be useful for filtergraph chaining that will be added in following
commits.
---
fftools/ffmpeg_sched.c | 94 ++++++++++++++++++++++++++----------------
fftools/ffmpeg_sched.h | 6 ++-
2 files changed, 63 insertions(+), 37 deletions(-)
diff --git a/fftools/ffmpeg_sched.c b/fftools/ffmpeg_sched.c
index f8485db30b..e58b00ea97 100644
--- a/fftools/ffmpeg_sched.c
+++ b/fftools/ffmpeg_sched.c
@@ -983,20 +983,40 @@ int sch_connect(Scheduler *sch, SchedulerNode src, SchedulerNode dst)
}
case SCH_NODE_TYPE_FILTER_OUT: {
SchFilterOut *fo;
- SchEnc *enc;
av_assert0(src.idx < sch->nb_filters &&
src.idx_stream < sch->filters[src.idx].nb_outputs);
- // filtered frames go to encoding
- av_assert0(dst.type == SCH_NODE_TYPE_ENC &&
- dst.idx < sch->nb_enc);
+ fo = &sch->filters[src.idx].outputs[src.idx_stream];
- fo = &sch->filters[src.idx].outputs[src.idx_stream];
- enc = &sch->enc[dst.idx];
+ av_assert0(!fo->dst.type);
+ fo->dst = dst;
+
+ // filtered frames go to encoding or another filtergraph
+ switch (dst.type) {
+ case SCH_NODE_TYPE_ENC: {
+ SchEnc *enc;
+
+ av_assert0(dst.idx < sch->nb_enc);
+ enc = &sch->enc[dst.idx];
+
+ av_assert0(!enc->src.type);
+ enc->src = src;
+ break;
+ }
+ case SCH_NODE_TYPE_FILTER_IN: {
+ SchFilterIn *fi;
+
+ av_assert0(dst.idx < sch->nb_filters &&
+ dst.idx_stream < sch->filters[dst.idx].nb_inputs);
+ fi = &sch->filters[dst.idx].inputs[dst.idx_stream];
+
+ av_assert0(!fi->src.type);
+ fi->src = src;
+ break;
+ }
+ default: av_assert0(0);
+ }
- av_assert0(!fo->dst.type && !enc->src.type);
- fo->dst = dst;
- enc->src = src;
break;
}
@@ -1351,24 +1371,13 @@ static int check_acyclic(Scheduler *sch)
goto fail;
}
- // trace the transcoding graph upstream from every output stream
- // fed by a filtergraph
- for (unsigned i = 0; i < sch->nb_mux; i++) {
- SchMux *mux = &sch->mux[i];
-
- for (unsigned j = 0; j < mux->nb_streams; j++) {
- SchMuxStream *ms = &mux->streams[j];
- SchedulerNode src = ms->src_sched;
-
- if (src.type != SCH_NODE_TYPE_FILTER_OUT)
- continue;
- src.idx_stream = 0;
-
- ret = check_acyclic_for_output(sch, src, filters_visited, filters_stack);
- if (ret < 0) {
- av_log(mux, AV_LOG_ERROR, "Transcoding graph has a cycle\n");
- goto fail;
- }
+ // trace the transcoding graph upstream from every filtegraph
+ for (unsigned i = 0; i < sch->nb_filters; i++) {
+ ret = check_acyclic_for_output(sch, (SchedulerNode){ .idx = i },
+ filters_visited, filters_stack);
+ if (ret < 0) {
+ av_log(&sch->filters[i], AV_LOG_ERROR, "Transcoding graph has a cycle\n");
+ goto fail;
}
}
@@ -1484,13 +1493,18 @@ static int start_prepare(Scheduler *sch)
"Filtergraph input %u not connected to a source\n", j);
return AVERROR(EINVAL);
}
- av_assert0(fi->src.type == SCH_NODE_TYPE_DEC);
- dec = &sch->dec[fi->src.idx];
- switch (dec->src.type) {
- case SCH_NODE_TYPE_DEMUX: fi->src_sched = dec->src; break;
- case SCH_NODE_TYPE_ENC: fi->src_sched = sch->enc[dec->src.idx].src; break;
- default: av_assert0(0);
+ if (fi->src.type == SCH_NODE_TYPE_FILTER_OUT)
+ fi->src_sched = fi->src;
+ else {
+ av_assert0(fi->src.type == SCH_NODE_TYPE_DEC);
+ dec = &sch->dec[fi->src.idx];
+
+ switch (dec->src.type) {
+ case SCH_NODE_TYPE_DEMUX: fi->src_sched = dec->src; break;
+ case SCH_NODE_TYPE_ENC: fi->src_sched = sch->enc[dec->src.idx].src; break;
+ default: av_assert0(0);
+ }
}
}
@@ -2379,12 +2393,17 @@ void sch_filter_receive_finish(Scheduler *sch, unsigned fg_idx, unsigned in_idx)
int sch_filter_send(Scheduler *sch, unsigned fg_idx, unsigned out_idx, AVFrame *frame)
{
SchFilterGraph *fg;
+ SchedulerNode dst;
av_assert0(fg_idx < sch->nb_filters);
fg = &sch->filters[fg_idx];
av_assert0(out_idx < fg->nb_outputs);
- return send_to_enc(sch, &sch->enc[fg->outputs[out_idx].dst.idx], frame);
+ dst = fg->outputs[out_idx].dst;
+
+ return (dst.type == SCH_NODE_TYPE_ENC) ?
+ send_to_enc (sch, &sch->enc[dst.idx], frame) :
+ send_to_filter(sch, &sch->filters[dst.idx], dst.idx_stream, frame);
}
static int filter_done(Scheduler *sch, unsigned fg_idx)
@@ -2396,8 +2415,11 @@ static int filter_done(Scheduler *sch, unsigned fg_idx)
tq_receive_finish(fg->queue, i);
for (unsigned i = 0; i < fg->nb_outputs; i++) {
- SchEnc *enc = &sch->enc[fg->outputs[i].dst.idx];
- int err = send_to_enc(sch, enc, NULL);
+ SchedulerNode dst = fg->outputs[i].dst;
+ int err = (dst.type == SCH_NODE_TYPE_ENC) ?
+ send_to_enc (sch, &sch->enc[dst.idx], NULL) :
+ send_to_filter(sch, &sch->filters[dst.idx], dst.idx_stream, NULL);
+
if (err < 0 && err != AVERROR_EOF)
ret = err_merge(ret, err);
}
diff --git a/fftools/ffmpeg_sched.h b/fftools/ffmpeg_sched.h
index e51c26cec9..7cd839016c 100644
--- a/fftools/ffmpeg_sched.h
+++ b/fftools/ffmpeg_sched.h
@@ -41,7 +41,8 @@
* - filtergraphs, each containing zero or more inputs (0 in case the
* filtergraph contains a lavfi source filter), and one or more outputs; the
* inputs and outputs need not have matching media types;
- * each filtergraph input receives decoded frames from some decoder;
+ * each filtergraph input receives decoded frames from some decoder or another
+ * filtergraph output;
* filtered frames from each output are sent to some encoder;
* - encoders, which receive decoded frames from some decoder (subtitles) or
* some filtergraph output (audio/video), encode them, and send encoded
@@ -51,6 +52,9 @@
* encoder (transcoding); those packets are interleaved and written out by the
* muxer.
*
+ * The structure formed by the above components is a directed acyclic graph
+ * (absence of cycles is checked at startup).
+ *
* There must be at least one muxer instance, otherwise the transcode produces
* no output and is meaningless. Otherwise, in a generic transcoding scenario
* there may be arbitrary number of instances of any of the above components,
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 30/31] fftools/ffmpeg_filter: implement filtergraph chaining
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (27 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 29/31] fftools/ffmpeg_sched: allow filtergraphs to send to filtergraphs Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 31/31] doc/ffmpeg: document that there can be multiple complex filtergraphs Anton Khirnov
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
This allows one complex filtergraph's output to be sent as input to
another one, which is useful in certain situations (one is described in
the docs).
Chaining filtergraphs was already effectively possible by using a
wrapped_avframe encoder connected to a loopback decoder, but it is ugly,
non-obvious and inefficient.
---
Changelog | 1 +
doc/ffmpeg.texi | 58 ++++++++++++++++++++++++---
fftools/ffmpeg_filter.c | 89 +++++++++++++++++++++++++++++++++++++++--
3 files changed, 140 insertions(+), 8 deletions(-)
diff --git a/Changelog b/Changelog
index 18e83b99a1..b7a1af4083 100644
--- a/Changelog
+++ b/Changelog
@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
version <next>:
- Raw Captions with Time (RCWT) closed caption demuxer
- LC3/LC3plus decoding/encoding using external library liblc3
+- ffmpeg CLI filtergraph chaining
version 7.0:
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 801c083705..9bd548ce4e 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -2145,14 +2145,62 @@ type -- see the @option{-filter} options. @var{filtergraph} is a description of
the filtergraph, as described in the ``Filtergraph syntax'' section of the
ffmpeg-filters manual.
-Input link labels must refer to either input streams or loopback decoders. For
-input streams, use the @code{[file_index:stream_specifier]} syntax (i.e. the
-same as @option{-map} uses). If @var{stream_specifier} matches multiple streams,
-the first one will be used.
+Inputs to a complex filtergraph may come from different source types,
+distinguished by the format of the corresponding link label:
+@itemize
+@item
+To connect an input stream, use @code{[file_index:stream_specifier]} (i.e. the
+same syntax as @option{-map}). If @var{stream_specifier} matches multiple
+streams, the first one will be used.
-For decoders, the link label must be [dec:@var{dec_idx}], where @var{dec_idx} is
+@item
+To connect a loopback decoder use [dec:@var{dec_idx}], where @var{dec_idx} is
the index of the loopback decoder to be connected to given input.
+@item
+To connect an output from another complex filtergraph, use its link label. E.g
+the following example:
+
+@example
+ffmpeg -i input.mkv \
+ -filter_complex '[0:v]scale=size=hd1080,split=outputs=2[for_enc][orig_scaled]' \
+ -c:v libx264 -map '[for_enc]' output.mkv \
+ -dec 0:0 \
+ -filter_complex '[dec:0][orig_scaled]hstack[stacked]' \
+ -map '[stacked]' -c:v ffv1 comparison.mkv
+@end example
+
+reads an input video and
+@itemize
+@item
+(line 2) uses a complex filtergraph with one input and two outputs
+to scale the video to 1920x1080 and duplicate the result to both
+outputs;
+
+@item
+(line 3) encodes one scaled output with @code{libx264} and writes the result to
+@file{output.mkv};
+
+@item
+(line 4) decodes this encoded stream with a loopback decoder;
+
+@item
+(line 5) places the output of the loopback decoder (i.e. the
+@code{libx264}-encoded video) side by side with the scaled original input;
+
+@item
+(line 6) combined video is then losslessly encoded and written into
+@file{comparison.mkv}.
+
+@end itemize
+
+Note that the two filtergraphs cannot be combined into one, because then there
+would be a cycle in the transcoding pipeline (filtergraph output goes to
+encoding, from there to decoding, then back to the same graph), and such cycles
+are not allowed.
+
+@end itemize
+
An unlabeled input will be connected to the first unused input stream of the
matching type.
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 1e14962f41..f108f8daf9 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -902,6 +902,63 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
return 0;
}
+static int ofilter_bind_ifilter(OutputFilter *ofilter, InputFilterPriv *ifp,
+ const OutputFilterOptions *opts)
+{
+ OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
+
+ av_assert0(!ofilter->bound);
+ av_assert0(ofilter->type == ifp->type);
+
+ ofilter->bound = 1;
+ av_freep(&ofilter->linklabel);
+
+ ofp->name = av_strdup(opts->name);
+ if (!ofp->name)
+ return AVERROR(EINVAL);
+
+ av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofp->name);
+
+ return 0;
+}
+
+static int ifilter_bind_fg(InputFilterPriv *ifp, FilterGraph *fg_src, int out_idx)
+{
+ FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph);
+ OutputFilter *ofilter_src = fg_src->outputs[out_idx];
+ OutputFilterOptions opts;
+ char name[32];
+ int ret;
+
+ av_assert0(!ifp->bound);
+ ifp->bound = 1;
+
+ if (ifp->type != ofilter_src->type) {
+ av_log(fgp, AV_LOG_ERROR, "Tried to connect %s output to %s input\n",
+ av_get_media_type_string(ofilter_src->type),
+ av_get_media_type_string(ifp->type));
+ return AVERROR(EINVAL);
+ }
+
+ ifp->type_src = ifp->type;
+
+ memset(&opts, 0, sizeof(opts));
+
+ snprintf(name, sizeof(name), "fg:%d:%d", fgp->fg.index, ifp->index);
+ opts.name = name;
+
+ ret = ofilter_bind_ifilter(ofilter_src, ifp, &opts);
+ if (ret < 0)
+ return ret;
+
+ ret = sch_connect(fgp->sch, SCH_FILTER_OUT(fg_src->index, out_idx),
+ SCH_FILTER_IN(fgp->sch_idx, ifp->index));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static InputFilter *ifilter_alloc(FilterGraph *fg)
{
InputFilterPriv *ifp;
@@ -1213,12 +1270,38 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter)
ifilter->name);
return ret;
} else if (ifp->linklabel) {
- // bind to an explicitly specified demuxer stream
AVFormatContext *s;
AVStream *st = NULL;
char *p;
- int file_idx = strtol(ifp->linklabel, &p, 0);
+ int file_idx;
+ // try finding an unbound filtergraph output with this label
+ for (int i = 0; i < nb_filtergraphs; i++) {
+ FilterGraph *fg_src = filtergraphs[i];
+
+ if (fg == fg_src)
+ continue;
+
+ for (int j = 0; j < fg_src->nb_outputs; j++) {
+ OutputFilter *ofilter = fg_src->outputs[j];
+
+ if (!ofilter->bound && ofilter->linklabel &&
+ !strcmp(ofilter->linklabel, ifp->linklabel)) {
+ av_log(fg, AV_LOG_VERBOSE,
+ "Binding input with label '%s' to filtergraph output %d:%d\n",
+ ifp->linklabel, i, j);
+
+ ret = ifilter_bind_fg(ifp, fg_src, j);
+ if (ret < 0)
+ av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %s\n",
+ ifp->linklabel);
+ return ret;
+ }
+ }
+ }
+
+ // bind to an explicitly specified demuxer stream
+ file_idx = strtol(ifp->linklabel, &p, 0);
if (file_idx < 0 || file_idx >= nb_input_files) {
av_log(fg, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n",
file_idx, fgp->graph_desc);
@@ -1274,7 +1357,7 @@ static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter)
static int bind_inputs(FilterGraph *fg)
{
- // bind filtergraph inputs to input streams
+ // bind filtergraph inputs to input streams or other filtergraphs
for (int i = 0; i < fg->nb_inputs; i++) {
InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
int ret;
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread
* [FFmpeg-devel] [PATCH 31/31] doc/ffmpeg: document that there can be multiple complex filtergraphs
2024-04-05 16:11 [FFmpeg-devel] [PATCH 01/31] lavfi/vf_scale: fix AVOption flags for "size"/"s" Anton Khirnov
` (28 preceding siblings ...)
2024-04-05 16:12 ` [FFmpeg-devel] [PATCH 30/31] fftools/ffmpeg_filter: implement filtergraph chaining Anton Khirnov
@ 2024-04-05 16:12 ` Anton Khirnov
29 siblings, 0 replies; 35+ messages in thread
From: Anton Khirnov @ 2024-04-05 16:12 UTC (permalink / raw)
To: ffmpeg-devel
---
doc/ffmpeg.texi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 9bd548ce4e..e996ab945f 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -2143,7 +2143,8 @@ Define a complex filtergraph, i.e. one with arbitrary number of inputs and/or
outputs. For simple graphs -- those with one input and one output of the same
type -- see the @option{-filter} options. @var{filtergraph} is a description of
the filtergraph, as described in the ``Filtergraph syntax'' section of the
-ffmpeg-filters manual.
+ffmpeg-filters manual. This option may be specified multiple times - each use
+creates a new complex filtergraph.
Inputs to a complex filtergraph may come from different source types,
distinguished by the format of the corresponding link label:
--
2.43.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 35+ messages in thread