/* This file is part of the KDE project.
Copyright (C) 2009 Nokia Corporation 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