Trying to capture QImage of video frame
-
thanks for reply.I am new to Qt. but right now first I am making a project in my linux desktop system.Then I will cross compile it for target board.thats a later part. but now I want RGB frame image. What and where to change in code?please suggest me something
-
In this program I am changing the test Index but still I am getting the same frame?
frame_capture.pro
#-------------------------------------------------
#Project created by QtCreator 2017-02-15T11:45:09
#-------------------------------------------------QT += core gui multimedia multimediawidgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = frame_capture
TEMPLATE = appSOURCES += main.cpp
frame_capture.cpp
v_player.cppHEADERS += frame_capture.h
v_player.hframe_capture.h
#ifndef FRAME_CAPTURE_H
#define FRAME_CAPTURE_H#include <QAbstractVideoSurface>
#include <QList>
#include <QDebug>
#include <QTime>namespace Ui {
class frame_capture;
}class frame_capture : public QAbstractVideoSurface
{
Q_OBJECTpublic:
explicit frame_capture(QObject *parent = 0);
~frame_capture();
QListQVideoFrame::PixelFormat supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
bool present(const QVideoFrame &frame);
QTime timer;
int oldTime;signals:
void frameAvailable(QImage frame);
void hereAreBytes(QByteArray*, int, int, int);
};#endif // FRAME_CAPTURE_H
v_player.h
#ifndef V_PLAYER_H
#define V_PLAYER_H
#include "frame_capture.h"#include <QObject>
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QtWidgets>class v_player : public QWidget
{
Q_OBJECT
public:
v_player(QWidget *parent = 0);
~v_player();
frame_capture *capture;int counter = 0; QString s; QRect rect;
private slots:
void handleBytes(QByteArray*, int, int, int);
void doClose();private:
void paintEvent(QPaintEvent *event);QMediaPlayer mediaPlayer; QPushButton *closeButton; bool closeIt = false; QList<QByteArray*> bytesList; int numBytes; int vpWidth, vpHeight; QList<QImage*> imageList; quint8 myred, mygreen, myblue;
};
#endif // V_PLAYER_Hframe_capture.cpp
#include "frame_capture.h"
#include "v_player.h"frame_capture::frame_capture(QObject *parent) : QAbstractVideoSurface(parent)
{
qDebug()<<"CONSTRUCTOR";
timer.start();
}//---------- supportedPixelFormats ----------
QListQVideoFrame::PixelFormat frame_capture ::
supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
Q_UNUSED(handleType);
return QListQVideoFrame::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;
}//---------- present ----------
bool frame_capture::present(const QVideoFrame &frame)
{
if (frame.isValid())
{
QVideoFrame cloneFrame(frame);
cloneFrame.map(QAbstractVideoBuffer::WriteOnly);
cloneFrame.pixelFormatFromImageFormat(QImage::Format_RGB32);int numBytes = cloneFrame.mappedBytes(); QByteArray* bytesPtr = new QByteArray((const char*)(cloneFrame.bits()), numBytes); emit hereAreBytes(bytesPtr, numBytes, cloneFrame.width(), cloneFrame.height()); cloneFrame.unmap(); return true; qDebug()<<"\npixelFormat: "<<cloneFrame.pixelFormat(); qDebug()<<"mappedBytes: "<<cloneFrame.mappedBytes(); } return false;
}
frame_capture::~frame_capture()
{
qDebug()<<"DESTRUCTOR";
}main.cpp
#include <QApplication>
#include "v_player.cpp"int main(int argc, char *argv[])
{
QApplication a(argc, argv);
v_player * player = new v_player();
player->setGeometry(300,300,480,300);
player->show();
int result = a.exec();
delete player;
return result;
}v_player.cpp
#include "v_player.h"
v_player::v_player(QWidget *parent) : QWidget(parent) , mediaPlayer(0, QMediaPlayer::VideoSurface)
{qDebug()<<"CONSTRUCTOR VideoPlayer"; setAttribute(Qt::WA_QuitOnClose); capture = new frame_capture(this); QVideoWidget *videoWidget = new QVideoWidget; videoWidget->setWindowTitle("Select a Video"); closeButton = new QPushButton("Close", this); closeButton->setEnabled(true); QBoxLayout *controlLayout = new QHBoxLayout; controlLayout->setMargin(0); controlLayout->addWidget(closeButton); controlLayout->addWidget(videoWidget); setLayout(controlLayout); rect = QRect(002, 25, 150, 30); //This line sends mediaPlayer video output to the grabber mediaPlayer.setVideoOutput(capture); //By uncommenting this line, the video is played in the VideoPlayer window. //mediaPlayer.setVideoOutput(videoWidget); //Playback at 1/10 speed to give time for frame capture //mediaPlayer.setPlaybackRate(0.1); mediaPlayer.setPlaybackRate(0.1); QString fileName = "/home/einfochips/Downloads/Countdown_Timer_Background _10_Seconds.mpg"; if (!fileName.isEmpty()) { mediaPlayer.setMedia(QUrl::fromLocalFile(fileName)); //playButton->setEnabled(true); mediaPlayer.play(); } connect(capture, &frame_capture::hereAreBytes, this, &v_player::handleBytes); connect(closeButton, SIGNAL(clicked()), this, SLOT(doClose())); setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
}
//---------- ~VideoPlayer ----------
v_player::~v_player()
{
qDebug()<<"DESTRUCTOR VideoPlayer";if ( ! bytesList.isEmpty()) { int testIndex = 150; QImage testImage = QImage((const uchar*)(bytesList.at(testIndex)), vpWidth, vpHeight, QImage::Format_RGB32, 0, 0); QString fileName = QFileDialog::getSaveFileName(this, "Save Image", "/home/einfochips/sitara/AM335x/Qt5.7.0/prog/frame_capture/build-frame_capture-Desktop_Qt_5_7_0_GCC_64bit-Debug/frame/testimage.png"); testImage.save(fileName,"PNG"); QTime aDelay; aDelay.start(); while (aDelay.elapsed() < 500) { int dummy = 0; dummy++; } } if ( ! bytesList.isEmpty()) { int num = bytesList.count(); for (int i=0; i<num; i++) delete bytesList.at(i); }
}
//---------- SLOT handleBytes ----------
void v_player::handleBytes(QByteArray* bytes, int nBytes, int w, int h)
{bytesList.append(bytes); numBytes = nBytes; vpWidth = w; vpHeight = h; if (closeIt) QCoreApplication::quit(); counter++; s.clear(); s = "Frame: " + QString::number(counter); qDebug() << counter << endl; update();
}
//---------- SLOT doClose ----------
void v_player::doClose()
{
qDebug()<<" doClose";
if (mediaPlayer.state() == QMediaPlayer::StoppedState)
QCoreApplication::quit();
if ((mediaPlayer.state() == QMediaPlayer::PlayingState) || (mediaPlayer.state() == QMediaPlayer::PausedState))
mediaPlayer.stop();
closeIt = true;
}//---------- paintEvent ----------
void v_player::paintEvent(QPaintEvent * event)
{
QPainter painter(this);
painter.eraseRect(rect);
painter.drawText(rect, 0, s);
} -
Please, are you expecting us to analyse your complete application to find what index you may or may not modify ?
-
no sir not really. The basic code is same as posted in this thread previously. This is just for the reference.You can directly suggest me which api or function will change the pixel formate of frame to RGB and allow me to save direct RGB only? or manually I need to add logic for conversion?
and the other thing I am not getting is why this gives me same frame? or I would say 1st frame only... -
It depends on the output you'll be using e.g. if OpenGL a shader will be used for that conversion.
Note that your grabber looks strange, you return all the types rather than just the one you would like to have and then you map the video frame as write only but you only read from it.
-
Thank you for reply. I tried as you say. but didn't get any change in output.what I do now?
k if you can suggest me any thing which can change frame output(regardless of its formate) rather than being same all the time at any instance i capture a frame.Output is going to same and it is equal to first frame. for instance at least if i'll get different pictures for different frames than for formate i'll convert manually,just for now. -
For converting YUV to RGB, Qt has a private API , qt_imageFromVideoFrame() , which could convert QVideoFrame to QImage in RGB format (I can't remember the exact RGB format to be converted) .
p.s It can't handle texture frame
You could try and see could it solve your problem first.
To enable the private API, you have to add this line in your .pro file
QT += multimedia-private
And include this header file
#include "private/qvideoframe_p.h"
Remarks: That is a private API. Use it as your own risk
-
Please be more precise. "Not working" doesn't say much. What are you getting ? A blank image ? A black image ? Funny colours ?
-
Please be more precise. "Not working" doesn't say much. What are you getting ? A blank image ? A black image ? Funny colours ?
-
Aren't you getting a .png file ?
-
You do realise that if you load your image again in a QImage, you'll get a RGB image ?
If you really want to save an RGB image then go for bitmap but beware, it's uncompressed.
-
oh yes thank you. this will solve my problem partially. but what about new frame capture.? can you please help me out where I am lacking or what i am missing? why I am getting the same frame every time?If I'll get updated frame my task will be almost on final stage.please solve this.and again thank you.
-
You always take the same image from the list, check that your counter increments properly and that you indeed update the list.
On a side note, you should pass const reference to QImage parameters. That will save useless copies.
-
Use:
const QImage &image
as parameter