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 160 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
    #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