X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=avconv.c;h=7351b7757f5cc4e269a4c2c69ddba1d4bab5012b;hb=c3386bd5b4d3662f94e902a0fe3e9e869e29967d;hp=0b703edd3c87f28c591b0ec2433a8589d39f8b85;hpb=11d1ca4b2c406bee2d22b04268a43b0873096c92;p=ffmpeg diff --git a/avconv.c b/avconv.c index 0b703edd3c8..7351b7757f5 100644 --- a/avconv.c +++ b/avconv.c @@ -32,10 +32,9 @@ #include "libswscale/swscale.h" #include "libavresample/avresample.h" #include "libavutil/opt.h" -#include "libavutil/audioconvert.h" +#include "libavutil/channel_layout.h" #include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" -#include "libavutil/colorspace.h" #include "libavutil/fifo.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" @@ -48,11 +47,11 @@ #include "libavformat/os_support.h" # include "libavfilter/avfilter.h" -# include "libavfilter/avfiltergraph.h" # include "libavfilter/buffersrc.h" # include "libavfilter/buffersink.h" #if HAVE_SYS_RESOURCE_H +#include #include #include #elif HAVE_GETPROCESSTIMES @@ -143,7 +142,7 @@ static int decode_interrupt_cb(void *ctx) const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; -void exit_program(int ret) +static void avconv_cleanup(int ret) { int i, j; @@ -159,6 +158,7 @@ void exit_program(int ret) av_freep(&filtergraphs[i]->outputs[j]); } av_freep(&filtergraphs[i]->outputs); + av_freep(&filtergraphs[i]->graph_desc); av_freep(&filtergraphs[i]); } av_freep(&filtergraphs); @@ -166,7 +166,7 @@ void exit_program(int ret) /* close files */ for (i = 0; i < nb_output_files; i++) { AVFormatContext *s = output_files[i]->ctx; - if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) + if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_close(s->pb); avformat_free_context(s); av_dict_free(&output_files[i]->opts); @@ -192,9 +192,9 @@ void exit_program(int ret) av_freep(&input_files[i]); } for (i = 0; i < nb_input_streams; i++) { - avcodec_free_frame(&input_streams[i]->decoded_frame); + av_frame_free(&input_streams[i]->decoded_frame); + av_frame_free(&input_streams[i]->filter_frame); av_dict_free(&input_streams[i]->opts); - free_buffer_pool(&input_streams[i]->buffer_pool); av_freep(&input_streams[i]->filters); av_freep(&input_streams[i]); } @@ -210,7 +210,6 @@ void exit_program(int ret) uninit_opts(); - avfilter_uninit(); avformat_network_deinit(); if (received_sigterm) { @@ -218,8 +217,6 @@ void exit_program(int ret) (int) received_sigterm); exit (255); } - - exit(ret); } void assert_avoptions(AVDictionary *m) @@ -231,24 +228,21 @@ void assert_avoptions(AVDictionary *m) } } -static void assert_codec_experimental(AVCodecContext *c, int encoder) +static void abort_codec_experimental(AVCodec *c, int encoder) { const char *codec_string = encoder ? "encoder" : "decoder"; AVCodec *codec; - if (c->codec->capabilities & CODEC_CAP_EXPERIMENTAL && - c->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - av_log(NULL, AV_LOG_FATAL, "%s '%s' is experimental and might produce bad " - "results.\nAdd '-strict experimental' if you want to use it.\n", - codec_string, c->codec->name); - codec = encoder ? avcodec_find_encoder(c->codec->id) : avcodec_find_decoder(c->codec->id); - if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL)) - av_log(NULL, AV_LOG_FATAL, "Or use the non experimental %s '%s'.\n", - codec_string, codec->name); - exit_program(1); - } + av_log(NULL, AV_LOG_FATAL, "%s '%s' is experimental and might produce bad " + "results.\nAdd '-strict experimental' if you want to use it.\n", + codec_string, c->name); + codec = encoder ? avcodec_find_encoder(c->id) : avcodec_find_decoder(c->id); + if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL)) + av_log(NULL, AV_LOG_FATAL, "Or use the non experimental %s '%s'.\n", + codec_string, codec->name); + exit_program(1); } -/** +/* * Update the requested input sample format based on the output sample format. * This is currently only used to request float output from decoders which * support multiple sample formats, one of which is AV_SAMPLE_FMT_FLT. @@ -269,22 +263,41 @@ static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec, dec_codec->sample_fmts[0] != AV_SAMPLE_FMT_NONE && dec_codec->sample_fmts[1] != AV_SAMPLE_FMT_NONE) { const enum AVSampleFormat *p; - int min_dec = -1, min_inc = -1; + int min_dec = INT_MAX, min_inc = INT_MAX; + enum AVSampleFormat dec_fmt = AV_SAMPLE_FMT_NONE; + enum AVSampleFormat inc_fmt = AV_SAMPLE_FMT_NONE; /* find a matching sample format in the encoder */ for (p = dec_codec->sample_fmts; *p != AV_SAMPLE_FMT_NONE; p++) { if (*p == enc->sample_fmt) { dec->request_sample_fmt = *p; return; - } else if (*p > enc->sample_fmt) { - min_inc = FFMIN(min_inc, *p - enc->sample_fmt); - } else - min_dec = FFMIN(min_dec, enc->sample_fmt - *p); + } else { + enum AVSampleFormat dfmt = av_get_packed_sample_fmt(*p); + enum AVSampleFormat efmt = av_get_packed_sample_fmt(enc->sample_fmt); + int fmt_diff = 32 * abs(dfmt - efmt); + if (av_sample_fmt_is_planar(*p) != + av_sample_fmt_is_planar(enc->sample_fmt)) + fmt_diff++; + if (dfmt == efmt) { + min_inc = fmt_diff; + inc_fmt = *p; + } else if (dfmt > efmt) { + if (fmt_diff < min_inc) { + min_inc = fmt_diff; + inc_fmt = *p; + } + } else { + if (fmt_diff < min_dec) { + min_dec = fmt_diff; + dec_fmt = *p; + } + } + } } /* if none match, provide the one that matches quality closest */ - dec->request_sample_fmt = min_inc > 0 ? enc->sample_fmt + min_inc : - enc->sample_fmt - min_dec; + dec->request_sample_fmt = min_inc != INT_MAX ? inc_fmt : dec_fmt; } } @@ -317,7 +330,10 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) pkt->flags & AV_PKT_FLAG_KEY); if (a > 0) { av_free_packet(pkt); - new_pkt.destruct = av_destruct_packet; + new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size, + av_buffer_default_free, NULL, 0); + if (!new_pkt.buf) + exit_program(1); } else if (a < 0) { av_log(NULL, AV_LOG_ERROR, "%s failed for stream %d, codec %s", bsfc->filter->name, pkt->stream_index, @@ -331,6 +347,25 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) bsfc = bsfc->next; } + if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS) && + ost->last_mux_dts != AV_NOPTS_VALUE && + pkt->dts < ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT)) { + av_log(NULL, AV_LOG_WARNING, "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(NULL, AV_LOG_WARNING, "changing to %"PRId64". This may result " + "in incorrect timestamps in the output file.\n", + ost->last_mux_dts + 1); + pkt->dts = ost->last_mux_dts + 1; + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts = FFMAX(pkt->pts, pkt->dts); + } + ost->last_mux_dts = pkt->dts; + pkt->stream_index = ost->index; ret = av_interleaved_write_frame(s, pkt); if (ret < 0) { @@ -363,9 +398,6 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, pkt.data = NULL; pkt.size = 0; - if (!check_recording_time(ost)) - return; - if (frame->pts == AV_NOPTS_VALUE || audio_sync_method < 0) frame->pts = ost->sync_opts; ost->sync_opts = frame->pts + frame->nb_samples; @@ -389,45 +421,6 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost, } } -static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void **bufp) -{ - AVCodecContext *dec; - AVPicture *picture2; - AVPicture picture_tmp; - uint8_t *buf = 0; - - dec = ist->st->codec; - - /* deinterlace : must be done before any resize */ - if (do_deinterlace) { - int size; - - /* create temporary picture */ - size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height); - buf = av_malloc(size); - if (!buf) - return; - - picture2 = &picture_tmp; - avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height); - - if (avpicture_deinterlace(picture2, picture, - dec->pix_fmt, dec->width, dec->height) < 0) { - /* if error, do not deinterlace */ - av_log(NULL, AV_LOG_WARNING, "Deinterlacing failed\n"); - av_free(buf); - buf = NULL; - picture2 = picture; - } - } else { - picture2 = picture; - } - - if (picture != picture2) - *picture = *picture2; - *bufp = buf; -} - static void do_subtitle_out(AVFormatContext *s, OutputStream *ost, InputStream *ist, @@ -497,7 +490,7 @@ static void do_subtitle_out(AVFormatContext *s, static void do_video_out(AVFormatContext *s, OutputStream *ost, AVFrame *in_picture, - int *frame_size, float quality) + int *frame_size) { int ret, format_video_sync; AVPacket pkt; @@ -530,8 +523,7 @@ static void do_video_out(AVFormatContext *s, pkt.data = NULL; pkt.size = 0; - if (!check_recording_time(ost) || - ost->frame_number >= ost->max_frames) + if (ost->frame_number >= ost->max_frames) return; if (s->oformat->flags & AVFMT_RAWPICTURE && @@ -549,30 +541,20 @@ static void do_video_out(AVFormatContext *s, write_frame(s, &pkt, ost); } else { int got_packet; - AVFrame big_picture; - - big_picture = *in_picture; - /* better than nothing: use input picture interlaced - settings */ - big_picture.interlaced_frame = in_picture->interlaced_frame; - if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) { - if (ost->top_field_first == -1) - big_picture.top_field_first = in_picture->top_field_first; - else - big_picture.top_field_first = !!ost->top_field_first; - } - /* handles same_quant here. This is not correct because it may - not be a global option */ - big_picture.quality = quality; + if (ost->st->codec->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; if (!enc->me_threshold) - big_picture.pict_type = 0; + in_picture->pict_type = 0; if (ost->forced_kf_index < ost->forced_kf_count && - big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) { - big_picture.pict_type = AV_PICTURE_TYPE_I; + in_picture->pts >= ost->forced_kf_pts[ost->forced_kf_index]) { + in_picture->pict_type = AV_PICTURE_TYPE_I; ost->forced_kf_index++; } - ret = avcodec_encode_video2(enc, &pkt, &big_picture, &got_packet); + ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); exit_program(1); @@ -608,8 +590,7 @@ static double psnr(double d) return -10.0 * log(d) / log(10.0); } -static void do_video_stats(AVFormatContext *os, OutputStream *ost, - int frame_size) +static void do_video_stats(OutputStream *ost, int frame_size) { AVCodecContext *enc; int frame_number; @@ -645,13 +626,12 @@ static void do_video_stats(AVFormatContext *os, OutputStream *ost, } } -/** +/* * Read one frame for lavfi output for ost and encode it. */ static int poll_filter(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; - AVFilterBufferRef *picref; AVFrame *filtered_frame = NULL; int frame_size, ret; @@ -663,39 +643,32 @@ static int poll_filter(OutputStream *ost) if (ost->enc->type == AVMEDIA_TYPE_AUDIO && !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) - ret = av_buffersink_read_samples(ost->filter->filter, &picref, + ret = av_buffersink_get_samples(ost->filter->filter, filtered_frame, ost->st->codec->frame_size); else - ret = av_buffersink_read(ost->filter->filter, &picref); + ret = av_buffersink_get_frame(ost->filter->filter, filtered_frame); if (ret < 0) return ret; - avfilter_copy_buf_props(filtered_frame, picref); - if (picref->pts != AV_NOPTS_VALUE) { - filtered_frame->pts = av_rescale_q(picref->pts, + if (filtered_frame->pts != AV_NOPTS_VALUE) { + 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) - - av_rescale_q(of->start_time, + av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->codec->time_base); - - if (of->start_time && filtered_frame->pts < 0) { - avfilter_unref_buffer(picref); - return 0; - } } switch (ost->filter->filter->inputs[0]->type) { case AVMEDIA_TYPE_VIDEO: if (!ost->frame_aspect_ratio) - ost->st->codec->sample_aspect_ratio = picref->video->pixel_aspect; + ost->st->codec->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; - do_video_out(of->ctx, ost, filtered_frame, &frame_size, - same_quant ? ost->last_quality : - ost->st->codec->global_quality); + do_video_out(of->ctx, ost, filtered_frame, &frame_size); if (vstats_filename && frame_size) - do_video_stats(of->ctx, ost, frame_size); + do_video_stats(ost, frame_size); break; case AVMEDIA_TYPE_AUDIO: do_audio_out(of->ctx, ost, filtered_frame); @@ -705,12 +678,12 @@ static int poll_filter(OutputStream *ost) av_assert0(0); } - avfilter_unref_buffer(picref); + av_frame_unref(filtered_frame); return 0; } -/** +/* * Read as many frames from possible from lavfi and encode them. * * Always read from the active stream with the lowest timestamp. If no frames @@ -796,8 +769,15 @@ static void print_report(int is_last_report, int64_t timer_start) oc = output_files[0]->ctx; total_size = avio_size(oc->pb); - if (total_size < 0) // FIXME improve avio_size() so it works with non seekable output too + if (total_size <= 0) // FIXME improve avio_size() so it works with non seekable output too total_size = avio_tell(oc->pb); + if (total_size < 0) { + char errbuf[128]; + av_strerror(total_size, errbuf, sizeof(errbuf)); + av_log(NULL, AV_LOG_VERBOSE, "Bitrate not available, " + "avio_tell() failed: %s\n", errbuf); + total_size = 0; + } buf[0] = '\0'; ti1 = 1e10; @@ -947,6 +927,8 @@ static void flush_encoders(void) pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base); if (pkt.dts != AV_NOPTS_VALUE) pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base); + if (pkt.duration > 0) + pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base); write_frame(os, &pkt, ost); } @@ -967,7 +949,7 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) if (ost->source_index != ist_index) return 0; - if (of->start_time && ist->last_dts < of->start_time) + if (of->start_time != AV_NOPTS_VALUE && ist->last_dts < of->start_time) return 0; return 1; @@ -976,7 +958,9 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt) { OutputFile *of = output_files[ost->file_index]; - int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); + InputFile *f = input_files [ist->file_index]; + int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; + int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base); AVPacket opkt; av_init_packet(&opkt); @@ -986,11 +970,21 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p return; if (of->recording_time != INT64_MAX && - ist->last_dts >= of->recording_time + of->start_time) { + ist->last_dts >= of->recording_time + start_time) { ost->finished = 1; return; } + if (f->recording_time != INT64_MAX) { + start_time = f->ctx->start_time; + if (f->start_time != AV_NOPTS_VALUE) + start_time += f->start_time; + if (ist->last_dts >= f->recording_time + start_time) { + ost->finished = 1; + return; + } + } + /* force the input stream PTS */ if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) audio_size += pkt->size; @@ -1019,8 +1013,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p && ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO && ost->st->codec->codec_id != AV_CODEC_ID_VC1 ) { - if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY)) - opkt.destruct = av_destruct_packet; + if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY)) { + opkt.buf = av_buffer_create(opkt.data, opkt.size, av_buffer_default_free, NULL, 0); + if (!opkt.buf) + exit_program(1); + } } else { opkt.data = pkt->data; opkt.size = pkt->size; @@ -1028,17 +1025,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p write_frame(of->ctx, &opkt, ost); ost->st->codec->frame_number++; - av_free_packet(&opkt); -} - -static void rate_emu_sleep(InputStream *ist) -{ - if (input_files[ist->file_index]->rate_emu) { - int64_t pts = av_rescale(ist->last_dts, 1000000, AV_TIME_BASE); - int64_t now = av_gettime() - ist->start; - if (pts > now) - av_usleep(pts - now); - } } int guess_input_channel_layout(InputStream *ist) @@ -1061,22 +1047,21 @@ int guess_input_channel_layout(InputStream *ist) static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) { - AVFrame *decoded_frame; + AVFrame *decoded_frame, *f; AVCodecContext *avctx = ist->st->codec; - int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt); - int i, ret, resample_changed; + int i, ret, err = 0, resample_changed; if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame())) return AVERROR(ENOMEM); - else - avcodec_get_frame_defaults(ist->decoded_frame); + if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) + return AVERROR(ENOMEM); decoded_frame = ist->decoded_frame; ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt); if (!*got_output || ret < 0) { if (!pkt->size) { for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_buffer(ist->filters[i]->filter, NULL); + av_buffersrc_add_frame(ist->filters[i]->filter, NULL); } return ret; } @@ -1090,66 +1075,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) pkt->pts = AV_NOPTS_VALUE; } - // preprocess audio (volume) - if (audio_volume != 256) { - int decoded_data_size = decoded_frame->nb_samples * avctx->channels * bps; - void *samples = decoded_frame->data[0]; - switch (avctx->sample_fmt) { - case AV_SAMPLE_FMT_U8: - { - uint8_t *volp = samples; - for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { - int v = (((*volp - 128) * audio_volume + 128) >> 8) + 128; - *volp++ = av_clip_uint8(v); - } - break; - } - case AV_SAMPLE_FMT_S16: - { - int16_t *volp = samples; - for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { - int v = ((*volp) * audio_volume + 128) >> 8; - *volp++ = av_clip_int16(v); - } - break; - } - case AV_SAMPLE_FMT_S32: - { - int32_t *volp = samples; - for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { - int64_t v = (((int64_t)*volp * audio_volume + 128) >> 8); - *volp++ = av_clipl_int32(v); - } - break; - } - case AV_SAMPLE_FMT_FLT: - { - float *volp = samples; - float scale = audio_volume / 256.f; - for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { - *volp++ *= scale; - } - break; - } - case AV_SAMPLE_FMT_DBL: - { - double *volp = samples; - double scale = audio_volume / 256.; - for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) { - *volp++ *= scale; - } - break; - } - default: - av_log(NULL, AV_LOG_FATAL, - "Audio volume adjustment on sample format %s is not supported.\n", - av_get_sample_fmt_name(ist->st->codec->sample_fmt)); - exit_program(1); - } - } - - rate_emu_sleep(ist); - resample_changed = ist->resample_sample_fmt != decoded_frame->format || ist->resample_channels != avctx->channels || ist->resample_channel_layout != decoded_frame->channel_layout || @@ -1195,23 +1120,35 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) decoded_frame->pts = av_rescale_q(decoded_frame->pts, ist->st->time_base, (AVRational){1, ist->st->codec->sample_rate}); - for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_write_frame(ist->filters[i]->filter, decoded_frame); + for (i = 0; i < ist->nb_filters; i++) { + if (i < ist->nb_filters - 1) { + f = ist->filter_frame; + err = av_frame_ref(f, decoded_frame); + if (err < 0) + break; + } else + f = decoded_frame; - return ret; + err = av_buffersrc_add_frame(ist->filters[i]->filter, f); + if (err < 0) + break; + } + + av_frame_unref(ist->filter_frame); + av_frame_unref(decoded_frame); + return err < 0 ? err : ret; } static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) { - AVFrame *decoded_frame; + AVFrame *decoded_frame, *f; void *buffer_to_free = NULL; - int i, ret = 0, resample_changed; - float quality; + int i, ret = 0, err = 0, resample_changed; - if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame())) + if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) + return AVERROR(ENOMEM); + if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) return AVERROR(ENOMEM); - else - avcodec_get_frame_defaults(ist->decoded_frame); decoded_frame = ist->decoded_frame; ret = avcodec_decode_video2(ist->st->codec, @@ -1219,18 +1156,14 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) if (!*got_output || ret < 0) { if (!pkt->size) { for (i = 0; i < ist->nb_filters; i++) - av_buffersrc_buffer(ist->filters[i]->filter, NULL); + av_buffersrc_add_frame(ist->filters[i]->filter, NULL); } return ret; } - quality = same_quant ? decoded_frame->quality : 0; decoded_frame->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts, decoded_frame->pkt_dts); pkt->size = 0; - pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free); - - rate_emu_sleep(ist); if (ist->st->sample_aspect_ratio.num) decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio; @@ -1262,30 +1195,23 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) } for (i = 0; i < ist->nb_filters; i++) { - // XXX what an ugly hack - if (ist->filters[i]->graph->nb_outputs == 1) - ist->filters[i]->graph->outputs[0]->ost->last_quality = quality; - - if (ist->st->codec->codec->capabilities & CODEC_CAP_DR1) { - FrameBuffer *buf = decoded_frame->opaque; - AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays( - decoded_frame->data, decoded_frame->linesize, - AV_PERM_READ | AV_PERM_PRESERVE, - ist->st->codec->width, ist->st->codec->height, - ist->st->codec->pix_fmt); - - avfilter_copy_frame_props(fb, decoded_frame); - fb->buf->priv = buf; - fb->buf->free = filter_release_buffer; - - buf->refcount++; - av_buffersrc_buffer(ist->filters[i]->filter, fb); + if (i < ist->nb_filters - 1) { + f = ist->filter_frame; + err = av_frame_ref(f, decoded_frame); + if (err < 0) + break; } else - av_buffersrc_write_frame(ist->filters[i]->filter, decoded_frame); + f = decoded_frame; + + err = av_buffersrc_add_frame(ist->filters[i]->filter, f); + if (err < 0) + break; } + av_frame_unref(ist->filter_frame); + av_frame_unref(decoded_frame); av_free(buffer_to_free); - return ret; + return err < 0 ? err : ret; } static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) @@ -1298,8 +1224,6 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) if (!*got_output) return ret; - rate_emu_sleep(ist); - for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; @@ -1387,7 +1311,6 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) /* handle stream copy */ if (!ist->decoding_needed) { - rate_emu_sleep(ist); ist->last_dts = ist->next_dts; switch (ist->st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -1418,7 +1341,7 @@ static int output_packet(InputStream *ist, const AVPacket *pkt) static void print_sdp(void) { - char sdp[2048]; + char sdp[16384]; int i; AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files); @@ -1435,7 +1358,7 @@ static void print_sdp(void) static int init_input_stream(int ist_index, char *error, int error_len) { - int i; + int i, ret; InputStream *ist = input_streams[ist_index]; if (ist->decoding_needed) { AVCodec *codec = ist->dec; @@ -1455,20 +1378,23 @@ static int init_input_stream(int ist_index, char *error, int error_len) } } - if (codec->type == AVMEDIA_TYPE_VIDEO && codec->capabilities & CODEC_CAP_DR1) { - ist->st->codec->get_buffer = codec_get_buffer; - ist->st->codec->release_buffer = codec_release_buffer; - ist->st->codec->opaque = &ist->buffer_pool; - } + av_opt_set_int(ist->st->codec, "refcounted_frames", 1, 0); if (!av_dict_get(ist->opts, "threads", NULL, 0)) av_dict_set(&ist->opts, "threads", "auto", 0); - if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) { - snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d", - ist->file_index, ist->st->index); - return AVERROR(EINVAL); + if ((ret = avcodec_open2(ist->st->codec, codec, &ist->opts)) < 0) { + char errbuf[128]; + if (ret == AVERROR_EXPERIMENTAL) + abort_codec_experimental(codec, 0); + + av_strerror(ret, errbuf, sizeof(errbuf)); + + snprintf(error, error_len, + "Error while opening decoder for input stream " + "#%d:%d : %s", + ist->file_index, ist->st->index, errbuf); + return ret; } - assert_codec_experimental(ist->st->codec, 0); assert_avoptions(ist->opts); } @@ -1582,6 +1508,7 @@ static int transcode_init(void) } if (ost->stream_copy) { + AVRational sar; uint64_t extra_size; av_assert0(ist && !ost->filter); @@ -1639,13 +1566,13 @@ static int transcode_init(void) codec->width = icodec->width; codec->height = icodec->height; codec->has_b_frames = icodec->has_b_frames; - if (!codec->sample_aspect_ratio.num) { - codec->sample_aspect_ratio = - ost->st->sample_aspect_ratio = - ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio : - ist->st->codec->sample_aspect_ratio.num ? - ist->st->codec->sample_aspect_ratio : (AVRational){0, 1}; - } + if (ost->frame_aspect_ratio) + sar = av_d2q(ost->frame_aspect_ratio * codec->height / codec->width, 255); + else if (ist->st->sample_aspect_ratio.num) + sar = ist->st->sample_aspect_ratio; + else + sar = icodec->sample_aspect_ratio; + ost->st->sample_aspect_ratio = codec->sample_aspect_ratio = sar; break; case AVMEDIA_TYPE_SUBTITLE: codec->width = icodec->width; @@ -1705,7 +1632,7 @@ static int transcode_init(void) fg = init_simple_filtergraph(ist, ost); if (configure_filtergraph(fg)) { av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n"); - exit(1); + exit_program(1); } } @@ -1801,13 +1728,13 @@ static int transcode_init(void) } if (!av_dict_get(ost->opts, "threads", NULL, 0)) av_dict_set(&ost->opts, "threads", "auto", 0); - if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) { + if ((ret = avcodec_open2(ost->st->codec, codec, &ost->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); - ret = AVERROR(EINVAL); goto dump_format; } - assert_codec_experimental(ost->st->codec, 1); assert_avoptions(ost->opts); if (ost->st->codec->bit_rate && ost->st->codec->bit_rate < 1000) av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." @@ -1816,6 +1743,8 @@ static int transcode_init(void) if (ost->st->codec->me_threshold) input_streams[ost->source_index]->st->codec->debug |= FF_DEBUG_MV; + } else { + av_opt_set_dict(ost->st->codec, &ost->opts); } } @@ -1846,10 +1775,11 @@ static int transcode_init(void) oc->interrupt_callback = int_cb; if ((ret = avformat_write_header(oc, &output_files[i]->opts)) < 0) { char errbuf[128]; - const char *errbuf_ptr = errbuf; - if (av_strerror(ret, errbuf, sizeof(errbuf)) < 0) - errbuf_ptr = strerror(AVUNERROR(ret)); - snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?): %s", i, errbuf_ptr); + av_strerror(ret, errbuf, sizeof(errbuf)); + snprintf(error, sizeof(error), + "Could not write header for output file #%d " + "(incorrect codec parameters ?): %s", + i, errbuf); ret = AVERROR(EINVAL); goto dump_format; } @@ -1934,10 +1864,7 @@ static int transcode_init(void) return 0; } -/** - * @return 1 if there are still streams where more output is wanted, - * 0 otherwise - */ +/* Return 1 if there remain streams where more output is wanted, 0 otherwise. */ static int need_output(void) { int i; @@ -2098,6 +2025,17 @@ static int get_input_packet_mt(InputFile *f, AVPacket *pkt) static int get_input_packet(InputFile *f, AVPacket *pkt) { + if (f->rate_emu) { + int i; + for (i = 0; i < f->nb_streams; i++) { + InputStream *ist = input_streams[f->ist_index + i]; + int64_t pts = av_rescale(ist->last_dts, 1000000, AV_TIME_BASE); + int64_t now = av_gettime() - ist->start; + if (pts > now) + return AVERROR(EAGAIN); + } + } + #if HAVE_PTHREADS if (nb_input_files > 1) return get_input_packet_mt(f, pkt); @@ -2121,13 +2059,13 @@ static void reset_eagain(void) input_files[i]->eagain = 0; } -/** +/* * Read one packet from an input file and send it for * - decoding -> lavfi (audio/video) * - decoding -> encoding -> muxing (subtitles) * - muxing (streamcopy) * - * @return + * Return * - 0 -- one packet was read and processed * - AVERROR(EAGAIN) -- no packets were available for selected file, * this function should be called again @@ -2356,6 +2294,7 @@ static int transcode(void) av_freep(&ost->st->codec->subtitle_header); av_free(ost->forced_kf_pts); av_dict_free(&ost->opts); + av_dict_free(&ost->resample_opts); } } } @@ -2398,19 +2337,12 @@ static int64_t getmaxrss(void) #endif } -static void parse_cpuflags(int argc, char **argv, const OptionDef *options) -{ - int idx = locate_option(argc, argv, options, "cpuflags"); - if (idx && argv[idx + 1]) - opt_cpuflags(NULL, "cpuflags", argv[idx + 1]); -} - int main(int argc, char **argv) { - OptionsContext o = { 0 }; + int ret; int64_t ti; - reset_options(&o); + register_exit(avconv_cleanup); av_log_set_flags(AV_LOG_SKIP_REPEATED); parse_loglevel(argc, argv, options); @@ -2425,10 +2357,10 @@ int main(int argc, char **argv) show_banner(); - parse_cpuflags(argc, argv, options); - - /* parse options */ - parse_options(&o, argc, argv, options, opt_output_file); + /* parse options and open all input/output files */ + ret = avconv_parse_options(argc, argv); + if (ret < 0) + exit_program(1); if (nb_output_files <= 0 && nb_input_files == 0) { show_usage();