• Qt音视频开发14-mpv读取和控制


    一、前言

    用mpv来读取文件的信息,以及设置当前播放进度,音量、静音等,和当时vlc封装的功能一样,只不过vlc是通过调用函数接口去处理,而mpv是通过读取和设置属性来处理,vlc支持定时器或者线程中函数方法去读取状态,也支持事件回调去拿到对应的状态改变,mpv当然也支持,而且还更方便,主要的工作量或者花费的时间在如何知道有哪些属性、分别是什么功能含义,这个在官方都列出来了(http://mpv.io/manual/master/#options、http://mpv.io/manual/master/#list-of-input-commands、http://mpv.io/manual/master/#properties),不过都是英文就是,大部分程序员应该是没有什么难度的,大不了鼠标右键翻译成中文即可,哈哈,相信不少人都这么干过,很多浏览器默认就支持鼠标右键菜单翻译的,实在是很方便的,本人在查阅很多英文文档的时候,用的也是蛮多的,包括Qt官方的文档和BUG报告页面,但是建议在搜索问题的时候还是建议尽量用英文的描述去搜索,这样才能搜索的更精确。

    常用的一些属性:

    1. 视频原始宽度高度 width height
    2. 视频缩放后宽度高度 dwidth dheight
    3. 保存视频文件 stream-record 为空则表示停止录像
    4. 视频宽高比 video-aspect
    5. 暂停播放 pause yes表示暂停no表示继续
    6. 视频文件时长 duration
    7. 静音 mute yes表示静音no表示非静音
    8. 音量 volume int值0-100
    9. 获取播放进度 time-pos
    10. 设置播放进度 seek
    11. 当前音轨 aid
    12. 音轨数量 track-list/count
    13. 截图 screenshot-to-file

    二、功能特点

    1. 多线程实时播放视频流+本地视频等。
    2. 支持windows+linux+mac。
    3. 多线程显示图像,不卡主界面。
    4. 自动重连网络摄像头。
    5. 可设置是否保存到文件以及文件名。
    6. 可直接拖曳文件到mpvwidget控件播放。
    7. 支持h265视频流+rtmp等常见视频流。
    8. 可暂停播放和继续播放。
    9. 支持存储单个视频文件和定时存储视频文件。
    10. 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。
    11. 可设置画面拉伸填充或者等比例填充。
    12. 可对视频进行截图(原始图片)和截屏。
    13. 录像文件存储MP4文件。
    14. 支持qsv、dxva2、d3d11va等硬解码。

    三、效果图

    四、相关站点

    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

    五、核心代码

    void MpvThread::readMediaInfo()
    {
        if (mpvPlayer != NULL) {
            QVariant width = getValue("width");
            QVariant height = getValue("height");
            videoWidth = width.toInt();
            videoHeight = height.toInt();
            qDebug() << TIMEMS << url << "videoWidth:" << videoWidth << "videoHeight:" << videoHeight;
        }
    }
    
    void MpvThread::readPlayInfo()
    {
        //定义长度变量用于存储文件时长
        uint length = getLength();
        //定义变量存储声音大小,默认值1
        int volume = getVolume();
        //定义变量存储是否静音
        bool mute = getMute();
    
        //发送文件时长信号
        emit fileLengthReceive(length);
        //发送当前音量值信号
        emit fileVolumeReceive(volume, mute);
    
        //改变标志位启动读取播放进度
        if (!callbackevent) {
            isReadPosition = true;
        }
    }
    
    void MpvThread::readPosition()
    {
        //获取播放进度位置
        int position = getPosition();
        //获取是否播放结束
        bool isPlay = (position != 0);
        if (position > 0 && !isRtsp) {
            emit filePositionReceive(position, isPlay);
        }
    
        //本地文件播放结束
        if (!isPlay && !isRtsp && suffix != "dshow") {
            this->stop();
        }
    }
    
    void MpvThread::setSize()
    {
        if (mpvPlayer != NULL) {
            double width = playWidget->width();
            double height = playWidget->height();
            setValue("video-aspect", width / height);
        }
    }
    
    bool MpvThread::getIsPlaying()
    {
        //在视频流模式下,不是暂停状态,当前的位置和上一次的位置一致则表示断了
        //进度为0表示没有播放成功也需要重新加载
        bool isPlay = this->isRunning();
        if (isPlay && isRtsp && !getValue("pause").toBool()) {
            int position = getPosition();
            if (position == 0 || this->position == position) {
                isPlay = false;
            }
    
            this->position = position;
        }
    
        return isPlay;
    }
    
    uint MpvThread::getLength()
    {
        uint length = 0;
        if (mpvPlayer != NULL) {
            QVariant value = getValue("duration");
            length = value.toDouble() * 1000;
        }
    
        return length;
    }
    
    uint MpvThread::getPosition()
    {
        uint positon = 0;
        if (mpvPlayer != NULL) {
            QVariant value = getValue("time-pos");
            positon = value.toDouble() * 1000;
        }
    
        return positon;
    }
    
    void MpvThread::setPosition(int position)
    {
        if (mpvPlayer != NULL && !isRtsp) {
            command(QVariantList() << "seek" << position / 1000 << "absolute");
        }
    }
    
    bool MpvThread::getMute()
    {
        bool ok = false;
        if (mpvPlayer != NULL) {
            QVariant value = getValue("mute");
            ok = !value.toBool();
        }
    
        return ok;
    }
    
    void MpvThread::setMute(bool mute)
    {
        if (mpvPlayer != NULL) {
            setValue("mute", mute ? "yes" : "no");
        }
    }
    
    int MpvThread::getVolume()
    {
        int volume = 0;
        if (mpvPlayer != NULL) {
            QVariant value = getValue("volume");
            volume = value.toInt();
        }
    
        return volume;
    }
    
    void MpvThread::setVolume(int volume)
    {
        if (mpvPlayer != NULL) {
            setValue("volume", volume);
        }
    }
    
    int MpvThread::getTrack()
    {
        int track = 0;
        if (mpvPlayer != NULL) {
            QVariant value = getValue("aid");
            track = value.toInt();
        }
    
        return track;
    }
    
    int MpvThread::getTrackCount()
    {
        int trackCount = 0;
        if (mpvPlayer != NULL) {
            QVariant value = getValue("track-list/count");
            trackCount = value.toInt();
        }
    
        return trackCount;
    }
    
    void MpvThread::setTrack(int track)
    {
        if (mpvPlayer != NULL) {
            setValue("aid", track);
        }
    }
    
  • 相关阅读:
    什么是IOC
    spring的作用
    什么是spring框架?
    72
    71
    70
    69
    68
    67
    66
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/13536485.html
Copyright © 2020-2023  润新知