gstgdkpixbuf.c 16.3 KB
Newer Older
1
/* GStreamer GdkPixbuf-based image decoder
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * Copyright (C) 1999-2001 Erik Walthinsen <omega@cse.ogi.edu>
 * Copyright (C) 2003 David A. Schleef <ds@schleef.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

21 22 23
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
24
#include <gst/gst.h>
David Schleef's avatar
David Schleef committed
25
#include <gst/video/video.h>
26
#include <gdk-pixbuf/gdk-pixbuf.h>
27 28 29
#include <string.h>

#include "gstgdkpixbuf.h"
30
#include "gstgdkpixbufsink.h"
31

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
32 33 34
GST_DEBUG_CATEGORY_STATIC (gst_gdk_pixbuf_debug);
#define GST_CAT_DEFAULT gst_gdk_pixbuf_debug

35
static const GstElementDetails plugin_details =
Wim Taymans's avatar
Wim Taymans committed
36 37 38 39
GST_ELEMENT_DETAILS ("GdkPixbuf image decoder",
    "Codec/Decoder/Image",
    "Decodes images in a video stream using GdkPixbuf",
    "David A. Schleef <ds@schleef.org>, Renato Filho <renato.filho@indt.org.br>");
40

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
41 42
enum
{
43
  ARG_0,
44
  ARG_SILENT                    /* FIXME 0.11: remove */
45 46
};

David Schleef's avatar
David Schleef committed
47
static GstStaticPadTemplate gst_gdk_pixbuf_sink_template =
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
48 49 50 51
    GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("image/png; "
52
        /* "image/jpeg; " disabled because we can't handle MJPEG */
53 54 55 56 57 58 59 60 61 62 63 64 65 66
        "image/gif; "
        "image/x-icon; "
        "application/x-navi-animation; "
        "image/x-cmu-raster; "
        "image/x-sun-raster; "
        "image/x-pixmap; "
        "image/tiff; "
        "image/x-portable-anymap; "
        "image/x-portable-bitmap; "
        "image/x-portable-graymap; "
        "image/x-portable-pixmap; "
        "image/bmp; "
        "image/x-bmp; "
        "image/x-MS-bmp; "
67 68
        "image/vnd.wap.wbmp; " "image/x-bitmap; " "image/x-tga; "
        "image/x-pcx; image/svg; image/svg+xml")
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
69
    );
70

David Schleef's avatar
David Schleef committed
71
static GstStaticPadTemplate gst_gdk_pixbuf_src_template =
72
    GST_STATIC_PAD_TEMPLATE ("src",
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
73 74
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
75
    GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_RGBA)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
76 77
    );

78 79
gboolean pixbufscale_init (GstPlugin * plugin);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
80 81
static void gst_gdk_pixbuf_base_init (gpointer g_class);
static void gst_gdk_pixbuf_class_init (GstGdkPixbufClass * klass);
82 83
static void gst_gdk_pixbuf_init (GstGdkPixbuf * filter,
    GstGdkPixbufClass * klass);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
84 85 86 87 88 89

static void gst_gdk_pixbuf_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_gdk_pixbuf_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);

90 91
static GstStateChangeReturn
gst_gdk_pixbuf_change_state (GstElement * element, GstStateChange transition);
92
static GstFlowReturn gst_gdk_pixbuf_chain (GstPad * pad, GstBuffer * buffer);
93
static gboolean gst_gdk_pixbuf_sink_event (GstPad * pad, GstEvent * event);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
94

95
#ifdef enable_typefind
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
96
static void gst_gdk_pixbuf_type_find (GstTypeFind * tf, gpointer ignore);
97
#endif
98

99
GST_BOILERPLATE (GstGdkPixbuf, gst_gdk_pixbuf, GstElement, GST_TYPE_ELEMENT);
100

101 102
static gboolean
gst_gdk_pixbuf_sink_setcaps (GstPad * pad, GstCaps * caps)
103 104
{
  GstGdkPixbuf *filter;
105 106
  const GValue *framerate;
  GstStructure *s;
107

108
  filter = GST_GDK_PIXBUF (GST_PAD_PARENT (pad));
109 110 111 112 113 114
  s = gst_caps_get_structure (caps, 0);

  if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
    filter->framerate_numerator = gst_value_get_fraction_numerator (framerate);
    filter->framerate_denominator =
        gst_value_get_fraction_denominator (framerate);
115
    GST_DEBUG_OBJECT (filter, "got framerate of %d/%d fps => packetized mode",
116
        filter->framerate_numerator, filter->framerate_denominator);
117 118 119 120
  } else {
    filter->framerate_numerator = 0;
    filter->framerate_denominator = 1;
    GST_DEBUG_OBJECT (filter, "no framerate, assuming single image");
121
  }
122

123
  return TRUE;
124 125
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
126 127
static GstCaps *
gst_gdk_pixbuf_get_capslist (void)
128 129 130
{
  GSList *slist;
  GSList *slist0;
David Schleef's avatar
David Schleef committed
131
  GstCaps *capslist = NULL;
132
  GstCaps *return_caps = NULL;
133

David Schleef's avatar
David Schleef committed
134
  capslist = gst_caps_new_empty ();
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
135
  slist0 = gdk_pixbuf_get_formats ();
David Schleef's avatar
David Schleef committed
136

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
137
  for (slist = slist0; slist; slist = g_slist_next (slist)) {
138 139 140 141
    GdkPixbufFormat *pixbuf_format;
    char **mimetypes;
    char **mimetype;

David Schleef's avatar
David Schleef committed
142
    pixbuf_format = slist->data;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
143
    mimetypes = gdk_pixbuf_format_get_mime_types (pixbuf_format);
144

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
145 146
    for (mimetype = mimetypes; *mimetype; mimetype++) {
      gst_caps_append_structure (capslist, gst_structure_new (*mimetype, NULL));
David Schleef's avatar
David Schleef committed
147
    }
148
    g_strfreev (mimetypes);
149
  }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
150
  g_slist_free (slist0);
151

152 153 154
  return_caps = gst_caps_intersect (capslist,
      gst_static_caps_get (&gst_gdk_pixbuf_sink_template.static_caps));

155
  gst_caps_unref (capslist);
156
  return return_caps;
157 158
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
159 160
static GstCaps *
gst_gdk_pixbuf_sink_getcaps (GstPad * pad)
161
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
162
  return gst_gdk_pixbuf_get_capslist ();
163 164
}

165 166 167 168 169
static void
gst_gdk_pixbuf_base_init (gpointer g_class)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);

David Schleef's avatar
David Schleef committed
170
  gst_element_class_add_pad_template (element_class,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
171
      gst_static_pad_template_get (&gst_gdk_pixbuf_src_template));
David Schleef's avatar
David Schleef committed
172
  gst_element_class_add_pad_template (element_class,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
173
      gst_static_pad_template_get (&gst_gdk_pixbuf_sink_template));
174 175 176
  gst_element_class_set_details (element_class, &plugin_details);
}

177 178
/* initialize the plugin's class */
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
179
gst_gdk_pixbuf_class_init (GstGdkPixbufClass * klass)
180 181 182 183
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
184 185
  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
186

187 188 189
  gobject_class->set_property = gst_gdk_pixbuf_set_property;
  gobject_class->get_property = gst_gdk_pixbuf_get_property;

190
  g_object_class_install_property (gobject_class, ARG_SILENT,
191 192
      g_param_spec_boolean ("silent", "Silent",
          "Produce verbose output ? (deprecated)", FALSE, G_PARAM_READWRITE));
193 194 195

  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_change_state);
196 197 198
}

static void
199
gst_gdk_pixbuf_init (GstGdkPixbuf * filter, GstGdkPixbufClass * klass)
200
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
201
  filter->sinkpad =
202
      gst_pad_new_from_static_template (&gst_gdk_pixbuf_sink_template, "sink");
203 204 205 206 207 208 209 210
  gst_pad_set_setcaps_function (filter->sinkpad,
      GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_sink_setcaps));
  gst_pad_set_getcaps_function (filter->sinkpad,
      GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_sink_getcaps));
  gst_pad_set_chain_function (filter->sinkpad,
      GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_chain));
  gst_pad_set_event_function (filter->sinkpad,
      GST_DEBUG_FUNCPTR (gst_gdk_pixbuf_sink_event));
211
  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
212

213 214
  filter->srcpad =
      gst_pad_new_from_static_template (&gst_gdk_pixbuf_src_template, "src");
215
  gst_pad_use_fixed_caps (filter->srcpad);
216 217
  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);

218 219
  filter->last_timestamp = GST_CLOCK_TIME_NONE;
  filter->pixbuf_loader = NULL;
220 221
}

222 223
static GstFlowReturn
gst_gdk_pixbuf_flush (GstGdkPixbuf * filter)
224
{
225 226 227 228 229 230 231 232
  GstBuffer *outbuf;
  GdkPixbuf *pixbuf;
  int y;
  guint8 *out_pix;
  guint8 *in_pix;
  int in_rowstride;
  GstFlowReturn ret;
  GstCaps *caps = NULL;
233
  gint n_channels;
234 235

  pixbuf = gdk_pixbuf_loader_get_pixbuf (filter->pixbuf_loader);
236 237
  if (pixbuf == NULL)
    goto no_pixbuf;
238

239 240 241 242 243 244
  if (filter->image_size == 0) {
    filter->width = gdk_pixbuf_get_width (pixbuf);
    filter->height = gdk_pixbuf_get_height (pixbuf);
    filter->rowstride = gdk_pixbuf_get_rowstride (pixbuf);
    filter->image_size = filter->rowstride * filter->height;

245 246 247 248 249 250 251 252 253 254
    n_channels = gdk_pixbuf_get_n_channels (pixbuf);
    switch (n_channels) {
      case 3:
        caps = gst_caps_from_string (GST_VIDEO_CAPS_RGB);
        break;
      case 4:
        caps = gst_caps_from_string (GST_VIDEO_CAPS_RGBA);
        break;
      default:
        goto channels_not_supported;
255
    }
256

257 258 259 260 261 262 263 264 265
    gst_caps_set_simple (caps,
        "width", G_TYPE_INT, filter->width,
        "height", G_TYPE_INT, filter->height,
        "framerate", GST_TYPE_FRACTION, filter->framerate_numerator,
        filter->framerate_denominator, NULL);

    GST_DEBUG ("Set size to %dx%d", filter->width, filter->height);
    gst_pad_set_caps (filter->srcpad, caps);
    gst_caps_unref (caps);
266
  }
267

268 269 270 271
  ret = gst_pad_alloc_buffer_and_set_caps (filter->srcpad,
      GST_BUFFER_OFFSET_NONE,
      filter->image_size, GST_PAD_CAPS (filter->srcpad), &outbuf);

272 273
  if (ret != GST_FLOW_OK)
    goto no_buffer;
274

275 276
  GST_BUFFER_TIMESTAMP (outbuf) = filter->last_timestamp;
  GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
277

278 279 280
  in_pix = gdk_pixbuf_get_pixels (pixbuf);
  in_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
  out_pix = GST_BUFFER_DATA (outbuf);
281

282
  /* FIXME, last line might not have rowstride pixels */
283 284 285 286 287
  for (y = 0; y < filter->height; y++) {
    memcpy (out_pix, in_pix, filter->rowstride);
    in_pix += in_rowstride;
    out_pix += filter->rowstride;
  }
288

289
  GST_DEBUG ("pushing... %d bytes", GST_BUFFER_SIZE (outbuf));
290 291 292 293 294 295
  ret = gst_pad_push (filter->srcpad, outbuf);

  if (ret != GST_FLOW_OK)
    GST_DEBUG_OBJECT (filter, "flow: %s", gst_flow_get_name (ret));

  return ret;
296 297 298 299

  /* ERRORS */
no_pixbuf:
  {
300
    GST_ELEMENT_ERROR (filter, STREAM, DECODE, (NULL), ("error geting pixbuf"));
301 302 303 304
    return GST_FLOW_ERROR;
  }
channels_not_supported:
  {
305
    GST_ELEMENT_ERROR (filter, STREAM, DECODE, (NULL),
306 307 308 309 310 311 312 313
        ("%d channels not supported", n_channels));
    return GST_FLOW_ERROR;
  }
no_buffer:
  {
    GST_DEBUG ("Failed to create outbuffer - %s", gst_flow_get_name (ret));
    return ret;
  }
314
}
315

316
static gboolean
317
gst_gdk_pixbuf_sink_event (GstPad * pad, GstEvent * event)
318 319 320 321
{
  GstFlowReturn res = GST_FLOW_OK;
  gboolean ret = TRUE;
  GstGdkPixbuf *pixbuf;
322

323
  pixbuf = GST_GDK_PIXBUF (gst_pad_get_parent (pad));
324

325 326
  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_EOS:
327 328 329 330 331
      if (pixbuf->pixbuf_loader != NULL) {
        gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL);
        res = gst_gdk_pixbuf_flush (pixbuf);
        g_object_unref (G_OBJECT (pixbuf->pixbuf_loader));
        pixbuf->pixbuf_loader = NULL;
332 333 334 335 336 337 338
        /* as long as we don't have flow returns for event functions we need
         * to post an error here, or the application might never know that
         * things failed */
        if (res != GST_FLOW_OK && res != GST_FLOW_WRONG_STATE) {
          GST_ELEMENT_ERROR (pixbuf, STREAM, FAILED, (NULL),
              ("Flow: %s", gst_flow_get_name (res)));
        }
339
      }
340 341 342 343 344 345 346
      break;
    case GST_EVENT_NEWSEGMENT:
    case GST_EVENT_FLUSH_STOP:
      if (pixbuf->pixbuf_loader != NULL) {
        gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL);
        g_object_unref (G_OBJECT (pixbuf->pixbuf_loader));
        pixbuf->pixbuf_loader = NULL;
347
      }
348 349 350
      break;
    default:
      break;
351 352
  }

353 354 355 356
  if (res == GST_FLOW_OK) {
    ret = gst_pad_event_default (pad, event);
  } else {
    ret = FALSE;
357 358
  }

359 360 361 362 363 364 365 366 367 368 369 370
  gst_object_unref (pixbuf);

  return ret;
}

static GstFlowReturn
gst_gdk_pixbuf_chain (GstPad * pad, GstBuffer * buf)
{
  GstGdkPixbuf *filter;
  GstFlowReturn ret = GST_FLOW_OK;
  GError *error = NULL;
  GstClockTime timestamp;
371 372
  guint8 *data;
  guint size;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
373

374 375 376 377
  filter = GST_GDK_PIXBUF (gst_pad_get_parent (pad));

  timestamp = GST_BUFFER_TIMESTAMP (buf);

378
  if (GST_CLOCK_TIME_IS_VALID (timestamp))
379
    filter->last_timestamp = timestamp;
380

381
  GST_LOG_OBJECT (filter, "buffer with ts: %" GST_TIME_FORMAT,
382 383 384
      GST_TIME_ARGS (timestamp));

  if (filter->pixbuf_loader == NULL)
385 386
    filter->pixbuf_loader = gdk_pixbuf_loader_new ();

387 388
  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);
389

390
  GST_LOG_OBJECT (filter, "Writing buffer size %d", size);
391 392 393
  if (!gdk_pixbuf_loader_write (filter->pixbuf_loader, data, size, &error))
    goto error;

394 395 396 397 398 399 400 401
  /* packetised mode? */
  if (filter->framerate_numerator != 0) {
    gdk_pixbuf_loader_close (filter->pixbuf_loader, NULL);
    ret = gst_gdk_pixbuf_flush (filter);
    g_object_unref (filter->pixbuf_loader);
    filter->pixbuf_loader = NULL;
  }

402
  gst_buffer_unref (buf);
403
  gst_object_unref (filter);
404

405
  return ret;
406 407 408 409

  /* ERRORS */
error:
  {
410 411
    GST_ELEMENT_ERROR (filter, STREAM, DECODE, (NULL),
        ("gdk_pixbuf_loader_write error: %s", error->message));
412
    g_error_free (error);
413
    gst_buffer_unref (buf);
414 415
    gst_object_unref (filter);
    return GST_FLOW_ERROR;
416
  }
417 418 419
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
420 421
gst_gdk_pixbuf_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
422 423 424 425 426
{
  GstGdkPixbuf *filter;

  filter = GST_GDK_PIXBUF (object);

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
427 428
  switch (prop_id) {
    case ARG_SILENT:
429
      /* filter->silent = g_value_get_boolean (value); */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
430 431 432 433
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
434 435 436 437
  }
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
438 439
gst_gdk_pixbuf_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
440 441 442 443 444 445
{
  GstGdkPixbuf *filter;

  filter = GST_GDK_PIXBUF (object);

  switch (prop_id) {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
446
    case ARG_SILENT:
447
      /* g_value_set_boolean (value, filter->silent); */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
448 449 450 451
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
452 453 454
  }
}

455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
static GstStateChangeReturn
gst_gdk_pixbuf_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
  GstGdkPixbuf *dec = GST_GDK_PIXBUF (element);

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      /* default to single image mode, setcaps function might not be called */
      dec->framerate_numerator = 0;
      dec->framerate_denominator = 1;
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      dec->framerate_numerator = 0;
      dec->framerate_denominator = 0;
      break;
    default:
      break;
  }

  return ret;
}

487 488
#define GST_GDK_PIXBUF_TYPE_FIND_SIZE 1024

489
#ifdef enable_typefind
490
static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
491
gst_gdk_pixbuf_type_find (GstTypeFind * tf, gpointer ignore)
492 493 494 495 496 497
{
  guint8 *data;
  GdkPixbufLoader *pixbuf_loader;
  GdkPixbufFormat *format;

  data = gst_type_find_peek (tf, 0, GST_GDK_PIXBUF_TYPE_FIND_SIZE);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
498 499
  if (data == NULL)
    return;
500

501
  GST_DEBUG ("creating new loader");
502

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
503 504
  pixbuf_loader = gdk_pixbuf_loader_new ();

505
  gdk_pixbuf_loader_write (pixbuf_loader, data, GST_GDK_PIXBUF_TYPE_FIND_SIZE,
506
      NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
507

508 509 510
  format = gdk_pixbuf_loader_get_format (pixbuf_loader);

  if (format != NULL) {
511
    GstCaps *caps;
512 513
    gchar **p;
    gchar **mlist = gdk_pixbuf_format_get_mime_types (format);
514

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
515
    for (p = mlist; *p; ++p) {
516 517 518 519 520
      GST_DEBUG ("suggesting mime type %s", *p);
      caps = gst_caps_new_simple (*p, NULL);
      gst_type_find_suggest (tf, GST_TYPE_FIND_MINIMUM, caps);
      gst_caps_free (caps);
    }
521
    g_strfreev (mlist);
522 523
  }

524 525 526 527
  GST_DEBUG ("closing pixbuf loader, hope it doesn't hang ...");
  /* librsvg 2.4.x has a bug where it triggers an endless loop in trying
     to close a gzip that's not an svg; fixed upstream but no good way
     to work around it */
528
  gdk_pixbuf_loader_close (pixbuf_loader, NULL);
529
  GST_DEBUG ("closed pixbuf loader");
530 531
  g_object_unref (G_OBJECT (pixbuf_loader));
}
532
#endif
533

534 535 536 537 538 539
/* entry point to initialize the plug-in
 * initialize the plug-in itself
 * register the element factories and pad templates
 * register the features
 */
static gboolean
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
540
plugin_init (GstPlugin * plugin)
541
{
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
542 543
  GST_DEBUG_CATEGORY_INIT (gst_gdk_pixbuf_debug, "gdkpixbuf", 0,
      "gdk pixbuf loader");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
544

545
  if (!gst_element_register (plugin, "gdkpixbufdec", GST_RANK_MARGINAL,
546
          GST_TYPE_GDK_PIXBUF))
547
    return FALSE;
548

549
#ifdef enable_typefind
550
  gst_type_find_register (plugin, "image/*", GST_RANK_MARGINAL,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
551
      gst_gdk_pixbuf_type_find, NULL, GST_CAPS_ANY, NULL);
552
#endif
553

554 555 556 557
  if (!gst_element_register (plugin, "gdkpixbufsink", GST_RANK_NONE,
          GST_TYPE_GDK_PIXBUF_SINK))
    return FALSE;

558 559 560
  if (!pixbufscale_init (plugin))
    return FALSE;

561 562 563 564
  /* plugin initialisation succeeded */
  return TRUE;
}

565

566 567
/* this is the structure that gst-register looks for
 * so keep the name plugin_desc, or you cannot get your plug-in registered */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
568 569 570
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    "gdkpixbuf",
571
    "GdkPixbuf-based image decoder, scaler and sink",
572
    plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)