diff --git a/avconv.c b/avconv.c index 30b85cc770..b167ff662f 100644 --- a/avconv.c +++ b/avconv.c @@ -191,6 +191,8 @@ static void avconv_cleanup(int ret) av_freep(&ost->avfilter); av_freep(&ost->logfile_prefix); + avcodec_free_context(&ost->enc_ctx); + av_freep(&output_streams[i]); } for (i = 0; i < nb_input_files; i++) { @@ -316,7 +318,7 @@ static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec, static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) { AVBitStreamFilterContext *bsfc = ost->bitstream_filters; - AVCodecContext *avctx = ost->st->codec; + AVCodecContext *avctx = ost->enc_ctx; int ret; /* @@ -394,7 +396,7 @@ static int check_recording_time(OutputStream *ost) OutputFile *of = output_files[ost->file_index]; if (of->recording_time != INT64_MAX && - av_compare_ts(ost->sync_opts - ost->first_pts, ost->st->codec->time_base, of->recording_time, + av_compare_ts(ost->sync_opts - ost->first_pts, ost->enc_ctx->time_base, of->recording_time, AV_TIME_BASE_Q) >= 0) { ost->finished = 1; return 0; @@ -405,7 +407,7 @@ static int check_recording_time(OutputStream *ost) static void do_audio_out(AVFormatContext *s, OutputStream *ost, AVFrame *frame) { - AVCodecContext *enc = ost->st->codec; + AVCodecContext *enc = ost->enc_ctx; AVPacket pkt; int got_packet = 0; @@ -456,7 +458,7 @@ static void do_subtitle_out(AVFormatContext *s, return; } - enc = ost->st->codec; + enc = ost->enc_ctx; if (!subtitle_out) { subtitle_out = av_malloc(subtitle_out_max_size); @@ -513,7 +515,7 @@ static void do_video_out(AVFormatContext *s, { int ret, format_video_sync; AVPacket pkt; - AVCodecContext *enc = ost->st->codec; + AVCodecContext *enc = ost->enc_ctx; *frame_size = 0; @@ -563,11 +565,11 @@ static void do_video_out(AVFormatContext *s, } else { int got_packet; - if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME) && + if (enc->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME) && ost->top_field_first >= 0) in_picture->top_field_first = !!ost->top_field_first; - in_picture->quality = ost->st->codec->global_quality; + in_picture->quality = enc->global_quality; if (!enc->me_threshold) in_picture->pict_type = 0; if (ost->forced_kf_index < ost->forced_kf_count && @@ -628,7 +630,7 @@ static void do_video_stats(OutputStream *ost, int frame_size) } } - enc = ost->st->codec; + enc = ost->enc_ctx; if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { frame_number = ost->frame_number; fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality / (float)FF_QP2LAMBDA); @@ -666,7 +668,7 @@ static int poll_filter(OutputStream *ost) if (ost->enc->type == AVMEDIA_TYPE_AUDIO && !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) ret = av_buffersink_get_samples(ost->filter->filter, filtered_frame, - ost->st->codec->frame_size); + ost->enc_ctx->frame_size); else ret = av_buffersink_get_frame(ost->filter->filter, filtered_frame); @@ -677,16 +679,16 @@ static int poll_filter(OutputStream *ost) int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; filtered_frame->pts = av_rescale_q(filtered_frame->pts, ost->filter->filter->inputs[0]->time_base, - ost->st->codec->time_base) - + ost->enc_ctx->time_base) - av_rescale_q(start_time, AV_TIME_BASE_Q, - ost->st->codec->time_base); + ost->enc_ctx->time_base); } switch (ost->filter->filter->inputs[0]->type) { case AVMEDIA_TYPE_VIDEO: if (!ost->frame_aspect_ratio) - ost->st->codec->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; + ost->enc_ctx->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; do_video_out(of->ctx, ost, filtered_frame, &frame_size); if (vstats_filename && frame_size) @@ -728,7 +730,7 @@ static int poll_filters(void) if (!output_streams[i]->filter || output_streams[i]->finished) continue; - pts = av_rescale_q(pts, output_streams[i]->st->codec->time_base, + pts = av_rescale_q(pts, output_streams[i]->enc_ctx->time_base, AV_TIME_BASE_Q); if (pts < min_pts) { min_pts = pts; @@ -768,12 +770,12 @@ static void print_final_stats(int64_t total_size) for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - switch (ost->st->codec->codec_type) { + switch (ost->enc_ctx->codec_type) { case AVMEDIA_TYPE_VIDEO: video_size += ost->data_size; break; case AVMEDIA_TYPE_AUDIO: audio_size += ost->data_size; break; default: other_size += ost->data_size; break; } - extra_size += ost->st->codec->extradata_size; + extra_size += ost->enc_ctx->extradata_size; data_size += ost->data_size; } @@ -836,7 +838,7 @@ static void print_final_stats(int64_t total_size) for (j = 0; j < of->ctx->nb_streams; j++) { OutputStream *ost = output_streams[of->ost_index + j]; - enum AVMediaType type = ost->st->codec->codec_type; + enum AVMediaType type = ost->enc_ctx->codec_type; total_size += ost->data_size; total_packets += ost->packets_written; @@ -910,7 +912,7 @@ static void print_report(int is_last_report, int64_t timer_start) for (i = 0; i < nb_output_streams; i++) { float q = -1; ost = output_streams[i]; - enc = ost->st->codec; + enc = ost->enc_ctx; if (!ost->stream_copy && enc->coded_frame) q = enc->coded_frame->quality / (float)FF_QP2LAMBDA; if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -989,23 +991,23 @@ static void flush_encoders(void) for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - AVCodecContext *enc = ost->st->codec; + AVCodecContext *enc = ost->enc_ctx; AVFormatContext *os = output_files[ost->file_index]->ctx; int stop_encoding = 0; if (!ost->encoding_needed) continue; - if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) + if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) continue; - if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO) + if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO) continue; for (;;) { int (*encode)(AVCodecContext*, AVPacket*, const AVFrame*, int*) = NULL; const char *desc; - switch (ost->st->codec->codec_type) { + switch (enc->codec_type) { case AVMEDIA_TYPE_AUDIO: encode = avcodec_encode_audio2; desc = "Audio"; @@ -1100,7 +1102,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } /* force the input stream PTS */ - if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) ost->sync_opts++; if (pkt->pts != AV_NOPTS_VALUE) @@ -1118,10 +1120,10 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.flags = pkt->flags; // FIXME remove the following 2 lines they shall be replaced by the bitstream filters - if ( ost->st->codec->codec_id != AV_CODEC_ID_H264 - && ost->st->codec->codec_id != AV_CODEC_ID_MPEG1VIDEO - && ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO - && ost->st->codec->codec_id != AV_CODEC_ID_VC1 + if ( ost->enc_ctx->codec_id != AV_CODEC_ID_H264 + && ost->enc_ctx->codec_id != AV_CODEC_ID_MPEG1VIDEO + && ost->enc_ctx->codec_id != AV_CODEC_ID_MPEG2VIDEO + && ost->enc_ctx->codec_id != AV_CODEC_ID_VC1 ) { if (av_parser_change(ost->parser, ost->st->codec, &opkt.data, &opkt.size, @@ -1555,7 +1557,7 @@ static int init_input_stream(int ist_index, char *error, int error_len) for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; if (ost->source_index == ist_index) { - update_sample_fmt(ist->dec_ctx, codec, ost->st->codec); + update_sample_fmt(ist->dec_ctx, codec, ost->enc_ctx); break; } } @@ -1602,7 +1604,7 @@ static InputStream *get_input_stream(OutputStream *ost) int i; for (i = 0; i < fg->nb_inputs; i++) - if (fg->inputs[i]->ist->dec_ctx->codec_type == ost->st->codec->codec_type) + if (fg->inputs[i]->ist->dec_ctx->codec_type == ost->enc_ctx->codec_type) return fg->inputs[i]->ist; } @@ -1711,7 +1713,7 @@ static int transcode_init(void) if (ost->attachment_filename) continue; - enc_ctx = ost->st->codec; + enc_ctx = ost->enc_ctx; if (ist) { dec_ctx = ist->dec_ctx; @@ -1893,7 +1895,7 @@ static int transcode_init(void) if (ost->forced_keyframes) parse_forced_key_frames(ost->forced_keyframes, ost, - ost->st->codec); + ost->enc_ctx); break; case AVMEDIA_TYPE_SUBTITLE: enc_ctx->time_base = (AVRational){1, 1000}; @@ -1947,17 +1949,19 @@ static int transcode_init(void) if ((ist = get_input_stream(ost))) dec = ist->dec_ctx; if (dec && dec->subtitle_header) { - ost->st->codec->subtitle_header = av_malloc(dec->subtitle_header_size); - if (!ost->st->codec->subtitle_header) { + ost->enc_ctx->subtitle_header = av_malloc(dec->subtitle_header_size); + if (!ost->enc_ctx->subtitle_header) { ret = AVERROR(ENOMEM); goto dump_format; } - memcpy(ost->st->codec->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); - ost->st->codec->subtitle_header_size = dec->subtitle_header_size; + 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); - if ((ret = avcodec_open2(ost->st->codec, codec, &ost->encoder_opts)) < 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", @@ -1965,11 +1969,18 @@ static int transcode_init(void) goto dump_format; } assert_avoptions(ost->encoder_opts); - if (ost->st->codec->bit_rate && ost->st->codec->bit_rate < 1000) + 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"); } else { - av_opt_set_dict(ost->st->codec, &ost->encoder_opts); + av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts); + } + + 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); } } @@ -2505,8 +2516,7 @@ static int transcode(void) for (i = 0; i < nb_output_streams; i++) { ost = output_streams[i]; if (ost->encoding_needed) { - av_freep(&ost->st->codec->stats_in); - avcodec_close(ost->st->codec); + av_freep(&ost->enc_ctx->stats_in); } } @@ -2532,13 +2542,10 @@ static int transcode(void) for (i = 0; i < nb_output_streams; i++) { ost = output_streams[i]; if (ost) { - if (ost->stream_copy) - av_freep(&ost->st->codec->extradata); if (ost->logfile) { fclose(ost->logfile); ost->logfile = NULL; } - av_freep(&ost->st->codec->subtitle_header); av_free(ost->forced_kf_pts); av_dict_free(&ost->encoder_opts); av_dict_free(&ost->resample_opts); diff --git a/avconv.h b/avconv.h index 64d8ad0b16..b932d7e8db 100644 --- a/avconv.h +++ b/avconv.h @@ -314,6 +314,7 @@ typedef struct OutputStream { /* dts of the last packet sent to the muxer */ int64_t last_mux_dts; AVBitStreamFilterContext *bitstream_filters; + AVCodecContext *enc_ctx; AVCodec *enc; int64_t max_frames; AVFrame *filtered_frame; diff --git a/avconv_filter.c b/avconv_filter.c index c667992165..1eda7b845e 100644 --- a/avconv_filter.c +++ b/avconv_filter.c @@ -39,8 +39,8 @@ #define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name) \ static char *choose_ ## var ## s(OutputStream *ost) \ { \ - if (ost->st->codec->var != none) { \ - get_name(ost->st->codec->var); \ + if (ost->enc_ctx->var != none) { \ + get_name(ost->enc_ctx->var); \ return av_strdup(name); \ } else if (ost->enc && ost->enc->supported_list) { \ const type *p; \ @@ -231,7 +231,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, char *pix_fmts; OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; - AVCodecContext *codec = ost->st->codec; + AVCodecContext *codec = ost->enc_ctx; AVFilterContext *last_filter = out->filter_ctx; int pad_idx = out->pad_idx; int ret; @@ -319,7 +319,7 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, { OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; - AVCodecContext *codec = ost->st->codec; + AVCodecContext *codec = ost->enc_ctx; AVFilterContext *last_filter = out->filter_ctx; int pad_idx = out->pad_idx; char *sample_fmts, *sample_rates, *channel_layouts; diff --git a/avconv_opt.c b/avconv_opt.c index 539b1a0f61..f8c524568c 100644 --- a/avconv_opt.c +++ b/avconv_opt.c @@ -905,6 +905,14 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->st = st; st->codec->codec_type = type; choose_encoder(o, oc, ost); + + ost->enc_ctx = avcodec_alloc_context3(ost->enc); + if (!ost->enc_ctx) { + av_log(NULL, AV_LOG_ERROR, "Error allocating the encoding context.\n"); + exit_program(1); + } + ost->enc_ctx->codec_type = type; + if (ost->enc) { AVIOContext *s = NULL; char *buf = NULL, *arg = NULL, *preset = NULL; @@ -939,9 +947,6 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->encoder_opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); } - avcodec_get_context_defaults3(st->codec, ost->enc); - st->codec->codec_type = type; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy - ost->max_frames = INT64_MAX; MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); @@ -967,17 +972,17 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e uint32_t tag = strtol(codec_tag, &next, 0); if (*next) tag = AV_RL32(codec_tag); - st->codec->codec_tag = tag; + ost->enc_ctx->codec_tag = tag; } MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st); if (qscale >= 0) { - st->codec->flags |= CODEC_FLAG_QSCALE; - st->codec->global_quality = FF_QP2LAMBDA * qscale; + ost->enc_ctx->flags |= CODEC_FLAG_QSCALE; + ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale; } if (oc->oformat->flags & AVFMT_GLOBALHEADER) - st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; + ost->enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; av_opt_get_int(o->g->sws_opts, "sws_flags", 0, &ost->sws_flags); @@ -1068,7 +1073,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO); st = ost->st; - video_enc = st->codec; + video_enc = ost->enc_ctx; MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); if (frame_aspect_ratio) @@ -1189,7 +1194,7 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc) ost = new_output_stream(o, oc, AVMEDIA_TYPE_AUDIO); st = ost->st; - audio_enc = st->codec; + audio_enc = ost->enc_ctx; audio_enc->codec_type = AVMEDIA_TYPE_AUDIO; if (!ost->stream_copy) { @@ -1237,13 +1242,11 @@ static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *o static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc) { - AVStream *st; OutputStream *ost; AVCodecContext *subtitle_enc; ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE); - st = ost->st; - subtitle_enc = st->codec; + subtitle_enc = ost->enc_ctx; subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;