1
/*  This file is part of the KDE project.
2
3
    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
5
    This library is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU Lesser General Public License as published by
7
    the Free Software Foundation, either version 2.1 or 3 of the License.
8
9
    This library is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU Lesser General Public License for more details.
13
14
    You should have received a copy of the GNU Lesser General Public License
15
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
#include <QApplication>
19
#include "videowidget.h"
20
#include "qwidgetvideosink.h"
21
22
QT_BEGIN_NAMESPACE
23
24
namespace Phonon
25
{
26
namespace Gstreamer
27
{
28
29
static GstVideoSinkClass*   parentClass;
30
31
/*!
32
    \class gstreamer::QWidgetVideoSink
33
    \internal
34
*/
35
36
template <VideoFormat FMT>
37
GstCaps* QWidgetVideoSink<FMT>::get_caps(GstBaseSink* sink)
38
{
39
    Q_UNUSED(sink);
40
    return 0;
41
}
42
43
template <>
44
const char* QWidgetVideoSinkClass<VideoFormat_YUV>::get_name()
45
{
46
    return "QWidgetVideoSinkYUV";
47
}
48
49
template <>
50
const char* QWidgetVideoSinkClass<VideoFormat_RGB>::get_name()
51
{
52
    return "QWidgetVideoSinkRGB";
53
}
54
55
template <VideoFormat FMT>
56
gboolean QWidgetVideoSink<FMT>::set_caps(GstBaseSink* sink, GstCaps* caps)
57
{
58
    GstStructure*       data;
59
    QWidgetVideoSink<FMT> *self = G_TYPE_CHECK_INSTANCE_CAST(sink, QWidgetVideoSinkClass<FMT>::get_type(), QWidgetVideoSink<FMT>);
60
61
    data = gst_caps_get_structure(caps, 0);
62
63
    gst_structure_get_int(data, "width", &self->width);
64
    gst_structure_get_int(data, "height", &self->height);
65
    gst_structure_get_int(data, "bpp", &self->bpp);
66
    gst_structure_get_int(data, "depth", &self->depth);
67
    return TRUE;
68
}
69
70
template <VideoFormat FMT>
71
GstStateChangeReturn QWidgetVideoSink<FMT>::change_state(GstElement* element, GstStateChange transition)
72
{
73
    return GST_ELEMENT_CLASS(parentClass)->change_state(element, transition);
74
}
75
76
template <VideoFormat FMT>
77
GstFlowReturn QWidgetVideoSink<FMT>::render(GstBaseSink* sink, GstBuffer* buf)
78
{
79
    GstFlowReturn rc = GST_FLOW_OK;
80
81
    if (buf != 0)
82
    {
83
        QWidgetVideoSink<FMT> *self = G_TYPE_CHECK_INSTANCE_CAST(sink, QWidgetVideoSinkClass<FMT>::get_type(), QWidgetVideoSink<FMT>);
84
        QByteArray frame;
85
        frame.resize(buf->size);
86
        memcpy(frame.data(), buf->data, buf->size);
87
        NewFrameEvent *frameEvent = new NewFrameEvent(frame, self->width, self->height);
88
        QApplication::postEvent(self->renderWidget, frameEvent);
89
    }
90
    else
91
        rc = GST_FLOW_ERROR;
92
    return rc;
93
}
94
95
static GstStaticPadTemplate template_factory_yuv =
96
    GST_STATIC_PAD_TEMPLATE("sink",
97
                            GST_PAD_SINK,
98
                            GST_PAD_ALWAYS,
99
                            GST_STATIC_CAPS("video/x-raw-yuv, "
100
                                            "framerate = (fraction) [ 0, MAX ], "
101
                                            "width = (int) [ 1, MAX ], "
102
                                            "height = (int) [ 1, MAX ],"
103
                                            "bpp = (int) 32"));
104
105
static GstStaticPadTemplate template_factory_rgb =
106
    GST_STATIC_PAD_TEMPLATE("sink",
107
                            GST_PAD_SINK,
108
                            GST_PAD_ALWAYS,
109
                            GST_STATIC_CAPS("video/x-raw-rgb, "
110
                                            "framerate = (fraction) [ 0, MAX ], "
111
                                            "width = (int) [ 1, MAX ], "
112
                                            "height = (int) [ 1, MAX ],"
113
                                            "bpp = (int) 32"));
114
115
template <VideoFormat FMT>
116
struct template_factory;
117
118
119
template <>
120
struct template_factory<VideoFormat_YUV>
121
{
122
    static GstStaticPadTemplate *getFactory()
123
    {
124
        return &template_factory_yuv;
125
    }
126
};
127
128
template <>
129
struct template_factory<VideoFormat_RGB>
130
{
131
    static GstStaticPadTemplate *getFactory()
132
    {
133
        return &template_factory_rgb;
134
    }
135
};
136
137
template <VideoFormat FMT>
138
void QWidgetVideoSink<FMT>::base_init(gpointer g_class)
139
{
140
    gst_element_class_add_pad_template(GST_ELEMENT_CLASS(g_class),
141
                                       gst_static_pad_template_get(template_factory<FMT>::getFactory()));
142
}
143
144
template <VideoFormat FMT>
145
void QWidgetVideoSink<FMT>::instance_init(GTypeInstance *instance, gpointer g_class)
146
{
147
    Q_UNUSED(g_class);
148
149
    QWidgetVideoSink<FMT>* self = reinterpret_cast<QWidgetVideoSink<FMT>*>(instance);
150
151
    self->renderWidget = 0;
152
    self->width = 0;
153
    self->height = 0;
154
    self->bpp = 0;
155
    self->depth = 0;
156
}
157
158
// QWidgetVideoSinkClass
159
template <VideoFormat FMT>
160
void QWidgetVideoSinkClass<FMT>::class_init(gpointer g_class, gpointer class_data)
161
{
162
    Q_UNUSED(class_data);
163
    GstBaseSinkClass*   gstBaseSinkClass = (GstBaseSinkClass*)g_class;
164
    GstElementClass*    gstElementClass = (GstElementClass*)g_class;
165
166
    parentClass = reinterpret_cast<GstVideoSinkClass*>(g_type_class_peek_parent(g_class));
167
168
    // base
169
    gstBaseSinkClass->set_caps = QWidgetVideoSink<FMT>::set_caps;
170
    gstBaseSinkClass->preroll = QWidgetVideoSink<FMT>::render;
171
    gstBaseSinkClass->render = QWidgetVideoSink<FMT>::render;
172
173
    // element
174
    gstElementClass->change_state = QWidgetVideoSink<FMT>::change_state;
175
}
176
177
template <VideoFormat FMT>
178
GType QWidgetVideoSinkClass<FMT>::get_type()
179
{
180
    static GType type = 0;
181
182
    if (type == 0)
183
    {
184
        static const GTypeInfo info =
185
        {
186
            sizeof(QWidgetVideoSinkClass<FMT>),                 // class_size
187
            QWidgetVideoSink<FMT>::base_init,                   // base init
188
            NULL,                                               // base_finalize
189
190
            QWidgetVideoSinkClass<FMT>::class_init,             // class_init
191
            NULL,                                               // class_finalize
192
            NULL,                                               // class_data
193
194
            sizeof(QWidgetVideoSink<FMT>),                      // instance_size
195
            0,                                                  // n_preallocs
196
            QWidgetVideoSink<FMT>::instance_init,               // instance_init
197
            0                                                   // value_table
198
        };
199
200
        type = g_type_register_static(GST_TYPE_VIDEO_SINK,
201
                                     QWidgetVideoSinkClass<FMT>::get_name(),
202
                                      &info,
203
                                      GTypeFlags(0));
204
    }
205
    return type;
206
}
207
208
GType get_type_YUV()
209
{
210
    return QWidgetVideoSinkClass<VideoFormat_YUV>::get_type();
211
}
212
213
GType get_type_RGB()
214
{
215
    return QWidgetVideoSinkClass<VideoFormat_RGB>::get_type();
216
}
217
218
}
219
} //namespace Phonon::Gstreamer
220
221
QT_END_NAMESPACE