fftools/ffmpeg: convert to a threaded architecture
Change the main loop and every component (demuxers, decoders, filters, encoders, muxers) to use the previously added transcode scheduler. Every instance of every such component was already running in a separate thread, but now they can actually run in parallel. Changes the results of ffmpeg-fix_sub_duration_heartbeat - tested by JEEB to be more correct and deterministic.
This commit is contained in:
@@ -924,13 +924,6 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int new_stream_attachment(Muxer *mux, const OptionsContext *o,
|
||||
OutputStream *ost)
|
||||
{
|
||||
ost->finished = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int new_stream_subtitle(Muxer *mux, const OptionsContext *o,
|
||||
OutputStream *ost)
|
||||
{
|
||||
@@ -1168,9 +1161,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
||||
if (!ost->par_in)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0);
|
||||
if (!ms->muxing_queue)
|
||||
return AVERROR(ENOMEM);
|
||||
ms->last_mux_dts = AV_NOPTS_VALUE;
|
||||
|
||||
ost->st = st;
|
||||
@@ -1190,7 +1180,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
||||
if (!ost->enc_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ret = sch_add_enc(mux->sch, encoder_thread, ost, NULL);
|
||||
ret = sch_add_enc(mux->sch, encoder_thread, ost,
|
||||
ost->type == AVMEDIA_TYPE_SUBTITLE ? NULL : enc_open);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ms->sch_idx_enc = ret;
|
||||
@@ -1414,9 +1405,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
||||
|
||||
sch_mux_stream_buffering(mux->sch, mux->sch_idx, ms->sch_idx,
|
||||
max_muxing_queue_size, muxing_queue_data_threshold);
|
||||
|
||||
ms->max_muxing_queue_size = max_muxing_queue_size;
|
||||
ms->muxing_queue_data_threshold = muxing_queue_data_threshold;
|
||||
}
|
||||
|
||||
MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample,
|
||||
@@ -1434,8 +1422,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
||||
if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24)
|
||||
av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0);
|
||||
|
||||
ost->last_mux_dts = AV_NOPTS_VALUE;
|
||||
|
||||
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i,
|
||||
ms->copy_initial_nonkeyframes, oc, st);
|
||||
|
||||
@@ -1443,7 +1429,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
||||
case AVMEDIA_TYPE_VIDEO: ret = new_stream_video (mux, o, ost); break;
|
||||
case AVMEDIA_TYPE_AUDIO: ret = new_stream_audio (mux, o, ost); break;
|
||||
case AVMEDIA_TYPE_SUBTITLE: ret = new_stream_subtitle (mux, o, ost); break;
|
||||
case AVMEDIA_TYPE_ATTACHMENT: ret = new_stream_attachment(mux, o, ost); break;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -1938,7 +1923,6 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u
|
||||
MuxStream *ms = ms_from_ost(ost);
|
||||
enum AVMediaType type = ost->type;
|
||||
|
||||
ost->sq_idx_encode = -1;
|
||||
ost->sq_idx_mux = -1;
|
||||
|
||||
nb_interleaved += IS_INTERLEAVED(type);
|
||||
@@ -1961,11 +1945,17 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u
|
||||
* - at least one encoded audio/video stream is frame-limited, since
|
||||
* that has similar semantics to 'shortest'
|
||||
* - at least one audio encoder requires constant frame sizes
|
||||
*
|
||||
* Note that encoding sync queues are handled in the scheduler, because
|
||||
* different encoders run in different threads and need external
|
||||
* synchronization, while muxer sync queues can be handled inside the muxer
|
||||
*/
|
||||
if ((of->shortest && nb_av_enc > 1) || limit_frames_av_enc || nb_audio_fs) {
|
||||
of->sq_encode = sq_alloc(SYNC_QUEUE_FRAMES, buf_size_us, mux);
|
||||
if (!of->sq_encode)
|
||||
return AVERROR(ENOMEM);
|
||||
int sq_idx, ret;
|
||||
|
||||
sq_idx = sch_add_sq_enc(mux->sch, buf_size_us, mux);
|
||||
if (sq_idx < 0)
|
||||
return sq_idx;
|
||||
|
||||
for (int i = 0; i < oc->nb_streams; i++) {
|
||||
OutputStream *ost = of->streams[i];
|
||||
@@ -1975,13 +1965,11 @@ static int setup_sync_queues(Muxer *mux, AVFormatContext *oc, int64_t buf_size_u
|
||||
if (!IS_AV_ENC(ost, type))
|
||||
continue;
|
||||
|
||||
ost->sq_idx_encode = sq_add_stream(of->sq_encode,
|
||||
of->shortest || ms->max_frames < INT64_MAX);
|
||||
if (ost->sq_idx_encode < 0)
|
||||
return ost->sq_idx_encode;
|
||||
|
||||
if (ms->max_frames != INT64_MAX)
|
||||
sq_limit_frames(of->sq_encode, ost->sq_idx_encode, ms->max_frames);
|
||||
ret = sch_sq_add_enc(mux->sch, sq_idx, ms->sch_idx_enc,
|
||||
of->shortest || ms->max_frames < INT64_MAX,
|
||||
ms->max_frames);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2652,23 +2640,6 @@ static int validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_output_stream_nofilter(OutputStream *ost)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (ost->enc_ctx) {
|
||||
ret = enc_open(ost, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
ret = of_stream_init(output_files[ost->file_index], ost);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *output_file_item_name(void *obj)
|
||||
{
|
||||
const Muxer *mux = obj;
|
||||
@@ -2751,8 +2722,6 @@ int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
|
||||
av_strlcat(mux->log_name, "/", sizeof(mux->log_name));
|
||||
av_strlcat(mux->log_name, oc->oformat->name, sizeof(mux->log_name));
|
||||
|
||||
if (strcmp(oc->oformat->name, "rtp"))
|
||||
want_sdp = 0;
|
||||
|
||||
of->format = oc->oformat;
|
||||
if (recording_time != INT64_MAX)
|
||||
@@ -2768,7 +2737,7 @@ int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
|
||||
AVFMT_FLAG_BITEXACT);
|
||||
}
|
||||
|
||||
err = sch_add_mux(sch, muxer_thread, NULL, mux,
|
||||
err = sch_add_mux(sch, muxer_thread, mux_check_init, mux,
|
||||
!strcmp(oc->oformat->name, "rtp"));
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -2854,26 +2823,15 @@ int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
|
||||
|
||||
of->url = filename;
|
||||
|
||||
/* initialize stream copy and subtitle/data streams.
|
||||
* Encoded AVFrame based streams will get initialized when the first AVFrame
|
||||
* is received in do_video_out
|
||||
*/
|
||||
/* initialize streamcopy streams. */
|
||||
for (int i = 0; i < of->nb_streams; i++) {
|
||||
OutputStream *ost = of->streams[i];
|
||||
|
||||
if (ost->filter)
|
||||
continue;
|
||||
|
||||
err = init_output_stream_nofilter(ost);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* write the header for files with no streams */
|
||||
if (of->format->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) {
|
||||
int ret = mux_check_init(mux);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!ost->enc) {
|
||||
err = of_stream_init(of, ost);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user