* [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
@ 2022-04-04 11:29 Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 01/49] fftools/ffmpeg: drop an obsolete hack Anton Khirnov
` (51 more replies)
0 siblings, 52 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
Hi,
this WIP patchset is the first major part of my ongoing work to change
ffmpeg.c architecture such that every
- demuxer
- decoder
- filtergraph
- encoder
- muxer
lives in its own thread. The advantages of doing this, beyond increased
throughput, would be enforced separation between these components,
making the code more local and easier to reason about.
This set implements threading for muxers. My tentative plan is to
continue with encoders and then filters. The patches still need some
polishing, especially the last one. Two FATE tests do not yet pass, this
will be fixed in later iterations.
Meanwhile, comments on the overall approach are especially welcome.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 81+ messages in thread
* [FFmpeg-devel] [PATCH 01/49] fftools/ffmpeg: drop an obsolete hack
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 02/49] fftools/ffmpeg: move a comment to a more appropriate place Anton Khirnov
` (50 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
Introduced in 05741d70c7a. All encoders should set the timestamps
properly now, so it should never be necessary.
---
fftools/ffmpeg.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 6d62bdc7b0..afa1b012a6 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1372,9 +1372,6 @@ static void do_video_out(OutputFile *of,
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
}
- if (pkt->pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & AV_CODEC_CAP_DELAY))
- pkt->pts = ost->sync_opts;
-
av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase);
if (debug_ts) {
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 02/49] fftools/ffmpeg: move a comment to a more appropriate place
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 01/49] fftools/ffmpeg: drop an obsolete hack Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-06 11:20 ` James Almer
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 03/49] fftools/ffmpeg: stop using OutputStream.frame_number for streamcopy Anton Khirnov
` (49 subsequent siblings)
51 siblings, 1 reply; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index afa1b012a6..13be32f0cf 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1238,6 +1238,11 @@ static void do_video_out(OutputFile *of,
}
}
+ /*
+ * For video, number of frames in == number of packets out.
+ * But there may be reordering, so we can't throw away frames on encoder
+ * flush, we need to limit them here, before they go into encoder.
+ */
nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
nb0_frames = FFMIN(nb0_frames, nb_frames);
@@ -1392,11 +1397,6 @@ static void do_video_out(OutputFile *of,
}
}
ost->sync_opts++;
- /*
- * For video, number of frames in == number of packets out.
- * But there may be reordering, so we can't throw away frames on encoder
- * flush, we need to limit them here, before they go into encoder.
- */
ost->frame_number++;
if (vstats_filename && frame_size)
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 03/49] fftools/ffmpeg: stop using OutputStream.frame_number for streamcopy
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 01/49] fftools/ffmpeg: drop an obsolete hack Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 02/49] fftools/ffmpeg: move a comment to a more appropriate place Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-06 11:20 ` James Almer
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 04/49] fftools/ffmpeg: pass the muxer context explicitly to some functions Anton Khirnov
` (48 subsequent siblings)
51 siblings, 1 reply; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
This field is currently used by checks
- skipping packets before the first keyframe
- skipping packets before start time
to test whether any packets have been output already. But since
frame_number is incremented after the bitstream filters are applied
(which may involve delay), this use is incorrect. The keyframe check
works around this by adding an extra flag, the start-time check does
not.
Simplify both checks by replacing the seen_kf flag with a flag tracking
whether any packets have been output by do_streamcopy().
---
fftools/ffmpeg.c | 10 +++++-----
fftools/ffmpeg.h | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 13be32f0cf..29b01f9d93 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -894,8 +894,6 @@ static void output_packet(OutputFile *of, AVPacket *pkt,
/* apply the output bitstream filters */
if (ost->bsf_ctx) {
- if (pkt->flags & AV_PKT_FLAG_KEY)
- ost->seen_kf = 1;
ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt);
if (ret < 0)
goto finish;
@@ -2043,11 +2041,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
return;
}
- if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
- !ost->copy_initial_nonkeyframes && !ost->seen_kf)
+ if (!ost->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) &&
+ !ost->copy_initial_nonkeyframes)
return;
- if (!ost->frame_number && !ost->copy_prior_start) {
+ if (!ost->streamcopy_started && !ost->copy_prior_start) {
int64_t comp_start = start_time;
if (copy_ts && f->start_time != AV_NOPTS_VALUE)
comp_start = FFMAX(start_time, f->start_time + f->ts_offset);
@@ -2101,6 +2099,8 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
ost->sync_opts += opkt->duration;
output_packet(of, opkt, ost, 0);
+
+ ost->streamcopy_started = 1;
}
int guess_input_channel_layout(InputStream *ist)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 1e14bf9fa9..04369df139 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -536,7 +536,7 @@ typedef struct OutputStream {
int inputs_done;
const char *attachment_filename;
- int seen_kf;
+ int streamcopy_started;
int copy_initial_nonkeyframes;
int copy_prior_start;
char *disposition;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 04/49] fftools/ffmpeg: pass the muxer context explicitly to some functions
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (2 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 03/49] fftools/ffmpeg: stop using OutputStream.frame_number for streamcopy Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 05/49] fftools/ffmpeg: store the output file index in OutputFile Anton Khirnov
` (47 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
Stop accessing OutputFile.ctx. This will be useful in the following
commits, where it will become hidden.
---
fftools/ffmpeg_opt.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 22c88287df..8e217af4ab 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2125,10 +2125,10 @@ static int opt_streamid(void *optctx, const char *opt, const char *arg)
return 0;
}
-static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata)
+static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os,
+ int copy_metadata)
{
AVFormatContext *is = ifile->ctx;
- AVFormatContext *os = ofile->ctx;
AVChapter **tmp;
int i;
@@ -2168,14 +2168,14 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata)
return 0;
}
-static int set_dispositions(OutputFile *of)
+static int set_dispositions(OutputFile *of, AVFormatContext *ctx)
{
int nb_streams[AVMEDIA_TYPE_NB] = { 0 };
int have_default[AVMEDIA_TYPE_NB] = { 0 };
int have_manual = 0;
// first, copy the input dispositions
- for (int i = 0; i< of->ctx->nb_streams; i++) {
+ for (int i = 0; i < ctx->nb_streams; i++) {
OutputStream *ost = output_streams[of->ost_index + i];
nb_streams[ost->st->codecpar->codec_type]++;
@@ -2192,7 +2192,7 @@ static int set_dispositions(OutputFile *of)
if (have_manual) {
// process manually set dispositions - they override the above copy
- for (int i = 0; i< of->ctx->nb_streams; i++) {
+ for (int i = 0; i < ctx->nb_streams; i++) {
OutputStream *ost = output_streams[of->ost_index + i];
int ret;
@@ -2218,7 +2218,7 @@ static int set_dispositions(OutputFile *of)
// For each media type with more than one stream, find a suitable stream to
// mark as default, unless one is already marked default.
// "Suitable" means the first of that type, skipping attached pictures.
- for (int i = 0; i< of->ctx->nb_streams; i++) {
+ for (int i = 0; i < ctx->nb_streams; i++) {
OutputStream *ost = output_streams[of->ost_index + i];
enum AVMediaType type = ost->st->codecpar->codec_type;
@@ -2760,7 +2760,7 @@ loop_end:
}
}
if (o->chapters_input_file >= 0)
- copy_chapters(input_files[o->chapters_input_file], of,
+ copy_chapters(input_files[o->chapters_input_file], of, oc,
!o->metadata_chapters_manual);
/* copy global metadata by default */
@@ -2913,7 +2913,7 @@ loop_end:
}
}
- err = set_dispositions(of);
+ err = set_dispositions(of, oc);
if (err < 0) {
av_log(NULL, AV_LOG_FATAL, "Error setting output stream dispositions\n");
exit_program(1);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 05/49] fftools/ffmpeg: store the output file index in OutputFile
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (3 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 04/49] fftools/ffmpeg: pass the muxer context explicitly to some functions Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 06/49] fftools/ffmpeg: move some muxing-related code into a separate file Anton Khirnov
` (46 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
Use it to simplify check_init_output_file(). Will allow further
simplifications in the following commits.
---
fftools/ffmpeg.c | 10 +++++-----
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_opt.c | 1 +
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 29b01f9d93..bc700052b6 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2947,7 +2947,7 @@ static int compare_int64(const void *a, const void *b)
}
/* open the muxer when all the streams are initialized */
-static int check_init_output_file(OutputFile *of, int file_index)
+static int check_init_output_file(OutputFile *of)
{
int ret, i;
@@ -2962,13 +2962,13 @@ static int check_init_output_file(OutputFile *of, int file_index)
av_log(NULL, AV_LOG_ERROR,
"Could not write header for output file #%d "
"(incorrect codec parameters ?): %s\n",
- file_index, av_err2str(ret));
+ of->index, av_err2str(ret));
return ret;
}
//assert_avoptions(of->opts);
of->header_written = 1;
- av_dump_format(of->ctx, file_index, of->ctx->url, 1);
+ av_dump_format(of->ctx, of->index, of->ctx->url, 1);
nb_output_dumped++;
if (sdp_filename || want_sdp) {
@@ -3571,7 +3571,7 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame,
ost->initialized = 1;
- ret = check_init_output_file(output_files[ost->file_index], ost->file_index);
+ ret = check_init_output_file(output_files[ost->file_index]);
if (ret < 0)
return ret;
@@ -3674,7 +3674,7 @@ static int transcode_init(void)
for (i = 0; i < nb_output_files; i++) {
oc = output_files[i]->ctx;
if (oc->oformat->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) {
- ret = check_init_output_file(output_files[i], i);
+ ret = check_init_output_file(output_files[i]);
if (ret < 0)
goto dump_format;
}
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 04369df139..0eee6f4da8 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -577,6 +577,8 @@ typedef struct OutputStream {
} OutputStream;
typedef struct OutputFile {
+ int index;
+
AVFormatContext *ctx;
AVDictionary *opts;
int ost_index; /* index of the first stream in output_streams */
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 8e217af4ab..daecba9e57 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2314,6 +2314,7 @@ static int open_output_file(OptionsContext *o, const char *filename)
of = ALLOC_ARRAY_ELEM(output_files, nb_output_files);
+ of->index = nb_output_files - 1;
of->ost_index = nb_output_streams;
of->recording_time = o->recording_time;
of->start_time = o->start_time;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 06/49] fftools/ffmpeg: move some muxing-related code into a separate file
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (4 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 05/49] fftools/ffmpeg: store the output file index in OutputFile Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 07/49] fftools/ffmpeg: move writing the trailer to ffmpeg_mux.c Anton Khirnov
` (45 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
This is a first step towards making muxers more independent from the
rest of the code.
---
fftools/Makefile | 6 +-
fftools/ffmpeg.c | 272 ++--------------------------------------
fftools/ffmpeg.h | 10 ++
fftools/ffmpeg_mux.c | 292 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 314 insertions(+), 266 deletions(-)
create mode 100644 fftools/ffmpeg_mux.c
diff --git a/fftools/Makefile b/fftools/Makefile
index 5ebf50d42e..81ad6c4f4f 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -9,7 +9,11 @@ AVBASENAMES = ffmpeg ffplay ffprobe
ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
-OBJS-ffmpeg += fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o
+OBJS-ffmpeg += \
+ fftools/ffmpeg_filter.o \
+ fftools/ffmpeg_hw.o \
+ fftools/ffmpeg_mux.o \
+ fftools/ffmpeg_opt.o \
define DOFFTOOL
OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index bc700052b6..47724f7231 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -137,9 +137,9 @@ static int nb_frames_dup = 0;
static unsigned dup_warning = 1000;
static int nb_frames_drop = 0;
static int64_t decode_error_stat[2];
-static unsigned nb_output_dumped = 0;
+unsigned nb_output_dumped = 0;
-static int want_sdp = 1;
+int want_sdp = 1;
static BenchmarkTimeStamps current_time;
AVIOContext *progress_avio = NULL;
@@ -345,7 +345,7 @@ static volatile int received_sigterm = 0;
static volatile int received_nb_signals = 0;
static atomic_int transcode_init_done = ATOMIC_VAR_INIT(0);
static volatile int ffmpeg_exited = 0;
-static int main_return_code = 0;
+int main_return_code = 0;
static int64_t copy_ts_first_pts = AV_NOPTS_VALUE;
static void
@@ -711,159 +711,6 @@ static void update_benchmark(const char *fmt, ...)
}
}
-static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others)
-{
- int i;
- for (i = 0; i < nb_output_streams; i++) {
- OutputStream *ost2 = output_streams[i];
- ost2->finished |= ost == ost2 ? this_stream : others;
- }
-}
-
-static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
-{
- AVFormatContext *s = of->ctx;
- AVStream *st = ost->st;
- int ret;
-
- /*
- * Audio encoders may split the packets -- #frames in != #packets out.
- * But there is no reordering, so we can limit the number of output packets
- * by simply dropping them here.
- * Counting encoded video frames needs to be done separately because of
- * reordering, see do_video_out().
- * Do not count the packet when unqueued because it has been counted when queued.
- */
- if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed) && !unqueue) {
- if (ost->frame_number >= ost->max_frames) {
- av_packet_unref(pkt);
- return;
- }
- ost->frame_number++;
- }
-
- if (!of->header_written) {
- AVPacket *tmp_pkt;
- /* the muxer is not initialized yet, buffer the packet */
- if (!av_fifo_can_write(ost->muxing_queue)) {
- size_t cur_size = av_fifo_can_read(ost->muxing_queue);
- unsigned int are_we_over_size =
- (ost->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold;
- size_t limit = are_we_over_size ? ost->max_muxing_queue_size : SIZE_MAX;
- size_t new_size = FFMIN(2 * cur_size, limit);
-
- if (new_size <= cur_size) {
- av_log(NULL, AV_LOG_ERROR,
- "Too many packets buffered for output stream %d:%d.\n",
- ost->file_index, ost->st->index);
- exit_program(1);
- }
- ret = av_fifo_grow2(ost->muxing_queue, new_size - cur_size);
- if (ret < 0)
- exit_program(1);
- }
- ret = av_packet_make_refcounted(pkt);
- if (ret < 0)
- exit_program(1);
- tmp_pkt = av_packet_alloc();
- if (!tmp_pkt)
- exit_program(1);
- av_packet_move_ref(tmp_pkt, pkt);
- ost->muxing_queue_data_size += tmp_pkt->size;
- av_fifo_write(ost->muxing_queue, &tmp_pkt, 1);
- return;
- }
-
- if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
- (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
- pkt->pts = pkt->dts = AV_NOPTS_VALUE;
-
- if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
- int i;
- uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
- NULL);
- ost->quality = sd ? AV_RL32(sd) : -1;
- ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE;
-
- for (i = 0; i<FF_ARRAY_ELEMS(ost->error); i++) {
- if (sd && i < sd[5])
- ost->error[i] = AV_RL64(sd + 8 + 8*i);
- else
- ost->error[i] = -1;
- }
-
- if (ost->frame_rate.num && ost->is_cfr) {
- if (pkt->duration > 0)
- av_log(NULL, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n");
- pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate),
- ost->mux_timebase);
- }
- }
-
- av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base);
-
- if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
- if (pkt->dts != AV_NOPTS_VALUE &&
- pkt->pts != AV_NOPTS_VALUE &&
- pkt->dts > pkt->pts) {
- av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n",
- pkt->dts, pkt->pts,
- ost->file_index, ost->st->index);
- pkt->pts =
- pkt->dts = pkt->pts + pkt->dts + ost->last_mux_dts + 1
- - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1)
- - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1);
- }
- if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) &&
- pkt->dts != AV_NOPTS_VALUE &&
- ost->last_mux_dts != AV_NOPTS_VALUE) {
- int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
- if (pkt->dts < max) {
- int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
- if (exit_on_error)
- loglevel = AV_LOG_ERROR;
- av_log(s, loglevel, "Non-monotonous DTS in output stream "
- "%d:%d; previous: %"PRId64", current: %"PRId64"; ",
- ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts);
- if (exit_on_error) {
- av_log(NULL, AV_LOG_FATAL, "aborting.\n");
- exit_program(1);
- }
- av_log(s, loglevel, "changing to %"PRId64". This may result "
- "in incorrect timestamps in the output file.\n",
- max);
- if (pkt->pts >= pkt->dts)
- pkt->pts = FFMAX(pkt->pts, max);
- pkt->dts = max;
- }
- }
- }
- ost->last_mux_dts = pkt->dts;
-
- ost->data_size += pkt->size;
- ost->packets_written++;
-
- pkt->stream_index = ost->index;
-
- if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "muxer <- type:%s "
- "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n",
- av_get_media_type_string(ost->enc_ctx->codec_type),
- av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base),
- av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base),
- av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base),
- pkt->size
- );
- }
-
- ret = av_interleaved_write_frame(s, pkt);
- if (ret < 0) {
- print_error("av_interleaved_write_frame()", ret);
- main_return_code = 1;
- close_all_output_streams(ost, MUXER_FINISHED | ENCODER_FINISHED, ENCODER_FINISHED);
- }
-}
-
static void close_output_stream(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
@@ -898,11 +745,11 @@ static void output_packet(OutputFile *of, AVPacket *pkt,
if (ret < 0)
goto finish;
while ((ret = av_bsf_receive_packet(ost->bsf_ctx, pkt)) >= 0)
- write_packet(of, pkt, ost, 0);
+ of_write_packet(of, pkt, ost, 0);
if (ret == AVERROR(EAGAIN))
ret = 0;
} else if (!eof)
- write_packet(of, pkt, ost, 0);
+ of_write_packet(of, pkt, ost, 0);
finish:
if (ret < 0 && ret != AVERROR_EOF) {
@@ -2767,59 +2614,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo
return !eof_reached;
}
-static int print_sdp(void)
-{
- char sdp[16384];
- int i;
- int j, ret;
- AVIOContext *sdp_pb;
- AVFormatContext **avc;
-
- for (i = 0; i < nb_output_files; i++) {
- if (!output_files[i]->header_written)
- return 0;
- }
-
- avc = av_malloc_array(nb_output_files, sizeof(*avc));
- if (!avc)
- exit_program(1);
- for (i = 0, j = 0; i < nb_output_files; i++) {
- if (!strcmp(output_files[i]->ctx->oformat->name, "rtp")) {
- avc[j] = output_files[i]->ctx;
- j++;
- }
- }
-
- if (!j) {
- av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n");
- ret = AVERROR(EINVAL);
- goto fail;
- }
-
- ret = av_sdp_create(avc, j, sdp, sizeof(sdp));
- if (ret < 0)
- goto fail;
-
- if (!sdp_filename) {
- printf("SDP:\n%s\n", sdp);
- fflush(stdout);
- } else {
- ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL);
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename);
- goto fail;
- }
-
- avio_print(sdp_pb, sdp);
- avio_closep(&sdp_pb);
- av_freep(&sdp_filename);
- }
-
-fail:
- av_freep(&avc);
- return ret;
-}
-
static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts)
{
InputStream *ist = s->opaque;
@@ -2946,58 +2740,6 @@ static int compare_int64(const void *a, const void *b)
return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b);
}
-/* open the muxer when all the streams are initialized */
-static int check_init_output_file(OutputFile *of)
-{
- int ret, i;
-
- for (i = 0; i < of->ctx->nb_streams; i++) {
- OutputStream *ost = output_streams[of->ost_index + i];
- if (!ost->initialized)
- return 0;
- }
-
- ret = avformat_write_header(of->ctx, &of->opts);
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR,
- "Could not write header for output file #%d "
- "(incorrect codec parameters ?): %s\n",
- of->index, av_err2str(ret));
- return ret;
- }
- //assert_avoptions(of->opts);
- of->header_written = 1;
-
- av_dump_format(of->ctx, of->index, of->ctx->url, 1);
- nb_output_dumped++;
-
- if (sdp_filename || want_sdp) {
- ret = print_sdp();
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "Error writing the SDP.\n");
- return ret;
- }
- }
-
- /* flush the muxing queues */
- for (i = 0; i < of->ctx->nb_streams; i++) {
- OutputStream *ost = output_streams[of->ost_index + i];
- AVPacket *pkt;
-
- /* try to improve muxing time_base (only possible if nothing has been written yet) */
- if (!av_fifo_can_read(ost->muxing_queue))
- ost->mux_timebase = ost->st->time_base;
-
- while (av_fifo_read(ost->muxing_queue, &pkt, 1) >= 0) {
- ost->muxing_queue_data_size -= pkt->size;
- write_packet(of, pkt, ost, 1);
- av_packet_free(&pkt);
- }
- }
-
- return 0;
-}
-
static int init_output_bsfs(OutputStream *ost)
{
AVBSFContext *ctx = ost->bsf_ctx;
@@ -3571,7 +3313,7 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame,
ost->initialized = 1;
- ret = check_init_output_file(output_files[ost->file_index]);
+ ret = of_check_init(output_files[ost->file_index]);
if (ret < 0)
return ret;
@@ -3674,7 +3416,7 @@ static int transcode_init(void)
for (i = 0; i < nb_output_files; i++) {
oc = output_files[i]->ctx;
if (oc->oformat->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) {
- ret = check_init_output_file(output_files[i]);
+ ret = of_check_init(output_files[i]);
if (ret < 0)
goto dump_format;
}
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 0eee6f4da8..cb475bb690 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -647,6 +647,10 @@ extern char *qsv_device;
#endif
extern HWDevice *filter_hw_device;
+extern int want_sdp;
+extern unsigned nb_output_dumped;
+extern int main_return_code;
+
void term_init(void);
void term_exit(void);
@@ -683,4 +687,10 @@ int hw_device_setup_for_filter(FilterGraph *fg);
int hwaccel_decode_init(AVCodecContext *avctx);
+/* open the muxer when all the streams are initialized */
+int of_check_init(OutputFile *of);
+
+void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
+ int unqueue);
+
#endif /* FFTOOLS_FFMPEG_H */
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
new file mode 100644
index 0000000000..92d8a8c088
--- /dev/null
+++ b/fftools/ffmpeg_mux.c
@@ -0,0 +1,292 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ffmpeg.h"
+
+#include "libavutil/fifo.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/timestamp.h"
+
+#include "libavcodec/packet.h"
+
+#include "libavformat/avformat.h"
+#include "libavformat/avio.h"
+
+static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others)
+{
+ int i;
+ for (i = 0; i < nb_output_streams; i++) {
+ OutputStream *ost2 = output_streams[i];
+ ost2->finished |= ost == ost2 ? this_stream : others;
+ }
+}
+
+void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
+ int unqueue)
+{
+ AVFormatContext *s = of->ctx;
+ AVStream *st = ost->st;
+ int ret;
+
+ /*
+ * Audio encoders may split the packets -- #frames in != #packets out.
+ * But there is no reordering, so we can limit the number of output packets
+ * by simply dropping them here.
+ * Counting encoded video frames needs to be done separately because of
+ * reordering, see do_video_out().
+ * Do not count the packet when unqueued because it has been counted when queued.
+ */
+ if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed) && !unqueue) {
+ if (ost->frame_number >= ost->max_frames) {
+ av_packet_unref(pkt);
+ return;
+ }
+ ost->frame_number++;
+ }
+
+ if (!of->header_written) {
+ AVPacket *tmp_pkt;
+ /* the muxer is not initialized yet, buffer the packet */
+ if (!av_fifo_can_write(ost->muxing_queue)) {
+ size_t cur_size = av_fifo_can_read(ost->muxing_queue);
+ unsigned int are_we_over_size =
+ (ost->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold;
+ size_t limit = are_we_over_size ? ost->max_muxing_queue_size : SIZE_MAX;
+ size_t new_size = FFMIN(2 * cur_size, limit);
+
+ if (new_size <= cur_size) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Too many packets buffered for output stream %d:%d.\n",
+ ost->file_index, ost->st->index);
+ exit_program(1);
+ }
+ ret = av_fifo_grow2(ost->muxing_queue, new_size - cur_size);
+ if (ret < 0)
+ exit_program(1);
+ }
+ ret = av_packet_make_refcounted(pkt);
+ if (ret < 0)
+ exit_program(1);
+ tmp_pkt = av_packet_alloc();
+ if (!tmp_pkt)
+ exit_program(1);
+ av_packet_move_ref(tmp_pkt, pkt);
+ ost->muxing_queue_data_size += tmp_pkt->size;
+ av_fifo_write(ost->muxing_queue, &tmp_pkt, 1);
+ return;
+ }
+
+ if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
+ (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
+ pkt->pts = pkt->dts = AV_NOPTS_VALUE;
+
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+ int i;
+ uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
+ NULL);
+ ost->quality = sd ? AV_RL32(sd) : -1;
+ ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE;
+
+ for (i = 0; i<FF_ARRAY_ELEMS(ost->error); i++) {
+ if (sd && i < sd[5])
+ ost->error[i] = AV_RL64(sd + 8 + 8*i);
+ else
+ ost->error[i] = -1;
+ }
+
+ if (ost->frame_rate.num && ost->is_cfr) {
+ if (pkt->duration > 0)
+ av_log(NULL, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n");
+ pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate),
+ ost->mux_timebase);
+ }
+ }
+
+ av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base);
+
+ if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
+ if (pkt->dts != AV_NOPTS_VALUE &&
+ pkt->pts != AV_NOPTS_VALUE &&
+ pkt->dts > pkt->pts) {
+ av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n",
+ pkt->dts, pkt->pts,
+ ost->file_index, ost->st->index);
+ pkt->pts =
+ pkt->dts = pkt->pts + pkt->dts + ost->last_mux_dts + 1
+ - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1)
+ - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1);
+ }
+ if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) &&
+ pkt->dts != AV_NOPTS_VALUE &&
+ ost->last_mux_dts != AV_NOPTS_VALUE) {
+ int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
+ if (pkt->dts < max) {
+ int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
+ if (exit_on_error)
+ loglevel = AV_LOG_ERROR;
+ av_log(s, loglevel, "Non-monotonous DTS in output stream "
+ "%d:%d; previous: %"PRId64", current: %"PRId64"; ",
+ ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts);
+ if (exit_on_error) {
+ av_log(NULL, AV_LOG_FATAL, "aborting.\n");
+ exit_program(1);
+ }
+ av_log(s, loglevel, "changing to %"PRId64". This may result "
+ "in incorrect timestamps in the output file.\n",
+ max);
+ if (pkt->pts >= pkt->dts)
+ pkt->pts = FFMAX(pkt->pts, max);
+ pkt->dts = max;
+ }
+ }
+ }
+ ost->last_mux_dts = pkt->dts;
+
+ ost->data_size += pkt->size;
+ ost->packets_written++;
+
+ pkt->stream_index = ost->index;
+
+ if (debug_ts) {
+ av_log(NULL, AV_LOG_INFO, "muxer <- type:%s "
+ "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n",
+ av_get_media_type_string(ost->enc_ctx->codec_type),
+ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base),
+ av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base),
+ av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base),
+ pkt->size
+ );
+ }
+
+ ret = av_interleaved_write_frame(s, pkt);
+ if (ret < 0) {
+ print_error("av_interleaved_write_frame()", ret);
+ main_return_code = 1;
+ close_all_output_streams(ost, MUXER_FINISHED | ENCODER_FINISHED, ENCODER_FINISHED);
+ }
+}
+
+static int print_sdp(void)
+{
+ char sdp[16384];
+ int i;
+ int j, ret;
+ AVIOContext *sdp_pb;
+ AVFormatContext **avc;
+
+ for (i = 0; i < nb_output_files; i++) {
+ if (!output_files[i]->header_written)
+ return 0;
+ }
+
+ avc = av_malloc_array(nb_output_files, sizeof(*avc));
+ if (!avc)
+ exit_program(1);
+ for (i = 0, j = 0; i < nb_output_files; i++) {
+ if (!strcmp(output_files[i]->ctx->oformat->name, "rtp")) {
+ avc[j] = output_files[i]->ctx;
+ j++;
+ }
+ }
+
+ if (!j) {
+ av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n");
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ ret = av_sdp_create(avc, j, sdp, sizeof(sdp));
+ if (ret < 0)
+ goto fail;
+
+ if (!sdp_filename) {
+ printf("SDP:\n%s\n", sdp);
+ fflush(stdout);
+ } else {
+ ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename);
+ goto fail;
+ }
+
+ avio_print(sdp_pb, sdp);
+ avio_closep(&sdp_pb);
+ av_freep(&sdp_filename);
+ }
+
+fail:
+ av_freep(&avc);
+ return ret;
+}
+
+/* open the muxer when all the streams are initialized */
+int of_check_init(OutputFile *of)
+{
+ int ret, i;
+
+ for (i = 0; i < of->ctx->nb_streams; i++) {
+ OutputStream *ost = output_streams[of->ost_index + i];
+ if (!ost->initialized)
+ return 0;
+ }
+
+ ret = avformat_write_header(of->ctx, &of->opts);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Could not write header for output file #%d "
+ "(incorrect codec parameters ?): %s\n",
+ of->index, av_err2str(ret));
+ return ret;
+ }
+ //assert_avoptions(of->opts);
+ of->header_written = 1;
+
+ av_dump_format(of->ctx, of->index, of->ctx->url, 1);
+ nb_output_dumped++;
+
+ if (sdp_filename || want_sdp) {
+ ret = print_sdp();
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error writing the SDP.\n");
+ return ret;
+ }
+ }
+
+ /* flush the muxing queues */
+ for (i = 0; i < of->ctx->nb_streams; i++) {
+ OutputStream *ost = output_streams[of->ost_index + i];
+ AVPacket *pkt;
+
+ /* try to improve muxing time_base (only possible if nothing has been written yet) */
+ if (!av_fifo_can_read(ost->muxing_queue))
+ ost->mux_timebase = ost->st->time_base;
+
+ while (av_fifo_read(ost->muxing_queue, &pkt, 1) >= 0) {
+ ost->muxing_queue_data_size -= pkt->size;
+ of_write_packet(of, pkt, ost, 1);
+ av_packet_free(&pkt);
+ }
+ }
+
+ return 0;
+}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 07/49] fftools/ffmpeg: move writing the trailer to ffmpeg_mux.c
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (5 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 06/49] fftools/ffmpeg: move some muxing-related code into a separate file Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 08/49] fftools/ffmpeg: move freeing the output file " Anton Khirnov
` (44 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 16 +++-------------
fftools/ffmpeg.h | 1 +
fftools/ffmpeg_mux.c | 21 +++++++++++++++++++++
3 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 47724f7231..cc7855a4cc 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -4450,19 +4450,9 @@ static int transcode(void)
/* write the trailer if needed */
for (i = 0; i < nb_output_files; i++) {
- os = output_files[i]->ctx;
- if (!output_files[i]->header_written) {
- av_log(NULL, AV_LOG_ERROR,
- "Nothing was written into output file %d (%s), because "
- "at least one of its streams received no packets.\n",
- i, os->url);
- continue;
- }
- if ((ret = av_write_trailer(os)) < 0) {
- av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", os->url, av_err2str(ret));
- if (exit_on_error)
- exit_program(1);
- }
+ ret = of_write_trailer(output_files[i]);
+ if (ret < 0 && exit_on_error)
+ exit_program(1);
}
/* dump report by using the first video and audio streams */
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index cb475bb690..4425b7a874 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -689,6 +689,7 @@ int hwaccel_decode_init(AVCodecContext *avctx);
/* open the muxer when all the streams are initialized */
int of_check_init(OutputFile *of);
+int of_write_trailer(OutputFile *of);
void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
int unqueue);
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 92d8a8c088..5348eef01d 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -290,3 +290,24 @@ int of_check_init(OutputFile *of)
return 0;
}
+
+int of_write_trailer(OutputFile *of)
+{
+ int ret;
+
+ if (!of->header_written) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Nothing was written into output file %d (%s), because "
+ "at least one of its streams received no packets.\n",
+ of->index, of->ctx->url);
+ return AVERROR(EINVAL);
+ }
+
+ ret = av_write_trailer(of->ctx);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", of->ctx->url, av_err2str(ret));
+ return ret;
+ }
+
+ return 0;
+}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 08/49] fftools/ffmpeg: move freeing the output file to ffmpeg_mux.c
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (6 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 07/49] fftools/ffmpeg: move writing the trailer to ffmpeg_mux.c Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 09/49] fftools/ffmpeg: store output format separately from the muxer context Anton Khirnov
` (43 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 14 ++------------
fftools/ffmpeg.h | 1 +
fftools/ffmpeg_mux.c | 17 +++++++++++++++++
3 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index cc7855a4cc..69d1949103 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -565,19 +565,9 @@ static void ffmpeg_cleanup(int ret)
av_freep(&subtitle_out);
/* close files */
- for (i = 0; i < nb_output_files; i++) {
- OutputFile *of = output_files[i];
- AVFormatContext *s;
- if (!of)
- continue;
- s = of->ctx;
- if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE))
- avio_closep(&s->pb);
- avformat_free_context(s);
- av_dict_free(&of->opts);
+ for (i = 0; i < nb_output_files; i++)
+ of_close(&output_files[i]);
- av_freep(&output_files[i]);
- }
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 4425b7a874..ff8ebbfab5 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -690,6 +690,7 @@ int hwaccel_decode_init(AVCodecContext *avctx);
/* open the muxer when all the streams are initialized */
int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
+void of_close(OutputFile **pof);
void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
int unqueue);
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 5348eef01d..3cdaa494d7 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -311,3 +311,20 @@ int of_write_trailer(OutputFile *of)
return 0;
}
+
+void of_close(OutputFile **pof)
+{
+ OutputFile *of = *pof;
+ AVFormatContext *s;
+
+ if (!of)
+ return;
+
+ s = of->ctx;
+ if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE))
+ avio_closep(&s->pb);
+ avformat_free_context(s);
+ av_dict_free(&of->opts);
+
+ av_freep(pof);
+}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 09/49] fftools/ffmpeg: store output format separately from the muxer context
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (7 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 08/49] fftools/ffmpeg: move freeing the output file " Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-06 12:00 ` James Almer
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 10/49] fftools/ffmpeg_mux: add private " Anton Khirnov
` (42 subsequent siblings)
51 siblings, 1 reply; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
Allows accessing it without going through the muxer context. This will
be useful in the following commits, where the muxer context will be
hidden.
---
fftools/ffmpeg.c | 18 ++++++++++--------
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_opt.c | 1 +
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 69d1949103..a85ed18b08 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2789,9 +2789,9 @@ static int init_output_stream_streamcopy(OutputStream *ost)
if (!codec_tag) {
unsigned int codec_tag_tmp;
- if (!of->ctx->oformat->codec_tag ||
- av_codec_get_id (of->ctx->oformat->codec_tag, par_src->codec_tag) == par_src->codec_id ||
- !av_codec_get_tag2(of->ctx->oformat->codec_tag, par_src->codec_id, &codec_tag_tmp))
+ if (!of->format->codec_tag ||
+ av_codec_get_id (of->format->codec_tag, par_src->codec_tag) == par_src->codec_id ||
+ !av_codec_get_tag2(of->format->codec_tag, par_src->codec_id, &codec_tag_tmp))
codec_tag = par_src->codec_tag;
}
@@ -2809,7 +2809,7 @@ static int init_output_stream_streamcopy(OutputStream *ost)
else
ost->st->avg_frame_rate = ist->st->avg_frame_rate;
- ret = avformat_transfer_internal_stream_timing_info(of->ctx->oformat, ost->st, ist->st, copy_tb);
+ ret = avformat_transfer_internal_stream_timing_info(of->format, ost->st, ist->st, copy_tb);
if (ret < 0)
return ret;
@@ -3011,7 +3011,8 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
InputStream *ist = get_input_stream(ost);
AVCodecContext *enc_ctx = ost->enc_ctx;
AVCodecContext *dec_ctx = NULL;
- AVFormatContext *oc = output_files[ost->file_index]->ctx;
+ OutputFile *of = output_files[ost->file_index];
+ AVFormatContext *oc = of->ctx;
int ret;
set_encoder_id(output_files[ost->file_index], ost);
@@ -3072,7 +3073,8 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
if (!(enc_ctx->time_base.num && enc_ctx->time_base.den))
enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter);
if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
- && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
+ && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR ||
+ (video_sync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){
av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n"
"Please consider specifying a lower framerate, a different muxer or -vsync 2\n");
}
@@ -3405,7 +3407,7 @@ static int transcode_init(void)
/* write headers for files with no streams */
for (i = 0; i < nb_output_files; i++) {
oc = output_files[i]->ctx;
- if (oc->oformat->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) {
+ if (output_files[i]->format->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) {
ret = of_check_init(output_files[i]);
if (ret < 0)
goto dump_format;
@@ -4615,7 +4617,7 @@ int main(int argc, char **argv)
}
for (i = 0; i < nb_output_files; i++) {
- if (strcmp(output_files[i]->ctx->oformat->name, "rtp"))
+ if (strcmp(output_files[i]->format->name, "rtp"))
want_sdp = 0;
}
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index ff8ebbfab5..9f0c093e34 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -579,6 +579,8 @@ typedef struct OutputStream {
typedef struct OutputFile {
int index;
+ const AVOutputFormat *format;
+
AVFormatContext *ctx;
AVDictionary *opts;
int ost_index; /* index of the first stream in output_streams */
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index daecba9e57..47e8b9b7bd 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2332,6 +2332,7 @@ static int open_output_file(OptionsContext *o, const char *filename)
}
of->ctx = oc;
+ of->format = oc->oformat;
if (o->recording_time != INT64_MAX)
oc->duration = o->recording_time;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 10/49] fftools/ffmpeg_mux: add private muxer context
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (8 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 09/49] fftools/ffmpeg: store output format separately from the muxer context Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 11/49] fftools/ffmpeg: add a helper function to access output file size Anton Khirnov
` (41 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
Move header_written into it, which is not (and should not be) used by
any code outside of ffmpeg_mux.
In the future this context will contain more muxer-private state that
should not be visible to other code.
---
fftools/ffmpeg.h | 6 ++++--
fftools/ffmpeg_mux.c | 26 ++++++++++++++++++++++----
fftools/ffmpeg_opt.c | 6 ++++++
3 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 9f0c093e34..3db03e0cfe 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -576,9 +576,12 @@ typedef struct OutputStream {
int64_t error[4];
} OutputStream;
+typedef struct Muxer Muxer;
+
typedef struct OutputFile {
int index;
+ Muxer *mux;
const AVOutputFormat *format;
AVFormatContext *ctx;
@@ -589,8 +592,6 @@ typedef struct OutputFile {
uint64_t limit_filesize; /* filesize limit expressed in bytes */
int shortest;
-
- int header_written;
} OutputFile;
extern InputStream **input_streams;
@@ -689,6 +690,7 @@ int hw_device_setup_for_filter(FilterGraph *fg);
int hwaccel_decode_init(AVCodecContext *avctx);
+int of_muxer_init(OutputFile *of);
/* open the muxer when all the streams are initialized */
int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 3cdaa494d7..84c94e46be 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -32,6 +32,10 @@
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
+struct Muxer {
+ int header_written;
+};
+
static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others)
{
int i;
@@ -64,7 +68,7 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
ost->frame_number++;
}
- if (!of->header_written) {
+ if (!of->mux->header_written) {
AVPacket *tmp_pkt;
/* the muxer is not initialized yet, buffer the packet */
if (!av_fifo_can_write(ost->muxing_queue)) {
@@ -195,7 +199,7 @@ static int print_sdp(void)
AVFormatContext **avc;
for (i = 0; i < nb_output_files; i++) {
- if (!output_files[i]->header_written)
+ if (!output_files[i]->mux->header_written)
return 0;
}
@@ -259,7 +263,7 @@ int of_check_init(OutputFile *of)
return ret;
}
//assert_avoptions(of->opts);
- of->header_written = 1;
+ of->mux->header_written = 1;
av_dump_format(of->ctx, of->index, of->ctx->url, 1);
nb_output_dumped++;
@@ -295,7 +299,7 @@ int of_write_trailer(OutputFile *of)
{
int ret;
- if (!of->header_written) {
+ if (!of->mux->header_written) {
av_log(NULL, AV_LOG_ERROR,
"Nothing was written into output file %d (%s), because "
"at least one of its streams received no packets.\n",
@@ -326,5 +330,19 @@ void of_close(OutputFile **pof)
avformat_free_context(s);
av_dict_free(&of->opts);
+ av_freep(&of->mux);
+
av_freep(pof);
}
+
+int of_muxer_init(OutputFile *of)
+{
+ Muxer *mux = av_mallocz(sizeof(*mux));
+
+ if (!mux)
+ return AVERROR(ENOMEM);
+
+ of->mux = mux;
+
+ return 0;
+}
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 47e8b9b7bd..fff230eafc 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2921,6 +2921,12 @@ loop_end:
exit_program(1);
}
+ err = of_muxer_init(of);
+ if (err < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Error initializing internal muxing state\n");
+ exit_program(1);
+ }
+
return 0;
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 11/49] fftools/ffmpeg: add a helper function to access output file size
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (9 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 10/49] fftools/ffmpeg_mux: add private " Anton Khirnov
@ 2022-04-04 11:29 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 12/49] fftools/ffmpeg: fix the type of limit_filesize Anton Khirnov
` (40 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:29 UTC (permalink / raw)
To: ffmpeg-devel
Stop accessing muxer internals from outside of ffmpeg_mux.
---
fftools/ffmpeg.c | 10 +---------
fftools/ffmpeg.h | 1 +
fftools/ffmpeg_mux.c | 14 ++++++++++++++
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index a85ed18b08..52dffa57bd 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1513,8 +1513,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
{
AVBPrint buf, buf_script;
OutputStream *ost;
- AVFormatContext *oc;
- int64_t total_size;
+ int64_t total_size = of_filesize(output_files[0]);
AVCodecContext *enc;
int frame_number, vid, i;
double bitrate;
@@ -1543,13 +1542,6 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
t = (cur_time-timer_start) / 1000000.0;
-
- oc = output_files[0]->ctx;
-
- total_size = avio_size(oc->pb);
- if (total_size <= 0) // FIXME improve avio_size() so it works with non seekable output too
- total_size = avio_tell(oc->pb);
-
vid = 0;
av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC);
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 3db03e0cfe..fa7b202ae6 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -698,5 +698,6 @@ void of_close(OutputFile **pof);
void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
int unqueue);
+int64_t of_filesize(OutputFile *of);
#endif /* FFTOOLS_FFMPEG_H */
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 84c94e46be..930a7bdfe7 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -346,3 +346,17 @@ int of_muxer_init(OutputFile *of)
return 0;
}
+
+int64_t of_filesize(OutputFile *of)
+{
+ AVIOContext *pb = of->ctx->pb;
+ int64_t ret = -1;
+
+ if (pb) {
+ ret = avio_size(pb);
+ if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too
+ ret = avio_tell(pb);
+ }
+
+ return ret;
+}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 12/49] fftools/ffmpeg: fix the type of limit_filesize
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (10 preceding siblings ...)
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 11/49] fftools/ffmpeg: add a helper function to access output file size Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 13/49] fftools/ffmpeg: refactor limiting output file size with -fs Anton Khirnov
` (39 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
The option is parsed as INT64 (signed). It is also compared to the
output of avio_tell(), which is also int64_t.
---
fftools/ffmpeg.h | 4 ++--
fftools/ffmpeg_opt.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index fa7b202ae6..d76f4266d6 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -147,7 +147,7 @@ typedef struct OptionsContext {
int64_t recording_time;
int64_t stop_time;
- uint64_t limit_filesize;
+ int64_t limit_filesize;
float mux_preload;
float mux_max_delay;
int shortest;
@@ -589,7 +589,7 @@ typedef struct OutputFile {
int ost_index; /* index of the first stream in output_streams */
int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units
int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units
- uint64_t limit_filesize; /* filesize limit expressed in bytes */
+ int64_t limit_filesize; /* filesize limit expressed in bytes */
int shortest;
} OutputFile;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index fff230eafc..4e601f1cf8 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -228,7 +228,7 @@ static void init_options(OptionsContext *o)
o->start_time = AV_NOPTS_VALUE;
o->start_time_eof = AV_NOPTS_VALUE;
o->recording_time = INT64_MAX;
- o->limit_filesize = UINT64_MAX;
+ o->limit_filesize = INT64_MAX;
o->chapters_input_file = INT_MAX;
o->accurate_seek = 1;
o->thread_queue_size = -1;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 13/49] fftools/ffmpeg: refactor limiting output file size with -fs
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (11 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 12/49] fftools/ffmpeg: fix the type of limit_filesize Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 14/49] fftools/ffmpeg: set want_sdp when initializing the muxer Anton Khirnov
` (38 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Move the file size checking code to ffmpeg_mux. Use the recently
introduced of_filesize(), making this code consistent with the size
shown by print_report().
---
fftools/ffmpeg.c | 4 +---
fftools/ffmpeg.h | 4 ++--
fftools/ffmpeg_mux.c | 11 ++++++++++-
fftools/ffmpeg_opt.c | 3 +--
4 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 52dffa57bd..05e14c42c5 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -3508,10 +3508,8 @@ static int need_output(void)
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
OutputFile *of = output_files[ost->file_index];
- AVFormatContext *os = output_files[ost->file_index]->ctx;
- if (ost->finished ||
- (os->pb && avio_tell(os->pb) >= of->limit_filesize))
+ if (ost->finished || of_finished(of))
continue;
if (ost->frame_number >= ost->max_frames) {
int j;
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index d76f4266d6..c3b90ac9a2 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -589,7 +589,6 @@ typedef struct OutputFile {
int ost_index; /* index of the first stream in output_streams */
int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units
int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units
- int64_t limit_filesize; /* filesize limit expressed in bytes */
int shortest;
} OutputFile;
@@ -690,7 +689,7 @@ int hw_device_setup_for_filter(FilterGraph *fg);
int hwaccel_decode_init(AVCodecContext *avctx);
-int of_muxer_init(OutputFile *of);
+int of_muxer_init(OutputFile *of, int64_t limit_filesize);
/* open the muxer when all the streams are initialized */
int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
@@ -698,6 +697,7 @@ void of_close(OutputFile **pof);
void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
int unqueue);
+int of_finished(OutputFile *of);
int64_t of_filesize(OutputFile *of);
#endif /* FFTOOLS_FFMPEG_H */
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 930a7bdfe7..78bb338bce 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -33,6 +33,8 @@
#include "libavformat/avio.h"
struct Muxer {
+ /* filesize limit expressed in bytes */
+ int64_t limit_filesize;
int header_written;
};
@@ -335,7 +337,7 @@ void of_close(OutputFile **pof)
av_freep(pof);
}
-int of_muxer_init(OutputFile *of)
+int of_muxer_init(OutputFile *of, int64_t limit_filesize)
{
Muxer *mux = av_mallocz(sizeof(*mux));
@@ -344,9 +346,16 @@ int of_muxer_init(OutputFile *of)
of->mux = mux;
+ mux->limit_filesize = limit_filesize;
+
return 0;
}
+int of_finished(OutputFile *of)
+{
+ return of_filesize(of) >= of->mux->limit_filesize;
+}
+
int64_t of_filesize(OutputFile *of)
{
AVIOContext *pb = of->ctx->pb;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 4e601f1cf8..4a41ebc736 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2318,7 +2318,6 @@ static int open_output_file(OptionsContext *o, const char *filename)
of->ost_index = nb_output_streams;
of->recording_time = o->recording_time;
of->start_time = o->start_time;
- of->limit_filesize = o->limit_filesize;
of->shortest = o->shortest;
av_dict_copy(&of->opts, o->g->format_opts, 0);
@@ -2921,7 +2920,7 @@ loop_end:
exit_program(1);
}
- err = of_muxer_init(of);
+ err = of_muxer_init(of, o->limit_filesize);
if (err < 0) {
av_log(NULL, AV_LOG_FATAL, "Error initializing internal muxing state\n");
exit_program(1);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 14/49] fftools/ffmpeg: set want_sdp when initializing the muxer
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (12 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 13/49] fftools/ffmpeg: refactor limiting output file size with -fs Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 15/49] fftools/ffmpeg: write the header for stream-less outputs " Anton Khirnov
` (37 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Allows making the variable local to ffmpeg_mux.
---
fftools/ffmpeg.c | 9 +--------
fftools/ffmpeg.h | 1 -
fftools/ffmpeg_mux.c | 5 +++++
3 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 05e14c42c5..688e1c7e56 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -139,8 +139,6 @@ static int nb_frames_drop = 0;
static int64_t decode_error_stat[2];
unsigned nb_output_dumped = 0;
-int want_sdp = 1;
-
static BenchmarkTimeStamps current_time;
AVIOContext *progress_avio = NULL;
@@ -4563,7 +4561,7 @@ static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
int main(int argc, char **argv)
{
- int i, ret;
+ int ret;
BenchmarkTimeStamps ti;
init_dynload();
@@ -4606,11 +4604,6 @@ int main(int argc, char **argv)
exit_program(1);
}
- for (i = 0; i < nb_output_files; i++) {
- if (strcmp(output_files[i]->format->name, "rtp"))
- want_sdp = 0;
- }
-
current_time = ti = get_benchmark_time_stamps();
if (transcode() < 0)
exit_program(1);
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index c3b90ac9a2..d0ddaeaeff 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -649,7 +649,6 @@ extern char *qsv_device;
#endif
extern HWDevice *filter_hw_device;
-extern int want_sdp;
extern unsigned nb_output_dumped;
extern int main_return_code;
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 78bb338bce..f1ec5881c4 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -38,6 +38,8 @@ struct Muxer {
int header_written;
};
+static int want_sdp = 1;
+
static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others)
{
int i;
@@ -348,6 +350,9 @@ int of_muxer_init(OutputFile *of, int64_t limit_filesize)
mux->limit_filesize = limit_filesize;
+ if (strcmp(of->format->name, "rtp"))
+ want_sdp = 0;
+
return 0;
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 15/49] fftools/ffmpeg: write the header for stream-less outputs when initializing the muxer
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (13 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 14/49] fftools/ffmpeg: set want_sdp when initializing the muxer Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 16/49] fftools/ffmpeg: move closing the file into of_write_trailer() Anton Khirnov
` (36 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
There is no reason to delay this.
---
fftools/ffmpeg.c | 11 -----------
fftools/ffmpeg_mux.c | 7 +++++++
2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 688e1c7e56..e862a57215 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -3320,7 +3320,6 @@ static void report_new_stream(int input_index, AVPacket *pkt)
static int transcode_init(void)
{
int ret = 0, i, j, k;
- AVFormatContext *oc;
OutputStream *ost;
InputStream *ist;
char error[1024] = {0};
@@ -3394,16 +3393,6 @@ static int transcode_init(void)
}
}
- /* write headers for files with no streams */
- for (i = 0; i < nb_output_files; i++) {
- oc = output_files[i]->ctx;
- if (output_files[i]->format->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) {
- ret = of_check_init(output_files[i]);
- if (ret < 0)
- goto dump_format;
- }
- }
-
dump_format:
/* dump the stream mapping */
av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index f1ec5881c4..2a95b2602d 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -353,6 +353,13 @@ int of_muxer_init(OutputFile *of, int64_t limit_filesize)
if (strcmp(of->format->name, "rtp"))
want_sdp = 0;
+ /* write the header for files with no streams */
+ if (of->format->flags & AVFMT_NOSTREAMS && of->ctx->nb_streams == 0) {
+ int ret = of_check_init(of);
+ if (ret < 0)
+ return ret;
+ }
+
return 0;
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 16/49] fftools/ffmpeg: move closing the file into of_write_trailer()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (14 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 15/49] fftools/ffmpeg: write the header for stream-less outputs " Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 17/49] fftools/ffmpeg: refactor the code checking for bitexact output Anton Khirnov
` (35 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
The current code postpones closing the files until after printing the
final report, which accesses the output file size. Deal with this by
storing the final file size before closing the file.
---
fftools/ffmpeg.c | 13 -------------
fftools/ffmpeg_mux.c | 16 +++++++++++++++-
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index e862a57215..252b14a710 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -4358,7 +4358,6 @@ static int transcode_step(void)
static int transcode(void)
{
int ret, i;
- AVFormatContext *os;
OutputStream *ost;
InputStream *ist;
int64_t timer_start;
@@ -4427,18 +4426,6 @@ static int transcode(void)
/* dump report by using the first video and audio streams */
print_report(1, timer_start, av_gettime_relative());
- /* close the output files */
- for (i = 0; i < nb_output_files; i++) {
- os = output_files[i]->ctx;
- if (os && os->oformat && !(os->oformat->flags & AVFMT_NOFILE)) {
- if ((ret = avio_closep(&os->pb)) < 0) {
- av_log(NULL, AV_LOG_ERROR, "Error closing file %s: %s\n", os->url, av_err2str(ret));
- if (exit_on_error)
- exit_program(1);
- }
- }
- }
-
/* close each encoder */
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 2a95b2602d..927d9228b7 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -35,6 +35,7 @@
struct Muxer {
/* filesize limit expressed in bytes */
int64_t limit_filesize;
+ int64_t final_filesize;
int header_written;
};
@@ -317,6 +318,17 @@ int of_write_trailer(OutputFile *of)
return ret;
}
+ of->mux->final_filesize = of_filesize(of);
+
+ if (!(of->format->flags & AVFMT_NOFILE)) {
+ ret = avio_closep(&of->ctx->pb);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error closing file %s: %s\n",
+ of->ctx->url, av_err2str(ret));
+ return ret;
+ }
+ }
+
return 0;
}
@@ -373,7 +385,9 @@ int64_t of_filesize(OutputFile *of)
AVIOContext *pb = of->ctx->pb;
int64_t ret = -1;
- if (pb) {
+ if (of->mux->final_filesize)
+ ret = of->mux->final_filesize;
+ else if (pb) {
ret = avio_size(pb);
if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too
ret = avio_tell(pb);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 17/49] fftools/ffmpeg: refactor the code checking for bitexact output
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (15 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 16/49] fftools/ffmpeg: move closing the file into of_write_trailer() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 18/49] fftools/ffmpeg: access output file chapters through a wrapper Anton Khirnov
` (34 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Figure out earlier whether the output stream/file should be bitexact and
store this information in a flag in OutputFile/OutputStream.
Stop accessing the muxer in set_encoder_id(), which will become
forbidden in future commits.
---
fftools/ffmpeg.c | 21 +--------------------
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_opt.c | 27 ++++++++++++++++++++++++++-
3 files changed, 29 insertions(+), 21 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 252b14a710..dfd57d2d03 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2870,37 +2870,18 @@ static int init_output_stream_streamcopy(OutputStream *ost)
static void set_encoder_id(OutputFile *of, OutputStream *ost)
{
- const AVDictionaryEntry *e;
-
uint8_t *encoder_string;
int encoder_string_len;
- int format_flags = 0;
- int codec_flags = ost->enc_ctx->flags;
if (av_dict_get(ost->st->metadata, "encoder", NULL, 0))
return;
- e = av_dict_get(of->opts, "fflags", NULL, 0);
- if (e) {
- const AVOption *o = av_opt_find(of->ctx, "fflags", NULL, 0, 0);
- if (!o)
- return;
- av_opt_eval_flags(of->ctx, o, e->value, &format_flags);
- }
- e = av_dict_get(ost->encoder_opts, "flags", NULL, 0);
- if (e) {
- const AVOption *o = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0);
- if (!o)
- return;
- av_opt_eval_flags(ost->enc_ctx, o, e->value, &codec_flags);
- }
-
encoder_string_len = sizeof(LIBAVCODEC_IDENT) + strlen(ost->enc->name) + 2;
encoder_string = av_mallocz(encoder_string_len);
if (!encoder_string)
exit_program(1);
- if (!(format_flags & AVFMT_FLAG_BITEXACT) && !(codec_flags & AV_CODEC_FLAG_BITEXACT))
+ if (!of->bitexact && !ost->bitexact)
av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
else
av_strlcpy(encoder_string, "Lavc ", encoder_string_len);
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index d0ddaeaeff..ec0d454fcc 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -493,6 +493,7 @@ typedef struct OutputStream {
int top_field_first;
int rotate_overridden;
int autoscale;
+ int bitexact;
int bits_per_raw_sample;
double rotate_override_value;
@@ -591,6 +592,7 @@ typedef struct OutputFile {
int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units
int shortest;
+ int bitexact;
} OutputFile;
extern InputStream **input_streams;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 4a41ebc736..780c11903b 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1437,6 +1437,22 @@ static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *o
return 0;
}
+static int check_opt_bitexact(void *ctx, const AVDictionary *opts,
+ const char *opt_name, int flag)
+{
+ const AVDictionaryEntry *e = av_dict_get(opts, opt_name, NULL, 0);
+
+ if (e) {
+ const AVOption *o = av_opt_find(ctx, opt_name, NULL, 0, 0);
+ int val = 0;
+ if (!o)
+ return 0;
+ av_opt_eval_flags(ctx, o, e->value, &val);
+ return !!(val & flag);
+ }
+ return 0;
+}
+
static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type, int source_index)
{
OutputStream *ost;
@@ -1529,8 +1545,13 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
}
- if (o->bitexact)
+ if (o->bitexact) {
ost->enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
+ ost->bitexact = 1;
+ } else {
+ ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags",
+ AV_CODEC_FLAG_BITEXACT);
+ }
MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st);
if (time_base) {
@@ -2339,6 +2360,10 @@ static int open_output_file(OptionsContext *o, const char *filename)
if (o->bitexact) {
oc->flags |= AVFMT_FLAG_BITEXACT;
+ of->bitexact = 1;
+ } else {
+ of->bitexact = check_opt_bitexact(oc, of->opts, "fflags",
+ AVFMT_FLAG_BITEXACT);
}
/* create streams for all unlabeled output pads */
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 18/49] fftools/ffmpeg: access output file chapters through a wrapper
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (16 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 17/49] fftools/ffmpeg: refactor the code checking for bitexact output Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 19/49] fftools/ffmpeg: do not log to the muxer context Anton Khirnov
` (33 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Avoid accessing the muxer context directly, as this will become
forbidden in future commits.
---
fftools/ffmpeg.c | 15 +++++++++------
fftools/ffmpeg.h | 2 ++
fftools/ffmpeg_mux.c | 7 +++++++
3 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index dfd57d2d03..b9ecbf4739 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2915,12 +2915,15 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost,
*next++ = 0;
if (!memcmp(p, "chapters", 8)) {
-
- AVFormatContext *avf = output_files[ost->file_index]->ctx;
+ OutputFile *of = output_files[ost->file_index];
+ AVChapter * const *ch;
+ unsigned int nb_ch;
int j;
- if (avf->nb_chapters > INT_MAX - size ||
- !(pts = av_realloc_f(pts, size += avf->nb_chapters - 1,
+ ch = of_get_chapters(of, &nb_ch);
+
+ if (nb_ch > INT_MAX - size ||
+ !(pts = av_realloc_f(pts, size += nb_ch - 1,
sizeof(*pts)))) {
av_log(NULL, AV_LOG_FATAL,
"Could not allocate forced key frames array.\n");
@@ -2929,8 +2932,8 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost,
t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0;
t = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
- for (j = 0; j < avf->nb_chapters; j++) {
- AVChapter *c = avf->chapters[j];
+ for (j = 0; j < nb_ch; j++) {
+ const AVChapter *c = ch[j];
av_assert1(index < size);
pts[index++] = av_rescale_q(c->start, c->time_base,
avctx->time_base) + t;
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index ec0d454fcc..8e34ae0702 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -700,5 +700,7 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
int unqueue);
int of_finished(OutputFile *of);
int64_t of_filesize(OutputFile *of);
+AVChapter * const *
+of_get_chapters(OutputFile *of, unsigned int *nb_chapters);
#endif /* FFTOOLS_FFMPEG_H */
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 927d9228b7..9dd5e8b076 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -395,3 +395,10 @@ int64_t of_filesize(OutputFile *of)
return ret;
}
+
+AVChapter * const *
+of_get_chapters(OutputFile *of, unsigned int *nb_chapters)
+{
+ *nb_chapters = of->ctx->nb_chapters;
+ return of->ctx->chapters;
+}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 19/49] fftools/ffmpeg: do not log to the muxer context
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (17 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 18/49] fftools/ffmpeg: access output file chapters through a wrapper Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 20/49] fftools/ffmpeg: move the mux queue into muxer private data Anton Khirnov
` (32 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
All other logging goes to NULL context.
---
fftools/ffmpeg.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index b9ecbf4739..a9a62eb8c3 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -2960,7 +2960,6 @@ static void init_encoder_time_base(OutputStream *ost, AVRational default_time_ba
{
InputStream *ist = get_input_stream(ost);
AVCodecContext *enc_ctx = ost->enc_ctx;
- AVFormatContext *oc;
if (ost->enc_timebase.num > 0) {
enc_ctx->time_base = ost->enc_timebase;
@@ -2973,8 +2972,9 @@ static void init_encoder_time_base(OutputStream *ost, AVRational default_time_ba
return;
}
- oc = output_files[ost->file_index]->ctx;
- av_log(oc, AV_LOG_WARNING, "Input stream data not available, using default time base\n");
+ av_log(NULL, AV_LOG_WARNING,
+ "Input stream data for output stream #%d:%d not available, "
+ "using default time base\n", ost->file_index, ost->index);
}
enc_ctx->time_base = default_time_base;
@@ -2986,7 +2986,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
AVCodecContext *enc_ctx = ost->enc_ctx;
AVCodecContext *dec_ctx = NULL;
OutputFile *of = output_files[ost->file_index];
- AVFormatContext *oc = of->ctx;
int ret;
set_encoder_id(output_files[ost->file_index], ost);
@@ -3049,8 +3048,9 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
&& (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR ||
(video_sync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){
- av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n"
- "Please consider specifying a lower framerate, a different muxer or -vsync 2\n");
+ av_log(NULL, AV_LOG_WARNING, "Frame rate in output stream #%d:%d very high for a muxer not efficiently supporting it.\n"
+ "Please consider specifying a lower framerate, a different muxer or -vsync 2\n",
+ ost->file_index, ost->index);
}
enc_ctx->width = av_buffersink_get_w(ost->filter->filter);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 20/49] fftools/ffmpeg: move the mux queue into muxer private data
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (18 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 19/49] fftools/ffmpeg: do not log to the muxer context Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 21/49] fftools/ffmpeg_mux: split queuing packets into a separate function Anton Khirnov
` (31 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
The muxing queue currently lives in OutputStream, which is a very large
struct storing the state for both encoding and muxing. The muxing queue
is only used by the code in ffmpeg_mux, so it makes sense to restrict it
to that file.
This makes the first step towards reducing the scope of OutputStream.
---
fftools/ffmpeg.c | 7 ----
fftools/ffmpeg.h | 9 -----
fftools/ffmpeg_mux.c | 87 +++++++++++++++++++++++++++++++++++++-------
fftools/ffmpeg_opt.c | 9 -----
4 files changed, 73 insertions(+), 39 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index a9a62eb8c3..b240bbd984 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -593,13 +593,6 @@ static void ffmpeg_cleanup(int ret)
avcodec_free_context(&ost->enc_ctx);
avcodec_parameters_free(&ost->ref_par);
- if (ost->muxing_queue) {
- AVPacket *pkt;
- while (av_fifo_read(ost->muxing_queue, &pkt, 1) >= 0)
- av_packet_free(&pkt);
- av_fifo_freep2(&ost->muxing_queue);
- }
-
av_freep(&output_streams[i]);
}
#if HAVE_THREADS
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 8e34ae0702..f0c3a3de7c 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -558,15 +558,6 @@ typedef struct OutputStream {
int max_muxing_queue_size;
- /* the packets are buffered here until the muxer is ready to be initialized */
- AVFifo *muxing_queue;
-
- /*
- * The size of the AVPackets' buffers in queue.
- * Updated when a packet is either pushed or pulled from the queue.
- */
- size_t muxing_queue_data_size;
-
/* Threshold after which max_muxing_queue_size will be in effect */
size_t muxing_queue_data_threshold;
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 9dd5e8b076..33cea56c62 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -32,7 +32,20 @@
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
+typedef struct MuxStream {
+ /* the packets are buffered here until the muxer is ready to be initialized */
+ AVFifo *muxing_queue;
+
+ /*
+ * The size of the AVPackets' buffers in queue.
+ * Updated when a packet is either pushed or pulled from the queue.
+ */
+ size_t muxing_queue_data_size;
+} MuxStream;
+
struct Muxer {
+ MuxStream *streams;
+
/* filesize limit expressed in bytes */
int64_t limit_filesize;
int64_t final_filesize;
@@ -55,6 +68,7 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
{
AVFormatContext *s = of->ctx;
AVStream *st = ost->st;
+ MuxStream *ms = &of->mux->streams[st->index];
int ret;
/*
@@ -76,10 +90,10 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
if (!of->mux->header_written) {
AVPacket *tmp_pkt;
/* the muxer is not initialized yet, buffer the packet */
- if (!av_fifo_can_write(ost->muxing_queue)) {
- size_t cur_size = av_fifo_can_read(ost->muxing_queue);
+ if (!av_fifo_can_write(ms->muxing_queue)) {
+ size_t cur_size = av_fifo_can_read(ms->muxing_queue);
unsigned int are_we_over_size =
- (ost->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold;
+ (ms->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold;
size_t limit = are_we_over_size ? ost->max_muxing_queue_size : SIZE_MAX;
size_t new_size = FFMIN(2 * cur_size, limit);
@@ -89,7 +103,7 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
ost->file_index, ost->st->index);
exit_program(1);
}
- ret = av_fifo_grow2(ost->muxing_queue, new_size - cur_size);
+ ret = av_fifo_grow2(ms->muxing_queue, new_size - cur_size);
if (ret < 0)
exit_program(1);
}
@@ -100,8 +114,8 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
if (!tmp_pkt)
exit_program(1);
av_packet_move_ref(tmp_pkt, pkt);
- ost->muxing_queue_data_size += tmp_pkt->size;
- av_fifo_write(ost->muxing_queue, &tmp_pkt, 1);
+ ms->muxing_queue_data_size += tmp_pkt->size;
+ av_fifo_write(ms->muxing_queue, &tmp_pkt, 1);
return;
}
@@ -283,15 +297,16 @@ int of_check_init(OutputFile *of)
/* flush the muxing queues */
for (i = 0; i < of->ctx->nb_streams; i++) {
+ MuxStream *ms = &of->mux->streams[i];
OutputStream *ost = output_streams[of->ost_index + i];
AVPacket *pkt;
/* try to improve muxing time_base (only possible if nothing has been written yet) */
- if (!av_fifo_can_read(ost->muxing_queue))
+ if (!av_fifo_can_read(ms->muxing_queue))
ost->mux_timebase = ost->st->time_base;
- while (av_fifo_read(ost->muxing_queue, &pkt, 1) >= 0) {
- ost->muxing_queue_data_size -= pkt->size;
+ while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) {
+ ms->muxing_queue_data_size -= pkt->size;
of_write_packet(of, pkt, ost, 1);
av_packet_free(&pkt);
}
@@ -332,6 +347,29 @@ int of_write_trailer(OutputFile *of)
return 0;
}
+static void mux_free(Muxer **pmux, int nb_streams)
+{
+ Muxer *mux = *pmux;
+
+ if (!mux)
+ return;
+
+ for (int i = 0; i < nb_streams; i++) {
+ MuxStream *ms = &mux->streams[i];
+ AVPacket *pkt;
+
+ if (!ms->muxing_queue)
+ continue;
+
+ while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0)
+ av_packet_free(&pkt);
+ av_fifo_freep2(&ms->muxing_queue);
+ }
+ av_freep(&mux->streams);
+
+ av_freep(pmux);
+}
+
void of_close(OutputFile **pof)
{
OutputFile *of = *pof;
@@ -341,25 +379,42 @@ void of_close(OutputFile **pof)
return;
s = of->ctx;
+
+ mux_free(&of->mux, s ? s->nb_streams : 0);
+
if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE))
avio_closep(&s->pb);
avformat_free_context(s);
av_dict_free(&of->opts);
- av_freep(&of->mux);
-
av_freep(pof);
}
int of_muxer_init(OutputFile *of, int64_t limit_filesize)
{
Muxer *mux = av_mallocz(sizeof(*mux));
+ int ret = 0;
if (!mux)
return AVERROR(ENOMEM);
+ mux->streams = av_calloc(of->ctx->nb_streams, sizeof(*mux->streams));
+ if (!mux->streams) {
+ av_freep(&mux);
+ return AVERROR(ENOMEM);
+ }
+
of->mux = mux;
+ for (int i = 0; i < of->ctx->nb_streams; i++) {
+ MuxStream *ms = &mux->streams[i];
+ ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0);
+ if (!ms->muxing_queue) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ }
+
mux->limit_filesize = limit_filesize;
if (strcmp(of->format->name, "rtp"))
@@ -367,12 +422,16 @@ int of_muxer_init(OutputFile *of, int64_t limit_filesize)
/* write the header for files with no streams */
if (of->format->flags & AVFMT_NOSTREAMS && of->ctx->nb_streams == 0) {
- int ret = of_check_init(of);
+ ret = of_check_init(of);
if (ret < 0)
- return ret;
+ goto fail;
}
- return 0;
+fail:
+ if (ret < 0)
+ mux_free(&of->mux, of->ctx->nb_streams);
+
+ return ret;
}
int of_finished(OutputFile *of)
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 780c11903b..a9944e637d 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1618,8 +1618,6 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
ost->max_muxing_queue_size = 128;
MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st);
- ost->muxing_queue_data_size = 0;
-
ost->muxing_queue_data_threshold = 50*1024*1024;
MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st);
@@ -1643,13 +1641,6 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
}
ost->last_mux_dts = AV_NOPTS_VALUE;
- ost->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0);
- if (!ost->muxing_queue)
- exit_program(1);
-
- MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i,
- ost->copy_initial_nonkeyframes, oc, st);
-
return ost;
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 21/49] fftools/ffmpeg_mux: split queuing packets into a separate function
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (19 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 20/49] fftools/ffmpeg: move the mux queue into muxer private data Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 22/49] fftools/ffmpeg_mux: split of_write_packet() Anton Khirnov
` (30 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_mux.c | 72 +++++++++++++++++++++++++++-----------------
1 file changed, 44 insertions(+), 28 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 33cea56c62..e7b0a9ca99 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -63,12 +63,50 @@ static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream,
}
}
+static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
+{
+ MuxStream *ms = &of->mux->streams[ost->index];
+ AVPacket *tmp_pkt;
+ int ret;
+
+ if (!av_fifo_can_write(ms->muxing_queue)) {
+ size_t cur_size = av_fifo_can_read(ms->muxing_queue);
+ unsigned int are_we_over_size =
+ (ms->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold;
+ size_t limit = are_we_over_size ? ost->max_muxing_queue_size : SIZE_MAX;
+ size_t new_size = FFMIN(2 * cur_size, limit);
+
+ if (new_size <= cur_size) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Too many packets buffered for output stream %d:%d.\n",
+ ost->file_index, ost->st->index);
+ return AVERROR(ENOSPC);
+ }
+ ret = av_fifo_grow2(ms->muxing_queue, new_size - cur_size);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = av_packet_make_refcounted(pkt);
+ if (ret < 0)
+ return ret;
+
+ tmp_pkt = av_packet_alloc();
+ if (!tmp_pkt)
+ return AVERROR(ENOMEM);
+
+ av_packet_move_ref(tmp_pkt, pkt);
+ ms->muxing_queue_data_size += tmp_pkt->size;
+ av_fifo_write(ms->muxing_queue, &tmp_pkt, 1);
+
+ return 0;
+}
+
void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
int unqueue)
{
AVFormatContext *s = of->ctx;
AVStream *st = ost->st;
- MuxStream *ms = &of->mux->streams[st->index];
int ret;
/*
@@ -87,35 +125,13 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
ost->frame_number++;
}
+ /* the muxer is not initialized yet, buffer the packet */
if (!of->mux->header_written) {
- AVPacket *tmp_pkt;
- /* the muxer is not initialized yet, buffer the packet */
- if (!av_fifo_can_write(ms->muxing_queue)) {
- size_t cur_size = av_fifo_can_read(ms->muxing_queue);
- unsigned int are_we_over_size =
- (ms->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold;
- size_t limit = are_we_over_size ? ost->max_muxing_queue_size : SIZE_MAX;
- size_t new_size = FFMIN(2 * cur_size, limit);
-
- if (new_size <= cur_size) {
- av_log(NULL, AV_LOG_ERROR,
- "Too many packets buffered for output stream %d:%d.\n",
- ost->file_index, ost->st->index);
- exit_program(1);
- }
- ret = av_fifo_grow2(ms->muxing_queue, new_size - cur_size);
- if (ret < 0)
- exit_program(1);
- }
- ret = av_packet_make_refcounted(pkt);
- if (ret < 0)
- exit_program(1);
- tmp_pkt = av_packet_alloc();
- if (!tmp_pkt)
+ ret = queue_packet(of, ost, pkt);
+ if (ret < 0) {
+ av_packet_unref(pkt);
exit_program(1);
- av_packet_move_ref(tmp_pkt, pkt);
- ms->muxing_queue_data_size += tmp_pkt->size;
- av_fifo_write(ms->muxing_queue, &tmp_pkt, 1);
+ }
return;
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 22/49] fftools/ffmpeg_mux: split of_write_packet()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (20 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 21/49] fftools/ffmpeg_mux: split queuing packets into a separate function Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 23/49] fftools/ffmpeg: move output file opts into private context Anton Khirnov
` (29 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
It is currently called from two places:
- output_packet() in ffmpeg.c, which submits the newly available output
packet to the muxer
- from of_check_init() in ffmpeg_mux.c after the header has been
written, to flush the muxing queue
Some packets will thus be processed by this function twice, so it
requires an extra parameter to indicate the place it is called from and
avoid modifying some state twice.
This is fragile and hard to follow, so split this function into two.
Also rename of_write_packet() to of_submit_packet() to better reflect
its new purpose.
---
fftools/ffmpeg.c | 4 +--
fftools/ffmpeg.h | 3 +--
fftools/ffmpeg_mux.c | 63 ++++++++++++++++++++++++--------------------
3 files changed, 37 insertions(+), 33 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index b240bbd984..ef0d5156eb 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -726,11 +726,11 @@ static void output_packet(OutputFile *of, AVPacket *pkt,
if (ret < 0)
goto finish;
while ((ret = av_bsf_receive_packet(ost->bsf_ctx, pkt)) >= 0)
- of_write_packet(of, pkt, ost, 0);
+ of_submit_packet(of, pkt, ost);
if (ret == AVERROR(EAGAIN))
ret = 0;
} else if (!eof)
- of_write_packet(of, pkt, ost, 0);
+ of_submit_packet(of, pkt, ost);
finish:
if (ret < 0 && ret != AVERROR_EOF) {
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index f0c3a3de7c..5f002521ab 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -687,8 +687,7 @@ int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
void of_close(OutputFile **pof);
-void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
- int unqueue);
+void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost);
int of_finished(OutputFile *of);
int64_t of_filesize(OutputFile *of);
AVChapter * const *
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index e7b0a9ca99..2b85d55504 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -102,39 +102,12 @@ static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
return 0;
}
-void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
- int unqueue)
+static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
{
AVFormatContext *s = of->ctx;
AVStream *st = ost->st;
int ret;
- /*
- * Audio encoders may split the packets -- #frames in != #packets out.
- * But there is no reordering, so we can limit the number of output packets
- * by simply dropping them here.
- * Counting encoded video frames needs to be done separately because of
- * reordering, see do_video_out().
- * Do not count the packet when unqueued because it has been counted when queued.
- */
- if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed) && !unqueue) {
- if (ost->frame_number >= ost->max_frames) {
- av_packet_unref(pkt);
- return;
- }
- ost->frame_number++;
- }
-
- /* the muxer is not initialized yet, buffer the packet */
- if (!of->mux->header_written) {
- ret = queue_packet(of, ost, pkt);
- if (ret < 0) {
- av_packet_unref(pkt);
- exit_program(1);
- }
- return;
- }
-
if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
@@ -225,6 +198,38 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
}
}
+void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
+{
+ AVStream *st = ost->st;
+ int ret;
+
+ /*
+ * Audio encoders may split the packets -- #frames in != #packets out.
+ * But there is no reordering, so we can limit the number of output packets
+ * by simply dropping them here.
+ * Counting encoded video frames needs to be done separately because of
+ * reordering, see do_video_out().
+ */
+ if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) {
+ if (ost->frame_number >= ost->max_frames) {
+ av_packet_unref(pkt);
+ return;
+ }
+ ost->frame_number++;
+ }
+
+ if (of->mux->header_written) {
+ write_packet(of, ost, pkt);
+ } else {
+ /* the muxer is not initialized yet, buffer the packet */
+ ret = queue_packet(of, ost, pkt);
+ if (ret < 0) {
+ av_packet_unref(pkt);
+ exit_program(1);
+ }
+ }
+}
+
static int print_sdp(void)
{
char sdp[16384];
@@ -323,7 +328,7 @@ int of_check_init(OutputFile *of)
while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) {
ms->muxing_queue_data_size -= pkt->size;
- of_write_packet(of, pkt, ost, 1);
+ write_packet(of, ost, pkt);
av_packet_free(&pkt);
}
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 23/49] fftools/ffmpeg: move output file opts into private context
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (21 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 22/49] fftools/ffmpeg_mux: split of_write_packet() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 24/49] fftools/ffmpeg: move processing video stats to ffmpeg_mux Anton Khirnov
` (28 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
It is private to the muxer, no reason to access it from outside.
---
fftools/ffmpeg.h | 3 +--
fftools/ffmpeg_mux.c | 9 ++++++---
fftools/ffmpeg_opt.c | 12 ++++++------
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 5f002521ab..c6bbc653b8 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -577,7 +577,6 @@ typedef struct OutputFile {
const AVOutputFormat *format;
AVFormatContext *ctx;
- AVDictionary *opts;
int ost_index; /* index of the first stream in output_streams */
int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units
int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units
@@ -681,7 +680,7 @@ int hw_device_setup_for_filter(FilterGraph *fg);
int hwaccel_decode_init(AVCodecContext *avctx);
-int of_muxer_init(OutputFile *of, int64_t limit_filesize);
+int of_muxer_init(OutputFile *of, AVDictionary *opts, int64_t limit_filesize);
/* open the muxer when all the streams are initialized */
int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 2b85d55504..f301b8a66a 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -46,6 +46,8 @@ typedef struct MuxStream {
struct Muxer {
MuxStream *streams;
+ AVDictionary *opts;
+
/* filesize limit expressed in bytes */
int64_t limit_filesize;
int64_t final_filesize;
@@ -294,7 +296,7 @@ int of_check_init(OutputFile *of)
return 0;
}
- ret = avformat_write_header(of->ctx, &of->opts);
+ ret = avformat_write_header(of->ctx, &of->mux->opts);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR,
"Could not write header for output file #%d "
@@ -387,6 +389,7 @@ static void mux_free(Muxer **pmux, int nb_streams)
av_fifo_freep2(&ms->muxing_queue);
}
av_freep(&mux->streams);
+ av_dict_free(&mux->opts);
av_freep(pmux);
}
@@ -406,12 +409,11 @@ void of_close(OutputFile **pof)
if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE))
avio_closep(&s->pb);
avformat_free_context(s);
- av_dict_free(&of->opts);
av_freep(pof);
}
-int of_muxer_init(OutputFile *of, int64_t limit_filesize)
+int of_muxer_init(OutputFile *of, AVDictionary *opts, int64_t limit_filesize)
{
Muxer *mux = av_mallocz(sizeof(*mux));
int ret = 0;
@@ -437,6 +439,7 @@ int of_muxer_init(OutputFile *of, int64_t limit_filesize)
}
mux->limit_filesize = limit_filesize;
+ mux->opts = opts;
if (strcmp(of->format->name, "rtp"))
want_sdp = 0;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index a9944e637d..adad46de5f 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2306,7 +2306,7 @@ static int open_output_file(OptionsContext *o, const char *filename)
OutputFile *of;
OutputStream *ost;
InputStream *ist;
- AVDictionary *unused_opts = NULL;
+ AVDictionary *unused_opts = NULL, *format_opts = NULL;
const AVDictionaryEntry *e = NULL;
if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
@@ -2331,7 +2331,7 @@ static int open_output_file(OptionsContext *o, const char *filename)
of->recording_time = o->recording_time;
of->start_time = o->start_time;
of->shortest = o->shortest;
- av_dict_copy(&of->opts, o->g->format_opts, 0);
+ av_dict_copy(&format_opts, o->g->format_opts, 0);
if (!strcmp(filename, "-"))
filename = "pipe:";
@@ -2353,7 +2353,7 @@ static int open_output_file(OptionsContext *o, const char *filename)
oc->flags |= AVFMT_FLAG_BITEXACT;
of->bitexact = 1;
} else {
- of->bitexact = check_opt_bitexact(oc, of->opts, "fflags",
+ of->bitexact = check_opt_bitexact(oc, format_opts, "fflags",
AVFMT_FLAG_BITEXACT);
}
@@ -2734,7 +2734,7 @@ loop_end:
/* open the file */
if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
&oc->interrupt_callback,
- &of->opts)) < 0) {
+ &format_opts)) < 0) {
print_error(filename, err);
exit_program(1);
}
@@ -2742,7 +2742,7 @@ loop_end:
assert_file_overwrite(filename);
if (o->mux_preload) {
- av_dict_set_int(&of->opts, "preload", o->mux_preload*AV_TIME_BASE, 0);
+ av_dict_set_int(&format_opts, "preload", o->mux_preload*AV_TIME_BASE, 0);
}
oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
@@ -2936,7 +2936,7 @@ loop_end:
exit_program(1);
}
- err = of_muxer_init(of, o->limit_filesize);
+ err = of_muxer_init(of, format_opts, o->limit_filesize);
if (err < 0) {
av_log(NULL, AV_LOG_FATAL, "Error initializing internal muxing state\n");
exit_program(1);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 24/49] fftools/ffmpeg: move processing video stats to ffmpeg_mux
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (22 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 23/49] fftools/ffmpeg: move output file opts into private context Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 25/49] fftools/ffmpeg_mux: drop a useless check and reduce indentation Anton Khirnov
` (27 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Currently it is called from
- do_video_out(), at the end of each encode loop iteration
- from flush_encoders(), after muxing each packet
Since this function processes the data from the last encoded packet,
neither of the above is fully correct, because
- an encoder can in principle produce multiple packets per one submitted
frame
- bitstream filters may modify the number of encoded packets or their
properties.
It thus makes most sense to call this function right before sending the
packet to the muxer.
---
fftools/ffmpeg.c | 61 +-------------------------------------------
fftools/ffmpeg.h | 5 ++++
fftools/ffmpeg_mux.c | 47 ++++++++++++++++++++++++++++++++++
3 files changed, 53 insertions(+), 60 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index ef0d5156eb..68e720d889 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -110,7 +110,7 @@
const char program_name[] = "ffmpeg";
const int program_birth_year = 2000;
-static FILE *vstats_file;
+FILE *vstats_file;
const char *const forced_keyframes_const_names[] = {
"n",
@@ -127,7 +127,6 @@ typedef struct BenchmarkTimeStamps {
int64_t sys_usec;
} BenchmarkTimeStamps;
-static void do_video_stats(OutputStream *ost, int frame_size);
static BenchmarkTimeStamps get_benchmark_time_stamps(void);
static int64_t getmaxrss(void);
static int ifilter_has_all_input_formats(FilterGraph *fg);
@@ -977,7 +976,6 @@ static void do_video_out(OutputFile *of,
double delta, delta0;
double duration = 0;
double sync_ipts = AV_NOPTS_VALUE;
- int frame_size = 0;
InputStream *ist = NULL;
AVFilterContext *filter = ost->filter->filter;
@@ -1214,7 +1212,6 @@ static void do_video_out(OutputFile *of,
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->mux_timebase));
}
- frame_size = pkt->size;
output_packet(of, pkt, ost, 0);
/* if two pass, output log */
@@ -1224,9 +1221,6 @@ static void do_video_out(OutputFile *of,
}
ost->sync_opts++;
ost->frame_number++;
-
- if (vstats_filename && frame_size)
- do_video_stats(ost, frame_size);
}
av_frame_unref(ost->last_frame);
@@ -1239,54 +1233,6 @@ error:
exit_program(1);
}
-static double psnr(double d)
-{
- return -10.0 * log10(d);
-}
-
-static void do_video_stats(OutputStream *ost, int frame_size)
-{
- AVCodecContext *enc;
- int frame_number;
- double ti1, bitrate, avg_bitrate;
-
- /* this is executed just the first time do_video_stats is called */
- if (!vstats_file) {
- vstats_file = fopen(vstats_filename, "w");
- if (!vstats_file) {
- perror("fopen");
- exit_program(1);
- }
- }
-
- enc = ost->enc_ctx;
- if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
- frame_number = ost->st->nb_frames;
- if (vstats_version <= 1) {
- fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number,
- ost->quality / (float)FF_QP2LAMBDA);
- } else {
- fprintf(vstats_file, "out= %2d st= %2d frame= %5d q= %2.1f ", ost->file_index, ost->index, frame_number,
- ost->quality / (float)FF_QP2LAMBDA);
- }
-
- if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR))
- fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0)));
-
- fprintf(vstats_file,"f_size= %6d ", frame_size);
- /* compute pts value */
- ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base);
- if (ti1 < 0.01)
- ti1 = 0.01;
-
- bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
- avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0;
- fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
- (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate);
- fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type));
- }
-}
-
static void finish_output_stream(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
@@ -1773,7 +1719,6 @@ static void flush_encoders(void)
for (;;) {
const char *desc = NULL;
AVPacket *pkt = ost->pkt;
- int pkt_size;
switch (enc->codec_type) {
case AVMEDIA_TYPE_AUDIO:
@@ -1817,11 +1762,7 @@ static void flush_encoders(void)
continue;
}
av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase);
- pkt_size = pkt->size;
output_packet(of, pkt, ost, 0);
- if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) {
- do_video_stats(ost, pkt_size);
- }
}
}
}
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index c6bbc653b8..604f0145e3 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -627,6 +627,7 @@ extern int stdin_interaction;
extern int frame_bits_per_raw_sample;
extern AVIOContext *progress_avio;
extern float max_error_rate;
+extern FILE *vstats_file;
extern char *filter_nbthreads;
extern int filter_complex_nbthreads;
@@ -644,6 +645,10 @@ extern HWDevice *filter_hw_device;
extern unsigned nb_output_dumped;
extern int main_return_code;
+static inline double psnr(double d)
+{
+ return -10.0 * log10(d);
+}
void term_init(void);
void term_exit(void);
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index f301b8a66a..5facc9b1fc 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -56,6 +56,49 @@ struct Muxer {
static int want_sdp = 1;
+static void do_video_stats(OutputStream *ost, int frame_size)
+{
+ AVCodecContext *enc;
+ int frame_number;
+ double ti1, bitrate, avg_bitrate;
+
+ /* this is executed just the first time do_video_stats is called */
+ if (!vstats_file) {
+ vstats_file = fopen(vstats_filename, "w");
+ if (!vstats_file) {
+ perror("fopen");
+ exit_program(1);
+ }
+ }
+
+ enc = ost->enc_ctx;
+ if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+ frame_number = ost->st->nb_frames;
+ if (vstats_version <= 1) {
+ fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number,
+ ost->quality / (float)FF_QP2LAMBDA);
+ } else {
+ fprintf(vstats_file, "out= %2d st= %2d frame= %5d q= %2.1f ", ost->file_index, ost->index, frame_number,
+ ost->quality / (float)FF_QP2LAMBDA);
+ }
+
+ if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR))
+ fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0)));
+
+ fprintf(vstats_file,"f_size= %6d ", frame_size);
+ /* compute pts value */
+ ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base);
+ if (ti1 < 0.01)
+ ti1 = 0.01;
+
+ bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
+ avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0;
+ fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
+ (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate);
+ fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type));
+ }
+}
+
static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others)
{
int i;
@@ -179,6 +222,10 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
ost->data_size += pkt->size;
ost->packets_written++;
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+ ost->encoding_needed && vstats_filename)
+ do_video_stats(ost, pkt->size);
+
pkt->stream_index = ost->index;
if (debug_ts) {
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 25/49] fftools/ffmpeg_mux: drop a useless check and reduce indentation
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (23 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 24/49] fftools/ffmpeg: move processing video stats to ffmpeg_mux Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 26/49] fftools/ffmpeg_mux: stop using AVStream.nb_frames in do_video_stats() Anton Khirnov
` (26 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
do_video_stats() is only ever called for video.
---
fftools/ffmpeg_mux.c | 42 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 5facc9b1fc..059beabaf3 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -72,31 +72,29 @@ static void do_video_stats(OutputStream *ost, int frame_size)
}
enc = ost->enc_ctx;
- if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
- frame_number = ost->st->nb_frames;
- if (vstats_version <= 1) {
- fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number,
- ost->quality / (float)FF_QP2LAMBDA);
- } else {
- fprintf(vstats_file, "out= %2d st= %2d frame= %5d q= %2.1f ", ost->file_index, ost->index, frame_number,
- ost->quality / (float)FF_QP2LAMBDA);
- }
+ frame_number = ost->st->nb_frames;
+ if (vstats_version <= 1) {
+ fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number,
+ ost->quality / (float)FF_QP2LAMBDA);
+ } else {
+ fprintf(vstats_file, "out= %2d st= %2d frame= %5d q= %2.1f ", ost->file_index, ost->index, frame_number,
+ ost->quality / (float)FF_QP2LAMBDA);
+ }
- if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR))
- fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0)));
+ if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR))
+ fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0)));
- fprintf(vstats_file,"f_size= %6d ", frame_size);
- /* compute pts value */
- ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base);
- if (ti1 < 0.01)
- ti1 = 0.01;
+ fprintf(vstats_file,"f_size= %6d ", frame_size);
+ /* compute pts value */
+ ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base);
+ if (ti1 < 0.01)
+ ti1 = 0.01;
- bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
- avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0;
- fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
- (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate);
- fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type));
- }
+ bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
+ avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0;
+ fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
+ (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate);
+ fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type));
}
static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others)
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 26/49] fftools/ffmpeg_mux: stop using AVStream.nb_frames in do_video_stats()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (24 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 25/49] fftools/ffmpeg_mux: drop a useless check and reduce indentation Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 27/49] fftools/ffmpeg_mux: stop using av_stream_get_end_pts() " Anton Khirnov
` (25 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Its use for muxing is not documented, in practice it is incremented per
each packet successfully passed to the muxer's write_packet(). Since
there is a lot of indirection between ffmpeg submitting a packet to the
muxer and it actually being written (e.g. the interleaving queue), using
nb_frames to count packets sent to the muxer is incorrect. Use
OutputStream.packets_written instead.
---
fftools/ffmpeg_mux.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 059beabaf3..49703ed727 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -72,7 +72,7 @@ static void do_video_stats(OutputStream *ost, int frame_size)
}
enc = ost->enc_ctx;
- frame_number = ost->st->nb_frames;
+ frame_number = ost->packets_written - 1;
if (vstats_version <= 1) {
fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number,
ost->quality / (float)FF_QP2LAMBDA);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 27/49] fftools/ffmpeg_mux: stop using av_stream_get_end_pts() in do_video_stats()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (25 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 26/49] fftools/ffmpeg_mux: stop using AVStream.nb_frames in do_video_stats() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 28/49] fftools/ffmpeg_mux: merge variable declaration and initialization Anton Khirnov
` (24 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
It retrieves libavformat's internal dts value (contrary to the
function's name), which is not necessary here because we can access the
packet directly.
---
fftools/ffmpeg_mux.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 49703ed727..8e0e278e4f 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -56,7 +56,7 @@ struct Muxer {
static int want_sdp = 1;
-static void do_video_stats(OutputStream *ost, int frame_size)
+static void do_video_stats(OutputStream *ost, const AVPacket *pkt)
{
AVCodecContext *enc;
int frame_number;
@@ -84,13 +84,13 @@ static void do_video_stats(OutputStream *ost, int frame_size)
if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR))
fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0)));
- fprintf(vstats_file,"f_size= %6d ", frame_size);
+ fprintf(vstats_file,"f_size= %6d ", pkt->size);
/* compute pts value */
- ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base);
+ ti1 = pkt->dts * av_q2d(ost->st->time_base);
if (ti1 < 0.01)
ti1 = 0.01;
- bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
+ bitrate = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0;
avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0;
fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
(double)ost->data_size / 1024, ti1, bitrate, avg_bitrate);
@@ -222,7 +222,7 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
ost->encoding_needed && vstats_filename)
- do_video_stats(ost, pkt->size);
+ do_video_stats(ost, pkt);
pkt->stream_index = ost->index;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 28/49] fftools/ffmpeg_mux: merge variable declaration and initialization
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (26 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 27/49] fftools/ffmpeg_mux: stop using av_stream_get_end_pts() " Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 29/49] fftools/ffmpeg_mux: move processing AV_PKT_DATA_QUALITY_STATS to do_video_stats() Anton Khirnov
` (23 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_mux.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 8e0e278e4f..b7140fca5e 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -58,7 +58,7 @@ static int want_sdp = 1;
static void do_video_stats(OutputStream *ost, const AVPacket *pkt)
{
- AVCodecContext *enc;
+ AVCodecContext *enc = ost->enc_ctx;
int frame_number;
double ti1, bitrate, avg_bitrate;
@@ -71,7 +71,6 @@ static void do_video_stats(OutputStream *ost, const AVPacket *pkt)
}
}
- enc = ost->enc_ctx;
frame_number = ost->packets_written - 1;
if (vstats_version <= 1) {
fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number,
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 29/49] fftools/ffmpeg_mux: move processing AV_PKT_DATA_QUALITY_STATS to do_video_stats()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (27 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 28/49] fftools/ffmpeg_mux: merge variable declaration and initialization Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 30/49] fftools/ffmpeg: share the code encoding a single frame between video and audio Anton Khirnov
` (22 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
This is a more appropriate place for this code, since the values we read
from AV_PKT_DATA_QUALITY_STATS side data are primarily written into
video stats.
Rename the function to update_video_stats() to better reflect its new
purpose.
---
fftools/ffmpeg_mux.c | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index b7140fca5e..ccfe31e09a 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -56,13 +56,28 @@ struct Muxer {
static int want_sdp = 1;
-static void do_video_stats(OutputStream *ost, const AVPacket *pkt)
+static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats)
{
+ const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
+ NULL);
AVCodecContext *enc = ost->enc_ctx;
int frame_number;
double ti1, bitrate, avg_bitrate;
- /* this is executed just the first time do_video_stats is called */
+ ost->quality = sd ? AV_RL32(sd) : -1;
+ ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(ost->error); i++) {
+ if (sd && i < sd[5])
+ ost->error[i] = AV_RL64(sd + 8 + 8 * i);
+ else
+ ost->error[i] = -1;
+ }
+
+ if (!write_vstats)
+ return;
+
+ /* this is executed just the first time update_video_stats is called */
if (!vstats_file) {
vstats_file = fopen(vstats_filename, "w");
if (!vstats_file) {
@@ -155,19 +170,6 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
- int i;
- uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
- NULL);
- ost->quality = sd ? AV_RL32(sd) : -1;
- ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE;
-
- for (i = 0; i<FF_ARRAY_ELEMS(ost->error); i++) {
- if (sd && i < sd[5])
- ost->error[i] = AV_RL64(sd + 8 + 8*i);
- else
- ost->error[i] = -1;
- }
-
if (ost->frame_rate.num && ost->is_cfr) {
if (pkt->duration > 0)
av_log(NULL, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n");
@@ -219,9 +221,8 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
ost->data_size += pkt->size;
ost->packets_written++;
- if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
- ost->encoding_needed && vstats_filename)
- do_video_stats(ost, pkt);
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)
+ update_video_stats(ost, pkt, !!vstats_filename);
pkt->stream_index = ost->index;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 30/49] fftools/ffmpeg: share the code encoding a single frame between video and audio
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (28 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 29/49] fftools/ffmpeg_mux: move processing AV_PKT_DATA_QUALITY_STATS to do_video_stats() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 31/49] fftools/ffmpeg: reuse the encoding code for flushing encoders Anton Khirnov
` (21 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 136 ++++++++++++++++++++---------------------------
1 file changed, 58 insertions(+), 78 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 68e720d889..662a5d22b1 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -821,63 +821,93 @@ static int init_output_stream_wrapper(OutputStream *ost, AVFrame *frame,
return ret;
}
-static void do_audio_out(OutputFile *of, OutputStream *ost,
- AVFrame *frame)
+static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
{
- AVCodecContext *enc = ost->enc_ctx;
- AVPacket *pkt = ost->pkt;
+ AVCodecContext *enc = ost->enc_ctx;
+ AVPacket *pkt = ost->pkt;
+ const char *type_desc = av_get_media_type_string(enc->codec_type);
int ret;
- adjust_frame_pts_to_encoder_tb(of, ost, frame);
-
- if (!check_recording_time(ost))
- return;
-
- if (frame->pts == AV_NOPTS_VALUE || audio_sync_method < 0)
- frame->pts = ost->sync_opts;
- ost->sync_opts = frame->pts + frame->nb_samples;
- ost->samples_encoded += frame->nb_samples;
ost->frames_encoded++;
update_benchmark(NULL);
+
if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "encoder <- type:audio "
+ av_log(NULL, AV_LOG_INFO, "encoder <- type:%s "
"frame_pts:%s frame_pts_time:%s time_base:%d/%d\n",
+ type_desc,
av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base),
enc->time_base.num, enc->time_base.den);
}
ret = avcodec_send_frame(enc, frame);
- if (ret < 0)
- goto error;
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n",
+ type_desc);
+ return ret;
+ }
while (1) {
ret = avcodec_receive_packet(enc, pkt);
+ update_benchmark("encode_%s %d.%d", type_desc,
+ ost->file_index, ost->index);
if (ret == AVERROR(EAGAIN))
- break;
- if (ret < 0)
- goto error;
+ return 0;
+ else if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "%s encoding failed\n", type_desc);
+ return ret;
+ }
- update_benchmark("encode_audio %d.%d", ost->file_index, ost->index);
+ if (debug_ts) {
+ av_log(NULL, AV_LOG_INFO, "encoder -> type:%s "
+ "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
+ "duration:%s duration_time:%s\n",
+ type_desc,
+ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base),
+ av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base),
+ av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
+ }
av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase);
if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "encoder -> type:audio "
+ av_log(NULL, AV_LOG_INFO, "encoder -> type:%s "
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
"duration:%s duration_time:%s\n",
+ type_desc,
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base),
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
}
output_packet(of, pkt, ost, 0);
+
+ /* if two pass, output log */
+ if (ost->logfile && enc->stats_out)
+ fprintf(ost->logfile, "%s", enc->stats_out);
}
- return;
-error:
- av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
- exit_program(1);
+ av_assert0(0);
+}
+
+static void do_audio_out(OutputFile *of, OutputStream *ost,
+ AVFrame *frame)
+{
+ int ret;
+
+ adjust_frame_pts_to_encoder_tb(of, ost, frame);
+
+ if (!check_recording_time(ost))
+ return;
+
+ if (frame->pts == AV_NOPTS_VALUE || audio_sync_method < 0)
+ frame->pts = ost->sync_opts;
+ ost->sync_opts = frame->pts + frame->nb_samples;
+ ost->samples_encoded += frame->nb_samples;
+
+ ret = encode_frame(of, ost, frame);
+ if (ret < 0)
+ exit_program(1);
}
static void do_subtitle_out(OutputFile *of,
@@ -969,7 +999,6 @@ static void do_video_out(OutputFile *of,
AVFrame *next_picture)
{
int ret;
- AVPacket *pkt = ost->pkt;
AVCodecContext *enc = ost->enc_ctx;
AVRational frame_rate;
int nb_frames, nb0_frames, i;
@@ -1168,57 +1197,13 @@ static void do_video_out(OutputFile *of,
av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time);
}
- update_benchmark(NULL);
- if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "encoder <- type:video "
- "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n",
- av_ts2str(in_picture->pts), av_ts2timestr(in_picture->pts, &enc->time_base),
- enc->time_base.num, enc->time_base.den);
- }
-
- ost->frames_encoded++;
-
- ret = avcodec_send_frame(enc, in_picture);
+ ret = encode_frame(of, ost, in_picture);
if (ret < 0)
- goto error;
+ exit_program(1);
+
// Make sure Closed Captions will not be duplicated
av_frame_remove_side_data(in_picture, AV_FRAME_DATA_A53_CC);
- while (1) {
- ret = avcodec_receive_packet(enc, pkt);
- update_benchmark("encode_video %d.%d", ost->file_index, ost->index);
- if (ret == AVERROR(EAGAIN))
- break;
- if (ret < 0)
- goto error;
-
- if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "encoder -> type:video "
- "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
- "duration:%s duration_time:%s\n",
- av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base),
- av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base),
- av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
- }
-
- av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase);
-
- if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "encoder -> type:video "
- "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
- "duration:%s duration_time:%s\n",
- av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->mux_timebase),
- av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->mux_timebase),
- av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->mux_timebase));
- }
-
- output_packet(of, pkt, ost, 0);
-
- /* if two pass, output log */
- if (ost->logfile && enc->stats_out) {
- fprintf(ost->logfile, "%s", enc->stats_out);
- }
- }
ost->sync_opts++;
ost->frame_number++;
}
@@ -1226,11 +1211,6 @@ static void do_video_out(OutputFile *of,
av_frame_unref(ost->last_frame);
if (next_picture)
av_frame_move_ref(ost->last_frame, next_picture);
-
- return;
-error:
- av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
- exit_program(1);
}
static void finish_output_stream(OutputStream *ost)
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 31/49] fftools/ffmpeg: reuse the encoding code for flushing encoders
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (29 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 30/49] fftools/ffmpeg: share the code encoding a single frame between video and audio Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 32/49] fftools/ffmpeg: reindent after previous commit Anton Khirnov
` (20 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 72 ++++++++++++------------------------------------
1 file changed, 18 insertions(+), 54 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 662a5d22b1..adf69cb43e 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -826,12 +826,12 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
AVCodecContext *enc = ost->enc_ctx;
AVPacket *pkt = ost->pkt;
const char *type_desc = av_get_media_type_string(enc->codec_type);
+ const char *action = frame ? "encode" : "flush";
int ret;
+ if (frame) {
ost->frames_encoded++;
- update_benchmark(NULL);
-
if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "encoder <- type:%s "
"frame_pts:%s frame_pts_time:%s time_base:%d/%d\n",
@@ -839,9 +839,12 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base),
enc->time_base.num, enc->time_base.den);
}
+ }
+
+ update_benchmark(NULL);
ret = avcodec_send_frame(enc, frame);
- if (ret < 0) {
+ if (ret < 0 && !(ret == AVERROR_EOF && !frame)) {
av_log(NULL, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n",
type_desc);
return ret;
@@ -849,15 +852,20 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
while (1) {
ret = avcodec_receive_packet(enc, pkt);
- update_benchmark("encode_%s %d.%d", type_desc,
+ update_benchmark("%s_%s %d.%d", action, type_desc,
ost->file_index, ost->index);
- if (ret == AVERROR(EAGAIN))
+ if (ret == AVERROR(EAGAIN)) {
+ av_assert0(frame); // should never happen during flushing
return 0;
- else if (ret < 0) {
+ } else if (ret < 0 && ret != AVERROR_EOF) {
av_log(NULL, AV_LOG_ERROR, "%s encoding failed\n", type_desc);
return ret;
}
+ if (ret == AVERROR_EOF) {
+ output_packet(of, pkt, ost, 1);
+ return ret;
+ } else {
if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "encoder -> type:%s "
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
@@ -881,6 +889,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
}
output_packet(of, pkt, ost, 0);
+ }
/* if two pass, output log */
if (ost->logfile && enc->stats_out)
@@ -1696,54 +1705,9 @@ static void flush_encoders(void)
if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO)
continue;
- for (;;) {
- const char *desc = NULL;
- AVPacket *pkt = ost->pkt;
-
- switch (enc->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- desc = "audio";
- break;
- case AVMEDIA_TYPE_VIDEO:
- desc = "video";
- break;
- default:
- av_assert0(0);
- }
-
- update_benchmark(NULL);
-
- while ((ret = avcodec_receive_packet(enc, pkt)) == AVERROR(EAGAIN)) {
- ret = avcodec_send_frame(enc, NULL);
- if (ret < 0) {
- av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n",
- desc,
- av_err2str(ret));
- exit_program(1);
- }
- }
-
- update_benchmark("flush_%s %d.%d", desc, ost->file_index, ost->index);
- if (ret < 0 && ret != AVERROR_EOF) {
- av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n",
- desc,
- av_err2str(ret));
- exit_program(1);
- }
- if (ost->logfile && enc->stats_out) {
- fprintf(ost->logfile, "%s", enc->stats_out);
- }
- if (ret == AVERROR_EOF) {
- output_packet(of, pkt, ost, 1);
- break;
- }
- if (ost->finished & MUXER_FINISHED) {
- av_packet_unref(pkt);
- continue;
- }
- av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase);
- output_packet(of, pkt, ost, 0);
- }
+ ret = encode_frame(of, ost, NULL);
+ if (ret != AVERROR_EOF)
+ exit_program(1);
}
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 32/49] fftools/ffmpeg: reindent after previous commit
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (30 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 31/49] fftools/ffmpeg: reuse the encoding code for flushing encoders Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 33/49] fftools/ffmpeg: use refcounted packets for encoded subtitles Anton Khirnov
` (19 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 56 ++++++++++++++++++++++++------------------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index adf69cb43e..e0f15c0f61 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -830,15 +830,15 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
int ret;
if (frame) {
- ost->frames_encoded++;
+ ost->frames_encoded++;
- if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "encoder <- type:%s "
- "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n",
- type_desc,
- av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base),
- enc->time_base.num, enc->time_base.den);
- }
+ if (debug_ts) {
+ av_log(NULL, AV_LOG_INFO, "encoder <- type:%s "
+ "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n",
+ type_desc,
+ av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base),
+ enc->time_base.num, enc->time_base.den);
+ }
}
update_benchmark(NULL);
@@ -866,29 +866,29 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
output_packet(of, pkt, ost, 1);
return ret;
} else {
- if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "encoder -> type:%s "
- "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
- "duration:%s duration_time:%s\n",
- type_desc,
- av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base),
- av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base),
- av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
- }
+ if (debug_ts) {
+ av_log(NULL, AV_LOG_INFO, "encoder -> type:%s "
+ "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
+ "duration:%s duration_time:%s\n",
+ type_desc,
+ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base),
+ av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base),
+ av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
+ }
- av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase);
+ av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase);
- if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "encoder -> type:%s "
- "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
- "duration:%s duration_time:%s\n",
- type_desc,
- av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base),
- av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base),
- av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
- }
+ if (debug_ts) {
+ av_log(NULL, AV_LOG_INFO, "encoder -> type:%s "
+ "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s "
+ "duration:%s duration_time:%s\n",
+ type_desc,
+ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base),
+ av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base),
+ av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base));
+ }
- output_packet(of, pkt, ost, 0);
+ output_packet(of, pkt, ost, 0);
}
/* if two pass, output log */
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 33/49] fftools/ffmpeg: use refcounted packets for encoded subtitles
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (31 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 32/49] fftools/ffmpeg: reindent after previous commit Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 34/49] fftools/ffmpeg: rework -shortest implementation Anton Khirnov
` (18 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 25 ++++++++-----------------
1 file changed, 8 insertions(+), 17 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index e0f15c0f61..07d1fc8a5d 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -141,8 +141,6 @@ unsigned nb_output_dumped = 0;
static BenchmarkTimeStamps current_time;
AVIOContext *progress_avio = NULL;
-static uint8_t *subtitle_out;
-
InputStream **input_streams = NULL;
int nb_input_streams = 0;
InputFile **input_files = NULL;
@@ -559,8 +557,6 @@ static void ffmpeg_cleanup(int ret)
}
av_freep(&filtergraphs);
- av_freep(&subtitle_out);
-
/* close files */
for (i = 0; i < nb_output_files; i++)
of_close(&output_files[i]);
@@ -924,7 +920,7 @@ static void do_subtitle_out(OutputFile *of,
AVSubtitle *sub)
{
int subtitle_out_max_size = 1024 * 1024;
- int subtitle_out_size, nb, i;
+ int subtitle_out_size, nb, i, ret;
AVCodecContext *enc;
AVPacket *pkt = ost->pkt;
int64_t pts;
@@ -938,14 +934,6 @@ static void do_subtitle_out(OutputFile *of,
enc = ost->enc_ctx;
- if (!subtitle_out) {
- subtitle_out = av_malloc(subtitle_out_max_size);
- if (!subtitle_out) {
- av_log(NULL, AV_LOG_FATAL, "Failed to allocate subtitle_out\n");
- exit_program(1);
- }
- }
-
/* Note: DVB subtitle need one packet to draw them and one other
packet to clear them */
/* XXX: signal it in the codec context ? */
@@ -965,6 +953,12 @@ static void do_subtitle_out(OutputFile *of,
if (!check_recording_time(ost))
return;
+ ret = av_new_packet(pkt, subtitle_out_max_size);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Failed to allocate subtitle encode buffer\n");
+ exit_program(1);
+ }
+
sub->pts = pts;
// start_display_time is required to be 0
sub->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q);
@@ -975,8 +969,7 @@ static void do_subtitle_out(OutputFile *of,
ost->frames_encoded++;
- subtitle_out_size = avcodec_encode_subtitle(enc, subtitle_out,
- subtitle_out_max_size, sub);
+ subtitle_out_size = avcodec_encode_subtitle(enc, pkt->data, pkt->size, sub);
if (i == 1)
sub->num_rects = save_num_rects;
if (subtitle_out_size < 0) {
@@ -984,8 +977,6 @@ static void do_subtitle_out(OutputFile *of,
exit_program(1);
}
- av_packet_unref(pkt);
- pkt->data = subtitle_out;
pkt->size = subtitle_out_size;
pkt->pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->mux_timebase);
pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 34/49] fftools/ffmpeg: rework -shortest implementation
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (32 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 33/49] fftools/ffmpeg: use refcounted packets for encoded subtitles Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 35/49] fftools/ffmpeg: use the sync queues to handle -frames Anton Khirnov
` (17 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
The -shortest option (which finishes the output file at the time the
shortest stream ends) is currently implemented by faking the -t option
when an output stream ends. This approach is fragile, since it depends
on the frames/packets being processed in a specific order. E.g. there
are currently some situations in which the output file length will
depend unpredictably on unrelated factors like encoder delay. More
importantly, the present work aiming at splitting various ffmpeg
components into different threads will make this approach completely
unworkable, since the frames/packets will arrive in effectively random
order.
This commit introduces a "sync queue", which is essentially a collection
of FIFOs, one per stream. Frames/packets are submitted to these FIFOs
and are then released for further processing (encoding or muxing) when
it is ensured that the frame in question will not make its stream get
ahead of the other streams (the logic is similar to libavformat's
interleaving queue).
These sync queues are then used for encoding and/or muxing when the
-shortest option is specifierd.
This commit changes the results of the copy-shortest[12] tests, where
the last audio frame is now gone. This is correct, since it actually
outlasts the last video frame.
---
fftools/Makefile | 1 +
fftools/ffmpeg.c | 144 +++++++++++---
fftools/ffmpeg.h | 14 +-
fftools/ffmpeg_mux.c | 88 ++++++---
fftools/ffmpeg_opt.c | 80 ++++++++
fftools/sync_queue.c | 346 ++++++++++++++++++++++++++++++++++
fftools/sync_queue.h | 93 +++++++++
tests/ref/fate/copy-shortest1 | 1 -
tests/ref/fate/copy-shortest2 | 1 -
9 files changed, 712 insertions(+), 56 deletions(-)
create mode 100644 fftools/sync_queue.c
create mode 100644 fftools/sync_queue.h
diff --git a/fftools/Makefile b/fftools/Makefile
index 81ad6c4f4f..f015df6846 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -14,6 +14,7 @@ OBJS-ffmpeg += \
fftools/ffmpeg_hw.o \
fftools/ffmpeg_mux.o \
fftools/ffmpeg_opt.o \
+ fftools/sync_queue.o \
define DOFFTOOL
OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 07d1fc8a5d..8674f52047 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -104,6 +104,7 @@
#include "ffmpeg.h"
#include "cmdutils.h"
+#include "sync_queue.h"
#include "libavutil/avassert.h"
@@ -570,6 +571,7 @@ static void ffmpeg_cleanup(int ret)
av_bsf_free(&ost->bsf_ctx);
av_frame_free(&ost->filtered_frame);
+ av_frame_free(&ost->sq_frame);
av_frame_free(&ost->last_frame);
av_packet_free(&ost->pkt);
av_dict_free(&ost->encoder_opts);
@@ -690,13 +692,10 @@ static void update_benchmark(const char *fmt, ...)
static void close_output_stream(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
- AVRational time_base = ost->stream_copy ? ost->mux_timebase : ost->enc_ctx->time_base;
-
ost->finished |= ENCODER_FINISHED;
- if (of->shortest) {
- int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, time_base, AV_TIME_BASE_Q);
- of->recording_time = FFMIN(of->recording_time, end);
- }
+
+ if (ost->sq_idx_encode >= 0)
+ sq_send(of->sq_encode, ost->sq_idx_encode, SQFRAME(NULL));
}
/*
@@ -715,17 +714,22 @@ static void output_packet(OutputFile *of, AVPacket *pkt,
{
int ret = 0;
+ if (!eof && pkt->dts != AV_NOPTS_VALUE)
+ ost->last_mux_dts = av_rescale_q(pkt->dts, ost->mux_timebase, AV_TIME_BASE_Q);
+
/* apply the output bitstream filters */
if (ost->bsf_ctx) {
ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt);
if (ret < 0)
goto finish;
while ((ret = av_bsf_receive_packet(ost->bsf_ctx, pkt)) >= 0)
- of_submit_packet(of, pkt, ost);
+ of_submit_packet(of, pkt, ost, 0);
+ if (ret == AVERROR_EOF)
+ of_submit_packet(of, pkt, ost, 1);
if (ret == AVERROR(EAGAIN))
ret = 0;
- } else if (!eof)
- of_submit_packet(of, pkt, ost);
+ } else
+ of_submit_packet(of, pkt, ost, eof);
finish:
if (ret < 0 && ret != AVERROR_EOF) {
@@ -895,6 +899,52 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
av_assert0(0);
}
+static int submit_encode_frame(OutputFile *of, OutputStream *ost,
+ AVFrame *frame)
+{
+ int ret;
+
+ if (ost->sq_idx_encode < 0)
+ return encode_frame(of, ost, frame);
+
+ if (frame) {
+ ret = av_frame_ref(ost->sq_frame, frame);
+ if (ret < 0)
+ return ret;
+ frame = ost->sq_frame;
+ }
+
+ ret = sq_send(of->sq_encode, ost->sq_idx_encode,
+ SQFRAME(frame));
+ if (ret < 0) {
+ if (frame)
+ av_frame_unref(frame);
+ if (ret != AVERROR_EOF)
+ return ret;
+ }
+
+ while (1) {
+ AVFrame *enc_frame = ost->sq_frame;
+
+ ret = sq_receive(of->sq_encode, ost->sq_idx_encode,
+ SQFRAME(enc_frame));
+ if (ret == AVERROR_EOF) {
+ enc_frame = NULL;
+ } else if (ret < 0) {
+ return (ret == AVERROR(EAGAIN)) ? 0 : ret;
+ }
+
+ ret = encode_frame(of, ost, enc_frame);
+ if (enc_frame)
+ av_frame_unref(enc_frame);
+ if (ret < 0) {
+ if (ret == AVERROR_EOF)
+ close_output_stream(ost);
+ return ret;
+ }
+ }
+}
+
static void do_audio_out(OutputFile *of, OutputStream *ost,
AVFrame *frame)
{
@@ -910,8 +960,8 @@ static void do_audio_out(OutputFile *of, OutputStream *ost,
ost->sync_opts = frame->pts + frame->nb_samples;
ost->samples_encoded += frame->nb_samples;
- ret = encode_frame(of, ost, frame);
- if (ret < 0)
+ ret = submit_encode_frame(of, ost, frame);
+ if (ret < 0 && ret != AVERROR_EOF)
exit_program(1);
}
@@ -1197,8 +1247,8 @@ static void do_video_out(OutputFile *of,
av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time);
}
- ret = encode_frame(of, ost, in_picture);
- if (ret < 0)
+ ret = submit_encode_frame(of, ost, in_picture);
+ if (ret < 0 && ret != AVERROR_EOF)
exit_program(1);
// Make sure Closed Captions will not be duplicated
@@ -1216,14 +1266,12 @@ static void do_video_out(OutputFile *of,
static void finish_output_stream(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
- AVRational time_base = ost->stream_copy ? ost->mux_timebase : ost->enc_ctx->time_base;
-
- ost->finished = ENCODER_FINISHED | MUXER_FINISHED;
+ ost->finished = ENCODER_FINISHED;
- if (of->shortest) {
- int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, time_base, AV_TIME_BASE_Q);
- of->recording_time = FFMIN(of->recording_time, end);
- }
+ if (ost->sq_idx_mux >= 0)
+ sq_send(of->sq_mux, ost->sq_idx_mux, SQPKT(NULL));
+ else
+ ost->finished |= MUXER_FINISHED;
}
/**
@@ -1281,6 +1329,12 @@ static int reap_filters(int flush)
continue;
}
+ if (filtered_frame->pts != AV_NOPTS_VALUE) {
+ AVRational tb = av_buffersink_get_time_base(filter);
+ ost->last_filter_pts = av_rescale_q(filtered_frame->pts, tb,
+ AV_TIME_BASE_Q);
+ }
+
switch (av_buffersink_get_type(filter)) {
case AVMEDIA_TYPE_VIDEO:
if (!ost->frame_aspect_ratio.num)
@@ -1696,7 +1750,7 @@ static void flush_encoders(void)
if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO)
continue;
- ret = encode_frame(of, ost, NULL);
+ ret = submit_encode_frame(of, ost, NULL);
if (ret != AVERROR_EOF)
exit_program(1);
}
@@ -3006,6 +3060,9 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
break;
}
+ if (ost->sq_idx_encode >= 0)
+ sq_set_tb(of->sq_encode, ost->sq_idx_encode, enc_ctx->time_base);
+
ost->mux_timebase = enc_ctx->time_base;
return 0;
@@ -3014,6 +3071,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
static int init_output_stream(OutputStream *ost, AVFrame *frame,
char *error, int error_len)
{
+ OutputFile *of = output_files[ost->file_index];
int ret = 0;
if (ost->encoding_needed) {
@@ -3146,6 +3204,9 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame,
if (ret < 0)
return ret;
+ if (ost->sq_idx_mux >= 0)
+ sq_set_tb(of->sq_mux, ost->sq_idx_mux, ost->mux_timebase);
+
ost->initialized = 1;
ret = of_check_init(output_files[ost->file_index]);
@@ -3377,13 +3438,19 @@ static OutputStream *choose_output(void)
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
- int64_t opts = ost->last_mux_dts == AV_NOPTS_VALUE ? INT64_MIN :
- av_rescale_q(ost->last_mux_dts, ost->st->time_base,
- AV_TIME_BASE_Q);
- if (ost->last_mux_dts == AV_NOPTS_VALUE)
- av_log(NULL, AV_LOG_DEBUG,
- "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n",
- ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished);
+ int64_t opts;
+
+ if (ost->filter) {
+ opts = ost->last_filter_pts == AV_NOPTS_VALUE ?
+ INT64_MIN : ost->last_filter_pts;
+ } else {
+ opts = ost->last_mux_dts == AV_NOPTS_VALUE ?
+ INT64_MIN : ost->last_mux_dts;
+ if (ost->last_mux_dts == AV_NOPTS_VALUE)
+ av_log(NULL, AV_LOG_DEBUG,
+ "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n",
+ ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished);
+ }
if (!ost->initialized && !ost->inputs_done)
return ost->unavailable ? NULL : ost;
@@ -4205,6 +4272,26 @@ static int transcode_step(void)
return reap_filters(0);
}
+static void flush_sync_queues_mux(void)
+{
+ /* mark all queue inputs as done */
+ for (int i = 0; i < nb_output_streams; i++) {
+ OutputStream *ost = output_streams[i];
+ OutputFile *of = output_files[ost->file_index];
+ if (ost->sq_idx_mux >= 0)
+ sq_send(of->sq_mux, ost->sq_idx_mux, SQPKT(NULL));
+ }
+
+ /* encode all packets remaining in the sync queues */
+ for (int i = 0; i < nb_output_streams; i++) {
+ OutputStream *ost = output_streams[i];
+ OutputFile *of = output_files[ost->file_index];
+
+ if (!(ost->finished & MUXER_FINISHED))
+ output_packet(of, ost->pkt, ost, 1);
+ }
+}
+
/*
* The following code is the main loop of the file converter
*/
@@ -4266,6 +4353,7 @@ static int transcode(void)
}
}
flush_encoders();
+ flush_sync_queues_mux();
term_exit();
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 604f0145e3..dfda6ccbe9 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -26,6 +26,7 @@
#include <signal.h>
#include "cmdutils.h"
+#include "sync_queue.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
@@ -464,8 +465,10 @@ typedef struct OutputStream {
/* pts of the first frame encoded for this stream, used for limiting
* recording time */
int64_t first_pts;
- /* dts of the last packet sent to the muxer */
+ /* dts of the last packet sent to the muxing queue, in AV_TIME_BASE_Q */
int64_t last_mux_dts;
+ /* pts of the last frame received from the filters, in AV_TIME_BASE_Q */
+ int64_t last_filter_pts;
// the timebase of the packets sent to the muxer
AVRational mux_timebase;
AVRational enc_timebase;
@@ -478,6 +481,7 @@ typedef struct OutputStream {
int64_t max_frames;
AVFrame *filtered_frame;
AVFrame *last_frame;
+ AVFrame *sq_frame;
AVPacket *pkt;
int last_dropped;
int last_nb0_frames[3];
@@ -566,6 +570,9 @@ typedef struct OutputStream {
/* frame encode sum of squared error values */
int64_t error[4];
+
+ int sq_idx_encode;
+ int sq_idx_mux;
} OutputStream;
typedef struct Muxer Muxer;
@@ -576,6 +583,9 @@ typedef struct OutputFile {
Muxer *mux;
const AVOutputFormat *format;
+ SyncQueue *sq_encode;
+ SyncQueue *sq_mux;
+
AVFormatContext *ctx;
int ost_index; /* index of the first stream in output_streams */
int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units
@@ -691,7 +701,7 @@ int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
void of_close(OutputFile **pof);
-void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost);
+void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof);
int of_finished(OutputFile *of);
int64_t of_filesize(OutputFile *of);
AVChapter * const *
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index ccfe31e09a..69f01448b8 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -20,6 +20,7 @@
#include <string.h>
#include "ffmpeg.h"
+#include "sync_queue.h"
#include "libavutil/fifo.h"
#include "libavutil/intreadwrite.h"
@@ -41,6 +42,10 @@ typedef struct MuxStream {
* Updated when a packet is either pushed or pulled from the queue.
*/
size_t muxing_queue_data_size;
+
+ /* dts of the last packet sent to the muxer, in the stream timebase
+ * used for making up missing dts values */
+ int64_t last_mux_dts;
} MuxStream;
struct Muxer {
@@ -161,6 +166,7 @@ static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
{
+ MuxStream *ms = &of->mux->streams[ost->index];
AVFormatContext *s = of->ctx;
AVStream *st = ost->st;
int ret;
@@ -188,21 +194,21 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
pkt->dts, pkt->pts,
ost->file_index, ost->st->index);
pkt->pts =
- pkt->dts = pkt->pts + pkt->dts + ost->last_mux_dts + 1
- - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1)
- - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1);
+ pkt->dts = pkt->pts + pkt->dts + ms->last_mux_dts + 1
+ - FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1)
+ - FFMAX3(pkt->pts, pkt->dts, ms->last_mux_dts + 1);
}
if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) &&
pkt->dts != AV_NOPTS_VALUE &&
- ost->last_mux_dts != AV_NOPTS_VALUE) {
- int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
+ ms->last_mux_dts != AV_NOPTS_VALUE) {
+ int64_t max = ms->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
if (pkt->dts < max) {
int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG;
if (exit_on_error)
loglevel = AV_LOG_ERROR;
av_log(s, loglevel, "Non-monotonous DTS in output stream "
"%d:%d; previous: %"PRId64", current: %"PRId64"; ",
- ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts);
+ ost->file_index, ost->st->index, ms->last_mux_dts, pkt->dts);
if (exit_on_error) {
av_log(NULL, AV_LOG_FATAL, "aborting.\n");
exit_program(1);
@@ -216,7 +222,7 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
}
}
}
- ost->last_mux_dts = pkt->dts;
+ ms->last_mux_dts = pkt->dts;
ost->data_size += pkt->size;
ost->packets_written++;
@@ -245,26 +251,10 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
}
}
-void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
+static void submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
{
- AVStream *st = ost->st;
int ret;
- /*
- * Audio encoders may split the packets -- #frames in != #packets out.
- * But there is no reordering, so we can limit the number of output packets
- * by simply dropping them here.
- * Counting encoded video frames needs to be done separately because of
- * reordering, see do_video_out().
- */
- if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) {
- if (ost->frame_number >= ost->max_frames) {
- av_packet_unref(pkt);
- return;
- }
- ost->frame_number++;
- }
-
if (of->mux->header_written) {
write_packet(of, ost, pkt);
} else {
@@ -277,6 +267,52 @@ void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
}
}
+void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
+{
+ AVStream *st = ost->st;
+
+ if (!eof) {
+ /*
+ * Audio encoders may split the packets -- #frames in != #packets out.
+ * But there is no reordering, so we can limit the number of output packets
+ * by simply dropping them here.
+ * Counting encoded video frames needs to be done separately because of
+ * reordering, see do_video_out().
+ */
+ if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) {
+ if (ost->frame_number >= ost->max_frames) {
+ av_packet_unref(pkt);
+ return;
+ }
+ ost->frame_number++;
+ }
+ }
+
+ if (ost->sq_idx_mux >= 0) {
+ int ret = sq_send(of->sq_mux, ost->sq_idx_mux,
+ SQPKT(eof ? NULL: pkt));
+ if (ret < 0) {
+ av_packet_unref(pkt);
+ if (ret == AVERROR_EOF) {
+ ost->finished |= MUXER_FINISHED;
+ return;
+ } else
+ exit_program(1);
+ }
+
+ while (1) {
+ ret = sq_receive(of->sq_mux, -1, SQPKT(pkt));
+ if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
+ return;
+ else if (ret < 0)
+ exit_program(1);
+
+ submit_packet(of, pkt, output_streams[of->ost_index + ret]);
+ }
+ } else if (!eof)
+ submit_packet(of, pkt, ost);
+}
+
static int print_sdp(void)
{
char sdp[16384];
@@ -447,6 +483,9 @@ void of_close(OutputFile **pof)
if (!of)
return;
+ sq_free(&of->sq_encode);
+ sq_free(&of->sq_mux);
+
s = of->ctx;
mux_free(&of->mux, s ? s->nb_streams : 0);
@@ -481,6 +520,7 @@ int of_muxer_init(OutputFile *of, AVDictionary *opts, int64_t limit_filesize)
ret = AVERROR(ENOMEM);
goto fail;
}
+ ms->last_mux_dts = AV_NOPTS_VALUE;
}
mux->limit_filesize = limit_filesize;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index adad46de5f..8884a5f9ed 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -30,6 +30,7 @@
#include "ffmpeg.h"
#include "cmdutils.h"
#include "opt_common.h"
+#include "sync_queue.h"
#include "libavformat/avformat.h"
@@ -1640,6 +1641,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
input_streams[source_index]->st->discard = input_streams[source_index]->user_set_discard;
}
ost->last_mux_dts = AV_NOPTS_VALUE;
+ ost->last_filter_pts = AV_NOPTS_VALUE;
return ost;
}
@@ -2299,6 +2301,78 @@ static int init_complex_filters(void)
return 0;
}
+static int setup_sync_queues(OutputFile *of, AVFormatContext *oc)
+{
+ int nb_av_enc = 0, nb_interleaved = 0;
+
+#define IS_AV_ENC(ost, type) \
+ (ost->encoding_needed && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))
+#define IS_INTERLEAVED(type) (type != AVMEDIA_TYPE_ATTACHMENT)
+
+ for (int i = 0; i < oc->nb_streams; i++) {
+ OutputStream *ost = output_streams[of->ost_index + i];
+ enum AVMediaType type = ost->st->codecpar->codec_type;
+
+ ost->sq_idx_encode = -1;
+ ost->sq_idx_mux = -1;
+
+ nb_interleaved += IS_INTERLEAVED(type);
+ nb_av_enc += IS_AV_ENC(ost, type);
+ }
+
+ if (!(nb_interleaved > 1 && of->shortest))
+ return 0;
+
+ /* if we have more than one encoded audio/video streams, then we
+ * synchronize them before encoding */
+ if (nb_av_enc > 1) {
+ of->sq_encode = sq_alloc(SYNC_QUEUE_FRAMES);
+ if (!of->sq_encode)
+ return AVERROR(ENOMEM);
+
+ for (int i = 0; i < oc->nb_streams; i++) {
+ OutputStream *ost = output_streams[of->ost_index + i];
+ enum AVMediaType type = ost->st->codecpar->codec_type;
+
+ if (!IS_AV_ENC(ost, type))
+ continue;
+
+ ost->sq_idx_encode = sq_add_stream(of->sq_encode);
+ if (ost->sq_idx_encode < 0)
+ return ost->sq_idx_encode;
+
+ ost->sq_frame = av_frame_alloc();
+ if (!ost->sq_frame)
+ return AVERROR(ENOMEM);
+ }
+ }
+
+ /* if there any additional interleaved streams, then ALL the streams
+ * are also synchronized before sending them to the muxer */
+ if (nb_interleaved > nb_av_enc) {
+ of->sq_mux = sq_alloc(SYNC_QUEUE_PACKETS);
+ if (!of->sq_mux)
+ return AVERROR(ENOMEM);
+
+ for (int i = 0; i < oc->nb_streams; i++) {
+ OutputStream *ost = output_streams[of->ost_index + i];
+ enum AVMediaType type = ost->st->codecpar->codec_type;
+
+ if (!IS_INTERLEAVED(type))
+ continue;
+
+ ost->sq_idx_mux = sq_add_stream(of->sq_mux);
+ if (ost->sq_idx_mux < 0)
+ return ost->sq_idx_mux;
+ }
+ }
+
+#undef IS_AV_ENC
+#undef IS_INTERLEAVED
+
+ return 0;
+}
+
static int open_output_file(OptionsContext *o, const char *filename)
{
AVFormatContext *oc;
@@ -2936,6 +3010,12 @@ loop_end:
exit_program(1);
}
+ err = setup_sync_queues(of, oc);
+ if (err < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Error setting up output sync queues\n");
+ exit_program(1);
+ }
+
err = of_muxer_init(of, format_opts, o->limit_filesize);
if (err < 0) {
av_log(NULL, AV_LOG_FATAL, "Error initializing internal muxing state\n");
diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c
new file mode 100644
index 0000000000..cdf6a32cae
--- /dev/null
+++ b/fftools/sync_queue.c
@@ -0,0 +1,346 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/error.h"
+#include "libavutil/fifo.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/mem.h"
+
+#include "sync_queue.h"
+
+typedef struct SyncQueueStream {
+ AVFifo *fifo;
+ AVRational tb;
+ int64_t head_ts;
+ int finished;
+} SyncQueueStream;
+
+struct SyncQueue {
+ enum SyncQueueType type;
+
+ SyncQueueStream *streams;
+ unsigned int nb_streams;
+
+ // pool of preallocated frames to avoid constant allocations
+ SyncQueueFrame free_frames[32];
+ unsigned int nb_free_frames;
+
+ /* sync head: the stream with the smallest last timestamp */
+ int head_stream;
+ /* the finished stream with the smallest finish timestamp or -1 */
+ int head_finished_stream;
+ int finished;
+};
+
+static void frame_free(const SyncQueue *sq, SyncQueueFrame frame)
+{
+ if (sq->type == SYNC_QUEUE_PACKETS)
+ av_packet_free(&frame.p);
+ else
+ av_frame_free(&frame.f);
+}
+
+static void frame_clear(const SyncQueue *sq, SyncQueueFrame frame)
+{
+ if (sq->type == SYNC_QUEUE_PACKETS)
+ av_packet_unref(frame.p);
+ else
+ av_frame_unref(frame.f);
+}
+
+static void frame_release(SyncQueue *sq, SyncQueueFrame frame)
+{
+ if (sq->nb_free_frames < FF_ARRAY_ELEMS(sq->free_frames)) {
+ frame_clear(sq, frame);
+ sq->free_frames[sq->nb_free_frames++] = frame;
+ } else
+ frame_free(sq, frame);
+}
+
+static int frame_get(SyncQueue *sq, SyncQueueFrame *frame)
+{
+ if (sq->nb_free_frames) {
+ *frame = sq->free_frames[--sq->nb_free_frames];
+ memset(sq->free_frames + sq->nb_free_frames, 0, sizeof(sq->free_frames[0]));
+ return 0;
+ }
+ if (sq->type == SYNC_QUEUE_PACKETS) {
+ frame->p = av_packet_alloc();
+ return frame->p ? 0 : AVERROR(ENOMEM);
+ }
+ frame->f = av_frame_alloc();
+ return frame->f ? 0 : AVERROR(ENOMEM);
+}
+
+static void frame_move(const SyncQueue *sq, SyncQueueFrame dst,
+ SyncQueueFrame src)
+{
+ if (sq->type == SYNC_QUEUE_PACKETS)
+ av_packet_move_ref(dst.p, src.p);
+ else
+ av_frame_move_ref(dst.f, src.f);
+}
+
+static int64_t frame_ts(const SyncQueue *sq, SyncQueueFrame frame)
+{
+ return (sq->type == SYNC_QUEUE_PACKETS) ?
+ frame.p->pts + frame.p->duration :
+ frame.f->pts + frame.f->pkt_duration;
+}
+
+static int frame_null(const SyncQueue *sq, SyncQueueFrame frame)
+{
+ return (sq->type == SYNC_QUEUE_PACKETS) ? (frame.p == NULL) : (frame.f == NULL);
+}
+
+static void finish_stream(SyncQueue *sq, unsigned int stream_idx)
+{
+ SyncQueueStream *st = &sq->streams[stream_idx];
+
+ st->finished = 1;
+
+ if (st->head_ts != AV_NOPTS_VALUE) {
+ /* check if this stream is the new finished head */
+ if (sq->head_finished_stream < 0 ||
+ av_compare_ts(st->head_ts, st->tb,
+ sq->streams[sq->head_finished_stream].head_ts,
+ sq->streams[sq->head_finished_stream].tb) < 0) {
+ sq->head_finished_stream = stream_idx;
+ }
+
+ /* mark as finished all streams that should no longer receive new frames,
+ * due to them being ahead of some finished stream */
+ st = &sq->streams[sq->head_finished_stream];
+ for (unsigned int i = 0; i < sq->nb_streams; i++) {
+ SyncQueueStream *st1 = &sq->streams[i];
+ if (st != st1 && st1->head_ts != AV_NOPTS_VALUE &&
+ av_compare_ts(st->head_ts, st->tb, st1->head_ts, st1->tb) <= 0)
+ st1->finished = 1;
+ }
+ }
+
+ /* mark the whole queue as finished if all streams are finished */
+ for (unsigned int i = 0; i < sq->nb_streams; i++) {
+ if (!sq->streams[i].finished)
+ return;
+ }
+ sq->finished = 1;
+}
+
+int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame)
+{
+ SyncQueueStream *st;
+ SyncQueueFrame dst;
+ int64_t ts;
+ int ret;
+
+ av_assert0(stream_idx < sq->nb_streams);
+ st = &sq->streams[stream_idx];
+
+ if (frame_null(sq, frame)) {
+ finish_stream(sq, stream_idx);
+ return 0;
+ }
+ if (st->finished)
+ return AVERROR_EOF;
+
+ ret = frame_get(sq, &dst);
+ if (ret < 0)
+ return ret;
+
+ frame_move(sq, dst, frame);
+
+ ts = frame_ts(sq, dst);
+
+ ret = av_fifo_write(st->fifo, &dst, 1);
+ if (ret < 0) {
+ frame_move(sq, frame, dst);
+ frame_release(sq, dst);
+ return ret;
+ }
+
+ /* update this stream's head timestamp */
+ if (ts != AV_NOPTS_VALUE &&
+ (st->head_ts == AV_NOPTS_VALUE || st->head_ts < ts)) {
+ st->head_ts = ts;
+
+ /* if this stream is now ahead of some finished stream, then
+ * this stream is also finished */
+ if (sq->head_finished_stream >= 0 &&
+ av_compare_ts(sq->streams[sq->head_finished_stream].head_ts,
+ sq->streams[sq->head_finished_stream].tb,
+ ts, st->tb) <= 0)
+ st->finished = 1;
+
+ /* update the overall head timestamp if it could have changed */
+ if (sq->head_stream < 0 || sq->head_stream == stream_idx) {
+ sq->head_stream = stream_idx;
+ for (unsigned int i = 0; i < sq->nb_streams; i++) {
+ SyncQueueStream *st_head = &sq->streams[sq->head_stream];
+ SyncQueueStream *st_other = &sq->streams[i];
+ if (st_other->head_ts != AV_NOPTS_VALUE &&
+ av_compare_ts(st_other->head_ts, st_other->tb,
+ st_head->head_ts, st_head->tb) < 0)
+ sq->head_stream = i;
+ }
+ }
+ }
+
+
+ return 0;
+}
+
+static int frame_receive(SyncQueue *sq, unsigned int stream_idx,
+ SyncQueueFrame frame)
+{
+ SyncQueueStream *st_head = sq->head_stream >= 0 ?
+ &sq->streams[sq->head_stream] : NULL;
+ SyncQueueStream *st;
+
+ av_assert0(stream_idx < sq->nb_streams);
+ st = &sq->streams[stream_idx];
+
+ if (av_fifo_can_read(st->fifo)) {
+ SyncQueueFrame peek;
+ int64_t ts;
+ int cmp = 0;
+ int overflow = 0;
+
+ av_fifo_peek(st->fifo, &peek, 1, 0);
+ ts = frame_ts(sq, peek);
+
+ /* check if this stream's tail timestamp is before
+ * the overall queue head */
+ if (ts != AV_NOPTS_VALUE && st_head)
+ cmp = av_compare_ts(ts, st->tb, st_head->head_ts, st_head->tb);
+
+ /* also release the tail frame if this stream's head timestamp
+ * is over 10 seconds after the overall queue head */
+ if (st->head_ts != AV_NOPTS_VALUE && st_head) {
+ int64_t head_st = av_rescale_q(st->head_ts, st->tb, AV_TIME_BASE_Q);
+ int64_t head_queue = av_rescale_q(st_head->head_ts, st_head->tb,
+ AV_TIME_BASE_Q);
+ overflow = head_st - head_queue > 10 * AV_TIME_BASE;
+ }
+
+ /* return frames that are before the head;
+ * after all inputs are finished we can also return the head itself */
+ if (ts == AV_NOPTS_VALUE || cmp < 0 || overflow ||
+ (sq->finished && cmp == 0)) {
+ frame_move(sq, frame, peek);
+ frame_release(sq, peek);
+ av_fifo_drain2(st->fifo, 1);
+ return 0;
+ }
+ }
+
+ return sq->finished ? AVERROR_EOF : AVERROR(EAGAIN);
+}
+
+int sq_receive(SyncQueue *sq, int stream_idx, SyncQueueFrame frame)
+{
+ int nb_eof = 0;
+ int ret;
+
+ /* read a frame for a specific stream */
+ if (stream_idx >= 0) {
+ ret = frame_receive(sq, stream_idx, frame);
+ return (ret < 0) ? ret : stream_idx;
+ }
+
+ /* read a frame for any stream with available output */
+ for (unsigned int i = 0; i < sq->nb_streams; i++) {
+ ret = frame_receive(sq, i, frame);
+ if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) {
+ nb_eof += ret == AVERROR_EOF;
+ continue;
+ }
+ return (ret < 0) ? ret : i;
+ }
+
+ return (nb_eof == sq->nb_streams) ? AVERROR_EOF : AVERROR(EAGAIN);
+}
+
+int sq_add_stream(SyncQueue *sq)
+{
+ SyncQueueStream *tmp, *st;
+
+ tmp = av_realloc_array(sq->streams, sq->nb_streams + 1, sizeof(*sq->streams));
+ if (!tmp)
+ return AVERROR(ENOMEM);
+ sq->streams = tmp;
+
+ st = &sq->streams[sq->nb_streams];
+ memset(st, 0, sizeof(*st));
+
+ st->fifo = av_fifo_alloc2(1, sizeof(SyncQueueFrame), AV_FIFO_FLAG_AUTO_GROW);
+ if (!st->fifo)
+ return AVERROR(ENOMEM);
+
+ st->head_ts = AV_NOPTS_VALUE;
+
+ return sq->nb_streams++;
+}
+
+void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb)
+{
+ av_assert0(stream_idx < sq->nb_streams);
+ sq->streams[stream_idx].tb = tb;
+}
+
+SyncQueue *sq_alloc(enum SyncQueueType type)
+{
+ SyncQueue *sq = av_mallocz(sizeof(*sq));
+
+ if (!sq)
+ return NULL;
+
+ sq->type = type;
+
+ sq->head_stream = -1;
+ sq->head_finished_stream = -1;
+
+ return sq;
+}
+
+void sq_free(SyncQueue **psq)
+{
+ SyncQueue *sq = *psq;
+
+ if (!sq)
+ return;
+
+ for (unsigned int i = 0; i < sq->nb_streams; i++) {
+ SyncQueueFrame frame;
+ while (av_fifo_read(sq->streams[i].fifo, &frame, 1) >= 0)
+ frame_free(sq, frame);
+
+ av_fifo_freep2(&sq->streams[i].fifo);
+ }
+
+ av_freep(&sq->streams);
+
+ for (unsigned int i = 0; i < sq->nb_free_frames; i++)
+ frame_free(sq, sq->free_frames[i]);
+
+ av_freep(psq);
+}
diff --git a/fftools/sync_queue.h b/fftools/sync_queue.h
new file mode 100644
index 0000000000..4a16ae3e62
--- /dev/null
+++ b/fftools/sync_queue.h
@@ -0,0 +1,93 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_SYNC_QUEUE_H
+#define FFTOOLS_SYNC_QUEUE_H
+
+#include "libavcodec/packet.h"
+
+#include "libavutil/frame.h"
+
+enum SyncQueueType {
+ SYNC_QUEUE_PACKETS,
+ SYNC_QUEUE_FRAMES,
+};
+
+typedef union SyncQueueFrame {
+ AVFrame *f;
+ AVPacket *p;
+} SyncQueueFrame;
+
+#define SQFRAME(frame) ((SyncQueueFrame){ .f = (frame) })
+#define SQPKT(pkt) ((SyncQueueFrame){ .p = (pkt) })
+
+typedef struct SyncQueue SyncQueue;
+
+SyncQueue *sq_alloc(enum SyncQueueType type);
+void sq_free(SyncQueue **sq);
+
+/**
+ * Add a new stream to the sync queue.
+ *
+ * @return
+ * - a non-negative stream index on success
+ * - a negative error code on error
+ */
+int sq_add_stream(SyncQueue *sq);
+
+/**
+ * Set the timebase for the stream with index stream_idx. Should be called
+ * before sending any frames for this stream.
+ */
+void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb);
+
+/**
+ * Submit a frame for the stream with index stream_idx.
+ *
+ * On success, the sync queue takes ownership of the frame and will reset the
+ * contents of the supplied frame. On failure, the frame remains owned by the
+ * caller.
+ *
+ * Sending a frame with NULL contents marks the stream as finished.
+ *
+ * @return
+ * - 0 on success
+ * - AVERROR_EOF when no more frames should be submitted for this stream
+ * - another a negative error code on failure
+ */
+int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame);
+
+/**
+ * Read a frame from the queue.
+ *
+ * @param stream_idx index of the stream to read a frame for. May be -1, then
+ * try to read a frame from any stream that is ready for
+ * output.
+ * @param frame output frame will be written here on success. The frame is owned
+ * by the caller.
+ *
+ * @return
+ * - a non-negative index of the stream to which the returned frame belongs
+ * - AVERROR(EAGAIN) when more frames need to be submitted to the queue
+ * - AVERROR_EOF when no more frames will be available for this stream (for any
+ * stream if stream_idx is -1)
+ * - another negative error code on failure
+ */
+int sq_receive(SyncQueue *sq, int stream_idx, SyncQueueFrame frame);
+
+#endif // FFTOOLS_SYNC_QUEUE_H
diff --git a/tests/ref/fate/copy-shortest1 b/tests/ref/fate/copy-shortest1
index 5038973e4e..87bee4c41f 100644
--- a/tests/ref/fate/copy-shortest1
+++ b/tests/ref/fate/copy-shortest1
@@ -120,4 +120,3 @@
0, 98304, 98304, 2048, 11182, e35a2ab846029effdbca0e43639717f2
1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af
0, 100352, 100352, 2048, 1423, f480272c7d0b97834bc8ea36cceca61d
-1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d
diff --git a/tests/ref/fate/copy-shortest2 b/tests/ref/fate/copy-shortest2
index 5038973e4e..87bee4c41f 100644
--- a/tests/ref/fate/copy-shortest2
+++ b/tests/ref/fate/copy-shortest2
@@ -120,4 +120,3 @@
0, 98304, 98304, 2048, 11182, e35a2ab846029effdbca0e43639717f2
1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af
0, 100352, 100352, 2048, 1423, f480272c7d0b97834bc8ea36cceca61d
-1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 35/49] fftools/ffmpeg: use the sync queues to handle -frames
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (33 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 34/49] fftools/ffmpeg: rework -shortest implementation Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 36/49] fftools/ffmpeg: stop using OutputStream.frame_number in print_report() Anton Khirnov
` (16 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Same issues apply to it as to -shortest.
Changes the results of the following tests:
- matroska-flac-extradata-update
The test reencodes two input FLAC streams into three output FLAC
streams. The last output stream is limited to 8 frames. The current
code results in the first two output streams having 12 frames, after
this commit all three streams have 8 frames and are the same length.
This new result is better, since it is predictable.
- mkv-1242
The test streamcopies one video and one audio stream, video is limited
to 11 frames. The new result shortens the audio stream so that it is
not longer than the video.
---
fftools/ffmpeg.c | 6 ------
fftools/ffmpeg_mux.c | 10 +---------
fftools/ffmpeg_opt.c | 18 +++++++++++++++---
fftools/sync_queue.c | 13 +++++++++++++
fftools/sync_queue.h | 7 +++++++
| 16 +++++-----------
tests/ref/fate/mkv-1242 | 3 ---
7 files changed, 41 insertions(+), 32 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 8674f52047..e46554ddf4 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -3412,12 +3412,6 @@ static int need_output(void)
if (ost->finished || of_finished(of))
continue;
- if (ost->frame_number >= ost->max_frames) {
- int j;
- for (j = 0; j < of->ctx->nb_streams; j++)
- close_output_stream(output_streams[of->ost_index + j]);
- continue;
- }
return 1;
}
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 69f01448b8..11d5a0a885 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -273,19 +273,11 @@ void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
if (!eof) {
/*
- * Audio encoders may split the packets -- #frames in != #packets out.
- * But there is no reordering, so we can limit the number of output packets
- * by simply dropping them here.
* Counting encoded video frames needs to be done separately because of
* reordering, see do_video_out().
*/
- if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) {
- if (ost->frame_number >= ost->max_frames) {
- av_packet_unref(pkt);
- return;
- }
+ if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed))
ost->frame_number++;
- }
}
if (ost->sq_idx_mux >= 0) {
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 8884a5f9ed..ac0b4fc7d8 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2304,6 +2304,7 @@ static int init_complex_filters(void)
static int setup_sync_queues(OutputFile *of, AVFormatContext *oc)
{
int nb_av_enc = 0, nb_interleaved = 0;
+ int limit_frames = 0, limit_frames_av_enc = 0;
#define IS_AV_ENC(ost, type) \
(ost->encoding_needed && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO))
@@ -2318,14 +2319,19 @@ static int setup_sync_queues(OutputFile *of, AVFormatContext *oc)
nb_interleaved += IS_INTERLEAVED(type);
nb_av_enc += IS_AV_ENC(ost, type);
+
+ limit_frames |= ost->max_frames < INT64_MAX;
+ limit_frames_av_enc |= (ost->max_frames < INT64_MAX) && IS_AV_ENC(ost, type);
}
- if (!(nb_interleaved > 1 && of->shortest))
+ if (!((nb_interleaved > 1 && of->shortest) ||
+ (nb_interleaved > 0 && limit_frames)))
return 0;
- /* if we have more than one encoded audio/video streams, then we
+ /* if we have more than one encoded audio/video streams, or at least
+ * one encoded audio/video stream is frame-limited, then we
* synchronize them before encoding */
- if (nb_av_enc > 1) {
+ if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc) {
of->sq_encode = sq_alloc(SYNC_QUEUE_FRAMES);
if (!of->sq_encode)
return AVERROR(ENOMEM);
@@ -2344,6 +2350,9 @@ static int setup_sync_queues(OutputFile *of, AVFormatContext *oc)
ost->sq_frame = av_frame_alloc();
if (!ost->sq_frame)
return AVERROR(ENOMEM);
+
+ if (ost->max_frames != INT64_MAX)
+ sq_limit_frames(of->sq_encode, ost->sq_idx_encode, ost->max_frames);
}
}
@@ -2364,6 +2373,9 @@ static int setup_sync_queues(OutputFile *of, AVFormatContext *oc)
ost->sq_idx_mux = sq_add_stream(of->sq_mux);
if (ost->sq_idx_mux < 0)
return ost->sq_idx_mux;
+
+ if (ost->max_frames != INT64_MAX)
+ sq_limit_frames(of->sq_mux, ost->sq_idx_mux, ost->max_frames);
}
}
diff --git a/fftools/sync_queue.c b/fftools/sync_queue.c
index cdf6a32cae..8bfdcbab4d 100644
--- a/fftools/sync_queue.c
+++ b/fftools/sync_queue.c
@@ -32,6 +32,9 @@ typedef struct SyncQueueStream {
AVRational tb;
int64_t head_ts;
int finished;
+
+ uint64_t frames_sent;
+ uint64_t frames_max;
} SyncQueueStream;
struct SyncQueue {
@@ -205,6 +208,9 @@ int sq_send(SyncQueue *sq, unsigned int stream_idx, SyncQueueFrame frame)
}
}
+ st->frames_sent++;
+ if (st->frames_sent >= st->frames_max)
+ finish_stream(sq, stream_idx);
return 0;
}
@@ -297,6 +303,7 @@ int sq_add_stream(SyncQueue *sq)
return AVERROR(ENOMEM);
st->head_ts = AV_NOPTS_VALUE;
+ st->frames_max = UINT64_MAX;
return sq->nb_streams++;
}
@@ -307,6 +314,12 @@ void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb)
sq->streams[stream_idx].tb = tb;
}
+void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx, uint64_t frames)
+{
+ av_assert0(stream_idx < sq->nb_streams);
+ sq->streams[stream_idx].frames_max = frames;
+}
+
SyncQueue *sq_alloc(enum SyncQueueType type)
{
SyncQueue *sq = av_mallocz(sizeof(*sq));
diff --git a/fftools/sync_queue.h b/fftools/sync_queue.h
index 4a16ae3e62..9afd067c25 100644
--- a/fftools/sync_queue.h
+++ b/fftools/sync_queue.h
@@ -56,6 +56,13 @@ int sq_add_stream(SyncQueue *sq);
*/
void sq_set_tb(SyncQueue *sq, unsigned int stream_idx, AVRational tb);
+/**
+ * Limit the number of output frames for stream with index stream_idx
+ * to max_frames.
+ */
+void sq_limit_frames(SyncQueue *sq, unsigned int stream_idx,
+ uint64_t max_frames);
+
/**
* Submit a frame for the stream with index stream_idx.
*
--git a/tests/ref/fate/matroska-flac-extradata-update b/tests/ref/fate/matroska-flac-extradata-update
index b0276f734d..84dcc9c1d0 100644
--- a/tests/ref/fate/matroska-flac-extradata-update
+++ b/tests/ref/fate/matroska-flac-extradata-update
@@ -1,8 +1,8 @@
-56ff5763fd81ad3bc02c22402cd685e2 *tests/data/fate/matroska-flac-extradata-update.matroska
-2008 tests/data/fate/matroska-flac-extradata-update.matroska
-#extradata 0: 34, 0x7acb09e7
-#extradata 1: 34, 0x7acb09e7
-#extradata 2: 34, 0x443402dd
+8ec02dffd603f44e08b2ae3b81a0d5a0 *tests/data/fate/matroska-flac-extradata-update.matroska
+1816 tests/data/fate/matroska-flac-extradata-update.matroska
+#extradata 0: 34, 0x93650c81
+#extradata 1: 34, 0x93650c81
+#extradata 2: 34, 0x93650c81
#tb 0: 1/1000
#media_type 0: audio
#codec_id 0: flac
@@ -42,9 +42,3 @@
0, 672, 672, 96, 26, 0x50dd042e
1, 672, 672, 96, 26, 0x50dd042e
2, 672, 672, 96, 26, 0x50dd042e
-0, 768, 768, 96, 26, 0x53de0499
-1, 768, 768, 96, 26, 0x53de0499
-0, 864, 864, 96, 26, 0x53df04b4
-1, 864, 864, 96, 26, 0x53df04b4
-0, 960, 960, 42, 26, 0x5740044b
-1, 960, 960, 42, 26, 0x5740044b
diff --git a/tests/ref/fate/mkv-1242 b/tests/ref/fate/mkv-1242
index e025701093..1d1a227832 100644
--- a/tests/ref/fate/mkv-1242
+++ b/tests/ref/fate/mkv-1242
@@ -42,6 +42,3 @@
1, 383, 383, 21, 325, 0xcd7a9fd6
1, 404, 404, 22, 359, 0x6edeb91c
1, 426, 426, 21, 333, 0xb8999fb7
-1, 447, 447, 21, 317, 0xf2589e1a
-1, 468, 468, 21, 319, 0x82ed9572
-1, 489, 489, 22, 473, 0xea54e696
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 36/49] fftools/ffmpeg: stop using OutputStream.frame_number in print_report()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (34 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 35/49] fftools/ffmpeg: use the sync queues to handle -frames Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 37/49] fftools/ffmpeg: only set OutputStream.frame_number for video encoding Anton Khirnov
` (15 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
This field means different things for video encoding (number of frames
emitted to the encoding sync queue/encoder by the video sync code) and
for everything else (number of packets sent to the muxer sync queue).
Print the value of packets_written instead, which means the same thing
for all kinds of streams. It is also more consistent with the code
below, which prints PSNR from the last muxed packet.
---
fftools/ffmpeg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index e46554ddf4..53b3657ec9 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1531,7 +1531,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
float fps;
- frame_number = ost->frame_number;
+ frame_number = ost->packets_written;
fps = t > 1 ? frame_number / t : 0;
av_bprintf(&buf, "frame=%5d fps=%3.*f q=%3.1f ",
frame_number, fps < 9.95, fps, q);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 37/49] fftools/ffmpeg: only set OutputStream.frame_number for video encoding
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (35 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 36/49] fftools/ffmpeg: stop using OutputStream.frame_number in print_report() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 38/49] fftools/ffmpeg: make the muxer AVFormatContext private to ffmpeg_mux.c Anton Khirnov
` (14 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
It is unused otherwise.
Rename the field to vsync_frame_number to better reflect its current
purpose.
---
fftools/ffmpeg.c | 10 +++++-----
fftools/ffmpeg.h | 3 ++-
fftools/ffmpeg_mux.c | 11 -----------
3 files changed, 7 insertions(+), 17 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 53b3657ec9..701baa3a28 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1108,7 +1108,7 @@ static void do_video_out(OutputFile *of,
switch (ost->vsync_method) {
case VSYNC_VSCFR:
- if (ost->frame_number == 0 && delta0 >= 0.5) {
+ if (ost->vsync_frame_number == 0 && delta0 >= 0.5) {
av_log(NULL, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0));
delta = duration;
delta0 = 0;
@@ -1116,7 +1116,7 @@ static void do_video_out(OutputFile *of,
}
case VSYNC_CFR:
// FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
- if (frame_drop_threshold && delta < frame_drop_threshold && ost->frame_number) {
+ if (frame_drop_threshold && delta < frame_drop_threshold && ost->vsync_frame_number) {
nb_frames = 0;
} else if (delta < -1.1)
nb_frames = 0;
@@ -1146,7 +1146,7 @@ static void do_video_out(OutputFile *of,
* But there may be reordering, so we can't throw away frames on encoder
* flush, we need to limit them here, before they go into encoder.
*/
- nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
+ nb_frames = FFMIN(nb_frames, ost->max_frames - ost->vsync_frame_number);
nb0_frames = FFMIN(nb0_frames, nb_frames);
memmove(ost->last_nb0_frames + 1,
@@ -1158,7 +1158,7 @@ static void do_video_out(OutputFile *of,
nb_frames_drop++;
av_log(NULL, AV_LOG_VERBOSE,
"*** dropping frame %d from stream %d at ts %"PRId64"\n",
- ost->frame_number, ost->st->index, ost->last_frame->pts);
+ ost->vsync_frame_number, ost->st->index, ost->last_frame->pts);
}
if (nb_frames > (nb0_frames && ost->last_dropped) + (nb_frames > nb0_frames)) {
if (nb_frames > dts_error_threshold * 30) {
@@ -1255,7 +1255,7 @@ static void do_video_out(OutputFile *of,
av_frame_remove_side_data(in_picture, AV_FRAME_DATA_A53_CC);
ost->sync_opts++;
- ost->frame_number++;
+ ost->vsync_frame_number++;
}
av_frame_unref(ost->last_frame);
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index dfda6ccbe9..962867b783 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -457,7 +457,8 @@ typedef struct OutputStream {
int source_index; /* InputStream index */
AVStream *st; /* stream in the output file */
int encoding_needed; /* true if encoding needed for this stream */
- int frame_number;
+ /* number of frames emitted by the video-encoding sync code */
+ int vsync_frame_number;
/* input pts and corresponding output pts
for A/V sync */
struct InputStream *sync_ist; /* input stream to sync against */
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 11d5a0a885..1d8827277d 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -269,17 +269,6 @@ static void submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
{
- AVStream *st = ost->st;
-
- if (!eof) {
- /*
- * Counting encoded video frames needs to be done separately because of
- * reordering, see do_video_out().
- */
- if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed))
- ost->frame_number++;
- }
-
if (ost->sq_idx_mux >= 0) {
int ret = sq_send(of->sq_mux, ost->sq_idx_mux,
SQPKT(eof ? NULL: pkt));
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 38/49] fftools/ffmpeg: make the muxer AVFormatContext private to ffmpeg_mux.c
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (36 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 37/49] fftools/ffmpeg: only set OutputStream.frame_number for video encoding Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 39/49] fftools/ffmpeg_mux: return errors from of_submit_packet() Anton Khirnov
` (13 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Since the muxer will operate in a separate thread in the future, the
muxer context should not be accessed from the outside.
---
fftools/ffmpeg.c | 4 +--
fftools/ffmpeg.h | 6 ++--
fftools/ffmpeg_filter.c | 6 ++--
fftools/ffmpeg_mux.c | 80 +++++++++++++++++++++++++----------------
fftools/ffmpeg_opt.c | 6 ++--
5 files changed, 62 insertions(+), 40 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 701baa3a28..7e9ac943de 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1442,9 +1442,9 @@ static void print_final_stats(int64_t total_size)
uint64_t total_packets = 0, total_size = 0;
av_log(NULL, AV_LOG_VERBOSE, "Output file #%d (%s):\n",
- i, of->ctx->url);
+ i, of->url);
- for (j = 0; j < of->ctx->nb_streams; j++) {
+ for (j = 0; j < of->nb_streams; j++) {
OutputStream *ost = output_streams[of->ost_index + j];
enum AVMediaType type = ost->enc_ctx->codec_type;
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 962867b783..2ba58b492f 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -583,11 +583,12 @@ typedef struct OutputFile {
Muxer *mux;
const AVOutputFormat *format;
+ const char *url;
SyncQueue *sq_encode;
SyncQueue *sq_mux;
- AVFormatContext *ctx;
+ int nb_streams;
int ost_index; /* index of the first stream in output_streams */
int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units
int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units
@@ -696,7 +697,8 @@ int hw_device_setup_for_filter(FilterGraph *fg);
int hwaccel_decode_init(AVCodecContext *avctx);
-int of_muxer_init(OutputFile *of, AVDictionary *opts, int64_t limit_filesize);
+int of_muxer_init(OutputFile *of, AVFormatContext *fc,
+ AVDictionary *opts, int64_t limit_filesize);
/* open the muxer when all the streams are initialized */
int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 0845c631a5..122b17686a 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -603,11 +603,11 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter,
if (ost->apad && of->shortest) {
int i;
- for (i=0; i<of->ctx->nb_streams; i++)
- if (of->ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
+ for (i = 0; i < of->nb_streams; i++)
+ if (output_streams[of->ost_index + i]->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
break;
- if (i<of->ctx->nb_streams) {
+ if (i < of->nb_streams) {
AUTO_INSERT_FILTER("-apad", "apad", ost->apad);
}
}
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 1d8827277d..0a8bdc36d9 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -49,6 +49,8 @@ typedef struct MuxStream {
} MuxStream;
struct Muxer {
+ AVFormatContext *fc;
+
MuxStream *streams;
AVDictionary *opts;
@@ -167,7 +169,7 @@ static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
{
MuxStream *ms = &of->mux->streams[ost->index];
- AVFormatContext *s = of->ctx;
+ AVFormatContext *s = of->mux->fc;
AVStream *st = ost->st;
int ret;
@@ -311,8 +313,8 @@ static int print_sdp(void)
if (!avc)
exit_program(1);
for (i = 0, j = 0; i < nb_output_files; i++) {
- if (!strcmp(output_files[i]->ctx->oformat->name, "rtp")) {
- avc[j] = output_files[i]->ctx;
+ if (!strcmp(output_files[i]->format->name, "rtp")) {
+ avc[j] = output_files[i]->mux->fc;
j++;
}
}
@@ -350,15 +352,16 @@ fail:
/* open the muxer when all the streams are initialized */
int of_check_init(OutputFile *of)
{
+ AVFormatContext *fc = of->mux->fc;
int ret, i;
- for (i = 0; i < of->ctx->nb_streams; i++) {
+ for (i = 0; i < fc->nb_streams; i++) {
OutputStream *ost = output_streams[of->ost_index + i];
if (!ost->initialized)
return 0;
}
- ret = avformat_write_header(of->ctx, &of->mux->opts);
+ ret = avformat_write_header(fc, &of->mux->opts);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR,
"Could not write header for output file #%d "
@@ -369,7 +372,7 @@ int of_check_init(OutputFile *of)
//assert_avoptions(of->opts);
of->mux->header_written = 1;
- av_dump_format(of->ctx, of->index, of->ctx->url, 1);
+ av_dump_format(fc, of->index, fc->url, 1);
nb_output_dumped++;
if (sdp_filename || want_sdp) {
@@ -381,7 +384,7 @@ int of_check_init(OutputFile *of)
}
/* flush the muxing queues */
- for (i = 0; i < of->ctx->nb_streams; i++) {
+ for (i = 0; i < fc->nb_streams; i++) {
MuxStream *ms = &of->mux->streams[i];
OutputStream *ost = output_streams[of->ost_index + i];
AVPacket *pkt;
@@ -402,29 +405,30 @@ int of_check_init(OutputFile *of)
int of_write_trailer(OutputFile *of)
{
+ AVFormatContext *fc = of->mux->fc;
int ret;
if (!of->mux->header_written) {
av_log(NULL, AV_LOG_ERROR,
"Nothing was written into output file %d (%s), because "
"at least one of its streams received no packets.\n",
- of->index, of->ctx->url);
+ of->index, fc->url);
return AVERROR(EINVAL);
}
- ret = av_write_trailer(of->ctx);
+ ret = av_write_trailer(fc);
if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", of->ctx->url, av_err2str(ret));
+ av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", fc->url, av_err2str(ret));
return ret;
}
of->mux->final_filesize = of_filesize(of);
if (!(of->format->flags & AVFMT_NOFILE)) {
- ret = avio_closep(&of->ctx->pb);
+ ret = avio_closep(&fc->pb);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error closing file %s: %s\n",
- of->ctx->url, av_err2str(ret));
+ fc->url, av_err2str(ret));
return ret;
}
}
@@ -432,14 +436,28 @@ int of_write_trailer(OutputFile *of)
return 0;
}
-static void mux_free(Muxer **pmux, int nb_streams)
+static void fc_close(AVFormatContext **pfc)
+{
+ AVFormatContext *fc = *pfc;
+
+ if (!fc)
+ return;
+
+ if (!(fc->oformat->flags & AVFMT_NOFILE))
+ avio_closep(&fc->pb);
+ avformat_free_context(fc);
+
+ *pfc = NULL;
+}
+
+static void mux_free(Muxer **pmux)
{
Muxer *mux = *pmux;
if (!mux)
return;
- for (int i = 0; i < nb_streams; i++) {
+ for (int i = 0; i < mux->fc->nb_streams; i++) {
MuxStream *ms = &mux->streams[i];
AVPacket *pkt;
@@ -453,13 +471,14 @@ static void mux_free(Muxer **pmux, int nb_streams)
av_freep(&mux->streams);
av_dict_free(&mux->opts);
+ fc_close(&mux->fc);
+
av_freep(pmux);
}
void of_close(OutputFile **pof)
{
OutputFile *of = *pof;
- AVFormatContext *s;
if (!of)
return;
@@ -467,34 +486,33 @@ void of_close(OutputFile **pof)
sq_free(&of->sq_encode);
sq_free(&of->sq_mux);
- s = of->ctx;
-
- mux_free(&of->mux, s ? s->nb_streams : 0);
-
- if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE))
- avio_closep(&s->pb);
- avformat_free_context(s);
+ mux_free(&of->mux);
av_freep(pof);
}
-int of_muxer_init(OutputFile *of, AVDictionary *opts, int64_t limit_filesize)
+int of_muxer_init(OutputFile *of, AVFormatContext *fc,
+ AVDictionary *opts, int64_t limit_filesize)
{
Muxer *mux = av_mallocz(sizeof(*mux));
int ret = 0;
- if (!mux)
+ if (!mux) {
+ fc_close(&fc);
return AVERROR(ENOMEM);
+ }
- mux->streams = av_calloc(of->ctx->nb_streams, sizeof(*mux->streams));
+ mux->streams = av_calloc(fc->nb_streams, sizeof(*mux->streams));
if (!mux->streams) {
+ fc_close(&fc);
av_freep(&mux);
return AVERROR(ENOMEM);
}
of->mux = mux;
+ mux->fc = fc;
- for (int i = 0; i < of->ctx->nb_streams; i++) {
+ for (int i = 0; i < fc->nb_streams; i++) {
MuxStream *ms = &mux->streams[i];
ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0);
if (!ms->muxing_queue) {
@@ -511,7 +529,7 @@ int of_muxer_init(OutputFile *of, AVDictionary *opts, int64_t limit_filesize)
want_sdp = 0;
/* write the header for files with no streams */
- if (of->format->flags & AVFMT_NOSTREAMS && of->ctx->nb_streams == 0) {
+ if (of->format->flags & AVFMT_NOSTREAMS && fc->nb_streams == 0) {
ret = of_check_init(of);
if (ret < 0)
goto fail;
@@ -519,7 +537,7 @@ int of_muxer_init(OutputFile *of, AVDictionary *opts, int64_t limit_filesize)
fail:
if (ret < 0)
- mux_free(&of->mux, of->ctx->nb_streams);
+ mux_free(&of->mux);
return ret;
}
@@ -531,7 +549,7 @@ int of_finished(OutputFile *of)
int64_t of_filesize(OutputFile *of)
{
- AVIOContext *pb = of->ctx->pb;
+ AVIOContext *pb = of->mux->fc->pb;
int64_t ret = -1;
if (of->mux->final_filesize)
@@ -548,6 +566,6 @@ int64_t of_filesize(OutputFile *of)
AVChapter * const *
of_get_chapters(OutputFile *of, unsigned int *nb_chapters)
{
- *nb_chapters = of->ctx->nb_chapters;
- return of->ctx->chapters;
+ *nb_chapters = of->mux->fc->nb_chapters;
+ return of->mux->fc->chapters;
}
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index ac0b4fc7d8..a86255e409 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -2428,7 +2428,6 @@ static int open_output_file(OptionsContext *o, const char *filename)
exit_program(1);
}
- of->ctx = oc;
of->format = oc->oformat;
if (o->recording_time != INT64_MAX)
oc->duration = o->recording_time;
@@ -3028,7 +3027,10 @@ loop_end:
exit_program(1);
}
- err = of_muxer_init(of, format_opts, o->limit_filesize);
+ of->nb_streams = oc->nb_streams;
+ of->url = filename;
+
+ err = of_muxer_init(of, oc, format_opts, o->limit_filesize);
if (err < 0) {
av_log(NULL, AV_LOG_FATAL, "Error initializing internal muxing state\n");
exit_program(1);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 39/49] fftools/ffmpeg_mux: return errors from of_submit_packet()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (37 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 38/49] fftools/ffmpeg: make the muxer AVFormatContext private to ffmpeg_mux.c Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 40/49] fftools/ffmpeg_mux: return errors from submit_packet() Anton Khirnov
` (12 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 54 +++++++++++++++++++++++++++++++-------------
fftools/ffmpeg.h | 2 +-
fftools/ffmpeg_mux.c | 12 ++++++----
3 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 7e9ac943de..9987b15888 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -712,6 +712,7 @@ static void close_output_stream(OutputStream *ost)
static void output_packet(OutputFile *of, AVPacket *pkt,
OutputStream *ost, int eof)
{
+ const char *err_msg;
int ret = 0;
if (!eof && pkt->dts != AV_NOPTS_VALUE)
@@ -719,25 +720,46 @@ static void output_packet(OutputFile *of, AVPacket *pkt,
/* apply the output bitstream filters */
if (ost->bsf_ctx) {
+ int bsf_eof = 0;
+
ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt);
- if (ret < 0)
- goto finish;
- while ((ret = av_bsf_receive_packet(ost->bsf_ctx, pkt)) >= 0)
- of_submit_packet(of, pkt, ost, 0);
- if (ret == AVERROR_EOF)
- of_submit_packet(of, pkt, ost, 1);
- if (ret == AVERROR(EAGAIN))
- ret = 0;
- } else
- of_submit_packet(of, pkt, ost, eof);
+ if (ret < 0) {
+ err_msg = "submitting a packet for bitstream filtering";
+ goto fail;
+ }
-finish:
- if (ret < 0 && ret != AVERROR_EOF) {
- av_log(NULL, AV_LOG_ERROR, "Error applying bitstream filters to an output "
- "packet for stream #%d:%d.\n", ost->file_index, ost->index);
- if(exit_on_error)
- exit_program(1);
+ while (!bsf_eof) {
+ ret = av_bsf_receive_packet(ost->bsf_ctx, pkt);
+ if (ret == AVERROR(EAGAIN))
+ return;
+ else if (ret == AVERROR_EOF)
+ bsf_eof = 1;
+ else if (ret < 0) {
+ err_msg = "applying bitstream filters to a packet";
+ goto fail;
+ }
+
+ ret = of_submit_packet(of, pkt, ost, ret == AVERROR_EOF);
+ if (ret < 0)
+ goto mux_fail;
+ }
+ } else {
+ ret = of_submit_packet(of, pkt, ost, eof);
+ if (ret < 0)
+ goto mux_fail;
}
+
+ return;
+
+mux_fail:
+ err_msg = "submitting a packet to the muxer";
+
+fail:
+ av_log(NULL, AV_LOG_ERROR, "Error %s for output stream #%d:%d.\n",
+ err_msg, ost->file_index, ost->index);
+ if (exit_on_error)
+ exit_program(1);
+
}
static int check_recording_time(OutputStream *ost)
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 2ba58b492f..fef66c2325 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -704,7 +704,7 @@ int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
void of_close(OutputFile **pof);
-void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof);
+int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof);
int of_finished(OutputFile *of);
int64_t of_filesize(OutputFile *of);
AVChapter * const *
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 0a8bdc36d9..3ea7636380 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -269,7 +269,7 @@ static void submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
}
}
-void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
+int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
{
if (ost->sq_idx_mux >= 0) {
int ret = sq_send(of->sq_mux, ost->sq_idx_mux,
@@ -278,22 +278,24 @@ void of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
av_packet_unref(pkt);
if (ret == AVERROR_EOF) {
ost->finished |= MUXER_FINISHED;
- return;
+ return 0;
} else
- exit_program(1);
+ return ret;
}
while (1) {
ret = sq_receive(of->sq_mux, -1, SQPKT(pkt));
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
- return;
+ return 0;
else if (ret < 0)
- exit_program(1);
+ return ret;
submit_packet(of, pkt, output_streams[of->ost_index + ret]);
}
} else if (!eof)
submit_packet(of, pkt, ost);
+
+ return 0;
}
static int print_sdp(void)
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 40/49] fftools/ffmpeg_mux: return errors from submit_packet()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (38 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 39/49] fftools/ffmpeg_mux: return errors from of_submit_packet() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 41/49] fftools/ffmpeg_mux: return errors from write_packet() Anton Khirnov
` (11 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_mux.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 3ea7636380..69af2c8d46 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -253,7 +253,7 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
}
}
-static void submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
+static int submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
{
int ret;
@@ -264,9 +264,11 @@ static void submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
ret = queue_packet(of, ost, pkt);
if (ret < 0) {
av_packet_unref(pkt);
- exit_program(1);
+ return ret;
}
}
+
+ return 0;
}
int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
@@ -290,10 +292,12 @@ int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
else if (ret < 0)
return ret;
- submit_packet(of, pkt, output_streams[of->ost_index + ret]);
+ ret = submit_packet(of, pkt, output_streams[of->ost_index + ret]);
+ if (ret < 0)
+ return ret;
}
} else if (!eof)
- submit_packet(of, pkt, ost);
+ return submit_packet(of, pkt, ost);
return 0;
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 41/49] fftools/ffmpeg_mux: return errors from write_packet()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (39 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 40/49] fftools/ffmpeg_mux: return errors from submit_packet() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 42/49] fftools/ffmpeg_mux: simplify submit_packet() Anton Khirnov
` (10 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_mux.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 69af2c8d46..37ae61fee8 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -166,7 +166,7 @@ static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
return 0;
}
-static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
+static int write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
{
MuxStream *ms = &of->mux->streams[ost->index];
AVFormatContext *s = of->mux->fc;
@@ -211,10 +211,8 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
av_log(s, loglevel, "Non-monotonous DTS in output stream "
"%d:%d; previous: %"PRId64", current: %"PRId64"; ",
ost->file_index, ost->st->index, ms->last_mux_dts, pkt->dts);
- if (exit_on_error) {
- av_log(NULL, AV_LOG_FATAL, "aborting.\n");
- exit_program(1);
- }
+ if (exit_on_error)
+ return AVERROR(EINVAL);
av_log(s, loglevel, "changing to %"PRId64". This may result "
"in incorrect timestamps in the output file.\n",
max);
@@ -250,7 +248,10 @@ static void write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
print_error("av_interleaved_write_frame()", ret);
main_return_code = 1;
close_all_output_streams(ost, MUXER_FINISHED | ENCODER_FINISHED, ENCODER_FINISHED);
+ return ret;
}
+
+ return 0;
}
static int submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
@@ -258,7 +259,7 @@ static int submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
int ret;
if (of->mux->header_written) {
- write_packet(of, ost, pkt);
+ return write_packet(of, ost, pkt);
} else {
/* the muxer is not initialized yet, buffer the packet */
ret = queue_packet(of, ost, pkt);
@@ -401,8 +402,10 @@ int of_check_init(OutputFile *of)
while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) {
ms->muxing_queue_data_size -= pkt->size;
- write_packet(of, ost, pkt);
+ ret = write_packet(of, ost, pkt);
av_packet_free(&pkt);
+ if (ret < 0)
+ return ret;
}
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 42/49] fftools/ffmpeg_mux: simplify submit_packet()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (40 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 41/49] fftools/ffmpeg_mux: return errors from write_packet() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 43/49] fftools/ffmpeg_mux: return errors from update_video_stats() Anton Khirnov
` (9 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_mux.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 37ae61fee8..2cdbd5feef 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -258,18 +258,14 @@ static int submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
{
int ret;
- if (of->mux->header_written) {
+ if (of->mux->header_written)
return write_packet(of, ost, pkt);
- } else {
- /* the muxer is not initialized yet, buffer the packet */
- ret = queue_packet(of, ost, pkt);
- if (ret < 0) {
- av_packet_unref(pkt);
- return ret;
- }
- }
- return 0;
+ /* the muxer is not initialized yet, buffer the packet */
+ ret = queue_packet(of, ost, pkt);
+ if (ret < 0)
+ av_packet_unref(pkt);
+ return ret;
}
int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 43/49] fftools/ffmpeg_mux: return errors from update_video_stats()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (41 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 42/49] fftools/ffmpeg_mux: simplify submit_packet() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 44/49] fftools/ffmpeg_mux: do not call exit_program() in print_sdp() Anton Khirnov
` (8 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_mux.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 2cdbd5feef..087009e0eb 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -63,7 +63,7 @@ struct Muxer {
static int want_sdp = 1;
-static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats)
+static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats)
{
const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
NULL);
@@ -82,14 +82,14 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write
}
if (!write_vstats)
- return;
+ return 0;
/* this is executed just the first time update_video_stats is called */
if (!vstats_file) {
vstats_file = fopen(vstats_filename, "w");
if (!vstats_file) {
perror("fopen");
- exit_program(1);
+ return AVERROR(errno);
}
}
@@ -116,6 +116,8 @@ static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write
fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
(double)ost->data_size / 1024, ti1, bitrate, avg_bitrate);
fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type));
+
+ return 0;
}
static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others)
@@ -227,8 +229,11 @@ static int write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
ost->data_size += pkt->size;
ost->packets_written++;
- if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)
- update_video_stats(ost, pkt, !!vstats_filename);
+ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed) {
+ ret = update_video_stats(ost, pkt, !!vstats_filename);
+ if (ret < 0)
+ return ret;
+ }
pkt->stream_index = ost->index;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 44/49] fftools/ffmpeg_mux: do not call exit_program() in print_sdp()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (42 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 43/49] fftools/ffmpeg_mux: return errors from update_video_stats() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 45/49] fftools/ffmpeg: stop using av_stream_get_end_pts() Anton Khirnov
` (7 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
Return an error instead, as is already done in other places in this
function.
---
fftools/ffmpeg_mux.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 087009e0eb..2fd131d1bc 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -319,7 +319,7 @@ static int print_sdp(void)
avc = av_malloc_array(nb_output_files, sizeof(*avc));
if (!avc)
- exit_program(1);
+ return AVERROR(ENOMEM);
for (i = 0, j = 0; i < nb_output_files; i++) {
if (!strcmp(output_files[i]->format->name, "rtp")) {
avc[j] = output_files[i]->mux->fc;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 45/49] fftools/ffmpeg: stop using av_stream_get_end_pts()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (43 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 44/49] fftools/ffmpeg_mux: do not call exit_program() in print_sdp() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 46/49] fftools/ffmpeg: do not write the output file header from init_output_stream() Anton Khirnov
` (6 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
It retrieves some muxer's internal timestamp with under-defined
semantics. Continuing to use this value would also require
synchronization once the muxer is moved to a separate thread.
Replace the value with last_mux_dts.
---
fftools/ffmpeg.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 9987b15888..0cab73ad7a 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1604,9 +1604,8 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
vid = 1;
}
/* compute min output value */
- if (av_stream_get_end_pts(ost->st) != AV_NOPTS_VALUE) {
- pts = FFMAX(pts, av_rescale_q(av_stream_get_end_pts(ost->st),
- ost->st->time_base, AV_TIME_BASE_Q));
+ if (ost->last_mux_dts != AV_NOPTS_VALUE) {
+ pts = FFMAX(pts, ost->last_mux_dts);
if (copy_ts) {
if (copy_ts_first_pts == AV_NOPTS_VALUE && pts > 1)
copy_ts_first_pts = pts;
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 46/49] fftools/ffmpeg: do not write the output file header from init_output_stream()
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (44 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 45/49] fftools/ffmpeg: stop using av_stream_get_end_pts() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 47/49] fftools/ffmpeg: depend on threads Anton Khirnov
` (5 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 4 -
fftools/ffmpeg.h | 2 -
fftools/ffmpeg_mux.c | 186 ++++++++++++++++++++++---------------------
3 files changed, 96 insertions(+), 96 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 0cab73ad7a..2dff41e57f 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -3230,10 +3230,6 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame,
ost->initialized = 1;
- ret = of_check_init(output_files[ost->file_index]);
- if (ret < 0)
- return ret;
-
return ret;
}
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index fef66c2325..14b98909d0 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -699,8 +699,6 @@ int hwaccel_decode_init(AVCodecContext *avctx);
int of_muxer_init(OutputFile *of, AVFormatContext *fc,
AVDictionary *opts, int64_t limit_filesize);
-/* open the muxer when all the streams are initialized */
-int of_check_init(OutputFile *of);
int of_write_trailer(OutputFile *of);
void of_close(OutputFile **pof);
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 2fd131d1bc..6ca9a51dd6 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -63,6 +63,59 @@ struct Muxer {
static int want_sdp = 1;
+static int print_sdp(void)
+{
+ char sdp[16384];
+ int i;
+ int j, ret;
+ AVIOContext *sdp_pb;
+ AVFormatContext **avc;
+
+ for (i = 0; i < nb_output_files; i++) {
+ if (!output_files[i]->mux->header_written)
+ return 0;
+ }
+
+ avc = av_malloc_array(nb_output_files, sizeof(*avc));
+ if (!avc)
+ return AVERROR(ENOMEM);
+ for (i = 0, j = 0; i < nb_output_files; i++) {
+ if (!strcmp(output_files[i]->format->name, "rtp")) {
+ avc[j] = output_files[i]->mux->fc;
+ j++;
+ }
+ }
+
+ if (!j) {
+ av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n");
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ ret = av_sdp_create(avc, j, sdp, sizeof(sdp));
+ if (ret < 0)
+ goto fail;
+
+ if (!sdp_filename) {
+ printf("SDP:\n%s\n", sdp);
+ fflush(stdout);
+ } else {
+ ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename);
+ goto fail;
+ }
+
+ avio_print(sdp_pb, sdp);
+ avio_closep(&sdp_pb);
+ av_freep(&sdp_filename);
+ }
+
+fail:
+ av_freep(&avc);
+ return ret;
+}
+
static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats)
{
const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
@@ -273,92 +326,8 @@ static int submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
return ret;
}
-int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
-{
- if (ost->sq_idx_mux >= 0) {
- int ret = sq_send(of->sq_mux, ost->sq_idx_mux,
- SQPKT(eof ? NULL: pkt));
- if (ret < 0) {
- av_packet_unref(pkt);
- if (ret == AVERROR_EOF) {
- ost->finished |= MUXER_FINISHED;
- return 0;
- } else
- return ret;
- }
-
- while (1) {
- ret = sq_receive(of->sq_mux, -1, SQPKT(pkt));
- if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
- return 0;
- else if (ret < 0)
- return ret;
-
- ret = submit_packet(of, pkt, output_streams[of->ost_index + ret]);
- if (ret < 0)
- return ret;
- }
- } else if (!eof)
- return submit_packet(of, pkt, ost);
-
- return 0;
-}
-
-static int print_sdp(void)
-{
- char sdp[16384];
- int i;
- int j, ret;
- AVIOContext *sdp_pb;
- AVFormatContext **avc;
-
- for (i = 0; i < nb_output_files; i++) {
- if (!output_files[i]->mux->header_written)
- return 0;
- }
-
- avc = av_malloc_array(nb_output_files, sizeof(*avc));
- if (!avc)
- return AVERROR(ENOMEM);
- for (i = 0, j = 0; i < nb_output_files; i++) {
- if (!strcmp(output_files[i]->format->name, "rtp")) {
- avc[j] = output_files[i]->mux->fc;
- j++;
- }
- }
-
- if (!j) {
- av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n");
- ret = AVERROR(EINVAL);
- goto fail;
- }
-
- ret = av_sdp_create(avc, j, sdp, sizeof(sdp));
- if (ret < 0)
- goto fail;
-
- if (!sdp_filename) {
- printf("SDP:\n%s\n", sdp);
- fflush(stdout);
- } else {
- ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL);
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename);
- goto fail;
- }
-
- avio_print(sdp_pb, sdp);
- avio_closep(&sdp_pb);
- av_freep(&sdp_filename);
- }
-
-fail:
- av_freep(&avc);
- return ret;
-}
-
/* open the muxer when all the streams are initialized */
-int of_check_init(OutputFile *of)
+static int check_write_header(OutputFile *of)
{
AVFormatContext *fc = of->mux->fc;
int ret, i;
@@ -397,10 +366,6 @@ int of_check_init(OutputFile *of)
OutputStream *ost = output_streams[of->ost_index + i];
AVPacket *pkt;
- /* try to improve muxing time_base (only possible if nothing has been written yet) */
- if (!av_fifo_can_read(ms->muxing_queue))
- ost->mux_timebase = ost->st->time_base;
-
while (av_fifo_read(ms->muxing_queue, &pkt, 1) >= 0) {
ms->muxing_queue_data_size -= pkt->size;
ret = write_packet(of, ost, pkt);
@@ -413,6 +378,47 @@ int of_check_init(OutputFile *of)
return 0;
}
+int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
+{
+ int ret;
+
+ if (!of->mux->header_written) {
+ ret = check_write_header(of);
+ if (ret < 0) {
+ av_packet_unref(pkt);
+ return ret;
+ }
+ }
+
+ if (ost->sq_idx_mux >= 0) {
+ ret = sq_send(of->sq_mux, ost->sq_idx_mux,
+ SQPKT(eof ? NULL: pkt));
+ if (ret < 0) {
+ av_packet_unref(pkt);
+ if (ret == AVERROR_EOF) {
+ ost->finished |= MUXER_FINISHED;
+ return 0;
+ } else
+ return ret;
+ }
+
+ while (1) {
+ ret = sq_receive(of->sq_mux, -1, SQPKT(pkt));
+ if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
+ return 0;
+ else if (ret < 0)
+ return ret;
+
+ ret = submit_packet(of, pkt, output_streams[of->ost_index + ret]);
+ if (ret < 0)
+ return ret;
+ }
+ } else if (!eof)
+ return submit_packet(of, pkt, ost);
+
+ return 0;
+}
+
int of_write_trailer(OutputFile *of)
{
AVFormatContext *fc = of->mux->fc;
@@ -540,7 +546,7 @@ int of_muxer_init(OutputFile *of, AVFormatContext *fc,
/* write the header for files with no streams */
if (of->format->flags & AVFMT_NOSTREAMS && fc->nb_streams == 0) {
- ret = of_check_init(of);
+ ret = check_write_header(of);
if (ret < 0)
goto fail;
}
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 47/49] fftools/ffmpeg: depend on threads
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (45 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 46/49] fftools/ffmpeg: do not write the output file header from init_output_stream() Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 48/49] fftools: add a multistream thread-safe queue Anton Khirnov
` (4 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
ffmpeg will be switched to a fully threaded architecture, starting with
muxers.
---
configure | 2 +-
fftools/ffmpeg.c | 20 --------------------
fftools/ffmpeg.h | 2 --
fftools/ffmpeg_opt.c | 2 --
4 files changed, 1 insertion(+), 25 deletions(-)
diff --git a/configure b/configure
index e4d36aa639..4888b136a4 100755
--- a/configure
+++ b/configure
@@ -3796,7 +3796,7 @@ avfilter_extralibs="pthreads_extralibs"
avutil_extralibs="d3d11va_extralibs nanosleep_extralibs pthreads_extralibs vaapi_drm_extralibs vaapi_x11_extralibs vdpau_x11_extralibs"
# programs
-ffmpeg_deps="avcodec avfilter avformat"
+ffmpeg_deps="avcodec avfilter avformat threads"
ffmpeg_select="aformat_filter anull_filter atrim_filter format_filter
hflip_filter null_filter
transpose_filter trim_filter vflip_filter"
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 2dff41e57f..9dfbc4216a 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -162,9 +162,7 @@ static struct termios oldtty;
static int restore_tty;
#endif
-#if HAVE_THREADS
static void free_input_threads(void);
-#endif
/* sub2video hack:
Convert subtitles to video with alpha to insert them in filter graphs.
@@ -592,9 +590,7 @@ static void ffmpeg_cleanup(int ret)
av_freep(&output_streams[i]);
}
-#if HAVE_THREADS
free_input_threads();
-#endif
for (i = 0; i < nb_input_files; i++) {
avformat_close_input(&input_files[i]->ctx);
av_packet_free(&input_files[i]->pkt);
@@ -3601,7 +3597,6 @@ static int check_keyboard_interaction(int64_t cur_time)
return 0;
}
-#if HAVE_THREADS
static void *input_thread(void *arg)
{
InputFile *f = arg;
@@ -3719,7 +3714,6 @@ static int get_input_packet_mt(InputFile *f, AVPacket **pkt)
f->non_blocking ?
AV_THREAD_MESSAGE_NONBLOCK : 0);
}
-#endif
static int get_input_packet(InputFile *f, AVPacket **pkt)
{
@@ -3742,10 +3736,8 @@ static int get_input_packet(InputFile *f, AVPacket **pkt)
}
}
-#if HAVE_THREADS
if (f->thread_queue_size)
return get_input_packet_mt(f, pkt);
-#endif
*pkt = f->pkt;
return av_read_frame(f->ctx, *pkt);
}
@@ -3885,15 +3877,11 @@ static int process_input(int file_index)
avcodec_flush_buffers(avctx);
}
}
-#if HAVE_THREADS
free_input_thread(file_index);
-#endif
ret = seek_to_start(ifile, is);
-#if HAVE_THREADS
thread_ret = init_input_thread(file_index);
if (thread_ret < 0)
return thread_ret;
-#endif
if (ret < 0)
av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n");
else
@@ -4133,11 +4121,9 @@ static int process_input(int file_index)
process_input_packet(ist, pkt, 0);
discard_packet:
-#if HAVE_THREADS
if (ifile->thread_queue_size)
av_packet_free(&pkt);
else
-#endif
av_packet_unref(pkt);
return 0;
@@ -4324,10 +4310,8 @@ static int transcode(void)
timer_start = av_gettime_relative();
-#if HAVE_THREADS
if ((ret = init_input_threads()) < 0)
goto fail;
-#endif
while (!received_sigterm) {
int64_t cur_time= av_gettime_relative();
@@ -4352,9 +4336,7 @@ static int transcode(void)
/* dump report by using the output first video and audio streams */
print_report(0, timer_start, cur_time);
}
-#if HAVE_THREADS
free_input_threads();
-#endif
/* at the end of stream, we must flush the decoder buffers */
for (i = 0; i < nb_input_streams; i++) {
@@ -4412,9 +4394,7 @@ static int transcode(void)
ret = 0;
fail:
-#if HAVE_THREADS
free_input_threads();
-#endif
if (output_streams) {
for (i = 0; i < nb_output_streams; i++) {
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 14b98909d0..407342462f 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -423,13 +423,11 @@ typedef struct InputFile {
AVPacket *pkt;
-#if HAVE_THREADS
AVThreadMessageQueue *in_thread_queue;
pthread_t thread; /* thread reading from this file */
int non_blocking; /* reading packets from the thread should not block */
int joined; /* the thread has been joined */
int thread_queue_size; /* maximum number of queued packets */
-#endif
} InputFile;
enum forced_keyframes_const {
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index a86255e409..9bf22f6932 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -1305,9 +1305,7 @@ static int open_input_file(OptionsContext *o, const char *filename)
f->pkt = av_packet_alloc();
if (!f->pkt)
exit_program(1);
-#if HAVE_THREADS
f->thread_queue_size = o->thread_queue_size;
-#endif
/* check if all codec options have been used */
unused_opts = strip_specifiers(o->g->codec_opts);
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 48/49] fftools: add a multistream thread-safe queue
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (46 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 47/49] fftools/ffmpeg: depend on threads Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 49/49] fftools/ffmpeg: move each muxer to a separate thread Anton Khirnov
` (3 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
It is similar to AVThreadMessageQueue, but supports multiple streams,
each with its own EOF state.
---
fftools/Makefile | 1 +
fftools/thread_queue.c | 232 +++++++++++++++++++++++++++++++++++++++++
fftools/thread_queue.h | 37 +++++++
3 files changed, 270 insertions(+)
create mode 100644 fftools/thread_queue.c
create mode 100644 fftools/thread_queue.h
diff --git a/fftools/Makefile b/fftools/Makefile
index f015df6846..b0de4f4c61 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -15,6 +15,7 @@ OBJS-ffmpeg += \
fftools/ffmpeg_mux.o \
fftools/ffmpeg_opt.o \
fftools/sync_queue.o \
+ fftools/thread_queue.o \
define DOFFTOOL
OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes)
diff --git a/fftools/thread_queue.c b/fftools/thread_queue.c
new file mode 100644
index 0000000000..9ec02ca772
--- /dev/null
+++ b/fftools/thread_queue.c
@@ -0,0 +1,232 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/error.h"
+#include "libavutil/fifo.h"
+#include "libavutil/mem.h"
+#include "libavutil/thread.h"
+
+#include "thread_queue.h"
+
+enum {
+ FINISHED_SEND = (1 << 0),
+ FINISHED_RECV = (1 << 1),
+};
+
+typedef struct ThreadQueueStream {
+ AVFifo *fifo;
+ int finished;
+} ThreadQueueStream;
+
+struct ThreadQueue {
+ ThreadQueueStream *streams;
+ unsigned int nb_streams;
+
+ void (*elem_free)(void *);
+
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+};
+
+void tq_free(ThreadQueue **ptq)
+{
+ ThreadQueue *tq = *ptq;
+
+ if (!tq)
+ return;
+
+ for (unsigned int i = 0; i < tq->nb_streams; i++) {
+ ThreadQueueStream *st = &tq->streams[i];
+
+ if (st->fifo && tq->elem_free) {
+ void *elem;
+ while (av_fifo_read(st->fifo, &elem, 1) >= 0)
+ tq->elem_free(elem);
+ }
+ av_fifo_freep2(&tq->streams[i].fifo);
+ }
+ av_freep(&tq->streams);
+
+ pthread_cond_destroy(&tq->cond);
+ pthread_mutex_destroy(&tq->lock);
+
+ av_freep(ptq);
+}
+
+ThreadQueue *tq_alloc(unsigned int nb_streams,
+ size_t nb_elems, size_t elem_size,
+ void (*elem_free)(void *))
+{
+ ThreadQueue *tq;
+ int ret;
+
+ tq = av_mallocz(sizeof(*tq));
+ if (!tq)
+ return NULL;
+
+ tq->elem_free = elem_free;
+
+ ret = pthread_cond_init(&tq->cond, NULL);
+ if (ret) {
+ av_freep(&tq);
+ return NULL;
+ }
+
+ ret = pthread_mutex_init(&tq->lock, NULL);
+ if (ret) {
+ pthread_cond_destroy(&tq->cond);
+ av_freep(&tq);
+ return NULL;
+ }
+
+ tq->streams = av_calloc(nb_streams, sizeof(*tq->streams));
+ if (!tq->streams)
+ goto fail;
+ tq->nb_streams = nb_streams;
+
+ for (unsigned int i = 0; i < nb_streams; i++) {
+ ThreadQueueStream *st = &tq->streams[i];
+
+ st->fifo = av_fifo_alloc2(nb_elems, elem_size, 0);
+ if (!st->fifo)
+ goto fail;
+ }
+
+ return tq;
+fail:
+ tq_free(&tq);
+ return NULL;
+}
+
+int tq_send(ThreadQueue *tq, unsigned int stream_idx, void *data)
+{
+ ThreadQueueStream *st;
+ int ret;
+
+ av_assert0(stream_idx < tq->nb_streams);
+ st = &tq->streams[stream_idx];
+
+ pthread_mutex_lock(&tq->lock);
+
+ if (st->finished & FINISHED_SEND) {
+ ret = AVERROR(EINVAL);
+ goto finish;
+ }
+
+ while (!(st->finished & FINISHED_RECV) && !av_fifo_can_write(st->fifo))
+ pthread_cond_wait(&tq->cond, &tq->lock);
+
+ if (st->finished & FINISHED_RECV)
+ ret = AVERROR_EOF;
+ else {
+ ret = av_fifo_write(st->fifo, data, 1);
+ if (ret >= 0)
+ pthread_cond_broadcast(&tq->cond);
+ }
+
+finish:
+ pthread_mutex_unlock(&tq->lock);
+
+ return ret;
+}
+
+static int receive_locked(ThreadQueue *tq, int *stream_idx,
+ void *data)
+{
+ unsigned int nb_finished = 0;
+
+ for (unsigned int i = 0; i < tq->nb_streams; i++) {
+ ThreadQueueStream *st = &tq->streams[i];
+
+ if (av_fifo_read(st->fifo, data, 1) >= 0) {
+ *stream_idx = i;
+ return 0;
+ }
+
+ if (st->finished & FINISHED_SEND) {
+ /* return EOF to the consumer at most once for each stream */
+ if (!(st->finished & FINISHED_RECV)) {
+ st->finished |= FINISHED_RECV;
+ *stream_idx = i;
+ return AVERROR_EOF;
+ }
+
+ nb_finished++;
+ }
+ }
+
+ return nb_finished == tq->nb_streams ? AVERROR_EOF : AVERROR(EAGAIN);
+}
+
+int tq_receive(ThreadQueue *tq, int *stream_idx, void *data)
+{
+ int ret;
+
+ *stream_idx = -1;
+
+ pthread_mutex_lock(&tq->lock);
+
+ while (1) {
+ ret = receive_locked(tq, stream_idx, data);
+ if (ret == AVERROR(EAGAIN)) {
+ pthread_cond_wait(&tq->cond, &tq->lock);
+ continue;
+ }
+
+ break;
+ }
+
+ if (ret == 0)
+ pthread_cond_broadcast(&tq->cond);
+
+ pthread_mutex_unlock(&tq->lock);
+
+ return ret;
+}
+
+void tq_send_finish(ThreadQueue *tq, unsigned int stream_idx)
+{
+ av_assert0(stream_idx < tq->nb_streams);
+
+ pthread_mutex_lock(&tq->lock);
+
+ /* mark the stream as send-finished;
+ * the next time the consumer thread tries to read this stream it will get
+ * and EOF and recv-finished flag will be set */
+ tq->streams[stream_idx].finished |= FINISHED_SEND;
+ pthread_cond_broadcast(&tq->cond);
+
+ pthread_mutex_unlock(&tq->lock);
+}
+
+void tq_receive_finish(ThreadQueue *tq, unsigned int stream_idx)
+{
+ av_assert0(stream_idx < tq->nb_streams);
+
+ pthread_mutex_lock(&tq->lock);
+
+ /* mark the stream as send/recv-finished;
+ * both send AND recvs for this stream will now return EOF */
+ tq->streams[stream_idx].finished |= FINISHED_SEND | FINISHED_RECV;
+ pthread_cond_broadcast(&tq->cond);
+
+ pthread_mutex_unlock(&tq->lock);
+}
diff --git a/fftools/thread_queue.h b/fftools/thread_queue.h
new file mode 100644
index 0000000000..aaf491fe3c
--- /dev/null
+++ b/fftools/thread_queue.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_THREAD_QUEUE_H
+#define FFTOOLS_THREAD_QUEUE_H
+
+#include <string.h>
+
+typedef struct ThreadQueue ThreadQueue;
+
+ThreadQueue *tq_alloc(unsigned int nb_streams,
+ size_t nb_elems, size_t elem_size,
+ void (*elem_free)(void *));
+void tq_free(ThreadQueue **tq);
+
+int tq_send(ThreadQueue *tq, unsigned int stream_idx, void *data);
+void tq_send_finish(ThreadQueue *tq, unsigned int stream_idx);
+
+int tq_receive(ThreadQueue *tq, int *stream_idx, void *data);
+void tq_receive_finish(ThreadQueue *tq, unsigned int stream_idx);
+
+#endif // FFTOOLS_THREAD_QUEUE_H
--
2.34.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] 81+ messages in thread
* [FFmpeg-devel] [PATCH 49/49] fftools/ffmpeg: move each muxer to a separate thread
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (47 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 48/49] fftools: add a multistream thread-safe queue Anton Khirnov
@ 2022-04-04 11:30 ` Anton Khirnov
2022-04-05 9:00 ` [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (2 subsequent siblings)
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-04 11:30 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg.c | 38 +++------
fftools/ffmpeg.h | 7 +-
fftools/ffmpeg_mux.c | 197 +++++++++++++++++++++++++++++++++++--------
3 files changed, 178 insertions(+), 64 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 9dfbc4216a..8ea27d3422 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1286,10 +1286,7 @@ static void finish_output_stream(OutputStream *ost)
OutputFile *of = output_files[ost->file_index];
ost->finished = ENCODER_FINISHED;
- if (ost->sq_idx_mux >= 0)
- sq_send(of->sq_mux, ost->sq_idx_mux, SQPKT(NULL));
- else
- ost->finished |= MUXER_FINISHED;
+ output_packet(of, ost->pkt, ost, 1);
}
/**
@@ -3421,9 +3418,8 @@ static int need_output(void)
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
- OutputFile *of = output_files[ost->file_index];
- if (ost->finished || of_finished(of))
+ if (ost->finished)
continue;
return 1;
@@ -4269,26 +4265,6 @@ static int transcode_step(void)
return reap_filters(0);
}
-static void flush_sync_queues_mux(void)
-{
- /* mark all queue inputs as done */
- for (int i = 0; i < nb_output_streams; i++) {
- OutputStream *ost = output_streams[i];
- OutputFile *of = output_files[ost->file_index];
- if (ost->sq_idx_mux >= 0)
- sq_send(of->sq_mux, ost->sq_idx_mux, SQPKT(NULL));
- }
-
- /* encode all packets remaining in the sync queues */
- for (int i = 0; i < nb_output_streams; i++) {
- OutputStream *ost = output_streams[i];
- OutputFile *of = output_files[ost->file_index];
-
- if (!(ost->finished & MUXER_FINISHED))
- output_packet(of, ost->pkt, ost, 1);
- }
-}
-
/*
* The following code is the main loop of the file converter
*/
@@ -4310,6 +4286,12 @@ static int transcode(void)
timer_start = av_gettime_relative();
+ for (i = 0; i < nb_output_files; i++) {
+ ret = of_thread_start(output_files[i]);
+ if (ret < 0)
+ goto fail;
+ }
+
if ((ret = init_input_threads()) < 0)
goto fail;
@@ -4346,7 +4328,9 @@ static int transcode(void)
}
}
flush_encoders();
- flush_sync_queues_mux();
+
+ for (i = 0; i < nb_output_files; i++)
+ of_thread_stop(output_files[i]);
term_exit();
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 407342462f..c4a5c2a0a2 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -583,6 +583,8 @@ typedef struct OutputFile {
const AVOutputFormat *format;
const char *url;
+ AVThreadMessageQueue *mux_queue;
+
SyncQueue *sq_encode;
SyncQueue *sq_mux;
@@ -697,11 +699,14 @@ int hwaccel_decode_init(AVCodecContext *avctx);
int of_muxer_init(OutputFile *of, AVFormatContext *fc,
AVDictionary *opts, int64_t limit_filesize);
+
+int of_thread_start(OutputFile *of);
+void of_thread_stop(OutputFile *of);
+
int of_write_trailer(OutputFile *of);
void of_close(OutputFile **pof);
int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof);
-int of_finished(OutputFile *of);
int64_t of_filesize(OutputFile *of);
AVChapter * const *
of_get_chapters(OutputFile *of, unsigned int *nb_chapters);
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 6ca9a51dd6..f99dd5ec3e 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -16,17 +16,20 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <stdatomic.h>
#include <stdio.h>
#include <string.h>
#include "ffmpeg.h"
#include "sync_queue.h"
+#include "thread_queue.h"
#include "libavutil/fifo.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"
#include "libavutil/mem.h"
#include "libavutil/timestamp.h"
+#include "libavutil/thread.h"
#include "libavcodec/packet.h"
@@ -46,18 +49,24 @@ typedef struct MuxStream {
/* dts of the last packet sent to the muxer, in the stream timebase
* used for making up missing dts values */
int64_t last_mux_dts;
+
+ /* data (a real or a flush packet) was received for this stream */
+ int got_data;
} MuxStream;
struct Muxer {
AVFormatContext *fc;
+ pthread_t thread;
+ ThreadQueue *tq;
+
MuxStream *streams;
AVDictionary *opts;
/* filesize limit expressed in bytes */
int64_t limit_filesize;
- int64_t final_filesize;
+ atomic_int_least64_t last_filesize;
int header_written;
};
@@ -221,13 +230,32 @@ static int queue_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
return 0;
}
+static int64_t filesize(AVIOContext *pb)
+{
+ int64_t ret = -1;
+
+ if (pb) {
+ ret = avio_size(pb);
+ if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too
+ ret = avio_tell(pb);
+ }
+
+ return ret;
+}
+
static int write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
{
MuxStream *ms = &of->mux->streams[ost->index];
AVFormatContext *s = of->mux->fc;
AVStream *st = ost->st;
+ int64_t fs;
int ret;
+ fs = filesize(s->pb);
+ atomic_store(&of->mux->last_filesize, fs);
+ if (fs >= of->mux->limit_filesize)
+ return AVERROR_EOF;
+
if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
@@ -333,8 +361,8 @@ static int check_write_header(OutputFile *of)
int ret, i;
for (i = 0; i < fc->nb_streams; i++) {
- OutputStream *ost = output_streams[of->ost_index + i];
- if (!ost->initialized)
+ MuxStream *ms = &of->mux->streams[i];
+ if (!ms->got_data)
return 0;
}
@@ -378,12 +406,15 @@ static int check_write_header(OutputFile *of)
return 0;
}
-int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
+static int sync_queue_process(OutputFile *of, OutputStream *ost, AVPacket *pkt)
{
+ Muxer *mux = of->mux;
+ MuxStream *ms = &mux->streams[ost->index];
int ret;
- if (!of->mux->header_written) {
- ret = check_write_header(of);
+ ms->got_data = 1;
+ if (!mux->header_written) {
+ ret = check_write_header(of);
if (ret < 0) {
av_packet_unref(pkt);
return ret;
@@ -391,34 +422,102 @@ int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
}
if (ost->sq_idx_mux >= 0) {
- ret = sq_send(of->sq_mux, ost->sq_idx_mux,
- SQPKT(eof ? NULL: pkt));
+ int ret = sq_send(of->sq_mux, ost->sq_idx_mux, SQPKT(pkt));
if (ret < 0) {
- av_packet_unref(pkt);
- if (ret == AVERROR_EOF) {
- ost->finished |= MUXER_FINISHED;
- return 0;
- } else
- return ret;
+ if (pkt)
+ av_packet_unref(pkt);
+ return ret;
}
while (1) {
+ pkt = av_packet_alloc();
+ if (!pkt)
+ // XXX
+ abort();
+
ret = sq_receive(of->sq_mux, -1, SQPKT(pkt));
- if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
- return 0;
- else if (ret < 0)
- return ret;
+ if (ret < 0) {
+ av_packet_free(&pkt);
+ return (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) ? 0 : ret;
+ }
ret = submit_packet(of, pkt, output_streams[of->ost_index + ret]);
+ av_packet_free(&pkt);
if (ret < 0)
return ret;
}
- } else if (!eof)
+ } else if (pkt)
return submit_packet(of, pkt, ost);
return 0;
}
+static void *muxer_thread(void *arg)
+{
+ OutputFile *of = arg;
+ Muxer *mux = of->mux;
+
+ while (1) {
+ OutputStream *ost;
+ AVPacket *pkt = NULL;
+ int stream_idx, ret;
+
+ ret = tq_receive(mux->tq, &stream_idx, &pkt);
+ if (stream_idx < 0) {
+ av_log(NULL, AV_LOG_DEBUG,
+ "All streams finished for output file #%d\n", of->index);
+ break;
+ }
+
+ ost = output_streams[of->ost_index + stream_idx];
+ ret = sync_queue_process(of, ost, ret < 0 ? NULL : pkt);
+ av_packet_free(&pkt);
+ if (ret == AVERROR_EOF)
+ tq_receive_finish(mux->tq, stream_idx);
+ else if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Error muxing a packet for output file #%d\n", of->index);
+ break;
+ }
+ }
+
+ for (unsigned int i = 0; i < mux->fc->nb_streams; i++) {
+ sync_queue_process(of, output_streams[of->ost_index], NULL);
+ tq_receive_finish(mux->tq, i);
+ }
+
+ av_log(NULL, AV_LOG_DEBUG, "Terminating muxer thread %d\n", of->index);
+
+ return NULL;
+}
+
+int of_submit_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int eof)
+{
+ AVPacket *pkt1;
+ int ret = 0;
+
+ if (eof) {
+ tq_send_finish(of->mux->tq, ost->index);
+ return 0;
+ }
+
+ pkt1 = av_packet_alloc();
+ if (!pkt1) {
+ av_packet_unref(pkt);
+ return AVERROR(ENOMEM);
+ }
+
+ av_packet_move_ref(pkt1, pkt);
+
+ ret = tq_send(of->mux->tq, ost->index, &pkt1);
+ if (ret < 0) {
+ av_packet_free(&pkt1);
+ ost->finished |= MUXER_FINISHED;
+ }
+
+ return ret == AVERROR_EOF ? 0 : ret;
+}
+
int of_write_trailer(OutputFile *of)
{
AVFormatContext *fc = of->mux->fc;
@@ -438,7 +537,7 @@ int of_write_trailer(OutputFile *of)
return ret;
}
- of->mux->final_filesize = of_filesize(of);
+ of->mux->last_filesize = filesize(fc->pb);
if (!(of->format->flags & AVFMT_NOFILE)) {
ret = avio_closep(&fc->pb);
@@ -487,6 +586,9 @@ static void mux_free(Muxer **pmux)
av_freep(&mux->streams);
av_dict_free(&mux->opts);
+ if (mux->tq) {
+ }
+
fc_close(&mux->fc);
av_freep(pmux);
@@ -558,30 +660,53 @@ fail:
return ret;
}
-int of_finished(OutputFile *of)
+int64_t of_filesize(OutputFile *of)
{
- return of_filesize(of) >= of->mux->limit_filesize;
+ return atomic_load(&of->mux->last_filesize);
}
-int64_t of_filesize(OutputFile *of)
+AVChapter * const *
+of_get_chapters(OutputFile *of, unsigned int *nb_chapters)
{
- AVIOContext *pb = of->mux->fc->pb;
- int64_t ret = -1;
+ *nb_chapters = of->mux->fc->nb_chapters;
+ return of->mux->fc->chapters;
+}
- if (of->mux->final_filesize)
- ret = of->mux->final_filesize;
- else if (pb) {
- ret = avio_size(pb);
- if (ret <= 0) // FIXME improve avio_size() so it works with non seekable output too
- ret = avio_tell(pb);
+static void pkt_free(void *pkt)
+{
+ av_packet_free((AVPacket**)&pkt);
+}
+
+int of_thread_start(OutputFile *of)
+{
+ Muxer *mux = of->mux;
+ int ret;
+
+ mux->tq = tq_alloc(mux->fc->nb_streams, 8, sizeof(AVPacket*),
+ pkt_free);
+ if (!mux->tq)
+ return AVERROR(ENOMEM);
+
+ ret = pthread_create(&mux->thread, NULL, muxer_thread, (void*)of);
+ if (ret) {
+ tq_free(&mux->tq);
+ return AVERROR(ret);
}
- return ret;
+ return 0;
}
-AVChapter * const *
-of_get_chapters(OutputFile *of, unsigned int *nb_chapters)
+void of_thread_stop(OutputFile *of)
{
- *nb_chapters = of->mux->fc->nb_chapters;
- return of->mux->fc->chapters;
+ Muxer *mux = of->mux;
+
+ if (!mux || !mux->tq)
+ return;
+
+ for (unsigned int i = 0; i < mux->fc->nb_streams; i++)
+ tq_send_finish(mux->tq, i);
+
+ pthread_join(mux->thread, NULL);
+
+ tq_free(&mux->tq);
}
--
2.34.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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (48 preceding siblings ...)
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 49/49] fftools/ffmpeg: move each muxer to a separate thread Anton Khirnov
@ 2022-04-05 9:00 ` Anton Khirnov
2022-04-05 19:15 ` Michael Niedermayer
2022-04-06 10:02 ` Anton Khirnov
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-05 9:00 UTC (permalink / raw)
To: FFmpeg development discussions and patches
The code can also be obtained from branch ffmpeg_mt/mux in my tree
git://git.khirnov.net/libav
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (49 preceding siblings ...)
2022-04-05 9:00 ` [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
@ 2022-04-05 19:15 ` Michael Niedermayer
2022-04-05 19:46 ` Anton Khirnov
2022-04-06 10:02 ` Anton Khirnov
51 siblings, 1 reply; 81+ messages in thread
From: Michael Niedermayer @ 2022-04-05 19:15 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1195 bytes --]
On Mon, Apr 04, 2022 at 01:29:48PM +0200, Anton Khirnov wrote:
> Hi,
> this WIP patchset is the first major part of my ongoing work to change
> ffmpeg.c architecture such that every
> - demuxer
> - decoder
> - filtergraph
> - encoder
> - muxer
> lives in its own thread. The advantages of doing this, beyond increased
> throughput, would be enforced separation between these components,
> making the code more local and easier to reason about.
>
> This set implements threading for muxers. My tentative plan is to
> continue with encoders and then filters. The patches still need some
> polishing, especially the last one. Two FATE tests do not yet pass, this
> will be fixed in later iterations.
>
> Meanwhile, comments on the overall approach are especially welcome.
I agree that cleanup/modularization to make the code easier to
understand is a good idea!
Didnt really look at the patchset yet.
I assume these changes have no real disadvantage ?
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Good people do not need laws to tell them to act responsibly, while bad
people will find a way around the laws. -- Plato
[-- 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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-05 19:15 ` Michael Niedermayer
@ 2022-04-05 19:46 ` Anton Khirnov
2022-04-05 21:05 ` Soft Works
2022-04-06 8:41 ` Anton Khirnov
0 siblings, 2 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-05 19:46 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2022-04-05 21:15:42)
> On Mon, Apr 04, 2022 at 01:29:48PM +0200, Anton Khirnov wrote:
> > Hi,
> > this WIP patchset is the first major part of my ongoing work to change
> > ffmpeg.c architecture such that every
> > - demuxer
> > - decoder
> > - filtergraph
> > - encoder
> > - muxer
> > lives in its own thread. The advantages of doing this, beyond increased
> > throughput, would be enforced separation between these components,
> > making the code more local and easier to reason about.
> >
> > This set implements threading for muxers. My tentative plan is to
> > continue with encoders and then filters. The patches still need some
> > polishing, especially the last one. Two FATE tests do not yet pass, this
> > will be fixed in later iterations.
> >
> > Meanwhile, comments on the overall approach are especially welcome.
>
> I agree that cleanup/modularization to make the code easier to
> understand is a good idea!
> Didnt really look at the patchset yet.
> I assume these changes have no real disadvantage ?
Playing the devil's advocate, I can think of the following:
1) ffmpeg.c will hard-depend on threads
2) execution flow will become non-deterministic
3) overall resource usage will likely go up due to inter-thread
synchronization and overhead related to new objects
4) large-scale code changes always carry a higher risk of regressions
re 1): should not be a problem for any serious system
re 2): I spent a lot of effort to ensure the _output_ remains
deterministic (it actually becomes more predictable for some
cases)
re 3): I expect the impact to be small and negligible, respectively, but
would have to be measured once the conversion is complete
re 4): the only way to avoid this completely would be to stop
development
Overall, I believe the advantages far outweigh the potential negatives.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-05 19:46 ` Anton Khirnov
@ 2022-04-05 21:05 ` Soft Works
2022-04-05 21:18 ` Paul B Mahol
2022-04-06 8:41 ` Anton Khirnov
1 sibling, 1 reply; 81+ messages in thread
From: Soft Works @ 2022-04-05 21:05 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Anton Khirnov
> Sent: Tuesday, April 5, 2022 9:46 PM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> Quoting Michael Niedermayer (2022-04-05 21:15:42)
> > On Mon, Apr 04, 2022 at 01:29:48PM +0200, Anton Khirnov wrote:
> > > Hi,
> > > this WIP patchset is the first major part of my ongoing work to
> change
> > > ffmpeg.c architecture such that every
> > > - demuxer
> > > - decoder
> > > - filtergraph
> > > - encoder
> > > - muxer
> > > lives in its own thread. The advantages of doing this, beyond
> increased
> > > throughput, would be enforced separation between these components,
> > > making the code more local and easier to reason about.
> > >
> > > This set implements threading for muxers. My tentative plan is to
> > > continue with encoders and then filters. The patches still need
> some
> > > polishing, especially the last one. Two FATE tests do not yet
> pass, this
> > > will be fixed in later iterations.
> > >
> > > Meanwhile, comments on the overall approach are especially
> welcome.
> >
> > I agree that cleanup/modularization to make the code easier to
> > understand is a good idea!
> > Didnt really look at the patchset yet.
> > I assume these changes have no real disadvantage ?
>
> Playing the devil's advocate, I can think of the following:
> 1) ffmpeg.c will hard-depend on threads
> 2) execution flow will become non-deterministic
> 3) overall resource usage will likely go up due to inter-thread
> synchronization and overhead related to new objects
> 4) large-scale code changes always carry a higher risk of regressions
>
> re 1): should not be a problem for any serious system
> re 2): I spent a lot of effort to ensure the _output_ remains
> deterministic (it actually becomes more predictable for some
> cases)
> re 3): I expect the impact to be small and negligible, respectively,
> but
> would have to be measured once the conversion is complete
> re 4): the only way to avoid this completely would be to stop
> development
>
> Overall, I believe the advantages far outweigh the potential
> negatives.
Hi,
do I understand it right that there won't be a single-thread
operation mode that replicates/corresponds the current behavior?
Not that I wouldn't welcome the performance improvements, but one
concern I have is debugging filtergraph operations. This is already
a pretty tedious task in itself, because many relevant decisions
are made in sub-sub-sub-sub-sub-functions, spread over many places.
When adding an additional - not even deterministic - part to the
game, it won't make things easier. It could even create situations
where it could no longer be possible to replicate an error in a
debugger - in case the existence of a debugger would cause a variance
within the constraints of the non-determinism range.
From another point of view, this is a change, so fundamental like
ffmpeg(.c) hasn't seen in a long time.
I would at least suppose that this could cause issues at many ends,
and from experience, there may be additional ends where it's rather
unexpected to have effects.
In that context, I think that doing a change of such a wide scope
in an irreversible way like this, would impose quite a burden on
many other developers, because sooner or later, other developers
will run into situations where something is no longer working like
before and you'll regularly wonder whether this might be a consequence
of ffmpeg.c threading change or caused by other changes.
But then, you won't be able anymore to bisect on that suspicion,
because the threading change can't be reverted and (as long as it's
not shortly after the change) there might have been too many other
changes to easily port them back to a state before the threading
change.
I wonder whether this couldn't be done in a way that the current
behavior can be preserved and activated by option?
Wouldn't it be possible to follow an approach like this:
- Assuming the code would be fine and it would mark the desired
end result
- Put it aside and start over from the current HEAD
- Iteratively morph the code current code in a (possibly) long
sequence of refactoring operations where every single one
(and hence in sum) are semantically neutral - until the code
is turned more and more into what has already been developed
- eventually, only few differences will be left, and these can
be made switchable by an option - as a result, both - old and
new operation modes would be available.
I don't know whether there's a name to this approach, probably
there is, yet I never cared. Way more important is that I always
had good results following this methodology.
The funny thing about it is, that when you have a reliable tooling
for refactoring, you can even stop thinking (well, sort of..)
while transforming the code. Also, when you can't imagine how
the end result would look like or wonder whether it would
work out at all, it's fun to watch the morphing (if you're
doing it no-brain-wise)
softworkz
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-05 21:05 ` Soft Works
@ 2022-04-05 21:18 ` Paul B Mahol
2022-04-05 21:19 ` Soft Works
0 siblings, 1 reply; 81+ messages in thread
From: Paul B Mahol @ 2022-04-05 21:18 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, Apr 5, 2022 at 11:06 PM Soft Works <softworkz@hotmail.com> wrote:
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Anton Khirnov
> > Sent: Tuesday, April 5, 2022 9:46 PM
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > architecture
> >
> > Quoting Michael Niedermayer (2022-04-05 21:15:42)
> > > On Mon, Apr 04, 2022 at 01:29:48PM +0200, Anton Khirnov wrote:
> > > > Hi,
> > > > this WIP patchset is the first major part of my ongoing work to
> > change
> > > > ffmpeg.c architecture such that every
> > > > - demuxer
> > > > - decoder
> > > > - filtergraph
> > > > - encoder
> > > > - muxer
> > > > lives in its own thread. The advantages of doing this, beyond
> > increased
> > > > throughput, would be enforced separation between these components,
> > > > making the code more local and easier to reason about.
> > > >
> > > > This set implements threading for muxers. My tentative plan is to
> > > > continue with encoders and then filters. The patches still need
> > some
> > > > polishing, especially the last one. Two FATE tests do not yet
> > pass, this
> > > > will be fixed in later iterations.
> > > >
> > > > Meanwhile, comments on the overall approach are especially
> > welcome.
> > >
> > > I agree that cleanup/modularization to make the code easier to
> > > understand is a good idea!
> > > Didnt really look at the patchset yet.
> > > I assume these changes have no real disadvantage ?
> >
> > Playing the devil's advocate, I can think of the following:
> > 1) ffmpeg.c will hard-depend on threads
> > 2) execution flow will become non-deterministic
> > 3) overall resource usage will likely go up due to inter-thread
> > synchronization and overhead related to new objects
> > 4) large-scale code changes always carry a higher risk of regressions
> >
> > re 1): should not be a problem for any serious system
> > re 2): I spent a lot of effort to ensure the _output_ remains
> > deterministic (it actually becomes more predictable for some
> > cases)
> > re 3): I expect the impact to be small and negligible, respectively,
> > but
> > would have to be measured once the conversion is complete
> > re 4): the only way to avoid this completely would be to stop
> > development
> >
> > Overall, I believe the advantages far outweigh the potential
> > negatives.
>
> Hi,
>
> do I understand it right that there won't be a single-thread
> operation mode that replicates/corresponds the current behavior?
>
> Not that I wouldn't welcome the performance improvements, but one
> concern I have is debugging filtergraph operations. This is already
> a pretty tedious task in itself, because many relevant decisions
> are made in sub-sub-sub-sub-sub-functions, spread over many places.
> When adding an additional - not even deterministic - part to the
> game, it won't make things easier. It could even create situations
> where it could no longer be possible to replicate an error in a
> debugger - in case the existence of a debugger would cause a variance
> within the constraints of the non-determinism range.
>
>
Can you elaborate more?, otherwise this is PEBKAC.
> From another point of view, this is a change, so fundamental like
> ffmpeg(.c) hasn't seen in a long time.
> I would at least suppose that this could cause issues at many ends,
> and from experience, there may be additional ends where it's rather
> unexpected to have effects.
>
> In that context, I think that doing a change of such a wide scope
> in an irreversible way like this, would impose quite a burden on
> many other developers, because sooner or later, other developers
> will run into situations where something is no longer working like
> before and you'll regularly wonder whether this might be a consequence
> of ffmpeg.c threading change or caused by other changes.
> But then, you won't be able anymore to bisect on that suspicion,
> because the threading change can't be reverted and (as long as it's
> not shortly after the change) there might have been too many other
> changes to easily port them back to a state before the threading
> change.
>
> I wonder whether this couldn't be done in a way that the current
> behavior can be preserved and activated by option?
>
> Wouldn't it be possible to follow an approach like this:
>
> - Assuming the code would be fine and it would mark the desired
> end result
> - Put it aside and start over from the current HEAD
> - Iteratively morph the code current code in a (possibly) long
> sequence of refactoring operations where every single one
> (and hence in sum) are semantically neutral - until the code
> is turned more and more into what has already been developed
> - eventually, only few differences will be left, and these can
> be made switchable by an option - as a result, both - old and
> new operation modes would be available.
>
> I don't know whether there's a name to this approach, probably
> there is, yet I never cared. Way more important is that I always
> had good results following this methodology.
> The funny thing about it is, that when you have a reliable tooling
> for refactoring, you can even stop thinking (well, sort of..)
> while transforming the code. Also, when you can't imagine how
> the end result would look like or wonder whether it would
> work out at all, it's fun to watch the morphing (if you're
> doing it no-brain-wise)
>
> softworkz
>
>
>
>
>
>
>
>
> _______________________________________________
> 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".
>
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-05 21:18 ` Paul B Mahol
@ 2022-04-05 21:19 ` Soft Works
2022-04-06 11:17 ` Paul B Mahol
0 siblings, 1 reply; 81+ messages in thread
From: Soft Works @ 2022-04-05 21:19 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Paul
> B Mahol
> Sent: Tuesday, April 5, 2022 11:19 PM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> On Tue, Apr 5, 2022 at 11:06 PM Soft Works <softworkz@hotmail.com>
> wrote:
>
> >
> >
> > > -----Original Message-----
> > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > > Anton Khirnov
> > > Sent: Tuesday, April 5, 2022 9:46 PM
> > > To: FFmpeg development discussions and patches <ffmpeg-
> > > devel@ffmpeg.org>
> > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > architecture
> > >
> > > Quoting Michael Niedermayer (2022-04-05 21:15:42)
> > > > On Mon, Apr 04, 2022 at 01:29:48PM +0200, Anton Khirnov wrote:
> > > > > Hi,
> > > > > this WIP patchset is the first major part of my ongoing work
> to
> > > change
> > > > > ffmpeg.c architecture such that every
> > > > > - demuxer
> > > > > - decoder
> > > > > - filtergraph
> > > > > - encoder
> > > > > - muxer
> > > > > lives in its own thread. The advantages of doing this, beyond
> > > increased
> > > > > throughput, would be enforced separation between these
> components,
> > > > > making the code more local and easier to reason about.
> > > > >
> > > > > This set implements threading for muxers. My tentative plan is
> to
> > > > > continue with encoders and then filters. The patches still
> need
> > > some
> > > > > polishing, especially the last one. Two FATE tests do not yet
> > > pass, this
> > > > > will be fixed in later iterations.
> > > > >
> > > > > Meanwhile, comments on the overall approach are especially
> > > welcome.
> > > >
> > > > I agree that cleanup/modularization to make the code easier to
> > > > understand is a good idea!
> > > > Didnt really look at the patchset yet.
> > > > I assume these changes have no real disadvantage ?
> > >
> > > Playing the devil's advocate, I can think of the following:
> > > 1) ffmpeg.c will hard-depend on threads
> > > 2) execution flow will become non-deterministic
> > > 3) overall resource usage will likely go up due to inter-thread
> > > synchronization and overhead related to new objects
> > > 4) large-scale code changes always carry a higher risk of
> regressions
> > >
> > > re 1): should not be a problem for any serious system
> > > re 2): I spent a lot of effort to ensure the _output_ remains
> > > deterministic (it actually becomes more predictable for
> some
> > > cases)
> > > re 3): I expect the impact to be small and negligible,
> respectively,
> > > but
> > > would have to be measured once the conversion is complete
> > > re 4): the only way to avoid this completely would be to stop
> > > development
> > >
> > > Overall, I believe the advantages far outweigh the potential
> > > negatives.
> >
> > Hi,
> >
> > do I understand it right that there won't be a single-thread
> > operation mode that replicates/corresponds the current behavior?
> >
> > Not that I wouldn't welcome the performance improvements, but one
> > concern I have is debugging filtergraph operations. This is already
> > a pretty tedious task in itself, because many relevant decisions
> > are made in sub-sub-sub-sub-sub-functions, spread over many places.
> > When adding an additional - not even deterministic - part to the
> > game, it won't make things easier. It could even create situations
> > where it could no longer be possible to replicate an error in a
> > debugger - in case the existence of a debugger would cause a
> variance
> > within the constraints of the non-determinism range.
> >
> >
> Can you elaborate more?, otherwise this is PEBKAC.
You mean like WKOFAIT?
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-05 19:46 ` Anton Khirnov
2022-04-05 21:05 ` Soft Works
@ 2022-04-06 8:41 ` Anton Khirnov
2022-04-06 16:29 ` Soft Works
2022-04-07 8:32 ` Anton Khirnov
1 sibling, 2 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-06 8:41 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Soft Works (2022-04-05 23:05:57)
> do I understand it right that there won't be a single-thread
> operation mode that replicates/corresponds the current behavior?
Correct, maintaining a single-threaded mode would require massive
amounts of extra effort for questionable gain.
>
> Not that I wouldn't welcome the performance improvements, but one
> concern I have is debugging filtergraph operations. This is already
> a pretty tedious task in itself, because many relevant decisions
> are made in sub-sub-sub-sub-sub-functions, spread over many places.
> When adding an additional - not even deterministic - part to the
> game, it won't make things easier. It could even create situations
> where it could no longer be possible to replicate an error in a
> debugger - in case the existence of a debugger would cause a variance
> within the constraints of the non-determinism range.
I don't think debugging filtegraph internals will get significantly
harders, it might even become slightly easier because you will have a
thread entirely dedicated to filtering, with nothing else going on in
it.
>
> From another point of view, this is a change, so fundamental like
> ffmpeg(.c) hasn't seen in a long time.
> I would at least suppose that this could cause issues at many ends,
> and from experience, there may be additional ends where it's rather
> unexpected to have effects.
>
> In that context, I think that doing a change of such a wide scope
> in an irreversible way like this, would impose quite a burden on
> many other developers, because sooner or later, other developers
> will run into situations where something is no longer working like
> before and you'll regularly wonder whether this might be a consequence
> of ffmpeg.c threading change or caused by other changes.
> But then, you won't be able anymore to bisect on that suspicion,
> because the threading change can't be reverted and (as long as it's
> not shortly after the change) there might have been too many other
> changes to easily port them back to a state before the threading
> change.
>
> I wonder whether this couldn't be done in a way that the current
> behavior can be preserved and activated by option?
>
> Wouldn't it be possible to follow an approach like this:
>
> - Assuming the code would be fine and it would mark the desired
> end result
> - Put it aside and start over from the current HEAD
> - Iteratively morph the code current code in a (possibly) long
> sequence of refactoring operations where every single one
> (and hence in sum) are semantically neutral - until the code
> is turned more and more into what has already been developed
> - eventually, only few differences will be left, and these can
> be made switchable by an option - as a result, both - old and
> new operation modes would be available.
If I understand correctly what you're suggesting then I don't believe
this approach is feasible. The goal is not "add threading to improve
performance", keeping everything else intact as much as possible. The
goal is "improve architecture to make the code easier to
understand/maintain/extend", threads are a means towards that goal. The
fact that this should also improve throughput is more of a nice side
effect than anything else.
This patchset already changes behaviour in certain cases, making the
output more predictable and consistent. Reordering it somehow to
separate "semantically neutral" patches would require vast amounts of
extra work. Note that progressing at all without obviously breaking
anything is already quite hard --- I've been working on this since
November and this is just the first step. I really do not want to make
my work 10x harder for the vague benefit of maybe making some debugging
slightly easier.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
` (50 preceding siblings ...)
2022-04-05 19:15 ` Michael Niedermayer
@ 2022-04-06 10:02 ` Anton Khirnov
51 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-06 10:02 UTC (permalink / raw)
To: FFmpeg development discussions and patches
To clarify futher, the [RFC] tag applies mainly to patches 34-49/49,
which will certainly require some changes, possibly substatial ones.
Previous patches should IMO be acceptable for master as they are. I
would appreciate reviews for those, so I can push them sooner rather
than later and thus reduce the number of future rebase conflicts.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-05 21:19 ` Soft Works
@ 2022-04-06 11:17 ` Paul B Mahol
2022-04-06 15:46 ` Soft Works
0 siblings, 1 reply; 81+ messages in thread
From: Paul B Mahol @ 2022-04-06 11:17 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Tue, Apr 5, 2022 at 11:20 PM Soft Works <softworkz@hotmail.com> wrote:
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Paul
> > B Mahol
> > Sent: Tuesday, April 5, 2022 11:19 PM
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > architecture
> >
> > On Tue, Apr 5, 2022 at 11:06 PM Soft Works <softworkz@hotmail.com>
> > wrote:
> >
> > >
> > >
> > > > -----Original Message-----
> > > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > > > Anton Khirnov
> > > > Sent: Tuesday, April 5, 2022 9:46 PM
> > > > To: FFmpeg development discussions and patches <ffmpeg-
> > > > devel@ffmpeg.org>
> > > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > > architecture
> > > >
> > > > Quoting Michael Niedermayer (2022-04-05 21:15:42)
> > > > > On Mon, Apr 04, 2022 at 01:29:48PM +0200, Anton Khirnov wrote:
> > > > > > Hi,
> > > > > > this WIP patchset is the first major part of my ongoing work
> > to
> > > > change
> > > > > > ffmpeg.c architecture such that every
> > > > > > - demuxer
> > > > > > - decoder
> > > > > > - filtergraph
> > > > > > - encoder
> > > > > > - muxer
> > > > > > lives in its own thread. The advantages of doing this, beyond
> > > > increased
> > > > > > throughput, would be enforced separation between these
> > components,
> > > > > > making the code more local and easier to reason about.
> > > > > >
> > > > > > This set implements threading for muxers. My tentative plan is
> > to
> > > > > > continue with encoders and then filters. The patches still
> > need
> > > > some
> > > > > > polishing, especially the last one. Two FATE tests do not yet
> > > > pass, this
> > > > > > will be fixed in later iterations.
> > > > > >
> > > > > > Meanwhile, comments on the overall approach are especially
> > > > welcome.
> > > > >
> > > > > I agree that cleanup/modularization to make the code easier to
> > > > > understand is a good idea!
> > > > > Didnt really look at the patchset yet.
> > > > > I assume these changes have no real disadvantage ?
> > > >
> > > > Playing the devil's advocate, I can think of the following:
> > > > 1) ffmpeg.c will hard-depend on threads
> > > > 2) execution flow will become non-deterministic
> > > > 3) overall resource usage will likely go up due to inter-thread
> > > > synchronization and overhead related to new objects
> > > > 4) large-scale code changes always carry a higher risk of
> > regressions
> > > >
> > > > re 1): should not be a problem for any serious system
> > > > re 2): I spent a lot of effort to ensure the _output_ remains
> > > > deterministic (it actually becomes more predictable for
> > some
> > > > cases)
> > > > re 3): I expect the impact to be small and negligible,
> > respectively,
> > > > but
> > > > would have to be measured once the conversion is complete
> > > > re 4): the only way to avoid this completely would be to stop
> > > > development
> > > >
> > > > Overall, I believe the advantages far outweigh the potential
> > > > negatives.
> > >
> > > Hi,
> > >
> > > do I understand it right that there won't be a single-thread
> > > operation mode that replicates/corresponds the current behavior?
> > >
> > > Not that I wouldn't welcome the performance improvements, but one
> > > concern I have is debugging filtergraph operations. This is already
> > > a pretty tedious task in itself, because many relevant decisions
> > > are made in sub-sub-sub-sub-sub-functions, spread over many places.
> > > When adding an additional - not even deterministic - part to the
> > > game, it won't make things easier. It could even create situations
> > > where it could no longer be possible to replicate an error in a
> > > debugger - in case the existence of a debugger would cause a
> > variance
> > > within the constraints of the non-determinism range.
> > >
> > >
> > Can you elaborate more?, otherwise this is PEBKAC.
>
> You mean like WKOFAIT?
>
You failed to provide useful facts to backup your claims above.
So I can not take your inputs seriously at this time.
_______________________________________________
> 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".
>
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [PATCH 03/49] fftools/ffmpeg: stop using OutputStream.frame_number for streamcopy
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 03/49] fftools/ffmpeg: stop using OutputStream.frame_number for streamcopy Anton Khirnov
@ 2022-04-06 11:20 ` James Almer
0 siblings, 0 replies; 81+ messages in thread
From: James Almer @ 2022-04-06 11:20 UTC (permalink / raw)
To: ffmpeg-devel
On 4/4/2022 8:29 AM, Anton Khirnov wrote:
> This field is currently used by checks
> - skipping packets before the first keyframe
> - skipping packets before start time
> to test whether any packets have been output already. But since
> frame_number is incremented after the bitstream filters are applied
> (which may involve delay), this use is incorrect. The keyframe check
> works around this by adding an extra flag, the start-time check does
> not.
>
> Simplify both checks by replacing the seen_kf flag with a flag tracking
> whether any packets have been output by do_streamcopy().
> ---
> fftools/ffmpeg.c | 10 +++++-----
> fftools/ffmpeg.h | 2 +-
> 2 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
> index 13be32f0cf..29b01f9d93 100644
> --- a/fftools/ffmpeg.c
> +++ b/fftools/ffmpeg.c
> @@ -894,8 +894,6 @@ static void output_packet(OutputFile *of, AVPacket *pkt,
>
> /* apply the output bitstream filters */
> if (ost->bsf_ctx) {
> - if (pkt->flags & AV_PKT_FLAG_KEY)
> - ost->seen_kf = 1;
> ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt);
> if (ret < 0)
> goto finish;
> @@ -2043,11 +2041,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
> return;
> }
>
> - if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
> - !ost->copy_initial_nonkeyframes && !ost->seen_kf)
> + if (!ost->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) &&
> + !ost->copy_initial_nonkeyframes)
> return;
>
> - if (!ost->frame_number && !ost->copy_prior_start) {
> + if (!ost->streamcopy_started && !ost->copy_prior_start) {
> int64_t comp_start = start_time;
> if (copy_ts && f->start_time != AV_NOPTS_VALUE)
> comp_start = FFMAX(start_time, f->start_time + f->ts_offset);
> @@ -2101,6 +2099,8 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
> ost->sync_opts += opkt->duration;
>
> output_packet(of, opkt, ost, 0);
> +
> + ost->streamcopy_started = 1;
> }
>
> int guess_input_channel_layout(InputStream *ist)
> diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
> index 1e14bf9fa9..04369df139 100644
> --- a/fftools/ffmpeg.h
> +++ b/fftools/ffmpeg.h
> @@ -536,7 +536,7 @@ typedef struct OutputStream {
> int inputs_done;
>
> const char *attachment_filename;
> - int seen_kf;
> + int streamcopy_started;
> int copy_initial_nonkeyframes;
> int copy_prior_start;
> char *disposition;
fate-ffmpeg-setts-bsf, which depends on this code, still passes, so lgtm.
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [PATCH 02/49] fftools/ffmpeg: move a comment to a more appropriate place
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 02/49] fftools/ffmpeg: move a comment to a more appropriate place Anton Khirnov
@ 2022-04-06 11:20 ` James Almer
0 siblings, 0 replies; 81+ messages in thread
From: James Almer @ 2022-04-06 11:20 UTC (permalink / raw)
To: ffmpeg-devel
On 4/4/2022 8:29 AM, Anton Khirnov wrote:
> ---
> fftools/ffmpeg.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
> index afa1b012a6..13be32f0cf 100644
> --- a/fftools/ffmpeg.c
> +++ b/fftools/ffmpeg.c
> @@ -1238,6 +1238,11 @@ static void do_video_out(OutputFile *of,
> }
> }
>
> + /*
> + * For video, number of frames in == number of packets out.
> + * But there may be reordering, so we can't throw away frames on encoder
> + * flush, we need to limit them here, before they go into encoder.
> + */
> nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
> nb0_frames = FFMIN(nb0_frames, nb_frames);
>
> @@ -1392,11 +1397,6 @@ static void do_video_out(OutputFile *of,
> }
> }
> ost->sync_opts++;
> - /*
> - * For video, number of frames in == number of packets out.
> - * But there may be reordering, so we can't throw away frames on encoder
> - * flush, we need to limit them here, before they go into encoder.
> - */
> ost->frame_number++;
>
> if (vstats_filename && frame_size)
Patches 1 and 2 are trivial and lgtm.
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [PATCH 09/49] fftools/ffmpeg: store output format separately from the muxer context
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 09/49] fftools/ffmpeg: store output format separately from the muxer context Anton Khirnov
@ 2022-04-06 12:00 ` James Almer
2022-04-13 10:18 ` Anton Khirnov
0 siblings, 1 reply; 81+ messages in thread
From: James Almer @ 2022-04-06 12:00 UTC (permalink / raw)
To: ffmpeg-devel
On 4/4/2022 8:29 AM, Anton Khirnov wrote:
> Allows accessing it without going through the muxer context. This will
> be useful in the following commits, where the muxer context will be
> hidden.
> ---
> fftools/ffmpeg.c | 18 ++++++++++--------
> fftools/ffmpeg.h | 2 ++
> fftools/ffmpeg_opt.c | 1 +
> 3 files changed, 13 insertions(+), 8 deletions(-)
Patches 4 to 9 look ok.
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-06 11:17 ` Paul B Mahol
@ 2022-04-06 15:46 ` Soft Works
2022-04-06 15:54 ` Matt Zagrabelny
0 siblings, 1 reply; 81+ messages in thread
From: Soft Works @ 2022-04-06 15:46 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Paul
> B Mahol
> Sent: Wednesday, April 6, 2022 1:17 PM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> On Tue, Apr 5, 2022 at 11:20 PM Soft Works <softworkz@hotmail.com>
> wrote:
>
> >
> >
> > > -----Original Message-----
> > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Paul
> > > B Mahol
> > > Sent: Tuesday, April 5, 2022 11:19 PM
> > > To: FFmpeg development discussions and patches <ffmpeg-
> > > devel@ffmpeg.org>
> > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > architecture
> > >
> > > On Tue, Apr 5, 2022 at 11:06 PM Soft Works <softworkz@hotmail.com>
> > > wrote:
> > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf
> Of
> > > > > Anton Khirnov
> > > > > Sent: Tuesday, April 5, 2022 9:46 PM
> > > > > To: FFmpeg development discussions and patches <ffmpeg-
> > > > > devel@ffmpeg.org>
> > > > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a
> threaded
> > > > > architecture
> > > > >
> > > > > Quoting Michael Niedermayer (2022-04-05 21:15:42)
> > > > > > On Mon, Apr 04, 2022 at 01:29:48PM +0200, Anton Khirnov
> wrote:
> > > > > > > Hi,
> > > > > > > this WIP patchset is the first major part of my ongoing
> work
> > > to
> > > > > change
> > > > > > > ffmpeg.c architecture such that every
> > > > > > > - demuxer
> > > > > > > - decoder
> > > > > > > - filtergraph
> > > > > > > - encoder
> > > > > > > - muxer
> > > > > > > lives in its own thread. The advantages of doing this,
> beyond
> > > > > increased
> > > > > > > throughput, would be enforced separation between these
> > > components,
> > > > > > > making the code more local and easier to reason about.
> > > > > > >
> > > > > > > This set implements threading for muxers. My tentative
> plan is
> > > to
> > > > > > > continue with encoders and then filters. The patches still
> > > need
> > > > > some
> > > > > > > polishing, especially the last one. Two FATE tests do not
> yet
> > > > > pass, this
> > > > > > > will be fixed in later iterations.
> > > > > > >
> > > > > > > Meanwhile, comments on the overall approach are especially
> > > > > welcome.
> > > > > >
> > > > > > I agree that cleanup/modularization to make the code easier
> to
> > > > > > understand is a good idea!
> > > > > > Didnt really look at the patchset yet.
> > > > > > I assume these changes have no real disadvantage ?
> > > > >
> > > > > Playing the devil's advocate, I can think of the following:
> > > > > 1) ffmpeg.c will hard-depend on threads
> > > > > 2) execution flow will become non-deterministic
> > > > > 3) overall resource usage will likely go up due to inter-
> thread
> > > > > synchronization and overhead related to new objects
> > > > > 4) large-scale code changes always carry a higher risk of
> > > regressions
> > > > >
> > > > > re 1): should not be a problem for any serious system
> > > > > re 2): I spent a lot of effort to ensure the _output_ remains
> > > > > deterministic (it actually becomes more predictable for
> > > some
> > > > > cases)
> > > > > re 3): I expect the impact to be small and negligible,
> > > respectively,
> > > > > but
> > > > > would have to be measured once the conversion is
> complete
> > > > > re 4): the only way to avoid this completely would be to stop
> > > > > development
> > > > >
> > > > > Overall, I believe the advantages far outweigh the potential
> > > > > negatives.
> > > >
> > > > Hi,
> > > >
> > > > do I understand it right that there won't be a single-thread
> > > > operation mode that replicates/corresponds the current behavior?
> > > >
> > > > Not that I wouldn't welcome the performance improvements, but
> one
> > > > concern I have is debugging filtergraph operations. This is
> already
> > > > a pretty tedious task in itself, because many relevant decisions
> > > > are made in sub-sub-sub-sub-sub-functions, spread over many
> places.
> > > > When adding an additional - not even deterministic - part to the
> > > > game, it won't make things easier. It could even create
> situations
> > > > where it could no longer be possible to replicate an error in a
> > > > debugger - in case the existence of a debugger would cause a
> > > variance
> > > > within the constraints of the non-determinism range.
> > > >
> > > >
> > > Can you elaborate more?, otherwise this is PEBKAC.
> >
> > You mean like WKOFAIT?
> >
>
> You failed to provide useful facts to backup your claims above.
>
> So I can not take your inputs seriously at this time.
I was just wondering What Kind Of F..funny Acronym Is That?
(knowing you won't find it, after being too lazy to lookup yours..)
Getting serious again - I will answer your question, but please
give me some time until I'm back to work in this area, then I'll
explain in detail and provide the callstacks that I meant.
Thanks,
softworkz
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-06 15:46 ` Soft Works
@ 2022-04-06 15:54 ` Matt Zagrabelny
0 siblings, 0 replies; 81+ messages in thread
From: Matt Zagrabelny @ 2022-04-06 15:54 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> > > > Can you elaborate more?, otherwise this is PEBKAC.
> > >
> > > You mean like WKOFAIT?
> > >
> >
> > You failed to provide useful facts to backup your claims above.
> >
> > So I can not take your inputs seriously at this time.
>
> I was just wondering What Kind Of F..funny Acronym Is That?
>
Ahh. Thanks for shedding light on that. I was curious.
PEBKAC = Problem Exists Between Keyboard And Chair.
Maybe it is a more IT support related acronym.
Cheers!
-m
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-06 8:41 ` Anton Khirnov
@ 2022-04-06 16:29 ` Soft Works
2022-04-06 17:38 ` Paul B Mahol
2022-04-07 8:32 ` Anton Khirnov
1 sibling, 1 reply; 81+ messages in thread
From: Soft Works @ 2022-04-06 16:29 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Anton Khirnov
> Sent: Wednesday, April 6, 2022 10:42 AM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> Quoting Soft Works (2022-04-05 23:05:57)
> > do I understand it right that there won't be a single-thread
> > operation mode that replicates/corresponds the current behavior?
>
> Correct, maintaining a single-threaded mode would require massive
> amounts of extra effort for questionable gain.
The gain is not to be seen in having an alternate run-mode in
longer-term term perspective. It is about avoiding a single
point-of-no-return change which may have fundamental consequences
and impose debt on other developers when it would no longer be possible
to compare to the previous mode of operation.
> If I understand correctly what you're suggesting then I don't believe
> this approach is feasible. The goal is not "add threading to improve
> performance", keeping everything else intact as much as possible. The
> goal is "improve architecture to make the code easier to
> understand/maintain/extend", threads are a means towards that goal.
> The
> fact that this should also improve throughput is more of a nice side
> effect than anything else.
>
> This patchset already changes behaviour in certain cases, making the
> output more predictable and consistent. Reordering it somehow to
> separate "semantically neutral" patches would require vast amounts of
> extra work. Note that progressing at all without obviously breaking
> anything is already quite hard --- I've been working on this since
> November and this is just the first step. I really do not want to make
> my work 10x harder for the vague benefit of maybe making some
> debugging
> slightly easier.
I understand that, but I'm not talking about re-development. Let me try
explain it in a different way:
What I mean is to go through your patches one after another but apply
only those parts that do not affect the current single-threaded execution
flow - effectively separating out those parts. Then, you go through
the remaining changes and make corresponding "similar" changes to the
working code, making it get as close as possible to your original code.
It's an iterative process. At the end you should have just a small set
of changes left which make up the difference between the working code
(still following the traditional flow) and the threaded execution flow.
That last set of differences can be finally applied in a way that it
can be activated/deactivated by an option.
When you have been working on this for so long already, then this would
make up just a small part of the total work.
Regards,
softworkz
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-06 16:29 ` Soft Works
@ 2022-04-06 17:38 ` Paul B Mahol
2022-04-06 17:56 ` Kieran Kunhya
0 siblings, 1 reply; 81+ messages in thread
From: Paul B Mahol @ 2022-04-06 17:38 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Wed, Apr 6, 2022 at 6:30 PM Soft Works <softworkz@hotmail.com> wrote:
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Anton Khirnov
> > Sent: Wednesday, April 6, 2022 10:42 AM
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > architecture
> >
> > Quoting Soft Works (2022-04-05 23:05:57)
> > > do I understand it right that there won't be a single-thread
> > > operation mode that replicates/corresponds the current behavior?
> >
> > Correct, maintaining a single-threaded mode would require massive
> > amounts of extra effort for questionable gain.
>
> The gain is not to be seen in having an alternate run-mode in
> longer-term term perspective. It is about avoiding a single
> point-of-no-return change which may have fundamental consequences
> and impose debt on other developers when it would no longer be possible
> to compare to the previous mode of operation.
>
> > If I understand correctly what you're suggesting then I don't believe
> > this approach is feasible. The goal is not "add threading to improve
> > performance", keeping everything else intact as much as possible. The
> > goal is "improve architecture to make the code easier to
> > understand/maintain/extend", threads are a means towards that goal.
> > The
> > fact that this should also improve throughput is more of a nice side
> > effect than anything else.
> >
> > This patchset already changes behaviour in certain cases, making the
> > output more predictable and consistent. Reordering it somehow to
> > separate "semantically neutral" patches would require vast amounts of
> > extra work. Note that progressing at all without obviously breaking
> > anything is already quite hard --- I've been working on this since
> > November and this is just the first step. I really do not want to make
> > my work 10x harder for the vague benefit of maybe making some
> > debugging
> > slightly easier.
>
> I understand that, but I'm not talking about re-development. Let me try
> explain it in a different way:
>
> What I mean is to go through your patches one after another but apply
> only those parts that do not affect the current single-threaded execution
> flow - effectively separating out those parts. Then, you go through
> the remaining changes and make corresponding "similar" changes to the
> working code, making it get as close as possible to your original code.
> It's an iterative process. At the end you should have just a small set
> of changes left which make up the difference between the working code
> (still following the traditional flow) and the threaded execution flow.
> That last set of differences can be finally applied in a way that it
> can be activated/deactivated by an option.
>
> When you have been working on this for so long already, then this would
> make up just a small part of the total work.
>
>
Not gonna happen, not gonna block progress because of whim of single random
contributor.
> Regards,
> softworkz
> _______________________________________________
> 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".
>
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-06 17:38 ` Paul B Mahol
@ 2022-04-06 17:56 ` Kieran Kunhya
2022-04-06 18:53 ` Soft Works
0 siblings, 1 reply; 81+ messages in thread
From: Kieran Kunhya @ 2022-04-06 17:56 UTC (permalink / raw)
To: FFmpeg development discussions and patches
>
> Not gonna happen, not gonna block progress because of whim of single random
> contributor.
>
Agreed, this patch series is as important as buffer referencing. We can't
let holdouts block progress.
Kieran
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-06 17:56 ` Kieran Kunhya
@ 2022-04-06 18:53 ` Soft Works
0 siblings, 0 replies; 81+ messages in thread
From: Soft Works @ 2022-04-06 18:53 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Kieran Kunhya
> Sent: Wednesday, April 6, 2022 7:57 PM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> >
> > Not gonna happen, not gonna block progress because of whim of single
> random
> > contributor.
> >
>
> Agreed, this patch series is as important as buffer referencing. We
> can't
> let holdouts block progress.
RFC Patch => Opinionated Response != Blocking
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-06 8:41 ` Anton Khirnov
2022-04-06 16:29 ` Soft Works
@ 2022-04-07 8:32 ` Anton Khirnov
2022-04-08 15:27 ` Soft Works
2022-04-11 8:28 ` Anton Khirnov
1 sibling, 2 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-07 8:32 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Soft Works (2022-04-06 18:29:53)
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Anton Khirnov
> > Sent: Wednesday, April 6, 2022 10:42 AM
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > architecture
> >
> > Quoting Soft Works (2022-04-05 23:05:57)
> > > do I understand it right that there won't be a single-thread
> > > operation mode that replicates/corresponds the current behavior?
> >
> > Correct, maintaining a single-threaded mode would require massive
> > amounts of extra effort for questionable gain.
>
> The gain is not to be seen in having an alternate run-mode in
> longer-term term perspective. It is about avoiding a single
> point-of-no-return change which may have fundamental consequences
> and impose debt on other developers when it would no longer be possible
> to compare to the previous mode of operation.
I don't understand where your apocalyptic language is coming from. Yes,
overall this will be a very big change. But it will also be composed of
many individual patches that can be understood on their own. And I am
not a drive-by contributor, you can always just ask if something is
unclear.
Threads are not magic. It is ubiquitous well-understood technology that
has been around for decades. Yes, they do involve their own challenges,
but so does everything else, including the status quo.
The current architecture of ffmpeg.c is, in my opinion, unsustainable.
There is barely any separation of responsibilities. E.g. filtering code
will modify muxer state, etc. It is very hard to understand the code
behaviour in various scenarious (we have SO MANY options), and how will
some code change affect it. This makes adding new major features much
more painful than it should be. I am firmly convinced that these patches
will make the code significantly easier to understand.
> > If I understand correctly what you're suggesting then I don't believe
> > this approach is feasible. The goal is not "add threading to improve
> > performance", keeping everything else intact as much as possible. The
> > goal is "improve architecture to make the code easier to
> > understand/maintain/extend", threads are a means towards that goal.
> > The
> > fact that this should also improve throughput is more of a nice side
> > effect than anything else.
> >
> > This patchset already changes behaviour in certain cases, making the
> > output more predictable and consistent. Reordering it somehow to
> > separate "semantically neutral" patches would require vast amounts of
> > extra work. Note that progressing at all without obviously breaking
> > anything is already quite hard --- I've been working on this since
> > November and this is just the first step. I really do not want to make
> > my work 10x harder for the vague benefit of maybe making some
> > debugging
> > slightly easier.
>
> I understand that, but I'm not talking about re-development. Let me try
> explain it in a different way:
>
> What I mean is to go through your patches one after another but apply
> only those parts that do not affect the current single-threaded execution
> flow - effectively separating out those parts. Then, you go through
> the remaining changes and make corresponding "similar" changes to the
> working code, making it get as close as possible to your original code.
> It's an iterative process. At the end you should have just a small set
> of changes left which make up the difference between the working code
> (still following the traditional flow) and the threaded execution flow.
> That last set of differences can be finally applied in a way that it
> can be activated/deactivated by an option.
>
> When you have been working on this for so long already, then this would
> make up just a small part of the total work.
Sorry, this does not seem a reasonable request to me. For one thing, the
only advantage you claim involve highly hypothetical doomsday scenarios
where you cannot compare to the old code and so ALL IS LOST. That smells
like a cargo cult. The current code is not holy scripture determining
how things should work for all eternity. It has bugs, inconsistencies,
and poorly handled corner cases (some of which are fixed by this very
patchset).
Furthermore, remember that this is just the first step. There will be
further patchsets converting the other components. I intend to upstream
them gradually one after the other. Your suggestion would require me to
instead write the whole thing at once, fighting rebase conflicts all the
way, and then submit it as a giant utterly unreviewable patchset. That
is a good recipe for never getting this finished.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-07 8:32 ` Anton Khirnov
@ 2022-04-08 15:27 ` Soft Works
2022-04-11 8:28 ` Anton Khirnov
1 sibling, 0 replies; 81+ messages in thread
From: Soft Works @ 2022-04-08 15:27 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Anton Khirnov
> Sent: Thursday, April 7, 2022 10:33 AM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> Quoting Soft Works (2022-04-06 18:29:53)
> >
> >
> > > -----Original Message-----
> > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > > Anton Khirnov
> > > Sent: Wednesday, April 6, 2022 10:42 AM
> > > To: FFmpeg development discussions and patches <ffmpeg-
> > > devel@ffmpeg.org>
> > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > architecture
> > >
> > > Quoting Soft Works (2022-04-05 23:05:57)
> > > > do I understand it right that there won't be a single-thread
> > > > operation mode that replicates/corresponds the current behavior?
> > >
> > > Correct, maintaining a single-threaded mode would require massive
> > > amounts of extra effort for questionable gain.
> >
> > The gain is not to be seen in having an alternate run-mode in
> > longer-term term perspective. It is about avoiding a single
> > point-of-no-return change which may have fundamental consequences
> > and impose debt on other developers when it would no longer be
> possible
> > to compare to the previous mode of operation.
>
> I don't understand where your apocalyptic language is coming from.
> Yes,
> overall this will be a very big change.
Should it turn out that the switch will go smoothly and easily
without (minimal) issues, then I'll sincerely admit that my concerns
were exaggerated and unjustified.
>
> Threads are not magic. It is ubiquitous well-understood technology
> that
> has been around for decades. Yes, they do involve their own
> challenges,
> but so does everything else, including the status quo.
>
> The current architecture of ffmpeg.c is, in my opinion, unsustainable.
Agreed.
> There is barely any separation of responsibilities. E.g. filtering
> code
> will modify muxer state, etc. It is very hard to understand the code
> behaviour in various scenarious (we have SO MANY options), and how
> will
> some code change affect it. This makes adding new major features much
> more painful than it should be. I am firmly convinced that these
> patches
> will make the code significantly easier to understand.
No doubt about that.
> Sorry, this does not seem a reasonable request to me. For one thing,
> the
> only advantage you claim involve highly hypothetical doomsday
> scenarios
> where you cannot compare to the old code and so ALL IS LOST. That
> smells
> like a cargo cult. The current code is not holy scripture determining
> how things should work for all eternity. It has bugs, inconsistencies,
> and poorly handled corner cases (some of which are fixed by this very
> patchset).
As mentioned, the concern is about the transition not about carrying
this for a long time.
> Furthermore, remember that this is just the first step. There will be
> further patchsets converting the other components. I intend to
> upstream
> them gradually one after the other. Your suggestion would require me
> to
> instead write the whole thing at once, fighting rebase conflicts all
> the
> way, and then submit it as a giant utterly unreviewable patchset.
That's not what I meant, but anyway it's not worth discussing when
it's a minority opinion.
Just a practical question instead for planning purposes:
Which timeframe do you expect for the whole process?
When do you plan to start and for how long do you think it will
take until all further patchsets will be submitted/applied?
Thanks,
sw
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-07 8:32 ` Anton Khirnov
2022-04-08 15:27 ` Soft Works
@ 2022-04-11 8:28 ` Anton Khirnov
2022-04-11 20:09 ` Soft Works
1 sibling, 1 reply; 81+ messages in thread
From: Anton Khirnov @ 2022-04-11 8:28 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Soft Works (2022-04-08 17:27:10)
> > Furthermore, remember that this is just the first step. There will be
> > further patchsets converting the other components. I intend to
> > upstream
> > them gradually one after the other. Your suggestion would require me
> > to
> > instead write the whole thing at once, fighting rebase conflicts all
> > the
> > way, and then submit it as a giant utterly unreviewable patchset.
>
> That's not what I meant, but anyway it's not worth discussing when
> it's a minority opinion.
>
> Just a practical question instead for planning purposes:
>
> Which timeframe do you expect for the whole process?
> When do you plan to start
If you mean "start pushing the patches", then I intend to do that as
they are reviewed and approved. I hope to send the upstreamable version
of this set this week, if nobody has strong objectsions then I might
push it after vacation, i.e. late April/early May.
> and for how long do you think it will take until all further patchsets
> will be submitted/applied?
This is very hard to estimate accurately. A pessimistic guess assuming I
get stuck on every stupid thing would be end of this year, but I hope
for things to go much faster.
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-11 8:28 ` Anton Khirnov
@ 2022-04-11 20:09 ` Soft Works
2022-04-11 20:52 ` Paul B Mahol
0 siblings, 1 reply; 81+ messages in thread
From: Soft Works @ 2022-04-11 20:09 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Anton Khirnov
> Sent: Monday, April 11, 2022 10:29 AM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> Quoting Soft Works (2022-04-08 17:27:10)
> > > Furthermore, remember that this is just the first step. There will
> be
> > > further patchsets converting the other components. I intend to
> > > upstream
> > > them gradually one after the other. Your suggestion would require
> me
> > > to
> > > instead write the whole thing at once, fighting rebase conflicts
> all
> > > the
> > > way, and then submit it as a giant utterly unreviewable patchset.
> >
> > That's not what I meant, but anyway it's not worth discussing when
> > it's a minority opinion.
> >
> > Just a practical question instead for planning purposes:
> >
> > Which timeframe do you expect for the whole process?
> > When do you plan to start
>
> If you mean "start pushing the patches", then I intend to do that as
> they are reviewed and approved. I hope to send the upstreamable
> version
> of this set this week, if nobody has strong objectsions then I might
> push it after vacation, i.e. late April/early May.
>
> > and for how long do you think it will take until all further
> patchsets
> > will be submitted/applied?
>
> This is very hard to estimate accurately. A pessimistic guess assuming
> I
> get stuck on every stupid thing would be end of this year, but I hope
> for things to go much faster.
Thanks for the reply. I'm asking because I need to decide about the
way I'm going to proceed with the subtitle filtering patchset.
I think I will have to keep and continue this in private during this
procedure as I don't have the resources to regularly adapt and sync
from my (5.0 based) working branch back to the master branch.
Thanks,
softworkz
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-11 20:09 ` Soft Works
@ 2022-04-11 20:52 ` Paul B Mahol
2022-04-11 20:58 ` Soft Works
0 siblings, 1 reply; 81+ messages in thread
From: Paul B Mahol @ 2022-04-11 20:52 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Mon, Apr 11, 2022 at 10:10 PM Soft Works <softworkz@hotmail.com> wrote:
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Anton Khirnov
> > Sent: Monday, April 11, 2022 10:29 AM
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > architecture
> >
> > Quoting Soft Works (2022-04-08 17:27:10)
> > > > Furthermore, remember that this is just the first step. There will
> > be
> > > > further patchsets converting the other components. I intend to
> > > > upstream
> > > > them gradually one after the other. Your suggestion would require
> > me
> > > > to
> > > > instead write the whole thing at once, fighting rebase conflicts
> > all
> > > > the
> > > > way, and then submit it as a giant utterly unreviewable patchset.
> > >
> > > That's not what I meant, but anyway it's not worth discussing when
> > > it's a minority opinion.
> > >
> > > Just a practical question instead for planning purposes:
> > >
> > > Which timeframe do you expect for the whole process?
> > > When do you plan to start
> >
> > If you mean "start pushing the patches", then I intend to do that as
> > they are reviewed and approved. I hope to send the upstreamable
> > version
> > of this set this week, if nobody has strong objectsions then I might
> > push it after vacation, i.e. late April/early May.
> >
> > > and for how long do you think it will take until all further
> > patchsets
> > > will be submitted/applied?
> >
> > This is very hard to estimate accurately. A pessimistic guess assuming
> > I
> > get stuck on every stupid thing would be end of this year, but I hope
> > for things to go much faster.
>
> Thanks for the reply. I'm asking because I need to decide about the
> way I'm going to proceed with the subtitle filtering patchset.
>
> I think I will have to keep and continue this in private during this
> procedure as I don't have the resources to regularly adapt and sync
> from my (5.0 based) working branch back to the master branch.
>
>
That is big waste of resource when not implementing thing properly.
> Thanks,
> softworkz
>
>
>
>
>
> _______________________________________________
> 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".
>
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-11 20:52 ` Paul B Mahol
@ 2022-04-11 20:58 ` Soft Works
2022-04-12 9:29 ` Paul B Mahol
0 siblings, 1 reply; 81+ messages in thread
From: Soft Works @ 2022-04-11 20:58 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Paul
> B Mahol
> Sent: Monday, April 11, 2022 10:52 PM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> On Mon, Apr 11, 2022 at 10:10 PM Soft Works <softworkz@hotmail.com>
> wrote:
>
> >
> >
> > > -----Original Message-----
> > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > > Anton Khirnov
> > > Sent: Monday, April 11, 2022 10:29 AM
> > > To: FFmpeg development discussions and patches <ffmpeg-
> > > devel@ffmpeg.org>
> > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > architecture
> > >
> > > Quoting Soft Works (2022-04-08 17:27:10)
> > > > > Furthermore, remember that this is just the first step. There
> will
> > > be
> > > > > further patchsets converting the other components. I intend to
> > > > > upstream
> > > > > them gradually one after the other. Your suggestion would
> require
> > > me
> > > > > to
> > > > > instead write the whole thing at once, fighting rebase
> conflicts
> > > all
> > > > > the
> > > > > way, and then submit it as a giant utterly unreviewable
> patchset.
> > > >
> > > > That's not what I meant, but anyway it's not worth discussing
> when
> > > > it's a minority opinion.
> > > >
> > > > Just a practical question instead for planning purposes:
> > > >
> > > > Which timeframe do you expect for the whole process?
> > > > When do you plan to start
> > >
> > > If you mean "start pushing the patches", then I intend to do that
> as
> > > they are reviewed and approved. I hope to send the upstreamable
> > > version
> > > of this set this week, if nobody has strong objectsions then I
> might
> > > push it after vacation, i.e. late April/early May.
> > >
> > > > and for how long do you think it will take until all further
> > > patchsets
> > > > will be submitted/applied?
> > >
> > > This is very hard to estimate accurately. A pessimistic guess
> assuming
> > > I
> > > get stuck on every stupid thing would be end of this year, but I
> hope
> > > for things to go much faster.
> >
> > Thanks for the reply. I'm asking because I need to decide about the
> > way I'm going to proceed with the subtitle filtering patchset.
> >
> > I think I will have to keep and continue this in private during this
> > procedure as I don't have the resources to regularly adapt and sync
> > from my (5.0 based) working branch back to the master branch.
> >
> >
> That is big waste of resource when not implementing thing properly.
From my point of view, somebody who has never given any detailed
reviews, didn't state what exactly(!) he would consider to be "improper"
and never made any suggestion how the implementation would need to
be changed to become "proper" - doesn't have the right to make such
claims.
softworkz
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-11 20:58 ` Soft Works
@ 2022-04-12 9:29 ` Paul B Mahol
2022-04-12 22:43 ` Soft Works
0 siblings, 1 reply; 81+ messages in thread
From: Paul B Mahol @ 2022-04-12 9:29 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Mon, Apr 11, 2022 at 10:58 PM Soft Works <softworkz@hotmail.com> wrote:
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Paul
> > B Mahol
> > Sent: Monday, April 11, 2022 10:52 PM
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > architecture
> >
> > On Mon, Apr 11, 2022 at 10:10 PM Soft Works <softworkz@hotmail.com>
> > wrote:
> >
> > >
> > >
> > > > -----Original Message-----
> > > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > > > Anton Khirnov
> > > > Sent: Monday, April 11, 2022 10:29 AM
> > > > To: FFmpeg development discussions and patches <ffmpeg-
> > > > devel@ffmpeg.org>
> > > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > > architecture
> > > >
> > > > Quoting Soft Works (2022-04-08 17:27:10)
> > > > > > Furthermore, remember that this is just the first step. There
> > will
> > > > be
> > > > > > further patchsets converting the other components. I intend to
> > > > > > upstream
> > > > > > them gradually one after the other. Your suggestion would
> > require
> > > > me
> > > > > > to
> > > > > > instead write the whole thing at once, fighting rebase
> > conflicts
> > > > all
> > > > > > the
> > > > > > way, and then submit it as a giant utterly unreviewable
> > patchset.
> > > > >
> > > > > That's not what I meant, but anyway it's not worth discussing
> > when
> > > > > it's a minority opinion.
> > > > >
> > > > > Just a practical question instead for planning purposes:
> > > > >
> > > > > Which timeframe do you expect for the whole process?
> > > > > When do you plan to start
> > > >
> > > > If you mean "start pushing the patches", then I intend to do that
> > as
> > > > they are reviewed and approved. I hope to send the upstreamable
> > > > version
> > > > of this set this week, if nobody has strong objectsions then I
> > might
> > > > push it after vacation, i.e. late April/early May.
> > > >
> > > > > and for how long do you think it will take until all further
> > > > patchsets
> > > > > will be submitted/applied?
> > > >
> > > > This is very hard to estimate accurately. A pessimistic guess
> > assuming
> > > > I
> > > > get stuck on every stupid thing would be end of this year, but I
> > hope
> > > > for things to go much faster.
> > >
> > > Thanks for the reply. I'm asking because I need to decide about the
> > > way I'm going to proceed with the subtitle filtering patchset.
> > >
> > > I think I will have to keep and continue this in private during this
> > > procedure as I don't have the resources to regularly adapt and sync
> > > from my (5.0 based) working branch back to the master branch.
> > >
> > >
> > That is big waste of resource when not implementing thing properly.
>
> From my point of view, somebody who has never given any detailed
> reviews, didn't state what exactly(!) he would consider to be "improper"
> and never made any suggestion how the implementation would need to
> be changed to become "proper" - doesn't have the right to make such
> claims.
>
You never asked kindly.
>
> softworkz
>
>
>
> _______________________________________________
> 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".
>
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-12 9:29 ` Paul B Mahol
@ 2022-04-12 22:43 ` Soft Works
2022-04-13 9:42 ` Nicolas George
2022-04-14 10:02 ` Paul B Mahol
0 siblings, 2 replies; 81+ messages in thread
From: Soft Works @ 2022-04-12 22:43 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Paul
> B Mahol
> Sent: Tuesday, April 12, 2022 11:29 AM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> On Mon, Apr 11, 2022 at 10:58 PM Soft Works <softworkz@hotmail.com>
> wrote:
>
> >
> >
> > > -----Original Message-----
> > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Paul
> > > B Mahol
> > > Sent: Monday, April 11, 2022 10:52 PM
> > > To: FFmpeg development discussions and patches <ffmpeg-
> > > devel@ffmpeg.org>
> > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > architecture
> > >
> > > On Mon, Apr 11, 2022 at 10:10 PM Soft Works
> <softworkz@hotmail.com>
> > > wrote:
> > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf
> Of
> > > > > Anton Khirnov
> > > > > Sent: Monday, April 11, 2022 10:29 AM
> > > > > To: FFmpeg development discussions and patches <ffmpeg-
> > > > > devel@ffmpeg.org>
> > > > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a
> threaded
> > > > > architecture
> > > > >
> > > > > Quoting Soft Works (2022-04-08 17:27:10)
> > > > > > > Furthermore, remember that this is just the first step.
> There
> > > will
> > > > > be
> > > > > > > further patchsets converting the other components. I
> intend to
> > > > > > > upstream
> > > > > > > them gradually one after the other. Your suggestion would
> > > require
> > > > > me
> > > > > > > to
> > > > > > > instead write the whole thing at once, fighting rebase
> > > conflicts
> > > > > all
> > > > > > > the
> > > > > > > way, and then submit it as a giant utterly unreviewable
> > > patchset.
> > > > > >
> > > > > > That's not what I meant, but anyway it's not worth
> discussing
> > > when
> > > > > > it's a minority opinion.
> > > > > >
> > > > > > Just a practical question instead for planning purposes:
> > > > > >
> > > > > > Which timeframe do you expect for the whole process?
> > > > > > When do you plan to start
> > > > >
> > > > > If you mean "start pushing the patches", then I intend to do
> that
> > > as
> > > > > they are reviewed and approved. I hope to send the
> upstreamable
> > > > > version
> > > > > of this set this week, if nobody has strong objectsions then I
> > > might
> > > > > push it after vacation, i.e. late April/early May.
> > > > >
> > > > > > and for how long do you think it will take until all further
> > > > > patchsets
> > > > > > will be submitted/applied?
> > > > >
> > > > > This is very hard to estimate accurately. A pessimistic guess
> > > assuming
> > > > > I
> > > > > get stuck on every stupid thing would be end of this year, but
> I
> > > hope
> > > > > for things to go much faster.
> > > >
> > > > Thanks for the reply. I'm asking because I need to decide about
> the
> > > > way I'm going to proceed with the subtitle filtering patchset.
> > > >
> > > > I think I will have to keep and continue this in private during
> this
> > > > procedure as I don't have the resources to regularly adapt and
> sync
> > > > from my (5.0 based) working branch back to the master branch.
> > > >
> > > >
> > > That is big waste of resource when not implementing thing
> properly.
> >
> > From my point of view, somebody who has never given any detailed
> > reviews, didn't state what exactly(!) he would consider to be
> "improper"
> > and never made any suggestion how the implementation would need to
> > be changed to become "proper" - doesn't have the right to make such
> > claims.
> >
>
> You never asked kindly.
I have always asked you kindly, probably more kindly than many
others do (going through history, I just found many very kind
questions I've been asking you).
For the specific issue about the subtitles patchset, you jumped
in on IRC, saying "it's a hack". I had asked you (kindly!) what
makes you think that it would be a hack and what you would think needs
to be changed. You never answered the question since that time,
instead you kept labeling it in all those ways.
I think the fundamental problem about the current situation is
that there were discussions with several other developers whose
arguments were based on theoretical considerations after reviewing
the code but without having actually worked with it and gone
through all the real-world situations that exist.
My code though, is made to provision for all cases by providing
a high level of flexibility, which is done by having timing fields
that are redundant in some cases but are needed (and non-redundant)
in other cases. Full coverage of cases is elementary for me, though;
I can't drop it, like somebody had suggested.
As a matter of fact, I see two chances:
- others believe what I'm telling
or
- another developer of sufficient reputation and credibility
gets to look into the details for confirming my reasoning
> > > That is big waste of resources
Inclusion in ffmpeg master has always been a secondary objective
only with the intention to contribute something useful and keep
the diff-to-official at a moderate level, avoiding the effort for
adapting to upstream changes.
Now that ffmpeg.c is about to undergo changes for the next months,
it would really be a "big waste of resources" to regularly keep
up with those changes. On the other side, I think exactly those
changes would have benefitted from many of the subtitle changes
in my patchset, as this eliminates a lot of all the special treatment
which is in place for subtitle stream handling.
I recognize though, that interest and intentions for improvement
in this area are low; otherwise, a disagreement about two fields
more or less in AVFrame, wouldn't probably be blocking the story
as a whole.
softworkz
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-12 22:43 ` Soft Works
@ 2022-04-13 9:42 ` Nicolas George
2022-04-13 22:14 ` Soft Works
2022-04-14 10:02 ` Paul B Mahol
1 sibling, 1 reply; 81+ messages in thread
From: Nicolas George @ 2022-04-13 9:42 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Soft Works (12022-04-12):
> I have always asked you kindly
You have been repeatedly rude towards the people who know libavfilter
well.
On top of that, you have shown that you do not understand how
libavfilter currently works.
On top of that, you have refused to learn how libavfilter currently
works.
You made your bed.
--
Nicolas George
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [PATCH 09/49] fftools/ffmpeg: store output format separately from the muxer context
2022-04-06 12:00 ` James Almer
@ 2022-04-13 10:18 ` Anton Khirnov
0 siblings, 0 replies; 81+ messages in thread
From: Anton Khirnov @ 2022-04-13 10:18 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting James Almer (2022-04-06 14:00:21)
> On 4/4/2022 8:29 AM, Anton Khirnov wrote:
> > Allows accessing it without going through the muxer context. This will
> > be useful in the following commits, where the muxer context will be
> > hidden.
> > ---
> > fftools/ffmpeg.c | 18 ++++++++++--------
> > fftools/ffmpeg.h | 2 ++
> > fftools/ffmpeg_opt.c | 1 +
> > 3 files changed, 13 insertions(+), 8 deletions(-)
>
> Patches 4 to 9 look ok.
Thank you, pushed patches up to 9
--
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-13 9:42 ` Nicolas George
@ 2022-04-13 22:14 ` Soft Works
0 siblings, 0 replies; 81+ messages in thread
From: Soft Works @ 2022-04-13 22:14 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Nicolas George
> Sent: Wednesday, April 13, 2022 11:43 AM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> Soft Works (12022-04-12):
> > I have always asked you kindly
>
> You have been repeatedly rude towards the people who know libavfilter
> well.
That treatment was exclusively reserved to yours.
You had called for it.
You got it.
You deserved it.
> On top of that, you have shown that you do not understand how
> libavfilter currently works.
> On top of that, you have refused to learn how libavfilter currently
> works.
Exactly that's one of the reasons.
You keep throwing around exactly those kinds of statements without
substantial content.
That's purely demagogic behavior.
As a long as you continue like that, you don't deserve any
better responses.
softworkz
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-12 22:43 ` Soft Works
2022-04-13 9:42 ` Nicolas George
@ 2022-04-14 10:02 ` Paul B Mahol
2022-04-14 21:37 ` Soft Works
1 sibling, 1 reply; 81+ messages in thread
From: Paul B Mahol @ 2022-04-14 10:02 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Wed, Apr 13, 2022 at 12:43 AM Soft Works <softworkz@hotmail.com> wrote:
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Paul
> > B Mahol
> > Sent: Tuesday, April 12, 2022 11:29 AM
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > architecture
> >
> > On Mon, Apr 11, 2022 at 10:58 PM Soft Works <softworkz@hotmail.com>
> > wrote:
> >
> > >
> > >
> > > > -----Original Message-----
> > > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Paul
> > > > B Mahol
> > > > Sent: Monday, April 11, 2022 10:52 PM
> > > > To: FFmpeg development discussions and patches <ffmpeg-
> > > > devel@ffmpeg.org>
> > > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > > architecture
> > > >
> > > > On Mon, Apr 11, 2022 at 10:10 PM Soft Works
> > <softworkz@hotmail.com>
> > > > wrote:
> > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf
> > Of
> > > > > > Anton Khirnov
> > > > > > Sent: Monday, April 11, 2022 10:29 AM
> > > > > > To: FFmpeg development discussions and patches <ffmpeg-
> > > > > > devel@ffmpeg.org>
> > > > > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a
> > threaded
> > > > > > architecture
> > > > > >
> > > > > > Quoting Soft Works (2022-04-08 17:27:10)
> > > > > > > > Furthermore, remember that this is just the first step.
> > There
> > > > will
> > > > > > be
> > > > > > > > further patchsets converting the other components. I
> > intend to
> > > > > > > > upstream
> > > > > > > > them gradually one after the other. Your suggestion would
> > > > require
> > > > > > me
> > > > > > > > to
> > > > > > > > instead write the whole thing at once, fighting rebase
> > > > conflicts
> > > > > > all
> > > > > > > > the
> > > > > > > > way, and then submit it as a giant utterly unreviewable
> > > > patchset.
> > > > > > >
> > > > > > > That's not what I meant, but anyway it's not worth
> > discussing
> > > > when
> > > > > > > it's a minority opinion.
> > > > > > >
> > > > > > > Just a practical question instead for planning purposes:
> > > > > > >
> > > > > > > Which timeframe do you expect for the whole process?
> > > > > > > When do you plan to start
> > > > > >
> > > > > > If you mean "start pushing the patches", then I intend to do
> > that
> > > > as
> > > > > > they are reviewed and approved. I hope to send the
> > upstreamable
> > > > > > version
> > > > > > of this set this week, if nobody has strong objectsions then I
> > > > might
> > > > > > push it after vacation, i.e. late April/early May.
> > > > > >
> > > > > > > and for how long do you think it will take until all further
> > > > > > patchsets
> > > > > > > will be submitted/applied?
> > > > > >
> > > > > > This is very hard to estimate accurately. A pessimistic guess
> > > > assuming
> > > > > > I
> > > > > > get stuck on every stupid thing would be end of this year, but
> > I
> > > > hope
> > > > > > for things to go much faster.
> > > > >
> > > > > Thanks for the reply. I'm asking because I need to decide about
> > the
> > > > > way I'm going to proceed with the subtitle filtering patchset.
> > > > >
> > > > > I think I will have to keep and continue this in private during
> > this
> > > > > procedure as I don't have the resources to regularly adapt and
> > sync
> > > > > from my (5.0 based) working branch back to the master branch.
> > > > >
> > > > >
> > > > That is big waste of resource when not implementing thing
> > properly.
> > >
> > > From my point of view, somebody who has never given any detailed
> > > reviews, didn't state what exactly(!) he would consider to be
> > "improper"
> > > and never made any suggestion how the implementation would need to
> > > be changed to become "proper" - doesn't have the right to make such
> > > claims.
> > >
> >
> > You never asked kindly.
>
> I have always asked you kindly, probably more kindly than many
> others do (going through history, I just found many very kind
> questions I've been asking you).
>
> For the specific issue about the subtitles patchset, you jumped
> in on IRC, saying "it's a hack". I had asked you (kindly!) what
> makes you think that it would be a hack and what you would think needs
> to be changed. You never answered the question since that time,
> instead you kept labeling it in all those ways.
>
>
> I think the fundamental problem about the current situation is
> that there were discussions with several other developers whose
> arguments were based on theoretical considerations after reviewing
> the code but without having actually worked with it and gone
> through all the real-world situations that exist.
>
> My code though, is made to provision for all cases by providing
> a high level of flexibility, which is done by having timing fields
> that are redundant in some cases but are needed (and non-redundant)
> in other cases. Full coverage of cases is elementary for me, though;
> I can't drop it, like somebody had suggested.
>
> As a matter of fact, I see two chances:
>
> - others believe what I'm telling
> or
> - another developer of sufficient reputation and credibility
> gets to look into the details for confirming my reasoning
>
> > > > That is big waste of resources
>
> Inclusion in ffmpeg master has always been a secondary objective
> only with the intention to contribute something useful and keep
> the diff-to-official at a moderate level, avoiding the effort for
> adapting to upstream changes.
>
> Now that ffmpeg.c is about to undergo changes for the next months,
> it would really be a "big waste of resources" to regularly keep
> up with those changes. On the other side, I think exactly those
> changes would have benefitted from many of the subtitle changes
> in my patchset, as this eliminates a lot of all the special treatment
> which is in place for subtitle stream handling.
>
> I recognize though, that interest and intentions for improvement
> in this area are low; otherwise, a disagreement about two fields
> more or less in AVFrame, wouldn't probably be blocking the story
> as a whole.
>
Please provide current version of your work via link to repository.
Changing AVFrame is sign that something is not implemented carefully.
>
> softworkz
>
> _______________________________________________
> 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".
>
_______________________________________________
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] 81+ messages in thread
* Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture
2022-04-14 10:02 ` Paul B Mahol
@ 2022-04-14 21:37 ` Soft Works
0 siblings, 0 replies; 81+ messages in thread
From: Soft Works @ 2022-04-14 21:37 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Paul
> B Mahol
> Sent: Thursday, April 14, 2022 12:02 PM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> architecture
>
> On Wed, Apr 13, 2022 at 12:43 AM Soft Works <softworkz@hotmail.com>
> wrote:
>
> >
> >
> > > -----Original Message-----
> > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Paul
> > > B Mahol
> > > Sent: Tuesday, April 12, 2022 11:29 AM
> > > To: FFmpeg development discussions and patches <ffmpeg-
> > > devel@ffmpeg.org>
> > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded
> > > architecture
> > >
> > > On Mon, Apr 11, 2022 at 10:58 PM Soft Works
> <softworkz@hotmail.com>
> > > wrote:
> > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf
> Of
> > > Paul
> > > > > B Mahol
> > > > > Sent: Monday, April 11, 2022 10:52 PM
> > > > > To: FFmpeg development discussions and patches <ffmpeg-
> > > > > devel@ffmpeg.org>
> > > > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a
> threaded
> > > > > architecture
> > > > >
> > > > > On Mon, Apr 11, 2022 at 10:10 PM Soft Works
> > > <softworkz@hotmail.com>
> > > > > wrote:
> > > > >
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On
> Behalf
> > > Of
> > > > > > > Anton Khirnov
> > > > > > > Sent: Monday, April 11, 2022 10:29 AM
> > > > > > > To: FFmpeg development discussions and patches <ffmpeg-
> > > > > > > devel@ffmpeg.org>
> > > > > > > Subject: Re: [FFmpeg-devel] [RFC] Switching ffmpeg.c to a
> > > threaded
> > > > > > > architecture
> > > > > > >
> > > > > > > Quoting Soft Works (2022-04-08 17:27:10)
> > > > > > > > > Furthermore, remember that this is just the first
> step.
> > > There
> > > > > will
> > > > > > > be
> > > > > > > > > further patchsets converting the other components. I
> > > intend to
> > > > > > > > > upstream
> > > > > > > > > them gradually one after the other. Your suggestion
> would
> > > > > require
> > > > > > > me
> > > > > > > > > to
> > > > > > > > > instead write the whole thing at once, fighting rebase
> > > > > conflicts
> > > > > > > all
> > > > > > > > > the
> > > > > > > > > way, and then submit it as a giant utterly
> unreviewable
> > > > > patchset.
> > > > > > > >
> > > > > > > > That's not what I meant, but anyway it's not worth
> > > discussing
> > > > > when
> > > > > > > > it's a minority opinion.
> > > > > > > >
> > > > > > > > Just a practical question instead for planning purposes:
> > > > > > > >
> > > > > > > > Which timeframe do you expect for the whole process?
> > > > > > > > When do you plan to start
> > > > > > >
> > > > > > > If you mean "start pushing the patches", then I intend to
> do
> > > that
> > > > > as
> > > > > > > they are reviewed and approved. I hope to send the
> > > upstreamable
> > > > > > > version
> > > > > > > of this set this week, if nobody has strong objectsions
> then I
> > > > > might
> > > > > > > push it after vacation, i.e. late April/early May.
> > > > > > >
> > > > > > > > and for how long do you think it will take until all
> further
> > > > > > > patchsets
> > > > > > > > will be submitted/applied?
> > > > > > >
> > > > > > > This is very hard to estimate accurately. A pessimistic
> guess
> > > > > assuming
> > > > > > > I
> > > > > > > get stuck on every stupid thing would be end of this year,
> but
> > > I
> > > > > hope
> > > > > > > for things to go much faster.
> > > > > >
> > > > > > Thanks for the reply. I'm asking because I need to decide
> about
> > > the
> > > > > > way I'm going to proceed with the subtitle filtering
> patchset.
> > > > > >
> > > > > > I think I will have to keep and continue this in private
> during
> > > this
> > > > > > procedure as I don't have the resources to regularly adapt
> and
> > > sync
> > > > > > from my (5.0 based) working branch back to the master
> branch.
> > > > > >
> > > > > >
> > > > > That is big waste of resource when not implementing thing
> > > properly.
> > > >
> > > > From my point of view, somebody who has never given any detailed
> > > > reviews, didn't state what exactly(!) he would consider to be
> > > "improper"
> > > > and never made any suggestion how the implementation would need
> to
> > > > be changed to become "proper" - doesn't have the right to make
> such
> > > > claims.
> > > >
> > >
> > > You never asked kindly.
> >
> > I have always asked you kindly, probably more kindly than many
> > others do (going through history, I just found many very kind
> > questions I've been asking you).
> >
> > For the specific issue about the subtitles patchset, you jumped
> > in on IRC, saying "it's a hack". I had asked you (kindly!) what
> > makes you think that it would be a hack and what you would think
> needs
> > to be changed. You never answered the question since that time,
> > instead you kept labeling it in all those ways.
> >
> >
> > I think the fundamental problem about the current situation is
> > that there were discussions with several other developers whose
> > arguments were based on theoretical considerations after reviewing
> > the code but without having actually worked with it and gone
> > through all the real-world situations that exist.
> >
> > My code though, is made to provision for all cases by providing
> > a high level of flexibility, which is done by having timing fields
> > that are redundant in some cases but are needed (and non-redundant)
> > in other cases. Full coverage of cases is elementary for me, though;
> > I can't drop it, like somebody had suggested.
> >
> > As a matter of fact, I see two chances:
> >
> > - others believe what I'm telling
> > or
> > - another developer of sufficient reputation and credibility
> > gets to look into the details for confirming my reasoning
> >
> > > > > That is big waste of resources
> >
> > Inclusion in ffmpeg master has always been a secondary objective
> > only with the intention to contribute something useful and keep
> > the diff-to-official at a moderate level, avoiding the effort for
> > adapting to upstream changes.
> >
> > Now that ffmpeg.c is about to undergo changes for the next months,
> > it would really be a "big waste of resources" to regularly keep
> > up with those changes. On the other side, I think exactly those
> > changes would have benefitted from many of the subtitle changes
> > in my patchset, as this eliminates a lot of all the special
> treatment
> > which is in place for subtitle stream handling.
> >
> > I recognize though, that interest and intentions for improvement
> > in this area are low; otherwise, a disagreement about two fields
> > more or less in AVFrame, wouldn't probably be blocking the story
> > as a whole.
> >
>
> Please provide current version of your work via link to repository.
>
> Changing AVFrame is sign that something is not implemented carefully.
Yup, will do shortly, please give me a few days.
Thanks,
sw
_______________________________________________
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] 81+ messages in thread
end of thread, other threads:[~2022-04-14 21:38 UTC | newest]
Thread overview: 81+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-04 11:29 [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 01/49] fftools/ffmpeg: drop an obsolete hack Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 02/49] fftools/ffmpeg: move a comment to a more appropriate place Anton Khirnov
2022-04-06 11:20 ` James Almer
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 03/49] fftools/ffmpeg: stop using OutputStream.frame_number for streamcopy Anton Khirnov
2022-04-06 11:20 ` James Almer
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 04/49] fftools/ffmpeg: pass the muxer context explicitly to some functions Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 05/49] fftools/ffmpeg: store the output file index in OutputFile Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 06/49] fftools/ffmpeg: move some muxing-related code into a separate file Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 07/49] fftools/ffmpeg: move writing the trailer to ffmpeg_mux.c Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 08/49] fftools/ffmpeg: move freeing the output file " Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 09/49] fftools/ffmpeg: store output format separately from the muxer context Anton Khirnov
2022-04-06 12:00 ` James Almer
2022-04-13 10:18 ` Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 10/49] fftools/ffmpeg_mux: add private " Anton Khirnov
2022-04-04 11:29 ` [FFmpeg-devel] [PATCH 11/49] fftools/ffmpeg: add a helper function to access output file size Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 12/49] fftools/ffmpeg: fix the type of limit_filesize Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 13/49] fftools/ffmpeg: refactor limiting output file size with -fs Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 14/49] fftools/ffmpeg: set want_sdp when initializing the muxer Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 15/49] fftools/ffmpeg: write the header for stream-less outputs " Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 16/49] fftools/ffmpeg: move closing the file into of_write_trailer() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 17/49] fftools/ffmpeg: refactor the code checking for bitexact output Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 18/49] fftools/ffmpeg: access output file chapters through a wrapper Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 19/49] fftools/ffmpeg: do not log to the muxer context Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 20/49] fftools/ffmpeg: move the mux queue into muxer private data Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 21/49] fftools/ffmpeg_mux: split queuing packets into a separate function Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 22/49] fftools/ffmpeg_mux: split of_write_packet() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 23/49] fftools/ffmpeg: move output file opts into private context Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 24/49] fftools/ffmpeg: move processing video stats to ffmpeg_mux Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 25/49] fftools/ffmpeg_mux: drop a useless check and reduce indentation Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 26/49] fftools/ffmpeg_mux: stop using AVStream.nb_frames in do_video_stats() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 27/49] fftools/ffmpeg_mux: stop using av_stream_get_end_pts() " Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 28/49] fftools/ffmpeg_mux: merge variable declaration and initialization Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 29/49] fftools/ffmpeg_mux: move processing AV_PKT_DATA_QUALITY_STATS to do_video_stats() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 30/49] fftools/ffmpeg: share the code encoding a single frame between video and audio Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 31/49] fftools/ffmpeg: reuse the encoding code for flushing encoders Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 32/49] fftools/ffmpeg: reindent after previous commit Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 33/49] fftools/ffmpeg: use refcounted packets for encoded subtitles Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 34/49] fftools/ffmpeg: rework -shortest implementation Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 35/49] fftools/ffmpeg: use the sync queues to handle -frames Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 36/49] fftools/ffmpeg: stop using OutputStream.frame_number in print_report() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 37/49] fftools/ffmpeg: only set OutputStream.frame_number for video encoding Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 38/49] fftools/ffmpeg: make the muxer AVFormatContext private to ffmpeg_mux.c Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 39/49] fftools/ffmpeg_mux: return errors from of_submit_packet() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 40/49] fftools/ffmpeg_mux: return errors from submit_packet() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 41/49] fftools/ffmpeg_mux: return errors from write_packet() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 42/49] fftools/ffmpeg_mux: simplify submit_packet() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 43/49] fftools/ffmpeg_mux: return errors from update_video_stats() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 44/49] fftools/ffmpeg_mux: do not call exit_program() in print_sdp() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 45/49] fftools/ffmpeg: stop using av_stream_get_end_pts() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 46/49] fftools/ffmpeg: do not write the output file header from init_output_stream() Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 47/49] fftools/ffmpeg: depend on threads Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 48/49] fftools: add a multistream thread-safe queue Anton Khirnov
2022-04-04 11:30 ` [FFmpeg-devel] [PATCH 49/49] fftools/ffmpeg: move each muxer to a separate thread Anton Khirnov
2022-04-05 9:00 ` [FFmpeg-devel] [RFC] Switching ffmpeg.c to a threaded architecture Anton Khirnov
2022-04-05 19:15 ` Michael Niedermayer
2022-04-05 19:46 ` Anton Khirnov
2022-04-05 21:05 ` Soft Works
2022-04-05 21:18 ` Paul B Mahol
2022-04-05 21:19 ` Soft Works
2022-04-06 11:17 ` Paul B Mahol
2022-04-06 15:46 ` Soft Works
2022-04-06 15:54 ` Matt Zagrabelny
2022-04-06 8:41 ` Anton Khirnov
2022-04-06 16:29 ` Soft Works
2022-04-06 17:38 ` Paul B Mahol
2022-04-06 17:56 ` Kieran Kunhya
2022-04-06 18:53 ` Soft Works
2022-04-07 8:32 ` Anton Khirnov
2022-04-08 15:27 ` Soft Works
2022-04-11 8:28 ` Anton Khirnov
2022-04-11 20:09 ` Soft Works
2022-04-11 20:52 ` Paul B Mahol
2022-04-11 20:58 ` Soft Works
2022-04-12 9:29 ` Paul B Mahol
2022-04-12 22:43 ` Soft Works
2022-04-13 9:42 ` Nicolas George
2022-04-13 22:14 ` Soft Works
2022-04-14 10:02 ` Paul B Mahol
2022-04-14 21:37 ` Soft Works
2022-04-06 10:02 ` 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