X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=d0f247ec685c2fa83da4d5f1c12cbdf6364cbd56;hb=3597d32e88c8e0c6e6f25fe73a9ebd235c879c2b;hp=1367920b50db101c098015b23cc59cc83b096953;hpb=d3426fb5921d069cd950e43504b005bfbb1686d2;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index 1367920b50d..d0f247ec685 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -502,22 +502,21 @@ static void ffmpeg_cleanup(int ret) } for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; - AVBitStreamFilterContext *bsfc; if (!ost) continue; - bsfc = ost->bitstream_filters; - while (bsfc) { - AVBitStreamFilterContext *next = bsfc->next; - av_bitstream_filter_close(bsfc); - bsfc = next; - } - ost->bitstream_filters = NULL; + for (j = 0; j < ost->nb_bitstream_filters; j++) + av_bsf_free(&ost->bsf_ctx[j]); + av_freep(&ost->bsf_ctx); + av_freep(&ost->bsf_extradata_updated); + av_frame_free(&ost->filtered_frame); av_frame_free(&ost->last_frame); + av_dict_free(&ost->encoder_opts); av_parser_close(ost->parser); + avcodec_free_context(&ost->parser_avctx); av_freep(&ost->forced_keyframes); av_expr_free(ost->forced_keyframes_pexpr); @@ -530,6 +529,7 @@ static void ffmpeg_cleanup(int ret) av_dict_free(&ost->sws_dict); avcodec_free_context(&ost->enc_ctx); + avcodec_parameters_free(&ost->ref_par); av_freep(&output_streams[i]); } @@ -632,22 +632,13 @@ static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, } } -static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) +static void write_packet(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) { - AVBitStreamFilterContext *bsfc = ost->bitstream_filters; - AVCodecContext *avctx = ost->encoding_needed ? ost->enc_ctx : ost->st->codec; + AVStream *st = ost->st; int ret; - if (!ost->st->codec->extradata_size && ost->enc_ctx->extradata_size) { - ost->st->codec->extradata = av_mallocz(ost->enc_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (ost->st->codec->extradata) { - memcpy(ost->st->codec->extradata, ost->enc_ctx->extradata, ost->enc_ctx->extradata_size); - ost->st->codec->extradata_size = ost->enc_ctx->extradata_size; - } - } - - if ((avctx->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) || - (avctx->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) + if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) || + (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) pkt->pts = pkt->dts = AV_NOPTS_VALUE; /* @@ -657,14 +648,14 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) * Counting encoded video frames needs to be done separately because of * reordering, see do_video_out() */ - if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) { + if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed)) { if (ost->frame_number >= ost->max_frames) { av_packet_unref(pkt); return; } ost->frame_number++; } - if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { int i; uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, NULL); @@ -686,26 +677,6 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) } } - if (bsfc) - av_packet_split_side_data(pkt); - - if ((ret = av_apply_bitstream_filters(avctx, pkt, bsfc)) < 0) { - print_error("", ret); - if (exit_on_error) - exit_program(1); - } - if (pkt->size == 0 && pkt->side_data_elems == 0) - return; - if (!ost->st->codecpar->extradata && avctx->extradata) { - ost->st->codecpar->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!ost->st->codecpar->extradata) { - av_log(NULL, AV_LOG_ERROR, "Could not allocate extradata buffer to copy parser data.\n"); - exit_program(1); - } - ost->st->codecpar->extradata_size = avctx->extradata_size; - memcpy(ost->st->codecpar->extradata, avctx->extradata, avctx->extradata_size); - } - if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { if (pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && @@ -718,29 +689,28 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1) - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1); } - if( - (avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type == AVMEDIA_TYPE_VIDEO) && - pkt->dts != AV_NOPTS_VALUE && - !(avctx->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) && - ost->last_mux_dts != AV_NOPTS_VALUE) { - int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); - if (pkt->dts < max) { - int loglevel = max - pkt->dts > 2 || avctx->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; - av_log(s, loglevel, "Non-monotonous DTS in output stream " - "%d:%d; previous: %"PRId64", current: %"PRId64"; ", - ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); - if (exit_on_error) { - av_log(NULL, AV_LOG_FATAL, "aborting.\n"); - exit_program(1); + if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && + pkt->dts != AV_NOPTS_VALUE && + !(st->codecpar->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) && + ost->last_mux_dts != AV_NOPTS_VALUE) { + int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); + if (pkt->dts < max) { + int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; + av_log(s, loglevel, "Non-monotonous DTS in output stream " + "%d:%d; previous: %"PRId64", current: %"PRId64"; ", + ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); + if (exit_on_error) { + av_log(NULL, AV_LOG_FATAL, "aborting.\n"); + exit_program(1); + } + av_log(s, loglevel, "changing to %"PRId64". This may result " + "in incorrect timestamps in the output file.\n", + max); + if (pkt->pts >= pkt->dts) + pkt->pts = FFMAX(pkt->pts, max); + pkt->dts = max; + } } - av_log(s, loglevel, "changing to %"PRId64". This may result " - "in incorrect timestamps in the output file.\n", - max); - if(pkt->pts >= pkt->dts) - pkt->pts = FFMAX(pkt->pts, max); - pkt->dts = max; - } - } } ost->last_mux_dts = pkt->dts; @@ -779,6 +749,68 @@ static void close_output_stream(OutputStream *ost) } } +static void output_packet(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) +{ + int ret = 0; + + /* apply the output bitstream filters, if any */ + if (ost->nb_bitstream_filters) { + int idx; + + ret = av_bsf_send_packet(ost->bsf_ctx[0], pkt); + if (ret < 0) + goto finish; + + idx = 1; + while (idx) { + /* get a packet from the previous filter up the chain */ + ret = av_bsf_receive_packet(ost->bsf_ctx[idx - 1], pkt); + /* HACK! - aac_adtstoasc updates extradata after filtering the first frame when + * the api states this shouldn't happen after init(). Propagate it here to the + * muxer and to the next filters in the chain to workaround this. + * TODO/FIXME - Make aac_adtstoasc use new packet side data instead of changing + * par_out->extradata and adapt muxers accordingly to get rid of this. */ + if (!(ost->bsf_extradata_updated[idx - 1] & 1)) { + ret = avcodec_parameters_copy(ost->st->codecpar, ost->bsf_ctx[idx - 1]->par_out); + if (ret < 0) + goto finish; + ost->bsf_extradata_updated[idx - 1] |= 1; + } + if (ret == AVERROR(EAGAIN)) { + ret = 0; + idx--; + continue; + } else if (ret < 0) + goto finish; + + /* send it to the next filter down the chain or to the muxer */ + if (idx < ost->nb_bitstream_filters) { + /* HACK/FIXME! - See above */ + if (!(ost->bsf_extradata_updated[idx] & 2)) { + ret = avcodec_parameters_copy(ost->bsf_ctx[idx]->par_out, ost->bsf_ctx[idx - 1]->par_out); + if (ret < 0) + goto finish; + ost->bsf_extradata_updated[idx] |= 2; + } + ret = av_bsf_send_packet(ost->bsf_ctx[idx], pkt); + if (ret < 0) + goto finish; + idx++; + } else + write_packet(s, pkt, ost); + } + } else + write_packet(s, pkt, ost); + +finish: + if (ret < 0 && ret != AVERROR_EOF) { + av_log(NULL, AV_LOG_ERROR, "Error applying bitstream filters to an output " + "packet for stream #%d:%d.\n", ost->file_index, ost->index); + if(exit_on_error) + exit_program(1); + } +} + static int check_recording_time(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; @@ -837,7 +869,7 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base)); } - write_frame(s, &pkt, ost); + output_packet(s, &pkt, ost); } } @@ -921,7 +953,7 @@ static void do_subtitle_out(AVFormatContext *s, pkt.pts += 90 * sub->end_display_time; } pkt.dts = pkt.pts; - write_frame(s, &pkt, ost); + output_packet(s, &pkt, ost); } } @@ -933,7 +965,7 @@ static void do_video_out(AVFormatContext *s, int ret, format_video_sync; AVPacket pkt; AVCodecContext *enc = ost->enc_ctx; - AVCodecContext *mux_enc = ost->st->codec; + AVCodecParameters *mux_par = ost->st->codecpar; int nb_frames, nb0_frames, i; double delta, delta0; double duration = 0; @@ -1094,15 +1126,15 @@ static void do_video_out(AVFormatContext *s, avoid any copies. We support temporarily the older method. */ if (in_picture->interlaced_frame) - mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; + mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; else - mux_enc->field_order = AV_FIELD_PROGRESSIVE; + mux_par->field_order = AV_FIELD_PROGRESSIVE; pkt.data = (uint8_t *)in_picture; pkt.size = sizeof(AVPicture); pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base); pkt.flags |= AV_PKT_FLAG_KEY; - write_frame(s, &pkt, ost); + output_packet(s, &pkt, ost); } else #endif { @@ -1115,11 +1147,11 @@ static void do_video_out(AVFormatContext *s, if (in_picture->interlaced_frame) { if (enc->codec->id == AV_CODEC_ID_MJPEG) - mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; + mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; else - mux_enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; + mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; } else - mux_enc->field_order = AV_FIELD_PROGRESSIVE; + mux_par->field_order = AV_FIELD_PROGRESSIVE; in_picture->quality = enc->global_quality; in_picture->pict_type = 0; @@ -1201,7 +1233,7 @@ static void do_video_out(AVFormatContext *s, } frame_size = pkt.size; - write_frame(s, &pkt, ost); + output_packet(s, &pkt, ost); /* if two pass, output log */ if (ost->logfile && enc->stats_out) { @@ -1763,7 +1795,7 @@ static void flush_encoders(void) } av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); pkt_size = pkt.size; - write_frame(os, &pkt, ost); + output_packet(os, &pkt, ost); if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { do_video_stats(ost, pkt_size); } @@ -1851,7 +1883,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); opkt.dts -= ost_tb_start_time; - if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) { + if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) { int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size); if(!duration) duration = ist->dec_ctx->frame_size; @@ -1863,12 +1895,12 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); 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->st->codecpar->codec_id != AV_CODEC_ID_H264 + && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG1VIDEO + && ost->st->codecpar->codec_id != AV_CODEC_ID_MPEG2VIDEO + && ost->st->codecpar->codec_id != AV_CODEC_ID_VC1 ) { - int ret = av_parser_change(ost->parser, ost->st->codec, + int ret = av_parser_change(ost->parser, ost->parser_avctx, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY); @@ -1889,11 +1921,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p av_copy_packet_side_data(&opkt, pkt); #if FF_API_LAVF_FMT_RAWPICTURE - if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && - ost->st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && + if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + ost->st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO && (of->ctx->oformat->flags & AVFMT_RAWPICTURE)) { /* store AVPicture in AVPacket, as expected by the output format */ - int ret = avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height); + int ret = avpicture_fill(&pict, opkt.data, ost->st->codecpar->format, ost->st->codecpar->width, ost->st->codecpar->height); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "avpicture_fill failed: %s\n", av_err2str(ret)); @@ -1905,7 +1937,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } #endif - write_frame(of->ctx, &opkt, ost); + output_packet(of->ctx, &opkt, ost); } int guess_input_channel_layout(InputStream *ist) @@ -2090,17 +2122,17 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) // The following line may be required in some cases where there is no parser // or the parser does not has_b_frames correctly - if (ist->st->codec->has_b_frames < ist->dec_ctx->has_b_frames) { + if (ist->st->codecpar->video_delay < ist->dec_ctx->has_b_frames) { if (ist->dec_ctx->codec_id == AV_CODEC_ID_H264) { - ist->st->codec->has_b_frames = ist->dec_ctx->has_b_frames; + ist->st->codecpar->video_delay = ist->dec_ctx->has_b_frames; } else av_log(ist->dec_ctx, AV_LOG_WARNING, - "has_b_frames is larger in decoder than demuxer %d > %d.\n" + "video_delay is larger in decoder than demuxer %d > %d.\n" "If you want to help, upload a sample " "of this file to ftp://upload.ffmpeg.org/incoming/ " "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)", ist->dec_ctx->has_b_frames, - ist->st->codec->has_b_frames); + ist->st->codecpar->video_delay); } check_decode_result(ist, got_output, ret); @@ -2561,6 +2593,10 @@ static int init_input_stream(int ist_index, char *error, int error_len) av_dict_set(&ist->decoder_opts, "sub_text_format", "ass", AV_DICT_DONT_OVERWRITE); + /* Useful for subtitles retiming by lavf (FIXME), skipping samples in + * audio, and video decoders such as cuvid or mediacodec */ + av_codec_set_pkt_timebase(ist->dec_ctx, ist->st->time_base); + if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0)) av_dict_set(&ist->decoder_opts, "threads", "auto", 0); if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) { @@ -2594,6 +2630,195 @@ static int compare_int64(const void *a, const void *b) return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b); } +static int init_output_bsfs(OutputStream *ost) +{ + AVBSFContext *ctx; + int i, ret; + + if (!ost->nb_bitstream_filters) + return 0; + + for (i = 0; i < ost->nb_bitstream_filters; i++) { + ctx = ost->bsf_ctx[i]; + + 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->bsf_ctx[i]->filter->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 = ost->ref_par; + AVRational sar; + int i, ret; + uint64_t extra_size; + + av_assert0(ist && !ost->filter); + + avcodec_parameters_to_context(ost->enc_ctx, ist->st->codecpar); + 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; + } + avcodec_parameters_from_context(par_src, ost->enc_ctx); + + extra_size = (uint64_t)par_src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE; + + if (extra_size > INT_MAX) { + return AVERROR(EINVAL); + } + + /* 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) { + unsigned int 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_tag2(of->ctx->oformat->codec_tag, par_src->codec_id, &codec_tag)) + 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_size) { + 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; + } + par_dst->bits_per_coded_sample = par_src->bits_per_coded_sample; + par_dst->bits_per_raw_sample = par_src->bits_per_raw_sample; + + if (!ost->frame_rate.num) + ost->frame_rate = ist->framerate; + ost->st->avg_frame_rate = ost->frame_rate; + + ret = avformat_transfer_internal_stream_timing_info(of->ctx->oformat, ost->st, ist->st, copy_tb); + if (ret < 0) + return ret; + + // copy timebase while removing common factors + ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1}); + + 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); + + ost->st->nb_side_data = 0; + 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[ost->st->nb_side_data]; + + if (ost->rotate_overridden && sd_src->type == AV_PKT_DATA_DISPLAYMATRIX) + continue; + + 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->frame_size = par_src->frame_size; + par_dst->block_align = par_src->block_align; + par_dst->initial_padding = par_src->initial_padding; + par_dst->trailing_padding = par_src->trailing_padding; + par_dst->profile = par_src->profile; + if((par_dst->block_align == 1 || par_dst->block_align == 1152 || par_dst->block_align == 576) && par_dst->codec_id == AV_CODEC_ID_MP3) + par_dst->block_align= 0; + if(par_dst->codec_id == AV_CODEC_ID_AC3) + par_dst->block_align= 0; + break; + case AVMEDIA_TYPE_VIDEO: + par_dst->format = par_src->format; + par_dst->color_space = par_src->color_space; + par_dst->color_range = par_src->color_range; + par_dst->color_primaries = par_src->color_primaries; + par_dst->color_trc = par_src->color_trc; + par_dst->width = par_src->width; + par_dst->height = par_src->height; + par_dst->video_delay = par_src->video_delay; + par_dst->profile = par_src->profile; + if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option + sar = + av_mul_q(ost->frame_aspect_ratio, + (AVRational){ par_dst->height, par_dst->width }); + av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio " + "with stream copy may produce invalid files\n"); + } + 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; + ost->st->avg_frame_rate = ist->st->avg_frame_rate; + ost->st->r_frame_rate = ist->st->r_frame_rate; + break; + case AVMEDIA_TYPE_SUBTITLE: + par_dst->width = par_src->width; + par_dst->height = par_src->height; + break; + case AVMEDIA_TYPE_UNKNOWN: + 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; @@ -2645,12 +2870,18 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len) 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); + 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); } + /* + * FIXME: ost->st->codec should't be needed here anymore. + */ + ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx); + if (ret < 0) + return ret; if (ost->enc_ctx->nb_coded_side_data) { int i; @@ -2677,17 +2908,27 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len) // 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->st->codec, &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}); + } 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; } @@ -2763,7 +3004,7 @@ static void report_new_stream(int input_index, AVPacket *pkt) return; av_log(file->ctx, AV_LOG_WARNING, "New %s stream %d:%d at pos:%"PRId64" and DTS:%ss\n", - av_get_media_type_string(st->codec->codec_type), + av_get_media_type_string(st->codecpar->codec_type), input_index, pkt->stream_index, pkt->pos, av_ts2timestr(pkt->dts, &st->time_base)); file->nb_streams_warn = pkt->stream_index + 1; @@ -2844,8 +3085,6 @@ static int transcode_init(void) /* for each output stream, we compute the right encoding parameters */ for (i = 0; i < nb_output_streams; i++) { - AVCodecContext *enc_ctx; - AVCodecContext *dec_ctx = NULL; ost = output_streams[i]; oc = output_files[ost->file_index]->ctx; ist = get_input_stream(ost); @@ -2853,212 +3092,32 @@ static int transcode_init(void) if (ost->attachment_filename) continue; - enc_ctx = ost->stream_copy ? ost->st->codec : ost->enc_ctx; - if (ist) { - dec_ctx = ist->dec_ctx; - ost->st->disposition = ist->st->disposition; - enc_ctx->bits_per_raw_sample = dec_ctx->bits_per_raw_sample; - enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; } else { for (j=0; jnb_streams; j++) { AVStream *st = oc->streams[j]; - if (st != ost->st && st->codec->codec_type == enc_ctx->codec_type) + if (st != ost->st && st->codecpar->codec_type == ost->st->codecpar->codec_type) break; } if (j == oc->nb_streams) - if (enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO || enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) + if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || + ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) ost->st->disposition = AV_DISPOSITION_DEFAULT; } - if (ost->stream_copy) { - AVRational sar; - uint64_t extra_size; - - av_assert0(ist && !ost->filter); - - extra_size = (uint64_t)dec_ctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE; - - if (extra_size > INT_MAX) { - return AVERROR(EINVAL); - } - - /* if stream_copy is selected, no need to decode or encode */ - enc_ctx->codec_id = dec_ctx->codec_id; - enc_ctx->codec_type = dec_ctx->codec_type; - - if (!enc_ctx->codec_tag) { - unsigned int codec_tag; - if (!oc->oformat->codec_tag || - av_codec_get_id (oc->oformat->codec_tag, dec_ctx->codec_tag) == enc_ctx->codec_id || - !av_codec_get_tag2(oc->oformat->codec_tag, dec_ctx->codec_id, &codec_tag)) - enc_ctx->codec_tag = dec_ctx->codec_tag; - } - - enc_ctx->bit_rate = dec_ctx->bit_rate; - enc_ctx->rc_max_rate = dec_ctx->rc_max_rate; - enc_ctx->rc_buffer_size = dec_ctx->rc_buffer_size; - enc_ctx->field_order = dec_ctx->field_order; - if (dec_ctx->extradata_size) { - enc_ctx->extradata = av_mallocz(extra_size); - if (!enc_ctx->extradata) { - return AVERROR(ENOMEM); - } - memcpy(enc_ctx->extradata, dec_ctx->extradata, dec_ctx->extradata_size); - } - enc_ctx->extradata_size= dec_ctx->extradata_size; - enc_ctx->bits_per_coded_sample = dec_ctx->bits_per_coded_sample; - - enc_ctx->time_base = ist->st->time_base; - /* - * Avi is a special case here because it supports variable fps but - * having the fps and timebase differe significantly adds quite some - * overhead - */ - if(!strcmp(oc->oformat->name, "avi")) { - if ( copy_tb<0 && ist->st->r_frame_rate.num - && av_q2d(ist->st->r_frame_rate) >= av_q2d(ist->st->avg_frame_rate) - && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(ist->st->time_base) - && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(dec_ctx->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500 - || copy_tb==2){ - enc_ctx->time_base.num = ist->st->r_frame_rate.den; - enc_ctx->time_base.den = 2*ist->st->r_frame_rate.num; - enc_ctx->ticks_per_frame = 2; - } else if ( copy_tb<0 && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->st->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 - || copy_tb==0){ - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - enc_ctx->time_base.den *= 2; - enc_ctx->ticks_per_frame = 2; - } - } else if(!(oc->oformat->flags & AVFMT_VARIABLE_FPS) - && strcmp(oc->oformat->name, "mov") && strcmp(oc->oformat->name, "mp4") && strcmp(oc->oformat->name, "3gp") - && strcmp(oc->oformat->name, "3g2") && strcmp(oc->oformat->name, "psp") && strcmp(oc->oformat->name, "ipod") - && strcmp(oc->oformat->name, "f4v") - ) { - if( copy_tb<0 && dec_ctx->time_base.den - && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->st->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 - || copy_tb==0){ - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - } - } - if ( enc_ctx->codec_tag == AV_RL32("tmcd") - && dec_ctx->time_base.num < dec_ctx->time_base.den - && dec_ctx->time_base.num > 0 - && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) { - enc_ctx->time_base = dec_ctx->time_base; - } - - if (!ost->frame_rate.num) - ost->frame_rate = ist->framerate; - if(ost->frame_rate.num) - enc_ctx->time_base = av_inv_q(ost->frame_rate); + if (!ost->stream_copy) { + AVCodecContext *enc_ctx = ost->enc_ctx; + AVCodecContext *dec_ctx = NULL; - av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, - enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX); + set_encoder_id(output_files[ost->file_index], ost); - 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); + if (ist) { + dec_ctx = ist->dec_ctx; - ost->st->nb_side_data = 0; - for (j = 0; j < ist->st->nb_side_data; j++) { - const AVPacketSideData *sd_src = &ist->st->side_data[j]; - AVPacketSideData *sd_dst = &ost->st->side_data[ost->st->nb_side_data]; - - if (ost->rotate_overridden && sd_src->type == AV_PKT_DATA_DISPLAYMATRIX) - continue; - - 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++; - } + enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; } - ost->parser = av_parser_init(enc_ctx->codec_id); - - switch (enc_ctx->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); - } - enc_ctx->channel_layout = dec_ctx->channel_layout; - enc_ctx->sample_rate = dec_ctx->sample_rate; - enc_ctx->channels = dec_ctx->channels; - enc_ctx->frame_size = dec_ctx->frame_size; - enc_ctx->audio_service_type = dec_ctx->audio_service_type; - enc_ctx->block_align = dec_ctx->block_align; - enc_ctx->initial_padding = dec_ctx->delay; - enc_ctx->profile = dec_ctx->profile; -#if FF_API_AUDIOENC_DELAY - enc_ctx->delay = dec_ctx->delay; -#endif - if((enc_ctx->block_align == 1 || enc_ctx->block_align == 1152 || enc_ctx->block_align == 576) && enc_ctx->codec_id == AV_CODEC_ID_MP3) - enc_ctx->block_align= 0; - if(enc_ctx->codec_id == AV_CODEC_ID_AC3) - enc_ctx->block_align= 0; - break; - case AVMEDIA_TYPE_VIDEO: - enc_ctx->pix_fmt = dec_ctx->pix_fmt; - enc_ctx->colorspace = dec_ctx->colorspace; - enc_ctx->color_range = dec_ctx->color_range; - enc_ctx->color_primaries = dec_ctx->color_primaries; - enc_ctx->color_trc = dec_ctx->color_trc; - enc_ctx->width = dec_ctx->width; - enc_ctx->height = dec_ctx->height; - enc_ctx->has_b_frames = dec_ctx->has_b_frames; - enc_ctx->profile = dec_ctx->profile; - if (ost->frame_aspect_ratio.num) { // overridden by the -aspect cli option - sar = - av_mul_q(ost->frame_aspect_ratio, - (AVRational){ enc_ctx->height, enc_ctx->width }); - av_log(NULL, AV_LOG_WARNING, "Overriding aspect ratio " - "with stream copy may produce invalid files\n"); - } - else if (ist->st->sample_aspect_ratio.num) - sar = ist->st->sample_aspect_ratio; - else - sar = dec_ctx->sample_aspect_ratio; - ost->st->sample_aspect_ratio = enc_ctx->sample_aspect_ratio = sar; - ost->st->avg_frame_rate = ist->st->avg_frame_rate; - ost->st->r_frame_rate = ist->st->r_frame_rate; - break; - case AVMEDIA_TYPE_SUBTITLE: - enc_ctx->width = dec_ctx->width; - enc_ctx->height = dec_ctx->height; - break; - case AVMEDIA_TYPE_UNKNOWN: - case AVMEDIA_TYPE_DATA: - case AVMEDIA_TYPE_ATTACHMENT: - break; - default: - abort(); - } - } else { - if (!ost->enc) - ost->enc = avcodec_find_encoder(enc_ctx->codec_id); - if (!ost->enc) { - /* should only happen when a default codec is not present. */ - snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d", - avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index); - ret = AVERROR(EINVAL); - goto dump_format; - } - - set_encoder_id(output_files[ost->file_index], ost); - #if CONFIG_LIBMFX if (qsv_transcode_init(ost)) exit_program(1); @@ -3069,11 +3128,10 @@ static int transcode_init(void) exit_program(1); #endif - if (!ost->filter && - (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO || - enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) { - FilterGraph *fg; - fg = init_simple_filtergraph(ist, ost); + 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); @@ -3111,6 +3169,9 @@ static int transcode_init(void) switch (enc_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format; + if (dec_ctx) + enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, + av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); 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 = avfilter_link_get_channels(ost->filter->filter->inputs[0]); @@ -3151,6 +3212,9 @@ static int transcode_init(void) "Use -pix_fmt yuv420p for compatibility with outdated media players.\n", av_get_pix_fmt_name(ost->filter->filter->inputs[0]->format)); enc_ctx->pix_fmt = ost->filter->filter->inputs[0]->format; + if (dec_ctx) + enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, + av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); ost->st->avg_frame_rate = ost->frame_rate; @@ -3185,8 +3249,8 @@ static int transcode_init(void) case AVMEDIA_TYPE_SUBTITLE: enc_ctx->time_base = (AVRational){1, 1000}; if (!enc_ctx->width) { - enc_ctx->width = input_streams[ost->source_index]->st->codec->width; - enc_ctx->height = input_streams[ost->source_index]->st->codec->height; + enc_ctx->width = input_streams[ost->source_index]->st->codecpar->width; + enc_ctx->height = input_streams[ost->source_index]->st->codecpar->height; } break; case AVMEDIA_TYPE_DATA: @@ -3293,7 +3357,7 @@ static int transcode_init(void) ist = input_streams[i]; for (j = 0; j < ist->nb_filters; j++) { - if (ist->filters[j]->graph->graph_desc) { + if (!filtergraph_is_simple(ist->filters[j]->graph)) { av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s", ist->file_index, ist->st->index, ist->dec ? ist->dec->name : "?", ist->filters[j]->name); @@ -3314,7 +3378,7 @@ static int transcode_init(void) continue; } - if (ost->filter && ost->filter->graph->graph_desc) { + if (ost->filter && !filtergraph_is_simple(ost->filter->graph)) { /* output from a complex graph */ av_log(NULL, AV_LOG_INFO, " %s", ost->filter->name); if (nb_filtergraphs > 1) @@ -3806,6 +3870,10 @@ static int process_input(int file_index) if ((ret = seek_to_start(ifile, is)) < 0) return ret; ret = get_input_packet(ifile, &pkt); + if (ret == AVERROR(EAGAIN)) { + ifile->eagain = 1; + return ret; + } } if (ret < 0) { if (ret != AVERROR_EOF) { @@ -4304,6 +4372,8 @@ int main(int argc, char **argv) int ret; int64_t ti; + init_dynload(); + register_exit(ffmpeg_cleanup); setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */