Search code examples
c++qtvideoqmlqt-resource

QML Component 'Video' can not play video files from Qt resource files


Whole project can be found here:

QML Video Test Project

I have made an example application with three buttons one image and one video player. When pressing the buttons a video is supposed to play. This is what distinguishes the buttons:

  1. Access a video file in the same folder as the applications executable file.
  2. Access a video file added to the Qt Resource file.
  3. Access a video file from an external binary Qt Resource file with no compression.

Only button 1. work in my application and the reason for this post is that I have run out of idea on why button 2. and 3. can not make the video play.

The image included in the application is an image that is packed together with a video file in the external binary Qt Resource file. This image is successfully read from the external resource file. This means that access to the external resource file is not the problem.

Here is the main.qml file:

import QtQuick 2.4
import QtQuick.Window 2.2
import com.qml.externalresourcemanager 1.0
import QtMultimedia 5.4
import QtQuick.Controls 1.2

Window {
    visible: true

    minimumHeight: 700
    minimumWidth: 400

    property string imageSelected: ""
    property string videoSelected: ""

    ExternalResourceManager {
        id: externalResourceManager

        Component.onCompleted: {
            console.log("External resource registered: " + registerExternalResource("file:/../../VideoTest/binaryExpansionFile.rcc"))
            imageSelected = "externalImage.jpg"
        }
    }

    Button {
        id: button0
        width: parent.width
        height: parent.height / 7
        anchors.top: parent.top
        text: "Click me to play as local file"
        onClicked: {
            console.log(installPath + "local.mp4")
            videoSelected = installPath + "local.mp4"
        }
    }

    Button {
        id: button1
        width: parent.width
        height: parent.height / 7
        anchors.top: button0.bottom
        text: "Click me to play local resource file"
        onClicked: {
            videoSelected = "local.mp4"
        }
    }

    Button {
        id: button2
        width: parent.width
        height: parent.height / 7
        anchors.top: button1.bottom
        text: "Click me to play external resource file"
        onClicked: {
            videoSelected = "external.mp4"
        }
    }

    Image {
        id: image
        source: imageSelected
        width: parent.width
        height: parent.height * 2 / 7
        anchors.top: button2.bottom
    }

    Video {
        id: video
        source: videoSelected
        height: parent.height * 2 / 7
        width: parent.width
        anchors.top: image.bottom
        fillMode: VideoOutput.PreserveAspectFit

        onStatusChanged: {
            var temp

            switch (playbackState)
            {
                case MediaPlayer.NoMedia:
                    temp = "MediaPlayer.NoMedia"
                break;

                case MediaPlayer.Loading:
                    temp = "MediaPlayer.Loading"
                break;

                case MediaPlayer.Loaded:
                    temp = "MediaPlayer.Loaded"
                break;

                case MediaPlayer.Buffering:
                    temp = "MediaPlayer.Buffering"
                break;

                case MediaPlayer.Stalled:
                    temp = "MediaPlayer.Stalled"
                break;

                case MediaPlayer.Buffered:
                    temp = "MediaPlayer.Buffered"
                break;

                case MediaPlayer.EndOfMedia:
                    temp = "MediaPlayer.EndOfMedia"
                break;

                case MediaPlayer.InvalidMedia:
                    temp = "MediaPlayer.InvalidMedia"
                break;

                case MediaPlayer.UnknownStatus:
                    temp = "MediaPlayer.UnknownStatus"
                break;
            }

            console.log(temp)

            if (status === MediaPlayer.Loaded)
            {
                video.play()
            }
        }
        onBufferProgressChanged: {
            console.log("Buffering: " + bufferProgress * 100)
        }
        onSourceChanged: {
            console.log("Source: " + source)
        }
        onAvailabilityChanged: {
            console.log("Availability: " + availability)
        }
        onErrorChanged: {
            console.log("Error: " + error)
        }
        onErrorStringChanged: {
            console.log("Error String: " + errorString.toString())
        }
        onHasVideoChanged: {
            console.log("Has video: " + hasVideo)
        }
        onPlaybackStateChanged: {
            var temp

            switch (playbackState)
            {
                case MediaPlayer.PlayingState:
                    temp = "MediaPlayer.PlayingState"
                break;

                case MediaPlayer.PausedState:
                    temp = "MediaPlayer.PausedState"
                break;

                case MediaPlayer.StoppedState:
                    temp = "MediaPlayer.StoppedState"
                break;
            }

            console.log(temp)
        }
    }
}

Pressing button 1 my application outputs this:

Resource path:  "file:/../../VideoTest/binaryExpansionFile.rcc"
qml: External resource registered: true
qml: file:/C:/Users/MisterX/Documents/QtProjects/build-VideoTest-Desktop_Qt_5_4_2_MinGW_32bit-Debug/debug/local.mp4
qml: Source: file:///C:/Users/MisterX/Documents/QtProjects/build-VideoTest-Desktop_Qt_5_4_2_MinGW_32bit-Debug/debug/local.mp4
qml: MediaPlayer.UnknownStatus
qml: Has video: true
qml: MediaPlayer.UnknownStatus
qml: MediaPlayer.NoMedia
qml: MediaPlayer.PlayingState

Pressing button 2 my application outputs this:

Resource path:  "file:/../../VideoTest/binaryExpansionFile.rcc"
qml: External resource registered: true
qml: Source: qrc:/local.mp4
qml: MediaPlayer.UnknownStatus
qml: Has video: false
qml: MediaPlayer.UnknownStatus
qml: MediaPlayer.NoMedia
qml: MediaPlayer.PlayingState

Whole project can be found here: QML Video Test Project


Solution

  • This is a bug when using the MinGW compiler that uses the DirectShow backend. See this bug report link for more information.