Qt音视频开发5-vlc事件订阅

2020-08-07 14:41:57 浏览数 (1)

一、前言

事件订阅可以拿到文件长度、播放进度、播放状态改变等信息,vlc的事件订阅机制封装的比较友好,只需要先创建一个事件管理器,然后逐个订阅自己感兴趣的需要的事件,不感兴趣的可以不要订阅,只有订阅了的事件才能在事件回调中拿到,所以如果在事件回调中发现一些事件没有拿到,首先要检查下到底订阅了没有,所有事件的枚举在libvlc_events.h头文件中可以查阅到,都用的是通俗易懂的全英文单词描述,有过基本英语能力的开发人员都能看懂。

在调用libvlc_event_attach订阅事件的时候,第三个参数指定事件回调函数,第四个参数传入用户数据,一般是用来传入类的指针,这样在事件回调的时候,可以直接拿到并转换为类指针,然后使用类中的方法,在对Qt4-Qt5的兼容过程中发现,Qt5中的信号是public的,所以可以直接在回调函数中emit发送信号,而Qt4中的信号是protected的,没法直接emit,所以需要做一个通用的中转函数,用来重新分发信号,通过参数type来控制类型,QVariantList来传入参数集合。

二、功能特点

  1. 多线程实时播放视频流和本地视频。
  2. 支持windows linux mac,支持vlc2和vlc3。
  3. 多线程显示图像,不卡主界面。
  4. 自动重连网络摄像头。
  5. 可设置边框大小即偏移量和边框颜色。
  6. 可设置是否绘制OSD标签即标签文本或图片和标签位置。
  7. 可设置两种OSD位置和风格。
  8. 可设置是否保存到文件以及文件名。
  9. 可直接拖曳文件到vlcwidget控件播放。
  10. 支持h265视频流 rtmp等常见视频流。
  11. 可暂停播放和继续播放。
  12. 支持回调模式和句柄两种模式。
  13. 支持线程读取进度等信息和事件回调两种处理模式。
  14. 自动将当前播放位置和音量大小是否静音以信号发出去。
  15. 提供接口设置播放位置和音量及设置静音。
  16. 支持存储单个视频文件和定时存储视频文件。
  17. 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。

三、效果图

QQ截图20200806130129.jpgQQ截图20200806130129.jpg

四、相关站点

  1. 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
  2. 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
  3. 个人主页:https://blog.csdn.net/feiyangqingyun
  4. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
  5. 体验地址:https://blog.csdn.net/feiyangqingyun/article/details/97565652

五、核心代码

代码语言:txt复制
//事件回调
static void handleEvents(const libvlc_event_t *event, void *userData)
{
    VlcThread *thread = (VlcThread *)userData;
    switch (event->type) {
        case libvlc_MediaPlayerLengthChanged: {
            quint64 length = event->u.media_player_length_changed.new_length;
            if (length > 0) {
                thread->doEvent(1, QVariantList() << length);
                qDebug() << TIMEMS << "文件总长: " << length;
            }
        }
        break;

        case libvlc_MediaPlayerTimeChanged: {
            quint64 position = event->u.media_player_time_changed.new_time;
            if (position > 0) {
                thread->doEvent(2, QVariantList() << position);
                //qDebug() << TIMEMS << "当前时间: " << position;
            }
        }
        break;

        case libvlc_MediaPlayerPositionChanged: {
            float position = event->u.media_player_position_changed.new_position;
            if (position > 0) {
                //qDebug() << TIMEMS << "当前进度: " << position;
            }
        }
        break;

        case libvlc_MediaParsedChanged:
            qDebug() << TIMEMS << "媒体信息: " << event->u.media_parsed_changed.new_status;
            break;

        //qDebug() << TIMEMS << "状态改变: " << event->u.media_state_changed.new_state;
        case libvlc_MediaPlayerOpening:
            qDebug() << TIMEMS << "状态改变: " << "libvlc_MediaPlayerOpening";
            break;

        case libvlc_MediaPlayerPlaying:
            qDebug() << TIMEMS << "状态改变: " << "libvlc_MediaPlayerPlaying";
            break;

        case libvlc_MediaPlayerPaused:
            qDebug() << TIMEMS << "状态改变: " << "libvlc_MediaPlayerPaused";
            break;

        case libvlc_MediaPlayerStopped:
            qDebug() << TIMEMS << "状态改变: " << "libvlc_MediaPlayerStopped";
            break;

        case libvlc_MediaPlayerEndReached: {
            thread->doEvent(0, QVariantList());
            qDebug() << TIMEMS << "状态改变: " << "libvlc_MediaPlayerEndReached";
        }
        break;

        default:
            break;
    }
}

//订阅事件
static void libvlc_event_new(libvlc_event_manager_t *vlcEvent, VlcThread *thread)
{
    //逐个订阅自己感兴趣的需要的事件
    libvlc_event_attach(vlcEvent, libvlc_MediaPlayerLengthChanged, handleEvents, thread);
    libvlc_event_attach(vlcEvent, libvlc_MediaPlayerTimeChanged, handleEvents, thread);
    libvlc_event_attach(vlcEvent, libvlc_MediaPlayerPositionChanged, handleEvents, thread);
    libvlc_event_attach(vlcEvent, libvlc_MediaParsedChanged, handleEvents, thread);
    libvlc_event_attach(vlcEvent, libvlc_MediaPlayerOpening, handleEvents, thread);
    libvlc_event_attach(vlcEvent, libvlc_MediaPlayerPlaying, handleEvents, thread);
    libvlc_event_attach(vlcEvent, libvlc_MediaPlayerPaused, handleEvents, thread);
    libvlc_event_attach(vlcEvent, libvlc_MediaPlayerStopped, handleEvents, thread);
    libvlc_event_attach(vlcEvent, libvlc_MediaPlayerEndReached, handleEvents, thread);
}

//反订阅事件
static void libvlc_event_release(libvlc_event_manager_t *vlcEvent, VlcThread *thread)
{
    libvlc_event_detach(vlcEvent, libvlc_MediaPlayerLengthChanged, handleEvents, thread);
    libvlc_event_detach(vlcEvent, libvlc_MediaPlayerTimeChanged, handleEvents, thread);
    libvlc_event_detach(vlcEvent, libvlc_MediaPlayerPositionChanged, handleEvents, thread);
    libvlc_event_detach(vlcEvent, libvlc_MediaParsedChanged, handleEvents, thread);
    libvlc_event_detach(vlcEvent, libvlc_MediaPlayerOpening, handleEvents, thread);
    libvlc_event_detach(vlcEvent, libvlc_MediaPlayerPlaying, handleEvents, thread);
    libvlc_event_detach(vlcEvent, libvlc_MediaPlayerPaused, handleEvents, thread);
    libvlc_event_detach(vlcEvent, libvlc_MediaPlayerStopped, handleEvents, thread);
    libvlc_event_detach(vlcEvent, libvlc_MediaPlayerEndReached, handleEvents, thread);
}

0 人点赞