qt/LedOK/wProgramManager/wEditProgram/wElement/mpvplayer.cpp
2022-01-04 18:11:48 +08:00

127 lines
3.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "mpvplayer.h"
// 唤醒函数
static void wakeup(void *ctx)
{
// 此回调可从任何mpv线程调用但也可以从调用mpv API的线程递归地返回
// 只是需要通知要唤醒的Qt GUI线程以便它可以使用mpv_wait_event并尽快返回
MpvPlayer *mvpPlayer = (MpvPlayer *)ctx;
emit mvpPlayer->mpv_events();
}
MpvPlayer::MpvPlayer(QWidget *parent) :
QWidget(parent)
{
// 创建mvpPlayer
create_mvpPlayer(parent);
}
MpvPlayer::~MpvPlayer()
{
if (mpv)
mpv_terminate_destroy(mpv);
}
// 创建mvpPlayer
void MpvPlayer::create_mvpPlayer(QWidget *videoWin)
{
// 创建mpv实例
mpv = mpv_create();
if (!mpv)
throw std::runtime_error("can't create mpv instance");
// 将视频子窗口的窗口ID传递给mpv wid选项
int64_t wid = videoWin->winId();
mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid);
// 让我们通过MPV_EVENT_PROPERTY_CHANGE接收属性更改事件如果这属性更改了
mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE);
// 从这里开始,将调用唤醒功能。 回调可以来自任何线程因此我们使用QueuedConnection机制以线程安全的方式中继唤醒
connect(this, &MpvPlayer::mpv_events, this, &MpvPlayer::on_mpv_events,
Qt::QueuedConnection);
mpv_set_wakeup_callback(mpv, wakeup, this);
// 判断mpv实例是否成功初始化
if (mpv_initialize(mpv) < 0)
throw std::runtime_error("mpv failed to initialize");
}
// 设置mpv属性
void MpvPlayer::setProperty(const QString &name, const QString &value)
{
mpv_set_option_string(mpv, name.toLatin1().data(), value.toLatin1().data());
}
// 获得mpv属性
QString MpvPlayer::getProperty(const QString &name) const
{
return (QString)mpv_get_property_string(mpv, name.toLatin1().data());
}
// 播放视频
void MpvPlayer::play(QString filename)
{
if (mpv)
{
const QByteArray c_filename = filename.toUtf8();
const char *args[] = {"loadfile", c_filename.data(), NULL};
// 与mpv_command相同但异步运行命令来避免阻塞直到进程终止
mpv_command_async(mpv, 0, args);
}
}
// 这个槽函数由 wakeup()调用通过mpv_events信号
void MpvPlayer::on_mpv_events()
{
// 处理所有事件,直到事件队列为空
while (mpv)
{
mpv_event *event = mpv_wait_event(mpv, 0);
if (event->event_id == MPV_EVENT_NONE)
break;
handle_mpv_event(event);
}
}
// 处理mpv事件
void MpvPlayer::handle_mpv_event(mpv_event *event)
{
switch (event->event_id)
{
// 属性改变事件发生
case MPV_EVENT_PROPERTY_CHANGE:
{
mpv_event_property *prop = (mpv_event_property *)event->data;
if (strcmp(prop->name, "time-pos") == 0)
{
if (prop->format == MPV_FORMAT_DOUBLE)
{
// 获得播放时间
double time = *(double *)prop->data;
qDebug() << "播放时间: " << QString::number(time, 10, 2);
}
else if (prop->format == MPV_FORMAT_NONE)
{
// 该属性不可用,可能意味着播放已停止
emit mpv_palyEnd();
qDebug() << "播放结束";
}
}
}
break;
// palyer退出事件发生
case MPV_EVENT_SHUTDOWN:
{
mpv_terminate_destroy(mpv);
mpv = NULL;
}
break;
default: ;
}
}