diff options
Diffstat (limited to 'src/gsttools/qvideosurfacegstsink.cpp')
-rw-r--r-- | src/gsttools/qvideosurfacegstsink.cpp | 246 |
1 files changed, 24 insertions, 222 deletions
diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp index f3e2d884c..36644581e 100644 --- a/src/gsttools/qvideosurfacegstsink.cpp +++ b/src/gsttools/qvideosurfacegstsink.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** @@ -10,9 +10,9 @@ ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -23,8 +23,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ @@ -41,8 +41,13 @@ #include <private/qmediapluginloader_p.h> #include "qgstvideobuffer_p.h" +#include "qgstutils_p.h" #include "qvideosurfacegstsink_p.h" +#if GST_VERSION_MAJOR >=1 +#include <gst/video/video.h> +#endif + //#define DEBUG_VIDEO_SURFACE_SINK QT_BEGIN_NAMESPACE @@ -62,10 +67,12 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate( if (m_surface) { foreach (QObject *instance, bufferPoolLoader()->instances(QGstBufferPoolPluginKey)) { QGstBufferPoolInterface* plugin = qobject_cast<QGstBufferPoolInterface*>(instance); + if (plugin) { m_pools.append(plugin); } } + updateSupportedFormats(); connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats())); } @@ -191,13 +198,15 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer) m_format.frameSize(), m_format.pixelFormat()); - QVideoSurfaceGstSink::setFrameTimeStamps(&m_frame, buffer); + QGstUtils::setFrameTimeStamps(&m_frame, buffer); m_renderReturn = GST_FLOW_OK; if (QThread::currentThread() == thread()) { if (!m_surface.isNull()) m_surface->present(m_frame); + else + qWarning() << "m_surface.isNull()."; } else { QMetaObject::invokeMethod(this, "queuedRender", Qt::QueuedConnection); m_renderCondition.wait(&m_mutex, 300); @@ -283,90 +292,6 @@ void QVideoSurfaceGstDelegate::updateSupportedFormats() } } -struct YuvFormat -{ - QVideoFrame::PixelFormat pixelFormat; - guint32 fourcc; - int bitsPerPixel; -}; - -static const YuvFormat qt_yuvColorLookup[] = -{ - { QVideoFrame::Format_YUV420P, GST_MAKE_FOURCC('I','4','2','0'), 8 }, - { QVideoFrame::Format_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 }, - { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 }, - { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 16 }, - { QVideoFrame::Format_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 }, - { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 }, - { QVideoFrame::Format_AYUV444, GST_MAKE_FOURCC('A','Y','U','V'), 32 } -}; - -static int indexOfYuvColor(QVideoFrame::PixelFormat format) -{ - const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat); - - for (int i = 0; i < count; ++i) - if (qt_yuvColorLookup[i].pixelFormat == format) - return i; - - return -1; -} - -static int indexOfYuvColor(guint32 fourcc) -{ - const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat); - - for (int i = 0; i < count; ++i) - if (qt_yuvColorLookup[i].fourcc == fourcc) - return i; - - return -1; -} - -struct RgbFormat -{ - QVideoFrame::PixelFormat pixelFormat; - int bitsPerPixel; - int depth; - int endianness; - int red; - int green; - int blue; - int alpha; -}; - -static const RgbFormat qt_rgbColorLookup[] = -{ - { QVideoFrame::Format_RGB32 , 32, 24, 4321, 0x0000FF00, 0x00FF0000, int(0xFF000000), 0x00000000 }, - { QVideoFrame::Format_RGB32 , 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, - { QVideoFrame::Format_BGR32 , 32, 24, 4321, int(0xFF000000), 0x00FF0000, 0x0000FF00, 0x00000000 }, - { QVideoFrame::Format_BGR32 , 32, 24, 1234, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }, - { QVideoFrame::Format_ARGB32, 32, 24, 4321, 0x0000FF00, 0x00FF0000, int(0xFF000000), 0x000000FF }, - { QVideoFrame::Format_ARGB32, 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, int(0xFF000000) }, - { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, - { QVideoFrame::Format_BGR24 , 24, 24, 4321, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }, - { QVideoFrame::Format_RGB565, 16, 16, 1234, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 } -}; - -static int indexOfRgbColor( - int bits, int depth, int endianness, int red, int green, int blue, int alpha) -{ - const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat); - - for (int i = 0; i < count; ++i) { - if (qt_rgbColorLookup[i].bitsPerPixel == bits - && qt_rgbColorLookup[i].depth == depth - && qt_rgbColorLookup[i].endianness == endianness - && qt_rgbColorLookup[i].red == red - && qt_rgbColorLookup[i].green == green - && qt_rgbColorLookup[i].blue == blue - && qt_rgbColorLookup[i].alpha == alpha) { - return i; - } - } - return -1; -} - static GstVideoSinkClass *sink_parent_class; #define VO_SINK(s) QVideoSurfaceGstSink *sink(reinterpret_cast<QVideoSurfaceGstSink *>(s)) @@ -494,8 +419,6 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) { VO_SINK(base); - GstCaps *caps = gst_caps_new_empty(); - // Find the supported pixel formats // with buffer pool specific formats listed first QList<QVideoFrame::PixelFormat> supportedFormats; @@ -503,6 +426,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) QList<QVideoFrame::PixelFormat> poolHandleFormats; sink->delegate->poolMutex()->lock(); QGstBufferPoolInterface *pool = sink->delegate->pool(); + if (pool) poolHandleFormats = sink->delegate->supportedPixelFormats(pool->handleType()); sink->delegate->poolMutex()->unlock(); @@ -513,47 +437,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) supportedFormats.append(format); } - foreach (QVideoFrame::PixelFormat format, supportedFormats) { - int index = indexOfYuvColor(format); - - if (index != -1) { - gst_caps_append_structure(caps, gst_structure_new( - "video/x-raw-yuv", - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1, - "width" , GST_TYPE_INT_RANGE, 1, INT_MAX, - "height" , GST_TYPE_INT_RANGE, 1, INT_MAX, - "format" , GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc, - NULL)); - continue; - } - - const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat); - - for (int i = 0; i < count; ++i) { - if (qt_rgbColorLookup[i].pixelFormat == format) { - GstStructure *structure = gst_structure_new( - "video/x-raw-rgb", - "framerate" , GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1, - "width" , GST_TYPE_INT_RANGE, 1, INT_MAX, - "height" , GST_TYPE_INT_RANGE, 1, INT_MAX, - "bpp" , G_TYPE_INT, qt_rgbColorLookup[i].bitsPerPixel, - "depth" , G_TYPE_INT, qt_rgbColorLookup[i].depth, - "endianness", G_TYPE_INT, qt_rgbColorLookup[i].endianness, - "red_mask" , G_TYPE_INT, qt_rgbColorLookup[i].red, - "green_mask", G_TYPE_INT, qt_rgbColorLookup[i].green, - "blue_mask" , G_TYPE_INT, qt_rgbColorLookup[i].blue, - NULL); - - if (qt_rgbColorLookup[i].alpha != 0) { - gst_structure_set( - structure, "alpha_mask", G_TYPE_INT, qt_rgbColorLookup[i].alpha, NULL); - } - gst_caps_append_structure(caps, structure); - } - } - } - - return caps; + return QGstUtils::capsForFormats(supportedFormats); } gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps) @@ -575,7 +459,7 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps) QAbstractVideoBuffer::HandleType handleType = pool ? pool->handleType() : QAbstractVideoBuffer::NoHandle; - QVideoSurfaceFormat format = formatForCaps(caps, &bytesPerLine, handleType); + QVideoSurfaceFormat format = QGstUtils::formatForCaps(caps, &bytesPerLine, handleType); if (sink->delegate->isActive()) { QVideoSurfaceFormat surfaceFormst = sink->delegate->surfaceFormat(); @@ -592,7 +476,7 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps) sink->lastRequestedCaps = 0; #ifdef DEBUG_VIDEO_SURFACE_SINK - qDebug() << "Staring video surface, format:"; + qDebug() << "Starting video surface, format:"; qDebug() << format; qDebug() << "bytesPerLine:" << bytesPerLine; #endif @@ -606,87 +490,6 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps) return FALSE; } -QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *bytesPerLine, QAbstractVideoBuffer::HandleType handleType) -{ - const GstStructure *structure = gst_caps_get_structure(caps, 0); - - QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid; - int bitsPerPixel = 0; - - QSize size; - gst_structure_get_int(structure, "width", &size.rwidth()); - gst_structure_get_int(structure, "height", &size.rheight()); - - if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) { - guint32 fourcc = 0; - gst_structure_get_fourcc(structure, "format", &fourcc); - - int index = indexOfYuvColor(fourcc); - if (index != -1) { - pixelFormat = qt_yuvColorLookup[index].pixelFormat; - bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel; - } - } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) { - int depth = 0; - int endianness = 0; - int red = 0; - int green = 0; - int blue = 0; - int alpha = 0; - - gst_structure_get_int(structure, "bpp", &bitsPerPixel); - gst_structure_get_int(structure, "depth", &depth); - gst_structure_get_int(structure, "endianness", &endianness); - gst_structure_get_int(structure, "red_mask", &red); - gst_structure_get_int(structure, "green_mask", &green); - gst_structure_get_int(structure, "blue_mask", &blue); - gst_structure_get_int(structure, "alpha_mask", &alpha); - - int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha); - - if (index != -1) - pixelFormat = qt_rgbColorLookup[index].pixelFormat; - } - - if (pixelFormat != QVideoFrame::Format_Invalid) { - QVideoSurfaceFormat format(size, pixelFormat, handleType); - - QPair<int, int> rate; - gst_structure_get_fraction(structure, "framerate", &rate.first, &rate.second); - - if (rate.second) - format.setFrameRate(qreal(rate.first)/rate.second); - - gint aspectNum = 0; - gint aspectDenum = 0; - if (gst_structure_get_fraction( - structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) { - if (aspectDenum > 0) - format.setPixelAspectRatio(aspectNum, aspectDenum); - } - - if (bytesPerLine) - *bytesPerLine = ((size.width() * bitsPerPixel / 8) + 3) & ~3; - - return format; - } - - return QVideoSurfaceFormat(); -} - -void QVideoSurfaceGstSink::setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer) -{ - // GStreamer uses nanoseconds, Qt uses microseconds - qint64 startTime = GST_BUFFER_TIMESTAMP(buffer); - if (startTime >= 0) { - frame->setStartTime(startTime/G_GINT64_CONSTANT (1000)); - - qint64 duration = GST_BUFFER_DURATION(buffer); - if (duration >= 0) - frame->setEndTime((startTime + duration)/G_GINT64_CONSTANT (1000)); - } -} - GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( GstBaseSink *base, guint64 offset, guint size, GstCaps *caps, GstBuffer **buffer) { @@ -731,7 +534,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( if (sink->delegate->isActive()) { //if format was changed, restart the surface - QVideoSurfaceFormat format = formatForCaps(intersection); + QVideoSurfaceFormat format = QGstUtils::formatForCaps(intersection); QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat(); if (format.pixelFormat() != surfaceFormat.pixelFormat() || @@ -749,7 +552,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( QAbstractVideoBuffer::HandleType handleType = pool ? pool->handleType() : QAbstractVideoBuffer::NoHandle; - QVideoSurfaceFormat format = formatForCaps(intersection, &bytesPerLine, handleType); + QVideoSurfaceFormat format = QGstUtils::formatForCaps(intersection, &bytesPerLine, handleType); if (!sink->delegate->start(format, bytesPerLine)) { qWarning() << "failed to start video surface"; @@ -763,7 +566,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat(); if (!pool->isFormatSupported(surfaceFormat)) { - //qDebug() << "sink doesn't support native pool format, skip custom buffers allocation"; + qDebug() << "sink doesn't support native pool format, skip custom buffers allocation"; return GST_FLOW_OK; } @@ -787,7 +590,6 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( gboolean QVideoSurfaceGstSink::start(GstBaseSink *base) { Q_UNUSED(base); - return TRUE; } |