Truely excellent. Thanks so much. There was no thing that elluded to this in 
the docs. And I don't know very much about GL. Thanks!

> Sent: Monday, June 18, 2018 at 1:29 AM
> From: "Gil H" <[email protected]>
> To: "Qt Interest" <[email protected]>
> Subject: Re: [Interest] (code) Cannot map videoforames for 
> QAbstractVideoSurface::present
>
> Hi Jason, you need to check the handle type on the QVideoFrame.  If 
> input->handleType() == QAbstractVideoBuffer::NoHandle then you can map the 
> memory directly, as you've tried.  But on Mac, the handle type is 
> GLTextureHandle and you need to write some OpenGL code to get the texture 
> handle, read it, and then get at the pixels that way.  
> 
> Here's a bit of code I used to do this:
> 
> // declare as class members
> QByteArray                   _frameBuffer;
> int                            _frameBytes;
> GLuint                       _fbo;
> 
> // in processing function:
> GLuint textureId = input->handle().toUInt();
> if (_fbo == 0)
>         glGenFramebuffers(1, &_fbo);
> 
> _frameBytes = input->width()*input->height() * 4;
> 
> GLuint prevFbo;
> glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo);
> glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
> glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 
> textureId, 0);
> 
> #ifdef Q_OS_IOS
>     glReadPixels(0, 0, input->width(), input->height(), GL_RGBA, 
> GL_UNSIGNED_BYTE, _frameBuffer.data());
> #else
>     glReadPixels(0, 0, input->width(), input->height(), GL_BGRA_EXT, 
> GL_UNSIGNED_BYTE, _frameBuffer.data());
> #endif
> 
> glBindFramebuffer(GL_FRAMEBUFFER, prevFbo);
> 
> // at this point _frameBuffer bytearray contains your pixels
> 
> 
> Hope this saves you some of the headaches I went through as well!
> 
> Gil
> 
> 
> On 6/14/18, 11:26 AM, "Interest on behalf of Jason H" 
> <[email protected] on behalf of [email protected]> 
> wrote:
> 
>     Yes, I essentially have that (your message just made it to my email after 
> I sent my code)
>     I don't know why map() would fail, and why bits() would not be valid.
>     
>     I'm on OSX, reading from an MP4...
>     
>     
>     > Sent: Thursday, June 14, 2018 at 7:12 AM
>     > From: "Igor Mironchik" <[email protected]>
>     > To: [email protected]
>     > Subject: Re: [Interest] (code) Cannot map videoforames for 
> QAbstractVideoSurface::present
>     >
>     > Hi,
>     > 
>     > Start from here:
>     > 
>     > bool
>     > Frames::present( const QVideoFrame & frame )
>     > {
>     >    if( !isActive() )
>     >      return false;
>     > 
>     >    QVideoFrame f = frame;
>     >    f.map( QAbstractVideoBuffer::ReadOnly );
>     > 
>     >    QImage image( f.bits(), f.width(), f.height(), f.bytesPerLine(),
>     >      QVideoFrame::imageFormatFromPixelFormat( f.pixelFormat() ) );
>     > 
>     >    f.unmap();
>     > 
>     >    emit newFrame( image.copy( image.rect() ) );
>     > 
>     >    return true;
>     > }
>     > 
>     > This works for me...
>     > 
>     > 
>     > 14-Jun-18 17:52, Jason H пишет:
>     > > I have no idea what I'm doing wrong. Can someone this and let me know?
>     > > The frames I'm getting are BGR32, so I have special code for that.
>     > > But I'm getting the message "QVideoFrame::unmap() was called more 
> times then QVideoFrame::map()"
>     > > Which is obviously not the case.
>     > >
>     > > To restate the problems:
>     > > 1. I only get to present() once
>     > > 2. I's failing to map frames
>     > > 3. "then" in the message should be "than"
>     > >
>     > > Here's the first 3 lines of the .pro and complete code:
>     > > extractframes.pro-----
>     > > QT += multimedia
>     > > CONFIG += c++11 console
>     > > CONFIG -= app_bundle
>     > >
>     > > main.cpp--------------
>     > > #include <QAbstractVideoSurface>
>     > > #include <QGuiApplication>
>     > > #include <QMediaPlayer>
>     > > #include <QVideoSurfaceFormat>
>     > >
>     > > #include <QtDebug>
>     > >
>     > > class VideoSurface: public QAbstractVideoSurface {
>     > >               int _frameNumber;
>     > >               QVideoSurfaceFormat _format;
>     > >               QString _prefix;
>     > >               int _frameInterval;
>     > > public:
>     > >               VideoSurface(const QString &prefix, int frameInterval): 
> _prefix(prefix), _frameInterval(frameInterval) {        }
>     > >
>     > >       bool present(const QVideoFrame &frame) override {
>     > >               qDebug() << Q_FUNC_INFO << _frameNumber << 
> frame.isValid();
>     > >
>     > >               if (_frameNumber % _frameInterval == 0) {
>     > >                       QVideoFrame frame2(frame);
>     > >                       frame2.map(QAbstractVideoBuffer::ReadOnly);
>     > >                       QImage image;
>     > >
>     > >                       if (frame2.pixelFormat() == 
> QVideoFrame::Format_BGR32) {
>     > >                                image =  QImage(frame2.bits(), 
> frame2.width(), frame2.height(), QImage::Format_RGB32);
>     > >                                image = image.rgbSwapped();
>     > >                       } else {
>     > >                               image =  QImage(frame2.bits(), 
> frame2.width(), frame2.height(), 
> QVideoFrame::imageFormatFromPixelFormat(frame2.pixelFormat()));
>     > >                       }
>     > >
>     > >                       frame2.unmap();
>     > >                       QString filename = 
> QString(_prefix).arg(_frameNumber);
>     > >                       bool result = image.save(filename);
>     > >                       qDebug() << Q_FUNC_INFO << filename << result;
>     > >               }
>     > >               _frameNumber ++;
>     > >               return true;
>     > >       }
>     > >
>     > >       bool start(const QVideoSurfaceFormat &format) override {
>     > >               qDebug() << Q_FUNC_INFO;
>     > >               _format = format;
>     > >               _frameNumber = 0;
>     > >               QAbstractVideoSurface::start(format);
>     > >               return true;
>     > >       }
>     > >       void stop() override {
>     > >               qDebug() << Q_FUNC_INFO;
>     > >               QAbstractVideoSurface::stop();
>     > >       }
>     > >       QList<QVideoFrame::PixelFormat> 
> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const 
> override
>     > >       {
>     > >               Q_UNUSED(handleType);
>     > >               return QList<QVideoFrame::PixelFormat>()
>     > >                       << QVideoFrame::Format_ARGB32
>     > >                       << QVideoFrame::Format_ARGB32_Premultiplied
>     > >                       << QVideoFrame::Format_RGB32
>     > >                       << QVideoFrame::Format_RGB24
>     > >                       << QVideoFrame::Format_RGB565
>     > >                       << QVideoFrame::Format_RGB555
>     > >                       << QVideoFrame::Format_ARGB8565_Premultiplied
>     > >                       << QVideoFrame::Format_BGRA32
>     > >                       << QVideoFrame::Format_BGRA32_Premultiplied
>     > >                       << QVideoFrame::Format_BGR32
>     > >                       << QVideoFrame::Format_BGR24
>     > >                       << QVideoFrame::Format_BGR565
>     > >                       << QVideoFrame::Format_BGR555
>     > >                       << QVideoFrame::Format_BGRA5658_Premultiplied
>     > >                       << QVideoFrame::Format_AYUV444
>     > >                       << QVideoFrame::Format_AYUV444_Premultiplied
>     > >                       << QVideoFrame::Format_YUV444
>     > >                       << QVideoFrame::Format_YUV420P
>     > >                       << QVideoFrame::Format_YV12
>     > >                       << QVideoFrame::Format_UYVY
>     > >                       << QVideoFrame::Format_YUYV
>     > >                       << QVideoFrame::Format_NV12
>     > >                       << QVideoFrame::Format_NV21
>     > >                       << QVideoFrame::Format_IMC1
>     > >                       << QVideoFrame::Format_IMC2
>     > >                       << QVideoFrame::Format_IMC3
>     > >                       << QVideoFrame::Format_IMC4
>     > >                       << QVideoFrame::Format_Y8
>     > >                       << QVideoFrame::Format_Y16
>     > >                       << QVideoFrame::Format_Jpeg
>     > >                       << QVideoFrame::Format_CameraRaw
>     > >                       << QVideoFrame::Format_AdobeDng;
>     > >       }
>     > >
>     > >
>     > > };
>     > >
>     > > // Command line: extractframes format interval
>     > > // format:QString, with %1 = frame number
>     > > // Example:
>     > > // extractframes filename.mp4 image_%1.png 30
>     > >
>     > > int main(int argc, char *argv[])
>     > > {
>     > >       QGuiApplication a(argc, argv);
>     > >       QMediaPlayer player;
>     > >       VideoSurface surface(argv[2], QString(argv[3]).toInt());
>     > >       QObject::connect(&player, &QMediaPlayer::mediaStatusChanged, 
> [=]( QMediaPlayer::MediaStatus status ) {
>     > >               qDebug() << Q_FUNC_INFO << status;
>     > >       });
>     > >       QObject::connect(&player, 
> QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), [=]( 
> QMediaPlayer::Error error ) {
>     > >               qDebug() << Q_FUNC_INFO << error;
>     > >       });
>     > >       QObject::connect(&player, &QMediaPlayer::stateChanged, [=]( 
> const QMediaPlayer::State &state ) {
>     > >               qDebug() << Q_FUNC_INFO << state;
>     > >               if (QMediaPlayer::StoppedState == state) qApp->quit();
>     > >       });
>     > >
>     > >       player.setMedia(QUrl::fromLocalFile(argv[1]));
>     > >       player.setVideoOutput(&surface);
>     > >       player.setMuted(true);
>     > >
>     > >       player.play();
>     > >
>     > >       return a.exec();
>     > > }
>     > > _______________________________________________
>     > > Interest mailing list
>     > > [email protected]
>     > > http://lists.qt-project.org/mailman/listinfo/interest
>     > 
>     > _______________________________________________
>     > Interest mailing list
>     > [email protected]
>     > http://lists.qt-project.org/mailman/listinfo/interest
>     >
>     _______________________________________________
>     Interest mailing list
>     [email protected]
>     http://lists.qt-project.org/mailman/listinfo/interest
>     
> 
> 
> _______________________________________________
> Interest mailing list
> [email protected]
> http://lists.qt-project.org/mailman/listinfo/interest
>
_______________________________________________
Interest mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/interest

Reply via email to