android: Make it ready for androgenizer
[platform/upstream/gst-plugins-good.git] / gst / flx / gstflxdec.c
index 3323ca0..627aad1 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+/**
+ * SECTION:element-flxdec
+ *
+ * This element decodes fli/flc/flx-video into raw video
+ */
+/*
+ * http://www.coolutils.com/Formats/FLI
+ * http://woodshole.er.usgs.gov/operations/modeling/flc.html
+ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 GST_DEBUG_CATEGORY_STATIC (flxdec_debug);
 #define GST_CAT_DEFAULT flxdec_debug
 
-/* flx element information */
-static GstElementDetails flxdec_details = {
-  "FLX Decoder",
-  "Codec/Decoder/Audio",
-  "FLX decoder",
-  "Sepp Wijnands <mrrazz@garbage-coderz.net>"
-};
-
-/* Flx signals and args */
-enum
-{
-  /* FILL ME */
-  LAST_SIGNAL
-};
-
-enum
-{
-  ARG_0
-};
-
 /* input */
 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
@@ -69,23 +58,23 @@ static GstStaticPadTemplate src_video_factory = GST_STATIC_PAD_TEMPLATE ("src",
 static void gst_flxdec_class_init (GstFlxDecClass * klass);
 static void gst_flxdec_base_init (GstFlxDecClass * klass);
 static void gst_flxdec_init (GstFlxDec * flxdec);
+static void gst_flxdec_dispose (GstFlxDec * flxdec);
 
-static void gst_flxdec_loop (GstElement * element);
+static GstFlowReturn gst_flxdec_chain (GstPad * pad, GstBuffer * buf);
 
-static GstElementStateReturn gst_flxdec_change_state (GstElement * element);
-
-static void gst_flxdec_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_flxdec_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
+static GstStateChangeReturn gst_flxdec_change_state (GstElement * element,
+    GstStateChange transition);
 
+static gboolean gst_flxdec_src_query_handler (GstPad * pad, GstQuery * query);
+static gboolean gst_flxdec_src_event_handler (GstPad * pad, GstEvent * event);
+static gboolean gst_flxdec_sink_event_handler (GstPad * pad, GstEvent * event);
 
 static void flx_decode_color (GstFlxDec *, guchar *, guchar *, gint);
 static void flx_decode_brun (GstFlxDec *, guchar *, guchar *);
 static void flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
 static void flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
 
-#define rndalign(off) ((off) + ((off) % 2))
+#define rndalign(off) ((off) + ((off) & 1))
 
 static GstElementClass *parent_class = NULL;
 
@@ -118,7 +107,10 @@ gst_flxdec_base_init (GstFlxDecClass * klass)
 {
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 
-  gst_element_class_set_details (gstelement_class, &flxdec_details);
+  gst_element_class_set_details_simple (gstelement_class, "FLX video decoder",
+      "Codec/Decoder/Video",
+      "FLC/FLI/FLX video decoder",
+      "Sepp Wijnands <mrrazz@garbage-coderz.net>, Zeeshan Ali <zeenix@gmail.com>");
   gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&sink_factory));
   gst_element_class_add_pad_template (gstelement_class,
@@ -134,39 +126,108 @@ gst_flxdec_class_init (GstFlxDecClass * klass)
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
 
-  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+  parent_class = g_type_class_peek_parent (klass);
 
-  GST_DEBUG_CATEGORY_INIT (flxdec_debug, "flxdec", 0, "FLX video decoder");
+  gobject_class->dispose = (GObjectFinalizeFunc) gst_flxdec_dispose;
 
-  gobject_class->set_property = gst_flxdec_set_property;
-  gobject_class->get_property = gst_flxdec_get_property;
+  GST_DEBUG_CATEGORY_INIT (flxdec_debug, "flxdec", 0, "FLX video decoder");
 
   gstelement_class->change_state = gst_flxdec_change_state;
 }
 
-
-
 static void
 gst_flxdec_init (GstFlxDec * flxdec)
 {
-  flxdec->sinkpad =
-      gst_pad_new_from_template (gst_static_pad_template_get (&sink_factory),
-      "sink");
+  flxdec->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
   gst_element_add_pad (GST_ELEMENT (flxdec), flxdec->sinkpad);
-  gst_element_set_loop_function (GST_ELEMENT (flxdec), gst_flxdec_loop);
+  gst_pad_set_chain_function (flxdec->sinkpad, gst_flxdec_chain);
+  gst_pad_set_event_function (flxdec->sinkpad, gst_flxdec_sink_event_handler);
 
-  flxdec->srcpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&src_video_factory), "src");
+  flxdec->srcpad = gst_pad_new_from_static_template (&src_video_factory, "src");
   gst_element_add_pad (GST_ELEMENT (flxdec), flxdec->srcpad);
+  gst_pad_set_query_function (flxdec->srcpad, gst_flxdec_src_query_handler);
+  gst_pad_set_event_function (flxdec->srcpad, gst_flxdec_src_event_handler);
+
+  gst_pad_use_fixed_caps (flxdec->srcpad);
 
-  flxdec->bs = NULL;
   flxdec->frame = NULL;
   flxdec->delta = NULL;
+
+  flxdec->adapter = gst_adapter_new ();
 }
 
 static void
-flx_decode_chunks (GstFlxDec * flxdec, gulong count, gchar * data, gchar * dest)
+gst_flxdec_dispose (GstFlxDec * flxdec)
+{
+  if (flxdec->adapter) {
+    g_object_unref (flxdec->adapter);
+    flxdec->adapter = NULL;
+  }
+
+  G_OBJECT_CLASS (parent_class)->dispose ((GObject *) flxdec);
+}
+
+static gboolean
+gst_flxdec_src_query_handler (GstPad * pad, GstQuery * query)
+{
+  GstFlxDec *flxdec = (GstFlxDec *) gst_pad_get_parent (pad);
+  gboolean ret = FALSE;
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_DURATION:
+    {
+      GstFormat format;
+
+      gst_query_parse_duration (query, &format, NULL);
+
+      if (format != GST_FORMAT_TIME)
+        goto done;
+
+      gst_query_set_duration (query, format, flxdec->duration);
+
+      ret = TRUE;
+    }
+    default:
+      break;
+  }
+done:
+  gst_object_unref (flxdec);
+
+  return ret;
+}
+
+static gboolean
+gst_flxdec_src_event_handler (GstPad * pad, GstEvent * event)
+{
+  GstFlxDec *flxdec = (GstFlxDec *) gst_pad_get_parent (pad);
+  gboolean ret;
+
+  /* TODO: implement the seek and other event handling */
+
+  ret = gst_pad_push_event (flxdec->sinkpad, event);
+
+  gst_object_unref (flxdec);
+
+  return ret;
+}
+
+static gboolean
+gst_flxdec_sink_event_handler (GstPad * pad, GstEvent * event)
+{
+  GstFlxDec *flxdec;
+  gboolean ret;
+
+  flxdec = GST_FLXDEC (gst_pad_get_parent (pad));
+
+  ret = gst_pad_push_event (flxdec->srcpad, event);
+
+  gst_object_unref (flxdec);
+  return ret;
+}
+
+static void
+flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+    guchar * dest)
 {
   FlxFrameChunk *hdr;
 
@@ -174,6 +235,7 @@ flx_decode_chunks (GstFlxDec * flxdec, gulong count, gchar * data, gchar * dest)
 
   while (count--) {
     hdr = (FlxFrameChunk *) data;
+    FLX_FRAME_CHUNK_FIX_ENDIANNESS (hdr);
     data += FlxFrameChunkSize;
 
     switch (hdr->id) {
@@ -242,7 +304,7 @@ flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale)
     if (count == 0)
       count = 256;
 
-    GST_LOG ("GstFlxDec: cmap count: %d (indx: %d)\n", count, indx);
+    GST_LOG ("GstFlxDec: cmap count: %d (indx: %d)", count, indx);
     flx_set_palette_vector (flxdec->converter, indx, count, data, scale);
 
     data += (count * 3);
@@ -293,13 +355,12 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
 static void
 flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
 {
-  gulong count, packets, lines, start_line, start_l;
+  gulong count, packets, lines, start_line;
   guchar *start_p, x;
 
   g_return_if_fail (flxdec != NULL);
   g_return_if_fail (flxdec->delta != NULL);
 
-
   /* use last frame for delta */
   memcpy (dest, GST_BUFFER_DATA (flxdec->delta),
       GST_BUFFER_SIZE (flxdec->delta));
@@ -311,7 +372,6 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
   /* start position of delta */
   dest += (flxdec->hdr.width * start_line);
   start_p = dest;
-  start_l = lines;
 
   while (lines--) {
     /* packet count */
@@ -352,7 +412,6 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
   g_return_if_fail (flxdec != NULL);
   g_return_if_fail (flxdec->delta != NULL);
 
-
   /* use last frame for delta */
   memcpy (dest, GST_BUFFER_DATA (flxdec->delta),
       GST_BUFFER_SIZE (flxdec->delta));
@@ -409,240 +468,217 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
   }
 }
 
-static GstBuffer *
-flx_get_data (GstFlxDec * flxdec, gulong size)
-{
-  GstBuffer *retbuf;
-  guint32 got_bytes;
-
-  g_return_val_if_fail (flxdec != NULL, NULL);
-
-  got_bytes = gst_bytestream_read (flxdec->bs, &retbuf, size);
-  if (got_bytes < size) {
-    GstEvent *event;
-    guint32 remaining;
-
-    gst_bytestream_get_status (flxdec->bs, &remaining, &event);
-    gst_pad_event_default (flxdec->sinkpad, event);
-  }
-
-  return retbuf;
-}
-
-
-static void
-gst_flxdec_loop (GstElement * element)
+static GstFlowReturn
+gst_flxdec_chain (GstPad * pad, GstBuffer * buf)
 {
-  GstBuffer *buf;
-  GstBuffer *databuf;
-  guchar *data, *chunk;
   GstCaps *caps;
+  guint avail;
+  GstFlowReturn res = GST_FLOW_OK;
 
   GstFlxDec *flxdec;
   FlxHeader *flxh;
-  FlxFrameChunk *flxfh;
 
-  g_return_if_fail (element != NULL);
-  g_return_if_fail (GST_IS_FLXDEC (element));
+  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+  flxdec = (GstFlxDec *) gst_pad_get_parent (pad);
+  g_return_val_if_fail (flxdec != NULL, GST_FLOW_ERROR);
 
-  GST_DEBUG ("entering loop function");
-
-  flxdec = GST_FLXDEC (element);
+  gst_adapter_push (flxdec->adapter, buf);
+  avail = gst_adapter_available (flxdec->adapter);
 
   if (flxdec->state == GST_FLXDEC_READ_HEADER) {
-    databuf = flx_get_data (flxdec, FlxHeaderSize);
+    if (avail >= FlxHeaderSize) {
+      const guint8 *data = gst_adapter_peek (flxdec->adapter, FlxHeaderSize);
 
-    if (!databuf) {
-      GST_LOG ("empty buffer");
-      return;
-    }
+      memcpy ((gchar *) & flxdec->hdr, data, FlxHeaderSize);
+      FLX_HDR_FIX_ENDIANNESS (&(flxdec->hdr));
+      gst_adapter_flush (flxdec->adapter, FlxHeaderSize);
 
-    data = GST_BUFFER_DATA (databuf);
+      flxh = &flxdec->hdr;
 
-    memcpy ((char *) &flxdec->hdr, data, sizeof (FlxHeader));
+      /* check header */
+      if (flxh->type != FLX_MAGICHDR_FLI &&
+          flxh->type != FLX_MAGICHDR_FLC && flxh->type != FLX_MAGICHDR_FLX)
+        goto wrong_type;
 
-    gst_buffer_unref (databuf);
+      GST_LOG ("size      :  %d", flxh->size);
+      GST_LOG ("frames    :  %d", flxh->frames);
+      GST_LOG ("width     :  %d", flxh->width);
+      GST_LOG ("height    :  %d", flxh->height);
+      GST_LOG ("depth     :  %d", flxh->depth);
+      GST_LOG ("speed     :  %d", flxh->speed);
 
-    flxh = &flxdec->hdr;
+      flxdec->next_time = 0;
 
-    /* check header */
-    if (flxh->type != FLX_MAGICHDR_FLI &&
-        flxh->type != FLX_MAGICHDR_FLC && flxh->type != FLX_MAGICHDR_FLX) {
-      GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL),
-          ("not a flx file (type %d)\n", flxh->type));
-      return;
-    }
+      if (flxh->type == FLX_MAGICHDR_FLI) {
+        flxdec->frame_time = JIFFIE * flxh->speed;
+      } else if (flxh->speed == 0) {
+        flxdec->frame_time = GST_SECOND / 70;
+      } else {
+        flxdec->frame_time = flxh->speed * GST_MSECOND;
+      }
 
+      flxdec->duration = flxh->frames * flxdec->frame_time;
+      GST_LOG ("duration   :  %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (flxdec->duration));
+
+      caps = gst_caps_from_string (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN);
+      gst_caps_set_simple (caps,
+          "width", G_TYPE_INT, flxh->width,
+          "height", G_TYPE_INT, flxh->height,
+          "framerate", GST_TYPE_FRACTION, (gint) GST_MSECOND,
+          (gint) flxdec->frame_time / 1000, NULL);
+
+      gst_pad_set_caps (flxdec->srcpad, caps);
+      gst_caps_unref (caps);
+
+      if (flxh->depth <= 8)
+        flxdec->converter =
+            flx_colorspace_converter_new (flxh->width, flxh->height);
+
+      if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) {
+        GST_LOG ("(FLC) aspect_dx :  %d", flxh->aspect_dx);
+        GST_LOG ("(FLC) aspect_dy :  %d", flxh->aspect_dy);
+        GST_LOG ("(FLC) oframe1   :  0x%08x", flxh->oframe1);
+        GST_LOG ("(FLC) oframe2   :  0x%08x", flxh->oframe2);
+      }
 
-    GST_LOG ("size      :  %d\n", flxh->size);
-    GST_LOG ("frames    :  %d\n", flxh->frames);
-    GST_LOG ("width     :  %d\n", flxh->width);
-    GST_LOG ("height    :  %d\n", flxh->height);
-    GST_LOG ("depth     :  %d\n", flxh->depth);
-    GST_LOG ("speed     :  %d\n", flxh->speed);
+      flxdec->size = (flxh->width * flxh->height);
 
-    flxdec->next_time = 0;
+      /* create delta and output frame */
+      flxdec->frame = gst_buffer_new ();
+      flxdec->delta = gst_buffer_new ();
+      GST_BUFFER_DATA (flxdec->frame) = g_malloc (flxdec->size);
+      GST_BUFFER_MALLOCDATA (flxdec->frame) = GST_BUFFER_DATA (flxdec->frame);
+      GST_BUFFER_SIZE (flxdec->frame) = flxdec->size;
+      GST_BUFFER_DATA (flxdec->delta) = g_malloc (flxdec->size);
+      GST_BUFFER_MALLOCDATA (flxdec->delta) = GST_BUFFER_DATA (flxdec->delta);
+      GST_BUFFER_SIZE (flxdec->delta) = flxdec->size;
 
-    if (flxh->type == FLX_MAGICHDR_FLI) {
-      flxdec->frame_time = JIFFIE * flxh->speed;
-    } else {
-      flxdec->frame_time = flxh->speed * GST_MSECOND;
+      flxdec->state = GST_FLXDEC_PLAYING;
     }
-
-    caps = gst_caps_from_string (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN);
-    gst_caps_set_simple (caps,
-        "width", G_TYPE_INT, flxh->width,
-        "height", G_TYPE_INT, flxh->height,
-        "framerate", G_TYPE_DOUBLE, GST_SECOND / flxdec->frame_time, NULL);
-
-    if (flxh->depth <= 8)
-      flxdec->converter =
-          flx_colorspace_converter_new (flxh->width, flxh->height);
-
-    if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) {
-      GST_LOG ("(FLC) aspect_dx :  %d\n", flxh->aspect_dx);
-      GST_LOG ("(FLC) aspect_dy :  %d\n", flxh->aspect_dy);
-      GST_LOG ("(FLC) oframe1   :  0x%08x\n", flxh->oframe1);
-      GST_LOG ("(FLC) oframe2   :  0x%08x\n", flxh->oframe2);
-    }
-
-    flxdec->size = (flxh->width * flxh->height);
-
-    /* create delta and output frame */
-    flxdec->frame = gst_buffer_new ();
-    flxdec->delta = gst_buffer_new ();
-    GST_BUFFER_DATA (flxdec->frame) = g_malloc (flxdec->size);
-    GST_BUFFER_SIZE (flxdec->frame) = flxdec->size;
-    GST_BUFFER_DATA (flxdec->delta) = g_malloc (flxdec->size);
-    GST_BUFFER_SIZE (flxdec->delta) = flxdec->size;
-
-    flxdec->state = GST_FLXDEC_PLAYING;
   } else if (flxdec->state == GST_FLXDEC_PLAYING) {
     GstBuffer *out;
 
-    databuf = flx_get_data (flxdec, FlxFrameChunkSize);
-    if (!databuf)
-      return;
-
-    flxfh = (FlxFrameChunk *) GST_BUFFER_DATA (databuf);
-
-    switch (flxfh->id) {
-      case FLX_FRAME_TYPE:
-        buf = flx_get_data (flxdec, flxfh->size - FlxFrameChunkSize);
-
-        chunk = GST_BUFFER_DATA (buf);
-
-        if (((FlxFrameType *) chunk)->chunks == 0)
+    /* while we have enough data in the adapter */
+    while (avail >= FlxFrameChunkSize) {
+      FlxFrameChunk flxfh;
+      guchar *chunk;
+      const guint8 *data;
+
+      chunk = NULL;
+      data = gst_adapter_peek (flxdec->adapter, FlxFrameChunkSize);
+      memcpy (&flxfh, data, FlxFrameChunkSize);
+      FLX_FRAME_CHUNK_FIX_ENDIANNESS (&flxfh);
+
+      switch (flxfh.id) {
+        case FLX_FRAME_TYPE:
+          /* check if we have the complete frame */
+          if (avail < flxfh.size)
+            goto need_more_data;
+
+          /* flush header */
+          gst_adapter_flush (flxdec->adapter, FlxFrameChunkSize);
+
+          chunk = gst_adapter_take (flxdec->adapter,
+              flxfh.size - FlxFrameChunkSize);
+          FLX_FRAME_TYPE_FIX_ENDIANNESS ((FlxFrameType *) chunk);
+          if (((FlxFrameType *) chunk)->chunks == 0)
+            break;
+
+          /* create 32 bits output frame */
+          res = gst_pad_alloc_buffer_and_set_caps (flxdec->srcpad,
+              GST_BUFFER_OFFSET_NONE,
+              flxdec->size * 4, GST_PAD_CAPS (flxdec->srcpad), &out);
+          if (res != GST_FLOW_OK)
+            break;
+
+          /* decode chunks */
+          flx_decode_chunks (flxdec,
+              ((FlxFrameType *) chunk)->chunks,
+              chunk + FlxFrameTypeSize, GST_BUFFER_DATA (flxdec->frame));
+
+          /* save copy of the current frame for possible delta. */
+          memcpy (GST_BUFFER_DATA (flxdec->delta),
+              GST_BUFFER_DATA (flxdec->frame), GST_BUFFER_SIZE (flxdec->delta));
+
+          /* convert current frame. */
+          flx_colorspace_convert (flxdec->converter,
+              GST_BUFFER_DATA (flxdec->frame), GST_BUFFER_DATA (out));
+
+          GST_BUFFER_TIMESTAMP (out) = flxdec->next_time;
+          flxdec->next_time += flxdec->frame_time;
+
+          gst_pad_push (flxdec->srcpad, out);
           break;
+      }
 
-        /* create 32 bits output frame */
-        out = gst_buffer_new ();
-        GST_BUFFER_DATA (out) = g_malloc (flxdec->size * 4);
-        GST_BUFFER_SIZE (out) = flxdec->size * 4;
-
-        /* decode chunks */
-        flx_decode_chunks (flxdec,
-            ((FlxFrameType *) chunk)->chunks,
-            GST_BUFFER_DATA (buf) + FlxFrameTypeSize,
-            GST_BUFFER_DATA (flxdec->frame));
-
-        /* destroy input buffer */
-        gst_buffer_unref (buf);
-
-        /* save copy of the current frame for possible delta. */
-        memcpy (GST_BUFFER_DATA (flxdec->delta),
-            GST_BUFFER_DATA (flxdec->frame), GST_BUFFER_SIZE (flxdec->delta));
-
-        /* convert current frame. */
-        flx_colorspace_convert (flxdec->converter,
-            GST_BUFFER_DATA (flxdec->frame), GST_BUFFER_DATA (out));
-
-        GST_BUFFER_TIMESTAMP (out) = flxdec->next_time;
-        flxdec->next_time += flxdec->frame_time;
-
-        gst_pad_push (flxdec->srcpad, GST_DATA (out));
+      if (chunk)
+        g_free (chunk);
 
-        break;
+      avail = gst_adapter_available (flxdec->adapter);
     }
-
-    /* destroy header buffer */
-    gst_buffer_unref (databuf);
+  }
+need_more_data:
+  gst_object_unref (flxdec);
+  return res;
+
+  /* ERRORS */
+wrong_type:
+  {
+    GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL),
+        ("not a flx file (type %x)", flxh->type));
+    gst_object_unref (flxdec);
+    return GST_FLOW_ERROR;
   }
 }
 
-static GstElementStateReturn
-gst_flxdec_change_state (GstElement * element)
+static GstStateChangeReturn
+gst_flxdec_change_state (GstElement * element, GstStateChange transition)
 {
   GstFlxDec *flxdec;
+  GstStateChangeReturn ret;
 
   flxdec = GST_FLXDEC (element);
 
-  switch (GST_STATE_TRANSITION (element)) {
-    case GST_STATE_NULL_TO_READY:
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
       break;
-    case GST_STATE_READY_TO_PAUSED:
-      flxdec->bs = gst_bytestream_new (flxdec->sinkpad);
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      gst_adapter_clear (flxdec->adapter);
       flxdec->state = GST_FLXDEC_READ_HEADER;
       break;
-    case GST_STATE_PAUSED_TO_PLAYING:
-      break;
-    case GST_STATE_PLAYING_TO_PAUSED:
-      break;
-    case GST_STATE_PAUSED_TO_READY:
-      gst_buffer_unref (flxdec->frame);
-      flxdec->frame = NULL;
-      gst_buffer_unref (flxdec->delta);
-      flxdec->delta = NULL;
-      gst_bytestream_destroy (flxdec->bs);
-      break;
-    case GST_STATE_READY_TO_NULL:
+    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       break;
-  }
-
-  parent_class->change_state (element);
-
-  return GST_STATE_SUCCESS;
-}
-
-static void
-gst_flxdec_set_property (GObject * object, guint prop_id, const GValue * value,
-    GParamSpec * pspec)
-{
-  GstFlxDec *flxdec;
-
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail (GST_IS_FLXDEC (object));
-  flxdec = GST_FLXDEC (object);
-
-  switch (prop_id) {
     default:
       break;
   }
-}
-
-static void
-gst_flxdec_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
-{
-  GstFlxDec *flxdec;
 
-  /* it's not null if we got it, but it might not be ours */
-  g_return_if_fail (GST_IS_FLXDEC (object));
-  flxdec = GST_FLXDEC (object);
+  ret = parent_class->change_state (element, transition);
 
-  switch (prop_id) {
+  switch (transition) {
+    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+      break;
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      if (flxdec->frame) {
+        gst_buffer_unref (flxdec->frame);
+        flxdec->frame = NULL;
+      }
+      if (flxdec->delta) {
+        gst_buffer_unref (flxdec->delta);
+        flxdec->delta = NULL;
+      }
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      break;
     default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
+  return ret;
 }
 
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  if (!gst_library_load ("gstbytestream"))
-    return FALSE;
-
   return gst_element_register (plugin, "flxdec",
       GST_RANK_PRIMARY, GST_TYPE_FLXDEC);
 }
@@ -650,5 +686,5 @@ plugin_init (GstPlugin * plugin)
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "flxdec",
-    "FLX video decoder",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
+    "FLC/FLI/FLX video decoder",
+    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)