void GenericSurfacePainter::init(const BufferFormat &format)
{
    switch (format.videoFormat()) {
    // QImage is shitty and reads integers instead of bytes,
    // thus it is affected by the host's endianness
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
    case GST_VIDEO_FORMAT_ARGB:
#else
    case GST_VIDEO_FORMAT_BGRA:
#endif
        m_imageFormat = QImage::Format_ARGB32;
        break;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
    case GST_VIDEO_FORMAT_xRGB:
#else
    case GST_VIDEO_FORMAT_BGRx:
#endif
        m_imageFormat = QImage::Format_RGB32;
        break;
    //16-bit RGB formats use host's endianness in GStreamer
    //FIXME-0.11 do endianness checks like above if semantics have changed
    case GST_VIDEO_FORMAT_RGB16:
        m_imageFormat = QImage::Format_RGB16;
        break;
    //This is not affected by endianness
    case GST_VIDEO_FORMAT_RGB:
        m_imageFormat = QImage::Format_RGB888;
        break;
    default:
        throw QString("Unsupported format");
    }
}
Exemplo n.º 2
0
static gboolean
gst_qt_quick2_video_sink_set_caps(GstBaseSink *sink, GstCaps *caps)
{
    GstQtQuick2VideoSink *self = GST_QT_QUICK2_VIDEO_SINK (sink);

    GST_LOG_OBJECT(self, "new caps %" GST_PTR_FORMAT, caps);
    BufferFormat format = BufferFormat::fromCaps(caps);

    //too lazy to do proper checks. if the format is not UNKNOWN, then
    //it should conform to the template caps formats, unless gstreamer
    //core has a bug.
    if (format.videoFormat() != GST_VIDEO_FORMAT_UNKNOWN) {
        QCoreApplication::postEvent(self->priv->delegate,
                                    new BaseDelegate::BufferFormatEvent(format));
        return TRUE;
    } else {
        return FALSE;
    }
}
void GenericSurfacePainter::paint(quint8 *data,
        const BufferFormat & frameFormat,
        QPainter *painter,
        const PaintAreas & areas)
{
    Q_ASSERT(m_imageFormat != QImage::Format_Invalid);

    QImage image(
        data,
        frameFormat.frameSize().width(),
        frameFormat.frameSize().height(),
        frameFormat.bytesPerLine(),
        m_imageFormat);

    QRectF sourceRect = areas.sourceRect;
    sourceRect.setX(sourceRect.x() * frameFormat.frameSize().width());
    sourceRect.setY(sourceRect.y() * frameFormat.frameSize().height());
    sourceRect.setWidth(sourceRect.width() * frameFormat.frameSize().width());
    sourceRect.setHeight(sourceRect.height() * frameFormat.frameSize().height());

    painter->fillRect(areas.blackArea1, Qt::black);
    painter->drawImage(areas.videoArea, image, sourceRect);
    painter->fillRect(areas.blackArea2, Qt::black);
}
Exemplo n.º 4
0
void QtVideoSinkDelegate::changePainter(const BufferFormat & format)
{
    if (m_painter) {
        m_painter->cleanup();
        if (G_UNLIKELY(!m_painter->supportsFormat(format.videoFormat()))) {
            destroyPainter();
        }
    }

    QStack<PainterType> possiblePainters;
    if (GenericSurfacePainter::supportedPixelFormats().contains(format.videoFormat())) {
        possiblePainters.push(Generic);
    }

#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
    if (OpenGLSurfacePainter::supportedPixelFormats().contains(format.videoFormat())) {
        if (m_supportedPainters & ArbFp) {
            possiblePainters.push(ArbFp);
        }

        if (m_supportedPainters & Glsl) {
            possiblePainters.push(Glsl);
        }
    }
#endif

    while (!possiblePainters.isEmpty()) {
        if (!m_painter) {
            PainterType type = possiblePainters.pop();
            switch(type) {
#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
            case Glsl:
                GST_LOG_OBJECT(m_sink, "Creating GLSL painter");
                m_painter = new GlslSurfacePainter;
                break;
# ifndef QT_OPENGL_ES
            case ArbFp:
                GST_LOG_OBJECT(m_sink, "Creating ARB Fragment Shader painter");
                m_painter = new ArbFpSurfacePainter;
                break;
# endif
#endif
            case Generic:
                GST_LOG_OBJECT(m_sink, "Creating Generic painter");
                m_painter = new GenericSurfacePainter;
                break;
            default:
                Q_ASSERT(false);
            }
        }

        try {
            m_painter->init(format);
            return;
        } catch (const QString & error) {
            GST_ELEMENT_WARNING(m_sink, RESOURCE, FAILED,
                    ("Failed to start painter"), ("%s", error.toUtf8().constData()));
            delete m_painter;
            m_painter = 0;
        }
    }

    GST_ELEMENT_ERROR(m_sink, RESOURCE, FAILED,
            ("Failed to create a painter for the given format"), (NULL));
}
Exemplo n.º 5
0
void QtVideoSinkDelegate::paint(QPainter *painter, const QRectF & targetArea)
{
    GST_TRACE_OBJECT(m_sink, "paint called");

#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
    if (m_glContext) {
        Q_ASSERT_X(m_glContext == QGLContext::currentContext(),
            "qtvideosink - paint",
            "Please use a QPainter that is initialized to paint on the "
            "GL surface that has the same context as the one given on the glcontext property"
        );
    }
#endif

    if (!m_buffer) {
        painter->fillRect(targetArea, Qt::black);
    } else {
        BufferFormat format = m_formatDirty ?
                BufferFormat::fromCaps(GST_BUFFER_CAPS(m_buffer)) : m_bufferFormat;

        //recalculate the video area if needed
        QReadLocker forceAspectRatioLocker(&m_forceAspectRatioLock);
        if (targetArea != m_areas.targetArea
             || (m_formatDirty && (format.frameSize() != m_bufferFormat.frameSize()
                               || format.pixelAspectRatio() != m_bufferFormat.pixelAspectRatio()))
             || m_forceAspectRatioDirty)
        {
            m_forceAspectRatioDirty = false;

            if (m_forceAspectRatio) {
                QReadLocker pixelAspectRatioLocker(&m_pixelAspectRatioLock);
                m_areas.calculate(targetArea, format.frameSize(),
                                  format.pixelAspectRatio(), m_pixelAspectRatio);
            } else {
                m_areas.targetArea = targetArea;
                m_areas.videoArea = targetArea;
                m_areas.blackArea1 = m_areas.blackArea2 = QRectF();
            }

            GST_LOG_OBJECT(m_sink,
                "Recalculated paint areas: "
                "Frame size: " QSIZE_FORMAT ", "
                "target area: " QRECTF_FORMAT ", "
                "video area: " QRECTF_FORMAT ", "
                "black1: " QRECTF_FORMAT ", "
                "black2: " QRECTF_FORMAT,
                QSIZE_FORMAT_ARGS(format.frameSize()),
                QRECTF_FORMAT_ARGS(m_areas.targetArea),
                QRECTF_FORMAT_ARGS(m_areas.videoArea),
                QRECTF_FORMAT_ARGS(m_areas.blackArea1),
                QRECTF_FORMAT_ARGS(m_areas.blackArea2)
            );
        }
        forceAspectRatioLocker.unlock();

        if (m_formatDirty /* || m_clipRectDirty */) {
            //TODO add properties for modifying clipRect
            m_clipRect = QRectF(QPointF(0,0), format.frameSize());
        }

        //if either pixelFormat or frameSize have changed, we need to reset the painter
        //and/or change painter, in case the current one does not handle the requested format
        if ((m_formatDirty && (format.videoFormat() != m_bufferFormat.videoFormat()
                || format.colorMatrix() != m_bufferFormat.colorMatrix()
                || format.frameSize() != m_bufferFormat.frameSize()))
            || !m_painter)
        {
            changePainter(format);

            m_bufferFormat = format;
            m_formatDirty = false;

            //make sure to update the colors after changing painter
            m_colorsDirty = true;
        }

        if (G_LIKELY(m_painter)) {
            QReadLocker colorsLocker(&m_colorsLock);
            if (m_colorsDirty) {
                m_painter->updateColors(m_brightness, m_contrast, m_hue, m_saturation);
                m_colorsDirty = false;
            }
            colorsLocker.unlock();

            m_painter->paint(m_buffer->data, m_bufferFormat, m_clipRect, painter, m_areas);
        }
    }
}