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. construct QVideoFrame with Format_YUV420P
QtWS25 Last Chance

construct QVideoFrame with Format_YUV420P

Scheduled Pinned Locked Moved Unsolved General and Desktop
qvideoframeqabstractvideosyuv420pargb32
13 Posts 2 Posters 5.3k Views
  • 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.
  • G Offline
    G Offline
    GKMR
    wrote on 30 May 2018, 17:26 last edited by
    #1

    Hello,

    I have implemented QAbstractVideoSurface and i can play the media without any problem.
    The next step in the project is to take the frame in present method, convert it to image and draw some shapes.
    I also want to reconstruct the frame and display it.

    The problem is that my video source has YUV420P format and while I could find a solution to change this to Format_ARGB32 for handling and manipulation by QImage, I can not generate a Format_YUV420P QVideoFrame from Format_ARGB32 Image.

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 30 May 2018, 20:52 last edited by
      #2

      Hi,

      Why do you need to change it back to YUV420P ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      G 1 Reply Last reply 31 May 2018, 13:25
      0
      • G Offline
        G Offline
        GKMR
        wrote on 30 May 2018, 21:30 last edited by GKMR 6 Jan 2018, 16:07
        #3

        Hi,

        I was myself wondering if I should be required to do that. But, here is the detail.

        I have implemented QAbstractVideoSurface to capture QVideoFrame. The Video has YUV420P format. Now, the isFormatSupported obviously returns Format_Invalid because YUV420P is not supported.

        bool VideoFrameGrabber::start(const QVideoSurfaceFormat &format)
        {
            const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
            const QSize size = format.frameSize();
            if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) {
                this->imageFormat = imageFormat;
                imageSize = size;
                sourceRect = format.viewport();
                QAbstractVideoSurface::start(format);
                widget->updateGeometry();
                updateVideoRect();
                return true;
            } else if (imageFormat == QImage::Format_Invalid && !size.isEmpty()) {
                this->imageFormat = QImage::Format_Invalid;
                imageSize = size;
                sourceRect = format.viewport();
                QAbstractVideoSurface::start(format);
                widget->updateGeometry();
                updateVideoRect();
                return true;
            } else {
                return false;
            }
        }
        
        

        I am then converting it to ARGB32 format and manipulating it a bit.
        But when i try to see the pixel format of cloneFrame, it is YUV420P and I have a ARGB32 image. It shows some wierd shades on the surface but not the edited image while the dumped image is what I expected. A reduced version of the code is as below.

        bool VideoFrameGrabber::present(const QVideoFrame &frame)
        {
            if (frame.isValid())
            {
                QVideoFrame cloneFrame(frame);
                cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
                globalTime = seekOffset * 1000 + cloneFrame.endTime();
                emit setSlider(globalTime);
                if(imageFormat != QImage::Format_Invalid){
                    qDebug() << " Valid Format Case ";
                    imageEdited = QImage(cloneFrame.bits(),
                                         cloneFrame.width(),
                                         cloneFrame.height(),
                                         imageFormat);
                } else {
                    qDebug() << " Invalid Format Case ";
                    imageEdited = qt_imageFromVideoFrame(cloneFrame);
                }
                if(rectMetaData.count() > 0){
                    while(rectMetaData.at(rectSequence).frameNumber == frameSequence
                          && rectSequence < rectCount-1){
                        if(rectMetaData.at(rectSequence).fillStatus){
                            p.setBrush(QBrush(QColor(rectMetaData.at(rectSequence).color)));
                        } else {
                            p.setPen(rectMetaData.at(rectSequence).color);
                        }
                        p.drawRect(rectMetaData.at(rectSequence).x1,
                                   rectMetaData.at(rectSequence).y1,
                                   rectMetaData.at(rectSequence).x2,
                                   rectMetaData.at(rectSequence).y2);
                        rectSequence++;
                    }
                }
                if(circleMetaData.count() > 0){
                    while(circleMetaData.at(circleSequence).frameNumber < frameSequence){
                        circleSequence++;
                    }
                    while(circleMetaData.at(circleSequence).frameNumber == frameSequence &&
                          circleSequence < circleCount-1){
                        if(circleMetaData.at(circleSequence).fillStatus){
                            p.setBrush(QBrush(QColor(circleMetaData.at(circleSequence).color)));
                        } else {
                            p.setPen(circleMetaData.at(circleSequence).color);
                        }
                        p.drawEllipse(circleMetaData.at(circleSequence).centerX,
                                      circleMetaData.at(circleSequence).centerY,
                                      circleMetaData.at(circleSequence).radiusX,
                                      circleMetaData.at(circleSequence).radiusY);
                        circleSequence++;
                    }
                }
                p.end();
                cloneFrame.unmap();
            }
        
            imageEdited.save(QString("/home/gaurav/ImageTest/image_"+QString::number(frameSequence)+".jpg").toLatin1());
        
            if (surfaceFormat().pixelFormat() != frame.pixelFormat()
                    || surfaceFormat().frameSize() != frame.size()) {
                setError(IncorrectFormatError);
                stop();
                return false;
            } else {
                currentFrame = QVideoFrame(imageEdited);
                widget->repaint(targetRect);
                if(saveStatus) {
        
                    fflush(stdout);
        
                    av_image_fill_arrays(tempFrame->data,
                                         tempFrame->linesize,
                                         imageEdited.bits(),
                                         AV_PIX_FMT_BGRA,
                                         imageEdited.width(),
                                         imageEdited.height(),
                                         1);
        
                    sws_scale(ctx,
                              tempFrame->data,
                              tempFrame->linesize,
                              0,
                              imageEdited.height(),
                              avFrame->data,
                              avFrame->linesize);
        
                    avFrame->pts = frameSequence;
        
                    encode();
        
                }
                frameSequence++;
                return true;
            }
        }
        
        

        I thought I should be doing it this way but not sure if this is the correct process. Maybe there is something else which is wrong.

        1 Reply Last reply
        0
        • S SGaist
          30 May 2018, 20:52

          Hi,

          Why do you need to change it back to YUV420P ?

          G Offline
          G Offline
          GKMR
          wrote on 31 May 2018, 13:25 last edited by GKMR
          #4

          @SGaist can you point me to some solution for this case.

          The summary is I implement the start method which is then calling start of QAbstractVideoSurface with the Pixel Format of incoming QVideoFrames, as required.

          I can only start it with correct input format else the start call will work but supplied frames will not be read properly. When i say read properly, i tried to read them and then display as well as write them. In case of writing it gave me an exception. To display, it just kept the screen blank.

          If I start it with the correct format with little tweak where i call start of QAbstractVideoSurface even if the result of imageFormatFromPixelFormat if FORMAT_Invalid, I could get the valid QVideoFrame frame in present since I bypass the check in start to ensure start if image format is supported. But to get my task done I need to edit this frame and so I can read this YUV420P image by non-standard library and successfully edit/dump(to test) it, I cannot convert it back to QVideoFrame because no constructor except with supplied QImage would work. At this point my Image in the converted format FORMAT_ABGR32 creates a corresponding pixel format and not of YUV420P. The Surface is initialized with this and does not show anything.

          I am stuck and any help is appreciated.

          1 Reply Last reply
          0
          • S Offline
            S Offline
            SGaist
            Lifetime Qt Champion
            wrote on 31 May 2018, 20:07 last edited by
            #5

            Something is not clear, since you control the frame grabber, why not tell that you'll be providing ARGB32 images directly ?

            The non-standard library you are using is an "implementation detail" and the rest of the pipeline doesn't need to know that.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            G 1 Reply Last reply 1 Jun 2018, 16:15
            0
            • S SGaist
              31 May 2018, 20:07

              Something is not clear, since you control the frame grabber, why not tell that you'll be providing ARGB32 images directly ?

              The non-standard library you are using is an "implementation detail" and the rest of the pipeline doesn't need to know that.

              G Offline
              G Offline
              GKMR
              wrote on 1 Jun 2018, 16:15 last edited by GKMR 6 Feb 2018, 14:08
              #6

              @SGaist What do you mean by Images directly?

              What i understand from you is that I should initialize my surface with ARGB Format and I tried that but the problem is as follows. I tested both options ARGB and YUV.

              If I set the ARGB format in start function for surface via "bool start(const QVideoSurfaceFormat &format);" I get wrong frame data. As the frame has pixel format of YUV. I see that the image conversion fails. I separately constructed a QVideoSurfaceFormat for correct size and Format_YUV420P and passed as argument.

              Else, if I set correct format which is YUV bypassing the check of image format before initializing surface I get a QVideoFrame with Format_YUV420P in the "bool present(const QVideoFrame &frame);" function. Reading QImage from this frame works with non standard library. But since the surface is initialized with YUV we have to reconstruct a QVideoFrame of YUV format from RGB Image.
              And no constructor of QVideoFrame does that as the only feasible argument to supply is QImage which does not support YUV and resulting frame is not YUV, hence incompatible with surface initialization.

              Am I understanding it wrong.

              1 Reply Last reply
              0
              • S Offline
                S Offline
                SGaist
                Lifetime Qt Champion
                wrote on 1 Jun 2018, 20:32 last edited by
                #7

                Ho wait, I was not at the right place of the pipeline. Can you tell me where the images are coming from ?

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                G 1 Reply Last reply 2 Jun 2018, 14:07
                0
                • S SGaist
                  1 Jun 2018, 20:32

                  Ho wait, I was not at the right place of the pipeline. Can you tell me where the images are coming from ?

                  G Offline
                  G Offline
                  GKMR
                  wrote on 2 Jun 2018, 14:07 last edited by
                  #8

                  @SGaist I dont know if this exactly answers your question but I am extracting the images from QVideoFrame received in present and then edit it. The image is then used for generating a QVideoFrame to display the edited Image.

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on 3 Jun 2018, 21:06 last edited by
                    #9

                    That part is clear but you wrote that you are using a non-standard library to get your images. How are you doing that ?

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    G 1 Reply Last reply 5 Jun 2018, 16:17
                    0
                    • S SGaist
                      3 Jun 2018, 21:06

                      That part is clear but you wrote that you are using a non-standard library to get your images. How are you doing that ?

                      G Offline
                      G Offline
                      GKMR
                      wrote on 5 Jun 2018, 16:17 last edited by GKMR 6 May 2018, 16:19
                      #10

                      @SGaist Hi, Sorry for the delayed reply. I got into another problem with the same code. By the way I am currently importing some code from windows to linux by copying the code and getting these issues.

                      I used the wrong term to call it non-standard library. I was referring to
                      imageEdited = qt_imageFromVideoFrame(cloneFrame);
                      by non standard library function.

                      Also in the present function when i call widget->repaint(), i do not get a paintEvent in the derived class of this class. The implementation is inline with videoWidgetExample from QT (https://doc.qt.io/archives/4.6/multimedia-videowidget.html). Can you help me in that because I am currently checking the pipeline to be sure that except for the said issue of the topic, at least the source frame is painted.

                      1 Reply Last reply
                      0
                      • S Offline
                        S Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on 5 Jun 2018, 19:56 last edited by
                        #11

                        Where does the media come from ? A video file ? A camera ?

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        G 1 Reply Last reply 6 Jun 2018, 07:56
                        0
                        • S SGaist
                          5 Jun 2018, 19:56

                          Where does the media come from ? A video file ? A camera ?

                          G Offline
                          G Offline
                          GKMR
                          wrote on 6 Jun 2018, 07:56 last edited by
                          #12

                          @SGaist Its a video File being read by QMediaPlayer and set on a QAbstractVideoSurface which is then capturing the QVideoFrame and sending to present. This present is extracting the image from the frame.

                          Also the QAbstractVideoSurface is casted into a QWidget.

                          Since the conversion from frame to image and vice versa is what I am struggling with, I tried to test the pipeline by trying to draw the same frame which I received in present without any modification. For this I saw people call repaint(QRect) over the widget which has the QAbstractVideoSurface. But I do not get the paintEvent in the derived class of above class.

                          The last statement might be confusing but the analogy is from the videoWidgetExample. I derived this class into another which is a widget.

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on 7 Jun 2018, 21:01 last edited by
                            #13

                            I see that you are also using ffmpeg in your code. Then you could leverage it to do the format conversions between YUV and RGB and back to YUV.

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            0

                            1/13

                            30 May 2018, 17:26

                            • Login

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