Commit ba7397ba authored by Anton Khirnov's avatar Anton Khirnov

avconv: factor out initializing stream parameters for encoding

Setting the filter input parameters is moved to init_input_stream(),
so that it is done before the decoder is opened, potentially overwriting
the information from avformat_find_stream_info() with less accurate
data.

This commit temporarily disables QSV transcoding with hw frames. The
functionality will be re-added in the following commits.
parent 722ec3eb
......@@ -1616,8 +1616,17 @@ static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
static int init_input_stream(int ist_index, char *error, int error_len)
{
int ret;
int i, ret;
InputStream *ist = input_streams[ist_index];
for (i = 0; i < ist->nb_filters; i++) {
ret = ifilter_parameters_from_decoder(ist->filters[i], ist->dec_ctx);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Error initializing filter input\n");
return ret;
}
}
if (ist->decoding_needed) {
AVCodec *codec = ist->dec;
if (!codec) {
......@@ -1872,6 +1881,136 @@ static int init_output_stream_streamcopy(OutputStream *ost)
return 0;
}
static void set_encoder_id(OutputFile *of, OutputStream *ost)
{
AVDictionaryEntry *e;
uint8_t *encoder_string;
int encoder_string_len;
int format_flags = 0;
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);
}
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))
av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
av_strlcat(encoder_string, ost->enc->name, encoder_string_len);
av_dict_set(&ost->st->metadata, "encoder", encoder_string,
AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
}
static void parse_forced_key_frames(char *kf, OutputStream *ost,
AVCodecContext *avctx)
{
char *p;
int n = 1, i;
int64_t t;
for (p = kf; *p; p++)
if (*p == ',')
n++;
ost->forced_kf_count = n;
ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n);
if (!ost->forced_kf_pts) {
av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
exit_program(1);
}
p = kf;
for (i = 0; i < n; i++) {
char *next = strchr(p, ',');
if (next)
*next++ = 0;
t = parse_time_or_die("force_key_frames", p, 1);
ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
p = next;
}
}
static int init_output_stream_encode(OutputStream *ost)
{
InputStream *ist = get_input_stream(ost);
AVCodecContext *enc_ctx = ost->enc_ctx;
AVCodecContext *dec_ctx = NULL;
set_encoder_id(output_files[ost->file_index], ost);
if (ist) {
ost->st->disposition = ist->st->disposition;
dec_ctx = ist->dec_ctx;
enc_ctx->bits_per_raw_sample = dec_ctx->bits_per_raw_sample;
enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
}
if ((enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
filtergraph_is_simple(ost->filter->graph)) {
FilterGraph *fg = ost->filter->graph;
if (configure_filtergraph(fg)) {
av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
exit_program(1);
}
}
switch (enc_ctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format;
enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate;
enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout;
enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
break;
case AVMEDIA_TYPE_VIDEO:
enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base;
enc_ctx->width = ost->filter->filter->inputs[0]->w;
enc_ctx->height = ost->filter->filter->inputs[0]->h;
enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio =
ost->frame_aspect_ratio ? // overridden by the -aspect cli option
av_d2q(ost->frame_aspect_ratio * enc_ctx->height/enc_ctx->width, 255) :
ost->filter->filter->inputs[0]->sample_aspect_ratio;
enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format;
ost->st->avg_frame_rate = ost->frame_rate;
if (dec_ctx &&
(enc_ctx->width != dec_ctx->width ||
enc_ctx->height != dec_ctx->height ||
enc_ctx->pix_fmt != dec_ctx->pix_fmt)) {
enc_ctx->bits_per_raw_sample = 0;
}
if (ost->forced_keyframes)
parse_forced_key_frames(ost->forced_keyframes, ost,
ost->enc_ctx);
break;
case AVMEDIA_TYPE_SUBTITLE:
enc_ctx->time_base = (AVRational){1, 1000};
break;
default:
abort();
break;
}
return 0;
}
static int init_output_stream(OutputStream *ost, char *error, int error_len)
{
int ret = 0;
......@@ -1881,6 +2020,10 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
AVCodecContext *dec = NULL;
InputStream *ist;
ret = init_output_stream_encode(ost);
if (ret < 0)
return ret;
if ((ist = get_input_stream(ost)))
dec = ist->dec_ctx;
if (dec && dec->subtitle_header) {
......@@ -1973,69 +2116,9 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
return ret;
}
static void parse_forced_key_frames(char *kf, OutputStream *ost,
AVCodecContext *avctx)
{
char *p;
int n = 1, i;
int64_t t;
for (p = kf; *p; p++)
if (*p == ',')
n++;
ost->forced_kf_count = n;
ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n);
if (!ost->forced_kf_pts) {
av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
exit_program(1);
}
p = kf;
for (i = 0; i < n; i++) {
char *next = strchr(p, ',');
if (next)
*next++ = 0;
t = parse_time_or_die("force_key_frames", p, 1);
ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
p = next;
}
}
static void set_encoder_id(OutputFile *of, OutputStream *ost)
{
AVDictionaryEntry *e;
uint8_t *encoder_string;
int encoder_string_len;
int format_flags = 0;
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);
}
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))
av_strlcpy(encoder_string, LIBAVCODEC_IDENT " ", encoder_string_len);
av_strlcat(encoder_string, ost->enc->name, encoder_string_len);
av_dict_set(&ost->st->metadata, "encoder", encoder_string,
AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_OVERWRITE);
}
static int transcode_init(void)
{
int ret = 0, i, j, k;
AVFormatContext *oc;
OutputStream *ost;
InputStream *ist;
char error[1024];
......@@ -2048,97 +2131,6 @@ static int transcode_init(void)
input_streams[j + ifile->ist_index]->start = av_gettime_relative();
}
/* for each output stream, we compute the right encoding parameters */
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
oc = output_files[ost->file_index]->ctx;
ist = get_input_stream(ost);
if (ost->attachment_filename)
continue;
if (ist) {
ost->st->disposition = ist->st->disposition;
}
if (!ost->stream_copy) {
AVCodecContext *enc_ctx = ost->enc_ctx;
AVCodecContext *dec_ctx = NULL;
set_encoder_id(output_files[ost->file_index], ost);
if (ist) {
dec_ctx = ist->dec_ctx;
enc_ctx->bits_per_raw_sample = dec_ctx->bits_per_raw_sample;
enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
}
#if CONFIG_LIBMFX
if (qsv_transcode_init(ost))
exit_program(1);
#endif
if ((enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
filtergraph_is_simple(ost->filter->graph)) {
FilterGraph *fg = ost->filter->graph;
ret = ifilter_parameters_from_decoder(fg->inputs[0],
dec_ctx);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "Error initializing filter input\n");
exit_program(1);
}
if (configure_filtergraph(fg)) {
av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
exit_program(1);
}
}
switch (enc_ctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format;
enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate;
enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout;
enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
break;
case AVMEDIA_TYPE_VIDEO:
enc_ctx->time_base = ost->filter->filter->inputs[0]->time_base;
enc_ctx->width = ost->filter->filter->inputs[0]->w;
enc_ctx->height = ost->filter->filter->inputs[0]->h;
enc_ctx->sample_aspect_ratio = ost->st->sample_aspect_ratio =
ost->frame_aspect_ratio ? // overridden by the -aspect cli option
av_d2q(ost->frame_aspect_ratio * enc_ctx->height/enc_ctx->width, 255) :
ost->filter->filter->inputs[0]->sample_aspect_ratio;
enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format;
ost->st->avg_frame_rate = ost->frame_rate;
if (dec_ctx &&
(enc_ctx->width != dec_ctx->width ||
enc_ctx->height != dec_ctx->height ||
enc_ctx->pix_fmt != dec_ctx->pix_fmt)) {
enc_ctx->bits_per_raw_sample = 0;
}
if (ost->forced_keyframes)
parse_forced_key_frames(ost->forced_keyframes, ost,
ost->enc_ctx);
break;
case AVMEDIA_TYPE_SUBTITLE:
enc_ctx->time_base = (AVRational){1, 1000};
break;
default:
abort();
break;
}
}
}
/* init input streams */
for (i = 0; i < nb_input_streams; i++)
if ((ret = init_input_stream(i, error, sizeof(error))) < 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment