fftools/ffmpeg_mux_init: move new_output_stream() lower in the file

Reduces the diff in the following commit.

Temporarily add a forward declaration for new_output_stream(), it will
be removed in the next commit.
This commit is contained in:
Anton Khirnov 2023-04-10 13:24:41 +02:00
parent 89c9a3ac35
commit a7f26b1c63

View File

@ -419,248 +419,7 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type)
}
static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
enum AVMediaType type, InputStream *ist)
{
AVFormatContext *oc = mux->fc;
MuxStream *ms;
OutputStream *ost;
const AVCodec *enc;
AVStream *st = avformat_new_stream(oc, NULL);
int ret = 0;
const char *bsfs = NULL, *time_base = NULL;
char *next, *codec_tag = NULL;
double qscale = -1;
int i;
if (!st)
report_and_exit(AVERROR(ENOMEM));
if (oc->nb_streams - 1 < o->nb_streamid_map)
st->id = o->streamid_map[oc->nb_streams - 1];
ms = mux_stream_alloc(mux, type);
ost = &ms->ost;
ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0);
if (!ms->muxing_queue)
report_and_exit(AVERROR(ENOMEM));
ms->last_mux_dts = AV_NOPTS_VALUE;
ost->st = st;
ost->ist = ist;
ost->kf.ref_pts = AV_NOPTS_VALUE;
st->codecpar->codec_type = type;
ret = choose_encoder(o, oc, ost, &enc);
if (ret < 0) {
av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n");
exit_program(1);
}
if (enc) {
ost->enc_ctx = avcodec_alloc_context3(enc);
if (!ost->enc_ctx)
report_and_exit(AVERROR(ENOMEM));
ret = enc_alloc(&ost->enc, enc);
if (ret < 0)
report_and_exit(ret);
av_strlcat(ms->log_name, "/", sizeof(ms->log_name));
av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name));
} else {
av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name));
}
ost->filtered_frame = av_frame_alloc();
if (!ost->filtered_frame)
report_and_exit(AVERROR(ENOMEM));
ost->pkt = av_packet_alloc();
if (!ost->pkt)
report_and_exit(AVERROR(ENOMEM));
if (ost->enc_ctx) {
AVCodecContext *enc = ost->enc_ctx;
AVIOContext *s = NULL;
char *buf = NULL, *arg = NULL, *preset = NULL;
const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL;
ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id,
oc, st, enc->codec);
MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
ost->autoscale = 1;
MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st);
if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) {
AVBPrint bprint;
av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
do {
av_bprint_clear(&bprint);
buf = get_line(s, &bprint);
if (!buf[0] || buf[0] == '#')
continue;
if (!(arg = strchr(buf, '='))) {
av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n");
exit_program(1);
}
*arg++ = 0;
av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE);
} while (!s->eof_reached);
av_bprint_finalize(&bprint, NULL);
avio_closep(&s);
}
if (ret) {
av_log(ost, AV_LOG_FATAL,
"Preset %s specified, but could not be opened.\n", preset);
exit_program(1);
}
MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st);
if (enc_stats_pre &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
const char *format = "{fidx} {sidx} {n} {t}";
MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st);
ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format);
if (ret < 0)
exit_program(1);
}
MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st);
if (enc_stats_post &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
const char *format = "{fidx} {sidx} {n} {t}";
MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st);
ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format);
if (ret < 0)
exit_program(1);
}
MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st);
if (mux_stats &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
const char *format = "{fidx} {sidx} {n} {t}";
MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st);
ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format);
if (ret < 0)
exit_program(1);
}
} else {
ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL);
}
if (o->bitexact) {
ost->bitexact = 1;
} else if (ost->enc_ctx) {
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) {
AVRational q;
if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 ||
q.num <= 0 || q.den <= 0) {
av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base);
exit_program(1);
}
st->time_base = q;
}
MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st);
if (time_base) {
AVRational q;
if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 ||
q.den <= 0) {
av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base);
exit_program(1);
}
ost->enc_timebase = q;
}
ms->max_frames = INT64_MAX;
MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st);
for (i = 0; i<o->nb_max_frames; i++) {
char *p = o->max_frames[i].specifier;
if (!*p && type != AVMEDIA_TYPE_VIDEO) {
av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n");
break;
}
}
ost->copy_prior_start = -1;
MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st);
MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st);
if (bsfs && *bsfs) {
ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx);
if (ret < 0) {
av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret));
exit_program(1);
}
}
MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st);
if (codec_tag) {
uint32_t tag = strtol(codec_tag, &next, 0);
if (*next) {
uint8_t buf[4] = { 0 };
memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag)));
tag = AV_RL32(buf);
}
ost->st->codecpar->codec_tag = tag;
if (ost->enc_ctx)
ost->enc_ctx->codec_tag = tag;
}
MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st);
if (ost->enc_ctx && qscale >= 0) {
ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE;
ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
}
ms->max_muxing_queue_size = 128;
MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ms->max_muxing_queue_size, oc, st);
ms->muxing_queue_data_threshold = 50*1024*1024;
MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ms->muxing_queue_data_threshold, oc, st);
MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample,
oc, st);
MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat,
oc, st);
if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx)
ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0);
av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0);
if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24)
av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0);
if (ost->ist) {
ost->ist->discard = 0;
ost->ist->st->discard = ost->ist->user_set_discard;
if (!(ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)))
ist_output_add(ost->ist, ost);
}
ost->last_mux_dts = AV_NOPTS_VALUE;
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i,
ost->copy_initial_nonkeyframes, oc, st);
return ost;
}
enum AVMediaType type, InputStream *ist);
static char *get_ost_filters(const OptionsContext *o, AVFormatContext *oc,
OutputStream *ost)
@ -1101,6 +860,250 @@ static OutputStream *new_subtitle_stream(Muxer *mux, const OptionsContext *o, In
return ost;
}
static OutputStream *new_output_stream(Muxer *mux, const OptionsContext *o,
enum AVMediaType type, InputStream *ist)
{
AVFormatContext *oc = mux->fc;
MuxStream *ms;
OutputStream *ost;
const AVCodec *enc;
AVStream *st = avformat_new_stream(oc, NULL);
int ret = 0;
const char *bsfs = NULL, *time_base = NULL;
char *next, *codec_tag = NULL;
double qscale = -1;
int i;
if (!st)
report_and_exit(AVERROR(ENOMEM));
if (oc->nb_streams - 1 < o->nb_streamid_map)
st->id = o->streamid_map[oc->nb_streams - 1];
ms = mux_stream_alloc(mux, type);
ost = &ms->ost;
ms->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0);
if (!ms->muxing_queue)
report_and_exit(AVERROR(ENOMEM));
ms->last_mux_dts = AV_NOPTS_VALUE;
ost->st = st;
ost->ist = ist;
ost->kf.ref_pts = AV_NOPTS_VALUE;
st->codecpar->codec_type = type;
ret = choose_encoder(o, oc, ost, &enc);
if (ret < 0) {
av_log(ost, AV_LOG_FATAL, "Error selecting an encoder\n");
exit_program(1);
}
if (enc) {
ost->enc_ctx = avcodec_alloc_context3(enc);
if (!ost->enc_ctx)
report_and_exit(AVERROR(ENOMEM));
ret = enc_alloc(&ost->enc, enc);
if (ret < 0)
report_and_exit(ret);
av_strlcat(ms->log_name, "/", sizeof(ms->log_name));
av_strlcat(ms->log_name, enc->name, sizeof(ms->log_name));
} else {
av_strlcat(ms->log_name, "/copy", sizeof(ms->log_name));
}
ost->filtered_frame = av_frame_alloc();
if (!ost->filtered_frame)
report_and_exit(AVERROR(ENOMEM));
ost->pkt = av_packet_alloc();
if (!ost->pkt)
report_and_exit(AVERROR(ENOMEM));
if (ost->enc_ctx) {
AVCodecContext *enc = ost->enc_ctx;
AVIOContext *s = NULL;
char *buf = NULL, *arg = NULL, *preset = NULL;
const char *enc_stats_pre = NULL, *enc_stats_post = NULL, *mux_stats = NULL;
ost->encoder_opts = filter_codec_opts(o->g->codec_opts, enc->codec_id,
oc, st, enc->codec);
MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
ost->autoscale = 1;
MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st);
if (preset && (!(ret = get_preset_file_2(preset, enc->codec->name, &s)))) {
AVBPrint bprint;
av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
do {
av_bprint_clear(&bprint);
buf = get_line(s, &bprint);
if (!buf[0] || buf[0] == '#')
continue;
if (!(arg = strchr(buf, '='))) {
av_log(ost, AV_LOG_FATAL, "Invalid line found in the preset file.\n");
exit_program(1);
}
*arg++ = 0;
av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE);
} while (!s->eof_reached);
av_bprint_finalize(&bprint, NULL);
avio_closep(&s);
}
if (ret) {
av_log(ost, AV_LOG_FATAL,
"Preset %s specified, but could not be opened.\n", preset);
exit_program(1);
}
MATCH_PER_STREAM_OPT(enc_stats_pre, str, enc_stats_pre, oc, st);
if (enc_stats_pre &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
const char *format = "{fidx} {sidx} {n} {t}";
MATCH_PER_STREAM_OPT(enc_stats_pre_fmt, str, format, oc, st);
ret = enc_stats_init(ost, &ost->enc_stats_pre, 1, enc_stats_pre, format);
if (ret < 0)
exit_program(1);
}
MATCH_PER_STREAM_OPT(enc_stats_post, str, enc_stats_post, oc, st);
if (enc_stats_post &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
const char *format = "{fidx} {sidx} {n} {t}";
MATCH_PER_STREAM_OPT(enc_stats_post_fmt, str, format, oc, st);
ret = enc_stats_init(ost, &ost->enc_stats_post, 0, enc_stats_post, format);
if (ret < 0)
exit_program(1);
}
MATCH_PER_STREAM_OPT(mux_stats, str, mux_stats, oc, st);
if (mux_stats &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
const char *format = "{fidx} {sidx} {n} {t}";
MATCH_PER_STREAM_OPT(mux_stats_fmt, str, format, oc, st);
ret = enc_stats_init(ost, &ms->stats, 0, mux_stats, format);
if (ret < 0)
exit_program(1);
}
} else {
ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL);
}
if (o->bitexact) {
ost->bitexact = 1;
} else if (ost->enc_ctx) {
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) {
AVRational q;
if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 ||
q.num <= 0 || q.den <= 0) {
av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base);
exit_program(1);
}
st->time_base = q;
}
MATCH_PER_STREAM_OPT(enc_time_bases, str, time_base, oc, st);
if (time_base) {
AVRational q;
if (av_parse_ratio(&q, time_base, INT_MAX, 0, NULL) < 0 ||
q.den <= 0) {
av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", time_base);
exit_program(1);
}
ost->enc_timebase = q;
}
ms->max_frames = INT64_MAX;
MATCH_PER_STREAM_OPT(max_frames, i64, ms->max_frames, oc, st);
for (i = 0; i<o->nb_max_frames; i++) {
char *p = o->max_frames[i].specifier;
if (!*p && type != AVMEDIA_TYPE_VIDEO) {
av_log(ost, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n");
break;
}
}
ost->copy_prior_start = -1;
MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st);
MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st);
if (bsfs && *bsfs) {
ret = av_bsf_list_parse_str(bsfs, &ms->bsf_ctx);
if (ret < 0) {
av_log(ost, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret));
exit_program(1);
}
}
MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st);
if (codec_tag) {
uint32_t tag = strtol(codec_tag, &next, 0);
if (*next) {
uint8_t buf[4] = { 0 };
memcpy(buf, codec_tag, FFMIN(sizeof(buf), strlen(codec_tag)));
tag = AV_RL32(buf);
}
ost->st->codecpar->codec_tag = tag;
if (ost->enc_ctx)
ost->enc_ctx->codec_tag = tag;
}
MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st);
if (ost->enc_ctx && qscale >= 0) {
ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE;
ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
}
ms->max_muxing_queue_size = 128;
MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ms->max_muxing_queue_size, oc, st);
ms->muxing_queue_data_threshold = 50*1024*1024;
MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ms->muxing_queue_data_threshold, oc, st);
MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample,
oc, st);
MATCH_PER_STREAM_OPT(fix_sub_duration_heartbeat, i, ost->fix_sub_duration_heartbeat,
oc, st);
if (oc->oformat->flags & AVFMT_GLOBALHEADER && ost->enc_ctx)
ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
av_dict_copy(&ost->sws_dict, o->g->sws_dict, 0);
av_dict_copy(&ost->swr_opts, o->g->swr_opts, 0);
if (ost->enc_ctx && av_get_exact_bits_per_sample(ost->enc_ctx->codec_id) == 24)
av_dict_set(&ost->swr_opts, "output_sample_bits", "24", 0);
if (ost->ist) {
ost->ist->discard = 0;
ost->ist->st->discard = ost->ist->user_set_discard;
if (!(ost->enc && (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)))
ist_output_add(ost->ist, ost);
}
ost->last_mux_dts = AV_NOPTS_VALUE;
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i,
ost->copy_initial_nonkeyframes, oc, st);
return ost;
}
static void init_output_filter(OutputFilter *ofilter, const OptionsContext *o,
Muxer *mux)
{