/* This file is part of the KDE project. Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 or 3 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include #include "videowidget.h" #include "qwidgetvideosink.h" QT_BEGIN_NAMESPACE namespace Phonon { namespace Gstreamer { static GstVideoSinkClass* parentClass; /*! \class gstreamer::QWidgetVideoSink \internal */ template GstCaps* QWidgetVideoSink::get_caps(GstBaseSink* sink) { Q_UNUSED(sink); return 0; } template <> const char* QWidgetVideoSinkClass::get_name() { return "QWidgetVideoSinkYUV"; } template <> const char* QWidgetVideoSinkClass::get_name() { return "QWidgetVideoSinkRGB"; } template gboolean QWidgetVideoSink::set_caps(GstBaseSink* sink, GstCaps* caps) { GstStructure* data; QWidgetVideoSink *self = G_TYPE_CHECK_INSTANCE_CAST(sink, QWidgetVideoSinkClass::get_type(), QWidgetVideoSink); data = gst_caps_get_structure(caps, 0); gst_structure_get_int(data, "width", &self->width); gst_structure_get_int(data, "height", &self->height); gst_structure_get_int(data, "bpp", &self->bpp); gst_structure_get_int(data, "depth", &self->depth); return TRUE; } template GstStateChangeReturn QWidgetVideoSink::change_state(GstElement* element, GstStateChange transition) { return GST_ELEMENT_CLASS(parentClass)->change_state(element, transition); } template GstFlowReturn QWidgetVideoSink::render(GstBaseSink* sink, GstBuffer* buf) { GstFlowReturn rc = GST_FLOW_OK; if (buf != 0) { QWidgetVideoSink *self = G_TYPE_CHECK_INSTANCE_CAST(sink, QWidgetVideoSinkClass::get_type(), QWidgetVideoSink); QByteArray frame; frame.resize(buf->size); memcpy(frame.data(), buf->data, buf->size); NewFrameEvent *frameEvent = new NewFrameEvent(frame, self->width, self->height); QApplication::postEvent(self->renderWidget, frameEvent); } else rc = GST_FLOW_ERROR; return rc; } static GstStaticPadTemplate template_factory_yuv = GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("video/x-raw-yuv, " "framerate = (fraction) [ 0, MAX ], " "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]," "bpp = (int) 32")); static GstStaticPadTemplate template_factory_rgb = GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("video/x-raw-rgb, " "framerate = (fraction) [ 0, MAX ], " "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]," "bpp = (int) 32")); template struct template_factory; template <> struct template_factory { static GstStaticPadTemplate *getFactory() { return &template_factory_yuv; } }; template <> struct template_factory { static GstStaticPadTemplate *getFactory() { return &template_factory_rgb; } }; template void QWidgetVideoSink::base_init(gpointer g_class) { gst_element_class_add_pad_template(GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(template_factory::getFactory())); } template void QWidgetVideoSink::instance_init(GTypeInstance *instance, gpointer g_class) { Q_UNUSED(g_class); QWidgetVideoSink* self = reinterpret_cast*>(instance); self->renderWidget = 0; self->width = 0; self->height = 0; self->bpp = 0; self->depth = 0; } // QWidgetVideoSinkClass template void QWidgetVideoSinkClass::class_init(gpointer g_class, gpointer class_data) { Q_UNUSED(class_data); GstBaseSinkClass* gstBaseSinkClass = (GstBaseSinkClass*)g_class; GstElementClass* gstElementClass = (GstElementClass*)g_class; parentClass = reinterpret_cast(g_type_class_peek_parent(g_class)); // base gstBaseSinkClass->set_caps = QWidgetVideoSink::set_caps; gstBaseSinkClass->preroll = QWidgetVideoSink::render; gstBaseSinkClass->render = QWidgetVideoSink::render; // element gstElementClass->change_state = QWidgetVideoSink::change_state; } template GType QWidgetVideoSinkClass::get_type() { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(QWidgetVideoSinkClass), // class_size QWidgetVideoSink::base_init, // base init NULL, // base_finalize QWidgetVideoSinkClass::class_init, // class_init NULL, // class_finalize NULL, // class_data sizeof(QWidgetVideoSink), // instance_size 0, // n_preallocs QWidgetVideoSink::instance_init, // instance_init 0 // value_table }; type = g_type_register_static(GST_TYPE_VIDEO_SINK, QWidgetVideoSinkClass::get_name(), &info, GTypeFlags(0)); } return type; } GType get_type_YUV() { return QWidgetVideoSinkClass::get_type(); } GType get_type_RGB() { return QWidgetVideoSinkClass::get_type(); } } } //namespace Phonon::Gstreamer QT_END_NAMESPACE