ffplay 的事件处理分析
ffplay 的事件处理分析
曾经花田错 发表于11个月前
ffplay 的事件处理分析
  • 发表于 11个月前
  • 阅读 90
  • 收藏 0
  • 点赞 0
  • 评论 0

标题:腾讯云 新注册用户域名抢购1元起>>>   

ffplay 的事件处理依赖于SDL。在 main 函数中:

...
flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
...
if (SDL_Init (flags)) {
        av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError());
        av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
        exit(1);
    }

以上代码完成SDL的初始化工作,其中包含SDL_EVENT的初始化。

事件处理都是在 event_loop 中进行:

/* handle an event sent by the GUI */
static void event_loop(VideoState *cur_stream)
{
    SDL_Event event;
    double incr, pos, frac;

    for (;;) {
        double x;
        refresh_loop_wait_event(cur_stream, &event);
        switch (event.type) {
        case SDL_KEYDOWN:
            if (exit_on_keydown) {
                do_exit(cur_stream);
                break;
            }
            switch (event.key.keysym.sym) {
            case SDLK_ESCAPE:
            case SDLK_q:
                do_exit(cur_stream);
                break;
            case SDLK_f:
                toggle_full_screen(cur_stream);
                cur_stream->force_refresh = 1;
                break;
            ...
            break;

        case SDL_VIDEOEXPOSE:
            cur_stream->force_refresh = 1;
            break;

        case SDL_MOUSEBUTTONDOWN:
            ...

        case SDL_MOUSEMOTION:
            ...
            break;

        case SDL_VIDEORESIZE:
            ...
            break;

        case SDL_QUIT:
        case FF_QUIT_EVENT:
            do_exit(cur_stream);
            break;
        case FF_ALLOC_EVENT:
            alloc_picture(event.user.data1);
            break;
        default:
            break;
        }
    }
}

event_loop 中有循环不停的获取事件,具体的获取事件及刷新视频的操作在函数 refresh_loop_wait_event 中完成。

static void refresh_loop_wait_event(VideoState *is, SDL_Event *event)
{
    double remaining_time = 0.0;
    SDL_PumpEvents();//更新事件队列
    while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS))
    {
        /* 根据时间差值判断是否隐藏焦点 */
        if (!cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY)
        {
            SDL_ShowCursor(0);
            cursor_hidden = 1;
        }

        if (remaining_time > 0.0)
            av_usleep((int64_t)(remaining_time * 1000000.0));
        remaining_time = REFRESH_RATE;
        if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh))
            video_refresh(is, &remaining_time);
        SDL_PumpEvents();
    }
}

其中,SDL_PumpEvents 函数主动收集来自输入设备的事件,填入事件循环中,从而更新事件队列。

SDL_PeepEvents 会检查事件队列,如果队列中有事件,回取出事件进行处理;如果没有则会按照REFRESH_RATE的延迟去刷新视频。

具体的SDL事件机制可以参考 https://my.oschina.net/u/735973/blog/832117 。

标签: ffplay 事件处理 SDL
共有 人打赏支持
粉丝 3
博文 32
码字总数 38676
×
曾经花田错
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: