* [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add()
@ 2023-05-28 9:13 Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 02/24] fftools/ffmpeg: add logging for creating output streams Anton Khirnov
` (22 more replies)
0 siblings, 23 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:13 UTC (permalink / raw)
To: ffmpeg-devel
This way ost_add() knows about the complex filtergraph it is fed from,
which will become useful in future commits.
---
fftools/ffmpeg_mux_init.c | 71 ++++++++++++++++++---------------------
1 file changed, 32 insertions(+), 39 deletions(-)
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 7878789bb4..de39b360af 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -985,7 +985,8 @@ fail:
}
static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
- enum AVMediaType type, InputStream *ist)
+ enum AVMediaType type, InputStream *ist,
+ OutputFilter *ofilter)
{
AVFormatContext *oc = mux->fc;
MuxStream *ms;
@@ -1040,6 +1041,14 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
av_strlcat(ms->log_name, "/", sizeof(ms->log_name));
av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name));
} else {
+ if (ofilter) {
+ av_log(ost, AV_LOG_ERROR,
+ "Streamcopy requested for output stream fed "
+ "from a complex filtergraph. Filtering and streamcopy "
+ "cannot be used together.\n");
+ exit_program(1);
+ }
+
av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name));
}
@@ -1233,22 +1242,26 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
exit_program(1);
}
- if (ost->ist) {
- if (ost->enc &&
- (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
+ if (ost->enc &&
+ (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
+ if (ofilter) {
+ ost->filter = ofilter;
+ ofilter->ost = ost;
+ avfilter_inout_free(&ofilter->out_tmp);
+ } else {
ret = init_simple_filtergraph(ost->ist, ost);
if (ret < 0) {
av_log(ost, AV_LOG_ERROR,
"Error initializing a simple filtergraph\n");
exit_program(1);
}
- } else {
- ret = ist_output_add(ost->ist, ost);
- if (ret < 0) {
- av_log(ost, AV_LOG_ERROR,
- "Error binding an input stream\n");
- exit_program(1);
- }
+ }
+ } else if (ost->ist) {
+ ret = ist_output_add(ost->ist, ost);
+ if (ret < 0) {
+ av_log(ost, AV_LOG_ERROR,
+ "Error binding an input stream\n");
+ exit_program(1);
}
}
@@ -1261,26 +1274,6 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
return ost;
}
-// add a new output stream fed by the provided filtergraph output
-static void ost_add_from_filter(OutputFilter *ofilter, const OptionsContext *o,
- Muxer *mux)
-{
- OutputStream *ost = ost_add(mux, o, ofilter->type, NULL);
-
- ost->filter = ofilter;
-
- ofilter->ost = ost;
-
- if (!ost->enc_ctx) {
- av_log(ost, AV_LOG_ERROR, "Streamcopy requested for output stream fed "
- "from a complex filtergraph. Filtering and streamcopy "
- "cannot be used together.\n");
- exit_program(1);
- }
-
- avfilter_inout_free(&ofilter->out_tmp);
-}
-
static void map_auto_video(Muxer *mux, const OptionsContext *o)
{
AVFormatContext *oc = mux->fc;
@@ -1329,7 +1322,7 @@ static void map_auto_video(Muxer *mux, const OptionsContext *o)
}
}
if (best_ist)
- ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist);
+ ost_add(mux, o, AVMEDIA_TYPE_VIDEO, best_ist, NULL);
}
static void map_auto_audio(Muxer *mux, const OptionsContext *o)
@@ -1371,7 +1364,7 @@ static void map_auto_audio(Muxer *mux, const OptionsContext *o)
}
}
if (best_ist)
- ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist);
+ ost_add(mux, o, AVMEDIA_TYPE_AUDIO, best_ist, NULL);
}
static void map_auto_subtitle(Muxer *mux, const OptionsContext *o)
@@ -1406,7 +1399,7 @@ static void map_auto_subtitle(Muxer *mux, const OptionsContext *o)
input_descriptor && output_descriptor &&
(!input_descriptor->props ||
!output_descriptor->props)) {
- ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist);
+ ost_add(mux, o, AVMEDIA_TYPE_SUBTITLE, ist, NULL);
break;
}
}
@@ -1426,7 +1419,7 @@ static void map_auto_data(Muxer *mux, const OptionsContext *o)
continue;
if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_DATA &&
ist->st->codecpar->codec_id == codec_id )
- ost_add(mux, o, AVMEDIA_TYPE_DATA, ist);
+ ost_add(mux, o, AVMEDIA_TYPE_DATA, ist, NULL);
}
}
@@ -1458,7 +1451,7 @@ loop_end:
"in any defined filter graph, or was already used elsewhere.\n", map->linklabel);
exit_program(1);
}
- ost_add_from_filter(ofilter, o, mux);
+ ost_add(mux, o, ofilter->type, NULL, ofilter);
} else {
ist = input_files[map->file_index]->streams[map->stream_index];
if (ist->user_set_discard == AVDISCARD_ALL) {
@@ -1490,7 +1483,7 @@ loop_end:
return;
}
- ost_add(mux, o, ist->st->codecpar->codec_type, ist);
+ ost_add(mux, o, ist->st->codecpar->codec_type, ist, NULL);
}
}
@@ -1524,7 +1517,7 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o)
avio_read(pb, attachment, len);
memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
- ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL);
+ ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL);
ost->attachment_filename = o->attachments[i];
ost->par_in->extradata = attachment;
ost->par_in->extradata_size = len;
@@ -1557,7 +1550,7 @@ static void create_streams(Muxer *mux, const OptionsContext *o)
case AVMEDIA_TYPE_AUDIO: auto_disable_a = 1; break;
case AVMEDIA_TYPE_SUBTITLE: auto_disable_s = 1; break;
}
- ost_add_from_filter(ofilter, o, mux);
+ ost_add(mux, o, ofilter->type, NULL, ofilter);
}
}
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 02/24] fftools/ffmpeg: add logging for creating output streams
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
@ 2023-05-28 9:13 ` Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 03/24] fftools/ffmpeg_filter: use a dedicated variable for marking simple filtergraphs Anton Khirnov
` (21 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:13 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_mux_init.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index de39b360af..033e55d76e 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1052,6 +1052,19 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name));
}
+ av_log(ost, AV_LOG_VERBOSE, "Created %s stream from ",
+ av_get_media_type_string(type));
+ if (ist)
+ av_log(ost, AV_LOG_VERBOSE, "input stream %d:%d",
+ ist->file_index, ist->index);
+ else if (ofilter)
+ av_log(ost, AV_LOG_VERBOSE, "complex filtergraph %d:[%s]\n",
+ ofilter->graph->index, ofilter->name);
+ else if (type == AVMEDIA_TYPE_ATTACHMENT)
+ av_log(ost, AV_LOG_VERBOSE, "attached file");
+ else av_assert0(0);
+ av_log(ost, AV_LOG_VERBOSE, "\n");
+
ost->pkt = av_packet_alloc();
if (!ost->pkt)
report_and_exit(AVERROR(ENOMEM));
@@ -1451,6 +1464,10 @@ loop_end:
"in any defined filter graph, or was already used elsewhere.\n", map->linklabel);
exit_program(1);
}
+
+ av_log(mux, AV_LOG_VERBOSE, "Creating output stream from an explicitly "
+ "mapped complex filtergraph %d, output [%s]\n", fg->index, map->linklabel);
+
ost_add(mux, o, ofilter->type, NULL, ofilter);
} else {
ist = input_files[map->file_index]->streams[map->stream_index];
@@ -1517,6 +1534,9 @@ static void of_add_attachments(Muxer *mux, const OptionsContext *o)
avio_read(pb, attachment, len);
memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+ av_log(mux, AV_LOG_VERBOSE, "Creating attachment stream from file %s\n",
+ o->attachments[i]);
+
ost = ost_add(mux, o, AVMEDIA_TYPE_ATTACHMENT, NULL, NULL);
ost->attachment_filename = o->attachments[i];
ost->par_in->extradata = attachment;
@@ -1550,11 +1570,21 @@ static void create_streams(Muxer *mux, const OptionsContext *o)
case AVMEDIA_TYPE_AUDIO: auto_disable_a = 1; break;
case AVMEDIA_TYPE_SUBTITLE: auto_disable_s = 1; break;
}
+
+ av_log(mux, AV_LOG_VERBOSE, "Creating output stream from unlabeled "
+ "output of complex filtergraph %d.", fg->index);
+ if (!o->nb_stream_maps)
+ av_log(mux, AV_LOG_VERBOSE, " This overrides automatic %s mapping.",
+ av_get_media_type_string(ofilter->type));
+ av_log(mux, AV_LOG_VERBOSE, "\n");
+
ost_add(mux, o, ofilter->type, NULL, ofilter);
}
}
if (!o->nb_stream_maps) {
+ av_log(mux, AV_LOG_VERBOSE, "No explicit maps, mapping streams automatically...\n");
+
/* pick the "best" stream of each type */
if (!auto_disable_v)
map_auto_video(mux, o);
@@ -1565,6 +1595,8 @@ static void create_streams(Muxer *mux, const OptionsContext *o)
if (!auto_disable_d)
map_auto_data(mux, o);
} else {
+ av_log(mux, AV_LOG_VERBOSE, "Adding streams from explicit maps...\n");
+
for (int i = 0; i < o->nb_stream_maps; i++)
map_manual(mux, o, &o->stream_maps[i]);
}
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 03/24] fftools/ffmpeg_filter: use a dedicated variable for marking simple filtergraphs
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 02/24] fftools/ffmpeg: add logging for creating output streams Anton Khirnov
@ 2023-05-28 9:13 ` Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 04/24] fftools/ffmpeg_filter: always pass graph description to fg_create() Anton Khirnov
` (20 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:13 UTC (permalink / raw)
To: ffmpeg-devel
Do not use an unrelated graph property, which will change in future
commits.
---
fftools/ffmpeg_filter.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index f37b867b31..e11ae2e9bf 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -41,6 +41,8 @@
typedef struct FilterGraphPriv {
FilterGraph fg;
+ int is_simple;
+
const char *graph_desc;
// frame for temporarily holding output from the filtergraph
@@ -353,6 +355,7 @@ FilterGraph *fg_create(char *graph_desc)
int init_simple_filtergraph(InputStream *ist, OutputStream *ost)
{
FilterGraph *fg;
+ FilterGraphPriv *fgp;
OutputFilter *ofilter;
InputFilter *ifilter;
int ret;
@@ -360,6 +363,9 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost)
fg = fg_create(NULL);
if (!fg)
report_and_exit(AVERROR(ENOMEM));
+ fgp = fgp_from_fg(fg);
+
+ fgp->is_simple = 1;
ofilter = ofilter_alloc(fg);
ofilter->ost = ost;
@@ -1474,7 +1480,7 @@ int ifilter_has_all_input_formats(FilterGraph *fg)
int filtergraph_is_simple(FilterGraph *fg)
{
FilterGraphPriv *fgp = fgp_from_fg(fg);
- return !fgp->graph_desc;
+ return fgp->is_simple;
}
int reap_filters(int flush)
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 04/24] fftools/ffmpeg_filter: always pass graph description to fg_create()
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 02/24] fftools/ffmpeg: add logging for creating output streams Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 03/24] fftools/ffmpeg_filter: use a dedicated variable for marking simple filtergraphs Anton Khirnov
@ 2023-05-28 9:13 ` Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 05/24] fftools/ffmpeg_filter: store just the link label in OutputFilter Anton Khirnov
` (19 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:13 UTC (permalink / raw)
To: ffmpeg-devel
Currently NULL would be passed for simple filtergraphs, which would
make the filter code extract the graph description from the output
stream when needed. This is unnecessarily convoluted.
---
fftools/ffmpeg.h | 4 ++--
fftools/ffmpeg_filter.c | 8 ++++----
fftools/ffmpeg_mux.c | 1 -
fftools/ffmpeg_mux_init.c | 16 ++++++++--------
4 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 95334825ef..1bb9125bf2 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -590,7 +590,6 @@ typedef struct OutputStream {
FILE *logfile;
OutputFilter *filter;
- char *avfilter;
AVDictionary *encoder_opts;
AVDictionary *sws_dict;
@@ -737,7 +736,8 @@ int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_id
int configure_filtergraph(FilterGraph *fg);
void check_filter_outputs(void);
int filtergraph_is_simple(FilterGraph *fg);
-int init_simple_filtergraph(InputStream *ist, OutputStream *ost);
+int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
+ char *graph_desc);
int init_complex_filtergraph(FilterGraph *fg);
void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub);
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index e11ae2e9bf..75317139ba 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -352,7 +352,8 @@ FilterGraph *fg_create(char *graph_desc)
return fg;
}
-int init_simple_filtergraph(InputStream *ist, OutputStream *ost)
+int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
+ char *graph_desc)
{
FilterGraph *fg;
FilterGraphPriv *fgp;
@@ -360,7 +361,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost)
InputFilter *ifilter;
int ret;
- fg = fg_create(NULL);
+ fg = fg_create(graph_desc);
if (!fg)
report_and_exit(AVERROR(ENOMEM));
fgp = fgp_from_fg(fg);
@@ -1263,8 +1264,7 @@ int configure_filtergraph(FilterGraph *fg)
AVBufferRef *hw_device;
AVFilterInOut *inputs, *outputs, *cur;
int ret, i, simple = filtergraph_is_simple(fg);
- const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter :
- fgp->graph_desc;
+ const char *graph_desc = fgp->graph_desc;
cleanup_filtergraph(fg);
if (!(fg->graph = avfilter_graph_alloc()))
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 36ed482072..3da3c04d7f 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -853,7 +853,6 @@ static void ost_free(OutputStream **post)
av_freep(&ost->kf.pts);
av_expr_free(ost->kf.pexpr);
- av_freep(&ost->avfilter);
av_freep(&ost->logfile_prefix);
av_freep(&ost->apad);
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 033e55d76e..1c97804ec8 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -432,7 +432,7 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type)
}
static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc,
- OutputStream *ost)
+ OutputStream *ost, char **dst)
{
const char *filters = NULL, *filters_script = NULL;
@@ -470,12 +470,12 @@ static int ost_get_filters(const OptionsContext *o, AVFormatContext *oc,
}
if (filters_script)
- ost->avfilter = file_read(filters_script);
+ *dst = file_read(filters_script);
else if (filters)
- ost->avfilter = av_strdup(filters);
+ *dst = av_strdup(filters);
else
- ost->avfilter = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull");
- return ost->avfilter ? 0 : AVERROR(ENOMEM);
+ *dst = av_strdup(ost->type == AVMEDIA_TYPE_VIDEO ? "null" : "anull");
+ return *dst ? 0 : AVERROR(ENOMEM);
}
static void parse_matrix_coeffs(void *logctx, uint16_t *dest, const char *str)
@@ -995,7 +995,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
AVStream *st = avformat_new_stream(oc, NULL);
int ret = 0;
const char *bsfs = NULL, *time_base = NULL;
- char *next, *codec_tag = NULL;
+ char *filters = NULL, *next, *codec_tag = NULL;
double qscale = -1;
int i;
@@ -1250,7 +1250,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
}
if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) {
- ret = ost_get_filters(o, oc, ost);
+ ret = ost_get_filters(o, oc, ost, &filters);
if (ret < 0)
exit_program(1);
}
@@ -1262,7 +1262,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
ofilter->ost = ost;
avfilter_inout_free(&ofilter->out_tmp);
} else {
- ret = init_simple_filtergraph(ost->ist, ost);
+ ret = init_simple_filtergraph(ost->ist, ost, filters);
if (ret < 0) {
av_log(ost, AV_LOG_ERROR,
"Error initializing a simple filtergraph\n");
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 05/24] fftools/ffmpeg_filter: store just the link label in OutputFilter
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (2 preceding siblings ...)
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 04/24] fftools/ffmpeg_filter: always pass graph description to fg_create() Anton Khirnov
@ 2023-05-28 9:13 ` Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 06/24] fftools/ffmpeg_filter: decouple allocating InputFilter and binding it to InputStream Anton Khirnov
` (18 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:13 UTC (permalink / raw)
To: ffmpeg-devel
Not the entire AVFilterInOut. This is simpler.
---
fftools/ffmpeg.h | 6 ++++--
fftools/ffmpeg_filter.c | 8 +++++---
fftools/ffmpeg_mux_init.c | 8 ++++----
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 1bb9125bf2..3aa19c7f5f 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -289,8 +289,10 @@ typedef struct OutputFilter {
struct FilterGraph *graph;
uint8_t *name;
- /* temporary storage until stream maps are processed */
- AVFilterInOut *out_tmp;
+ /* for filters that are not yet bound to an output stream,
+ * this stores the output linklabel, if any */
+ uint8_t *linklabel;
+
enum AVMediaType type;
/* desired output stream properties */
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 75317139ba..323e63b829 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -324,7 +324,7 @@ void fg_free(FilterGraph **pfg)
for (int j = 0; j < fg->nb_outputs; j++) {
OutputFilter *ofilter = fg->outputs[j];
- avfilter_inout_free(&ofilter->out_tmp);
+ av_freep(&ofilter->linklabel);
av_freep(&ofilter->name);
av_channel_layout_uninit(&ofilter->ch_layout);
av_freep(&fg->outputs[j]);
@@ -661,16 +661,18 @@ int init_complex_filtergraph(FilterGraph *fg)
for (cur = outputs; cur;) {
OutputFilter *const ofilter = ofilter_alloc(fg);
- ofilter->out_tmp = cur;
+ 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);
cur = cur->next;
- ofilter->out_tmp->next = NULL;
}
fail:
avfilter_inout_free(&inputs);
+ avfilter_inout_free(&outputs);
avfilter_graph_free(&graph);
return ret;
}
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 1c97804ec8..f7a24feec7 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1260,7 +1260,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
if (ofilter) {
ost->filter = ofilter;
ofilter->ost = ost;
- avfilter_inout_free(&ofilter->out_tmp);
+ av_freep(&ofilter->linklabel);
} else {
ret = init_simple_filtergraph(ost->ist, ost, filters);
if (ret < 0) {
@@ -1451,8 +1451,8 @@ static void map_manual(Muxer *mux, const OptionsContext *o, const StreamMap *map
for (j = 0; j < nb_filtergraphs; j++) {
fg = filtergraphs[j];
for (k = 0; k < fg->nb_outputs; k++) {
- AVFilterInOut *out = fg->outputs[k]->out_tmp;
- if (out && !strcmp(out->name, map->linklabel)) {
+ const char *linklabel = fg->outputs[k]->linklabel;
+ if (linklabel && !strcmp(linklabel, map->linklabel)) {
ofilter = fg->outputs[k];
goto loop_end;
}
@@ -1562,7 +1562,7 @@ static void create_streams(Muxer *mux, const OptionsContext *o)
for (int j = 0; j < fg->nb_outputs; j++) {
OutputFilter *ofilter = fg->outputs[j];
- if (!ofilter->out_tmp || ofilter->out_tmp->name)
+ if (ofilter->linklabel || ofilter->ost)
continue;
switch (ofilter->type) {
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 06/24] fftools/ffmpeg_filter: decouple allocating InputFilter and binding it to InputStream
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (3 preceding siblings ...)
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 05/24] fftools/ffmpeg_filter: store just the link label in OutputFilter Anton Khirnov
@ 2023-05-28 9:13 ` Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 07/24] fftools/ffmpeg_filter: move some functions higher up Anton Khirnov
` (17 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:13 UTC (permalink / raw)
To: ffmpeg-devel
Will be useful in future commits.
---
fftools/ffmpeg_filter.c | 31 ++++++++++++++++++++++---------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 323e63b829..a8c4ef321f 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -258,7 +258,24 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg)
return ofilter;
}
-static InputFilter *ifilter_alloc(FilterGraph *fg, InputStream *ist)
+static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist)
+{
+ InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
+ int ret;
+
+ ret = ist_filter_add(ist, ifilter, filtergraph_is_simple(ifilter->graph));
+ if (ret < 0)
+ return ret;
+
+ ifp->ist = ist;
+ ifp->type_src = ist->st->codecpar->codec_type;
+ ifp->type = ifp->type_src == AVMEDIA_TYPE_SUBTITLE ?
+ AVMEDIA_TYPE_VIDEO : ifp->type_src;
+
+ return 0;
+}
+
+static InputFilter *ifilter_alloc(FilterGraph *fg)
{
InputFilterPriv *ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp),
&fg->nb_inputs);
@@ -272,10 +289,6 @@ static InputFilter *ifilter_alloc(FilterGraph *fg, InputStream *ist)
ifp->format = -1;
ifp->fallback.format = -1;
- ifp->ist = ist;
- ifp->type_src = ist->st->codecpar->codec_type;
- ifp->type = ifp->type_src == AVMEDIA_TYPE_SUBTITLE ?
- AVMEDIA_TYPE_VIDEO : ifp->type_src;
ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW);
if (!ifp->frame_queue)
@@ -373,9 +386,9 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
ost->filter = ofilter;
- ifilter = ifilter_alloc(fg, ist);
+ ifilter = ifilter_alloc(fg);
- ret = ist_filter_add(ist, ifilter, 1);
+ ret = ifilter_bind_ist(ifilter, ist);
if (ret < 0)
return ret;
@@ -455,10 +468,10 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
}
av_assert0(ist);
- ifilter = ifilter_alloc(fg, ist);
+ ifilter = ifilter_alloc(fg);
ifilter->name = describe_filter_link(fg, in, 1);
- ret = ist_filter_add(ist, ifilter, 0);
+ ret = ifilter_bind_ist(ifilter, ist);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR,
"Error binding an input stream to complex filtergraph input %s.\n",
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 07/24] fftools/ffmpeg_filter: move some functions higher up
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (4 preceding siblings ...)
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 06/24] fftools/ffmpeg_filter: decouple allocating InputFilter and binding it to InputStream Anton Khirnov
@ 2023-05-28 9:13 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 08/24] fftools/ffmpeg_filter: create Input/OutputFilters together with FilterGraph Anton Khirnov
` (16 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:13 UTC (permalink / raw)
To: ffmpeg-devel
Needed by the following commit.
---
fftools/ffmpeg_filter.c | 374 ++++++++++++++++++++--------------------
1 file changed, 187 insertions(+), 187 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index a8c4ef321f..5169a3ca82 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -246,6 +246,193 @@ static void choose_channel_layouts(OutputFilter *ofilter, AVBPrint *bprint)
av_bprint_chars(bprint, ':', 1);
}
+static int read_binary(const char *path, uint8_t **data, int *len)
+{
+ AVIOContext *io = NULL;
+ int64_t fsize;
+ int ret;
+
+ *data = NULL;
+ *len = 0;
+
+ ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s': %s\n",
+ path, av_err2str(ret));
+ return ret;
+ }
+
+ fsize = avio_size(io);
+ if (fsize < 0 || fsize > INT_MAX) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path);
+ ret = AVERROR(EIO);
+ goto fail;
+ }
+
+ *data = av_malloc(fsize);
+ if (!*data) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ ret = avio_read(io, *data, fsize);
+ if (ret != fsize) {
+ av_log(NULL, AV_LOG_ERROR, "Error reading file %s\n", path);
+ ret = ret < 0 ? ret : AVERROR(EIO);
+ goto fail;
+ }
+
+ *len = fsize;
+
+ ret = 0;
+fail:
+ avio_close(io);
+ if (ret < 0) {
+ av_freep(data);
+ *len = 0;
+ }
+ return ret;
+}
+
+static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val)
+{
+ const AVOption *o = NULL;
+ int ret;
+
+ ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN);
+ if (ret >= 0)
+ return 0;
+
+ if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/')
+ o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN);
+ if (!o)
+ goto err_apply;
+
+ // key is a valid option name prefixed with '/'
+ // interpret value as a path from which to load the actual option value
+ key++;
+
+ if (o->type == AV_OPT_TYPE_BINARY) {
+ uint8_t *data;
+ int len;
+
+ ret = read_binary(val, &data, &len);
+ if (ret < 0)
+ goto err_load;
+
+ ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN);
+ av_freep(&data);
+ } else {
+ char *data = file_read(val);
+ if (!data) {
+ ret = AVERROR(EIO);
+ goto err_load;
+ }
+
+ ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN);
+ av_freep(&data);
+ }
+ if (ret < 0)
+ goto err_apply;
+
+ return 0;
+
+err_apply:
+ av_log(NULL, AV_LOG_ERROR,
+ "Error applying option '%s' to filter '%s': %s\n",
+ key, f->filter->name, av_err2str(ret));
+ return ret;
+err_load:
+ av_log(NULL, AV_LOG_ERROR,
+ "Error loading value for option '%s' from file '%s'\n",
+ key, val);
+ return ret;
+}
+
+static int graph_opts_apply(AVFilterGraphSegment *seg)
+{
+ for (size_t i = 0; i < seg->nb_chains; i++) {
+ AVFilterChain *ch = seg->chains[i];
+
+ for (size_t j = 0; j < ch->nb_filters; j++) {
+ AVFilterParams *p = ch->filters[j];
+ const AVDictionaryEntry *e = NULL;
+
+ av_assert0(p->filter);
+
+ while ((e = av_dict_iterate(p->opts, e))) {
+ int ret = filter_opt_apply(p->filter, e->key, e->value);
+ if (ret < 0)
+ return ret;
+ }
+
+ av_dict_free(&p->opts);
+ }
+ }
+
+ return 0;
+}
+
+static int graph_parse(AVFilterGraph *graph, const char *desc,
+ AVFilterInOut **inputs, AVFilterInOut **outputs,
+ AVBufferRef *hw_device)
+{
+ AVFilterGraphSegment *seg;
+ int ret;
+
+ *inputs = NULL;
+ *outputs = NULL;
+
+ ret = avfilter_graph_segment_parse(graph, desc, 0, &seg);
+ if (ret < 0)
+ return ret;
+
+ ret = avfilter_graph_segment_create_filters(seg, 0);
+ if (ret < 0)
+ goto fail;
+
+ if (hw_device) {
+ for (int i = 0; i < graph->nb_filters; i++) {
+ AVFilterContext *f = graph->filters[i];
+
+ if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE))
+ continue;
+ f->hw_device_ctx = av_buffer_ref(hw_device);
+ if (!f->hw_device_ctx) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ }
+ }
+
+ ret = graph_opts_apply(seg);
+ if (ret < 0)
+ goto fail;
+
+ ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs);
+
+fail:
+ avfilter_graph_segment_free(&seg);
+ return ret;
+}
+
+static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in)
+{
+ AVFilterContext *ctx = inout->filter_ctx;
+ AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads;
+ int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs;
+ char *res;
+
+ if (nb_pads > 1)
+ res = av_strdup(ctx->filter->name);
+ else
+ res = av_asprintf("%s:%s", ctx->filter->name,
+ avfilter_pad_get_name(pads, inout->pad_idx));
+ if (!res)
+ report_and_exit(AVERROR(ENOMEM));
+ return res;
+}
+
static OutputFilter *ofilter_alloc(FilterGraph *fg)
{
OutputFilter *ofilter;
@@ -395,23 +582,6 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
return 0;
}
-static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in)
-{
- AVFilterContext *ctx = inout->filter_ctx;
- AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads;
- int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs;
- char *res;
-
- if (nb_pads > 1)
- res = av_strdup(ctx->filter->name);
- else
- res = av_asprintf("%s:%s", ctx->filter->name,
- avfilter_pad_get_name(pads, inout->pad_idx));
- if (!res)
- report_and_exit(AVERROR(ENOMEM));
- return res;
-}
-
static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
{
FilterGraphPriv *fgp = fgp_from_fg(fg);
@@ -480,176 +650,6 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
}
}
-static int read_binary(const char *path, uint8_t **data, int *len)
-{
- AVIOContext *io = NULL;
- int64_t fsize;
- int ret;
-
- *data = NULL;
- *len = 0;
-
- ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL);
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s': %s\n",
- path, av_err2str(ret));
- return ret;
- }
-
- fsize = avio_size(io);
- if (fsize < 0 || fsize > INT_MAX) {
- av_log(NULL, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path);
- ret = AVERROR(EIO);
- goto fail;
- }
-
- *data = av_malloc(fsize);
- if (!*data) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- ret = avio_read(io, *data, fsize);
- if (ret != fsize) {
- av_log(NULL, AV_LOG_ERROR, "Error reading file %s\n", path);
- ret = ret < 0 ? ret : AVERROR(EIO);
- goto fail;
- }
-
- *len = fsize;
-
- ret = 0;
-fail:
- avio_close(io);
- if (ret < 0) {
- av_freep(data);
- *len = 0;
- }
- return ret;
-}
-
-static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val)
-{
- const AVOption *o = NULL;
- int ret;
-
- ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN);
- if (ret >= 0)
- return 0;
-
- if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/')
- o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN);
- if (!o)
- goto err_apply;
-
- // key is a valid option name prefixed with '/'
- // interpret value as a path from which to load the actual option value
- key++;
-
- if (o->type == AV_OPT_TYPE_BINARY) {
- uint8_t *data;
- int len;
-
- ret = read_binary(val, &data, &len);
- if (ret < 0)
- goto err_load;
-
- ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN);
- av_freep(&data);
- } else {
- char *data = file_read(val);
- if (!data) {
- ret = AVERROR(EIO);
- goto err_load;
- }
-
- ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN);
- av_freep(&data);
- }
- if (ret < 0)
- goto err_apply;
-
- return 0;
-
-err_apply:
- av_log(NULL, AV_LOG_ERROR,
- "Error applying option '%s' to filter '%s': %s\n",
- key, f->filter->name, av_err2str(ret));
- return ret;
-err_load:
- av_log(NULL, AV_LOG_ERROR,
- "Error loading value for option '%s' from file '%s'\n",
- key, val);
- return ret;
-}
-
-static int graph_opts_apply(AVFilterGraphSegment *seg)
-{
- for (size_t i = 0; i < seg->nb_chains; i++) {
- AVFilterChain *ch = seg->chains[i];
-
- for (size_t j = 0; j < ch->nb_filters; j++) {
- AVFilterParams *p = ch->filters[j];
- const AVDictionaryEntry *e = NULL;
-
- av_assert0(p->filter);
-
- while ((e = av_dict_iterate(p->opts, e))) {
- int ret = filter_opt_apply(p->filter, e->key, e->value);
- if (ret < 0)
- return ret;
- }
-
- av_dict_free(&p->opts);
- }
- }
-
- return 0;
-}
-
-static int graph_parse(AVFilterGraph *graph, const char *desc,
- AVFilterInOut **inputs, AVFilterInOut **outputs,
- AVBufferRef *hw_device)
-{
- AVFilterGraphSegment *seg;
- int ret;
-
- *inputs = NULL;
- *outputs = NULL;
-
- ret = avfilter_graph_segment_parse(graph, desc, 0, &seg);
- if (ret < 0)
- return ret;
-
- ret = avfilter_graph_segment_create_filters(seg, 0);
- if (ret < 0)
- goto fail;
-
- if (hw_device) {
- for (int i = 0; i < graph->nb_filters; i++) {
- AVFilterContext *f = graph->filters[i];
-
- if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE))
- continue;
- f->hw_device_ctx = av_buffer_ref(hw_device);
- if (!f->hw_device_ctx) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
- }
- }
-
- ret = graph_opts_apply(seg);
- if (ret < 0)
- goto fail;
-
- ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs);
-
-fail:
- avfilter_graph_segment_free(&seg);
- return ret;
-}
-
int init_complex_filtergraph(FilterGraph *fg)
{
FilterGraphPriv *fgp = fgp_from_fg(fg);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 08/24] fftools/ffmpeg_filter: create Input/OutputFilters together with FilterGraph
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (5 preceding siblings ...)
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 07/24] fftools/ffmpeg_filter: move some functions higher up Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 09/24] fftools/ffmpeg_filter: factor out binding an output stream to OutputFilter Anton Khirnov
` (15 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
This way the list of filtergraph inputs/outputs is always known after
FilterGraph creation. This will allow treating simple and complex
filtergraphs in a more uniform manner.
---
fftools/ffmpeg_filter.c | 157 +++++++++++++++++++---------------------
1 file changed, 74 insertions(+), 83 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 5169a3ca82..d74eeef52a 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -62,6 +62,10 @@ typedef struct InputFilterPriv {
// used to hold submitted input
AVFrame *frame;
+ /* for filters that are not yet bound to an input stream,
+ * this stores the input linklabel, if any */
+ uint8_t *linklabel;
+
// filter data type
enum AVMediaType type;
// source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
@@ -456,8 +460,6 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist)
ifp->ist = ist;
ifp->type_src = ist->st->codecpar->codec_type;
- ifp->type = ifp->type_src == AVMEDIA_TYPE_SUBTITLE ?
- AVMEDIA_TYPE_VIDEO : ifp->type_src;
return 0;
}
@@ -505,7 +507,7 @@ void fg_free(FilterGraph **pfg)
av_frame_free(&frame);
av_fifo_freep2(&ifp->frame_queue);
}
- if (ist->sub2video.sub_queue) {
+ if (ist && ist->sub2video.sub_queue) {
AVSubtitle sub;
while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0)
avsubtitle_free(&sub);
@@ -517,6 +519,7 @@ void fg_free(FilterGraph **pfg)
av_frame_free(&ifp->frame);
av_buffer_unref(&ifp->hw_frames_ctx);
+ av_freep(&ifp->linklabel);
av_freep(&ifilter->name);
av_freep(&fg->inputs[j]);
}
@@ -542,6 +545,10 @@ FilterGraph *fg_create(char *graph_desc)
FilterGraphPriv *fgp = allocate_array_elem(&filtergraphs, sizeof(*fgp), &nb_filtergraphs);
FilterGraph *fg = &fgp->fg;
+ AVFilterInOut *inputs, *outputs;
+ AVFilterGraph *graph;
+ int ret = 0;
+
fg->index = nb_filtergraphs - 1;
fgp->graph_desc = graph_desc;
@@ -549,6 +556,48 @@ FilterGraph *fg_create(char *graph_desc)
if (!fgp->frame)
report_and_exit(AVERROR(ENOMEM));
+ /* this graph is only used for determining the kinds of inputs
+ * and outputs we have, and is discarded on exit from this function */
+ graph = avfilter_graph_alloc();
+ if (!graph)
+ report_and_exit(AVERROR(ENOMEM));
+ graph->nb_threads = 1;
+
+ ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, NULL);
+ if (ret < 0)
+ goto fail;
+
+ for (AVFilterInOut *cur = inputs; cur; cur = cur->next) {
+ InputFilter *const ifilter = ifilter_alloc(fg);
+ InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
+
+ ifp->linklabel = cur->name;
+ cur->name = NULL;
+
+ ifp->type = avfilter_pad_get_type(cur->filter_ctx->input_pads,
+ cur->pad_idx);
+ ifilter->name = describe_filter_link(fg, cur, 1);
+ }
+
+ for (AVFilterInOut *cur = outputs; cur; cur = cur->next) {
+ OutputFilter *const ofilter = ofilter_alloc(fg);
+
+ 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);
+ }
+
+fail:
+ avfilter_inout_free(&inputs);
+ avfilter_inout_free(&outputs);
+ avfilter_graph_free(&graph);
+
+ if (ret < 0)
+ report_and_exit(ret);
+
return fg;
}
@@ -557,8 +606,6 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
{
FilterGraph *fg;
FilterGraphPriv *fgp;
- OutputFilter *ofilter;
- InputFilter *ifilter;
int ret;
fg = fg_create(graph_desc);
@@ -568,26 +615,32 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
fgp->is_simple = 1;
- ofilter = ofilter_alloc(fg);
- ofilter->ost = ost;
+ if (fg->nb_inputs != 1 || fg->nb_outputs != 1) {
+ av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected "
+ "to have exactly 1 input and 1 output. "
+ "However, it had %d input(s) and %d output(s). Please adjust, "
+ "or use a complex filtergraph (-filter_complex) instead.\n",
+ graph_desc, fg->nb_inputs, fg->nb_outputs);
+ return AVERROR(EINVAL);
+ }
- ost->filter = ofilter;
+ fg->outputs[0]->ost = ost;
- ifilter = ifilter_alloc(fg);
+ ost->filter = fg->outputs[0];
- ret = ifilter_bind_ist(ifilter, ist);
+ ret = ifilter_bind_ist(fg->inputs[0], ist);
if (ret < 0)
return ret;
return 0;
}
-static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
+static void init_input_filter(FilterGraph *fg, InputFilter *ifilter)
{
FilterGraphPriv *fgp = fgp_from_fg(fg);
+ InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
InputStream *ist = NULL;
- enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx);
- InputFilter *ifilter;
+ enum AVMediaType type = ifp->type;
int i, ret;
// TODO: support other filter types
@@ -597,11 +650,11 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
exit_program(1);
}
- if (in->name) {
+ if (ifp->linklabel) {
AVFormatContext *s;
AVStream *st = NULL;
char *p;
- int file_idx = strtol(in->name, &p, 0);
+ int file_idx = strtol(ifp->linklabel, &p, 0);
if (file_idx < 0 || file_idx >= nb_input_files) {
av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n",
@@ -631,63 +684,27 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
ist = ist_find_unused(type);
if (!ist) {
av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
- "unlabeled input pad %d on filter %s\n", in->pad_idx,
- in->filter_ctx->name);
+ "unlabeled input pad %s\n", ifilter->name);
exit_program(1);
}
}
av_assert0(ist);
- ifilter = ifilter_alloc(fg);
- ifilter->name = describe_filter_link(fg, in, 1);
-
ret = ifilter_bind_ist(ifilter, ist);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR,
"Error binding an input stream to complex filtergraph input %s.\n",
- in->name ? in->name : "");
+ ifilter->name);
exit_program(1);
}
}
int init_complex_filtergraph(FilterGraph *fg)
{
- FilterGraphPriv *fgp = fgp_from_fg(fg);
- AVFilterInOut *inputs, *outputs, *cur;
- AVFilterGraph *graph;
- int ret = 0;
-
- /* this graph is only used for determining the kinds of inputs
- * and outputs we have, and is discarded on exit from this function */
- graph = avfilter_graph_alloc();
- if (!graph)
- return AVERROR(ENOMEM);
- graph->nb_threads = 1;
-
- ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, NULL);
- if (ret < 0)
- goto fail;
-
- for (cur = inputs; cur; cur = cur->next)
- init_input_filter(fg, cur);
-
- for (cur = outputs; cur;) {
- OutputFilter *const ofilter = ofilter_alloc(fg);
-
- 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);
- cur = cur->next;
- }
-
-fail:
- avfilter_inout_free(&inputs);
- avfilter_inout_free(&outputs);
- avfilter_graph_free(&graph);
- return ret;
+ // bind filtergraph inputs to input streams
+ for (int i = 0; i < fg->nb_inputs; i++)
+ init_input_filter(fg, fg->inputs[i]);
+ return 0;
}
static int insert_trim(int64_t start_time, int64_t duration,
@@ -1324,32 +1341,6 @@ int configure_filtergraph(FilterGraph *fg)
if ((ret = graph_parse(fg->graph, graph_desc, &inputs, &outputs, hw_device)) < 0)
goto fail;
- if (simple && (!inputs || inputs->next || !outputs || outputs->next)) {
- const char *num_inputs;
- const char *num_outputs;
- if (!outputs) {
- num_outputs = "0";
- } else if (outputs->next) {
- num_outputs = ">1";
- } else {
- num_outputs = "1";
- }
- if (!inputs) {
- num_inputs = "0";
- } else if (inputs->next) {
- num_inputs = ">1";
- } else {
- num_inputs = "1";
- }
- av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected "
- "to have exactly 1 input and 1 output."
- " However, it had %s input(s) and %s output(s)."
- " Please adjust, or use a complex filtergraph (-filter_complex) instead.\n",
- graph_desc, num_inputs, num_outputs);
- ret = AVERROR(EINVAL);
- goto fail;
- }
-
for (cur = inputs, i = 0; cur; cur = cur->next, i++)
if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) {
avfilter_inout_free(&inputs);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 09/24] fftools/ffmpeg_filter: factor out binding an output stream to OutputFilter
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (6 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 08/24] fftools/ffmpeg_filter: create Input/OutputFilters together with FilterGraph Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 10/24] fftools/ffmpeg_mux_init: move OutputFilter setup code to ffmpeg_filter Anton Khirnov
` (14 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
While the new function is trivial for now, it will become more useful in
future commits.
---
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_filter.c | 10 ++++++++--
fftools/ffmpeg_mux_init.c | 3 +--
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 3aa19c7f5f..8c149f1f95 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -756,6 +756,8 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec)
int ifilter_has_all_input_formats(FilterGraph *fg);
+void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost);
+
/**
* Create a new filtergraph in the global filtergraph list.
*
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index d74eeef52a..5f77f1e00f 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -464,6 +464,12 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist)
return 0;
}
+void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost)
+{
+ ofilter->ost = ost;
+ av_freep(&ofilter->linklabel);
+}
+
static InputFilter *ifilter_alloc(FilterGraph *fg)
{
InputFilterPriv *ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp),
@@ -624,14 +630,14 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
return AVERROR(EINVAL);
}
- fg->outputs[0]->ost = ost;
-
ost->filter = fg->outputs[0];
ret = ifilter_bind_ist(fg->inputs[0], ist);
if (ret < 0)
return ret;
+ ofilter_bind_ost(fg->outputs[0], ost);
+
return 0;
}
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index f7a24feec7..99708b9621 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1259,8 +1259,7 @@ static OutputStream *ost_add(Muxer *mux, const OptionsContext *o,
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
if (ofilter) {
ost->filter = ofilter;
- ofilter->ost = ost;
- av_freep(&ofilter->linklabel);
+ ofilter_bind_ost(ofilter, ost);
} else {
ret = init_simple_filtergraph(ost->ist, ost, filters);
if (ret < 0) {
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 10/24] fftools/ffmpeg_mux_init: move OutputFilter setup code to ffmpeg_filter
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (7 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 09/24] fftools/ffmpeg_filter: factor out binding an output stream to OutputFilter Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 11/24] fftools/ffmpeg_filter: try to configure filtergraphs earlier Anton Khirnov
` (13 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
That is a more appropriate place for it.
---
fftools/ffmpeg_filter.c | 70 +++++++++++++++++++++++++++++++++++
fftools/ffmpeg_mux_init.c | 77 ---------------------------------------
2 files changed, 70 insertions(+), 77 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 5f77f1e00f..3f6b906468 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -464,10 +464,80 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist)
return 0;
}
+static void set_channel_layout(OutputFilter *f, OutputStream *ost)
+{
+ const AVCodec *c = ost->enc_ctx->codec;
+ int i, err;
+
+ if (ost->enc_ctx->ch_layout.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);
+ if (err < 0)
+ report_and_exit(AVERROR(ENOMEM));
+ return;
+ }
+
+ /* Requested layout is of order UNSPEC */
+ if (!c->ch_layouts) {
+ /* 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);
+ return;
+ }
+ /* 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)
+ break;
+ }
+ if (c->ch_layouts[i].nb_channels) {
+ /* Use it if one is found */
+ err = av_channel_layout_copy(&f->ch_layout, &c->ch_layouts[i]);
+ if (err < 0)
+ report_and_exit(AVERROR(ENOMEM));
+ return;
+ }
+ /* 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);
+}
+
void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost)
{
+ const AVCodec *c = ost->enc_ctx->codec;
+
ofilter->ost = ost;
av_freep(&ofilter->linklabel);
+
+ switch (ost->enc_ctx->codec_type) {
+ case AVMEDIA_TYPE_VIDEO:
+ ofilter->frame_rate = ost->frame_rate;
+ ofilter->width = ost->enc_ctx->width;
+ ofilter->height = ost->enc_ctx->height;
+ if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
+ ofilter->format = ost->enc_ctx->pix_fmt;
+ } else {
+ ofilter->formats = c->pix_fmts;
+ }
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) {
+ ofilter->format = ost->enc_ctx->sample_fmt;
+ } else {
+ ofilter->formats = c->sample_fmts;
+ }
+ if (ost->enc_ctx->sample_rate) {
+ ofilter->sample_rate = ost->enc_ctx->sample_rate;
+ } else {
+ ofilter->sample_rates = c->supported_samplerates;
+ }
+ if (ost->enc_ctx->ch_layout.nb_channels) {
+ set_channel_layout(ofilter, ost);
+ } else if (c->ch_layouts) {
+ ofilter->ch_layouts = c->ch_layouts;
+ }
+ break;
+ }
}
static InputFilter *ifilter_alloc(FilterGraph *fg)
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 99708b9621..4fc6f0fb46 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -1886,44 +1886,6 @@ static void of_add_metadata(OutputFile *of, AVFormatContext *oc,
}
}
-static void set_channel_layout(OutputFilter *f, OutputStream *ost)
-{
- const AVCodec *c = ost->enc_ctx->codec;
- int i, err;
-
- if (ost->enc_ctx->ch_layout.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);
- if (err < 0)
- report_and_exit(AVERROR(ENOMEM));
- return;
- }
-
- /* Requested layout is of order UNSPEC */
- if (!c->ch_layouts) {
- /* 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);
- return;
- }
- /* 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)
- break;
- }
- if (c->ch_layouts[i].nb_channels) {
- /* Use it if one is found */
- err = av_channel_layout_copy(&f->ch_layout, &c->ch_layouts[i]);
- if (err < 0)
- report_and_exit(AVERROR(ENOMEM));
- return;
- }
- /* 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);
-}
-
static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os,
int copy_metadata)
{
@@ -2458,45 +2420,6 @@ int of_open(const OptionsContext *o, const char *filename)
/* check if all codec options have been used */
validate_enc_avopt(mux, o->g->codec_opts);
- for (int i = 0; i < of->nb_streams; i++) {
- OutputStream *ost = of->streams[i];
-
- /* set the filter output constraints */
- if (ost->filter) {
- const AVCodec *c = ost->enc_ctx->codec;
- OutputFilter *f = ost->filter;
- switch (ost->enc_ctx->codec_type) {
- case AVMEDIA_TYPE_VIDEO:
- f->frame_rate = ost->frame_rate;
- f->width = ost->enc_ctx->width;
- f->height = ost->enc_ctx->height;
- if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
- f->format = ost->enc_ctx->pix_fmt;
- } else {
- f->formats = c->pix_fmts;
- }
- break;
- case AVMEDIA_TYPE_AUDIO:
- if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) {
- f->format = ost->enc_ctx->sample_fmt;
- } else {
- f->formats = c->sample_fmts;
- }
- if (ost->enc_ctx->sample_rate) {
- f->sample_rate = ost->enc_ctx->sample_rate;
- } else {
- f->sample_rates = c->supported_samplerates;
- }
- if (ost->enc_ctx->ch_layout.nb_channels) {
- set_channel_layout(f, ost);
- } else if (c->ch_layouts) {
- f->ch_layouts = c->ch_layouts;
- }
- break;
- }
- }
- }
-
/* check filename in case of an image number is expected */
if (oc->oformat->flags & AVFMT_NEEDNUMBER && !av_filename_number_test(oc->url)) {
av_log(mux, AV_LOG_FATAL,
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 11/24] fftools/ffmpeg_filter: try to configure filtergraphs earlier
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (8 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 10/24] fftools/ffmpeg_mux_init: move OutputFilter setup code to ffmpeg_filter Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 12/24] fftools/ffmpeg: constify AVSubtitle parameters as appropriate Anton Khirnov
` (12 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
When the filtergraph has no inputs, it can be configured immediately
when all its outputs are bound to output streams. This will simplify
treating some corner cases.
---
fftools/ffmpeg_filter.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 3f6b906468..3bf1862ab6 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -504,6 +504,7 @@ static void set_channel_layout(OutputFilter *f, OutputStream *ost)
void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost)
{
+ FilterGraph *fg = ofilter->graph;
const AVCodec *c = ost->enc_ctx->codec;
ofilter->ost = ost;
@@ -538,6 +539,23 @@ void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost)
}
break;
}
+
+ // if we have all input parameters and all outputs are bound,
+ // the graph can now be configured
+ if (ifilter_has_all_input_formats(fg)) {
+ int ret;
+
+ for (int i = 0; i < fg->nb_outputs; i++)
+ if (!fg->outputs[i]->ost)
+ return;
+
+ ret = configure_filtergraph(fg);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error configuring filter graph: %s\n",
+ av_err2str(ret));
+ exit_program(1);
+ }
+ }
}
static InputFilter *ifilter_alloc(FilterGraph *fg)
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 12/24] fftools/ffmpeg: constify AVSubtitle parameters as appropriate
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (9 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 11/24] fftools/ffmpeg_filter: try to configure filtergraphs earlier Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 13/24] fftools/ffmpeg_dec: move sub2video submission to ffmpeg_filter Anton Khirnov
` (11 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 5 +++--
fftools/ffmpeg.h | 3 ++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 0539a45856..9c68add0a4 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -211,7 +211,8 @@ static void sub2video_push_ref(InputStream *ist, int64_t pts)
}
}
-void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub)
+void sub2video_update(InputStream *ist, int64_t heartbeat_pts,
+ const AVSubtitle *sub)
{
AVFrame *frame = ist->sub2video.frame;
int8_t *dst;
@@ -754,7 +755,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
first_report = 0;
}
-static int copy_av_subtitle(AVSubtitle *dst, AVSubtitle *src)
+static int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src)
{
int ret = AVERROR_BUG;
AVSubtitle tmp = {
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 8c149f1f95..451d18db6f 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -742,7 +742,8 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
char *graph_desc);
int init_complex_filtergraph(FilterGraph *fg);
-void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub);
+void sub2video_update(InputStream *ist, int64_t heartbeat_pts,
+ const AVSubtitle *sub);
int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference);
int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 13/24] fftools/ffmpeg_dec: move sub2video submission to ffmpeg_filter
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (10 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 12/24] fftools/ffmpeg: constify AVSubtitle parameters as appropriate Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 14/24] fftools/ffmpeg_filter: move sub2video subtitle queue to InputFilterPriv Anton Khirnov
` (10 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
This code is analogous to ifilter_send_frame() for normal video frame,
so it properly belongs to the filtering code.
Note that using sub2video with more than one target for a given input
subtitle stream is currently broken and this commit does not change
that. It will be addressed in following commits.
---
fftools/ffmpeg.c | 2 +-
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_dec.c | 23 ++++++++---------------
fftools/ffmpeg_filter.c | 30 ++++++++++++++++++++++++++++++
4 files changed, 41 insertions(+), 16 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 9c68add0a4..9ee16ee8e0 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -755,7 +755,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
first_report = 0;
}
-static int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src)
+int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src)
{
int ret = AVERROR_BUG;
AVSubtitle tmp = {
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 451d18db6f..fa5824ee7b 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -744,9 +744,11 @@ int init_complex_filtergraph(FilterGraph *fg);
void sub2video_update(InputStream *ist, int64_t heartbeat_pts,
const AVSubtitle *sub);
+int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src);
int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference);
int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb);
+int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *sub);
/**
* Set up fallback filtering parameters from a decoder context. They will only
diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c
index c89630512a..a7acaf67c2 100644
--- a/fftools/ffmpeg_dec.c
+++ b/fftools/ffmpeg_dec.c
@@ -336,7 +336,6 @@ static void sub2video_flush(InputStream *ist)
int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output)
{
int ret = 0;
- int free_sub = 1;
if (ist->fix_sub_duration) {
int end = 1;
@@ -361,18 +360,13 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output)
if (!*got_output)
return ret;
- if (ist->sub2video.frame) {
- sub2video_update(ist, INT64_MIN, subtitle);
- } else if (ist->nb_filters) {
- if (!ist->sub2video.sub_queue)
- ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW);
- if (!ist->sub2video.sub_queue)
- report_and_exit(AVERROR(ENOMEM));
-
- ret = av_fifo_write(ist->sub2video.sub_queue, subtitle, 1);
- if (ret < 0)
- exit_program(1);
- free_sub = 0;
+ for (int i = 0; i < ist->nb_filters; i++) {
+ ret = ifilter_sub2video(ist->filters[i], subtitle);
+ if (ret < 0) {
+ av_log(ist, AV_LOG_ERROR, "Error sending a subtitle for filtering: %s\n",
+ av_err2str(ret));
+ goto out;
+ }
}
if (!subtitle->num_rects)
@@ -387,8 +381,7 @@ int process_subtitle(InputStream *ist, AVSubtitle *subtitle, int *got_output)
}
out:
- if (free_sub)
- avsubtitle_free(subtitle);
+ avsubtitle_free(subtitle);
return ret;
}
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 3bf1862ab6..acfd83244b 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1638,6 +1638,36 @@ int reap_filters(int flush)
return 0;
}
+int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle)
+{
+ InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
+ InputStream *ist = ifp->ist;
+ int ret;
+
+ if (ist->sub2video.frame) {
+ sub2video_update(ist, INT64_MIN, subtitle);
+ } else {
+ AVSubtitle sub;
+
+ if (!ist->sub2video.sub_queue)
+ ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW);
+ if (!ist->sub2video.sub_queue)
+ return AVERROR(ENOMEM);
+
+ ret = copy_av_subtitle(&sub, subtitle);
+ if (ret < 0)
+ return ret;
+
+ ret = av_fifo_write(ist->sub2video.sub_queue, &sub, 1);
+ if (ret < 0) {
+ avsubtitle_free(&sub);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb)
{
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 14/24] fftools/ffmpeg_filter: move sub2video subtitle queue to InputFilterPriv
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (11 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 13/24] fftools/ffmpeg_dec: move sub2video submission to ffmpeg_filter Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 15/24] fftools/ffmpeg: tweak sub2video_heartbeat() arguments Anton Khirnov
` (9 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
This queue should be associated with a specific filtergraph input - if
a subtitle stream is sent to multiple filters then each should have its
own queue.
---
fftools/ffmpeg.h | 1 -
fftools/ffmpeg_filter.c | 26 +++++++++++++++-----------
2 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index fa5824ee7b..d4aff5cc7c 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -374,7 +374,6 @@ typedef struct InputStream {
struct sub2video {
int64_t last_pts;
int64_t end_pts;
- AVFifo *sub_queue; ///< queue of AVSubtitle* before filter init
AVFrame *frame;
int w, h;
unsigned int initialize; ///< marks if sub2video_update should force an initialization
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index acfd83244b..2a73e3a3e3 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -104,6 +104,10 @@ typedef struct InputFilterPriv {
AVChannelLayout ch_layout;
} fallback;
+ struct {
+ ///< queue of AVSubtitle* before filter init
+ AVFifo *queue;
+ } sub2video;
} InputFilterPriv;
static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter)
@@ -593,7 +597,6 @@ void fg_free(FilterGraph **pfg)
for (int j = 0; j < fg->nb_inputs; j++) {
InputFilter *ifilter = fg->inputs[j];
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
- InputStream *ist = ifp->ist;
if (ifp->frame_queue) {
AVFrame *frame;
@@ -601,11 +604,11 @@ void fg_free(FilterGraph **pfg)
av_frame_free(&frame);
av_fifo_freep2(&ifp->frame_queue);
}
- if (ist && ist->sub2video.sub_queue) {
+ if (ifp->sub2video.queue) {
AVSubtitle sub;
- while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0)
+ while (av_fifo_read(ifp->sub2video.queue, &sub, 1) >= 0)
avsubtitle_free(&sub);
- av_fifo_freep2(&ist->sub2video.sub_queue);
+ av_fifo_freep2(&ifp->sub2video.queue);
}
av_channel_layout_uninit(&ifp->fallback.ch_layout);
@@ -1495,10 +1498,11 @@ int configure_filtergraph(FilterGraph *fg)
/* process queued up subtitle packets */
for (i = 0; i < fg->nb_inputs; i++) {
- InputStream *ist = ifp_from_ifilter(fg->inputs[i])->ist;
- if (ist->sub2video.sub_queue && ist->sub2video.frame) {
+ InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
+ InputStream *ist = ifp->ist;
+ if (ifp->sub2video.queue && ist->sub2video.frame) {
AVSubtitle tmp;
- while (av_fifo_read(ist->sub2video.sub_queue, &tmp, 1) >= 0) {
+ while (av_fifo_read(ifp->sub2video.queue, &tmp, 1) >= 0) {
sub2video_update(ist, INT64_MIN, &tmp);
avsubtitle_free(&tmp);
}
@@ -1649,16 +1653,16 @@ int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle)
} else {
AVSubtitle sub;
- if (!ist->sub2video.sub_queue)
- ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW);
- if (!ist->sub2video.sub_queue)
+ if (!ifp->sub2video.queue)
+ ifp->sub2video.queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW);
+ if (!ifp->sub2video.queue)
return AVERROR(ENOMEM);
ret = copy_av_subtitle(&sub, subtitle);
if (ret < 0)
return ret;
- ret = av_fifo_write(ist->sub2video.sub_queue, &sub, 1);
+ ret = av_fifo_write(ifp->sub2video.queue, &sub, 1);
if (ret < 0) {
avsubtitle_free(&sub);
return ret;
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 15/24] fftools/ffmpeg: tweak sub2video_heartbeat() arguments
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (12 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 14/24] fftools/ffmpeg_filter: move sub2video subtitle queue to InputFilterPriv Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 16/24] fftools/ffmpeg: rework setting sub2video parameters Anton Khirnov
` (8 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
This function should not take an InputStream, as it only uses it to get
the InputFile and the timebase. Pass those directly instead and avoid
confusion over dealing with multiple InputStreams.
---
fftools/ffmpeg.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 9ee16ee8e0..4624960c17 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -252,9 +252,8 @@ void sub2video_update(InputStream *ist, int64_t heartbeat_pts,
ist->sub2video.initialize = 0;
}
-static void sub2video_heartbeat(InputStream *ist, int64_t pts)
+static void sub2video_heartbeat(InputFile *infile, int64_t pts, AVRational tb)
{
- InputFile *infile = input_files[ist->file_index];
int i, j, nb_reqs;
int64_t pts2;
@@ -268,7 +267,7 @@ static void sub2video_heartbeat(InputStream *ist, int64_t pts)
continue;
/* subtitles seem to be usually muxed ahead of other streams;
if not, subtracting a larger time here is necessary */
- pts2 = av_rescale_q(pts, ist->st->time_base, ist2->st->time_base) - 1;
+ pts2 = av_rescale_q(pts, tb, ist2->st->time_base) - 1;
/* do not send the heartbeat frame if the subtitle is already ahead */
if (pts2 <= ist2->sub2video.last_pts)
continue;
@@ -1231,7 +1230,7 @@ static int process_input(int file_index)
ist = ifile->streams[pkt->stream_index];
- sub2video_heartbeat(ist, pkt->pts);
+ sub2video_heartbeat(ifile, pkt->pts, pkt->time_base);
process_input_packet(ist, pkt, 0);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 16/24] fftools/ffmpeg: rework setting sub2video parameters
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (13 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 15/24] fftools/ffmpeg: tweak sub2video_heartbeat() arguments Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 19:43 ` Michael Niedermayer
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 17/24] fftools/ffmpeg: move sub2video handling to ffmpeg_filter Anton Khirnov
` (7 subsequent siblings)
22 siblings, 1 reply; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
Set them in ifilter_parameters_from_dec(), similarly to audio/video
streams. This reduces the extent to which sub2video filters need to be
treated specially.
---
fftools/ffmpeg.c | 6 ++---
fftools/ffmpeg_demux.c | 21 +++++++++++++++++
fftools/ffmpeg_filter.c | 52 +++++++++++------------------------------
3 files changed, 38 insertions(+), 41 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 4624960c17..e9e60407d2 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -153,9 +153,9 @@ static int sub2video_get_blank_frame(InputStream *ist)
AVFrame *frame = ist->sub2video.frame;
av_frame_unref(frame);
- ist->sub2video.frame->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w;
- ist->sub2video.frame->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h;
- ist->sub2video.frame->format = AV_PIX_FMT_RGB32;
+ frame->width = ist->sub2video.w;
+ frame->height = ist->sub2video.h;
+ frame->format = AV_PIX_FMT_RGB32;
if ((ret = av_frame_get_buffer(frame, 0)) < 0)
return ret;
memset(frame->data[0], 0, frame->height * frame->linesize[0]);
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 561b4b0002..817ccbbedc 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -1228,6 +1228,27 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d)
av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
exit_program(1);
}
+
+ /* Compute the size of the canvas for the subtitles stream.
+ If the subtitles codecpar has set a size, use it. Otherwise use the
+ maximum dimensions of the video streams in the same file. */
+ ist->sub2video.w = ist->dec_ctx->width;
+ ist->sub2video.h = ist->dec_ctx->height;
+ if (!(ist->sub2video.w && ist->sub2video.h)) {
+ for (int j = 0; j < ic->nb_streams; j++) {
+ AVCodecParameters *par1 = ic->streams[j]->codecpar;
+ if (par1->codec_type == AVMEDIA_TYPE_VIDEO) {
+ ist->sub2video.w = FFMAX(ist->sub2video.w, par1->width);
+ ist->sub2video.h = FFMAX(ist->sub2video.h, par1->height);
+ }
+ }
+ }
+
+ if (!(ist->sub2video.w && ist->sub2video.h)) {
+ ist->sub2video.w = FFMAX(ist->sub2video.w, 720);
+ ist->sub2video.h = FFMAX(ist->sub2video.h, 576);
+ }
+
break;
}
case AVMEDIA_TYPE_ATTACHMENT:
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 2a73e3a3e3..670e697f69 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1110,38 +1110,6 @@ void check_filter_outputs(void)
static int sub2video_prepare(InputStream *ist, InputFilter *ifilter)
{
- InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
- AVFormatContext *avf = input_files[ist->file_index]->ctx;
- int i, w, h;
-
- /* Compute the size of the canvas for the subtitles stream.
- If the subtitles codecpar has set a size, use it. Otherwise use the
- maximum dimensions of the video streams in the same file. */
- w = ifp->width;
- h = ifp->height;
- if (!(w && h)) {
- for (i = 0; i < avf->nb_streams; i++) {
- if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
- w = FFMAX(w, avf->streams[i]->codecpar->width);
- h = FFMAX(h, avf->streams[i]->codecpar->height);
- }
- }
- if (!(w && h)) {
- w = FFMAX(w, 720);
- h = FFMAX(h, 576);
- }
- av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h);
- }
- ist->sub2video.w = ifp->width = w;
- ist->sub2video.h = ifp->height = h;
-
- ifp->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w;
- ifp->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h;
-
- /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the
- palettes for all rectangles are identical or compatible */
- ifp->format = AV_PIX_FMT_RGB32;
-
ist->sub2video.frame = av_frame_alloc();
if (!ist->sub2video.frame)
return AVERROR(ENOMEM);
@@ -1525,7 +1493,7 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec)
ifp->fallback.width = dec->width;
ifp->fallback.height = dec->height;
ifp->fallback.sample_aspect_ratio = dec->sample_aspect_ratio;
- } else {
+ } else if (dec->codec_type == AVMEDIA_TYPE_AUDIO) {
int ret;
ifp->fallback.format = dec->sample_fmt;
@@ -1534,6 +1502,17 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec)
ret = av_channel_layout_copy(&ifp->fallback.ch_layout, &dec->ch_layout);
if (ret < 0)
return ret;
+ } else {
+ // for subtitles (i.e. sub2video) we set the actual parameters,
+ // rather than just fallback
+ ifp->width = dec->width;
+ ifp->height = dec->height;
+
+ /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the
+ palettes for all rectangles are identical or compatible */
+ ifp->format = AV_PIX_FMT_RGB32;
+
+ av_log(NULL, AV_LOG_VERBOSE, "sub2video: using %dx%d canvas\n", ifp->width, ifp->height);
}
return 0;
@@ -1574,8 +1553,7 @@ int ifilter_has_all_input_formats(FilterGraph *fg)
int i;
for (i = 0; i < fg->nb_inputs; i++) {
InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
- if (ifp->format < 0 && (ifp->type_src == AVMEDIA_TYPE_AUDIO ||
- ifp->type_src == AVMEDIA_TYPE_VIDEO))
+ if (ifp->format < 0)
return 0;
}
return 1;
@@ -1709,9 +1687,7 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb)
}
}
- if (ifp->format < 0 &&
- (ifp->type_src == AVMEDIA_TYPE_AUDIO ||
- ifp->type_src == AVMEDIA_TYPE_VIDEO)) {
+ if (ifp->format < 0) {
av_log(NULL, AV_LOG_ERROR,
"Cannot determine format of input stream %d:%d after EOF\n",
ifp->ist->file_index, ifp->ist->index);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 17/24] fftools/ffmpeg: move sub2video handling to ffmpeg_filter
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (14 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 16/24] fftools/ffmpeg: rework setting sub2video parameters Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 18/24] fftools/ffmpeg_enc: stop configuring filters from encoder flush Anton Khirnov
` (6 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
Make all relevant state per-filtergraph input, rather than per-input
stream. Refactor the code to make it work and avoid leaking memory when
a single subtitle stream is sent to multiple filters.
---
fftools/ffmpeg.c | 133 ++--------------------------
fftools/ffmpeg.h | 7 +-
fftools/ffmpeg_dec.c | 9 +-
fftools/ffmpeg_demux.c | 1 -
fftools/ffmpeg_filter.c | 189 +++++++++++++++++++++++++++++++++++-----
5 files changed, 177 insertions(+), 162 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index e9e60407d2..36b4becaf2 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -147,139 +147,20 @@ static int restore_tty;
This is a temporary solution until libavfilter gets real subtitles support.
*/
-static int sub2video_get_blank_frame(InputStream *ist)
-{
- int ret;
- AVFrame *frame = ist->sub2video.frame;
-
- av_frame_unref(frame);
- frame->width = ist->sub2video.w;
- frame->height = ist->sub2video.h;
- frame->format = AV_PIX_FMT_RGB32;
- if ((ret = av_frame_get_buffer(frame, 0)) < 0)
- return ret;
- memset(frame->data[0], 0, frame->height * frame->linesize[0]);
- return 0;
-}
-
-static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h,
- AVSubtitleRect *r)
-{
- uint32_t *pal, *dst2;
- uint8_t *src, *src2;
- int x, y;
-
- if (r->type != SUBTITLE_BITMAP) {
- av_log(NULL, AV_LOG_WARNING, "sub2video: non-bitmap subtitle\n");
- return;
- }
- if (r->x < 0 || r->x + r->w > w || r->y < 0 || r->y + r->h > h) {
- av_log(NULL, AV_LOG_WARNING, "sub2video: rectangle (%d %d %d %d) overflowing %d %d\n",
- r->x, r->y, r->w, r->h, w, h
- );
- return;
- }
-
- dst += r->y * dst_linesize + r->x * 4;
- src = r->data[0];
- pal = (uint32_t *)r->data[1];
- for (y = 0; y < r->h; y++) {
- dst2 = (uint32_t *)dst;
- src2 = src;
- for (x = 0; x < r->w; x++)
- *(dst2++) = pal[*(src2++)];
- dst += dst_linesize;
- src += r->linesize[0];
- }
-}
-
-static void sub2video_push_ref(InputStream *ist, int64_t pts)
-{
- AVFrame *frame = ist->sub2video.frame;
- int i;
- int ret;
-
- av_assert1(frame->data[0]);
- ist->sub2video.last_pts = frame->pts = pts;
- for (i = 0; i < ist->nb_filters; i++) {
- ret = av_buffersrc_add_frame_flags(ist->filters[i]->filter, frame,
- AV_BUFFERSRC_FLAG_KEEP_REF |
- AV_BUFFERSRC_FLAG_PUSH);
- if (ret != AVERROR_EOF && ret < 0)
- av_log(NULL, AV_LOG_WARNING, "Error while add the frame to buffer source(%s).\n",
- av_err2str(ret));
- }
-}
-
-void sub2video_update(InputStream *ist, int64_t heartbeat_pts,
- const AVSubtitle *sub)
-{
- AVFrame *frame = ist->sub2video.frame;
- int8_t *dst;
- int dst_linesize;
- int num_rects, i;
- int64_t pts, end_pts;
-
- if (!frame)
- return;
- if (sub) {
- pts = av_rescale_q(sub->pts + sub->start_display_time * 1000LL,
- AV_TIME_BASE_Q, ist->st->time_base);
- end_pts = av_rescale_q(sub->pts + sub->end_display_time * 1000LL,
- AV_TIME_BASE_Q, ist->st->time_base);
- num_rects = sub->num_rects;
- } else {
- /* If we are initializing the system, utilize current heartbeat
- PTS as the start time, and show until the following subpicture
- is received. Otherwise, utilize the previous subpicture's end time
- as the fall-back value. */
- pts = ist->sub2video.initialize ?
- heartbeat_pts : ist->sub2video.end_pts;
- end_pts = INT64_MAX;
- num_rects = 0;
- }
- if (sub2video_get_blank_frame(ist) < 0) {
- av_log(NULL, AV_LOG_ERROR,
- "Impossible to get a blank canvas.\n");
- return;
- }
- dst = frame->data [0];
- dst_linesize = frame->linesize[0];
- for (i = 0; i < num_rects; i++)
- sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]);
- sub2video_push_ref(ist, pts);
- ist->sub2video.end_pts = end_pts;
- ist->sub2video.initialize = 0;
-}
-
static void sub2video_heartbeat(InputFile *infile, int64_t pts, AVRational tb)
{
- int i, j, nb_reqs;
- int64_t pts2;
-
/* When a frame is read from a file, examine all sub2video streams in
the same file and send the sub2video frame again. Otherwise, decoded
video frames could be accumulating in the filter graph while a filter
(possibly overlay) is desperately waiting for a subtitle frame. */
- for (i = 0; i < infile->nb_streams; i++) {
- InputStream *ist2 = infile->streams[i];
- if (!ist2->sub2video.frame)
- continue;
- /* subtitles seem to be usually muxed ahead of other streams;
- if not, subtracting a larger time here is necessary */
- pts2 = av_rescale_q(pts, tb, ist2->st->time_base) - 1;
- /* do not send the heartbeat frame if the subtitle is already ahead */
- if (pts2 <= ist2->sub2video.last_pts)
+ for (int i = 0; i < infile->nb_streams; i++) {
+ InputStream *ist = infile->streams[i];
+
+ if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_SUBTITLE)
continue;
- if (pts2 >= ist2->sub2video.end_pts || ist2->sub2video.initialize)
- /* if we have hit the end of the current displayed subpicture,
- or if we need to initialize the system, update the
- overlayed subpicture and its start/end times */
- sub2video_update(ist2, pts2 + 1, NULL);
- for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++)
- nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter);
- if (nb_reqs)
- sub2video_push_ref(ist2, pts2);
+
+ for (int j = 0; j < ist->nb_filters; j++)
+ ifilter_sub2video_heartbeat(ist->filters[j], pts, tb);
}
}
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index d4aff5cc7c..75695d3fb5 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -372,11 +372,7 @@ typedef struct InputStream {
} prev_sub;
struct sub2video {
- int64_t last_pts;
- int64_t end_pts;
- AVFrame *frame;
int w, h;
- unsigned int initialize; ///< marks if sub2video_update should force an initialization
} sub2video;
/* decoded data from this stream goes into all those filters
@@ -741,13 +737,12 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
char *graph_desc);
int init_complex_filtergraph(FilterGraph *fg);
-void sub2video_update(InputStream *ist, int64_t heartbeat_pts,
- const AVSubtitle *sub);
int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src);
int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference);
int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb);
int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *sub);
+void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb);
/**
* Set up fallback filtering parameters from a decoder context. They will only
diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c
index a7acaf67c2..30959c64b7 100644
--- a/fftools/ffmpeg_dec.c
+++ b/fftools/ffmpeg_dec.c
@@ -321,13 +321,8 @@ static int video_frame_process(InputStream *ist, AVFrame *frame)
static void sub2video_flush(InputStream *ist)
{
- int i;
- int ret;
-
- if (ist->sub2video.end_pts < INT64_MAX)
- sub2video_update(ist, INT64_MAX, NULL);
- for (i = 0; i < ist->nb_filters; i++) {
- ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
+ for (int i = 0; i < ist->nb_filters; i++) {
+ int ret = ifilter_sub2video(ist->filters[i], NULL);
if (ret != AVERROR_EOF && ret < 0)
av_log(NULL, AV_LOG_WARNING, "Flush the frame error.\n");
}
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 817ccbbedc..5c15b8bad3 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -817,7 +817,6 @@ static void ist_free(InputStream **pist)
av_dict_free(&ist->decoder_opts);
avsubtitle_free(&ist->prev_sub.subtitle);
- av_frame_free(&ist->sub2video.frame);
av_freep(&ist->filters);
av_freep(&ist->outputs);
av_freep(&ist->hwaccel_device);
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 670e697f69..ce2a914745 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -107,6 +107,14 @@ typedef struct InputFilterPriv {
struct {
///< queue of AVSubtitle* before filter init
AVFifo *queue;
+
+ AVFrame *frame;
+
+ int64_t last_pts;
+ int64_t end_pts;
+
+ ///< marks if sub2video_update should force an initialization
+ unsigned int initialize;
} sub2video;
} InputFilterPriv;
@@ -115,6 +123,111 @@ static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter)
return (InputFilterPriv*)ifilter;
}
+static int sub2video_get_blank_frame(InputFilterPriv *ifp)
+{
+ AVFrame *frame = ifp->sub2video.frame;
+ int ret;
+
+ av_frame_unref(frame);
+
+ frame->width = ifp->width;
+ frame->height = ifp->height;
+ frame->format = ifp->format;
+
+ ret = av_frame_get_buffer(frame, 0);
+ if (ret < 0)
+ return ret;
+
+ memset(frame->data[0], 0, frame->height * frame->linesize[0]);
+
+ return 0;
+}
+
+static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h,
+ AVSubtitleRect *r)
+{
+ uint32_t *pal, *dst2;
+ uint8_t *src, *src2;
+ int x, y;
+
+ if (r->type != SUBTITLE_BITMAP) {
+ av_log(NULL, AV_LOG_WARNING, "sub2video: non-bitmap subtitle\n");
+ return;
+ }
+ if (r->x < 0 || r->x + r->w > w || r->y < 0 || r->y + r->h > h) {
+ av_log(NULL, AV_LOG_WARNING, "sub2video: rectangle (%d %d %d %d) overflowing %d %d\n",
+ r->x, r->y, r->w, r->h, w, h
+ );
+ return;
+ }
+
+ dst += r->y * dst_linesize + r->x * 4;
+ src = r->data[0];
+ pal = (uint32_t *)r->data[1];
+ for (y = 0; y < r->h; y++) {
+ dst2 = (uint32_t *)dst;
+ src2 = src;
+ for (x = 0; x < r->w; x++)
+ *(dst2++) = pal[*(src2++)];
+ dst += dst_linesize;
+ src += r->linesize[0];
+ }
+}
+
+static void sub2video_push_ref(InputFilterPriv *ifp, int64_t pts)
+{
+ AVFrame *frame = ifp->sub2video.frame;
+ int ret;
+
+ av_assert1(frame->data[0]);
+ ifp->sub2video.last_pts = frame->pts = pts;
+ ret = av_buffersrc_add_frame_flags(ifp->ifilter.filter, frame,
+ AV_BUFFERSRC_FLAG_KEEP_REF |
+ AV_BUFFERSRC_FLAG_PUSH);
+ if (ret != AVERROR_EOF && ret < 0)
+ av_log(NULL, AV_LOG_WARNING, "Error while add the frame to buffer source(%s).\n",
+ av_err2str(ret));
+}
+
+static void sub2video_update(InputFilterPriv *ifp, int64_t heartbeat_pts,
+ const AVSubtitle *sub)
+{
+ AVFrame *frame = ifp->sub2video.frame;
+ int8_t *dst;
+ int dst_linesize;
+ int num_rects, i;
+ int64_t pts, end_pts;
+
+ if (sub) {
+ pts = av_rescale_q(sub->pts + sub->start_display_time * 1000LL,
+ AV_TIME_BASE_Q, ifp->time_base);
+ end_pts = av_rescale_q(sub->pts + sub->end_display_time * 1000LL,
+ AV_TIME_BASE_Q, ifp->time_base);
+ num_rects = sub->num_rects;
+ } else {
+ /* If we are initializing the system, utilize current heartbeat
+ PTS as the start time, and show until the following subpicture
+ is received. Otherwise, utilize the previous subpicture's end time
+ as the fall-back value. */
+ pts = ifp->sub2video.initialize ?
+ heartbeat_pts : ifp->sub2video.end_pts;
+ end_pts = INT64_MAX;
+ num_rects = 0;
+ }
+ if (sub2video_get_blank_frame(ifp) < 0) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Impossible to get a blank canvas.\n");
+ return;
+ }
+ dst = frame->data [0];
+ dst_linesize = frame->linesize[0];
+ for (i = 0; i < num_rects; i++)
+ sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]);
+ sub2video_push_ref(ifp, pts);
+ ifp->sub2video.end_pts = end_pts;
+ ifp->sub2video.initialize = 0;
+}
+
// FIXME: YUV420P etc. are actually supported with full color range,
// yet the latter information isn't available here.
static const enum AVPixelFormat *get_compliance_normal_pix_fmts(const AVCodec *codec, const enum AVPixelFormat default_formats[])
@@ -465,6 +578,12 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist)
ifp->ist = ist;
ifp->type_src = ist->st->codecpar->codec_type;
+ if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) {
+ ifp->sub2video.frame = av_frame_alloc();
+ if (!ifp->sub2video.frame)
+ return AVERROR(ENOMEM);
+ }
+
return 0;
}
@@ -610,6 +729,7 @@ void fg_free(FilterGraph **pfg)
avsubtitle_free(&sub);
av_fifo_freep2(&ifp->sub2video.queue);
}
+ av_frame_free(&ifp->sub2video.frame);
av_channel_layout_uninit(&ifp->fallback.ch_layout);
@@ -1108,20 +1228,15 @@ void check_filter_outputs(void)
}
}
-static int sub2video_prepare(InputStream *ist, InputFilter *ifilter)
+static void sub2video_prepare(InputFilterPriv *ifp)
{
- ist->sub2video.frame = av_frame_alloc();
- if (!ist->sub2video.frame)
- return AVERROR(ENOMEM);
- ist->sub2video.last_pts = INT64_MIN;
- ist->sub2video.end_pts = INT64_MIN;
+ ifp->sub2video.last_pts = INT64_MIN;
+ ifp->sub2video.end_pts = INT64_MIN;
/* sub2video structure has been (re-)initialized.
Mark it as such so that the system will be
initialized with the first received heartbeat. */
- ist->sub2video.initialize = 1;
-
- return 0;
+ ifp->sub2video.initialize = 1;
}
static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
@@ -1156,11 +1271,8 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
if (!fr.num)
fr = ist->framerate_guessed;
- if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
- ret = sub2video_prepare(ist, ifilter);
- if (ret < 0)
- goto fail;
- }
+ if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE)
+ sub2video_prepare(ifp);
ifp->time_base = ist->framerate.num ? av_inv_q(ist->framerate) :
ist->st->time_base;
@@ -1466,12 +1578,13 @@ int configure_filtergraph(FilterGraph *fg)
/* process queued up subtitle packets */
for (i = 0; i < fg->nb_inputs; i++) {
- InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
- InputStream *ist = ifp->ist;
- if (ifp->sub2video.queue && ist->sub2video.frame) {
+ InputFilter *ifilter = fg->inputs[i];
+ InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
+
+ if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE && ifp->sub2video.queue) {
AVSubtitle tmp;
while (av_fifo_read(ifp->sub2video.queue, &tmp, 1) >= 0) {
- sub2video_update(ist, INT64_MIN, &tmp);
+ sub2video_update(ifp, INT64_MIN, &tmp);
avsubtitle_free(&tmp);
}
}
@@ -1620,15 +1733,47 @@ int reap_filters(int flush)
return 0;
}
+void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb)
+{
+ InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
+ int64_t pts2;
+
+ if (!ifilter->graph->graph)
+ return;
+
+ /* subtitles seem to be usually muxed ahead of other streams;
+ if not, subtracting a larger time here is necessary */
+ pts2 = av_rescale_q(pts, tb, ifp->time_base) - 1;
+
+ /* do not send the heartbeat frame if the subtitle is already ahead */
+ if (pts2 <= ifp->sub2video.last_pts)
+ return;
+
+ if (pts2 >= ifp->sub2video.end_pts || ifp->sub2video.initialize)
+ /* if we have hit the end of the current displayed subpicture,
+ or if we need to initialize the system, update the
+ overlayed subpicture and its start/end times */
+ sub2video_update(ifp, pts2 + 1, NULL);
+
+ if (av_buffersrc_get_nb_failed_requests(ifilter->filter))
+ sub2video_push_ref(ifp, pts2);
+}
+
int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle)
{
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
- InputStream *ist = ifp->ist;
int ret;
- if (ist->sub2video.frame) {
- sub2video_update(ist, INT64_MIN, subtitle);
- } else {
+ if (ifilter->graph->graph) {
+ if (!subtitle) {
+ if (ifp->sub2video.end_pts < INT64_MAX)
+ sub2video_update(ifp, INT64_MAX, NULL);
+
+ return av_buffersrc_add_frame(ifilter->filter, NULL);
+ }
+
+ sub2video_update(ifp, INT64_MIN, subtitle);
+ } else if (subtitle) {
AVSubtitle sub;
if (!ifp->sub2video.queue)
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 18/24] fftools/ffmpeg_enc: stop configuring filters from encoder flush
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (15 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 17/24] fftools/ffmpeg: move sub2video handling to ffmpeg_filter Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 19/24] fftools/ffmpeg_filter: drop unreachable code Anton Khirnov
` (5 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
There is no way for a filtergraph to have all input parameters, yet not
be configured, so this code should not be reachable.
---
fftools/ffmpeg_enc.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index f023657a07..6c9cce252f 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -1172,18 +1172,8 @@ void enc_flush(void)
av_log(ost, AV_LOG_WARNING,
"Finishing stream without any data written to it.\n");
- if (ost->filter && !fg->graph) {
- if (!ifilter_has_all_input_formats(fg))
- continue;
-
- ret = configure_filtergraph(fg);
- if (ret < 0) {
- av_log(ost, AV_LOG_ERROR, "Error configuring filter graph\n");
- exit_program(1);
- }
-
- of_output_packet(of, ost->pkt, ost, 1);
- }
+ if (!fg->graph)
+ continue;
ret = enc_open(ost, NULL);
if (ret < 0)
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 19/24] fftools/ffmpeg_filter: drop unreachable code
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (16 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 18/24] fftools/ffmpeg_enc: stop configuring filters from encoder flush Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 20/24] fftools/ffmpeg_filter: make ifilter_has_all_input_formats() static Anton Khirnov
` (4 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
Filtergraphs with no inputs are initialized as soon as all their outputs
are bound, so this code should not be reachable.
---
fftools/ffmpeg_filter.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index ce2a914745..e0843b0729 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1946,17 +1946,6 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist)
int nb_requests, nb_requests_max = 0;
InputStream *ist;
- if (!graph->graph && ifilter_has_all_input_formats(graph)) {
- // graph has not been configured yet, but everything is ready;
- // this can happen for graphs with no inputs, or when some input
- // EOF'ed with zero frames and fallback parameters were used
- ret = configure_filtergraph(graph);
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n");
- return ret;
- }
- }
-
if (!graph->graph) {
for (int i = 0; i < graph->nb_inputs; i++) {
InputFilter *ifilter = graph->inputs[i];
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 20/24] fftools/ffmpeg_filter: make ifilter_has_all_input_formats() static
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (17 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 19/24] fftools/ffmpeg_filter: drop unreachable code Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 21/24] fftools/ffmpeg_filter: make InputStream.filter private Anton Khirnov
` (3 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
It is no longer used outside ffmpeg_filter.
---
fftools/ffmpeg.h | 2 --
fftools/ffmpeg_filter.c | 24 ++++++++++++------------
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 75695d3fb5..398bcc58e1 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -751,8 +751,6 @@ void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational t
*/
int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec);
-int ifilter_has_all_input_formats(FilterGraph *fg);
-
void ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost);
/**
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index e0843b0729..9c29850a26 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -537,6 +537,18 @@ fail:
return ret;
}
+// Filters can be configured only if the formats of all inputs are known.
+static int ifilter_has_all_input_formats(FilterGraph *fg)
+{
+ int i;
+ for (i = 0; i < fg->nb_inputs; i++) {
+ InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
+ if (ifp->format < 0)
+ return 0;
+ }
+ return 1;
+}
+
static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in)
{
AVFilterContext *ctx = inout->filter_ctx;
@@ -1660,18 +1672,6 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
return 0;
}
-// Filters can be configured only if the formats of all inputs are known.
-int ifilter_has_all_input_formats(FilterGraph *fg)
-{
- int i;
- for (i = 0; i < fg->nb_inputs; i++) {
- InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
- if (ifp->format < 0)
- return 0;
- }
- return 1;
-}
-
int filtergraph_is_simple(FilterGraph *fg)
{
FilterGraphPriv *fgp = fgp_from_fg(fg);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 21/24] fftools/ffmpeg_filter: make InputStream.filter private
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (18 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 20/24] fftools/ffmpeg_filter: make ifilter_has_all_input_formats() static Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 22/24] fftools/ffmpeg_filter: constify the argument of filtergraph_is_simple() Anton Khirnov
` (2 subsequent siblings)
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
It is no longer accessed outside of ffmpeg_filter.
---
fftools/ffmpeg.h | 1 -
fftools/ffmpeg_filter.c | 32 +++++++++++++++++---------------
2 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 398bcc58e1..655b5c7ec5 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -278,7 +278,6 @@ typedef struct OptionsContext {
} OptionsContext;
typedef struct InputFilter {
- AVFilterContext *filter;
struct FilterGraph *graph;
uint8_t *name;
} InputFilter;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 9c29850a26..0bd0593724 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -57,6 +57,8 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg)
typedef struct InputFilterPriv {
InputFilter ifilter;
+ AVFilterContext *filter;
+
InputStream *ist;
// used to hold submitted input
@@ -181,7 +183,7 @@ static void sub2video_push_ref(InputFilterPriv *ifp, int64_t pts)
av_assert1(frame->data[0]);
ifp->sub2video.last_pts = frame->pts = pts;
- ret = av_buffersrc_add_frame_flags(ifp->ifilter.filter, frame,
+ ret = av_buffersrc_add_frame_flags(ifp->filter, frame,
AV_BUFFERSRC_FLAG_KEEP_REF |
AV_BUFFERSRC_FLAG_PUSH);
if (ret != AVERROR_EOF && ret < 0)
@@ -1304,15 +1306,15 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
ist->file_index, ist->index);
- if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name,
+ if ((ret = avfilter_graph_create_filter(&ifp->filter, buffer_filt, name,
args.str, NULL, fg->graph)) < 0)
goto fail;
par->hw_frames_ctx = ifp->hw_frames_ctx;
- ret = av_buffersrc_parameters_set(ifilter->filter, par);
+ ret = av_buffersrc_parameters_set(ifp->filter, par);
if (ret < 0)
goto fail;
av_freep(&par);
- last_filter = ifilter->filter;
+ last_filter = ifp->filter;
desc = av_pix_fmt_desc_get(ifp->format);
av_assert0(desc);
@@ -1410,11 +1412,11 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
snprintf(name, sizeof(name), "graph_%d_in_%d_%d", fg->index,
ist->file_index, ist->index);
- if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt,
+ if ((ret = avfilter_graph_create_filter(&ifp->filter, abuffer_filt,
name, args.str, NULL,
fg->graph)) < 0)
return ret;
- last_filter = ifilter->filter;
+ last_filter = ifp->filter;
snprintf(name, sizeof(name), "trim for input stream %d:%d",
ist->file_index, ist->index);
@@ -1451,7 +1453,7 @@ static void cleanup_filtergraph(FilterGraph *fg)
for (i = 0; i < fg->nb_outputs; i++)
fg->outputs[i]->filter = (AVFilterContext *)NULL;
for (i = 0; i < fg->nb_inputs; i++)
- fg->inputs[i]->filter = (AVFilterContext *)NULL;
+ ifp_from_ifilter(fg->inputs[i])->filter = NULL;
avfilter_graph_free(&fg->graph);
}
@@ -1571,7 +1573,7 @@ int configure_filtergraph(FilterGraph *fg)
InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
AVFrame *tmp;
while (av_fifo_read(ifp->frame_queue, &tmp, 1) >= 0) {
- ret = av_buffersrc_add_frame(fg->inputs[i]->filter, tmp);
+ ret = av_buffersrc_add_frame(ifp->filter, tmp);
av_frame_free(&tmp);
if (ret < 0)
goto fail;
@@ -1582,7 +1584,7 @@ int configure_filtergraph(FilterGraph *fg)
for (i = 0; i < fg->nb_inputs; i++) {
InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
if (ifp->eof) {
- ret = av_buffersrc_add_frame(fg->inputs[i]->filter, NULL);
+ ret = av_buffersrc_add_frame(ifp->filter, NULL);
if (ret < 0)
goto fail;
}
@@ -1755,7 +1757,7 @@ void ifilter_sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational t
overlayed subpicture and its start/end times */
sub2video_update(ifp, pts2 + 1, NULL);
- if (av_buffersrc_get_nb_failed_requests(ifilter->filter))
+ if (av_buffersrc_get_nb_failed_requests(ifp->filter))
sub2video_push_ref(ifp, pts2);
}
@@ -1769,7 +1771,7 @@ int ifilter_sub2video(InputFilter *ifilter, const AVSubtitle *subtitle)
if (ifp->sub2video.end_pts < INT64_MAX)
sub2video_update(ifp, INT64_MAX, NULL);
- return av_buffersrc_add_frame(ifilter->filter, NULL);
+ return av_buffersrc_add_frame(ifp->filter, NULL);
}
sub2video_update(ifp, INT64_MIN, subtitle);
@@ -1802,11 +1804,11 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb)
ifp->eof = 1;
- if (ifilter->filter) {
+ if (ifp->filter) {
pts = av_rescale_q_rnd(pts, tb, ifp->time_base,
AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
- ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH);
+ ret = av_buffersrc_close(ifp->filter, pts, AV_BUFFERSRC_FLAG_PUSH);
if (ret < 0)
return ret;
} else {
@@ -1928,7 +1930,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference)
)
#endif
- ret = av_buffersrc_add_frame_flags(ifilter->filter, frame,
+ ret = av_buffersrc_add_frame_flags(ifp->filter, frame,
AV_BUFFERSRC_FLAG_PUSH);
if (ret < 0) {
av_frame_unref(frame);
@@ -1984,7 +1986,7 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist)
ist = ifp->ist;
if (input_files[ist->file_index]->eagain || ifp->eof)
continue;
- nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter);
+ nb_requests = av_buffersrc_get_nb_failed_requests(ifp->filter);
if (nb_requests > nb_requests_max) {
nb_requests_max = nb_requests;
*best_ist = ist;
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 22/24] fftools/ffmpeg_filter: constify the argument of filtergraph_is_simple()
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (19 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 21/24] fftools/ffmpeg_filter: make InputStream.filter private Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 23/24] fftools/ffmpeg_mux: flush bsfs immediately on exceeding recoding time Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 24/24] fftools/ffmpeg_filter: do not flush encoders on parameter change Anton Khirnov
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.h | 2 +-
fftools/ffmpeg_filter.c | 9 +++++++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 655b5c7ec5..966397270d 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -731,7 +731,7 @@ int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_id
int configure_filtergraph(FilterGraph *fg);
void check_filter_outputs(void);
-int filtergraph_is_simple(FilterGraph *fg);
+int filtergraph_is_simple(const FilterGraph *fg);
int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
char *graph_desc);
int init_complex_filtergraph(FilterGraph *fg);
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 0bd0593724..62ba27e559 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -54,6 +54,11 @@ static FilterGraphPriv *fgp_from_fg(FilterGraph *fg)
return (FilterGraphPriv*)fg;
}
+static const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg)
+{
+ return (const FilterGraphPriv*)fg;
+}
+
typedef struct InputFilterPriv {
InputFilter ifilter;
@@ -1674,9 +1679,9 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
return 0;
}
-int filtergraph_is_simple(FilterGraph *fg)
+int filtergraph_is_simple(const FilterGraph *fg)
{
- FilterGraphPriv *fgp = fgp_from_fg(fg);
+ const FilterGraphPriv *fgp = cfgp_from_cfg(fg);
return fgp->is_simple;
}
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 23/24] fftools/ffmpeg_mux: flush bsfs immediately on exceeding recoding time
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (20 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 22/24] fftools/ffmpeg_filter: constify the argument of filtergraph_is_simple() Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 24/24] fftools/ffmpeg_filter: do not flush encoders on parameter change Anton Khirnov
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
Current code marks the output stream as finished and waits for a flush
packet, but that is both unnecessary and suspect, as in theory nothing
should be sent to a finished stream - not even flush packets.
---
fftools/ffmpeg_mux.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 3da3c04d7f..feb014ca31 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -386,6 +386,11 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts)
AVPacket *opkt = ost->pkt;
av_packet_unref(opkt);
+
+ if (of->recording_time != INT64_MAX &&
+ dts >= of->recording_time + start_time)
+ pkt = NULL;
+
// EOF: flush output bitstream filters.
if (!pkt) {
of_output_packet(of, opkt, ost, 1);
@@ -407,12 +412,6 @@ void of_streamcopy(OutputStream *ost, const AVPacket *pkt, int64_t dts)
return;
}
- if (of->recording_time != INT64_MAX &&
- dts >= of->recording_time + start_time) {
- close_output_stream(ost);
- return;
- }
-
if (av_packet_ref(opkt, pkt) < 0)
exit_program(1);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH 24/24] fftools/ffmpeg_filter: do not flush encoders on parameter change
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
` (21 preceding siblings ...)
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 23/24] fftools/ffmpeg_mux: flush bsfs immediately on exceeding recoding time Anton Khirnov
@ 2023-05-28 9:14 ` Anton Khirnov
22 siblings, 0 replies; 27+ messages in thread
From: Anton Khirnov @ 2023-05-28 9:14 UTC (permalink / raw)
To: ffmpeg-devel
It makes no sense to do so.
---
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 62ba27e559..1eac253023 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -1905,7 +1905,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference)
return ret;
}
- ret = reap_filters(1);
+ ret = reap_filters(0);
if (ret < 0 && ret != AVERROR_EOF) {
av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret));
return ret;
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* Re: [FFmpeg-devel] [PATCH 16/24] fftools/ffmpeg: rework setting sub2video parameters
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 16/24] fftools/ffmpeg: rework setting sub2video parameters Anton Khirnov
@ 2023-05-28 19:43 ` Michael Niedermayer
2023-05-29 12:49 ` [FFmpeg-devel] [PATCH] " Anton Khirnov
0 siblings, 1 reply; 27+ messages in thread
From: Michael Niedermayer @ 2023-05-28 19:43 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 881 bytes --]
On Sun, May 28, 2023 at 11:14:08AM +0200, Anton Khirnov wrote:
> Set them in ifilter_parameters_from_dec(), similarly to audio/video
> streams. This reduces the extent to which sub2video filters need to be
> treated specially.
> ---
> fftools/ffmpeg.c | 6 ++---
> fftools/ffmpeg_demux.c | 21 +++++++++++++++++
> fftools/ffmpeg_filter.c | 52 +++++++++++------------------------------
> 3 files changed, 38 insertions(+), 41 deletions(-)
The following prodeuces a 0 byte file after the patch
-i ~/tickets/153/bbc_small.ts -filter_complex '[0:v][0:s]overlay' -qscale 2 -t 3 -y notcorrupt.avi
https://samples.ffmpeg.org/ffmpeg-bugs/trac/ticket153/bbc_small.ts
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
I am the wisest man alive, for I know one thing, and that is that I know
nothing. -- Socrates
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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] 27+ messages in thread
* [FFmpeg-devel] [PATCH] fftools/ffmpeg: rework setting sub2video parameters
2023-05-28 19:43 ` Michael Niedermayer
@ 2023-05-29 12:49 ` Anton Khirnov
2023-05-31 17:02 ` Michael Niedermayer
0 siblings, 1 reply; 27+ messages in thread
From: Anton Khirnov @ 2023-05-29 12:49 UTC (permalink / raw)
To: ffmpeg-devel
Set them in ifilter_parameters_from_dec(), similarly to audio/video
streams. This reduces the extent to which sub2video filters need to be
treated specially.
---
You can also get the updated tree from ffmpeg_sub2video in my repo
---
fftools/ffmpeg.c | 6 ++---
fftools/ffmpeg_demux.c | 21 +++++++++++++++
fftools/ffmpeg_filter.c | 58 ++++++++++++-----------------------------
3 files changed, 41 insertions(+), 44 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 4624960c17..e9e60407d2 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -153,9 +153,9 @@ static int sub2video_get_blank_frame(InputStream *ist)
AVFrame *frame = ist->sub2video.frame;
av_frame_unref(frame);
- ist->sub2video.frame->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w;
- ist->sub2video.frame->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h;
- ist->sub2video.frame->format = AV_PIX_FMT_RGB32;
+ frame->width = ist->sub2video.w;
+ frame->height = ist->sub2video.h;
+ frame->format = AV_PIX_FMT_RGB32;
if ((ret = av_frame_get_buffer(frame, 0)) < 0)
return ret;
memset(frame->data[0], 0, frame->height * frame->linesize[0]);
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 561b4b0002..817ccbbedc 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -1228,6 +1228,27 @@ static void add_input_streams(const OptionsContext *o, Demuxer *d)
av_log(ist, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
exit_program(1);
}
+
+ /* Compute the size of the canvas for the subtitles stream.
+ If the subtitles codecpar has set a size, use it. Otherwise use the
+ maximum dimensions of the video streams in the same file. */
+ ist->sub2video.w = ist->dec_ctx->width;
+ ist->sub2video.h = ist->dec_ctx->height;
+ if (!(ist->sub2video.w && ist->sub2video.h)) {
+ for (int j = 0; j < ic->nb_streams; j++) {
+ AVCodecParameters *par1 = ic->streams[j]->codecpar;
+ if (par1->codec_type == AVMEDIA_TYPE_VIDEO) {
+ ist->sub2video.w = FFMAX(ist->sub2video.w, par1->width);
+ ist->sub2video.h = FFMAX(ist->sub2video.h, par1->height);
+ }
+ }
+ }
+
+ if (!(ist->sub2video.w && ist->sub2video.h)) {
+ ist->sub2video.w = FFMAX(ist->sub2video.w, 720);
+ ist->sub2video.h = FFMAX(ist->sub2video.h, 576);
+ }
+
break;
}
case AVMEDIA_TYPE_ATTACHMENT:
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 2a73e3a3e3..4b5ccf50bd 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -458,13 +458,13 @@ static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist)
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
int ret;
+ ifp->ist = ist;
+ ifp->type_src = ist->st->codecpar->codec_type;
+
ret = ist_filter_add(ist, ifilter, filtergraph_is_simple(ifilter->graph));
if (ret < 0)
return ret;
- ifp->ist = ist;
- ifp->type_src = ist->st->codecpar->codec_type;
-
return 0;
}
@@ -1110,38 +1110,6 @@ void check_filter_outputs(void)
static int sub2video_prepare(InputStream *ist, InputFilter *ifilter)
{
- InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
- AVFormatContext *avf = input_files[ist->file_index]->ctx;
- int i, w, h;
-
- /* Compute the size of the canvas for the subtitles stream.
- If the subtitles codecpar has set a size, use it. Otherwise use the
- maximum dimensions of the video streams in the same file. */
- w = ifp->width;
- h = ifp->height;
- if (!(w && h)) {
- for (i = 0; i < avf->nb_streams; i++) {
- if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
- w = FFMAX(w, avf->streams[i]->codecpar->width);
- h = FFMAX(h, avf->streams[i]->codecpar->height);
- }
- }
- if (!(w && h)) {
- w = FFMAX(w, 720);
- h = FFMAX(h, 576);
- }
- av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h);
- }
- ist->sub2video.w = ifp->width = w;
- ist->sub2video.h = ifp->height = h;
-
- ifp->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w;
- ifp->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h;
-
- /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the
- palettes for all rectangles are identical or compatible */
- ifp->format = AV_PIX_FMT_RGB32;
-
ist->sub2video.frame = av_frame_alloc();
if (!ist->sub2video.frame)
return AVERROR(ENOMEM);
@@ -1525,7 +1493,7 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec)
ifp->fallback.width = dec->width;
ifp->fallback.height = dec->height;
ifp->fallback.sample_aspect_ratio = dec->sample_aspect_ratio;
- } else {
+ } else if (dec->codec_type == AVMEDIA_TYPE_AUDIO) {
int ret;
ifp->fallback.format = dec->sample_fmt;
@@ -1534,6 +1502,17 @@ int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec)
ret = av_channel_layout_copy(&ifp->fallback.ch_layout, &dec->ch_layout);
if (ret < 0)
return ret;
+ } else {
+ // for subtitles (i.e. sub2video) we set the actual parameters,
+ // rather than just fallback
+ ifp->width = ifp->ist->sub2video.w;
+ ifp->height = ifp->ist->sub2video.h;
+
+ /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the
+ palettes for all rectangles are identical or compatible */
+ ifp->format = AV_PIX_FMT_RGB32;
+
+ av_log(NULL, AV_LOG_VERBOSE, "sub2video: using %dx%d canvas\n", ifp->width, ifp->height);
}
return 0;
@@ -1574,8 +1553,7 @@ int ifilter_has_all_input_formats(FilterGraph *fg)
int i;
for (i = 0; i < fg->nb_inputs; i++) {
InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
- if (ifp->format < 0 && (ifp->type_src == AVMEDIA_TYPE_AUDIO ||
- ifp->type_src == AVMEDIA_TYPE_VIDEO))
+ if (ifp->format < 0)
return 0;
}
return 1;
@@ -1709,9 +1687,7 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb)
}
}
- if (ifp->format < 0 &&
- (ifp->type_src == AVMEDIA_TYPE_AUDIO ||
- ifp->type_src == AVMEDIA_TYPE_VIDEO)) {
+ if (ifp->format < 0) {
av_log(NULL, AV_LOG_ERROR,
"Cannot determine format of input stream %d:%d after EOF\n",
ifp->ist->file_index, ifp->ist->index);
--
2.40.1
_______________________________________________
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] 27+ messages in thread
* Re: [FFmpeg-devel] [PATCH] fftools/ffmpeg: rework setting sub2video parameters
2023-05-29 12:49 ` [FFmpeg-devel] [PATCH] " Anton Khirnov
@ 2023-05-31 17:02 ` Michael Niedermayer
0 siblings, 0 replies; 27+ messages in thread
From: Michael Niedermayer @ 2023-05-31 17:02 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1062 bytes --]
On Mon, May 29, 2023 at 02:49:55PM +0200, Anton Khirnov wrote:
> Set them in ifilter_parameters_from_dec(), similarly to audio/video
> streams. This reduces the extent to which sub2video filters need to be
> treated specially.
> ---
> You can also get the updated tree from ffmpeg_sub2video in my repo
> ---
> fftools/ffmpeg.c | 6 ++---
> fftools/ffmpeg_demux.c | 21 +++++++++++++++
> fftools/ffmpeg_filter.c | 58 ++++++++++++-----------------------------
> 3 files changed, 41 insertions(+), 44 deletions(-)
breaks (looks like wrong width/height) after the change from ffmpeg_sub2video
corresponding to this patch
./ffmpeg -i ~/tickets/4752/dump_dvbsubtitles.mp4 -y -ss 5 -t 1 -filter_complex '[0:v][0:s]overlay' /tmp/file4752.ts && ffplay /tmp/file4752.ts
seems to be in ffmpeg-bugs/trac/ticket4752/dump_dvbsubtitles.mp4
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
I do not agree with what you have to say, but I'll defend to the death your
right to say it. -- Voltaire
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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] 27+ messages in thread
end of thread, other threads:[~2023-05-31 17:03 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-28 9:13 [FFmpeg-devel] [PATCH 01/24] fftools/ffmpeg_mux_init: merge ost_add_from_filter() to ost_add() Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 02/24] fftools/ffmpeg: add logging for creating output streams Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 03/24] fftools/ffmpeg_filter: use a dedicated variable for marking simple filtergraphs Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 04/24] fftools/ffmpeg_filter: always pass graph description to fg_create() Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 05/24] fftools/ffmpeg_filter: store just the link label in OutputFilter Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 06/24] fftools/ffmpeg_filter: decouple allocating InputFilter and binding it to InputStream Anton Khirnov
2023-05-28 9:13 ` [FFmpeg-devel] [PATCH 07/24] fftools/ffmpeg_filter: move some functions higher up Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 08/24] fftools/ffmpeg_filter: create Input/OutputFilters together with FilterGraph Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 09/24] fftools/ffmpeg_filter: factor out binding an output stream to OutputFilter Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 10/24] fftools/ffmpeg_mux_init: move OutputFilter setup code to ffmpeg_filter Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 11/24] fftools/ffmpeg_filter: try to configure filtergraphs earlier Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 12/24] fftools/ffmpeg: constify AVSubtitle parameters as appropriate Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 13/24] fftools/ffmpeg_dec: move sub2video submission to ffmpeg_filter Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 14/24] fftools/ffmpeg_filter: move sub2video subtitle queue to InputFilterPriv Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 15/24] fftools/ffmpeg: tweak sub2video_heartbeat() arguments Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 16/24] fftools/ffmpeg: rework setting sub2video parameters Anton Khirnov
2023-05-28 19:43 ` Michael Niedermayer
2023-05-29 12:49 ` [FFmpeg-devel] [PATCH] " Anton Khirnov
2023-05-31 17:02 ` Michael Niedermayer
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 17/24] fftools/ffmpeg: move sub2video handling to ffmpeg_filter Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 18/24] fftools/ffmpeg_enc: stop configuring filters from encoder flush Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 19/24] fftools/ffmpeg_filter: drop unreachable code Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 20/24] fftools/ffmpeg_filter: make ifilter_has_all_input_formats() static Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 21/24] fftools/ffmpeg_filter: make InputStream.filter private Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 22/24] fftools/ffmpeg_filter: constify the argument of filtergraph_is_simple() Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 23/24] fftools/ffmpeg_mux: flush bsfs immediately on exceeding recoding time Anton Khirnov
2023-05-28 9:14 ` [FFmpeg-devel] [PATCH 24/24] fftools/ffmpeg_filter: do not flush encoders on parameter change Anton Khirnov
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git