blob: 89d5a9db9e634e50d7ff03ec7b5faeb9549d287a [file] [log] [blame]
/* 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 <http://www.gnu.org/licenses/>.
*/
#include <QApplication>
#include "videowidget.h"
#include "qwidgetvideosink.h"
QT_BEGIN_NAMESPACE
namespace Phonon
{
namespace Gstreamer
{
static GstVideoSinkClass* parentClass;
/*!
\class gstreamer::QWidgetVideoSink
\internal
*/
template <VideoFormat FMT>
GstCaps* QWidgetVideoSink<FMT>::get_caps(GstBaseSink* sink)
{
Q_UNUSED(sink);
return 0;
}
template <>
const char* QWidgetVideoSinkClass<VideoFormat_YUV>::get_name()
{
return "QWidgetVideoSinkYUV";
}
template <>
const char* QWidgetVideoSinkClass<VideoFormat_RGB>::get_name()
{
return "QWidgetVideoSinkRGB";
}
template <VideoFormat FMT>
gboolean QWidgetVideoSink<FMT>::set_caps(GstBaseSink* sink, GstCaps* caps)
{
GstStructure* data;
QWidgetVideoSink<FMT> *self = G_TYPE_CHECK_INSTANCE_CAST(sink, QWidgetVideoSinkClass<FMT>::get_type(), QWidgetVideoSink<FMT>);
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 <VideoFormat FMT>
GstStateChangeReturn QWidgetVideoSink<FMT>::change_state(GstElement* element, GstStateChange transition)
{
return GST_ELEMENT_CLASS(parentClass)->change_state(element, transition);
}
template <VideoFormat FMT>
GstFlowReturn QWidgetVideoSink<FMT>::render(GstBaseSink* sink, GstBuffer* buf)
{
GstFlowReturn rc = GST_FLOW_OK;
if (buf != 0)
{
QWidgetVideoSink<FMT> *self = G_TYPE_CHECK_INSTANCE_CAST(sink, QWidgetVideoSinkClass<FMT>::get_type(), QWidgetVideoSink<FMT>);
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 <VideoFormat FMT>
struct template_factory;
template <>
struct template_factory<VideoFormat_YUV>
{
static GstStaticPadTemplate *getFactory()
{
return &template_factory_yuv;
}
};
template <>
struct template_factory<VideoFormat_RGB>
{
static GstStaticPadTemplate *getFactory()
{
return &template_factory_rgb;
}
};
template <VideoFormat FMT>
void QWidgetVideoSink<FMT>::base_init(gpointer g_class)
{
gst_element_class_add_pad_template(GST_ELEMENT_CLASS(g_class),
gst_static_pad_template_get(template_factory<FMT>::getFactory()));
}
template <VideoFormat FMT>
void QWidgetVideoSink<FMT>::instance_init(GTypeInstance *instance, gpointer g_class)
{
Q_UNUSED(g_class);
QWidgetVideoSink<FMT>* self = reinterpret_cast<QWidgetVideoSink<FMT>*>(instance);
self->renderWidget = 0;
self->width = 0;
self->height = 0;
self->bpp = 0;
self->depth = 0;
}
// QWidgetVideoSinkClass
template <VideoFormat FMT>
void QWidgetVideoSinkClass<FMT>::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<GstVideoSinkClass*>(g_type_class_peek_parent(g_class));
// base
gstBaseSinkClass->set_caps = QWidgetVideoSink<FMT>::set_caps;
gstBaseSinkClass->preroll = QWidgetVideoSink<FMT>::render;
gstBaseSinkClass->render = QWidgetVideoSink<FMT>::render;
// element
gstElementClass->change_state = QWidgetVideoSink<FMT>::change_state;
}
template <VideoFormat FMT>
GType QWidgetVideoSinkClass<FMT>::get_type()
{
static GType type = 0;
if (type == 0)
{
static const GTypeInfo info =
{
sizeof(QWidgetVideoSinkClass<FMT>), // class_size
QWidgetVideoSink<FMT>::base_init, // base init
NULL, // base_finalize
QWidgetVideoSinkClass<FMT>::class_init, // class_init
NULL, // class_finalize
NULL, // class_data
sizeof(QWidgetVideoSink<FMT>), // instance_size
0, // n_preallocs
QWidgetVideoSink<FMT>::instance_init, // instance_init
0 // value_table
};
type = g_type_register_static(GST_TYPE_VIDEO_SINK,
QWidgetVideoSinkClass<FMT>::get_name(),
&info,
GTypeFlags(0));
}
return type;
}
GType get_type_YUV()
{
return QWidgetVideoSinkClass<VideoFormat_YUV>::get_type();
}
GType get_type_RGB()
{
return QWidgetVideoSinkClass<VideoFormat_RGB>::get_type();
}
}
} //namespace Phonon::Gstreamer
QT_END_NAMESPACE