hack fix for Ogg sequence headers being wrong
[schroedinger/research-port.git] / gst / gstlogoinsert.c
blobe5a274d855ed47112e0c74e1d4c71b7f7a5be00e
1 /* GStreamer
2 * Copyright (C) 2008 David Schleef <ds@entropywave.com>
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #define SCHRO_ENABLE_UNSTABLE_API
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include <gst/gst.h>
27 #include <gst/base/gstbasetransform.h>
28 #include <gst/video/video.h>
29 #include <string.h>
30 #include <schroedinger/schro.h>
31 #include <schroedinger/schrovirtframe.h>
32 #include <liboil/liboil.h>
33 #include <math.h>
34 #include <libpng/png.h>
35 #include "gstschroutils.h"
37 #define GST_TYPE_LOGOINSERT \
38 (gst_logoinsert_get_type())
39 #define GST_LOGOINSERT(obj) \
40 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_LOGOINSERT,GstLogoinsert))
41 #define GST_LOGOINSERT_CLASS(klass) \
42 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_LOGOINSERT,GstLogoinsertClass))
43 #define GST_IS_LOGOINSERT(obj) \
44 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_LOGOINSERT))
45 #define GST_IS_LOGOINSERT_CLASS(obj) \
46 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_LOGOINSERT))
48 typedef struct _GstLogoinsert GstLogoinsert;
49 typedef struct _GstLogoinsertClass GstLogoinsertClass;
51 struct _GstLogoinsert
53 GstBaseTransform base_transform;
55 gchar *location;
57 GstVideoFormat format;
58 int width;
59 int height;
61 gchar *data;
62 gsize size;
63 SchroFrame *overlay_frame;
64 SchroFrame *ayuv_frame;
65 SchroFrame *alpha_frame;
69 struct _GstLogoinsertClass
71 GstBaseTransformClass parent_class;
76 /* GstLogoinsert signals and args */
77 enum
79 /* FILL ME */
80 LAST_SIGNAL
83 enum
85 ARG_0,
86 ARG_LOCATION,
89 GType gst_logoinsert_get_type (void);
91 static void gst_logoinsert_base_init (gpointer g_class);
92 static void gst_logoinsert_class_init (gpointer g_class,
93 gpointer class_data);
94 static void gst_logoinsert_init (GTypeInstance * instance, gpointer g_class);
96 static void gst_logoinsert_set_property (GObject * object, guint prop_id,
97 const GValue * value, GParamSpec * pspec);
98 static void gst_logoinsert_get_property (GObject * object, guint prop_id,
99 GValue * value, GParamSpec * pspec);
101 static void gst_logoinsert_set_location (GstLogoinsert *li, const gchar *location);
103 static gboolean gst_logoinsert_set_caps (GstBaseTransform *base_transform,
104 GstCaps *incaps, GstCaps *outcaps);
105 static GstFlowReturn gst_logoinsert_transform_ip (GstBaseTransform * base_transform,
106 GstBuffer *buf);
107 static SchroFrame * schro_frame_new_from_png (void *data, int size);
108 static SchroFrame * schro_virt_frame_extract_alpha_take (SchroFrame *frame);
109 static SchroFrame * schro_frame_realize (SchroFrame *frame);
111 static GstStaticPadTemplate gst_logoinsert_sink_template =
112 GST_STATIC_PAD_TEMPLATE ("sink",
113 GST_PAD_SINK,
114 GST_PAD_ALWAYS,
115 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
118 static GstStaticPadTemplate gst_logoinsert_src_template =
119 GST_STATIC_PAD_TEMPLATE ("src",
120 GST_PAD_SRC,
121 GST_PAD_ALWAYS,
122 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{I420,YUY2,UYVY,AYUV}"))
125 GType
126 gst_logoinsert_get_type (void)
128 static GType compress_type = 0;
130 if (!compress_type) {
131 static const GTypeInfo compress_info = {
132 sizeof (GstLogoinsertClass),
133 gst_logoinsert_base_init,
134 NULL,
135 gst_logoinsert_class_init,
136 NULL,
137 NULL,
138 sizeof (GstLogoinsert),
140 gst_logoinsert_init,
143 compress_type = g_type_register_static (GST_TYPE_BASE_TRANSFORM,
144 "GstLogoinsert", &compress_info, 0);
146 return compress_type;
150 static void
151 gst_logoinsert_base_init (gpointer g_class)
153 static GstElementDetails compress_details =
154 GST_ELEMENT_DETAILS ("Video Filter Template",
155 "Filter/Effect/Video",
156 "Template for a video filter",
157 "David Schleef <ds@schleef.org>");
158 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
159 //GstBaseTransformClass *base_transform_class = GST_BASE_TRANSFORM_CLASS (g_class);
161 gst_element_class_add_pad_template (element_class,
162 gst_static_pad_template_get (&gst_logoinsert_src_template));
163 gst_element_class_add_pad_template (element_class,
164 gst_static_pad_template_get (&gst_logoinsert_sink_template));
166 gst_element_class_set_details (element_class, &compress_details);
169 static void
170 gst_logoinsert_class_init (gpointer g_class, gpointer class_data)
172 GObjectClass *gobject_class;
173 GstBaseTransformClass *base_transform_class;
174 GstLogoinsertClass *filter_class;
176 gobject_class = G_OBJECT_CLASS (g_class);
177 base_transform_class = GST_BASE_TRANSFORM_CLASS (g_class);
178 filter_class = GST_LOGOINSERT_CLASS (g_class);
180 gobject_class->set_property = gst_logoinsert_set_property;
181 gobject_class->get_property = gst_logoinsert_get_property;
183 g_object_class_install_property (gobject_class, ARG_LOCATION,
184 g_param_spec_string ("location", "location",
185 "location of PNG file to overlay",
186 "", G_PARAM_READWRITE));
188 base_transform_class->set_caps = gst_logoinsert_set_caps;
189 base_transform_class->transform_ip = gst_logoinsert_transform_ip;
192 static void
193 gst_logoinsert_init (GTypeInstance * instance, gpointer g_class)
195 //GstLogoinsert *compress = GST_LOGOINSERT (instance);
196 //GstBaseTransform *btrans = GST_BASE_TRANSFORM (instance);
198 GST_DEBUG ("gst_logoinsert_init");
201 static void
202 gst_logoinsert_set_property (GObject * object, guint prop_id,
203 const GValue * value, GParamSpec * pspec)
205 GstLogoinsert *src;
207 g_return_if_fail (GST_IS_LOGOINSERT (object));
208 src = GST_LOGOINSERT (object);
210 GST_DEBUG ("gst_logoinsert_set_property");
211 switch (prop_id) {
212 case ARG_LOCATION:
213 gst_logoinsert_set_location (src, g_value_get_string (value));
214 break;
215 default:
216 break;
220 static void
221 gst_logoinsert_get_property (GObject * object, guint prop_id, GValue * value,
222 GParamSpec * pspec)
224 GstLogoinsert *src;
226 g_return_if_fail (GST_IS_LOGOINSERT (object));
227 src = GST_LOGOINSERT (object);
229 switch (prop_id) {
230 case ARG_LOCATION:
231 g_value_set_string (value, src->location);
232 break;
233 default:
234 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
235 break;
239 static gboolean
240 gst_logoinsert_set_caps (GstBaseTransform *base_transform,
241 GstCaps *incaps, GstCaps *outcaps)
243 GstLogoinsert *li;
245 g_return_val_if_fail (GST_IS_LOGOINSERT (base_transform), GST_FLOW_ERROR);
246 li = GST_LOGOINSERT (base_transform);
248 gst_video_format_parse_caps (incaps, &li->format, &li->width,
249 &li->height);
251 return TRUE;
254 static GstFlowReturn
255 gst_logoinsert_transform_ip (GstBaseTransform * base_transform,
256 GstBuffer *buf)
258 GstLogoinsert *li;
259 SchroFrame *frame;
261 g_return_val_if_fail (GST_IS_LOGOINSERT (base_transform), GST_FLOW_ERROR);
262 li = GST_LOGOINSERT (base_transform);
264 frame = gst_schro_buffer_wrap (buf, li->format, li->width, li->height);
266 if (li->ayuv_frame == NULL) return GST_FLOW_OK;
268 if (li->overlay_frame == NULL) {
269 SchroFrame *f;
271 f = schro_virt_frame_extract_alpha_take (
272 schro_frame_ref (li->ayuv_frame));
273 f = schro_virt_frame_new_subsample_take (f, frame->format);
274 li->alpha_frame = schro_frame_realize (f);
276 f = schro_virt_frame_new_unpack_take (schro_frame_ref (li->ayuv_frame));
277 f = schro_virt_frame_new_color_matrix_take (f);
278 f = schro_virt_frame_new_subsample_take (f, frame->format);
279 li->overlay_frame = schro_frame_realize (f);
282 if (1) {
283 int i,j;
284 int k;
285 guint8 *dest;
286 guint8 *src;
287 guint8 *alpha;
288 int offset_x, offset_y;
290 for(k=0;k<3;k++){
291 offset_x = frame->components[k].width -
292 li->alpha_frame->components[k].width;
293 offset_y = frame->components[k].height -
294 li->alpha_frame->components[k].height;
296 for(j=0;j<li->overlay_frame->components[k].height;j++){
297 dest = SCHRO_FRAME_DATA_GET_LINE (frame->components + k, j + offset_y);
298 src = SCHRO_FRAME_DATA_GET_LINE (li->overlay_frame->components + k, j);
299 alpha = SCHRO_FRAME_DATA_GET_LINE (li->alpha_frame->components + k, j);
301 #define oil_divide_255(x) ((((x)+128) + (((x)+128)>>8))>>8)
303 for(i=0;i<li->overlay_frame->components[k].width;i++){
304 dest[i+offset_x] = oil_divide_255 (src[i]*alpha[i] + dest[i+offset_x]*(255-alpha[i]));
311 return GST_FLOW_OK;
314 static void
315 gst_logoinsert_set_location (GstLogoinsert *li, const gchar *location)
317 gboolean ret;
318 GError *error = NULL;
320 g_free (li->location);
321 g_free (li->data);
322 if (li->overlay_frame) {
323 schro_frame_unref (li->overlay_frame);
324 li->overlay_frame = NULL;
327 li->location = g_strdup (location);
329 ret = g_file_get_contents (li->location, &li->data, &li->size, &error);
330 if (!ret) {
331 li->data = NULL;
332 li->size = 0;
333 return;
336 li->ayuv_frame = schro_frame_new_from_png (li->data, li->size);
338 if (li->alpha_frame) {
339 schro_frame_unref (li->alpha_frame);
340 li->alpha_frame = NULL;
342 if (li->overlay_frame) {
343 schro_frame_unref (li->overlay_frame);
344 li->overlay_frame = NULL;
349 /* load PNG into SchroFrame */
351 struct png_data_struct {
352 unsigned char *data;
353 int size;
354 int offset;
357 static void
358 read_data(png_structp png_ptr, png_bytep data, png_size_t length)
360 struct png_data_struct *s = png_ptr->io_ptr;
362 memcpy (data, s->data + s->offset, length);
363 s->offset += length;
366 static SchroFrame *
367 schro_frame_new_from_png (void *data, int size)
369 struct png_data_struct s = { 0 };
370 png_structp png_ptr;
371 png_infop info_ptr;
372 png_bytep *rows;
373 SchroFrame *frame;
374 guchar *frame_data;
375 int rowbytes;
376 int j;
377 int width, height;
378 int color_type;
380 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
381 NULL, NULL, NULL);
382 info_ptr = png_create_info_struct(png_ptr);
384 s.data = data;
385 s.size = size;
386 png_set_read_fn(png_ptr, (void *)&s, read_data);
388 png_read_info (png_ptr, info_ptr);
390 width = png_get_image_width (png_ptr, info_ptr);
391 height = png_get_image_height (png_ptr, info_ptr);
392 color_type = png_get_color_type (png_ptr, info_ptr);
393 GST_DEBUG("PNG size %dx%d color_type %d", width, height, color_type);
395 png_set_strip_16 (png_ptr);
396 png_set_packing (png_ptr);
397 if (color_type == PNG_COLOR_TYPE_RGB) {
398 png_set_filler (png_ptr, 0xff, PNG_FILLER_BEFORE);
400 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
401 png_set_swap_alpha(png_ptr);
404 frame_data = g_malloc (width * height * 4);
405 frame = schro_frame_new_from_data_AYUV (frame_data, width, height);
407 rowbytes = png_get_rowbytes (png_ptr, info_ptr);
408 rows = (png_bytep *) g_malloc (sizeof (png_bytep) * height);
410 for (j = 0; j < height; j++) {
411 rows[j] = SCHRO_FRAME_DATA_GET_LINE (frame->components+0, j);
413 png_read_image (png_ptr, rows);
414 g_free (rows);
416 // PNG_TRANSFORM_STRP_16 | PNG_TRANSFORM_PACKING,
418 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
421 return frame;
424 static void
425 extract_alpha (SchroFrame *frame, void *_dest, int component, int j)
427 uint8_t *dest = _dest;
428 uint8_t *src;
429 int i;
431 src = SCHRO_FRAME_DATA_GET_LINE (frame->virt_frame1->components + 0, j);
432 for(i=0;i<frame->width;i++){
433 dest[i] = src[i*4 + 0];
437 static SchroFrame *
438 schro_virt_frame_extract_alpha_take (SchroFrame *frame)
440 SchroFrame *virt_frame;
442 /* FIXME check that frame is a real AYUV frame */
444 virt_frame = schro_frame_new_virtual (NULL, SCHRO_FRAME_FORMAT_U8_444,
445 frame->width, frame->height);
446 virt_frame->virt_frame1 = frame;
447 virt_frame->render_line = extract_alpha;
449 return virt_frame;
452 static SchroFrame *
453 schro_frame_realize (SchroFrame *frame)
455 SchroFrame *dest;
457 dest = schro_frame_clone (NULL, frame);
458 schro_virt_frame_render (frame, dest);
459 schro_frame_unref (frame);
461 return dest;