ext/mpeg2dec/gstmpeg2dec.*: Removed lots of dubious code.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 26 Oct 2005 16:45:04 +0000 (16:45 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 26 Oct 2005 16:45:04 +0000 (16:45 +0000)
Original commit message from CVS:
* ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_init),
(gst_mpeg2dec_dispose), (gst_mpeg2dec_reset),
(gst_mpeg2dec_alloc_buffer), (gst_mpeg2dec_negotiate_format),
(handle_sequence), (handle_picture):
* ext/mpeg2dec/gstmpeg2dec.h:
Removed lots of dubious code.
Handle flushing and seeking correctly. Still leaks though...

ChangeLog
ext/mpeg2dec/gstmpeg2dec.c
ext/mpeg2dec/gstmpeg2dec.h

index f33c1c5f5a22c04eb6f6a6fbf7b7cfd395509b57..197b7365a80d56dd617c7c9ef0cbe76791848e25 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2005-10-26  Wim Taymans  <wim@fluendo.com>
+
+       * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_init),
+       (gst_mpeg2dec_dispose), (gst_mpeg2dec_reset),
+       (gst_mpeg2dec_alloc_buffer), (gst_mpeg2dec_negotiate_format),
+       (handle_sequence), (handle_picture):
+       * ext/mpeg2dec/gstmpeg2dec.h:
+       Removed lots of dubious code.
+       Handle flushing and seeking correctly. Still leaks though...
+
 2005-10-24  Christian Schaller  <christian at fluendo dot com>
 
        * configure.ac: port over thomas plugin listing from base
index e6451680730e9b3a24923ada47c5f9962d67eb3a..42b6bb7f6d878f3b127524cda3175fb18d337587 100644 (file)
@@ -187,9 +187,6 @@ static const GstEventMask *gst_mpeg2dec_get_event_masks (GstPad * pad);
 static GstElementClass *parent_class = NULL;
 
 static GstBuffer *crop_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * input);
-static gboolean check_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf);
-static gboolean free_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf);
-static void free_all_buffers (GstMpeg2dec * mpeg2dec);
 
 /*static guint gst_mpeg2dec_signals[LAST_SIGNAL] = { 0 };*/
 
@@ -260,8 +257,6 @@ gst_mpeg2dec_class_init (GstMpeg2decClass * klass)
 static void
 gst_mpeg2dec_init (GstMpeg2dec * mpeg2dec)
 {
-  int i;
-
   /* create the sink and src pads */
   mpeg2dec->sinkpad =
       gst_pad_new_from_template (gst_static_pad_template_get
@@ -293,35 +288,6 @@ gst_mpeg2dec_init (GstMpeg2dec * mpeg2dec)
 #endif
 
   /* initialize the mpeg2dec acceleration */
-  mpeg2_accel (MPEG2_ACCEL_DETECT);
-  mpeg2dec->closed = TRUE;
-  mpeg2dec->have_fbuf = FALSE;
-  mpeg2dec->offset = 0;
-
-  for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++)
-    mpeg2dec->buffers[i] = NULL;
-
-}
-
-static void
-gst_mpeg2dec_close_decoder (GstMpeg2dec * mpeg2dec)
-{
-  if (!mpeg2dec->closed) {
-    mpeg2_close (mpeg2dec->decoder);
-    free_all_buffers (mpeg2dec);
-    mpeg2dec->closed = TRUE;
-    mpeg2dec->decoder = NULL;
-  }
-}
-
-static void
-gst_mpeg2dec_open_decoder (GstMpeg2dec * mpeg2dec)
-{
-  gst_mpeg2dec_close_decoder (mpeg2dec);
-  mpeg2dec->decoder = mpeg2_init ();
-  mpeg2dec->closed = FALSE;
-  mpeg2dec->have_fbuf = FALSE;
-  mpeg2_custom_fbuf (mpeg2dec->decoder, 1);
 }
 
 static void
@@ -329,7 +295,11 @@ gst_mpeg2dec_dispose (GObject * object)
 {
   GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (object);
 
-  gst_mpeg2dec_close_decoder (mpeg2dec);
+  if (mpeg2dec->decoder) {
+    GST_DEBUG_OBJECT (mpeg2dec, "closing decoder");
+    mpeg2_close (mpeg2dec->decoder);
+    mpeg2dec->decoder = NULL;
+  }
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -345,10 +315,11 @@ gst_mpeg2dec_reset (GstMpeg2dec * mpeg2dec)
   mpeg2dec->segment_end = -1;
   mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
   mpeg2dec->frame_period = 0;
-  gst_pad_use_fixed_caps (mpeg2dec->srcpad);
-  gst_mpeg2dec_open_decoder (mpeg2dec);
   mpeg2dec->need_sequence = TRUE;
+  mpeg2dec->next_time = 0;
+  mpeg2dec->offset = 0;
 }
+
 static void
 gst_mpeg2dec_set_index (GstElement * element, GstIndex * index)
 {
@@ -367,65 +338,6 @@ gst_mpeg2dec_get_index (GstElement * element)
   return mpeg2dec->index;
 }
 
-static gboolean
-put_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf)
-{
-  int i;
-
-  for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++) {
-    if (mpeg2dec->buffers[i] == NULL) {
-      GST_DEBUG_OBJECT (mpeg2dec, "Placing %p at slot %d", buf, i);
-      mpeg2dec->buffers[i] = buf;
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-
-static gboolean
-check_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf)
-{
-  int i;
-
-  for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++)
-    if (mpeg2dec->buffers[i] == buf)
-      return TRUE;
-
-  return FALSE;
-}
-
-static gboolean
-free_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf)
-{
-  int i;
-
-  for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++) {
-    if (mpeg2dec->buffers[i] == buf) {
-      GST_DEBUG_OBJECT (mpeg2dec, "Releasing %p at slot %d", buf, i);
-      gst_buffer_unref (buf);
-      mpeg2dec->buffers[i] = NULL;
-
-      return TRUE;
-    }
-  }
-  return FALSE;
-}
-
-static void
-free_all_buffers (GstMpeg2dec * mpeg2dec)
-{
-  int i;
-
-  for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++) {
-    if (mpeg2dec->buffers[i] != NULL) {
-      GST_DEBUG_OBJECT (mpeg2dec, "free_all Releasing %p at slot %d",
-          mpeg2dec->buffers[i], i);
-      gst_buffer_unref (mpeg2dec->buffers[i]);
-      mpeg2dec->buffers[i] = NULL;
-    }
-  }
-}
-
 static GstBuffer *
 crop_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * input)
 {
@@ -504,85 +416,52 @@ gst_mpeg2dec_alloc_buffer (GstMpeg2dec * mpeg2dec, gint64 offset)
   guint8 *buf[3], *out = NULL;
   GstFlowReturn ret = GST_FLOW_OK;
 
-  do {
+  if (mpeg2dec->format == MPEG2DEC_FORMAT_I422) {
+    ret =
+        gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE,
+        size * 2, GST_PAD_CAPS (mpeg2dec->srcpad), &outbuf);
+    if (ret != GST_FLOW_OK) {
+      GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL),
+          ("Failed to allocate memory for buffer"));
+      goto done;
+    }
+    out = GST_BUFFER_DATA (outbuf);
 
-    if (mpeg2dec->format == MPEG2DEC_FORMAT_I422) {
-      ret =
-          gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE,
-          size * 2, GST_PAD_CAPS (mpeg2dec->srcpad), &outbuf);
-      if (ret != GST_FLOW_OK) {
-        GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL),
-            ("Failed to allocate memory for buffer"));
-        break;
-      }
-      /* 0.9
-         outbuf =
-         gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE,
-         size * 2);
-
-         if (!outbuf) {
-         GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL),
-         ("Failed to allocate memory for buffer"));
-         return NULL;
-         }
-       */
+    buf[0] = out;
+    buf[1] = buf[0] + size;
+    buf[2] = buf[1] + size / 2;
 
-      out = GST_BUFFER_DATA (outbuf);
+  } else {
+    ret =
+        gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE,
+        (size * 3) / 2, GST_PAD_CAPS (mpeg2dec->srcpad), &outbuf);
+    if (ret != GST_FLOW_OK) {
+      GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL),
+          ("Failed to allocate memory for buffer"));
+      goto done;
+    }
+
+    out = GST_BUFFER_DATA (outbuf);
 
+    buf[0] = out;
+    if (mpeg2dec->format == MPEG2DEC_FORMAT_I420) {
       buf[0] = out;
       buf[1] = buf[0] + size;
-      buf[2] = buf[1] + size / 2;
-
+      buf[2] = buf[1] + size / 4;
     } else {
-      /* 0.9
-         outbuf =
-         gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE,
-         (size * 3) / 2);
-       */
-      ret =
-          gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE,
-          size * 2, GST_PAD_CAPS (mpeg2dec->srcpad), &outbuf);
-      if (ret != GST_FLOW_OK) {
-        GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL),
-            ("Failed to allocate memory for buffer"));
-        break;
-      }
-
-      out = GST_BUFFER_DATA (outbuf);
-
       buf[0] = out;
-      if (mpeg2dec->format == MPEG2DEC_FORMAT_I420) {
-        buf[0] = out;
-        buf[1] = buf[0] + size;
-        buf[2] = buf[1] + size / 4;
-      } else {
-        buf[0] = out;
-        buf[2] = buf[0] + size;
-        buf[1] = buf[2] + size / 4;
-      }
-    }
-
-    if (!put_buffer (mpeg2dec, outbuf)) {
-#if 0
-      GST_ELEMENT_ERROR (mpeg2dec, LIBRARY, TOO_LAZY, (NULL),
-          ("No free slot. libmpeg2 did not discard buffers."));
-#else
-      GST_WARNING_OBJECT (mpeg2dec,
-          "No free slot. libmpeg2 did not discard buffers.");
-#endif
-      return NULL;
+      buf[2] = buf[0] + size;
+      buf[1] = buf[2] + size / 4;
     }
+  }
 
-    mpeg2_custom_fbuf (mpeg2dec->decoder, 1);
-    mpeg2_set_buf (mpeg2dec->decoder, buf, outbuf);
-
-    /* we store the original byteoffset of this picture in the stream here
-     * because we need it for indexing */
-    GST_BUFFER_OFFSET (outbuf) = offset;
+  mpeg2_set_buf (mpeg2dec->decoder, buf, outbuf);
 
-  }
-  while (FALSE);
+  /* we store the original byteoffset of this picture in the stream here
+   * because we need it for indexing */
+  GST_BUFFER_OFFSET (outbuf) = offset;
 
+done:
   if (ret != GST_FLOW_OK) {
     outbuf = NULL;              /* just to asure NULL return, looking the path
                                    above it happens only when gst_pad_alloc_buffer
@@ -596,54 +475,36 @@ static gboolean
 gst_mpeg2dec_negotiate_format (GstMpeg2dec * mpeg2dec)
 {
   GstCaps *caps;
-  guint32 fourcc, myFourcc;
-  gboolean ret = TRUE;
+  guint32 fourcc;
   const mpeg2_info_t *info;
   const mpeg2_sequence_t *sequence;
 
-  if (!GST_PAD_IS_LINKED (mpeg2dec->srcpad)) {
-    mpeg2dec->format = MPEG2DEC_FORMAT_I420;
-    return TRUE;
-  }
-
   info = mpeg2_info (mpeg2dec->decoder);
   sequence = info->sequence;
 
   if (sequence->width != sequence->chroma_width &&
-      sequence->height != sequence->chroma_height)
-    myFourcc = GST_STR_FOURCC ("I420");
-  else if (sequence->width == sequence->chroma_width ||
-      sequence->height == sequence->chroma_height)
-    myFourcc = GST_STR_FOURCC ("Y42B");
-  else {
+      sequence->height != sequence->chroma_height) {
+    fourcc = GST_STR_FOURCC ("I420");
+    mpeg2dec->format = MPEG2DEC_FORMAT_I420;
+  } else if (sequence->width == sequence->chroma_width ||
+      sequence->height == sequence->chroma_height) {
+    fourcc = GST_STR_FOURCC ("Y42B");
+    mpeg2dec->format = MPEG2DEC_FORMAT_I422;
+  } else {
     g_warning ("mpeg2dec: 4:4:4 format not yet supported");
     return (FALSE);
   }
 
   caps = gst_caps_new_simple ("video/x-raw-yuv",
-      "format", GST_TYPE_FOURCC, myFourcc,
+      "format", GST_TYPE_FOURCC, fourcc,
       "width", G_TYPE_INT, mpeg2dec->width,
       "height", G_TYPE_INT, mpeg2dec->height,
       "pixel-aspect-ratio", GST_TYPE_FRACTION, mpeg2dec->pixel_width,
       mpeg2dec->pixel_height,
       "framerate", G_TYPE_DOUBLE, mpeg2dec->frame_rate, NULL);
 
-  // ret = gst_pad_set_explicit_caps (mpeg2dec->srcpad, caps);
-  ret = gst_pad_set_caps (mpeg2dec->srcpad, caps);
-  if (!ret)
-    return FALSE;
-
-  /* it worked, try to find what it was again */
-  gst_structure_get_fourcc (gst_caps_get_structure (caps, 0),
-      "format", &fourcc);
-
-  if (fourcc == GST_STR_FOURCC ("Y42B")) {
-    mpeg2dec->format = MPEG2DEC_FORMAT_I422;
-  } else if (fourcc == GST_STR_FOURCC ("I420")) {
-    mpeg2dec->format = MPEG2DEC_FORMAT_I420;
-  } else {
-    mpeg2dec->format = MPEG2DEC_FORMAT_YV12;
-  }
+  gst_pad_set_caps (mpeg2dec->srcpad, caps);
+  gst_caps_unref (caps);
 
   return TRUE;
 }
@@ -679,20 +540,23 @@ handle_sequence (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info)
       info->sequence->transfer_characteristics,
       info->sequence->matrix_coefficients);
 
-  if (!gst_mpeg2dec_negotiate_format (mpeg2dec)) {
-    GST_ELEMENT_ERROR (mpeg2dec, CORE, NEGOTIATION, (NULL), (NULL));
-    return FALSE;
-  }
+  if (!gst_mpeg2dec_negotiate_format (mpeg2dec))
+    goto negotiate_failed;
+
+  mpeg2_custom_fbuf (mpeg2dec->decoder, 1);
 
-  free_all_buffers (mpeg2dec);
-  if (!gst_mpeg2dec_alloc_buffer (mpeg2dec, mpeg2dec->offset) ||
-      !gst_mpeg2dec_alloc_buffer (mpeg2dec, mpeg2dec->offset) ||
-      !gst_mpeg2dec_alloc_buffer (mpeg2dec, mpeg2dec->offset))
+  if (!gst_mpeg2dec_alloc_buffer (mpeg2dec, mpeg2dec->offset))
     return FALSE;
 
   mpeg2dec->need_sequence = FALSE;
 
   return TRUE;
+
+negotiate_failed:
+  {
+    GST_ELEMENT_ERROR (mpeg2dec, CORE, NEGOTIATION, (NULL), (NULL));
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -701,6 +565,8 @@ handle_picture (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info)
   gboolean key_frame = FALSE;
   GstBuffer *outbuf;
 
+  GST_DEBUG_OBJECT (mpeg2dec, "handle picture");
+
   if (info->current_picture) {
     key_frame =
         (info->current_picture->flags & PIC_MASK_CODING_TYPE) ==
@@ -718,10 +584,7 @@ handle_picture (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info)
   if (mpeg2dec->discont_state == MPEG2DEC_DISC_NEW_PICTURE && key_frame)
     mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_KEYFRAME;
 
-  if (!GST_PAD_IS_USABLE (mpeg2dec->srcpad))
-    mpeg2_skip (mpeg2dec->decoder, 1);
-  else
-    mpeg2_skip (mpeg2dec->decoder, 0);
+  mpeg2_skip (mpeg2dec->decoder, 0);
 
   return TRUE;
 }
@@ -743,13 +606,6 @@ handle_slice (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info)
     gboolean key_frame = FALSE;
 
     outbuf = GST_BUFFER (info->display_fbuf->id);
-    if (!check_buffer (mpeg2dec, outbuf)) {
-      GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL),
-          ("libmpeg2 reported invalid buffer %p", outbuf));
-      return FALSE;
-    }
-
-    gst_buffer_ref (outbuf);
 
     picture = info->display_picture;
 
@@ -813,8 +669,7 @@ handle_slice (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info)
     if (picture->flags & PIC_FLAG_SKIP) {
       GST_DEBUG_OBJECT (mpeg2dec, "dropping buffer because of skip flag");
       gst_buffer_unref (outbuf);
-    } else if (!GST_PAD_IS_USABLE (mpeg2dec->srcpad)
-        || gst_pad_get_negotiated_caps (mpeg2dec->srcpad) == NULL) {
+    } else if (gst_pad_get_negotiated_caps (mpeg2dec->srcpad) == NULL) {
       GST_DEBUG_OBJECT (mpeg2dec, "dropping buffer, pad not usable");
       gst_buffer_unref (outbuf);
     } else if (mpeg2dec->discont_state != MPEG2DEC_DISC_NONE) {
@@ -857,14 +712,7 @@ handle_slice (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info)
   }
 
   if (info->discard_fbuf && info->discard_fbuf->id) {
-    if (free_buffer (mpeg2dec, GST_BUFFER (info->discard_fbuf->id))) {
-
-      GST_DEBUG_OBJECT (mpeg2dec, "Discarded buffer %p",
-          info->discard_fbuf->id);
-    } else {
-      GST_ELEMENT_ERROR (mpeg2dec, LIBRARY, TOO_LAZY, (NULL),
-          ("libmpeg2 reported invalid buffer %p", info->discard_fbuf->id));
-    }
+    GST_DEBUG_OBJECT (mpeg2dec, "Discarded buffer %p", info->discard_fbuf->id);
   }
   return TRUE;
 }
@@ -899,79 +747,10 @@ update_streaminfo (GstMpeg2dec * mpeg2dec)
 }
 #endif
 
-static void
-gst_mpeg2dec_flush_decoder (GstMpeg2dec * mpeg2dec)
-{
-  if (mpeg2dec->decoder) {
-    const mpeg2_info_t *info = mpeg2_info (mpeg2dec->decoder);
-    mpeg2_state_t state;
-
-    /*
-     * iterate the decoder and free buffers
-     */
-    do {
-      state = mpeg2_parse (mpeg2dec->decoder);
-      switch (state) {
-        case STATE_SEQUENCE:
-          if (!handle_sequence (mpeg2dec, info)) {
-            gst_mpeg2dec_close_decoder (mpeg2dec);
-            gst_mpeg2dec_open_decoder (mpeg2dec);
-            state = -1;
-          }
-          break;
-        case STATE_PICTURE:
-          if (!handle_picture (mpeg2dec, info)) {
-            gst_mpeg2dec_close_decoder (mpeg2dec);
-            gst_mpeg2dec_open_decoder (mpeg2dec);
-            state = -1;
-            break;
-          }
-          mpeg2_skip (mpeg2dec->decoder, 1);
-          break;
-        case STATE_END:
-#if MPEG2_RELEASE >= MPEG2_VERSION (0, 4, 0)
-        case STATE_INVALID_END:
-#endif
-        case STATE_SLICE:
-          if (info->discard_fbuf) {
-            if (free_buffer (mpeg2dec, GST_BUFFER (info->discard_fbuf->id))) {
-              GST_DEBUG_OBJECT (mpeg2dec, "Discarded buffer %p",
-                  info->discard_fbuf->id);
-            } else {
-              GST_ELEMENT_ERROR (mpeg2dec, LIBRARY, TOO_LAZY, (NULL),
-                  ("libmpeg2 reported invalid buffer %p, fbuf: %p",
-                      info->discard_fbuf->id, info->discard_fbuf));
-            }
-          }
-          break;
-        case STATE_INVALID:
-          GST_WARNING_OBJECT (mpeg2dec, "Decoding error");
-          /*
-           * We need to close the decoder here, according to docs
-           */
-          gst_mpeg2dec_close_decoder (mpeg2dec);
-          gst_mpeg2dec_open_decoder (mpeg2dec);
-          return;
-        default:
-          break;
-      }
-    }
-    while (state != STATE_BUFFER && state != -1);
-
-#if MPEG2_RELEASE >= MPEG2_VERSION(0,4,0)
-    GST_DEBUG_OBJECT (mpeg2dec, "resetting mpeg2 stream decoder");
-    /* 0 starts at next picture, 1 at next sequence header */
-    mpeg2_reset (mpeg2dec->decoder, 0);
-#endif
-
-  }
-}
-
 static GstFlowReturn
 gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf)
 {
-  /* 0.9  GstBuffer *buf = GST_BUFFER (_data); */
-  GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (GST_PAD_PARENT (pad));
+  GstMpeg2dec *mpeg2dec;
   guint32 size;
   guint8 *data, *end;
   GstClockTime pts;
@@ -979,73 +758,39 @@ gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf)
   mpeg2_state_t state;
   gboolean done = FALSE;
 
-
+  mpeg2dec = GST_MPEG2DEC (GST_PAD_PARENT (pad));
 
   size = GST_BUFFER_SIZE (buf);
   data = GST_BUFFER_DATA (buf);
   pts = GST_BUFFER_TIMESTAMP (buf);
+
   GST_LOG_OBJECT (mpeg2dec, "received buffer, timestamp %"
       GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
 
-  info = mpeg2_info (mpeg2dec->decoder);
+  info = mpeg2dec->info;
   end = data + size;
 
-  if (pts != GST_CLOCK_TIME_NONE) {
-    gint64 mpeg_pts = GST_TIME_TO_MPEG_TIME (pts);
-
-    GST_DEBUG_OBJECT (mpeg2dec,
-        "have pts: %" G_GINT64_FORMAT " (%" GST_TIME_FORMAT ")", mpeg_pts,
-        GST_TIME_ARGS (MPEG_TIME_TO_GST_TIME (mpeg_pts)));
-
-#if MPEG2_RELEASE >= MPEG2_VERSION(0,4,0)
-    mpeg2_tag_picture (mpeg2dec->decoder, mpeg_pts & 0xffffffff,
-        mpeg_pts >> 32);
-#else
-    mpeg2_pts (mpeg2dec->decoder, mpeg_pts);
-#endif
-
-  } else {
-    GST_LOG ("no pts");
-  }
-
-  GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer");
-  mpeg2_buffer (mpeg2dec->decoder, data, end);
-  GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer done");
-
   mpeg2dec->offset = GST_BUFFER_OFFSET (buf);
+
   while (!done) {
     GST_LOG_OBJECT (mpeg2dec, "calling parse");
     state = mpeg2_parse (mpeg2dec->decoder);
     GST_DEBUG_OBJECT (mpeg2dec, "parse state %d", state);
+
     switch (state) {
       case STATE_SEQUENCE:
-        if (!handle_sequence (mpeg2dec, info)) {
-          goto exit;
-        }
-
-        if (mpeg2dec->pending_event) {
-          done = TRUE;
-#if 0
-          GST_EVENT_SEEK_FLAGS (mpeg2dec->pending_event) & GST_SEEK_FLAG_FLUSH;
-#endif
-
-          gst_mpeg2dec_src_event (mpeg2dec->srcpad, mpeg2dec->pending_event);
-          mpeg2dec->pending_event = NULL;
-        }
+        handle_sequence (mpeg2dec, info);
         break;
       case STATE_SEQUENCE_REPEATED:
         GST_DEBUG_OBJECT (mpeg2dec, "sequence repeated");
+        break;
       case STATE_GOP:
         break;
       case STATE_PICTURE:
-      {
-        if (!handle_picture (mpeg2dec, info)) {
-          goto exit;
-        }
+        handle_picture (mpeg2dec, info);
         break;
-      }
       case STATE_SLICE_1ST:
         GST_LOG_OBJECT (mpeg2dec, "1st slice of frame encountered");
         break;
@@ -1059,25 +804,42 @@ gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf)
       case STATE_END:
         mpeg2dec->need_sequence = TRUE;
       case STATE_SLICE:
-        if (!handle_slice (mpeg2dec, info)) {
-          goto exit;
-        }
-
+        handle_slice (mpeg2dec, info);
         break;
       case STATE_BUFFER:
-      case -1:
-        /* need more data */
-        done = TRUE;
+        if (data == NULL) {
+          done = TRUE;
+        } else {
+          if (pts != GST_CLOCK_TIME_NONE) {
+            gint64 mpeg_pts = GST_TIME_TO_MPEG_TIME (pts);
+
+            GST_DEBUG_OBJECT (mpeg2dec,
+                "have pts: %" G_GINT64_FORMAT " (%" GST_TIME_FORMAT ")",
+                mpeg_pts, GST_TIME_ARGS (MPEG_TIME_TO_GST_TIME (mpeg_pts)));
+
+#if MPEG2_RELEASE >= MPEG2_VERSION(0,4,0)
+            mpeg2_tag_picture (mpeg2dec->decoder, mpeg_pts & 0xffffffff,
+                mpeg_pts >> 32);
+#else
+            mpeg2_pts (mpeg2dec->decoder, mpeg_pts);
+#endif
+          } else {
+            GST_LOG ("no pts");
+          }
+
+          GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer");
+          mpeg2_buffer (mpeg2dec->decoder, data, end);
+          GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer done");
+
+          data = NULL;
+        }
         break;
         /* error */
       case STATE_INVALID:
         GST_WARNING_OBJECT (mpeg2dec, "Decoding error");
         goto exit;
-
-        break;
       default:
         GST_ERROR_OBJECT (mpeg2dec, "Unknown libmpeg2 state %d, FIXME", state);
-
         break;
     }
 
@@ -1086,13 +848,11 @@ gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf)
      */
 #ifdef enable_user_data
     if (info->user_data_len > 0) {
-      if (GST_PAD_IS_USABLE (mpeg2dec->userdatapad)) {
-        GstBuffer *udbuf = gst_buffer_new_and_alloc (info->user_data_len);
+      GstBuffer *udbuf = gst_buffer_new_and_alloc (info->user_data_len);
 
-        memcpy (GST_BUFFER_DATA (udbuf), info->user_data, info->user_data_len);
+      memcpy (GST_BUFFER_DATA (udbuf), info->user_data, info->user_data_len);
 
-        gst_pad_push (mpeg2dec->userdatapad, GST_BUFFER (udbuf));
-      }
+      gst_pad_push (mpeg2dec->userdatapad, udbuf);
     }
 #endif
 
@@ -1101,12 +861,6 @@ gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf)
   return GST_FLOW_OK;
 
 exit:
-  /*
-   * Close and reopen the decoder, because
-   * something went pretty wrong
-   */
-  gst_mpeg2dec_close_decoder (mpeg2dec);
-  gst_mpeg2dec_open_decoder (mpeg2dec);
   gst_buffer_unref (buf);
   return GST_FLOW_ERROR;
 }
@@ -1121,45 +875,8 @@ gst_mpeg2dec_sink_event (GstPad * pad, GstEvent * event)
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_NEWSEGMENT:
     {
-#if 0
-      gint64 time;
-      gint64 end_time;          /* 0.9 just to call
-                                   gst_event_discont_get_value, non
-                                   used anywhere else */
-#endif
-
       GST_STREAM_LOCK (pad);
-
-#if 0
-      if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &time,
-              &end_time)
-          || !GST_CLOCK_TIME_IS_VALID (time)) {
-        GST_WARNING_OBJECT (mpeg2dec,
-            "No new time offset in discont event %p", event);
-      } else {
-        mpeg2dec->next_time = time;
-        GST_DEBUG_OBJECT (mpeg2dec,
-            "discont, reset next_time to %" G_GUINT64_FORMAT " (%"
-            GST_TIME_FORMAT ")", mpeg2dec->next_time,
-            GST_TIME_ARGS (mpeg2dec->next_time));
-      }
-#endif
-
-      // what's hell is that
-      /*
-         if (GST_EVENT_DISCONT_NEW_MEDIA (event))
-         {
-         gst_mpeg2dec_reset (mpeg2dec);
-         }
-         else
-         {
-         mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
-         gst_mpeg2dec_flush_decoder (mpeg2dec);
-         }
-       */
-
       mpeg2dec->next_time = -1;;
-
       ret = gst_pad_event_default (pad, event);
       GST_STREAM_UNLOCK (pad);
       break;
@@ -1170,7 +887,8 @@ gst_mpeg2dec_sink_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_FLUSH_STOP:
       GST_STREAM_LOCK (pad);
       mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
-      gst_mpeg2dec_flush_decoder (mpeg2dec);
+      mpeg2dec->next_time = -1;;
+      mpeg2_reset (mpeg2dec->decoder, 0);
       ret = gst_pad_event_default (pad, event);
       GST_STREAM_UNLOCK (pad);
       break;
@@ -1194,29 +912,6 @@ gst_mpeg2dec_sink_event (GstPad * pad, GstEvent * event)
 
 }
 
-
-
-#if 0
-static const GstFormat *
-gst_mpeg2dec_get_formats (GstPad * pad)
-{
-  static GstFormat src_formats[] = {
-    GST_FORMAT_BYTES,
-    GST_FORMAT_TIME,
-    GST_FORMAT_DEFAULT,
-    0
-  };
-  static GstFormat sink_formats[] = {
-    GST_FORMAT_BYTES,
-    GST_FORMAT_TIME,
-    0
-  };
-
-  return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
-}
-#endif
-
-
 static GstCaps *
 gst_mpeg2dec_src_getcaps (GstPad * pad)
 {
@@ -1372,13 +1067,9 @@ gst_mpeg2dec_src_query (GstPad * pad, GstQuery * query)
       gst_query_parse_position (query, &format, NULL);
 
       /* and convert to the requested format */
-      if (format != GST_FORMAT_DEFAULT) {
-        if (!gst_mpeg2dec_src_convert (pad, GST_FORMAT_DEFAULT,
-                mpeg2dec->next_time, &format, &cur))
-          goto error;
-      } else {
-        cur = mpeg2dec->next_time;
-      }
+      if (!gst_mpeg2dec_src_convert (pad, GST_FORMAT_TIME,
+              mpeg2dec->next_time, &format, &cur))
+        goto error;
 
       gst_query_set_position (query, format, cur);
 
@@ -1393,41 +1084,39 @@ gst_mpeg2dec_src_query (GstPad * pad, GstQuery * query)
       gint64 total, total_bytes;
       GstPad *peer;
 
+      if ((peer = gst_pad_get_peer (mpeg2dec->sinkpad)) == NULL)
+        goto error;
+
+      /* send to peer */
+      if ((res = gst_pad_query (peer, query))) {
+        gst_object_unref (peer);
+        goto done;
+      } else {
+        GST_LOG_OBJECT (mpeg2dec, "query on peer pad failed, trying bytes");
+      }
+
       /* save requested format */
       gst_query_parse_duration (query, &format, NULL);
 
       /* query peer for total length in bytes */
       gst_query_set_duration (query, GST_FORMAT_BYTES, -1);
 
-      if ((peer = gst_pad_get_peer (mpeg2dec->sinkpad)) == NULL)
-        goto error;
-
-      if (!gst_pad_query (peer, query)) {
+      if (!(res = gst_pad_query (peer, query))) {
         GST_LOG_OBJECT (mpeg2dec, "query on peer pad failed");
+        gst_object_unref (peer);
         goto error;
       }
       gst_object_unref (peer);
 
       /* get the returned format */
       gst_query_parse_duration (query, &rformat, &total_bytes);
-      if (rformat == GST_FORMAT_BYTES)
-        GST_LOG_OBJECT (mpeg2dec, "peer pad returned total=%lld bytes",
-            total_bytes);
-      else if (rformat == GST_FORMAT_TIME)
-        GST_LOG_OBJECT (mpeg2dec, "peer pad returned time=%lld", total_bytes);
-
-      /* Check if requested format is returned format */
-      if (format == rformat)
-        return TRUE;
+      GST_LOG_OBJECT (mpeg2dec, "peer pad returned total=%lld bytes",
+          total_bytes);
 
       if (total_bytes != -1) {
-        if (format != GST_FORMAT_BYTES) {
-          if (!gst_mpeg2dec_sink_convert (pad, GST_FORMAT_BYTES, total_bytes,
-                  &format, &total))
-            goto error;
-        } else {
-          total = total_bytes;
-        }
+        if (!gst_mpeg2dec_sink_convert (pad, GST_FORMAT_BYTES, total_bytes,
+                &format, &total))
+          goto error;
       } else {
         total = -1;
       }
@@ -1442,6 +1131,7 @@ gst_mpeg2dec_src_query (GstPad * pad, GstQuery * query)
       res = FALSE;
       break;
   }
+done:
   return res;
 
 error:
@@ -1597,44 +1287,6 @@ normal_seek (GstPad * pad, GstEvent * event)
     /* do the seek */
     res = gst_pad_push_event (mpeg2dec->sinkpad, seek_event);
   }
-#if 0
-
-  /* get our peer formats */
-  if (GST_PAD_PEER (mpeg2dec->sinkpad))
-    peer_formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad));
-
-  /* while we did not exhaust our seek formats without result */
-  while (peer_formats && *peer_formats) {
-    gint64 desired_offset;
-
-    format = *peer_formats;
-
-    /* try to convert requested format to one we can seek with on the sinkpad */
-    if (gst_mpeg2dec_sink_convert (mpeg2dec->sinkpad, GST_FORMAT_TIME,
-            src_offset, &format, &desired_offset)) {
-      GstEvent *seek_event;
-
-      /* conversion succeeded, create the seek */
-      seek_event =
-          gst_event_new_seek (format | GST_SEEK_METHOD_SET | flush,
-          desired_offset);
-      /* do the seekk */
-      if (gst_pad_send_event (GST_PAD_PEER (mpeg2dec->sinkpad), seek_event)) {
-        /* seek worked, we're done, loop will exit */
-        res = TRUE;
-        break;
-      }
-    }
-    peer_formats++;
-  }
-  /* at this point, either the seek worked and res = TRUE or res == FALSE and the seek
-   * failed */
-  if (res && flush) {
-    /* if we need to flush, iterate until the buffer is empty */
-    gst_mpeg2dec_flush_decoder (mpeg2dec);
-  }
-#endif
-
   return res;
 
   /* ERRORS */
@@ -1650,7 +1302,7 @@ convert_failed:
 static gboolean
 gst_mpeg2dec_src_event (GstPad * pad, GstEvent * event)
 {
-  gboolean res = TRUE;
+  gboolean res;
   GstMpeg2dec *mpeg2dec;
 
   mpeg2dec = GST_MPEG2DEC (GST_PAD_PARENT (pad));
@@ -1661,27 +1313,19 @@ gst_mpeg2dec_src_event (GstPad * pad, GstEvent * event)
   switch (GST_EVENT_TYPE (event)) {
       /* the all-formats seek logic */
     case GST_EVENT_SEEK:
-      if (mpeg2dec->need_sequence) {
-        mpeg2dec->pending_event = event;
-        return TRUE;
-      } else {
-        if (mpeg2dec->index)
-          res = index_seek (pad, event);
-        else
-          res = normal_seek (pad, event);
+      if (mpeg2dec->index)
+        res = index_seek (pad, event);
+      else
+        res = normal_seek (pad, event);
 
-        if (res)
-          mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
-      }
+      gst_event_unref (event);
       break;
     case GST_EVENT_NAVIGATION:
       /* Forward a navigation event unchanged */
-      return gst_pad_push_event (mpeg2dec->sinkpad, event);
     default:
-      res = FALSE;
+      res = gst_pad_push_event (mpeg2dec->sinkpad, event);
       break;
   }
-  gst_event_unref (event);
   return res;
 }
 
@@ -1693,9 +1337,12 @@ gst_mpeg2dec_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
+      mpeg2_accel (MPEG2_ACCEL_DETECT);
+      if ((mpeg2dec->decoder = mpeg2_init ()) == NULL)
+        goto init_failed;
+      mpeg2dec->info = mpeg2_info (mpeg2dec->decoder);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
-      mpeg2dec->next_time = 0;
       gst_mpeg2dec_reset (mpeg2dec);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
@@ -1709,14 +1356,26 @@ gst_mpeg2dec_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       break;
     case GST_STATE_CHANGE_PAUSED_TO_READY:
-      gst_mpeg2dec_close_decoder (mpeg2dec);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
+      if (mpeg2dec->decoder) {
+        mpeg2_close (mpeg2dec->decoder);
+        mpeg2dec->decoder = NULL;
+        mpeg2dec->info = NULL;
+      }
       break;
     default:
       break;
   }
   return ret;
+
+  /* ERRORS */
+init_failed:
+  {
+    GST_ELEMENT_ERROR (mpeg2dec, LIBRARY, INIT,
+        (NULL), ("Failed to initialize libmpeg2 library"));
+    return GST_STATE_CHANGE_FAILURE;
+  }
 }
 
 static void
index 14434d748432aaccc77f2025b6ec20a67f998727..7d8c7ba8814bf90186e2be59cc7e55b804f27877 100644 (file)
@@ -70,6 +70,8 @@ struct _GstMpeg2dec {
                *userdatapad;
 
   mpeg2dec_t   *decoder;
+  const mpeg2_info_t *info;
+
   gboolean      closed;
   gboolean      have_fbuf;