开源 C++ QT QML 开发(二十一)多媒体--K-Lite Mega Codec Pack解码和视频播放

           文章的目的为了记录使用QT QML开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

  相关链接:

开源 C++ QT QML 开发(一)基本介绍

开源 C++ QT QML 开发(二)工程结构

开源 C++ QT QML 开发(三)常用控件

开源 C++ QT QML 开发(四)复杂控件--Listview

开源 C++ QT QML 开发(五)复杂控件--Gridview

开源 C++ QT QML 开发(六)自定义控件--波形图

开源 C++ QT QML 开发(七)自定义控件--仪表盘

开源 C++ QT QML 开发(八)自定义控件--圆环

开源 C++ QT QML 开发(九)文件--文本和二进制

开源 C++ QT QML 开发(十)通讯--串口

开源 C++ QT QML 开发(十一)通讯--TCP服务器端

开源 C++ QT QML 开发(十二)通讯--TCP客户端

开源 C++ QT QML 开发(十三)多线程

开源 C++ QT QML 开发(十四)进程用途

开源 C++ QT QML 开发(十五)通讯--http下载

开源 C++ QT QML 开发(十六)进程--共享内存

开源 C++ QT QML 开发(十七)进程--LocalSocket

开源 C++ QT QML 开发(十八)多媒体--音频播放

开源 C++ QT QML 开发(十九)多媒体--音频录制

开源 C++ QT QML 开发(二十)多媒体--摄像头拍照

开源 C++ QT QML 开发(二十一)多媒体--视频播放

推荐链接:

开源 C# 快速开发(一)基础知识

开源 C# 快速开发(二)基础控件

开源 C# 快速开发(三)复杂控件

开源 C# 快速开发(四)自定义控件--波形图

开源 C# 快速开发(五)自定义控件--仪表盘

开源 C# 快速开发(六)自定义控件--圆环

开源 C# 快速开发(七)通讯--串口

开源 C# 快速开发(八)通讯--Tcp服务器端

开源 C# 快速开发(九)通讯--Tcp客户端

开源 C# 快速开发(十)通讯--http客户端

开源 C# 快速开发(十一)线程

开源 C# 快速开发(十二)进程监控

开源 C# 快速开发(十三)进程--管道通讯

开源 C# 快速开发(十四)进程--内存映射

开源 C# 快速开发(十五)进程--windows消息

开源 C# 快速开发(十六)数据库--sqlserver增删改查

本章节主要内容是:使用qml编写了媒体播放器,使用了K-Lite Codec Pack Mega作为解码包,实现mp4的播放。

1.代码分析

2.所有源码

3.效果演示

一、代码分析1. 主窗口和属性定义
 

ApplicationWindow {
    id: mainWindow
    width: 1024
    height: 720
    visible: true
    title: "MP4播放器 - 完全兼容版"
    minimumWidth: 800
    minimumHeight: 600

    property string currentVideo: ""  // 当前视频文件路径
    property bool hasVideo: videoPlayer.hasVideo  // 绑定到Video组件的hasVideo属性
    property bool isSeekable: videoPlayer.seekable  // 是否支持跳转
    property string currentStatus: "等待选择文件"  // 当前状态显示文本
}


2. 核心视频播放组件
Video组件及其信号处理
 

Video {
    id: videoPlayer
    anchors.fill: parent
    anchors.margins: 2
    source: currentVideo  // 绑定到currentVideo属性
    fillMode: VideoOutput.PreserveAspectFit  // 保持宽高比
    volume: volumeSlider.value  // 绑定音量滑块
    autoPlay: true  // 自动播放

    // 状态变化信号处理
    onStatusChanged: {
        console.log("视频状态变化:", status)
        updateStatusDisplay()  // 更新状态显示
    }

    // 播放状态变化信号处理
    onPlaybackStateChanged: {
        console.log("播放状态变化:", playbackState)
        updatePlayButton()  // 更新播放按钮文本
    }

    // 视频时长变化信号处理
    onDurationChanged: {
        console.log("视频时长:", duration, "ms")
        progressSlider.to = Math.max(1, duration)  // 设置进度条最大值
    }

    // 播放位置变化信号处理
    onPositionChanged: {
        if (!progressSlider.pressed) {  // 避免拖动时冲突
            progressSlider.value = position  // 更新进度条位置
        }
    }
}


3. 主要控制函数
播放/暂停切换函数
 

function togglePlayPause() {
    if (!hasVideo || currentVideo === "") return  // 安全检查

    if (videoPlayer.playbackState === MediaPlayer.PlayingState) {
        videoPlayer.pause()  // 如果正在播放,则暂停
    } else {
        videoPlayer.play()  // 否则开始播放
    }
}


状态显示更新函数
 

function updateStatusDisplay() {
    var status = videoPlayer.status  // 获取当前视频状态

    switch(status) {
        case MediaPlayer.NoMedia:
            currentStatus = "无媒体文件"
            break
        case MediaPlayer.Loading:
            currentStatus = "加载中..."
            break
        case MediaPlayer.Loaded:
            currentStatus = "已加载"
            break
        case MediaPlayer.Stalling:
            currentStatus = "缓冲中..."
            break
        case MediaPlayer.Buffering:
            currentStatus = "缓冲中"
            break
        case MediaPlayer.Buffered:
            currentStatus = "就绪"
            break
        case MediaPlayer.EndOfMedia:
            currentStatus = "播放结束"
            break
        case MediaPlayer.InvalidMedia:
            currentStatus = "格式不支持"
            break
        case MediaPlayer.UnknownStatus:
            currentStatus = "未知状态"
            break
        default:
            currentStatus = "就绪"
    }

    console.log("状态更新:", currentStatus)
}


播放按钮更新函数
 

function updatePlayButton() {
    switch(videoPlayer.playbackState) {
        case MediaPlayer.PlayingState:
            playButton.text = "⏸️ 暂停"  // 播放中显示暂停
            break
        case MediaPlayer.PausedState:
            playButton.text = "▶️ 继续"  // 暂停中显示继续
            break
        default:
            playButton.text = "▶️ 播放"  // 默认显示播放
    }
}


4. UI状态显示函数
状态图标获取函数
 

function getStatusIcon() {
    if (currentVideo === "") return "📁"  // 无文件
    if (videoPlayer.status === MediaPlayer.InvalidMedia) return "❌"  // 格式错误
    if (videoPlayer.status === MediaPlayer.Loading) return "⏳"  // 加载中
    if (!hasVideo) return "🎬"  // 无视频流
    return "✅"  // 正常状态
}


状态消息获取函数
 

function getStatusMessage() {
    if (currentVideo === "") return "请选择视频文件开始播放"  // 初始提示
    if (videoPlayer.status === MediaPlayer.InvalidMedia) return "无法播放此文件"  // 错误提示
    if (videoPlayer.status === MediaPlayer.Loading) return "正在加载..."  // 加载提示
    if (!hasVideo) return "准备播放"  // 准备状态
    return "正在播放: " + getFileName(currentVideo)  // 播放状态显示文件名
}


错误详情获取函数
 

function getErrorDetails() {
    if (videoPlayer.status === MediaPlayer.InvalidMedia) {
        return "此文件需要H.264解码器\n请安装K-Lite Codec Pack\n下载: https://codecguide.com/download_kl.htm"
    }
    return ""  // 无错误时返回空字符串
}


5. 工具函数
状态颜色获取函数

function getStatusColor() {
    if (videoPlayer.status === MediaPlayer.InvalidMedia) return "#e74c3c"  // 红色-错误
    if (videoPlayer.status === MediaPlayer.Buffered) return "#2ecc71"  // 绿色-就绪
    if (videoPlayer.status === MediaPlayer.Loading) return "#f39c12"  // 橙色-加载中
    return "#3498db"  // 蓝色-默认
}



文件名提取函数

function getFileName(filePath) {
    var path = filePath.toString()  // 转换为字符串
    var fileName = path.split('/').pop() || path.split('\\').pop()  // 从路径中提取文件名
    return fileName || "未知文件"  // 返回文件名或默认值
}


时间格式化函数

function formatTime(milliseconds) {
    if (!milliseconds || isNaN(milliseconds)) return "00:00"  // 无效时间处理

    var totalSeconds = Math.floor(milliseconds / 1000)  // 转换为秒
    var hours = Math.floor(totalSeconds / 3600)  // 计算小时
    var minutes = Math.floor((totalSeconds % 3600) / 60)  // 计算分钟
    var seconds = totalSeconds % 60  // 计算秒数

    if (hours > 0) {
        // 有时长格式:HH:MM:SS
        return hours.toString().padStart(2, '0') + ":" +
               minutes.toString().padStart(2, '0') + ":" +
               seconds.toString().padStart(2, '0')
    } else {
        // 无时长格式:MM:SS
        return minutes.toString().padStart(2, '0') + ":" +
               seconds.toString().padStart(2, '0')
    }
}


6. 进度条控制函数
进度条拖动处理

Slider {
    id: progressSlider
    // ... 其他属性
    
    onMoved: {
        if (isSeekable) {  // 检查是否支持跳转
            videoPlayer.seek(value)  // 跳转到指定位置
        }
    }
}



7. C++主程序函数
环境设置函数

int main(int argc, char *argv[])
{
    // 关键环境变量设置
    qputenv("QT_MEDIA_BACKEND", "windows");  // 强制使用Windows媒体后端
    qputenv("QT_LOGGING_RULES", "qt.multimedia.*=true");  // 启用多媒体调试日志
    qputenv("MF_DEBUG", "1");  // 启用Media Foundation调试
    
    // 应用程序属性设置
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);  // 高DPI支持
    QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);  // 软件渲染
    
    QGuiApplication app(argc, argv);
    
    // 应用程序信息
    app.setApplicationName("MP4播放器");
    app.setApplicationVersion("1.0");
    app.setOrganizationName("MyCompany");
}


系统诊断函数
 

// 详细的多媒体支持信息
qDebug() << "=== 多媒体系统诊断信息 ===";
qDebug() << "应用程序目录:" << QDir::currentPath();
qDebug() << "临时目录:" << QStandardPaths::writableLocation(QStandardPaths::TempLocation);
qDebug() << "支持的MIME类型数量:" << QMediaPlayer::supportedMimeTypes().count();

// 输出支持的格式
auto mimeTypes = QMediaPlayer::supportedMimeTypes();
for (int i = 0; i < qMin(10, mimeTypes.count()); ++i) {
    qDebug() << "支持格式:" << mimeTypes[i];
}


8. 文件对话框处理

FileDialog {
    id: fileDialog
    title: "选择视频文件"
    nameFilters: [ /* 文件过滤器列表 */ ]

    onAccepted: {
        currentVideo = fileDialog.fileUrl  // 获取选择的文件URL
        console.log("加载文件:", currentVideo)  // 调试日志
    }
}

二、所有源码

必须先安装解码器K-Lite Mega Codec Pack,程序才能播放视频。

K-Lite Mega Codec Pack是一款免费的多媒体解码器集合软件,整合了Full版解码包及Real/QuickTime替代组件,支持扩展Windows系统播放器对MKV/AVI/RMVB等格式的兼容,具有低系统资源占用和免重启安装特性。

K-Lite Mega Codec Pack核心功能与版本差异

  • 功能构成‌:集成K-Lite Codec Pack Full、Real Alternative和QuickTime Alternative组件,支持扩展Windows Media Player、KMPlayer等播放器对MKV/AVI/RMVB等格式的解码能力。‌12
  • 版本对比‌:提供Basic/Standard/Full/Mega四个版本,Mega版在Full版基础上增加VFW/ACM编解码器和Bass Audio Source模块,支持VirtualDub等视频编辑工具处理AVI文件。‌

使用场景与格式支持

  • 专业应用‌:适用于影视剪辑场景,通过集成x264VFW编解码器实现高压缩率视频编码,支持H.265/HEVC等新一代编码标准。‌37
  • 罕见格式‌:可解码OptimFrog音频(.ofr)和Tracker模块文件(.mod/.it),覆盖超过98%的常见多媒体格式。‌‌

1.安装正确的解码器包
K-Lite Codec Pack Mega
下载地址:https://codecguide.com/download_kl.htm

选择版本:下载 Mega 版本(包含所有解码器)

安装步骤:运行安装程序

2.pro文件

QT += quick quickcontrols2 multimedia multimediawidgets

3.main.qml文件源码

import QtQuick 2.14
import QtQuick.Window 2.14
import QtMultimedia 5.14
import QtQuick.Controls 2.14
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.14

ApplicationWindow {
    id: mainWindow
    width: 1024
    height: 720
    visible: true
    title: "MP4播放器 - 完全兼容版"
    minimumWidth: 800
    minimumHeight: 600

    property string currentVideo: ""
    property bool hasVideo: videoPlayer.hasVideo
    property bool isSeekable: videoPlayer.seekable
    property string currentStatus: "等待选择文件"

    // 背景渐变
    Rectangle {
        anchors.fill: parent
        gradient: Gradient {
            GradientStop { position: 0.0; color: "#2c3e50" }
            GradientStop { position: 1.0; color: "#3498db" }
        }
    }

    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 10
        spacing: 10

        // 标题栏
        Rectangle {
            Layout.fillWidth: true
            height: 60
            color: "transparent"

            RowLayout {
                anchors.fill: parent

                Text {
                    text: "🎬 MP4播放器"
                    color: "white"
                    font.pixelSize: 24
                    font.bold: true
                }

                Item { Layout.fillWidth: true }

                Text {
                    text: "Powered by Qt5.14"
                    color: "lightgray"
                    font.pixelSize: 12
                }
            }
        }

        // 视频显示区域
        Rectangle {
            id: videoContainer
            Layout.fillWidth: true
            Layout.fillHeight: true
            color: "black"
            radius: 8
            clip: true

            Video {
                id: videoPlayer
                anchors.fill: parent
                anchors.margins: 2
                source: currentVideo
                fillMode: VideoOutput.PreserveAspectFit
                volume: volumeSlider.value
                autoPlay: true

                // 状态变化处理 - 使用正确的信号
                onStatusChanged: {
                    console.log("视频状态变化:", status)
                    updateStatusDisplay()
                }

                onPlaybackStateChanged: {
                    console.log("播放状态变化:", playbackState)
                    updatePlayButton()
                }

                onDurationChanged: {
                    console.log("视频时长:", duration, "ms")
                    progressSlider.to = Math.max(1, duration)
                }

                onPositionChanged: {
                    if (!progressSlider.pressed) {
                        progressSlider.value = position
                    }
                }
            }

            // 加载指示器
            BusyIndicator {
                id: loadingIndicator
                anchors.centerIn: parent
                running: videoPlayer.status === MediaPlayer.Loading ||
                         videoPlayer.status === MediaPlayer.Stalling ||
                         videoPlayer.status === MediaPlayer.Buffering
                visible: running
            }

            // 居中状态信息
            Column {
                id: centerInfo
                anchors.centerIn: parent
                spacing: 10
                visible: currentVideo === "" || videoPlayer.status === MediaPlayer.InvalidMedia || !hasVideo

                Text {
                    id: statusIcon
                    anchors.horizontalCenter: parent.horizontalCenter
                    color: "white"
                    font.pixelSize: 48
                    text: getStatusIcon()
                }

                Text {
                    id: statusMessage
                    anchors.horizontalCenter: parent.horizontalCenter
                    color: "white"
                    font.pixelSize: 18
                    text: getStatusMessage()
                    horizontalAlignment: Text.AlignHCenter
                }

                Text {
                    id: errorDetails
                    anchors.horizontalCenter: parent.horizontalCenter
                    color: "yellow"
                    font.pixelSize: 12
                    text: getErrorDetails()
                    visible: text !== ""
                    horizontalAlignment: Text.AlignHCenter
                    width: 400
                    wrapMode: Text.WordWrap
                }
            }

            // 点击控制播放/暂停
            MouseArea {
                anchors.fill: parent
                onClicked: togglePlayPause()
                enabled: hasVideo && currentVideo !== ""
            }
        }

        // 进度控制区域
        ColumnLayout {
            Layout.fillWidth: true
            spacing: 5

            // 进度条
            Slider {
                id: progressSlider
                Layout.fillWidth: true
                from: 0
                to: 100
                value: 0
                enabled: isSeekable && hasVideo

                onMoved: {
                    if (isSeekable) {
                        videoPlayer.seek(value)
                    }
                }

                // 自定义样式
                background: Rectangle {
                    implicitHeight: 6
                    color: "#5a5a5a"
                    radius: 3
                }

                handle: Rectangle {
                    x: progressSlider.leftPadding + progressSlider.visualPosition * (progressSlider.availableWidth - width)
                    y: progressSlider.topPadding + progressSlider.availableHeight / 2 - height / 2
                    implicitWidth: 16
                    implicitHeight: 16
                    radius: 8
                    color: progressSlider.pressed ? "#f0f0f0" : "#ffffff"
                    border.color: "#bdbebf"
                }
            }

            // 时间信息
            RowLayout {
                Layout.fillWidth: true

                Text {
                    color: "white"
                    text: formatTime(videoPlayer.position)
                    font.pixelSize: 12
                }

                Item { Layout.fillWidth: true }

                Text {
                    color: "white"
                    text: formatTime(videoPlayer.duration)
                    font.pixelSize: 12
                }
            }
        }

        // 控制按钮区域
        Rectangle {
            Layout.fillWidth: true
            height: 70
            color: "transparent"

            RowLayout {
                anchors.fill: parent
                spacing: 10

                // 文件操作按钮
                Button {
                    text: "📁 打开文件"
                    onClicked: fileDialog.open()

                    background: Rectangle {
                        color: "#27ae60"
                        radius: 5
                    }

                    contentItem: Text {
                        text: parent.text
                        color: "white"
                        horizontalAlignment: Text.AlignHCenter
                        verticalAlignment: Text.AlignVCenter
                        font.bold: true
                    }
                }

                // 播放控制按钮
                Button {
                    id: playButton
                    text: "▶️ 播放"
                    onClicked: togglePlayPause()
                    enabled: hasVideo && currentVideo !== ""

                    background: Rectangle {
                        color: enabled ? "#2980b9" : "#7f8c8d"
                        radius: 5
                    }

                    contentItem: Text {
                        text: parent.text
                        color: "white"
                        horizontalAlignment: Text.AlignHCenter
                        verticalAlignment: Text.AlignVCenter
                        font.bold: true
                    }
                }

                Button {
                    text: "⏹️ 停止"
                    onClicked: {
                        videoPlayer.stop()
                        progressSlider.value = 0
                    }
                    enabled: hasVideo && currentVideo !== ""

                    background: Rectangle {
                        color: enabled ? "#e74c3c" : "#7f8c8d"
                        radius: 5
                    }

                    contentItem: Text {
                        text: parent.text
                        color: "white"
                        horizontalAlignment: Text.AlignHCenter
                        verticalAlignment: Text.AlignVCenter
                    }
                }

                Item { Layout.fillWidth: true }

                // 音量控制
                RowLayout {
                    spacing: 5

                    Text {
                        text: "🔊"
                        color: "white"
                        font.pixelSize: 16
                    }

                    Slider {
                        id: volumeSlider
                        from: 0
                        to: 1
                        value: 0.8
                        stepSize: 0.1
                        Layout.preferredWidth: 100

                        background: Rectangle {
                            implicitHeight: 4
                            color: "#5a5a5a"
                            radius: 2
                        }
                    }

                    Text {
                        color: "white"
                        text: Math.round(volumeSlider.value * 100) + "%"
                        font.pixelSize: 12
                        Layout.preferredWidth: 40
                    }
                }
            }
        }

        // 状态信息栏
        Rectangle {
            Layout.fillWidth: true
            height: 30
            color: "#34495e"
            radius: 4

            RowLayout {
                anchors.fill: parent
                anchors.margins: 5

                Text {
                    color: "white"
                    text: "文件: " + (currentVideo ? getFileName(currentVideo) : "未选择")
                    font.pixelSize: 11
                    elide: Text.ElideMiddle
                    Layout.fillWidth: true
                }

                Text {
                    color: getStatusColor()
                    text: currentStatus
                    font.pixelSize: 11
                    font.bold: true
                }

                Text {
                    color: hasVideo ? "lightgreen" : "red"
                    text: hasVideo ? "🎥 有视频" : "❌ 无视频"
                    font.pixelSize: 11
                }
            }
        }
    }

    FileDialog {
        id: fileDialog
        title: "选择视频文件"
        nameFilters: [
            "MP4文件 (*.mp4)",
            "AVI文件 (*.avi)",
            "MKV文件 (*.mkv)",
            "MOV文件 (*.mov)",
            "WMV文件 (*.wmv)",
            "所有文件 (*.*)"
        ]

        onAccepted: {
            currentVideo = fileDialog.fileUrl
            console.log("加载文件:", currentVideo)
        }
    }

    // 功能函数
    function togglePlayPause() {
        if (!hasVideo || currentVideo === "") return

        if (videoPlayer.playbackState === MediaPlayer.PlayingState) {
            videoPlayer.pause()
        } else {
            videoPlayer.play()
        }
    }

    function updateStatusDisplay() {
        var status = videoPlayer.status

        switch(status) {
            case MediaPlayer.NoMedia:
                currentStatus = "无媒体文件"
                break
            case MediaPlayer.Loading:
                currentStatus = "加载中..."
                break
            case MediaPlayer.Loaded:
                currentStatus = "已加载"
                break
            case MediaPlayer.Stalling:
                currentStatus = "缓冲中..."
                break
            case MediaPlayer.Buffering:
                currentStatus = "缓冲中"
                break
            case MediaPlayer.Buffered:
                currentStatus = "就绪"
                break
            case MediaPlayer.EndOfMedia:
                currentStatus = "播放结束"
                break
            case MediaPlayer.InvalidMedia:
                currentStatus = "格式不支持"
                break
            case MediaPlayer.UnknownStatus:
                currentStatus = "未知状态"
                break
            default:
                currentStatus = "就绪"
        }

        console.log("状态更新:", currentStatus)
    }

    function updatePlayButton() {
        switch(videoPlayer.playbackState) {
            case MediaPlayer.PlayingState:
                playButton.text = "⏸️ 暂停"
                break
            case MediaPlayer.PausedState:
                playButton.text = "▶️ 继续"
                break
            default:
                playButton.text = "▶️ 播放"
        }
    }

    function getStatusIcon() {
        if (currentVideo === "") return "📁"
        if (videoPlayer.status === MediaPlayer.InvalidMedia) return "❌"
        if (videoPlayer.status === MediaPlayer.Loading) return "⏳"
        if (!hasVideo) return "🎬"
        return "✅"
    }

    function getStatusMessage() {
        if (currentVideo === "") return "请选择视频文件开始播放"
        if (videoPlayer.status === MediaPlayer.InvalidMedia) return "无法播放此文件"
        if (videoPlayer.status === MediaPlayer.Loading) return "正在加载..."
        if (!hasVideo) return "准备播放"
        return "正在播放: " + getFileName(currentVideo)
    }

    function getErrorDetails() {
        if (videoPlayer.status === MediaPlayer.InvalidMedia) {
            return "此文件需要H.264解码器\n请安装K-Lite Codec Pack\n下载: https://codecguide.com/download_kl.htm"
        }
        return ""
    }

    function getStatusColor() {
        if (videoPlayer.status === MediaPlayer.InvalidMedia) return "#e74c3c"
        if (videoPlayer.status === MediaPlayer.Buffered) return "#2ecc71"
        if (videoPlayer.status === MediaPlayer.Loading) return "#f39c12"
        return "#3498db"
    }

    function getFileName(filePath) {
        var path = filePath.toString()
        var fileName = path.split('/').pop() || path.split('\\').pop()
        return fileName || "未知文件"
    }

    function formatTime(milliseconds) {
        if (!milliseconds || isNaN(milliseconds)) return "00:00"

        var totalSeconds = Math.floor(milliseconds / 1000)
        var hours = Math.floor(totalSeconds / 3600)
        var minutes = Math.floor((totalSeconds % 3600) / 60)
        var seconds = totalSeconds % 60

        if (hours > 0) {
            return hours.toString().padStart(2, '0') + ":" +
                   minutes.toString().padStart(2, '0') + ":" +
                   seconds.toString().padStart(2, '0')
        } else {
            return minutes.toString().padStart(2, '0') + ":" +
                   seconds.toString().padStart(2, '0')
        }
    }

    Component.onCompleted: {
        console.log("播放器初始化完成")
        console.log("视频输出支持:", videoPlayer.availability)
        console.log("是否有视频:", videoPlayer.hasVideo)
        console.log("是否可跳转:", videoPlayer.seekable)
    }
}

4. main.cpp文件源码

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QMediaPlayer>
#include <QDebug>
#include <QDir>
#include <QStandardPaths>

int main(int argc, char *argv[])
{
    // 设置环境变量 - 在创建QGuiApplication之前
    qputenv("QT_MEDIA_BACKEND", "windows");
    qputenv("QT_LOGGING_RULES", "qt.multimedia.*=true");
    qputenv("MF_DEBUG", "1");

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);

    QGuiApplication app(argc, argv);

    // 设置应用程序信息
    app.setApplicationName("MP4播放器");
    app.setApplicationVersion("1.0");
    app.setOrganizationName("MyCompany");

    // 详细的多媒体支持信息
    qDebug() << "=== 多媒体系统诊断信息 ===";
    qDebug() << "应用程序目录:" << QDir::currentPath();
    qDebug() << "临时目录:" << QStandardPaths::writableLocation(QStandardPaths::TempLocation);
    qDebug() << "支持的MIME类型数量:" << QMediaPlayer::supportedMimeTypes().count();

    // 输出前10个支持的格式
    auto mimeTypes = QMediaPlayer::supportedMimeTypes();
    for (int i = 0; i < qMin(10, mimeTypes.count()); ++i) {
        qDebug() << "支持格式:" << mimeTypes[i];
    }

    qDebug() << "环境变量:";
    qDebug() << "QT_MEDIA_BACKEND =" << qgetenv("QT_MEDIA_BACKEND");
    qDebug() << "PATH =" << qgetenv("PATH");

    QQmlApplicationEngine engine;

    // 连接加载失败信号
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [](QObject *obj, const QUrl &objUrl) {
        if (!obj) {
            qCritical() << "QML加载失败:" << objUrl;
            QCoreApplication::exit(-1);
        } else {
            qDebug() << "QML加载成功";
        }
    }, Qt::QueuedConnection);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

三、效果演示

选择MP4文件,进行播放,可以拖动和暂停。需要注意的是必须要安装解码器才行。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值