X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=avplay.c;h=432db978236dbdd84ff69a72fb6ef76c664a5450;hb=2f6eec65acc953faed3951fb8f1eabed830fdd2f;hp=0d72f466f991c2607c02818c56a9ad56c2ec4831;hpb=2bcbd98459915baefc15043d02f4a942ebcd33da;p=ffmpeg diff --git a/avplay.c b/avplay.c index 0d72f466f99..432db978236 100644 --- a/avplay.c +++ b/avplay.c @@ -23,6 +23,8 @@ #include #include #include +#include + #include "libavutil/avstring.h" #include "libavutil/colorspace.h" #include "libavutil/mathematics.h" @@ -31,16 +33,18 @@ #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" -#include "libavcodec/audioconvert.h" +#include "libavresample/avresample.h" #include "libavutil/opt.h" #include "libavcodec/avfft.h" #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 +56,6 @@ #undef main /* We don't want SDL to override our main() */ #endif -#include #include const char program_name[] = "avplay"; @@ -82,7 +85,7 @@ const int program_birth_year = 2003; /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */ #define SAMPLE_ARRAY_SIZE (2 * 65536) -static int sws_flags = SWS_BICUBIC; +static int64_t sws_flags = SWS_BICUBIC; typedef struct PacketQueue { AVPacketList *first_pkt, *last_pkt; @@ -97,18 +100,16 @@ typedef struct PacketQueue { #define SUBPICTURE_QUEUE_SIZE 4 typedef struct VideoPicture { - double pts; ///< presentation time stamp for this picture - double target_clock; ///< av_gettime() time at which this should be displayed ideally - int64_t pos; ///< byte position in file + double pts; // presentation timestamp for this picture + double target_clock; // av_gettime() time at which this should be displayed ideally + int64_t pos; // byte position in file SDL_Overlay *bmp; int width, height; /* source height & width */ int allocated; int reallocate; - enum PixelFormat pix_fmt; + enum AVPixelFormat pix_fmt; -#if CONFIG_AVFILTER - AVFilterBufferRef *picref; -#endif + AVRational sar; } VideoPicture; typedef struct SubPicture { @@ -159,8 +160,14 @@ typedef struct VideoState { int audio_buf_index; /* in bytes */ AVPacket audio_pkt_temp; AVPacket audio_pkt; - enum AVSampleFormat audio_src_fmt; - AVAudioConvert *reformat_ctx; + enum AVSampleFormat sdl_sample_fmt; + uint64_t sdl_channel_layout; + int sdl_channels; + int sdl_sample_rate; + enum AVSampleFormat resample_sample_fmt; + uint64_t resample_channel_layout; + int resample_sample_rate; + AVAudioResampleContext *avr; AVFrame *frame; int show_audio; /* if true, display audio samples */ @@ -185,13 +192,13 @@ typedef struct VideoState { double frame_timer; double frame_last_pts; double frame_last_delay; - double video_clock; ///< pts of last decoded frame / predicted pts of next decoded frame + double video_clock; // pts of last decoded frame / predicted pts of next decoded frame int video_stream; AVStream *video_st; PacketQueue videoq; - double video_current_pts; ///< current displayed pts (different from video_clock if frame fifos are used) - double video_current_pts_drift; ///< video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts - int64_t video_current_pos; ///< current displayed file pos + double video_current_pts; // current displayed pts (different from video_clock if frame fifos are used) + double video_current_pts_drift; // video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts + int64_t video_current_pos; // current displayed file pos VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE]; int pictq_size, pictq_rindex, pictq_windex; SDL_mutex *pictq_mutex; @@ -207,7 +214,8 @@ typedef struct VideoState { PtsCorrectionContext pts_ctx; #if CONFIG_AVFILTER - AVFilterContext *out_video_filter; ///< the last filter in the video chain + AVFilterContext *in_video_filter; // the first filter in the video chain + AVFilterContext *out_video_filter; // the last filter in the video chain #endif float skip_frames; @@ -215,8 +223,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; @@ -238,8 +244,6 @@ static int show_status = 1; static int av_sync_type = AV_SYNC_AUDIO_MASTER; static int64_t start_time = AV_NOPTS_VALUE; static int64_t duration = AV_NOPTS_VALUE; -static int debug = 0; -static int debug_mv = 0; static int step = 0; static int workaround_bugs = 1; static int fast = 0; @@ -255,6 +259,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 @@ -274,11 +279,6 @@ static AVPacket flush_pkt; static SDL_Surface *screen; -void exit_program(int ret) -{ - exit(ret); -} - static int packet_queue_put(PacketQueue *q, AVPacket *pkt); /* packet queue handling */ @@ -651,10 +651,10 @@ static void video_image_display(VideoState *is) vp = &is->pictq[is->pictq_rindex]; if (vp->bmp) { #if CONFIG_AVFILTER - if (vp->picref->video->pixel_aspect.num == 0) + if (!vp->sar.num) aspect_ratio = 0; else - aspect_ratio = av_q2d(vp->picref->video->pixel_aspect); + aspect_ratio = av_q2d(vp->sar); #else /* XXX: use variable in the frame */ @@ -743,7 +743,7 @@ static void video_audio_display(VideoState *s) nb_freq = 1 << (rdft_bits - 1); /* compute display index : center on currently output samples */ - channels = s->audio_st->codec->channels; + channels = s->sdl_channels; nb_display_channels = channels; if (!s->paused) { int data_used = s->show_audio == 1 ? s->width : (2 * nb_freq); @@ -755,7 +755,7 @@ static void video_audio_display(VideoState *s) the last buffer computation */ if (audio_callback_time) { time_diff = av_gettime() - audio_callback_time; - delay -= (time_diff * s->audio_st->codec->sample_rate) / 1000000; + delay -= (time_diff * s->sdl_sample_rate) / 1000000; } delay += 2 * data_used; @@ -848,7 +848,8 @@ static void video_audio_display(VideoState *s) } av_rdft_calc(s->rdft, data[ch]); } - // least efficient way to do this, we should of course directly access it but its more than fast enough + /* Least efficient way to do this, we should of course + * directly access it but it is more than fast enough. */ for (y = 0; y < s->height; y++) { double w = 1 / sqrt(nb_freq); int a = sqrt(w * sqrt(data[0][2 * y + 0] * data[0][2 * y + 0] + data[0][2 * y + 1] * data[0][2 * y + 1])); @@ -943,7 +944,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; } @@ -957,8 +958,8 @@ static double get_audio_clock(VideoState *is) hw_buf_size = audio_write_get_buf_size(is); bytes_per_sec = 0; if (is->audio_st) { - bytes_per_sec = is->audio_st->codec->sample_rate * - 2 * is->audio_st->codec->channels; + bytes_per_sec = is->sdl_sample_rate * is->sdl_channels * + av_get_bytes_per_sample(is->sdl_sample_fmt); } if (bytes_per_sec) pts -= (double)hw_buf_size / bytes_per_sec; @@ -1224,12 +1225,6 @@ static void stream_close(VideoState *is) /* free all pictures */ 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; - } -#endif if (vp->bmp) { SDL_FreeYUVOverlay(vp->bmp); vp->bmp = NULL; @@ -1253,9 +1248,6 @@ static void do_exit(void) cur_stream = NULL; } uninit_opts(); -#if CONFIG_AVFILTER - avfilter_uninit(); -#endif avformat_network_deinit(); if (show_status) printf("\n"); @@ -1277,10 +1269,6 @@ static void alloc_picture(void *opaque) SDL_FreeYUVOverlay(vp->bmp); #if CONFIG_AVFILTER - if (vp->picref) - avfilter_unref_buffer(vp->picref); - vp->picref = NULL; - vp->width = is->out_video_filter->inputs[0]->w; vp->height = is->out_video_filter->inputs[0]->h; vp->pix_fmt = is->out_video_filter->inputs[0]->format; @@ -1308,17 +1296,15 @@ static void alloc_picture(void *opaque) SDL_UnlockMutex(is->pictq_mutex); } -/** - * - * @param pts the dts of the pkt / pts of the frame and guessed if not known - */ +/* The 'pts' parameter is the dts of the packet / pts of the frame and + * guessed if not known. */ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos) { VideoPicture *vp; #if CONFIG_AVFILTER AVPicture pict_src; #else - int dst_pix_fmt = PIX_FMT_YUV420P; + int dst_pix_fmt = AV_PIX_FMT_YUV420P; #endif /* wait until we have space to put a new picture */ SDL_LockMutex(is->pictq_mutex); @@ -1371,11 +1357,6 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t /* if the frame is not skipped, then display it */ if (vp->bmp) { AVPicture pict = { { 0 } }; -#if CONFIG_AVFILTER - if (vp->picref) - avfilter_unref_buffer(vp->picref); - vp->picref = src_frame->opaque; -#endif /* get a pointer on the bitmap */ SDL_LockYUVOverlay (vp->bmp); @@ -1401,7 +1382,7 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t av_picture_copy(&pict, &pict_src, vp->pix_fmt, vp->width, vp->height); #else - sws_flags = av_get_int(sws_opts, "sws_flags", NULL); + av_opt_get_int(sws_opts, "sws_flags", 0, &sws_flags); is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx, vp->width, vp->height, vp->pix_fmt, vp->width, vp->height, dst_pix_fmt, sws_flags, NULL, NULL, NULL); @@ -1430,13 +1411,12 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t return 0; } -/** - * compute the exact PTS for the picture if it is omitted in the stream - * @param pts1 the dts of the pkt / pts of the frame - */ +/* Compute the exact PTS for the picture if it is omitted in the stream. + * The 'pts1' parameter is the dts of the packet / pts of the frame. */ static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos) { double frame_delay, pts; + int ret; pts = pts1; @@ -1453,7 +1433,9 @@ static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int6 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5); is->video_clock += frame_delay; - return queue_picture(is, src_frame, pts, pos); + ret = queue_picture(is, src_frame, pts, pos); + av_frame_unref(src_frame); + return ret; } static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt) @@ -1500,225 +1482,56 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke if (*pts == AV_NOPTS_VALUE) { *pts = 0; } + if (is->video_st->sample_aspect_ratio.num) { + frame->sample_aspect_ratio = is->video_st->sample_aspect_ratio; + } is->skip_frames_index += 1; if (is->skip_frames_index >= is->skip_frames) { is->skip_frames_index -= FFMAX(is->skip_frames, 1.0); return 1; } - + av_frame_unref(frame); } return 0; } #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) +static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters) { - FilterPriv *priv = link->src->priv; - AVFilterBufferRef *picref; - int64_t pts = 0; - AVPacket pkt; + char sws_flags_str[128]; + char buffersrc_args[256]; int ret; + AVFilterContext *filt_src = NULL, *filt_out = NULL, *filt_format; + AVCodecContext *codec = is->video_st->codec; - 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), + snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%"PRId64, sws_flags); + graph->scale_sws_opts = av_strdup(sws_flags_str); - .init = input_init, - .uninit = input_uninit, + 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); - .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]; - int ret; - SinkContext sink_ctx = { .pix_fmts = pix_fmts }; - AVFilterContext *filt_src = NULL, *filt_out = NULL; - 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, + 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_src, &input_filter, "src", - NULL, is, graph)) < 0) + 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(); @@ -1729,20 +1542,21 @@ 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; return ret; @@ -1752,33 +1566,41 @@ 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(); + AVFrame *frame = av_frame_alloc(); int64_t pts_int; double pts; int ret; #if CONFIG_AVFILTER AVFilterGraph *graph = avfilter_graph_alloc(); - AVFilterContext *filt_out = NULL; - int64_t pos; + AVFilterContext *filt_out = NULL, *filt_in = NULL; 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 - AVFilterBufferRef *picref; +#if CONFIG_AVFILTER 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) { @@ -1788,46 +1610,46 @@ 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) { - pts_int = picref->pts; - 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); - } -#else - ret = get_video_frame(is, frame, &pts_int, &pkt); -#endif + frame->pts = pts_int; + ret = av_buffersrc_add_frame(filt_in, frame); if (ret < 0) goto the_end; - if (!ret) - continue; - - pts = pts_int * av_q2d(is->video_st->time_base); + while (ret >= 0) { + ret = av_buffersink_get_frame(filt_out, frame); + if (ret < 0) { + ret = 0; + break; + } -#if CONFIG_AVFILTER - ret = output_picture2(is, frame, pts, pos); + pts_int = frame->pts; + tb = filt_out->inputs[0]->time_base; + 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, 0); + } #else + pts = pts_int * av_q2d(is->video_st->time_base); ret = output_picture2(is, frame, pts, pkt.pos); - av_free_packet(&pkt); #endif + if (ret < 0) goto the_end; + if (step) if (cur_stream) stream_pause(cur_stream); @@ -1837,7 +1659,8 @@ static int video_thread(void *arg) av_freep(&vfilters); avfilter_graph_free(&graph); #endif - av_free(frame); + av_free_packet(&pkt); + av_frame_free(&frame); return 0; } @@ -1937,7 +1760,7 @@ static int synchronize_audio(VideoState *is, short *samples, int n, samples_size; double ref_clock; - n = 2 * is->audio_st->codec->channels; + n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt); samples_size = samples_size1; /* if not master, then we try to remove or add samples to correct the clock */ @@ -1959,7 +1782,7 @@ static int synchronize_audio(VideoState *is, short *samples, avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef); if (fabs(avg_diff) >= is->audio_diff_threshold) { - wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n); + wanted_size = samples_size + ((int)(diff * is->sdl_sample_rate) * n); nb_samples = samples_size / n; min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n; @@ -2018,11 +1841,12 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) for (;;) { /* NOTE: the audio packet can contain several frames */ while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) { + int resample_changed, audio_resample; + if (!is->frame) { - if (!(is->frame = avcodec_alloc_frame())) + if (!(is->frame = av_frame_alloc())) return AVERROR(ENOMEM); - } else - avcodec_get_frame_defaults(is->frame); + } if (flush_complete) break; @@ -2045,41 +1869,72 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) } data_size = av_samples_get_buffer_size(NULL, dec->channels, is->frame->nb_samples, - dec->sample_fmt, 1); - - if (dec->sample_fmt != is->audio_src_fmt) { - if (is->reformat_ctx) - av_audio_convert_free(is->reformat_ctx); - is->reformat_ctx= av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, - dec->sample_fmt, 1, NULL, 0); - if (!is->reformat_ctx) { - fprintf(stderr, "Cannot convert %s sample format to %s sample format\n", - av_get_sample_fmt_name(dec->sample_fmt), - av_get_sample_fmt_name(AV_SAMPLE_FMT_S16)); + is->frame->format, 1); + + audio_resample = is->frame->format != is->sdl_sample_fmt || + is->frame->channel_layout != is->sdl_channel_layout || + is->frame->sample_rate != is->sdl_sample_rate; + + resample_changed = is->frame->format != is->resample_sample_fmt || + is->frame->channel_layout != is->resample_channel_layout || + is->frame->sample_rate != is->resample_sample_rate; + + if ((!is->avr && audio_resample) || resample_changed) { + int ret; + if (is->avr) + avresample_close(is->avr); + else if (audio_resample) { + 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", is->frame->channel_layout, 0); + av_opt_set_int(is->avr, "in_sample_fmt", is->frame->format, 0); + av_opt_set_int(is->avr, "in_sample_rate", is->frame->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", is->sdl_sample_rate, 0); + + if ((ret = avresample_open(is->avr)) < 0) { + fprintf(stderr, "error initializing libavresample\n"); + break; + } } - is->audio_src_fmt= dec->sample_fmt; + is->resample_sample_fmt = is->frame->format; + is->resample_channel_layout = is->frame->channel_layout; + is->resample_sample_rate = is->frame->sample_rate; } - if (is->reformat_ctx) { - const void *ibuf[6] = { is->frame->data[0] }; - void *obuf[6]; - int istride[6] = { av_get_bytes_per_sample(dec->sample_fmt) }; - int ostride[6] = { 2 }; - int len= data_size/istride[0]; - obuf[0] = av_realloc(is->audio_buf1, FFALIGN(len * ostride[0], 32)); - if (!obuf[0]) { + if (audio_resample) { + void *tmp_out; + int out_samples, out_size, out_linesize; + int osize = av_get_bytes_per_sample(is->sdl_sample_fmt); + int nb_samples = is->frame->nb_samples; + + out_size = av_samples_get_buffer_size(&out_linesize, + is->sdl_channels, + nb_samples, + is->sdl_sample_fmt, 0); + tmp_out = av_realloc(is->audio_buf1, out_size); + if (!tmp_out) return AVERROR(ENOMEM); - } - is->audio_buf1 = obuf[0]; - if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len) < 0) { - printf("av_audio_convert() failed\n"); + is->audio_buf1 = tmp_out; + + out_samples = avresample_convert(is->avr, + &is->audio_buf1, + out_linesize, nb_samples, + is->frame->data, + is->frame->linesize[0], + is->frame->nb_samples); + if (out_samples < 0) { + fprintf(stderr, "avresample_convert() failed\n"); break; } is->audio_buf = is->audio_buf1; - /* FIXME: existing code assume that data_size equals framesize*channels*2 - remove this legacy cruft */ - data_size = len * 2; + data_size = out_samples * osize * is->sdl_channels; } else { is->audio_buf = is->frame->data[0]; } @@ -2087,9 +1942,9 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) /* if no pts, then compute it */ pts = is->audio_clock; *pts_ptr = pts; - n = 2 * dec->channels; + n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt); is->audio_clock += (double)data_size / - (double)(n * dec->sample_rate); + (double)(n * is->sdl_sample_rate); #ifdef DEBUG { static double last_clock; @@ -2178,11 +2033,9 @@ 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; - avctx->debug = debug; avctx->workaround_bugs = workaround_bugs; avctx->idct_algo = idct; avctx->skip_frame = skip_frame; @@ -2194,6 +2047,8 @@ static int stream_component_open(VideoState *is, int stream_index) if (!av_dict_get(opts, "threads", NULL, 0)) av_dict_set(&opts, "threads", "auto", 0); + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) + av_dict_set(&opts, "refcounted_frames", "1", 0); if (!codec || avcodec_open2(avctx, codec, &opts) < 0) return -1; @@ -2204,9 +2059,23 @@ static int stream_component_open(VideoState *is, int stream_index) /* prepare audio output */ if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { - wanted_spec.freq = avctx->sample_rate; + is->sdl_sample_rate = avctx->sample_rate; + + if (!avctx->channel_layout) + avctx->channel_layout = av_get_default_channel_layout(avctx->channels); + if (!avctx->channel_layout) { + fprintf(stderr, "unable to guess channel layout\n"); + return -1; + } + if (avctx->channels == 1) + is->sdl_channel_layout = AV_CH_LAYOUT_MONO; + else + is->sdl_channel_layout = AV_CH_LAYOUT_STEREO; + is->sdl_channels = av_get_channel_layout_nb_channels(is->sdl_channel_layout); + wanted_spec.format = AUDIO_S16SYS; - wanted_spec.channels = avctx->channels; + wanted_spec.freq = is->sdl_sample_rate; + wanted_spec.channels = is->sdl_channels; wanted_spec.silence = 0; wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; wanted_spec.callback = sdl_audio_callback; @@ -2216,7 +2085,10 @@ static int stream_component_open(VideoState *is, int stream_index) return -1; } is->audio_hw_buf_size = spec.size; - is->audio_src_fmt = AV_SAMPLE_FMT_S16; + is->sdl_sample_fmt = AV_SAMPLE_FMT_S16; + is->resample_sample_fmt = is->sdl_sample_fmt; + is->resample_channel_layout = avctx->channel_layout; + is->resample_sample_rate = avctx->sample_rate; } ic->streams[stream_index]->discard = AVDISCARD_DEFAULT; @@ -2275,12 +2147,11 @@ static void stream_component_close(VideoState *is, int stream_index) packet_queue_end(&is->audioq); av_free_packet(&is->audio_pkt); - if (is->reformat_ctx) - av_audio_convert_free(is->reformat_ctx); - is->reformat_ctx = NULL; + if (is->avr) + avresample_free(&is->avr); av_freep(&is->audio_buf1); is->audio_buf = NULL; - av_freep(&is->frame); + av_frame_free(&is->frame); if (is->rdft) { av_rdft_end(is->rdft); @@ -2519,10 +2390,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; @@ -2690,13 +2562,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); } @@ -2876,26 +2748,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) { @@ -2905,14 +2777,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; @@ -2927,72 +2799,58 @@ 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) -{ - 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) -{ - debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); - return 0; -} - 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", "" }, + { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, { &workaround_bugs }, "workaround bugs", "" }, + { "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, }, }; @@ -3004,14 +2862,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); @@ -3090,11 +2946,9 @@ int main(int argc, char **argv) } if (!display_disable) { -#if HAVE_SDL_VIDEO_SIZE const SDL_VideoInfo *vi = SDL_GetVideoInfo(); fs_screen_width = vi->current_w; fs_screen_height = vi->current_h; -#endif } SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); @@ -3102,7 +2956,7 @@ int main(int argc, char **argv) SDL_EventState(SDL_USEREVENT, SDL_IGNORE); av_init_packet(&flush_pkt); - flush_pkt.data = "FLUSH"; + flush_pkt.data = (uint8_t *)&flush_pkt; cur_stream = stream_open(input_filename, file_iformat);