]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugins-ugly0-10.git/blob - ext/dvdread/dvdreadsrc.c
ext/dvdread/dvdreadsrc.c: Make titles > 0 work again (fixes #154834).
[glsdk/gst-plugins-ugly0-10.git] / ext / dvdread / dvdreadsrc.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
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.
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 GNU
12  * Library General Public License for more details.
13  *
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.
18  */
20 /**
21  * Copyright (C) 2001 Billy Biggs <vektor@dumbterm.net>.
22  *
23  * This program is free software; you can redistribute it and/or modify
24  * it under the terms of the GNU General Public License as published by
25  * the Free Software Foundation; either version 2 of the License, or (at
26  * your option) any later version.
27  *
28  * This program is distributed in the hope that it will be useful, but
29  * WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31  * General Public License for more details.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program; if not, write to the Free Software
35  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36  */
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <time.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 #include <sys/ioctl.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include <dirent.h>
53 #include <errno.h>
54 //#include <linux/cdrom.h>
55 #include <assert.h>
57 #include <dvdreadsrc.h>
59 #include <dvdread/dvd_reader.h>
60 #include <dvdread/ifo_types.h>
61 #include <dvdread/ifo_read.h>
62 #include <dvdread/nav_read.h>
63 #include <dvdread/nav_print.h>
65 struct _DVDReadSrcPrivate
66 {
67   /* pads */
68   GstPad *srcpad;
70   /* location */
71   gchar *location;
73   gboolean new_seek;
75   gboolean new_cell;
77   int title, chapter, angle;
78   int pgc_id, start_cell, cur_cell, cur_pack;
79   int ttn, pgn, next_cell;
80   dvd_reader_t *dvd;
81   dvd_file_t *dvd_title;
82   ifo_handle_t *vmg_file;
83   tt_srpt_t *tt_srpt;
84   ifo_handle_t *vts_file;
85   vts_ptt_srpt_t *vts_ptt_srpt;
86   pgc_t *cur_pgc;
87 };
89 GST_DEBUG_CATEGORY_STATIC (gstdvdreadsrc_debug);
90 #define GST_CAT_DEFAULT (gstdvdreadsrc_debug)
92 GstElementDetails dvdreadsrc_details = {
93   "DVD Source",
94   "Source/File/DVD",
95   "Access a DVD title/chapter/angle using libdvdread",
96   "Erik Walthinsen <omega@cse.ogi.edu>",
97 };
100 /* DVDReadSrc signals and args */
101 enum
103   /* FILL ME */
104   LAST_SIGNAL
105 };
107 enum
109   ARG_0,
110   ARG_LOCATION,
111   ARG_TITLE,
112   ARG_CHAPTER,
113   ARG_ANGLE
114 };
116 static void dvdreadsrc_base_init (gpointer g_class);
117 static void dvdreadsrc_class_init (DVDReadSrcClass * klass);
118 static void dvdreadsrc_init (DVDReadSrc * dvdreadsrc);
119 static void dvdreadsrc_dispose (GObject * object);
121 static void dvdreadsrc_set_property (GObject * object, guint prop_id,
122     const GValue * value, GParamSpec * pspec);
123 static void dvdreadsrc_get_property (GObject * object, guint prop_id,
124     GValue * value, GParamSpec * pspec);
126 static GstData *dvdreadsrc_get (GstPad * pad);
128 /*static GstBuffer *    dvdreadsrc_get_region   (GstPad *pad,gulong offset,gulong size); */
130 static GstElementStateReturn dvdreadsrc_change_state (GstElement * element);
133 static GstElementClass *parent_class = NULL;
135 /*static guint dvdreadsrc_signals[LAST_SIGNAL] = { 0 }; */
137 GType
138 dvdreadsrc_get_type (void)
140   static GType dvdreadsrc_type = 0;
142   if (!dvdreadsrc_type) {
143     static const GTypeInfo dvdreadsrc_info = {
144       sizeof (DVDReadSrcClass),
145       dvdreadsrc_base_init,
146       NULL,
147       (GClassInitFunc) dvdreadsrc_class_init,
148       NULL,
149       NULL,
150       sizeof (DVDReadSrc),
151       0,
152       (GInstanceInitFunc) dvdreadsrc_init,
153     };
155     dvdreadsrc_type =
156         g_type_register_static (GST_TYPE_ELEMENT, "DVDReadSrc",
157         &dvdreadsrc_info, 0);
158   }
159   return dvdreadsrc_type;
162 static void
163 dvdreadsrc_base_init (gpointer g_class)
165   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
167   gst_element_class_set_details (element_class, &dvdreadsrc_details);
170 static void
171 dvdreadsrc_class_init (DVDReadSrcClass * klass)
173   GObjectClass *gobject_class;
174   GstElementClass *gstelement_class;
176   gobject_class = (GObjectClass *) klass;
177   gstelement_class = (GstElementClass *) klass;
179   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
181   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
182       g_param_spec_string ("location", "location", "location",
183           NULL, G_PARAM_READWRITE));
184   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TITLE,
185       g_param_spec_int ("title", "title", "title",
186           0, G_MAXINT, 0, G_PARAM_READWRITE));
187   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CHAPTER,
188       g_param_spec_int ("chapter", "chapter", "chapter",
189           0, G_MAXINT, 0, G_PARAM_READWRITE));
190   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ANGLE,
191       g_param_spec_int ("angle", "angle", "angle",
192           0, G_MAXINT, 0, G_PARAM_READWRITE));
194   gobject_class->set_property = GST_DEBUG_FUNCPTR (dvdreadsrc_set_property);
195   gobject_class->get_property = GST_DEBUG_FUNCPTR (dvdreadsrc_get_property);
197   gobject_class->dispose = dvdreadsrc_dispose;
199   gstelement_class->change_state = dvdreadsrc_change_state;
201   GST_DEBUG_CATEGORY_INIT (gstdvdreadsrc_debug, "dvdreadsrc", 0,
202       "DVD reader element based on dvdreadsrc");
205 static void
206 dvdreadsrc_init (DVDReadSrc * dvdreadsrc)
208   dvdreadsrc->priv = g_new (DVDReadSrcPrivate, 1);
209   dvdreadsrc->priv->srcpad = gst_pad_new ("src", GST_PAD_SRC);
210   gst_pad_set_get_function (dvdreadsrc->priv->srcpad, dvdreadsrc_get);
211   gst_element_add_pad (GST_ELEMENT (dvdreadsrc), dvdreadsrc->priv->srcpad);
213   dvdreadsrc->priv->location = g_strdup ("/dev/dvd");
214   dvdreadsrc->priv->new_seek = TRUE;
215   dvdreadsrc->priv->new_cell = TRUE;
216   dvdreadsrc->priv->title = 0;
217   dvdreadsrc->priv->chapter = 0;
218   dvdreadsrc->priv->angle = 0;
221 static void
222 dvdreadsrc_dispose (GObject * object)
224   DVDReadSrc *dvdreadsrc = DVDREADSRC (object);
226   if (dvdreadsrc->priv) {
227     g_free (dvdreadsrc->priv->location);
228     g_free (dvdreadsrc->priv);
229     dvdreadsrc->priv = NULL;
230   }
233 static void
234 dvdreadsrc_set_property (GObject * object, guint prop_id, const GValue * value,
235     GParamSpec * pspec)
237   DVDReadSrc *src;
238   DVDReadSrcPrivate *priv;
240   /* it's not null if we got it, but it might not be ours */
241   g_return_if_fail (GST_IS_DVDREADSRC (object));
243   src = DVDREADSRC (object);
244   priv = src->priv;
246   switch (prop_id) {
247     case ARG_LOCATION:
248       /* the element must be stopped in order to do this */
249       /*g_return_if_fail(!GST_FLAG_IS_SET(src,GST_STATE_RUNNING)); */
251       if (priv->location)
252         g_free (priv->location);
253       /* clear the filename if we get a NULL (is that possible?) */
254       if (g_value_get_string (value) == NULL)
255         priv->location = g_strdup ("/dev/dvd");
256       /* otherwise set the new filename */
257       else
258         priv->location = g_strdup (g_value_get_string (value));
259       break;
260     case ARG_TITLE:
261       priv->title = g_value_get_int (value);
262       priv->new_seek = TRUE;
263       break;
264     case ARG_CHAPTER:
265       priv->chapter = g_value_get_int (value);
266       priv->new_seek = TRUE;
267       break;
268     case ARG_ANGLE:
269       priv->angle = g_value_get_int (value);
270       break;
271     default:
272       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
273       break;
274   }
278 static void
279 dvdreadsrc_get_property (GObject * object, guint prop_id, GValue * value,
280     GParamSpec * pspec)
282   DVDReadSrc *src;
283   DVDReadSrcPrivate *priv;
285   /* it's not null if we got it, but it might not be ours */
286   g_return_if_fail (GST_IS_DVDREADSRC (object));
288   src = DVDREADSRC (object);
289   priv = src->priv;
291   switch (prop_id) {
292     case ARG_LOCATION:
293       g_value_set_string (value, priv->location);
294       break;
295     case ARG_TITLE:
296       g_value_set_int (value, priv->title);
297       break;
298     case ARG_CHAPTER:
299       g_value_set_int (value, priv->chapter);
300       break;
301     case ARG_ANGLE:
302       g_value_set_int (value, priv->angle);
303       break;
304     default:
305       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
306       break;
307   }
310 /**
311  * Returns true if the pack is a NAV pack.  This check is clearly insufficient,
312  * and sometimes we incorrectly think that valid other packs are NAV packs.  I
313  * need to make this stronger.
314  */
315 static int
316 is_nav_pack (unsigned char *buffer)
318   return (buffer[41] == 0xbf && buffer[1027] == 0xbf);
321 static int
322 _open (DVDReadSrcPrivate * priv, const gchar * location)
324   g_return_val_if_fail (priv != NULL, -1);
325   g_return_val_if_fail (location != NULL, -1);
327   /**
328    * Open the disc.
329    */
330   priv->dvd = DVDOpen (location);
331   if (!priv->dvd) {
332     GST_ERROR ("Couldn't open DVD: %s", location);
333     return -1;
334   }
337   /**
338    * Load the video manager to find out the information about the titles on
339    * this disc.
340    */
341   priv->vmg_file = ifoOpen (priv->dvd, 0);
342   if (!priv->vmg_file) {
343     GST_ERROR ("Can't open VMG info");
344     DVDClose (priv->dvd);
345     return -1;
346   }
347   priv->tt_srpt = priv->vmg_file->tt_srpt;
349   return 0;
352 static int
353 _close (DVDReadSrcPrivate * priv)
355   ifoClose (priv->vts_file);
356   ifoClose (priv->vmg_file);
357   DVDCloseFile (priv->dvd_title);
358   DVDClose (priv->dvd);
359   return 0;
362 static int
363 _seek (DVDReadSrcPrivate * priv, int title, int chapter, int angle)
365     /**
366      * Make sure our title number is valid.
367      */
368   GST_LOG ("There are %d titles on this DVD", priv->tt_srpt->nr_of_srpts);
369   if (title < 0 || title >= priv->tt_srpt->nr_of_srpts) {
370     GST_ERROR ("Invalid title %d (only %d available)",
371         title, priv->tt_srpt->nr_of_srpts);
372     ifoClose (priv->vmg_file);
373     DVDClose (priv->dvd);
374     return -1;
375   }
378     /**
379      * Make sure the chapter number is valid for this title.
380      */
381   GST_LOG ("There are %d chapters in this title",
382       priv->tt_srpt->title[title].nr_of_ptts);
384   if (chapter < 0 || chapter >= priv->tt_srpt->title[title].nr_of_ptts) {
385     GST_ERROR ("Invalid chapter %d (only %d available)",
386         chapter, priv->tt_srpt->title[title].nr_of_ptts);
387     ifoClose (priv->vmg_file);
388     DVDClose (priv->dvd);
389     return -1;
390   }
393     /**
394      * Make sure the angle number is valid for this title.
395      */
396   GST_LOG ("There are %d angles available in this title",
397       priv->tt_srpt->title[title].nr_of_angles);
398   if (angle < 0 || angle >= priv->tt_srpt->title[title].nr_of_angles) {
399     GST_ERROR ("Invalid angle %d (only %d available)",
400         angle, priv->tt_srpt->title[title].nr_of_angles);
401     ifoClose (priv->vmg_file);
402     DVDClose (priv->dvd);
403     return -1;
404   }
407     /**
408      * Load the VTS information for the title set our title is in.
409      */
410   priv->vts_file =
411       ifoOpen (priv->dvd, priv->tt_srpt->title[title].title_set_nr);
412   if (!priv->vts_file) {
413     GST_ERROR ("Can't open the info file of title %d",
414         priv->tt_srpt->title[title].title_set_nr);
415     ifoClose (priv->vmg_file);
416     DVDClose (priv->dvd);
417     return -1;
418   }
421     /**
422      * Determine which program chain we want to watch.  This is based on the
423      * chapter number.
424      */
425   priv->ttn = priv->tt_srpt->title[title].vts_ttn;
426   priv->vts_ptt_srpt = priv->vts_file->vts_ptt_srpt;
427   priv->pgc_id = priv->vts_ptt_srpt->title[priv->ttn - 1].ptt[chapter].pgcn;
428   priv->pgn = priv->vts_ptt_srpt->title[priv->ttn - 1].ptt[chapter].pgn;
429   priv->cur_pgc = priv->vts_file->vts_pgcit->pgci_srp[priv->pgc_id - 1].pgc;
430   priv->start_cell = priv->cur_pgc->program_map[priv->pgn - 1] - 1;
432     /**
433      * We've got enough info, time to open the title set data.
434      */
435   priv->dvd_title =
436       DVDOpenFile (priv->dvd, priv->tt_srpt->title[title].title_set_nr,
437       DVD_READ_TITLE_VOBS);
438   if (!priv->dvd_title) {
439     GST_ERROR ("Can't open title VOBS (VTS_%02d_1.VOB)",
440         priv->tt_srpt->title[title].title_set_nr);
441     ifoClose (priv->vts_file);
442     ifoClose (priv->vmg_file);
443     DVDClose (priv->dvd);
444     return -1;
445   }
447   return 0;
450 /*
451  * Read function.
452  * -1: error, -2: eos, -3: try again, 0: ok.
453  */
455 static int
456 _read (DVDReadSrcPrivate * priv, int angle, int new_seek, GstBuffer * buf)
458   unsigned char *data;
460   data = GST_BUFFER_DATA (buf);
462     /**
463      * Playback by cell in this pgc, starting at the cell for our chapter.
464      */
465   if (new_seek) {
466     priv->next_cell = priv->start_cell;
467     priv->cur_cell = priv->start_cell;
468   }
470   if (priv->cur_cell < priv->cur_pgc->nr_of_cells) {
471     if (priv->new_cell)
472       priv->cur_cell = priv->next_cell;
474     /* Check if we're entering an angle block. */
475     if (priv->cur_pgc->cell_playback[priv->cur_cell].block_type
476         == BLOCK_TYPE_ANGLE_BLOCK) {
477       int i;
479       priv->cur_cell += angle;
480       for (i = 0;; ++i) {
481         if (priv->cur_pgc->cell_playback[priv->cur_cell + i].block_mode
482             == BLOCK_MODE_LAST_CELL) {
483           priv->next_cell = priv->cur_cell + i + 1;
484           break;
485         }
486       }
487     } else {
488       priv->next_cell = priv->cur_cell + 1;
489     }
492         /**
493          * We loop until we're out of this cell.
494          */
495     if (priv->new_cell) {
496       priv->cur_pack =
497           priv->cur_pgc->cell_playback[priv->cur_cell].first_sector;
498       priv->new_cell = FALSE;
499     }
501     if (priv->cur_pack <
502         priv->cur_pgc->cell_playback[priv->cur_cell].last_sector) {
503       dsi_t dsi_pack;
504       unsigned int next_vobu, next_ilvu_start, cur_output_size;
505       int len;
507             /**
508              * Read NAV packet.
509              */
510       len = DVDReadBlocks (priv->dvd_title, priv->cur_pack, 1, data);
511       if (len == 0) {
512         GST_ERROR ("Read failed for block %d", priv->cur_pack);
513         return -1;
514       }
515       assert (is_nav_pack (data));
518             /**
519              * Parse the contained dsi packet.
520              */
521       navRead_DSI (&dsi_pack, &(data[DSI_START_BYTE]));
522       assert (priv->cur_pack == dsi_pack.dsi_gi.nv_pck_lbn);
525             /**
526              * Determine where we go next.  These values are the ones we mostly
527              * care about.
528              */
529       next_ilvu_start = priv->cur_pack + dsi_pack.sml_agli.data[angle].address;
530       cur_output_size = dsi_pack.dsi_gi.vobu_ea;
533             /**
534              * If we're not at the end of this cell, we can determine the next
535              * VOBU to display using the VOBU_SRI information section of the
536              * DSI.  Using this value correctly follows the current angle,
537              * avoiding the doubled scenes in The Matrix, and makes our life
538              * really happy.
539              *
540              * Otherwise, we set our next address past the end of this cell to
541              * force the code above to go to the next cell in the program.
542              */
543       if (dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL) {
544         next_vobu = priv->cur_pack + (dsi_pack.vobu_sri.next_vobu & 0x7fffffff);
545       } else {
546         next_vobu = priv->cur_pack + cur_output_size + 1;
547       }
549       assert (cur_output_size < 1024);
550       priv->cur_pack++;
552             /**
553              * Read in and output cursize packs.
554              */
555       len =
556           DVDReadBlocks (priv->dvd_title, priv->cur_pack, cur_output_size,
557           data);
558       if (len != cur_output_size) {
559         GST_ERROR ("Read failed for %d blocks at %d",
560             cur_output_size, priv->cur_pack);
561         return -1;
562       }
564       GST_BUFFER_SIZE (buf) = cur_output_size * DVD_VIDEO_LB_LEN;
565       priv->cur_pack = next_vobu;
567       return 0;
568     } else {
569       priv->new_cell = TRUE;
570     }
571   } else {
572     return -2;
573   }
575   /* again */
576   return -3;
579 static GstData *
580 dvdreadsrc_get (GstPad * pad)
582   gint res;
583   DVDReadSrc *dvdreadsrc;
584   DVDReadSrcPrivate *priv;
585   GstBuffer *buf;
587   g_return_val_if_fail (pad != NULL, NULL);
588   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
590   dvdreadsrc = DVDREADSRC (gst_pad_get_parent (pad));
591   priv = dvdreadsrc->priv;
592   g_return_val_if_fail (GST_FLAG_IS_SET (dvdreadsrc, DVDREADSRC_OPEN), NULL);
594   /* create the buffer */
595   /* FIXME: should eventually use a bufferpool for this */
596   buf = gst_buffer_new_and_alloc (1024 * DVD_VIDEO_LB_LEN);
598   if (priv->new_seek) {
599     _seek (priv, priv->title, priv->chapter, priv->angle);
600   }
602   /* read it in from the file */
603   while ((res = _read (priv, priv->angle, priv->new_seek, buf)) == -3);
604   switch (res) {
605     case -1:
606       GST_ELEMENT_ERROR (dvdreadsrc, RESOURCE, READ, (NULL), (NULL));
607       gst_buffer_unref (buf);
608       return NULL;
609     case -2:
610       gst_element_set_eos (GST_ELEMENT (dvdreadsrc));
611       gst_buffer_unref (buf);
612       return GST_DATA (gst_event_new (GST_EVENT_EOS));
613     case 0:
614       break;
615     default:
616       g_assert_not_reached ();
617   }
619   priv->new_seek = FALSE;
621   return GST_DATA (buf);
624 /* open the file, necessary to go to RUNNING state */
625 static gboolean
626 dvdreadsrc_open_file (DVDReadSrc * src)
628   g_return_val_if_fail (src != NULL, FALSE);
629   g_return_val_if_fail (GST_IS_DVDREADSRC (src), FALSE);
630   g_return_val_if_fail (!GST_FLAG_IS_SET (src, DVDREADSRC_OPEN), FALSE);
632   if (_open (src->priv, src->priv->location)) {
633     GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), (NULL));
634     return FALSE;
635   }
636   if (_seek (src->priv, src->priv->title, src->priv->chapter, src->priv->angle)) {
637     GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL), (NULL));
638     return FALSE;
639   }
641   GST_FLAG_SET (src, DVDREADSRC_OPEN);
643   return TRUE;
646 /* close the file */
647 static void
648 dvdreadsrc_close_file (DVDReadSrc * src)
650   g_return_if_fail (GST_FLAG_IS_SET (src, DVDREADSRC_OPEN));
652   _close (src->priv);
654   GST_FLAG_UNSET (src, DVDREADSRC_OPEN);
657 static GstElementStateReturn
658 dvdreadsrc_change_state (GstElement * element)
660   DVDReadSrc *dvdreadsrc = DVDREADSRC (element);
662   g_return_val_if_fail (GST_IS_DVDREADSRC (element), GST_STATE_FAILURE);
664   GST_DEBUG ("gstdvdreadsrc: state pending %d", GST_STATE_PENDING (element));
666   /* if going down into NULL state, close the file if it's open */
667   switch (GST_STATE_TRANSITION (element)) {
668     case GST_STATE_NULL_TO_READY:
669       if (!dvdreadsrc_open_file (DVDREADSRC (element)))
670         return GST_STATE_FAILURE;
671       break;
672     case GST_STATE_PAUSED_TO_READY:
673       dvdreadsrc->priv->new_cell = TRUE;
674       dvdreadsrc->priv->new_seek = TRUE;
675       dvdreadsrc->priv->chapter = 0;
676       dvdreadsrc->priv->title = 0;
677       break;
678     case GST_STATE_READY_TO_NULL:
679       dvdreadsrc_close_file (DVDREADSRC (element));
680       break;
681     default:
682       break;
683   }
685   /* if we haven't failed already, give the parent class a chance to ;-) */
686   if (GST_ELEMENT_CLASS (parent_class)->change_state)
687     return GST_ELEMENT_CLASS (parent_class)->change_state (element);
689   return GST_STATE_SUCCESS;
692 static gboolean
693 plugin_init (GstPlugin * plugin)
695   if (!gst_element_register (plugin, "dvdreadsrc", GST_RANK_NONE,
696           GST_TYPE_DVDREADSRC))
697     return FALSE;
699   return TRUE;
702 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
703     GST_VERSION_MINOR,
704     "dvdreadsrc",
705     "Access a DVD with dvdread",
706     plugin_init, VERSION, "GPL", GST_PACKAGE, GST_ORIGIN)