1 /* GStreamer am7xxx sink plugin
2 * Copyright (C) 2013 Antonio Ospite <ospite@studenti.unina.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
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 GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
24 #include "gstam7xxxsink.h"
26 /* Debugging category */
27 GST_DEBUG_CATEGORY_STATIC (am7xxxsink_debug);
28 #define GST_CAT_DEFAULT am7xxxsink_debug
37 static void gst_am7xxxsink_get_times (GstBaseSink * basesink,
38 GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
41 static GstFlowReturn gst_am7xxxsink_show_frame (GstVideoSink * videosink,
44 static gboolean gst_am7xxxsink_start (GstBaseSink * bsink);
45 static gboolean gst_am7xxxsink_stop (GstBaseSink * bsink);
47 static GstCaps *gst_am7xxxsink_getcaps (GstBaseSink * bsink, GstCaps * filter);
48 static gboolean gst_am7xxxsink_setcaps (GstBaseSink * bsink, GstCaps * caps);
50 static void gst_am7xxxsink_finalize (GObject * object);
51 static void gst_am7xxxsink_set_property (GObject * object,
52 guint prop_id, const GValue * value, GParamSpec * pspec);
53 static void gst_am7xxxsink_get_property (GObject * object,
54 guint prop_id, GValue * value, GParamSpec * pspec);
55 static GstStateChangeReturn gst_am7xxxsink_change_state (GstElement * element,
56 GstStateChange transition);
58 #define RAW_VIDEO_CAPS "{ NV12 }"
60 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
63 GST_STATIC_CAPS ("image/jpeg;" GST_VIDEO_CAPS_MAKE (RAW_VIDEO_CAPS))
66 #define parent_class gst_am7xxxsink_parent_class
67 G_DEFINE_TYPE (GstAM7XXXSink, gst_am7xxxsink, GST_TYPE_VIDEO_SINK);
70 gst_am7xxxsink_init (GstAM7XXXSink * am7xxxsink)
72 /* nothing to do here yet */
77 gst_am7xxxsink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
78 GstClockTime * start, GstClockTime * end)
80 GstAM7XXXSink *am7xxxsink;
82 am7xxxsink = GST_AM7XXXSINK (basesink);
84 if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
85 *start = GST_BUFFER_TIMESTAMP (buffer);
86 if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
87 *end = *start + GST_BUFFER_DURATION (buffer);
89 if (am7xxxsink->fps_n > 0) {
91 gst_util_uint64_scale_int (GST_SECOND, am7xxxsink->fps_d,
100 gst_am7xxxsink_getcaps (GstBaseSink * bsink, GstCaps * filter)
102 GstAM7XXXSink *am7xxxsink;
105 am7xxxsink = GST_AM7XXXSINK (bsink);
107 caps = gst_static_pad_template_get_caps (&sink_template);
109 if (!am7xxxsink->dev)
112 /* display size negotiation */
113 caps = gst_caps_make_writable (caps);
114 gst_caps_set_simple (caps,
115 "width", GST_TYPE_INT_RANGE, 1, GST_VIDEO_SINK_WIDTH(am7xxxsink),
116 "height", GST_TYPE_INT_RANGE, 1, GST_VIDEO_SINK_HEIGHT(am7xxxsink),
117 "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
121 if (filter != NULL) {
124 icaps = gst_caps_intersect (caps, filter);
125 gst_caps_unref (caps);
133 gst_am7xxxsink_setcaps (GstBaseSink * bsink, GstCaps * vscapslist)
135 GstAM7XXXSink *am7xxxsink;
136 GstStructure *structure;
137 const gchar *mimetype;
141 am7xxxsink = GST_AM7XXXSINK (bsink);
143 ret = gst_video_info_from_caps (&vinfo, vscapslist);
147 structure = gst_caps_get_structure (vscapslist, 0);
148 mimetype = gst_structure_get_name (structure);
150 if (g_str_equal (mimetype, "image/jpeg")) {
151 am7xxxsink->format = AM7XXX_IMAGE_FORMAT_JPEG;
152 } else if (g_str_equal (mimetype, "video/x-raw")) {
153 if (GST_VIDEO_INFO_FORMAT (&vinfo) == GST_VIDEO_FORMAT_NV12) {
154 am7xxxsink->format = AM7XXX_IMAGE_FORMAT_NV12;
162 am7xxxsink->width = GST_VIDEO_INFO_WIDTH(&vinfo);
163 am7xxxsink->height = GST_VIDEO_INFO_HEIGHT(&vinfo);
169 GST_WARNING_OBJECT (am7xxxsink, "Could not figure format of input caps");
176 gst_am7xxxsink_show_frame (GstVideoSink * videosink, GstBuffer * buf)
179 GstAM7XXXSink *am7xxxsink;
183 am7xxxsink = GST_AM7XXXSINK (videosink);
185 ret = gst_buffer_map (buf, &map, GST_MAP_READ);
187 return GST_FLOW_ERROR;
189 ret = am7xxx_send_image_async(am7xxxsink->dev, am7xxxsink->format,
190 am7xxxsink->width, am7xxxsink->height,
193 ret = GST_FLOW_ERROR;
200 gst_buffer_unmap (buf, &map);
206 gst_am7xxxsink_start (GstBaseSink * bsink)
208 GstAM7XXXSink *am7xxxsink;
211 am7xxxsink = GST_AM7XXXSINK (bsink);
213 ret = am7xxx_init(&am7xxxsink->ctx);
217 ret = am7xxx_open_device(am7xxxsink->ctx, &am7xxxsink->dev, am7xxxsink->device_index);
221 ret = am7xxx_get_device_info(am7xxxsink->dev, &am7xxxsink->device_info);
225 GST_VIDEO_SINK_WIDTH (am7xxxsink) = (am7xxxsink->device_info).native_width;
226 GST_VIDEO_SINK_HEIGHT (am7xxxsink) = (am7xxxsink->device_info).native_height;
232 gst_am7xxxsink_stop (GstBaseSink * bsink)
234 GstAM7XXXSink *am7xxxsink;
236 am7xxxsink = GST_AM7XXXSINK (bsink);
238 /* open devices will be closed by am7xxx_shutdown() */
239 am7xxx_shutdown(am7xxxsink->ctx);
245 gst_am7xxxsink_set_property (GObject * object, guint prop_id,
246 const GValue * value, GParamSpec * pspec)
248 GstAM7XXXSink *am7xxxsink;
250 am7xxxsink = GST_AM7XXXSINK (object);
253 case ARG_DEVICE_INDEX:{
254 am7xxxsink->device_index = g_value_get_uint (value);
258 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
265 gst_am7xxxsink_get_property (GObject * object, guint prop_id, GValue * value,
268 GstAM7XXXSink *am7xxxsink;
270 am7xxxsink = GST_AM7XXXSINK (object);
273 case ARG_DEVICE_INDEX:{
274 g_value_set_uint (value, am7xxxsink->device_index);
278 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
283 static GstStateChangeReturn
284 gst_am7xxxsink_change_state (GstElement * element, GstStateChange transition)
286 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
288 g_return_val_if_fail (GST_IS_AM7XXXSINK (element), GST_STATE_CHANGE_FAILURE);
290 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
292 switch (transition) {
300 plugin_init (GstPlugin * plugin)
302 if (!gst_element_register (plugin, "am7xxxsink", GST_RANK_NONE,
303 GST_TYPE_AM7XXXSINK))
306 GST_DEBUG_CATEGORY_INIT (am7xxxsink_debug, "am7xxxsink", 0,
307 "am7xxx video sink element");
313 gst_am7xxxsink_class_init (GstAM7XXXSinkClass * klass)
315 GObjectClass *gobject_class;
316 GstElementClass *gstelement_class;
317 GstBaseSinkClass *basesink_class;
318 GstVideoSinkClass *videosink_class;
320 gobject_class = (GObjectClass *) klass;
321 gstelement_class = (GstElementClass *) klass;
322 basesink_class = (GstBaseSinkClass *) klass;
323 videosink_class = (GstVideoSinkClass *) klass;
325 gobject_class->set_property = gst_am7xxxsink_set_property;
326 gobject_class->get_property = gst_am7xxxsink_get_property;
327 gobject_class->finalize = gst_am7xxxsink_finalize;
329 gstelement_class->change_state =
330 GST_DEBUG_FUNCPTR (gst_am7xxxsink_change_state);
332 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE_INDEX,
333 g_param_spec_uint ("device-index", "device index",
334 "The am7xxx device index eg: 0", 0, G_MAXUINT, 0, G_PARAM_READWRITE));
336 basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_am7xxxsink_setcaps);
337 basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_am7xxxsink_getcaps);
339 basesink_class->get_times = GST_DEBUG_FUNCPTR (gst_am7xxxsink_get_times);
341 basesink_class->start = GST_DEBUG_FUNCPTR (gst_am7xxxsink_start);
342 basesink_class->stop = GST_DEBUG_FUNCPTR (gst_am7xxxsink_stop);
344 videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_am7xxxsink_show_frame);
346 gst_element_class_set_static_metadata (gstelement_class, "am7xxx video sink",
347 "Sink/Video", "A videosink for projectors supported by libam7xxx",
348 "Antonio Ospite <ospite@studenti.unina.it>");
350 gst_element_class_add_pad_template (gstelement_class,
351 gst_static_pad_template_get (&sink_template));
355 gst_am7xxxsink_finalize (GObject * object)
357 G_OBJECT_CLASS (parent_class)->finalize (object);
360 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
363 "libam7xxx video sink",
364 plugin_init, VERSION, "LGPL", "gst-am7xxxsink", "http://ao2.it")