Skip to content

Commit

Permalink
add methods for VideoFrame to get a image or frame with another format
Browse files Browse the repository at this point in the history
old convertTo() is a bad idea because VideoFrame now is explicitly
shared and will be removed
  • Loading branch information
wang-bin committed Jan 8, 2015
1 parent 131c6ea commit 23f5a8b
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 40 deletions.
3 changes: 1 addition & 2 deletions qml/QmlAV/QuickVideoPreview.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include <QtAV/VideoFrameExtractor.h>

namespace QtAV {
class ImageConverter;

class QMLAV_EXPORT QuickVideoPreview : public QQuickItemRenderer
{
Q_OBJECT
Expand All @@ -53,7 +53,6 @@ private slots:
private:
QUrl m_file;
VideoFrameExtractor m_extractor;
ImageConverter *m_conv;
};
} //namespace QtAV
#endif // QUICKVIDEOPREVIEW_H
12 changes: 2 additions & 10 deletions qml/QuickVideoPreview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@
******************************************************************************/

#include "QmlAV/QuickVideoPreview.h"
#include "QtAV/ImageConverterTypes.h"

namespace QtAV {

QuickVideoPreview::QuickVideoPreview(QQuickItem *parent) :
QQuickItemRenderer(parent)
, m_conv(0)
{
connect(&m_extractor, SIGNAL(positionChanged()), this, SIGNAL(timestampChanged()));
connect(&m_extractor, SIGNAL(frameExtracted(QtAV::VideoFrame)), SLOT(displayFrame(QtAV::VideoFrame)));
Expand Down Expand Up @@ -70,15 +68,9 @@ void QuickVideoPreview::displayFrame(const QtAV::VideoFrame &frame)
receive(frame);
return;
}
if (!m_conv) {
m_conv = ImageConverterFactory::create(ImageConverterId_FF);
}
VideoFrame f(frame);
f.setImageConverter(m_conv);
if (!f.convertTo(VideoFormat::Format_RGB32)) {
qWarning("QuickVideoPreview convert frame error");
VideoFrame f(frame.toFormat(VideoFormat::Format_RGB32));
if (!f.isValid())
return;
}
receive(f);
}

Expand Down
3 changes: 2 additions & 1 deletion src/ImageConverter.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/******************************************************************************
ImageConverter: Base class for image resizing & color model convertion
Copyright (C) 2012-2014 Wang Bin <[email protected]>
Copyright (C) 2012-2015 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -76,6 +76,7 @@ void ImageConverter::setInSize(int width, int height)
prepareData();
}

// TODO: default is in size
void ImageConverter::setOutSize(int width, int height)
{
DPTR_D(ImageConverter);
Expand Down
15 changes: 12 additions & 3 deletions src/QtAV/VideoFrame.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2012-2014 Wang Bin <[email protected]>
Copyright (C) 2012-2015 Wang Bin <[email protected]>
* This file is part of QtAV
Expand Down Expand Up @@ -83,11 +83,20 @@ class Q_AV_EXPORT VideoFrame : public Frame

//use ptr instead of ImageConverterId to avoid allocating memory
// Id can be used in VideoThread
void setImageConverter(ImageConverter *conv);
void setImageConverter(ImageConverter *conv); // deprecated
// if use gpu to convert, mapToDevice() first
/*!
* \brief toImage
* Return a QImage of current video frame, with given format, image size and region of interest.
* \param dstSize result image size
* \param roi NOT implemented!
*/
QImage toImage(QImage::Format fmt = QImage::Format_ARGB32, const QSize& dstSize = QSize(), const QRectF& roi = QRect()) const;
VideoFrame toFormat(VideoFormat::PixelFormat pixfmt, const QSize& dstSize = QSize(), const QRectF& roi = QRect()) const;
VideoFrame toFormat(const VideoFormat& fmt, const QSize& dstSize = QSize(), const QRectF& roi = QRect()) const;
/*!
* \brief convertTo
* You may clone the frame first because VideoFrame is explicitly shared
* deprecated. You may clone the frame first because VideoFrame is explicitly shared
*/
bool convertTo(const VideoFormat& fmt);
bool convertTo(VideoFormat::PixelFormat fmt);
Expand Down
28 changes: 5 additions & 23 deletions src/VideoCapture.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/******************************************************************************
VideoCapture.cpp: description
Copyright (C) 2012-2014 Wang Bin <[email protected]>
Copyright (C) 2012-2015 Wang Bin <[email protected]>
* This file is part of QtAV
Expand All @@ -21,7 +21,6 @@


#include "QtAV/VideoCapture.h"
#include "QtAV/ImageConverterTypes.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QRunnable>
Expand Down Expand Up @@ -56,29 +55,12 @@ class CaptureTask : public QRunnable
qDebug("app is dieing. cancel capture task %p", this);
return;
}
// TODO: add VideoFrame::toImage(QImage::Format),toFormat(VideoFormat)...
ImageConverter *conv = ImageConverterFactory::create(ImageConverterId_FF);
const VideoFormat vformat(frame.format());
conv->setInFormat(vformat.pixelFormatFFmpeg());
conv->setOutFormat(VideoFormat::pixelFormatToFFmpeg(VideoFormat::pixelFormatFromImageFormat(qfmt)));
conv->setInSize(frame.width(), frame.height());
conv->setOutSize(frame.width(), frame.height());
const int nb_planes = vformat.planeCount();
QVector<uchar*> planes(nb_planes);
QVector<int> line_sizes(nb_planes);
for (int i = 0; i < nb_planes; ++i) {
planes[i] = frame.bits(i);
line_sizes[i] = frame.bytesPerLine(i);
}
QImage image;
if (conv->convert(planes.constData(), line_sizes.constData())) {
image = QImage((const uchar*)conv->outData().constData(), frame.width(), frame.height(), conv->outLineSizes().at(0), qfmt);
image = image.copy();
QMetaObject::invokeMethod(cap, "imageCaptured", Q_ARG(QImage, image));
} else {
QImage image(frame.toImage());
if (image.isNull()) {
qWarning("Failed to convert to QImage");
return;
}
delete conv;
QMetaObject::invokeMethod(cap, "imageCaptured", Q_ARG(QImage, image));
if (!save)
return;
bool main_thread = QThread::currentThread() == qApp->thread();
Expand Down
61 changes: 60 additions & 1 deletion src/VideoFrame.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/******************************************************************************
QtAV: Media play library based on Qt and FFmpeg
Copyright (C) 2012-2014 Wang Bin <[email protected]>
Copyright (C) 2012-2015 Wang Bin <[email protected]>
* This file is part of QtAV
Expand All @@ -27,6 +27,7 @@
#include "QtAV/private/AVCompat.h"
#include <QtCore/QSharedPointer>
#include <QtGui/QImage>
#include "utils/Logger.h"

// FF_API_PIX_FMT
#ifdef PixelFormat
Expand Down Expand Up @@ -387,6 +388,64 @@ bool VideoFrame::convertTo(const VideoFormat& fmt, const QSizeF &dstSize, const
return d_func()->convertTo(fmt, dstSize, roi);
}

QImage VideoFrame::toImage(QImage::Format fmt, const QSize& dstSize, const QRectF &roi) const
{
Q_UNUSED(dstSize);
Q_UNUSED(roi);
if (!isValid() || !bits(0)) // only in data in host memory is supported now
return QImage();
if (imageFormat() == fmt) {
return QImage((const uchar*)frameData().constData(), width(), height(), bytesPerLine(0), fmt).copy();
}
Q_D(const VideoFrame);
QScopedPointer<ImageConverter> conv(ImageConverterFactory::create(ImageConverterId_FF));
conv->setInFormat(pixelFormatFFmpeg());
conv->setOutFormat(VideoFormat::pixelFormatToFFmpeg(VideoFormat::pixelFormatFromImageFormat(fmt)));
conv->setInSize(width(), height());
if (!dstSize.isEmpty())
conv->setOutSize(dstSize.width(), dstSize.height());
else
conv->setOutSize(width(), height());
if (!conv->convert(d->planes.constData(), d->line_sizes.constData())) {
qWarning("VideoFrame::toImage error");
return QImage();
}
QImage image((const uchar*)conv->outData().constData(), width(), height(), conv->outLineSizes().at(0), fmt);
return image.copy();
}

VideoFrame VideoFrame::toFormat(const VideoFormat &fmt, const QSize& dstSize, const QRectF& roi) const
{
Q_UNUSED(dstSize);
Q_UNUSED(roi);
if (!isValid() || !bits(0)) // only in data in host memory is supported now
return VideoFrame();
if (fmt.pixelFormatFFmpeg() == pixelFormatFFmpeg())
return clone();
Q_D(const VideoFrame);
QScopedPointer<ImageConverter> conv(ImageConverterFactory::create(ImageConverterId_FF));
conv->setInFormat(pixelFormatFFmpeg());
conv->setOutFormat(fmt.pixelFormatFFmpeg());
conv->setInSize(width(), height());
if (!dstSize.isEmpty())
conv->setOutSize(dstSize.width(), dstSize.height());
else
conv->setOutSize(width(), height());
if (!conv->convert(d->planes.constData(), d->line_sizes.constData())) {
qWarning() << "VideoFrame::toFormat error: " << format() << "=>" << fmt;
return VideoFrame();
}
VideoFrame f(conv->outData(), width(), height(), fmt);
f.setBits(conv->outPlanes());
f.setBytesPerLine(conv->outLineSizes());
return f;
}

VideoFrame VideoFrame::toFormat(VideoFormat::PixelFormat pixfmt, const QSize& dstSize, const QRectF &roi) const
{
return toFormat(VideoFormat(pixfmt), dstSize, roi);
}

void *VideoFrame::map(SurfaceType type, void *handle, int plane)
{
Q_D(VideoFrame);
Expand Down

0 comments on commit 23f5a8b

Please sign in to comment.