X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=avplay.c;h=a0b0e5bc5659b8517b61b2b2a1de358e200b1b9f;hb=932d8300d38587ebc223e3bacc3c33ed68bf3cf6;hp=e18b2e46f2b1555c41209f2d232988cc9b6ae157;hpb=f1ffb01ee9fd3a15c395c3cf6ff362ac5cd668d0;p=ffmpeg diff --git a/avplay.c b/avplay.c index e18b2e46f2b..a0b0e5bc565 100644 --- a/avplay.c +++ b/avplay.c @@ -31,6 +31,7 @@ #include "libavutil/dict.h" #include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" +#include "libavutil/time.h" #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" @@ -41,6 +42,8 @@ #if CONFIG_AVFILTER # include "libavfilter/avfilter.h" # include "libavfilter/avfiltergraph.h" +# include "libavfilter/buffersink.h" +# include "libavfilter/buffersrc.h" #endif #include "cmdutils.h" @@ -52,7 +55,6 @@ #undef main /* We don't want SDL to override our main() */ #endif -#include #include const char program_name[] = "avplay"; @@ -211,7 +213,10 @@ typedef struct VideoState { PtsCorrectionContext pts_ctx; #if CONFIG_AVFILTER + AVFilterContext *in_video_filter; ///< the first filter in the video chain AVFilterContext *out_video_filter; ///< the last filter in the video chain + int use_dr1; + FrameBuffer *buffer_pool; #endif float skip_frames; @@ -219,8 +224,6 @@ typedef struct VideoState { int refresh; } VideoState; -static void show_help(void); - /* options specified by the user */ static AVInputFormat *file_iformat; static const char *input_filename; @@ -259,6 +262,7 @@ static int exit_on_keydown; static int exit_on_mousedown; static int loop = 1; static int framedrop = 1; +static int infinite_buffer = 0; static int rdftspeed = 20; #if CONFIG_AVFILTER @@ -947,7 +951,7 @@ static int refresh_thread(void *opaque) is->refresh = 1; SDL_PushEvent(&event); } - usleep(is->audio_st && is->show_audio ? rdftspeed * 1000 : 5000); // FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly + av_usleep(is->audio_st && is->show_audio ? rdftspeed * 1000 : 5000); // FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly } return 0; } @@ -1229,10 +1233,7 @@ static void stream_close(VideoState *is) for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) { vp = &is->pictq[i]; #if CONFIG_AVFILTER - if (vp->picref) { - avfilter_unref_buffer(vp->picref); - vp->picref = NULL; - } + avfilter_unref_bufferp(&vp->picref); #endif if (vp->bmp) { SDL_FreeYUVOverlay(vp->bmp); @@ -1281,9 +1282,7 @@ static void alloc_picture(void *opaque) SDL_FreeYUVOverlay(vp->bmp); #if CONFIG_AVFILTER - if (vp->picref) - avfilter_unref_buffer(vp->picref); - vp->picref = NULL; + avfilter_unref_bufferp(&vp->picref); vp->width = is->out_video_filter->inputs[0]->w; vp->height = is->out_video_filter->inputs[0]->h; @@ -1376,8 +1375,7 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t if (vp->bmp) { AVPicture pict = { { 0 } }; #if CONFIG_AVFILTER - if (vp->picref) - avfilter_unref_buffer(vp->picref); + avfilter_unref_bufferp(&vp->picref); vp->picref = src_frame->opaque; #endif @@ -1516,213 +1514,41 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke } #if CONFIG_AVFILTER -typedef struct { - VideoState *is; - AVFrame *frame; - int use_dr1; -} FilterPriv; - -static int input_get_buffer(AVCodecContext *codec, AVFrame *pic) -{ - AVFilterContext *ctx = codec->opaque; - AVFilterBufferRef *ref; - int perms = AV_PERM_WRITE; - int i, w, h, stride[AV_NUM_DATA_POINTERS]; - unsigned edge; - int pixel_size; - - if (codec->codec->capabilities & CODEC_CAP_NEG_LINESIZES) - perms |= AV_PERM_NEG_LINESIZES; - - if (pic->buffer_hints & FF_BUFFER_HINTS_VALID) { - if (pic->buffer_hints & FF_BUFFER_HINTS_READABLE) perms |= AV_PERM_READ; - if (pic->buffer_hints & FF_BUFFER_HINTS_PRESERVE) perms |= AV_PERM_PRESERVE; - if (pic->buffer_hints & FF_BUFFER_HINTS_REUSABLE) perms |= AV_PERM_REUSE2; - } - if (pic->reference) perms |= AV_PERM_READ | AV_PERM_PRESERVE; - - w = codec->width; - h = codec->height; - avcodec_align_dimensions2(codec, &w, &h, stride); - edge = codec->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width(); - w += edge << 1; - h += edge << 1; - - if (!(ref = avfilter_get_video_buffer(ctx->outputs[0], perms, w, h))) - return -1; - - pixel_size = av_pix_fmt_descriptors[ref->format].comp[0].step_minus1 + 1; - ref->video->w = codec->width; - ref->video->h = codec->height; - for (i = 0; i < 4; i ++) { - unsigned hshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->format].log2_chroma_w : 0; - unsigned vshift = (i == 1 || i == 2) ? av_pix_fmt_descriptors[ref->format].log2_chroma_h : 0; - - if (ref->data[i]) { - ref->data[i] += ((edge * pixel_size) >> hshift) + ((edge * ref->linesize[i]) >> vshift); - } - pic->data[i] = ref->data[i]; - pic->linesize[i] = ref->linesize[i]; - } - pic->opaque = ref; - pic->type = FF_BUFFER_TYPE_USER; - pic->reordered_opaque = codec->reordered_opaque; - pic->width = codec->width; - pic->height = codec->height; - pic->format = codec->pix_fmt; - pic->sample_aspect_ratio = codec->sample_aspect_ratio; - if (codec->pkt) pic->pkt_pts = codec->pkt->pts; - else pic->pkt_pts = AV_NOPTS_VALUE; - return 0; -} - -static void input_release_buffer(AVCodecContext *codec, AVFrame *pic) -{ - memset(pic->data, 0, sizeof(pic->data)); - avfilter_unref_buffer(pic->opaque); -} - -static int input_reget_buffer(AVCodecContext *codec, AVFrame *pic) -{ - AVFilterBufferRef *ref = pic->opaque; - - if (pic->data[0] == NULL) { - pic->buffer_hints |= FF_BUFFER_HINTS_READABLE; - return codec->get_buffer(codec, pic); - } - - if ((codec->width != ref->video->w) || (codec->height != ref->video->h) || - (codec->pix_fmt != ref->format)) { - av_log(codec, AV_LOG_ERROR, "Picture properties changed.\n"); - return -1; - } - - pic->reordered_opaque = codec->reordered_opaque; - if (codec->pkt) pic->pkt_pts = codec->pkt->pts; - else pic->pkt_pts = AV_NOPTS_VALUE; - return 0; -} - -static int input_init(AVFilterContext *ctx, const char *args, void *opaque) -{ - FilterPriv *priv = ctx->priv; - AVCodecContext *codec; - if (!opaque) return -1; - - priv->is = opaque; - codec = priv->is->video_st->codec; - codec->opaque = ctx; - if (codec->codec->capabilities & CODEC_CAP_DR1) { - priv->use_dr1 = 1; - codec->get_buffer = input_get_buffer; - codec->release_buffer = input_release_buffer; - codec->reget_buffer = input_reget_buffer; - codec->thread_safe_callbacks = 1; - } - - priv->frame = avcodec_alloc_frame(); - - return 0; -} - -static void input_uninit(AVFilterContext *ctx) -{ - FilterPriv *priv = ctx->priv; - av_free(priv->frame); -} - -static int input_request_frame(AVFilterLink *link) -{ - FilterPriv *priv = link->src->priv; - AVFilterBufferRef *picref; - int64_t pts = 0; - AVPacket pkt; - int ret; - - while (!(ret = get_video_frame(priv->is, priv->frame, &pts, &pkt))) - av_free_packet(&pkt); - if (ret < 0) - return -1; - - if (priv->use_dr1) { - picref = avfilter_ref_buffer(priv->frame->opaque, ~0); - } else { - picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h); - av_image_copy(picref->data, picref->linesize, - priv->frame->data, priv->frame->linesize, - picref->format, link->w, link->h); - } - av_free_packet(&pkt); - - avfilter_copy_frame_props(picref, priv->frame); - picref->pts = pts; - - avfilter_start_frame(link, picref); - avfilter_draw_slice(link, 0, link->h, 1); - avfilter_end_frame(link); - - return 0; -} - -static int input_query_formats(AVFilterContext *ctx) -{ - FilterPriv *priv = ctx->priv; - enum PixelFormat pix_fmts[] = { - priv->is->video_st->codec->pix_fmt, PIX_FMT_NONE - }; - - avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); - return 0; -} - -static int input_config_props(AVFilterLink *link) -{ - FilterPriv *priv = link->src->priv; - AVCodecContext *c = priv->is->video_st->codec; - - link->w = c->width; - link->h = c->height; - link->time_base = priv->is->video_st->time_base; - - return 0; -} - -static AVFilter input_filter = -{ - .name = "avplay_input", - - .priv_size = sizeof(FilterPriv), - - .init = input_init, - .uninit = input_uninit, - - .query_formats = input_query_formats, - - .inputs = (AVFilterPad[]) {{ .name = NULL }}, - .outputs = (AVFilterPad[]) {{ .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .request_frame = input_request_frame, - .config_props = input_config_props, }, - { .name = NULL }}, -}; - static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters) { - static const enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE }; char sws_flags_str[128]; + char buffersrc_args[256]; int ret; - SinkContext sink_ctx = { .pix_fmts = pix_fmts }; - AVFilterContext *filt_src = NULL, *filt_out = NULL; + AVFilterContext *filt_src = NULL, *filt_out = NULL, *filt_format; + AVCodecContext *codec = is->video_st->codec; + snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags); graph->scale_sws_opts = av_strdup(sws_flags_str); - if ((ret = avfilter_graph_create_filter(&filt_src, &input_filter, "src", - NULL, is, graph)) < 0) + snprintf(buffersrc_args, sizeof(buffersrc_args), "%d:%d:%d:%d:%d:%d:%d", + codec->width, codec->height, codec->pix_fmt, + is->video_st->time_base.num, is->video_st->time_base.den, + codec->sample_aspect_ratio.num, codec->sample_aspect_ratio.den); + + + if ((ret = avfilter_graph_create_filter(&filt_src, + avfilter_get_by_name("buffer"), + "src", buffersrc_args, NULL, + graph)) < 0) + return ret; + if ((ret = avfilter_graph_create_filter(&filt_out, + avfilter_get_by_name("buffersink"), + "out", NULL, NULL, graph)) < 0) + return ret; + + if ((ret = avfilter_graph_create_filter(&filt_format, + avfilter_get_by_name("format"), + "format", "yuv420p", NULL, graph)) < 0) return ret; - if ((ret = avfilter_graph_create_filter(&filt_out, &sink, "out", - NULL, &sink_ctx, graph)) < 0) + if ((ret = avfilter_link(filt_format, 0, filt_out, 0)) < 0) return ret; + if (vfilters) { AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); @@ -1733,22 +1559,30 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c outputs->next = NULL; inputs->name = av_strdup("out"); - inputs->filter_ctx = filt_out; + inputs->filter_ctx = filt_format; inputs->pad_idx = 0; inputs->next = NULL; if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0) return ret; } else { - if ((ret = avfilter_link(filt_src, 0, filt_out, 0)) < 0) + if ((ret = avfilter_link(filt_src, 0, filt_format, 0)) < 0) return ret; } if ((ret = avfilter_graph_config(graph, NULL)) < 0) return ret; + is->in_video_filter = filt_src; is->out_video_filter = filt_out; + if (codec->codec->capabilities & CODEC_CAP_DR1) { + is->use_dr1 = 1; + codec->get_buffer = codec_get_buffer; + codec->release_buffer = codec_release_buffer; + codec->opaque = &is->buffer_pool; + } + return ret; } @@ -1756,6 +1590,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c static int video_thread(void *arg) { + AVPacket pkt = { 0 }; VideoState *is = arg; AVFrame *frame = avcodec_alloc_frame(); int64_t pts_int; @@ -1764,25 +1599,34 @@ static int video_thread(void *arg) #if CONFIG_AVFILTER AVFilterGraph *graph = avfilter_graph_alloc(); - AVFilterContext *filt_out = NULL; + AVFilterContext *filt_out = NULL, *filt_in = NULL; int64_t pos; int last_w = is->video_st->codec->width; int last_h = is->video_st->codec->height; if ((ret = configure_video_filters(graph, is, vfilters)) < 0) goto the_end; + filt_in = is->in_video_filter; filt_out = is->out_video_filter; #endif for (;;) { -#if !CONFIG_AVFILTER - AVPacket pkt; -#else +#if CONFIG_AVFILTER AVFilterBufferRef *picref; AVRational tb; #endif while (is->paused && !is->videoq.abort_request) SDL_Delay(10); + + av_free_packet(&pkt); + + ret = get_video_frame(is, frame, &pts_int, &pkt); + if (ret < 0) + goto the_end; + + if (!ret) + continue; + #if CONFIG_AVFILTER if ( last_w != is->video_st->codec->width || last_h != is->video_st->codec->height) { @@ -1792,43 +1636,61 @@ static int video_thread(void *arg) graph = avfilter_graph_alloc(); if ((ret = configure_video_filters(graph, is, vfilters)) < 0) goto the_end; + filt_in = is->in_video_filter; filt_out = is->out_video_filter; last_w = is->video_st->codec->width; last_h = is->video_st->codec->height; } - ret = get_filtered_video_frame(filt_out, frame, &picref, &tb); - if (picref) { + + frame->pts = pts_int; + if (is->use_dr1) { + FrameBuffer *buf = frame->opaque; + AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays( + frame->data, frame->linesize, + AV_PERM_READ | AV_PERM_PRESERVE, + frame->width, frame->height, + frame->format); + + avfilter_copy_frame_props(fb, frame); + fb->buf->priv = buf; + fb->buf->free = filter_release_buffer; + + buf->refcount++; + av_buffersrc_buffer(filt_in, fb); + + } else + av_buffersrc_write_frame(filt_in, frame); + + while (ret >= 0) { + ret = av_buffersink_read(filt_out, &picref); + if (ret < 0) { + ret = 0; + break; + } + + avfilter_copy_buf_props(frame, picref); + pts_int = picref->pts; + tb = filt_out->inputs[0]->time_base; pos = picref->pos; frame->opaque = picref; - } - if (ret >= 0 && av_cmp_q(tb, is->video_st->time_base)) { - av_unused int64_t pts1 = pts_int; - pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base); - av_dlog(NULL, "video_thread(): " - "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n", - tb.num, tb.den, pts1, - is->video_st->time_base.num, is->video_st->time_base.den, pts_int); + if (av_cmp_q(tb, is->video_st->time_base)) { + av_unused int64_t pts1 = pts_int; + pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base); + av_dlog(NULL, "video_thread(): " + "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n", + tb.num, tb.den, pts1, + is->video_st->time_base.num, is->video_st->time_base.den, pts_int); + } + pts = pts_int * av_q2d(is->video_st->time_base); + ret = output_picture2(is, frame, pts, pos); } #else - ret = get_video_frame(is, frame, &pts_int, &pkt); -#endif - - if (ret < 0) - goto the_end; - - if (!ret) - continue; - pts = pts_int * av_q2d(is->video_st->time_base); - -#if CONFIG_AVFILTER - ret = output_picture2(is, frame, pts, pos); -#else ret = output_picture2(is, frame, pts, pkt.pos); - av_free_packet(&pkt); #endif + if (ret < 0) goto the_end; @@ -1841,6 +1703,7 @@ static int video_thread(void *arg) av_freep(&vfilters); avfilter_graph_free(&graph); #endif + av_free_packet(&pkt); av_free(frame); return 0; } @@ -2060,23 +1923,23 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) dec->channel_layout != is->resample_channel_layout; if ((!is->avr && audio_resample) || resample_changed) { + int ret; if (is->avr) avresample_close(is->avr); else if (audio_resample) { - int ret; is->avr = avresample_alloc_context(); if (!is->avr) { fprintf(stderr, "error allocating AVAudioResampleContext\n"); break; } + } + if (audio_resample) { av_opt_set_int(is->avr, "in_channel_layout", dec->channel_layout, 0); av_opt_set_int(is->avr, "in_sample_fmt", dec->sample_fmt, 0); av_opt_set_int(is->avr, "in_sample_rate", dec->sample_rate, 0); av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0); av_opt_set_int(is->avr, "out_sample_fmt", is->sdl_sample_fmt, 0); av_opt_set_int(is->avr, "out_sample_rate", dec->sample_rate, 0); - if (av_get_bytes_per_sample(dec->sample_fmt) <= 2) - av_opt_set_int(is->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0); if ((ret = avresample_open(is->avr)) < 0) { fprintf(stderr, "error initializing libavresample\n"); @@ -2212,7 +2075,7 @@ static int stream_component_open(VideoState *is, int stream_index) return -1; avctx = ic->streams[stream_index]->codec; - opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index]); + opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], NULL); codec = avcodec_find_decoder(avctx->codec_id); avctx->debug_mv = debug_mv; @@ -2371,6 +2234,9 @@ static void stream_component_close(VideoState *is, int stream_index) ic->streams[stream_index]->discard = AVDISCARD_ALL; avcodec_close(avctx); +#if CONFIG_AVFILTER + free_buffer_pool(&is->buffer_pool); +#endif switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: is->audio_st = NULL; @@ -2567,10 +2433,11 @@ static int decode_thread(void *arg) } /* if the queue are full, no need to read more */ - if ( is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE + if (!infinite_buffer && + (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE || ( (is->audioq .size > MIN_AUDIOQ_SIZE || is->audio_stream < 0) && (is->videoq .nb_packets > MIN_FRAMES || is->video_stream < 0) - && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0))) { + && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0)))) { /* wait 10 ms */ SDL_Delay(10); continue; @@ -2738,13 +2605,13 @@ static void stream_cycle_channel(VideoState *is, int codec_type) static void toggle_full_screen(void) { - is_full_screen = !is_full_screen; #if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14) /* OS X needs to empty the picture_queue */ - for (int i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) { + int i; + for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) cur_stream->pictq[i].reallocate = 1; - } #endif + is_full_screen = !is_full_screen; video_open(cur_stream); } @@ -2924,26 +2791,26 @@ static void event_loop(void) } } -static int opt_frame_size(const char *opt, const char *arg) +static int opt_frame_size(void *optctx, const char *opt, const char *arg) { av_log(NULL, AV_LOG_ERROR, "Option '%s' has been removed, use private format options instead\n", opt); return AVERROR(EINVAL); } -static int opt_width(const char *opt, const char *arg) +static int opt_width(void *optctx, const char *opt, const char *arg) { screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX); return 0; } -static int opt_height(const char *opt, const char *arg) +static int opt_height(void *optctx, const char *opt, const char *arg) { screen_height = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX); return 0; } -static int opt_format(const char *opt, const char *arg) +static int opt_format(void *optctx, const char *opt, const char *arg) { file_iformat = av_find_input_format(arg); if (!file_iformat) { @@ -2953,14 +2820,14 @@ static int opt_format(const char *opt, const char *arg) return 0; } -static int opt_frame_pix_fmt(const char *opt, const char *arg) +static int opt_frame_pix_fmt(void *optctx, const char *opt, const char *arg) { av_log(NULL, AV_LOG_ERROR, "Option '%s' has been removed, use private format options instead\n", opt); return AVERROR(EINVAL); } -static int opt_sync(const char *opt, const char *arg) +static int opt_sync(void *optctx, const char *opt, const char *arg) { if (!strcmp(arg, "audio")) av_sync_type = AV_SYNC_AUDIO_MASTER; @@ -2975,26 +2842,26 @@ static int opt_sync(const char *opt, const char *arg) return 0; } -static int opt_seek(const char *opt, const char *arg) +static int opt_seek(void *optctx, const char *opt, const char *arg) { start_time = parse_time_or_die(opt, arg, 1); return 0; } -static int opt_duration(const char *opt, const char *arg) +static int opt_duration(void *optctx, const char *opt, const char *arg) { duration = parse_time_or_die(opt, arg, 1); return 0; } -static int opt_debug(const char *opt, const char *arg) +static int opt_debug(void *optctx, const char *opt, const char *arg) { av_log_set_level(99); debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); return 0; } -static int opt_vismv(const char *opt, const char *arg) +static int opt_vismv(void *optctx, const char *opt, const char *arg) { debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); return 0; @@ -3002,45 +2869,46 @@ static int opt_vismv(const char *opt, const char *arg) static const OptionDef options[] = { #include "cmdutils_common_opts.h" - { "x", HAS_ARG, { (void*)opt_width }, "force displayed width", "width" }, - { "y", HAS_ARG, { (void*)opt_height }, "force displayed height", "height" }, - { "s", HAS_ARG | OPT_VIDEO, { (void*)opt_frame_size }, "set frame size (WxH or abbreviation)", "size" }, - { "fs", OPT_BOOL, { (void*)&is_full_screen }, "force full screen" }, - { "an", OPT_BOOL, { (void*)&audio_disable }, "disable audio" }, - { "vn", OPT_BOOL, { (void*)&video_disable }, "disable video" }, - { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&wanted_stream[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_number" }, - { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&wanted_stream[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_number" }, - { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&wanted_stream[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_number" }, - { "ss", HAS_ARG, { (void*)&opt_seek }, "seek to a given position in seconds", "pos" }, - { "t", HAS_ARG, { (void*)&opt_duration }, "play \"duration\" seconds of audio/video", "duration" }, - { "bytes", OPT_INT | HAS_ARG, { (void*)&seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" }, - { "nodisp", OPT_BOOL, { (void*)&display_disable }, "disable graphical display" }, - { "f", HAS_ARG, { (void*)opt_format }, "force format", "fmt" }, - { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { (void*)opt_frame_pix_fmt }, "set pixel format", "format" }, - { "stats", OPT_BOOL | OPT_EXPERT, { (void*)&show_status }, "show status", "" }, - { "debug", HAS_ARG | OPT_EXPERT, { (void*)opt_debug }, "print specific debug info", "" }, - { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&workaround_bugs }, "workaround bugs", "" }, - { "vismv", HAS_ARG | OPT_EXPERT, { (void*)opt_vismv }, "visualize motion vectors", "" }, - { "fast", OPT_BOOL | OPT_EXPERT, { (void*)&fast }, "non spec compliant optimizations", "" }, - { "genpts", OPT_BOOL | OPT_EXPERT, { (void*)&genpts }, "generate pts", "" }, - { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""}, - { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_loop_filter }, "", "" }, - { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_frame }, "", "" }, - { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_idct }, "", "" }, - { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&idct }, "set idct algo", "algo" }, - { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&error_concealment }, "set error concealment options", "bit_mask" }, - { "sync", HAS_ARG | OPT_EXPERT, { (void*)opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" }, - { "autoexit", OPT_BOOL | OPT_EXPERT, { (void*)&autoexit }, "exit at the end", "" }, - { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { (void*)&exit_on_keydown }, "exit on key down", "" }, - { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { (void*)&exit_on_mousedown }, "exit on mouse down", "" }, - { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&loop }, "set number of times the playback shall be looped", "loop count" }, - { "framedrop", OPT_BOOL | OPT_EXPERT, { (void*)&framedrop }, "drop frames when cpu is too slow", "" }, - { "window_title", OPT_STRING | HAS_ARG, { (void*)&window_title }, "set window title", "window title" }, + { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" }, + { "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" }, + { "s", HAS_ARG | OPT_VIDEO, { .func_arg = opt_frame_size }, "set frame size (WxH or abbreviation)", "size" }, + { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" }, + { "an", OPT_BOOL, { &audio_disable }, "disable audio" }, + { "vn", OPT_BOOL, { &video_disable }, "disable video" }, + { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_number" }, + { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_number" }, + { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_number" }, + { "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" }, + { "t", HAS_ARG, { .func_arg = opt_duration }, "play \"duration\" seconds of audio/video", "duration" }, + { "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" }, + { "nodisp", OPT_BOOL, { &display_disable }, "disable graphical display" }, + { "f", HAS_ARG, { .func_arg = opt_format }, "force format", "fmt" }, + { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_frame_pix_fmt }, "set pixel format", "format" }, + { "stats", OPT_BOOL | OPT_EXPERT, { &show_status }, "show status", "" }, + { "debug", HAS_ARG | OPT_EXPERT, { .func_arg = opt_debug }, "print specific debug info", "" }, + { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, { &workaround_bugs }, "workaround bugs", "" }, + { "vismv", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vismv }, "visualize motion vectors", "" }, + { "fast", OPT_BOOL | OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" }, + { "genpts", OPT_BOOL | OPT_EXPERT, { &genpts }, "generate pts", "" }, + { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { &decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""}, + { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_loop_filter }, "", "" }, + { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_frame }, "", "" }, + { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, { &skip_idct }, "", "" }, + { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, { &idct }, "set idct algo", "algo" }, + { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, { &error_concealment }, "set error concealment options", "bit_mask" }, + { "sync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" }, + { "autoexit", OPT_BOOL | OPT_EXPERT, { &autoexit }, "exit at the end", "" }, + { "exitonkeydown", OPT_BOOL | OPT_EXPERT, { &exit_on_keydown }, "exit on key down", "" }, + { "exitonmousedown", OPT_BOOL | OPT_EXPERT, { &exit_on_mousedown }, "exit on mouse down", "" }, + { "loop", OPT_INT | HAS_ARG | OPT_EXPERT, { &loop }, "set number of times the playback shall be looped", "loop count" }, + { "framedrop", OPT_BOOL | OPT_EXPERT, { &framedrop }, "drop frames when cpu is too slow", "" }, + { "infbuf", OPT_BOOL | OPT_EXPERT, { &infinite_buffer }, "don't limit the input buffer size (useful with realtime streams)", "" }, + { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" }, #if CONFIG_AVFILTER - { "vf", OPT_STRING | HAS_ARG, { (void*)&vfilters }, "video filters", "filter list" }, + { "vf", OPT_STRING | HAS_ARG, { &vfilters }, "video filters", "filter list" }, #endif - { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { (void*)&rdftspeed }, "rdft speed", "msecs" }, - { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { (void*)opt_default }, "generic catch all option", "" }, + { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" }, + { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { opt_default }, "generic catch all option", "" }, { "i", 0, { NULL }, "avconv compatibility dummy option", ""}, { NULL, }, }; @@ -3052,14 +2920,12 @@ static void show_usage(void) printf("\n"); } -static void show_help(void) +void show_help_default(const char *opt, const char *arg) { av_log_set_callback(log_callback_help); show_usage(); - show_help_options(options, "Main options:\n", - OPT_EXPERT, 0); - show_help_options(options, "\nAdvanced options:\n", - OPT_EXPERT, OPT_EXPERT); + show_help_options(options, "Main options:", 0, OPT_EXPERT, 0); + show_help_options(options, "Advanced options:", OPT_EXPERT, 0, 0); printf("\n"); show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM); show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);