X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffmpeg.c;h=b7e8c5526dcb615214566dd3de7d2e70d180ced0;hb=e37f161e66e042d6c2c7470c4d9881df9427fc4a;hp=4ae194e5e8a65af118260d2ed503fbe385b15c40;hpb=67f5650a78de2567c58dbd7545434cc6d3ef9b7e;p=ffmpeg diff --git a/ffmpeg.c b/ffmpeg.c index 4ae194e5e8a..b7e8c5526dc 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -133,8 +133,6 @@ static int video_discard = 0; static int same_quant = 0; static int do_deinterlace = 0; static int intra_dc_precision = 8; -static int loop_input = 0; -static int loop_output = AVFMT_NOOUTPUTLOOP; static int qp_hist = 0; static int intra_only = 0; static const char *video_codec_name = NULL; @@ -238,7 +236,6 @@ typedef struct OutputStream { int frame_number; /* input pts and corresponding output pts for A/V sync */ - // double sync_ipts; /* dts from the AVPacket of the demuxer in second units */ struct InputStream *sync_ist; /* input stream to sync against */ int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ // FIXME look at frame_number AVBitStreamFilterContext *bitstream_filters; @@ -298,6 +295,7 @@ typedef struct OutputStream { /* init terminal so that we can grab keys */ static struct termios oldtty; +static int restore_tty; #endif typedef struct OutputFile { @@ -469,9 +467,8 @@ static void reset_options(OptionsContext *o, int is_input) init_opts(); } -static int alloc_buffer(InputStream *ist, FrameBuffer **pbuf) +static int alloc_buffer(AVCodecContext *s, InputStream *ist, FrameBuffer **pbuf) { - AVCodecContext *s = ist->st->codec; FrameBuffer *buf = av_mallocz(sizeof(*buf)); int ret, i; const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1; @@ -547,7 +544,10 @@ static int codec_get_buffer(AVCodecContext *s, AVFrame *frame) FrameBuffer *buf; int ret, i; - if (!ist->buffer_pool && (ret = alloc_buffer(ist, &ist->buffer_pool)) < 0) + if(av_image_check_size(s->width, s->height, 0, s)) + return -1; + + if (!ist->buffer_pool && (ret = alloc_buffer(s, ist, &ist->buffer_pool)) < 0) return ret; buf = ist->buffer_pool; @@ -557,7 +557,7 @@ static int codec_get_buffer(AVCodecContext *s, AVFrame *frame) av_freep(&buf->base[0]); av_free(buf); ist->dr1 = 0; - if ((ret = alloc_buffer(ist, &buf)) < 0) + if ((ret = alloc_buffer(s, ist, &buf)) < 0) return ret; } buf->refcount++; @@ -627,6 +627,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) "src", args, NULL, ost->graph); if (ret < 0) return ret; + #if FF_API_OLD_VSINK_API ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, ost->graph); @@ -636,6 +637,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) "out", NULL, buffersink_params, ost->graph); #endif av_freep(&buffersink_params); + if (ret < 0) return ret; last_filter = ost->input_video_filter; @@ -696,7 +698,7 @@ static void term_exit(void) { av_log(NULL, AV_LOG_QUIET, "%s", ""); #if HAVE_TERMIOS_H - if(!run_as_daemon) + if(restore_tty) tcsetattr (0, TCSANOW, &oldtty); #endif } @@ -718,8 +720,9 @@ static void term_init(void) if(!run_as_daemon){ struct termios tty; - tcgetattr (0, &tty); + if (tcgetattr (0, &tty) == 0) { oldtty = tty; + restore_tty = 1; atexit(term_exit); tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP @@ -732,6 +735,7 @@ static void term_init(void) tty.c_cc[VTIME] = 0; tcsetattr (0, TCSANOW, &tty); + } signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */ } #endif @@ -984,6 +988,19 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) AVCodecContext *avctx = ost->st->codec; int ret; + /* + * Audio encoders may split the packets -- #frames in != #packets out. + * But there is no reordering, so we can limit the number of output packets + * by simply dropping them here. + * 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 (ost->frame_number >= ost->max_frames) + return; + ost->frame_number++; + } + while (bsfc) { AVPacket new_pkt = *pkt; int a = av_bitstream_filter_filter(bsfc, avctx, NULL, @@ -1011,7 +1028,6 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) 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) @@ -1062,6 +1078,8 @@ static int encode_audio_frame(AVFormatContext *s, OutputStream *ost, exit_program(1); } + ret = pkt.size; + if (got_packet) { pkt.stream_index = ost->index; if (pkt.pts != AV_NOPTS_VALUE) @@ -1072,12 +1090,14 @@ static int encode_audio_frame(AVFormatContext *s, OutputStream *ost, write_frame(s, &pkt, ost); audio_size += pkt.size; + + av_free_packet(&pkt); } if (frame) ost->sync_opts += frame->nb_samples; - return pkt.size; + return ret; } static void do_audio_out(AVFormatContext *s, OutputStream *ost, @@ -1561,6 +1581,12 @@ static void do_video_out(AVFormatContext *s, } } ost->sync_opts++; + /* + * For video, number of frames in == number of packets out. + * But there may be reordering, so we can't throw away frames on encoder + * flush, we need to limit them here, before they go into encoder. + */ + ost->frame_number++; } } @@ -2336,6 +2362,8 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb ist->st->codec->opaque = ist; } + 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); @@ -2661,6 +2689,8 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, memcpy(ost->st->codec->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); ost->st->codec->subtitle_header_size = dec->subtitle_header_size; } + 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) { 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); @@ -3658,14 +3688,6 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena ic->flags |= AVFMT_FLAG_NONBLOCK; ic->interrupt_callback = int_cb; - if (loop_input) { - av_log(NULL, AV_LOG_WARNING, - "-loop_input is deprecated, use -loop 1\n" - "Note, both loop options only work with -f image2\n" - ); - ic->loop_input = loop_input; - } - /* open the input file with generic avformat function */ err = avformat_open_input(&ic, filename, file_iformat, &format_opts); if (err < 0) { @@ -4446,11 +4468,6 @@ static void opt_output_file(void *optctx, const char *filename) } oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE); - if (loop_output >= 0) { - av_log(NULL, AV_LOG_WARNING, "-loop_output is deprecated, use -loop\n"); - oc->loop_output = loop_output; - } - /* copy metadata */ for (i = 0; i < o->nb_metadata_map; i++) { char *p; @@ -4886,6 +4903,20 @@ static int opt_bitrate(OptionsContext *o, const char *opt, const char *arg) return opt_default(opt, arg); } +static int opt_qscale(OptionsContext *o, const char *opt, const char *arg) +{ + char *s; + int ret; + if(!strcmp(opt, "qscale")){ + av_log(0,AV_LOG_WARNING, "Please use -q:a or -q:v, -qscale is ambiguous\n"); + return parse_option(o, "q:v", arg, options); + } + s = av_asprintf("q%s", opt + 6); + ret = parse_option(o, s, arg, options); + av_free(s); + return ret; +} + static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg) { return parse_option(o, "filter:v", arg, options); @@ -4934,8 +4965,6 @@ static const OptionDef options[] = { { "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump}, "when dumping packets, also dump the payload" }, { "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" }, - { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "deprecated, use -loop" }, - { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "deprecated, use -loop", "" }, { "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_EXPERT, {(void*)opt_vsync}, "video sync method", "" }, { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, @@ -4949,7 +4978,7 @@ static const OptionDef options[] = { { "frames", OPT_INT64 | HAS_ARG | OPT_SPEC, {.off = OFFSET(max_frames)}, "set the number of frames to record", "number" }, { "tag", OPT_STRING | HAS_ARG | OPT_SPEC, {.off = OFFSET(codec_tags)}, "force codec tag/fourcc", "fourcc/tag" }, { "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" }, - { "qscale", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" }, + { "qscale", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_qscale}, "use fixed quality scale (VBR)", "q" }, #if CONFIG_AVFILTER { "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" }, #endif