|
|
|
@@ -2549,6 +2549,71 @@ static int compare_int64(const void *a, const void *b) |
|
|
|
return va < vb ? -1 : va > vb ? +1 : 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int init_output_stream(OutputStream *ost, char *error, int error_len) |
|
|
|
{ |
|
|
|
int ret = 0; |
|
|
|
|
|
|
|
if (ost->encoding_needed) { |
|
|
|
AVCodec *codec = ost->enc; |
|
|
|
AVCodecContext *dec = NULL; |
|
|
|
InputStream *ist; |
|
|
|
|
|
|
|
if ((ist = get_input_stream(ost))) |
|
|
|
dec = ist->dec_ctx; |
|
|
|
if (dec && dec->subtitle_header) { |
|
|
|
/* ASS code assumes this buffer is null terminated so add extra byte. */ |
|
|
|
ost->enc_ctx->subtitle_header = av_mallocz(dec->subtitle_header_size + 1); |
|
|
|
if (!ost->enc_ctx->subtitle_header) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
memcpy(ost->enc_ctx->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); |
|
|
|
ost->enc_ctx->subtitle_header_size = dec->subtitle_header_size; |
|
|
|
} |
|
|
|
if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) |
|
|
|
av_dict_set(&ost->encoder_opts, "threads", "auto", 0); |
|
|
|
av_dict_set(&ost->encoder_opts, "side_data_only_packets", "1", 0); |
|
|
|
|
|
|
|
if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { |
|
|
|
if (ret == AVERROR_EXPERIMENTAL) |
|
|
|
abort_codec_experimental(codec, 1); |
|
|
|
snprintf(error, error_len, |
|
|
|
"Error while opening encoder for output stream #%d:%d - " |
|
|
|
"maybe incorrect parameters such as bit_rate, rate, width or height", |
|
|
|
ost->file_index, ost->index); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
if (ost->enc->type == AVMEDIA_TYPE_AUDIO && |
|
|
|
!(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) |
|
|
|
av_buffersink_set_frame_size(ost->filter->filter, |
|
|
|
ost->enc_ctx->frame_size); |
|
|
|
assert_avoptions(ost->encoder_opts); |
|
|
|
if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000) |
|
|
|
av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." |
|
|
|
" It takes bits/s as argument, not kbits/s\n"); |
|
|
|
|
|
|
|
ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx); |
|
|
|
if (ret < 0) { |
|
|
|
av_log(NULL, AV_LOG_FATAL, |
|
|
|
"Error initializing the output stream codec context.\n"); |
|
|
|
exit_program(1); |
|
|
|
} |
|
|
|
|
|
|
|
// copy timebase while removing common factors |
|
|
|
ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); |
|
|
|
ost->st->codec->codec= ost->enc_ctx->codec; |
|
|
|
} else { |
|
|
|
ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts); |
|
|
|
if (ret < 0) { |
|
|
|
av_log(NULL, AV_LOG_FATAL, |
|
|
|
"Error setting up codec context options.\n"); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
// copy timebase while removing common factors |
|
|
|
ost->st->time_base = av_add_q(ost->st->codec->time_base, (AVRational){0, 1}); |
|
|
|
} |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
static void parse_forced_key_frames(char *kf, OutputStream *ost, |
|
|
|
AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
@@ -3087,63 +3152,9 @@ static int transcode_init(void) |
|
|
|
|
|
|
|
/* open each encoder */ |
|
|
|
for (i = 0; i < nb_output_streams; i++) { |
|
|
|
ost = output_streams[i]; |
|
|
|
if (ost->encoding_needed) { |
|
|
|
AVCodec *codec = ost->enc; |
|
|
|
AVCodecContext *dec = NULL; |
|
|
|
|
|
|
|
if ((ist = get_input_stream(ost))) |
|
|
|
dec = ist->dec_ctx; |
|
|
|
if (dec && dec->subtitle_header) { |
|
|
|
/* ASS code assumes this buffer is null terminated so add extra byte. */ |
|
|
|
ost->enc_ctx->subtitle_header = av_mallocz(dec->subtitle_header_size + 1); |
|
|
|
if (!ost->enc_ctx->subtitle_header) { |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
goto dump_format; |
|
|
|
} |
|
|
|
memcpy(ost->enc_ctx->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); |
|
|
|
ost->enc_ctx->subtitle_header_size = dec->subtitle_header_size; |
|
|
|
} |
|
|
|
if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0)) |
|
|
|
av_dict_set(&ost->encoder_opts, "threads", "auto", 0); |
|
|
|
av_dict_set(&ost->encoder_opts, "side_data_only_packets", "1", 0); |
|
|
|
|
|
|
|
if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) { |
|
|
|
if (ret == AVERROR_EXPERIMENTAL) |
|
|
|
abort_codec_experimental(codec, 1); |
|
|
|
snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height", |
|
|
|
ost->file_index, ost->index); |
|
|
|
goto dump_format; |
|
|
|
} |
|
|
|
if (ost->enc->type == AVMEDIA_TYPE_AUDIO && |
|
|
|
!(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) |
|
|
|
av_buffersink_set_frame_size(ost->filter->filter, |
|
|
|
ost->enc_ctx->frame_size); |
|
|
|
assert_avoptions(ost->encoder_opts); |
|
|
|
if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000) |
|
|
|
av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." |
|
|
|
" It takes bits/s as argument, not kbits/s\n"); |
|
|
|
|
|
|
|
ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx); |
|
|
|
if (ret < 0) { |
|
|
|
av_log(NULL, AV_LOG_FATAL, |
|
|
|
"Error initializing the output stream codec context.\n"); |
|
|
|
exit_program(1); |
|
|
|
} |
|
|
|
|
|
|
|
// copy timebase while removing common factors |
|
|
|
ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1}); |
|
|
|
ost->st->codec->codec= ost->enc_ctx->codec; |
|
|
|
} else { |
|
|
|
ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts); |
|
|
|
if (ret < 0) { |
|
|
|
av_log(NULL, AV_LOG_FATAL, |
|
|
|
"Error setting up codec context options.\n"); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
// copy timebase while removing common factors |
|
|
|
ost->st->time_base = av_add_q(ost->st->codec->time_base, (AVRational){0, 1}); |
|
|
|
} |
|
|
|
ret = init_output_stream(output_streams[i], error, sizeof(error)); |
|
|
|
if (ret < 0) |
|
|
|
goto dump_format; |
|
|
|
} |
|
|
|
|
|
|
|
/* init input streams */ |
|
|
|
|