X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=avconv.c;h=e02139db71932ef6ed9c941f5642439322f327fd;hb=877f6eb5fbe0ef71aa410a399713cae76f4e4eef;hp=6f036dac4187e2b0fb5ac6cb2c9b06dec988ddf1;hpb=00c0465dbc5acd27c736d612bbad95fdbe2ef96c;p=ffmpeg diff --git a/avconv.c b/avconv.c index 6f036dac418..e02139db719 100644 --- a/avconv.c +++ b/avconv.c @@ -88,6 +88,11 @@ #include "libavutil/avassert.h" +#define VSYNC_AUTO -1 +#define VSYNC_PASSTHROUGH 0 +#define VSYNC_CFR 1 +#define VSYNC_VFR 2 + const char program_name[] = "avconv"; const int program_birth_year = 2000; @@ -127,7 +132,7 @@ static int do_hex_dump = 0; static int do_pkt_dump = 0; static int do_pass = 0; static const char *pass_logfilename_prefix; -static int video_sync_method = -1; +static int video_sync_method = VSYNC_AUTO; static int audio_sync_method = 0; static float audio_drift_threshold = 0.1; static int copy_ts = 0; @@ -754,6 +759,15 @@ void exit_program(int ret) avformat_free_context(s); av_dict_free(&output_files[i].opts); } + for (i = 0; i < nb_output_streams; i++) { + AVBitStreamFilterContext *bsfc = output_streams[i].bitstream_filters; + while (bsfc) { + AVBitStreamFilterContext *next = bsfc->next; + av_bitstream_filter_close(bsfc); + bsfc = next; + } + output_streams[i].bitstream_filters = NULL; + } for (i = 0; i < nb_input_files; i++) { avformat_close_input(&input_files[i].ctx); } @@ -896,8 +910,10 @@ get_sync_ipts(const OutputStream *ost) return (double)(ist->pts - of->start_time) / AV_TIME_BASE; } -static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc) +static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) { + AVBitStreamFilterContext *bsfc = ost->bitstream_filters; + AVCodecContext *avctx = ost->st->codec; int ret; while (bsfc) { @@ -927,6 +943,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx print_error("av_interleaved_write_frame()", ret); exit_program(1); } + ost->frame_number++; } static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_t size) @@ -1141,7 +1158,7 @@ need_realloc: if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); pkt.flags |= AV_PKT_FLAG_KEY; - write_frame(s, &pkt, enc, ost->bitstream_filters); + write_frame(s, &pkt, ost); ost->sync_opts += enc->frame_size; } @@ -1176,7 +1193,7 @@ need_realloc: if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); pkt.flags |= AV_PKT_FLAG_KEY; - write_frame(s, &pkt, enc, ost->bitstream_filters); + write_frame(s, &pkt, ost); } } @@ -1278,7 +1295,7 @@ static void do_subtitle_out(AVFormatContext *s, else pkt.pts += 90 * sub->end_display_time; } - write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters); + write_frame(s, &pkt, ost); } } @@ -1378,16 +1395,16 @@ static void do_video_out(AVFormatContext *s, *frame_size = 0; format_video_sync = video_sync_method; - if (format_video_sync < 0) - format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? 0 : - (s->oformat->flags & AVFMT_VARIABLE_FPS) ? 2 : 1; + if (format_video_sync == VSYNC_AUTO) + format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : + (s->oformat->flags & AVFMT_VARIABLE_FPS) ? VSYNC_VFR : VSYNC_CFR; - if (format_video_sync) { + if (format_video_sync != VSYNC_PASSTHROUGH) { double vdelta = sync_ipts - ost->sync_opts; // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (vdelta < -1.1) nb_frames = 0; - else if (format_video_sync == 2) { + else if (format_video_sync == VSYNC_VFR) { if (vdelta <= -0.6) { nb_frames = 0; } else if (vdelta > 0.6) @@ -1429,7 +1446,7 @@ static void do_video_out(AVFormatContext *s, pkt.pts = av_rescale_q(ost->sync_opts, enc->time_base, ost->st->time_base); pkt.flags |= AV_PKT_FLAG_KEY; - write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters); + write_frame(s, &pkt, ost); } else { AVFrame big_picture; @@ -1477,7 +1494,7 @@ static void do_video_out(AVFormatContext *s, if (enc->coded_frame->key_frame) pkt.flags |= AV_PKT_FLAG_KEY; - write_frame(s, &pkt, ost->st->codec, ost->bitstream_filters); + write_frame(s, &pkt, ost); *frame_size = ret; video_size += ret; // fprintf(stderr,"\nFrame: %3d size: %5d type: %d", @@ -1489,7 +1506,6 @@ static void do_video_out(AVFormatContext *s, } } ost->sync_opts++; - ost->frame_number++; } } @@ -1747,7 +1763,7 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams) pkt.size = ret; if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); - write_frame(os, &pkt, ost->st->codec, ost->bitstream_filters); + write_frame(os, &pkt, ost); } } } @@ -1831,9 +1847,8 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt.flags |= AV_PKT_FLAG_KEY; } - write_frame(of->ctx, &opkt, ost->st->codec, ost->bitstream_filters); + write_frame(of->ctx, &opkt, ost); ost->st->codec->frame_number++; - ost->frame_number++; av_free_packet(&opkt); } @@ -3186,7 +3201,7 @@ static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream * */ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) { - int i, rfps, rfps_base; + int i; for (i = 0; i < ic->nb_streams; i++) { AVStream *st = ic->streams[i]; @@ -3215,19 +3230,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) case AVMEDIA_TYPE_VIDEO: if(!ist->dec) ist->dec = avcodec_find_decoder(dec->codec_id); - rfps = ic->streams[i]->r_frame_rate.num; - rfps_base = ic->streams[i]->r_frame_rate.den; if (dec->lowres) { dec->flags |= CODEC_FLAG_EMU_EDGE; } - if (dec->time_base.den != rfps * dec->ticks_per_frame || dec->time_base.num != rfps_base) { - - av_log(NULL, AV_LOG_INFO,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n", - i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num, - (float)rfps / rfps_base, rfps, rfps_base); - } - if (o->video_disable) st->discard = AVDISCARD_ALL; else if (video_discard) @@ -4425,6 +4431,17 @@ static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg return parse_option(o, "filter:v", arg, options); } +static int opt_vsync(const char *opt, const char *arg) +{ + if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR; + else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR; + else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH; + + if (video_sync_method == VSYNC_AUTO) + video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); + return 0; +} + #define OFFSET(x) offsetof(OptionsContext, x) static const OptionDef options[] = { /* main options */ @@ -4456,7 +4473,7 @@ static const OptionDef options[] = { "when dumping packets, also dump the payload" }, { "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" }, { "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, - { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" }, + { "vsync", HAS_ARG | OPT_EXPERT, {(void*)opt_vsync}, "video sync method", "" }, { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" },