Skip to content
Snippets Groups Projects
ffplay.c 114 KiB
Newer Older
  • Learn to ignore specific revisions
  • Fabrice Bellard's avatar
    Fabrice Bellard committed
                    goto do_seek;
                case SDLK_RIGHT:
                    incr = 10.0;
                    goto do_seek;
                case SDLK_UP:
                    incr = 60.0;
                    goto do_seek;
                case SDLK_DOWN:
                    incr = -60.0;
                do_seek:
    
                        if (seek_by_bytes) {
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
                            if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos >= 0) {
                                pos = cur_stream->video_current_pos;
                            } else if (cur_stream->audio_stream >= 0 && cur_stream->audio_pkt.pos >= 0) {
                                pos = cur_stream->audio_pkt.pos;
                            } else
    
                                pos = avio_tell(cur_stream->ic->pb);
    
                            if (cur_stream->ic->bit_rate)
    
                                incr *= cur_stream->ic->bit_rate / 8.0;
    
                            else
                                incr *= 180000.0;
                            pos += incr;
    
                        } else {
                            pos = get_master_clock(cur_stream);
                            pos += incr;
    
                            if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
                                pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
    
                            stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                    break;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                default:
                    break;
                }
                break;
    
            case SDL_VIDEOEXPOSE:
                cur_stream->force_refresh = 1;
                break;
    
                    do_exit(cur_stream);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
            case SDL_MOUSEMOTION:
    
                if (cursor_hidden) {
                    SDL_ShowCursor(1);
                    cursor_hidden = 0;
                }
                cursor_last_shown = av_gettime();
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
                if (event.type == SDL_MOUSEBUTTONDOWN) {
                    x = event.button.x;
                } else {
                    if (event.motion.state != SDL_PRESSED)
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                        break;
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
                    x = event.motion.x;
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
                    if (seek_by_bytes || cur_stream->ic->duration <= 0) {
                        uint64_t size =  avio_size(cur_stream->ic->pb);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                        stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
                    } else {
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                        int64_t ts;
                        int ns, hh, mm, ss;
                        int tns, thh, tmm, tss;
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
                        tns  = cur_stream->ic->duration / 1000000LL;
                        thh  = tns / 3600;
                        tmm  = (tns % 3600) / 60;
                        tss  = (tns % 60);
                        frac = x / cur_stream->width;
                        ns   = frac * tns;
                        hh   = ns / 3600;
                        mm   = (ns % 3600) / 60;
                        ss   = (ns % 60);
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                        fprintf(stderr, "Seek to %2.0f%% (%2d:%02d:%02d) of total duration (%2d:%02d:%02d)       \n", frac*100,
                                hh, mm, ss, thh, tmm, tss);
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
                        ts = frac * cur_stream->ic->duration;
    
    Michael Niedermayer's avatar
    Michael Niedermayer committed
                        if (cur_stream->ic->start_time != AV_NOPTS_VALUE)
                            ts += cur_stream->ic->start_time;
                        stream_seek(cur_stream, ts, 0, 0);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            case SDL_VIDEORESIZE:
    
                    screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                                              SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
    
    Aneesh Dogra's avatar
    Aneesh Dogra committed
                    screen_width  = cur_stream->width  = event.resize.w;
                    screen_height = cur_stream->height = event.resize.h;
    
                    cur_stream->force_refresh = 1;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
            case SDL_QUIT:
    
                do_exit(cur_stream);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
                break;
            case FF_ALLOC_EVENT:
                alloc_picture(event.user.data1);
                break;
            default:
                break;
            }
        }
    }
    
    
    static int opt_frame_size(void *optctx, const char *opt, const char *arg)
    
        av_log(NULL, AV_LOG_WARNING, "Option -s is deprecated, use -video_size.\n");
    
        return opt_default(NULL, "video_size", 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(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(void *optctx, const char *opt, const char *arg)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        file_iformat = av_find_input_format(arg);
        if (!file_iformat) {
            fprintf(stderr, "Unknown input format: %s\n", arg);
    
            return AVERROR(EINVAL);
    
        return 0;
    
    static int opt_frame_pix_fmt(void *optctx, const char *opt, const char *arg)
    
        av_log(NULL, AV_LOG_WARNING, "Option -pix_fmt is deprecated, use -pixel_format.\n");
    
        return opt_default(NULL, "pixel_format", arg);
    
    static int opt_sync(void *optctx, const char *opt, const char *arg)
    
    {
        if (!strcmp(arg, "audio"))
            av_sync_type = AV_SYNC_AUDIO_MASTER;
        else if (!strcmp(arg, "video"))
            av_sync_type = AV_SYNC_VIDEO_MASTER;
        else if (!strcmp(arg, "ext"))
            av_sync_type = AV_SYNC_EXTERNAL_CLOCK;
    
            fprintf(stderr, "Unknown value for %s: %s\n", opt, 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(void *optctx, const char *opt, const char *arg)
    
    Robert Krüger's avatar
    Robert Krüger committed
    {
        duration = parse_time_or_die(opt, arg, 1);
        return 0;
    }
    
    
    static int opt_show_mode(void *optctx, const char *opt, const char *arg)
    
    {
        show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
                    !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
                    !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT  :
                    parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1);
        return 0;
    }
    
    
    static void opt_input_file(void *optctx, const char *filename)
    
    {
        if (input_filename) {
            fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
                    filename, input_filename);
    
        }
        if (!strcmp(filename, "-"))
            filename = "pipe:";
        input_filename = filename;
    }
    
    
    static int opt_codec(void *optctx, const char *opt, const char *arg)
    
       const char *spec = strchr(opt, ':');
       if (!spec) {
           fprintf(stderr, "No media specifier was specified in '%s' in option '%s'\n",
                   arg, opt);
           return AVERROR(EINVAL);
       }
       spec++;
       switch (spec[0]) {
       case 'a' :    audio_codec_name = arg; break;
       case 's' : subtitle_codec_name = arg; break;
       case 'v' :    video_codec_name = arg; break;
       default:
           fprintf(stderr, "Invalid media specifier '%s' in option '%s'\n", spec, opt);
           return AVERROR(EINVAL);
       }
       return 0;
    
    #include "cmdutils_common_opts.h"
    
        { "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", ""},
        { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, { &lowres }, "", "" },
        { "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, { &vfilters }, "set video filters", "filter_graph" },
    
        { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
        { "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
        { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default }, "generic catch all option", "" },
        { "i", OPT_BOOL, { &dummy}, "read specified file", "input_file"},
    
        { "codec", HAS_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" },
        { "acodec", HAS_ARG | OPT_STRING | OPT_EXPERT, {    &audio_codec_name }, "force audio decoder",    "decoder_name" },
        { "scodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &subtitle_codec_name }, "force subtitle decoder", "decoder_name" },
        { "vcodec", HAS_ARG | OPT_STRING | OPT_EXPERT, {    &video_codec_name }, "force video decoder",    "decoder_name" },
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        { NULL, },
    };
    
    
    static void show_usage(void)
    
        av_log(NULL, AV_LOG_INFO, "Simple media player\n");
        av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
        av_log(NULL, AV_LOG_INFO, "\n");
    
    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:", 0, OPT_EXPERT, 0);
        show_help_options(options, "Advanced options:", OPT_EXPERT, 0, 0);
    
        show_help_children(avcodec_get_class(), AV_OPT_FLAG_DECODING_PARAM);
        show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
    
    #if !CONFIG_AVFILTER
    
        show_help_children(sws_get_class(), AV_OPT_FLAG_ENCODING_PARAM);
    
    #else
        show_help_children(avfilter_get_class(), AV_OPT_FLAG_FILTERING_PARAM);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        printf("\nWhile playing:\n"
               "q, ESC              quit\n"
               "f                   toggle full screen\n"
               "p, SPC              pause\n"
    
               "a                   cycle audio channel\n"
               "v                   cycle video channel\n"
    
               "s                   activate frame-step mode\n"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
               "left/right          seek backward/forward 10 seconds\n"
               "down/up             seek backward/forward 1 minute\n"
    
               "page down/page up   seek backward/forward 10 minutes\n"
    
               "mouse click         seek to percentage in file corresponding to fraction of width\n"
    
    static int lockmgr(void **mtx, enum AVLockOp op)
    {
       switch(op) {
          case AV_LOCK_CREATE:
              *mtx = SDL_CreateMutex();
              if(!*mtx)
                  return 1;
              return 0;
          case AV_LOCK_OBTAIN:
              return !!SDL_LockMutex(*mtx);
          case AV_LOCK_RELEASE:
              return !!SDL_UnlockMutex(*mtx);
          case AV_LOCK_DESTROY:
              SDL_DestroyMutex(*mtx);
              return 0;
       }
       return 1;
    }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    /* Called from the main */
    int main(int argc, char **argv)
    {
    
        char dummy_videodriver[] = "SDL_VIDEODRIVER=dummy";
    
        av_log_set_flags(AV_LOG_SKIP_REPEATED);
    
        parse_loglevel(argc, argv, options);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* register all codecs, demux and protocols */
    
    Luca Abeni's avatar
    Luca Abeni committed
        avcodec_register_all();
    
    Luca Abeni's avatar
    Luca Abeni committed
        avdevice_register_all();
    
    #if CONFIG_AVFILTER
        avfilter_register_all();
    #endif
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        av_register_all();
    
        avformat_network_init();
    
        signal(SIGINT , sigterm_handler); /* Interrupt (ANSI).    */
        signal(SIGTERM, sigterm_handler); /* Termination (ANSI).  */
    
    
        show_banner(argc, argv, options);
    
        parse_options(NULL, argc, argv, options, opt_input_file);
    
            fprintf(stderr, "An input file must be specified\n");
    
    Anton Khirnov's avatar
    Anton Khirnov committed
            fprintf(stderr, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        if (display_disable) {
            video_disable = 1;
        }
    
        flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
    
        if (audio_disable)
            flags &= ~SDL_INIT_AUDIO;
    
        if (display_disable)
            SDL_putenv(dummy_videodriver); /* For the event queue, we always need a video driver. */
    
    #if !defined(__MINGW32__) && !defined(__APPLE__)
        flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (SDL_Init (flags)) {
    
            fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
    
            fprintf(stderr, "(Did you set the DISPLAY variable?)\n");
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
            exit(1);
        }
    
        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;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
        SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
        SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
        SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
    
    
        if (av_lockmgr_register(lockmgr)) {
            fprintf(stderr, "Could not initialize lock manager!\n");
            do_exit(NULL);
        }
    
    
        av_init_packet(&flush_pkt);
    
        flush_pkt.data = (char *)(intptr_t)"FLUSH";
    
        is = stream_open(input_filename, file_iformat);
        if (!is) {
            fprintf(stderr, "Failed to initialize VideoState!\n");
            do_exit(NULL);
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
        /* never returns */
    
        return 0;
    }