Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.9.6
-
None
-
Software: Linux + Qt 5.9.6 + GStreamer 1.0
Hardware: Toradex Apalis iMX6
-
-
72101558b3afc40ef41132e66ce789b92929e911 (qt/qtmultimedia/5.12)
Description
Environment: Linux + Qt 5.9.6 + GStreamer 1.0
Hardware: Toradex Apalis iMX6
The scenario: a simple QML application creates a fullscreen VideoOutput + a MediaPlayer for each one of the videos of a given catalog (3 videos in the case of the attached example). The application:
- Plays every video during a certain amount of (random) time, then stops the current video, switches to the next one and plays it.
- When a video reaches the end before a video switch takes place, that video seeks to its zero position (inifnite loop).
The application manages the looping and switching of the videos by itself, without using the PlayList component. This is because we have observed that video looping and switching is faster (from the visual point of view) if we call stop() and play() instead of using the mentioned PlayList. Also, in a previous version the application used the Video component, which also caused the issue described here.
onPositionChanged: {
if ((mediaplayer.position >= mediaplayer.duration - 60)) {
seek(0);
}
}
The issue: after switching videos for a certain amount of time, the whole application eventually hangs at the moment of calling play() for the next video. The application has no symptoms of memory leakage. Also, the application does not crash, it only freezes and the CPU shows 100% usage, as if it was stuck in an inifinite loop or a deadlock. The amount of time needed to observe the issue is very random, but usually less than 1 hour when the videos are switched every few seconds.
Attached example: in the attached example, 3 videos are switched as described above. A switching takes place after a random amount of time between 10 and 15 seconds. If during this time a video reaches its end, we seek(0) it to reset it from the beginning. The issue happens after the application has run for some minutes. While writing this description, the last failures have taken place after 02:45, 03:40, 00:34, 07:13, 30:33, 14:42 ("minutes:seconds").
The main.qml file is copied below. See attached files for the whole project.
import QtQuick 2.9 import QtQuick.Window 2.2 import QtMultimedia 5.9 Window { id : mainWindow visible: true width : Screen.desktopAvailableWidth height : Screen.desktopAvailableHeight color : Qt.rgba(0, 0, 0.5, 1) //Application running time label: Text { id : time z : 1000 color : "green" font { family : "Arial" bold : true pixelSize: 42 } anchors { bottom: parent.bottom left : parent.left } } //Time label updater: Timer { property var startTime: 0; //Declared "var" to be able to operate this number with Date.getTime() result property bool stopped : true id : runningTime running : true repeat : true interval: 500 Component.onCompleted: { time.text = timeConversion(0); startTime = new Date().getTime(); } onTriggered: { var elapsed = new Date().getTime() - startTime; time.text = timeConversion (elapsed); } function timeConversion(millisec) { var d = new Date(parseInt(millisec, 10)); return Qt.formatDateTime(d,"hh:mm.ss") } function reset() { stopped = false; startTime = new Date().getTime(); } function stop() { stopped = true; time.text = timeConversion(0); } } //List of 3 videos (1920 x 720 pixels) ListModel { id: videosModel ListElement { videoName: "Beer_Bubbles.mov"; } ListElement { videoName: "Music.mov"; } ListElement { videoName: "Poker.mov"; } } //The delegate is an Item that wraps a VideoOutput and a MediaPlayer (the issue also happens if the delegate is a Video component) Repeater { property int currentVideo: 0 id : videos model: videosModel delegate: Item { width : mainWindow.width height : mainWindow.height property alias videoPlaybackState: mediaplayer.playbackState; //Proxy calls to the MediaPlayer video control methods function play () { mediaplayer.play () } function pause () { mediaplayer.pause() } function seek (n) { mediaplayer.seek (n) } function stop () { mediaplayer.stop () } //Play the first video on application start up Component.onCompleted: { if(model.index === 0) { mediaplayer.play(); } } VideoOutput { id : videodelegate source : mediaplayer fillMode: VideoOutput.PreserveAspectCrop anchors.fill: parent } MediaPlayer { id: mediaplayer autoPlay : false autoLoad : true muted : true source : "file:///home/videos/" + model.videoName notifyInterval: 10 //Videos should loop forever, so few miliseconds before the end we reset them to 0 onPositionChanged: { if ((mediaplayer.position >= mediaplayer.duration - 60)) { seek(0); } } } } } //Changes the video every 10 - 15 seconds Timer { id: videoChanger interval: (10*Math.random() + 5) * 1000 running : true repeat : true onTriggered: { videoChanger.interval = (10*Math.random() + 5) * 1000; nextVideo(); } } //Stops the current video and plays one of the 3 videos in the catalog function nextVideo() { //var nextID = (videos.currentVideo + 1) % videosModel.count; //In case we want the videos to play consecutively var nextID = Math.floor((Math.random() * 3)); //In case we want the videos to play in a random order if(videos.currentVideo > -1) { videos.itemAt(videos.currentVideo).stop(); } videos.currentVideo = nextID; if (videos.itemAt(videos.currentVideo).videoPlaybackState !== MediaPlayer.PlayingState) { videos.itemAt(videos.currentVideo).play(); } }}