+static int init_output_bsfs(OutputStream *ost)
+{
+ AVBSFContext *ctx;
+ int i, ret;
+
+ if (!ost->nb_bitstream_filters)
+ return 0;
+
+ ost->bsf_ctx = av_mallocz_array(ost->nb_bitstream_filters, sizeof(*ost->bsf_ctx));
+ if (!ost->bsf_ctx)
+ return AVERROR(ENOMEM);
+
+ for (i = 0; i < ost->nb_bitstream_filters; i++) {
+ ret = av_bsf_alloc(ost->bitstream_filters[i], &ctx);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error allocating a bitstream filter context\n");
+ return ret;
+ }
+ ost->bsf_ctx[i] = ctx;
+
+ ret = avcodec_parameters_copy(ctx->par_in,
+ i ? ost->bsf_ctx[i - 1]->par_out : ost->st->codecpar);
+ if (ret < 0)
+ return ret;
+
+ ctx->time_base_in = i ? ost->bsf_ctx[i - 1]->time_base_out : ost->st->time_base;
+
+ ret = av_bsf_init(ctx);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n",
+ ost->bitstream_filters[i]->name);
+ return ret;
+ }
+ }
+
+ ctx = ost->bsf_ctx[ost->nb_bitstream_filters - 1];
+ ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out);
+ if (ret < 0)
+ return ret;
+
+ ost->st->time_base = ctx->time_base_out;
+
+ return 0;
+}
+
+static int init_output_stream_streamcopy(OutputStream *ost)
+{
+ OutputFile *of = output_files[ost->file_index];
+ InputStream *ist = get_input_stream(ost);
+ AVCodecParameters *par_dst = ost->st->codecpar;
+ AVCodecParameters *par_src = ist->st->codecpar;
+ AVRational sar;
+ int i;
+ uint64_t extra_size;
+
+ extra_size = (uint64_t)par_src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE;
+ if (extra_size > INT_MAX) {
+ return AVERROR(EINVAL);
+ }
+
+ ost->st->disposition = ist->st->disposition;
+
+ /* if stream_copy is selected, no need to decode or encode */
+ par_dst->codec_id = par_src->codec_id;
+ par_dst->codec_type = par_src->codec_type;
+
+ if (!par_dst->codec_tag) {
+ if (!of->ctx->oformat->codec_tag ||
+ av_codec_get_id (of->ctx->oformat->codec_tag, par_src->codec_tag) == par_dst->codec_id ||
+ av_codec_get_tag(of->ctx->oformat->codec_tag, par_src->codec_id) <= 0)
+ par_dst->codec_tag = par_src->codec_tag;
+ }
+
+ par_dst->bit_rate = par_src->bit_rate;
+ par_dst->field_order = par_src->field_order;
+ par_dst->chroma_location = par_src->chroma_location;
+
+ if (par_src->extradata) {
+ par_dst->extradata = av_mallocz(extra_size);
+ if (!par_dst->extradata) {
+ return AVERROR(ENOMEM);
+ }
+ memcpy(par_dst->extradata, par_src->extradata, par_src->extradata_size);
+ par_dst->extradata_size = par_src->extradata_size;
+ }
+
+ ost->st->time_base = ist->st->time_base;
+
+ if (ist->st->nb_side_data) {
+ ost->st->side_data = av_realloc_array(NULL, ist->st->nb_side_data,
+ sizeof(*ist->st->side_data));
+ if (!ost->st->side_data)
+ return AVERROR(ENOMEM);
+
+ for (i = 0; i < ist->st->nb_side_data; i++) {
+ const AVPacketSideData *sd_src = &ist->st->side_data[i];
+ AVPacketSideData *sd_dst = &ost->st->side_data[i];
+
+ sd_dst->data = av_malloc(sd_src->size);
+ if (!sd_dst->data)
+ return AVERROR(ENOMEM);
+ memcpy(sd_dst->data, sd_src->data, sd_src->size);
+ sd_dst->size = sd_src->size;
+ sd_dst->type = sd_src->type;
+ ost->st->nb_side_data++;
+ }
+ }
+
+ ost->parser = av_parser_init(par_dst->codec_id);
+ ost->parser_avctx = avcodec_alloc_context3(NULL);
+ if (!ost->parser_avctx)
+ return AVERROR(ENOMEM);
+
+ switch (par_dst->codec_type) {
+ case AVMEDIA_TYPE_AUDIO:
+ if (audio_volume != 256) {
+ av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n");
+ exit_program(1);
+ }
+ par_dst->channel_layout = par_src->channel_layout;
+ par_dst->sample_rate = par_src->sample_rate;
+ par_dst->channels = par_src->channels;
+ par_dst->block_align = par_src->block_align;
+ break;
+ case AVMEDIA_TYPE_VIDEO:
+ par_dst->format = par_src->format;
+ par_dst->width = par_src->width;
+ par_dst->height = par_src->height;
+ if (ost->frame_aspect_ratio)
+ sar = av_d2q(ost->frame_aspect_ratio * par_dst->height / par_dst->width, 255);
+ else if (ist->st->sample_aspect_ratio.num)
+ sar = ist->st->sample_aspect_ratio;
+ else
+ sar = par_src->sample_aspect_ratio;
+ ost->st->sample_aspect_ratio = par_dst->sample_aspect_ratio = sar;
+ break;
+ case AVMEDIA_TYPE_SUBTITLE:
+ par_dst->width = par_src->width;
+ par_dst->height = par_src->height;
+ break;
+ case AVMEDIA_TYPE_DATA:
+ case AVMEDIA_TYPE_ATTACHMENT:
+ break;
+ default:
+ abort();
+ }
+
+ return 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) {
+ ost->enc_ctx->subtitle_header = av_malloc(dec->subtitle_header_size);
+ 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);
+
+ if (ost->filter && ost->filter->filter->inputs[0]->hw_frames_ctx) {
+ ost->enc_ctx->hw_frames_ctx = av_buffer_ref(ost->filter->filter->inputs[0]->hw_frames_ctx);
+ if (!ost->enc_ctx->hw_frames_ctx)
+ return AVERROR(ENOMEM);
+ }
+
+ 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;
+ }
+ 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_parameters_from_context(ost->st->codecpar, ost->enc_ctx);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_FATAL,
+ "Error initializing the output stream codec context.\n");
+ exit_program(1);
+ }
+
+ if (ost->enc_ctx->nb_coded_side_data) {
+ int i;
+
+ ost->st->side_data = av_realloc_array(NULL, ost->enc_ctx->nb_coded_side_data,
+ sizeof(*ost->st->side_data));
+ if (!ost->st->side_data)
+ return AVERROR(ENOMEM);
+
+ for (i = 0; i < ost->enc_ctx->nb_coded_side_data; i++) {
+ const AVPacketSideData *sd_src = &ost->enc_ctx->coded_side_data[i];
+ AVPacketSideData *sd_dst = &ost->st->side_data[i];
+
+ sd_dst->data = av_malloc(sd_src->size);
+ if (!sd_dst->data)
+ return AVERROR(ENOMEM);
+ memcpy(sd_dst->data, sd_src->data, sd_src->size);
+ sd_dst->size = sd_src->size;
+ sd_dst->type = sd_src->type;
+ ost->st->nb_side_data++;
+ }
+ }
+
+ ost->st->time_base = ost->enc_ctx->time_base;
+ } else if (ost->stream_copy) {
+ ret = init_output_stream_streamcopy(ost);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * FIXME: will the codec context used by the parser during streamcopy
+ * This should go away with the new parser API.
+ */
+ ret = avcodec_parameters_to_context(ost->parser_avctx, ost->st->codecpar);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* initialize bitstream filters for the output stream
+ * needs to be done here, because the codec id for streamcopy is not
+ * known until now */
+ ret = init_output_bsfs(ost);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+