Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-72468

QML Mediaplayer + GStreamer freezes when repeatedly switching videos

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.12.4, 5.13.1, 5.14.0 Alpha
    • 5.9.6
    • Multimedia
    • None
    • Software: Linux + Qt 5.9.6 + GStreamer 1.0
      Hardware: Toradex Apalis iMX6
    • Linux/Other display system
    • 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();
              }
          }}
      
      

       

      Attachments

        1. Beer_Bubbles.mov
          6.20 MB
        2. FullBacktrace.txt
          146 kB
        3. iMX6_video_crash.pro
          0.2 kB
        4. log.txt
          36 kB
        5. LogComplete.zip
          1.11 MB
        6. main.cpp
          0.4 kB
        7. main.qml
          4 kB
        8. Music.mov
          2.98 MB
        9. Poker.mov
          2.49 MB
        10. qml.qrc
          0.1 kB
        11. stacktrace_main.txt
          9 kB
        12. stacktrace_main.txt
          9 kB
        13. stacktrace_main01.txt
          9 kB
        14. stacktrace_multique100.txt
          3 kB
        15. stacktrace_QQmlThread.txt
          1.0 kB
        16. stacktrace_qsgrenderthread.txt
          1 kB
        17. stacktrace_qsgrenderthread.txt
          1 kB
        18. stacktrace_QSGRenderThread01.txt
          1 kB
        19. stacktrace_qtdemux101.txt
          0.4 kB
        20. stacktrace_typefind_sink.txt
          0.4 kB
        21. stacktrace.txt
          9 kB
        22. StacktraceAndLog.zip
          9 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            valentyn.doroshchuk Valentyn Doroshchuk
            sagucaz Sergio Aguilera Cazorla
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes