参考了以下文章:https://blog.csdn.net/jxbinwd/article/details/81034339
我按照上面文章的描述写程序,解析出来的图像保存成图片。保存的图片有很多乱码。后来在保存图像时,停止播放视频,这样乱码就没了。
这个程序只是为了获取帧数据并存成图像,没有显示功能。
在.pro文件中需要增加
QT += multimedia
qtvideotest.h
#ifndef QTVIDEOTEST_H
#define QTVIDEOTEST_H
#include <QWidget>
#include <QMediaPlayer>
#include "videosurface.h"
class QtVideoTest : public QWidget
{
Q_OBJECT
public:
QtVideoTest(QWidget *parent = 0);
~QtVideoTest();
public slots:
void ProcessFrame(QVideoFrame &frame);
private:
QMediaPlayer *mediaPlayer;
};
#endif // QTVIDEOTEST_H
qtvideotest.cpp
#include "qtvideotest.h"
#include <QDebug>
#include <QUrl>
#include <QMetaType>
QtVideoTest::QtVideoTest(QWidget *parent)
: QWidget(parent)
{
qRegisterMetaType<QVideoFrame>("QVideoFrame&");
mediaPlayer = new QMediaPlayer;
VideoSurface *videoSurface = new VideoSurface();
mediaPlayer->setVideoOutput(videoSurface);
mediaPlayer->setMedia(QUrl("../video.flv"));
mediaPlayer->setMuted(true);
mediaPlayer->play();
connect(videoSurface, SIGNAL(frameAvailable(QVideoFrame &)), this, SLOT(ProcessFrame(QVideoFrame &)), Qt::QueuedConnection);
}
QtVideoTest::~QtVideoTest()
{
}
void QtVideoTest::ProcessFrame(QVideoFrame &frame)
{
static int count=0;
count++;
if (count % 5 == 0)
{
mediaPlayer->pause();
frame.map(QAbstractVideoBuffer::ReadOnly);
QImage recvImage(frame.bits(), frame.width(), frame.height(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat()));
recvImage.save(QString("./images/%1.jpg").arg(count), "JPG");
frame.unmap();
mediaPlayer->play();
}
}
这里我每隔5帧保存一张图片,也可以每一帧都保存。
videosurface.h
#ifndef VIDEOSURFACE_H
#define VIDEOSURFACE_H
#include <QAbstractVideoSurface>
class VideoSurface : public QAbstractVideoSurface
{
Q_OBJECT
public:
VideoSurface(QObject *parent = Q_NULLPTR);
~VideoSurface();
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const;
bool present(const QVideoFrame &frame);
signals:
void frameAvailable(QVideoFrame &frame);
};
#endif // VIDEOSURFACE_H
videosurface.cpp
#include "videosurface.h"
#include <QVideoSurfaceFormat>
#include <QDebug>
VideoSurface::VideoSurface(QObject *parent):QAbstractVideoSurface (parent)
{
}
VideoSurface::~VideoSurface()
{
}
QList<QVideoFrame::PixelFormat> VideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
QList<QVideoFrame::PixelFormat> listPixelFormats;
listPixelFormats.append(QVideoFrame::Format_ARGB32);
listPixelFormats.append(QVideoFrame::Format_ARGB32_Premultiplied);
listPixelFormats.append(QVideoFrame::Format_RGB32);
listPixelFormats.append(QVideoFrame::Format_RGB24);
listPixelFormats.append(QVideoFrame::Format_RGB565);
listPixelFormats.append(QVideoFrame::Format_RGB555);
listPixelFormats.append(QVideoFrame::Format_ARGB8565_Premultiplied);
listPixelFormats.append(QVideoFrame::Format_BGRA32);
listPixelFormats.append(QVideoFrame::Format_BGRA32_Premultiplied);
listPixelFormats.append(QVideoFrame::Format_BGR32);
listPixelFormats.append(QVideoFrame::Format_BGR24);
listPixelFormats.append(QVideoFrame::Format_BGR565);
listPixelFormats.append(QVideoFrame::Format_BGR555);
listPixelFormats.append(QVideoFrame::Format_BGRA5658_Premultiplied);
listPixelFormats.append(QVideoFrame::Format_Jpeg);
listPixelFormats.append(QVideoFrame::Format_CameraRaw);
listPixelFormats.append(QVideoFrame::Format_AdobeDng);
return listPixelFormats;
}
bool VideoSurface::present(const QVideoFrame &frame)
{
if (this->surfaceFormat().pixelFormat() != frame.pixelFormat() || this->surfaceFormat().frameSize() != frame.size())
{
setError(IncorrectFormatError);
stop();
qDebug()<<"error format";
return false;
}
QVideoFrame cloneFrame(frame);
emit frameAvailable(cloneFrame);
return true;
}