From f1af3d19a7924c6f5963ee15a83bad26d2262dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 8 Mar 2013 11:59:57 +0200 Subject: [PATCH 1/3] output-example: Update to use encode_video2 instead of the now dropped encode_video Signed-off-by: Anton Khirnov --- libavformat/output-example.c | 45 +++++++++++++----------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/libavformat/output-example.c b/libavformat/output-example.c index 2f83990011..496b7f8212 100644 --- a/libavformat/output-example.c +++ b/libavformat/output-example.c @@ -177,8 +177,7 @@ static void close_audio(AVFormatContext *oc, AVStream *st) /* video output */ static AVFrame *picture, *tmp_picture; -static uint8_t *video_outbuf; -static int frame_count, video_outbuf_size; +static int frame_count; /* Add a video output stream. */ static AVStream *add_video_stream(AVFormatContext *oc, enum AVCodecID codec_id) @@ -264,18 +263,6 @@ static void open_video(AVFormatContext *oc, AVStream *st) exit(1); } - video_outbuf = NULL; - if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { - /* Allocate output buffer. */ - /* XXX: API change will be done. */ - /* Buffers passed into lav* can be allocated any way you prefer, - * as long as they're aligned enough for the architecture, and - * they're freed appropriately (such as using av_free for buffers - * allocated with av_malloc). */ - video_outbuf_size = 200000; - video_outbuf = av_malloc(video_outbuf_size); - } - /* Allocate the encoded raw picture. */ picture = alloc_picture(c->pix_fmt, c->width, c->height); if (!picture) { @@ -320,7 +307,7 @@ static void fill_yuv_image(AVFrame *pict, int frame_index, static void write_video_frame(AVFormatContext *oc, AVStream *st) { - int out_size, ret; + int ret; AVCodecContext *c; static struct SwsContext *img_convert_ctx; @@ -367,22 +354,23 @@ static void write_video_frame(AVFormatContext *oc, AVStream *st) ret = av_interleaved_write_frame(oc, &pkt); } else { - /* encode the image */ - out_size = avcodec_encode_video(c, video_outbuf, - video_outbuf_size, picture); - /* If size is zero, it means the image was buffered. */ - if (out_size > 0) { - AVPacket pkt; - av_init_packet(&pkt); + AVPacket pkt = { 0 }; + int got_packet; + av_init_packet(&pkt); - if (c->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts = av_rescale_q(c->coded_frame->pts, + /* encode the image */ + ret = avcodec_encode_video2(c, &pkt, picture, &got_packet); + /* If size is zero, it means the image was buffered. */ + if (!ret && got_packet && pkt.size) { + if (pkt.pts != AV_NOPTS_VALUE) { + pkt.pts = av_rescale_q(pkt.pts, c->time_base, st->time_base); - if (c->coded_frame->key_frame) - pkt.flags |= AV_PKT_FLAG_KEY; + } + if (pkt.dts != AV_NOPTS_VALUE) { + pkt.dts = av_rescale_q(pkt.dts, + c->time_base, st->time_base); + } pkt.stream_index = st->index; - pkt.data = video_outbuf; - pkt.size = out_size; /* Write the compressed frame to the media file. */ ret = av_interleaved_write_frame(oc, &pkt); @@ -406,7 +394,6 @@ static void close_video(AVFormatContext *oc, AVStream *st) av_free(tmp_picture->data[0]); av_free(tmp_picture); } - av_free(video_outbuf); } /**************************************************************/ From e460aa3282962aa3e89f19e207ec13b501187949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 8 Mar 2013 12:32:38 +0200 Subject: [PATCH 2/3] atomic: Check for __sync_val_compare_and_swap instead of __sync_synchronize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not all gcc configurations have an implementation of all the atomic operations, and some gcc configurations have some atomic builtins implemented but not all. Thus check for the most essential function, whose presence should indicate that all others are present as well, since it can be used to implement all the other ones. Signed-off-by: Martin Storsjö --- configure | 4 ++-- libavutil/atomic.c | 4 ++-- libavutil/atomic.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure b/configure index a4b12c6b2d..01bfbb15ed 100755 --- a/configure +++ b/configure @@ -1324,7 +1324,7 @@ HAVE_LIST=" struct_v4l2_frmivalenum_discrete symver_asm_label symver_gnu_asm - sync_synchronize + sync_val_compare_and_swap sysconf sysctl sys_mman_h @@ -3456,7 +3456,7 @@ check_func strerror_r check_func strptime check_func strtok_r check_func sched_getaffinity -check_builtin sync_synchronize "" "__sync_synchronize()" +check_builtin sync_val_compare_and_swap "" "int *ptr; int oldval, newval; __sync_val_compare_and_swap(ptr, oldval, newval)" check_builtin machine_rw_barrier mbarrier.h "__machine_rw_barrier()" check_builtin MemoryBarrier windows.h "MemoryBarrier()" check_func sysconf diff --git a/libavutil/atomic.c b/libavutil/atomic.c index 8fa2532fd6..37e796f05f 100644 --- a/libavutil/atomic.c +++ b/libavutil/atomic.c @@ -20,7 +20,7 @@ #include "atomic.h" -#if !HAVE_MEMORYBARRIER && !HAVE_SYNC_SYNCHRONIZE && !HAVE_MACHINE_RW_BARRIER +#if !HAVE_MEMORYBARRIER && !HAVE_SYNC_VAL_COMPARE_AND_SWAP && !HAVE_MACHINE_RW_BARRIER #if HAVE_PTHREADS @@ -102,7 +102,7 @@ void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval) #endif /* HAVE_PTHREADS */ -#endif /* !HAVE_MEMORYBARRIER && !HAVE_SYNC_SYNCHRONIZE && !HAVE_MACHINE_RW_BARRIER */ +#endif /* !HAVE_MEMORYBARRIER && !HAVE_SYNC_VAL_COMPARE_AND_SWAP && !HAVE_MACHINE_RW_BARRIER */ #ifdef TEST #include diff --git a/libavutil/atomic.h b/libavutil/atomic.h index dad93bd1aa..577e471462 100644 --- a/libavutil/atomic.h +++ b/libavutil/atomic.h @@ -25,7 +25,7 @@ #if HAVE_MEMORYBARRIER #include "atomic_win32.h" -#elif HAVE_SYNC_SYNCHRONIZE +#elif HAVE_SYNC_VAL_COMPARE_AND_SWAP #include "atomic_gcc.h" #elif HAVE_MACHINE_RW_BARRIER #include "atomic_suncc.h" From 9d3009c6c4b9b6734f07df7c88f6a42ded6cdf38 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 20 Feb 2013 08:02:16 +0100 Subject: [PATCH 3/3] avconv: print an error on applying options of the wrong type. I.e. input options to output files or vice versa. --- avconv_opt.c | 165 +++++++++++++++++++++++++++++++-------------------- cmdutils.c | 10 ++++ cmdutils.h | 7 +++ 3 files changed, 119 insertions(+), 63 deletions(-) diff --git a/avconv_opt.c b/avconv_opt.c index 5bb7fb75f5..98c38ae524 100644 --- a/avconv_opt.c +++ b/avconv_opt.c @@ -1864,8 +1864,8 @@ enum OptGroup { }; static const OptionGroupDef groups[] = { - [GROUP_OUTFILE] = { "output file", NULL }, - [GROUP_INFILE] = { "input file", "i" }, + [GROUP_OUTFILE] = { "output file", NULL, OPT_OUTPUT }, + [GROUP_INFILE] = { "input file", "i", OPT_INPUT }, }; static int open_files(OptionGroupList *l, const char *inout, @@ -1951,38 +1951,49 @@ fail: const OptionDef options[] = { /* main options */ #include "cmdutils_common_opts.h" - { "f", HAS_ARG | OPT_STRING | OPT_OFFSET, { .off = OFFSET(format) }, + { "f", HAS_ARG | OPT_STRING | OPT_OFFSET | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(format) }, "force format", "fmt" }, { "y", OPT_BOOL, { &file_overwrite }, "overwrite output files" }, - { "c", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(codec_names) }, + { "c", HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(codec_names) }, "codec name", "codec" }, - { "codec", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(codec_names) }, + { "codec", HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(codec_names) }, "codec name", "codec" }, - { "pre", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(presets) }, + { "pre", HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(presets) }, "preset name", "preset" }, - { "map", HAS_ARG | OPT_EXPERT | OPT_PERFILE, { .func_arg = opt_map }, + { "map", HAS_ARG | OPT_EXPERT | OPT_PERFILE | + OPT_OUTPUT, { .func_arg = opt_map }, "set input stream mapping", "[-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]]" }, - { "map_metadata", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(metadata_map) }, + { "map_metadata", HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(metadata_map) }, "set metadata information of outfile from infile", "outfile[,metadata]:infile[,metadata]" }, - { "map_chapters", HAS_ARG | OPT_INT | OPT_EXPERT | OPT_OFFSET, { .off = OFFSET(chapters_input_file) }, + { "map_chapters", HAS_ARG | OPT_INT | OPT_EXPERT | OPT_OFFSET | + OPT_OUTPUT, { .off = OFFSET(chapters_input_file) }, "set chapters mapping", "input_file_index" }, - { "t", HAS_ARG | OPT_TIME | OPT_OFFSET, { .off = OFFSET(recording_time) }, + { "t", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(recording_time) }, "record or transcode \"duration\" seconds of audio/video", "duration" }, - { "fs", HAS_ARG | OPT_INT64 | OPT_OFFSET, { .off = OFFSET(limit_filesize) }, + { "fs", HAS_ARG | OPT_INT64 | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(limit_filesize) }, "set the limit file size in bytes", "limit_size" }, - { "ss", HAS_ARG | OPT_TIME | OPT_OFFSET, { .off = OFFSET(start_time) }, + { "ss", HAS_ARG | OPT_TIME | OPT_OFFSET | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(start_time) }, "set the start time offset", "time_off" }, - { "itsoffset", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_EXPERT,{ .off = OFFSET(input_ts_offset) }, + { "itsoffset", HAS_ARG | OPT_TIME | OPT_OFFSET | + OPT_EXPERT | OPT_INPUT, { .off = OFFSET(input_ts_offset) }, "set the input ts offset", "time_off" }, - { "itsscale", HAS_ARG | OPT_DOUBLE | OPT_SPEC | OPT_EXPERT,{ .off = OFFSET(ts_scale) }, + { "itsscale", HAS_ARG | OPT_DOUBLE | OPT_SPEC | + OPT_EXPERT | OPT_INPUT, { .off = OFFSET(ts_scale) }, "set the input ts scale", "scale" }, - { "metadata", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(metadata) }, + { "metadata", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(metadata) }, "add metadata", "string=string" }, - { "dframes", HAS_ARG | OPT_PERFILE | OPT_EXPERT, { .func_arg = opt_data_frames }, + { "dframes", HAS_ARG | OPT_PERFILE | OPT_EXPERT | + OPT_OUTPUT, { .func_arg = opt_data_frames }, "set the number of data frames to record", "number" }, { "benchmark", OPT_BOOL | OPT_EXPERT, { &do_benchmark }, "add timings for benchmarking" }, @@ -1992,9 +2003,10 @@ const OptionDef options[] = { "dump each input packet" }, { "hex", OPT_BOOL | OPT_EXPERT, { &do_hex_dump }, "when dumping packets, also dump the payload" }, - { "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, { .off = OFFSET(rate_emu) }, + { "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET | + OPT_INPUT, { .off = OFFSET(rate_emu) }, "read input at native frame rate", "" }, - { "target", HAS_ARG | OPT_PERFILE, { .func_arg = opt_target }, + { "target", HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_target }, "specify target file type (\"vcd\", \"svcd\", \"dvd\"," " \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, { "vsync", HAS_ARG | OPT_EXPERT, { opt_vsync }, @@ -2007,57 +2019,71 @@ const OptionDef options[] = { "copy timestamps" }, { "copytb", OPT_BOOL | OPT_EXPERT, { ©_tb }, "copy input stream time base when stream copying" }, - { "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, { .off = OFFSET(shortest) }, + { "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET | + OPT_OUTPUT, { .off = OFFSET(shortest) }, "finish encoding within shortest input" }, { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &dts_delta_threshold }, "timestamp discontinuity delta threshold", "threshold" }, { "xerror", OPT_BOOL | OPT_EXPERT, { &exit_on_error }, "exit on error", "error" }, - { "copyinkf", OPT_BOOL | OPT_EXPERT | OPT_SPEC, { .off = OFFSET(copy_initial_nonkeyframes) }, + { "copyinkf", OPT_BOOL | OPT_EXPERT | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(copy_initial_nonkeyframes) }, "copy initial non-keyframes" }, - { "frames", OPT_INT64 | HAS_ARG | OPT_SPEC, { .off = OFFSET(max_frames) }, + { "frames", OPT_INT64 | HAS_ARG | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(max_frames) }, "set the number of frames to record", "number" }, - { "tag", OPT_STRING | HAS_ARG | OPT_SPEC | OPT_EXPERT,{ .off = OFFSET(codec_tags) }, + { "tag", OPT_STRING | HAS_ARG | OPT_SPEC | + OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(codec_tags) }, "force codec tag/fourcc", "fourcc/tag" }, - { "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC,{ .off = OFFSET(qscale) }, + { "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | + OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(qscale) }, "use fixed quality scale (VBR)", "q" }, - { "qscale", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC,{ .off = OFFSET(qscale) }, + { "qscale", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | + OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(qscale) }, "use fixed quality scale (VBR)", "q" }, - { "filter", HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(filters) }, + { "filter", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) }, "set stream filterchain", "filter_list" }, { "filter_complex", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex }, "create a complex filtergraph", "graph_description" }, { "stats", OPT_BOOL, { &print_stats }, "print progress report during encoding", }, - { "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT, { .func_arg = opt_attach }, + { "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT | + OPT_OUTPUT, { .func_arg = opt_attach }, "add an attachment to the output file", "filename" }, - { "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC |OPT_EXPERT,{ .off = OFFSET(dump_attachment) }, + { "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_EXPERT | OPT_INPUT, { .off = OFFSET(dump_attachment) }, "extract an attachment into a file", "filename" }, { "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "set CPU flags mask", "mask" }, /* video options */ - { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE, { .func_arg = opt_video_frames }, + { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, "set the number of video frames to record", "number" }, - { "r", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(frame_rates) }, + { "r", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_rates) }, "set frame rate (Hz value, fraction or abbreviation)", "rate" }, - { "s", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(frame_sizes) }, + { "s", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_sizes) }, "set frame size (WxH or abbreviation)", "size" }, - { "aspect", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC, { .off = OFFSET(frame_aspect_ratios) }, + { "aspect", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(frame_aspect_ratios) }, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" }, - { "pix_fmt", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC, { .off = OFFSET(frame_pix_fmts) }, + { "pix_fmt", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_pix_fmts) }, "set pixel format", "format" }, - { "vn", OPT_VIDEO | OPT_BOOL | OPT_OFFSET, { .off = OFFSET(video_disable) }, + { "vn", OPT_VIDEO | OPT_BOOL | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(video_disable) }, "disable video" }, { "vdt", OPT_VIDEO | OPT_INT | HAS_ARG | OPT_EXPERT , { &video_discard }, "discard threshold", "n" }, - { "rc_override", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC, { .off = OFFSET(rc_overrides) }, + { "rc_override", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(rc_overrides) }, "rate control override for specific intervals", "override" }, - { "vcodec", OPT_VIDEO | HAS_ARG | OPT_PERFILE, { .func_arg = opt_video_codec }, + { "vcodec", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_INPUT | + OPT_OUTPUT, { .func_arg = opt_video_codec }, "force video codec ('copy' to copy stream)", "codec" }, - { "pass", OPT_VIDEO | HAS_ARG | OPT_SPEC | OPT_INT, { .off = OFFSET(pass) }, + { "pass", OPT_VIDEO | HAS_ARG | OPT_SPEC | OPT_INT | OPT_OUTPUT, { .off = OFFSET(pass) }, "select the pass number (1 or 2)", "n" }, - { "passlogfile", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC, { .off = OFFSET(passlogfiles) }, + { "passlogfile", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(passlogfiles) }, "select two pass log file name prefix", "prefix" }, #if FF_API_DEINTERLACE { "deinterlace", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_deinterlace }, @@ -2067,73 +2093,86 @@ const OptionDef options[] = { "dump video coding statistics to file" }, { "vstats_file", OPT_VIDEO | HAS_ARG | OPT_EXPERT , { opt_vstats_file }, "dump video coding statistics to file", "file" }, - { "vf", OPT_VIDEO | HAS_ARG | OPT_PERFILE, { .func_arg = opt_video_filters }, + { "vf", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_filters }, "video filters", "filter list" }, - { "intra_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC, { .off = OFFSET(intra_matrices) }, + { "intra_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(intra_matrices) }, "specify intra matrix coeffs", "matrix" }, - { "inter_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC, { .off = OFFSET(inter_matrices) }, + { "inter_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(inter_matrices) }, "specify inter matrix coeffs", "matrix" }, - { "top", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_INT| OPT_SPEC, { .off = OFFSET(top_field_first) }, + { "top", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_INT| OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(top_field_first) }, "top=1/bottom=0/auto=-1 field first", "" }, { "dc", OPT_VIDEO | OPT_INT | HAS_ARG | OPT_EXPERT , { &intra_dc_precision }, "intra_dc_precision", "precision" }, - { "vtag", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE, { .func_arg = opt_video_tag }, + { "vtag", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE | + OPT_OUTPUT, { .func_arg = opt_video_tag }, "force video tag/fourcc", "fourcc/tag" }, { "qphist", OPT_VIDEO | OPT_BOOL | OPT_EXPERT , { &qp_hist }, "show QP histogram" }, - { "force_fps", OPT_VIDEO | OPT_BOOL | OPT_EXPERT | OPT_SPEC, { .off = OFFSET(force_fps) }, + { "force_fps", OPT_VIDEO | OPT_BOOL | OPT_EXPERT | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(force_fps) }, "force the selected framerate, disable the best supported framerate selection" }, - { "streamid", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE, { .func_arg = opt_streamid }, + { "streamid", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE | + OPT_OUTPUT, { .func_arg = opt_streamid }, "set the value of an outfile streamid", "streamIndex:value" }, - { "force_key_frames", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC, - { .off = OFFSET(forced_key_frames) }, "force key frames at specified timestamps", "timestamps" }, + { "force_key_frames", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | + OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(forced_key_frames) }, + "force key frames at specified timestamps", "timestamps" }, /* audio options */ - { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE, { .func_arg = opt_audio_frames }, + { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames }, "set the number of audio frames to record", "number" }, - { "aq", OPT_AUDIO | HAS_ARG | OPT_PERFILE, { .func_arg = opt_audio_qscale }, + { "aq", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_qscale }, "set audio quality (codec-specific)", "quality", }, - { "ar", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC, { .off = OFFSET(audio_sample_rate) }, + { "ar", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(audio_sample_rate) }, "set audio sampling rate (in Hz)", "rate" }, - { "ac", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC, { .off = OFFSET(audio_channels) }, + { "ac", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(audio_channels) }, "set number of audio channels", "channels" }, - { "an", OPT_AUDIO | OPT_BOOL | OPT_OFFSET, { .off = OFFSET(audio_disable) }, + { "an", OPT_AUDIO | OPT_BOOL | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(audio_disable) }, "disable audio" }, - { "acodec", OPT_AUDIO | HAS_ARG | OPT_PERFILE, { .func_arg = opt_audio_codec }, + { "acodec", OPT_AUDIO | HAS_ARG | OPT_PERFILE | + OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_audio_codec }, "force audio codec ('copy' to copy stream)", "codec" }, - { "atag", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE, { .func_arg = opt_audio_tag }, + { "atag", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE | + OPT_OUTPUT, { .func_arg = opt_audio_tag }, "force audio tag/fourcc", "fourcc/tag" }, { "vol", OPT_AUDIO | HAS_ARG | OPT_INT, { &audio_volume }, "change audio volume (256=normal)" , "volume" }, - { "sample_fmt", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_STRING, { .off = OFFSET(sample_fmts) }, + { "sample_fmt", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC | + OPT_STRING | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(sample_fmts) }, "set sample format", "format" }, - { "channel_layout", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE, { .func_arg = opt_channel_layout }, + { "channel_layout", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE | + OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_channel_layout }, "set channel layout", "layout" }, - { "af", OPT_AUDIO | HAS_ARG | OPT_PERFILE, { .func_arg = opt_audio_filters }, + { "af", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_filters }, "audio filters", "filter list" }, /* subtitle options */ - { "sn", OPT_SUBTITLE | OPT_BOOL | OPT_OFFSET, { .off = OFFSET(subtitle_disable) }, + { "sn", OPT_SUBTITLE | OPT_BOOL | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(subtitle_disable) }, "disable subtitle" }, - { "scodec", OPT_SUBTITLE | HAS_ARG | OPT_PERFILE, { .func_arg = opt_subtitle_codec }, + { "scodec", OPT_SUBTITLE | HAS_ARG | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_subtitle_codec }, "force subtitle codec ('copy' to copy stream)", "codec" }, - { "stag", OPT_SUBTITLE | HAS_ARG | OPT_EXPERT | OPT_PERFILE, { .func_arg = opt_subtitle_tag } + { "stag", OPT_SUBTITLE | HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_subtitle_tag } , "force subtitle tag/fourcc", "fourcc/tag" }, /* grab options */ { "isync", OPT_BOOL | OPT_EXPERT, { &input_sync }, "this option is deprecated and does nothing", "" }, /* muxer options */ - { "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET, { .off = OFFSET(mux_max_delay) }, + { "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_max_delay) }, "set the maximum demux-decode delay", "seconds" }, - { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET, { .off = OFFSET(mux_preload) }, + { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_preload) }, "set the initial demux-decode delay", "seconds" }, - { "bsf", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT, { .off = OFFSET(bitstream_filters) }, + { "bsf", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(bitstream_filters) }, "A comma-separated list of bitstream filters", "bitstream_filters" }, /* data codec support */ - { "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT, { .func_arg = opt_data_codec }, + { "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_data_codec }, "force data codec ('copy' to copy stream)", "codec" }, { NULL, }, diff --git a/cmdutils.c b/cmdutils.c index 4655681e4a..ff4b0270c3 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -351,6 +351,16 @@ int parse_optgroup(void *optctx, OptionGroup *g) for (i = 0; i < g->nb_opts; i++) { Option *o = &g->opts[i]; + if (g->group_def->flags && + !(g->group_def->flags & o->opt->flags)) { + av_log(NULL, AV_LOG_ERROR, "Option %s (%s) cannot be applied to " + "%s %s -- you are trying to apply an input option to an " + "output file or vice versa. Move this option before the " + "file it belongs to.\n", o->key, o->opt->help, + g->group_def->name, g->arg); + return AVERROR(EINVAL); + } + av_log(NULL, AV_LOG_DEBUG, "Applying option %s (%s) with argument %s.\n", o->key, o->opt->help, o->val); diff --git a/cmdutils.h b/cmdutils.h index cdcfc0728e..1ae1978ab2 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -144,6 +144,8 @@ typedef struct OptionDef { an int containing element count in the array. */ #define OPT_TIME 0x10000 #define OPT_DOUBLE 0x20000 +#define OPT_INPUT 0x40000 +#define OPT_OUTPUT 0x80000 union { void *dst_ptr; int (*func_arg)(void *, const char *, const char *); @@ -224,6 +226,11 @@ typedef struct OptionGroupDef { * are terminated by a non-option argument (e.g. avconv output files) */ const char *sep; + /** + * Option flags that must be set on each option that is + * applied to this group + */ + int flags; } OptionGroupDef; typedef struct OptionGroup {