Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Qt 6 QML MediaPlayer not playing M3U8 streams on Android, while WebView does

Qt 6 QML MediaPlayer not playing M3U8 streams on Android, while WebView does

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
14 Posts 2 Posters 504 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    woodpecker
    wrote last edited by
    #4

    If anyone is interested, here is the code:
    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        // 1. Load dependencies in the correct order via the Java layer
        // This will automatically call JNI_OnLoad and install s_jvm in VLC
        QJniObject::callStaticMethod<void>(
            "java/lang/System",
            "loadLibrary",
            "(Ljava/lang/String;)V",
            QJniObject::fromString("vlc").object() // core first
            );
    
        QQmlApplicationEngine engine;
        QObject::connect(
            &engine,
            &QQmlApplicationEngine::objectCreationFailed,
            &app,
            []() { QCoreApplication::exit(-1); },
            Qt::QueuedConnection);
        engine.loadFromModule("myproject", "Main");
    
        return app.exec();
    }
    
    

    .

    1 Reply Last reply
    0
    • W Offline
      W Offline
      woodpecker
      wrote last edited by
      #5

      vlcplayer.h

      #ifndef VLCPLAYER_H
      #define VLCPLAYER_H
      
      #include <vlc/vlc.h>
      #include "vlc/libvlc_media.h"
      #include "vlc/libvlc_media_player.h"
      #include <QtQml/qqmlregistration.h> //for QML_ELEMENT
      #include <QMutex>
      #include <vector>
      #include <QPointer>
      #include <QVideoSink>
      
      // using namespace QNativeInterface;
      
      // extern "C" {
      // // We declare the function we found using nm
      // void libvlc_media_player_set_android_context(libvlc_media_player_t *p_mi, void *p_jvm_or_surface);
      // }
      
      class VLCPlayer : public QObject {
          Q_OBJECT
          QML_ELEMENT // This makes the class available for use/instantiation on the QML side.
          Q_PROPERTY(QVideoSink* videoSink READ videoSink WRITE setVideoSink NOTIFY videoSinkChanged)
      public:
          VLCPlayer();
      
          Q_INVOKABLE void setSource(const QString &path);
      
         // 1. LOCK: VLC asks where to write the pixels of the next frame
         static void* lock(void *opaque, void **planes);
      
         // 2. UNLOCK: The frame has been written to the buffer
         static void unlock(void *opaque, void *picture, void *const *planes);
      
         // 3. DISPLAY: It's time to tell Qt that the image has been updated
         static void display(void *opaque, void *picture);
      
         QVideoSink *videoSink() const;
         void setVideoSink(QVideoSink *newVideoSink);
      
          // Video settings (can be changed)
          const int VIDEO_WIDTH = 1280;
          const int VIDEO_HEIGHT = 720;
      
          std::vector<uchar> videoBuffer;
          QMutex bufferMutex;
          libvlc_media_player_t *mp = nullptr;
      signals:
          void videoSinkChanged();
          void frameReady();
      
      public slots:
          void onframeReady();
      
      private:
          libvlc_instance_t *_vlcInstance;
          libvlc_media_player_t *_vlcPlayer;
          QPointer<QVideoSink> m_videoSink;
      };
      1 Reply Last reply
      0
      • W Offline
        W Offline
        woodpecker
        wrote last edited by
        #6

        vlcplayer.cpp

        1 Reply Last reply
        0
        • W Offline
          W Offline
          woodpecker
          wrote last edited by
          #7

          I can't paste it - I get a message that it's spam...

          1 Reply Last reply
          0
          • W Offline
            W Offline
            woodpecker
            wrote last edited by
            #8
            This post is deleted!
            1 Reply Last reply
            0
            • W Offline
              W Offline
              woodpecker
              wrote last edited by
              #9
              This post is deleted!
              1 Reply Last reply
              0
              • W Offline
                W Offline
                woodpecker
                wrote last edited by
                #10
                This post is deleted!
                1 Reply Last reply
                0
                • W Offline
                  W Offline
                  woodpecker
                  wrote last edited by
                  #11
                  #include "vlcplayer.h"
                  #include <QPainter>
                  #include <QVideoFrame>
                  
                  VLCPlayer::VLCPlayer() {
                      videoBuffer.resize(VIDEO_WIDTH * VIDEO_HEIGHT * 4); // RGBA
                      connect(this, &VLCPlayer::frameReady, this, &VLCPlayer::onframeReady);
                  }
                  
                  void VLCPlayer::setSource(const QString &path) {
                      // const char* vlc_args[] = { "--no-osd" };
                      _vlcInstance = libvlc_new(0, nullptr); //libvlc_new(1, vlc_args);
                      _vlcPlayer = libvlc_media_player_new(_vlcInstance);
                  
                      // Set the format: RGBA (4 bytes per pixel), width, height, pitch
                      libvlc_video_set_format(_vlcPlayer, "RGBA", VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_WIDTH * 4);
                  
                      // Link our functions
                      libvlc_video_set_callbacks(_vlcPlayer, &VLCPlayer::lock, &VLCPlayer::unlock, &VLCPlayer::display, this);
                  
                      libvlc_media_t *m = libvlc_media_new_location(_vlcInstance, path.toUtf8().constData());
                      libvlc_media_player_set_media(_vlcPlayer, m);
                      libvlc_media_release(m);
                      libvlc_media_player_play(_vlcPlayer);
                  }
                  
                  QVideoSink* VLCPlayer::videoSink() const
                  {
                      return m_videoSink.get();
                  }
                  
                  void VLCPlayer::setVideoSink(QVideoSink *newVideoSink)
                  {
                      if (m_videoSink == newVideoSink)
                          return;
                      m_videoSink = newVideoSink;
                      emit videoSinkChanged();
                  }
                  
                  void* VLCPlayer::lock(void *opaque, void **planes) {
                      VLCPlayer *player = static_cast<VLCPlayer*>(opaque);
                      player->bufferMutex.lock();
                      *planes = player->videoBuffer.data();
                      return nullptr;
                  }
                  
                  void VLCPlayer::unlock(void *opaque, void *picture, void *const *planes) {
                      VLCPlayer *player = static_cast<VLCPlayer*>(opaque);
                      player->bufferMutex.unlock();
                  }
                  
                  void VLCPlayer::display(void *opaque, void *picture) {
                      VLCPlayer *player = static_cast<VLCPlayer*>(opaque);
                      // Generate a signal to redraw the user interface in Qt's main thread
                      emit player->frameReady();
                  }
                  
                  void VLCPlayer::onframeReady()
                  {
                      if(!m_videoSink)
                          return;
                  
                      bufferMutex.lock();
                  
                      // Create a QImage object that simply "looks" at your video buffer (without copying)
                      QImage img(videoBuffer.data(), VIDEO_WIDTH, VIDEO_HEIGHT, QImage::Format_RGBA8888);
                  
                      // In Qt 6, you can create a frame directly from a QImage
                      // if the formats match, Qt will try to minimize overhead
                      QVideoFrame frame(img);
                  
                      // Sending to Sink
                      m_videoSink->setVideoFrame(frame);
                  
                      bufferMutex.unlock();
                  }
                  
                  
                  1 Reply Last reply
                  0
                  • W Offline
                    W Offline
                    woodpecker
                    wrote last edited by
                    #12

                    Because of the phrase "#include <Q D e b u g>," Askit considered this code spam.)
                    However, QDebug still needs to be enabled.

                    1 Reply Last reply
                    1
                    • W Offline
                      W Offline
                      woodpecker
                      wrote last edited by
                      #13

                      QML

                                          VLCPlayer {
                                              id: vlcplayer
                                              videoSink: videoOutput.videoSink
                                          }
                      
                                          VideoOutput {
                                              id: videoOutput
                                              anchors.fill: parent
                                              fillMode: VideoOutput.PreserveAspectFit
                                          }
                                          
                                          Component.onCompleted: vlcplayer.setSource("https://cdn.some_domen/.../stream.m3u8?uuid=some_uuid&token=some_token")
                      
                      
                      
                      1 Reply Last reply
                      1
                      • KH-219DesignK Offline
                        KH-219DesignK Offline
                        KH-219Design
                        wrote last edited by KH-219Design
                        #14

                        Interesting! I recently did some experimentation with Qt combined with IP camera, and I had less-than-ideal results (which I planned to revisit at some point but have not gotten around to).

                        @woodpecker How is the timing/lag/performance?

                        My principal issue was huge lag, which I also experienced when just using ffmpeg at the command line. (Since Qt uses ffmpeg under the hood I suspect the actual source of lag is therefore ffmpeg.)

                        I had come across:

                        https://forum.qt.io/topic/79208/how-to-kill-delay-in-live-streaming (which never got any reply at all)

                        https://stackoverflow.com/questions/7759695/terrible-performance-with-qmediaplayer-and-qvideowidget

                        But your (very) recent outcome will be of interest to myself and others! How's the lag?

                        (Also, you mentioned 6.10.1 but can you also state which OS or OSes?) EDIT: Android is in the title! But still I'm curious if you build for Linux/Windows also?

                        www.219design.com
                        Software | Electrical | Mechanical | Product Design

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved