Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QtMultimedia and QAbstractVideoBuffer
Forum Updated to NodeBB v4.3 + New Features

QtMultimedia and QAbstractVideoBuffer

Scheduled Pinned Locked Moved General and Desktop
2 Posts 2 Posters 3.7k 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.
  • A Offline
    A Offline
    aureshinite
    wrote on last edited by
    #1

    Hi everyone...

    I am currently trying to write a low level video player, which reads raw YUV frames and displays them.
    Its video engine will interact with many other components, principally by signaling the current frame.
    Actually, my player is working fine individually, but i believe i need a nice structure to encapsulate
    everything.

    I found out QtMultimedia has what I need with QVideoFrame, but I don't really
    know how QAbstractVideoBuffer is supposed to be used.
    Can we create a valid QVideoFrame without a QAbstractVideoBuffer? (refering to the ::map () member function )

    Thanks

    1 Reply Last reply
    0
    • M Offline
      M Offline
      Mauro
      wrote on last edited by
      #2

      Hi!
      I'm having the same problem: trying to figure out how to use the QtMultimedia module for playing video files.
      Maybe we can share our efforts and get some progress together.

      I'm using libvlc in order to decode video files: each time a new frame is ready, libvlc stores the RGB32 bytes representation in a preallocated buffer in memory, I'll call a pointer to this buffer "backendBuffer".

      I thought that I could just subclass QAbstractVideoBuffer so as to have a wrapper for the backendBuffer and return it with the map funcion:

      This is the header:

      @
      class VideoBuffer : public QAbstractVideoBuffer
      {
      public:
      VideoBuffer(HandleType type = NoHandle);
      virtual ~VideoBuffer();

      uchar* map(MapMode mode, int* numBytes, int* bytesPerLine);
      MapMode mapMode() const;
      void unmap();

      void setBackendBuffer(uchar* buffer, int frameWidth, int frameHeight);
      int frameWidth() { return _frameWidth; };
      int frameHeight() { return _frameHeight; };

      private:
      uchar* _backendBuffer;
      int _frameWidth;
      int _frameHeight;
      };
      @

      and this is the definition:

      @
      VideoBuffer::VideoBuffer(HandleType type)
      : QAbstractVideoBuffer(type)
      {
      }

      VideoBuffer::~VideoBuffer()
      {
      }

      uchar* VideoBuffer::map(MapMode mode, int* numBytes, int* bytesPerLine)
      {
      // I just ignore the MapMode

      if (numBytes != NULL)
      *numBytes = _frameWidth * _frameHeight * 4;
      if (bytesPerLine != NULL)
      *bytesPerLine = _frameWidth * 4;

      return _backendBuffer; // should I return a copy of the backendBuffer?
      }

      QAbstractVideoBuffer::MapMode VideoBuffer::mapMode() const
      {
      return ReadOnly;
      }

      void VideoBuffer::unmap()
      {
      // I assume there's nothing to do if I don't return a copy of the bakendBuffer
      }

      void VideoBuffer::setBackendBuffer(uchar* buffer, int frameWidth, int frameHeight)
      {
      _backendBuffer = buffer;
      _frameWidth = frameWidth;
      _frameHeight = frameHeight;
      }
      @

      The idea is to call VideoBuffer::setBackendBuffer(...) passing in the preallocated memory buffer which is filled in by libvlc, for instance:

      @
      _videoBuffer = new VideoBuffer;
      _videoBuffer->setBackendBuffer(_vlcBufferDataPtr, _frameWidth, _frameHeight);
      @

      Now, each time a new frame is ready to be displayed (its RGB32 representation has been written in the backendBuffer), libvlc calls the following method with a pointer to the VideoBuffer that wraps the backendBuffer.
      I create a QVideoFrame and then call QAbstractVideoSurface::present(...).

      QAbstractVideoSurface code is exactly the one you can find in the Video Widget Example.
      In the following code, videoSurface is a pointer to a QAbstractVideoSurface object.

      @
      void Controller::bufferReady(VideoBuffer* videoBuffer)
      {
      mutex.lock();

      QSize frameSize( videoBuffer->frameWidth(), videoBuffer->frameHeight() );
      QVideoFrame videoFrame( videoBuffer, frameSize, QVideoFrame::Format_RGB32 );

      if (!videoFrame.isValid())
          return; // false
      
      QVideoSurfaceFormat currentSurfaceFormat = videoSurface->surfaceFormat();
      
      if (videoFrame.pixelFormat() != currentSurfaceFormat.pixelFormat()
              || videoFrame.size() != currentSurfaceFormat.frameSize()) {
          QVideoSurfaceFormat format(videoFrame.size(), videoFrame.pixelFormat());
      
          if (!videoSurface->start(format))
              return; // false;
      }
      
      if (!videoSurface->present(videoFrame))
      {
       videoSurface->stop();
          return; // false;
      } else {
          return; // true;
      }
      

      mutex.unlock();
      }
      @

      However, this code crashes...
      Any idea why?
      Thanks for any help!

      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