[gst-devel] bytestream

vishnu at pobox.com vishnu at pobox.com
Sat Sep 29 09:15:05 CEST 2001


The attached bytestream patch fixes a few memory leaks.  i've tested
it with my mpeg2 video player.  Omega didn't like the inline functions,
so if someone converts those back to macros then you can probably check
this in to cvs.  Check with Omega first, though.  ;-)

-- 
Victory to the Divine Mother!!
  http://sahajayoga.org
-------------- next part --------------
diff -up 'gst.head/libs/bytestream/gstbytestream.c' 'events1/libs/bytestream/gstbytestream.c'
Index: ././libs/bytestream/gstbytestream.c
--- ././libs/bytestream/gstbytestream.c	Fri Sep 28 22:09:31 2001
+++ ././libs/bytestream/gstbytestream.c	Fri Sep 28 21:46:09 2001
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) 2001 Erik Walthinsen <omega at temple-baptist.com>
+ *               2001 Joshua N Pritikin <jpritikin at pobox.com>
  *
  * gstbytestream.c: adds a convenient bytestream based API to a pad.
  *
@@ -37,7 +38,28 @@
 #endif
 
 //static void gst_bytestream_print_status(GstByteStream *bs);
-guint8 *gst_bytestream_assemble (GstByteStream * bs, guint32 len);
+
+struct _GstByteStream {
+  GstPad *pad;
+
+  GSList *buflist;
+  guint32 listavail;  // sum of bytes - flushed
+  guint32 flushed;    // offset to first byte in first buffer
+  GstBuffer *peek;
+};
+
+static inline GstBuffer *
+_headbuf (GstByteStream *bs)
+{
+  return GST_BUFFER (bs->buflist->data);
+}
+
+static inline guint32
+_headbufavail (GstByteStream *bs)
+{
+  g_return_val_if_fail (bs->buflist, 0);
+  return GST_BUFFER_SIZE (_headbuf(bs)) - bs->flushed;
+}
 
 /**
  * gst_bytestream_new:
@@ -55,8 +77,8 @@ gst_bytestream_new (GstPad * pad)
   bs->pad = pad;   // need to refcnt?
 
   bs->buflist = NULL;
-  bs->headbufavail = 0;
   bs->listavail = 0;
+  bs->peek = NULL;
 
   return bs;
 }
@@ -74,6 +96,9 @@ gst_bytestream_destroy (GstByteStream * 
     walk = g_slist_next (walk);
   }
 
+  if (bs->peek)
+    gst_buffer_unref (bs->peek);
+
   g_slist_free (bs->buflist);
   g_free (bs);
 }
@@ -169,11 +194,6 @@ gst_bytestream_get_next_buf (GstByteStre
       // add to the length of the list
       bs->listavail += GST_BUFFER_SIZE (nextbuf);
 
-      // have to check to see if we merged with the head buffer
-      if (end == bs->buflist) {
-	bs->headbufavail += GST_BUFFER_SIZE (nextbuf);
-      }
-
       gst_buffer_unref (lastbuf);
       gst_buffer_unref (nextbuf);
 
@@ -194,8 +214,7 @@ gst_bytestream_get_next_buf (GstByteStre
     bs->buflist = g_slist_append (bs->buflist, nextbuf);
     // and increment the number of bytes in the list
     bs->listavail = GST_BUFFER_SIZE (nextbuf);
-    // set the head buffer avail to the size
-    bs->headbufavail = GST_BUFFER_SIZE (nextbuf);
+    bs->flushed = 0;
   }
 
   return TRUE;
@@ -215,138 +234,116 @@ gst_bytestream_fill_bytes (GstByteStream
   return TRUE;
 }
 
-
-GstBuffer *
-gst_bytestream_peek_loc (GST_WHERE_ARGS_ GstByteStream * bs, guint32 len)
+static void
+gst_bytestream_assemble (GstByteStream * bs, guint32 len)
 {
-  GstBuffer *headbuf, *retbuf = NULL;
+  guint8 *data;
+  GSList *walk;
+  gint64 timestamp;
+  guint32 copied;
+  GstBuffer *buf;
 
-  g_return_val_if_fail (bs != NULL, NULL);
-  g_return_val_if_fail (len > 0, NULL);
+  // It would be nice to round len up to a 32 byte multiple
+  // but it seems dangerous in view of eos conditions.
 
-  bs_print ("peek: asking for %d bytes\n", len);
+  // g_assert (len <= bs->listavail);
+  // g_assert (len > _headbufavail(bs));
 
-  // make sure we have enough
-  bs_print ("peek: there are %d bytes in the list\n", bs->listavail);
-  if (len > bs->listavail) {
-    if (!gst_bytestream_fill_bytes (bs, len))
-      return NULL;
-    bs_print ("peek: there are now %d bytes in the list\n", bs->listavail);
-  }
-  bs_status (bs);
+  data = g_malloc (len);
 
-  // extract the head buffer
-  headbuf = GST_BUFFER (bs->buflist->data);
+  if (bs->peek)
+    {
+      // This is an extremely unlikely branch.
+      // if (GST_BUFFER_SIZE (bs->peek) <= len) return;
 
-  // if the requested bytes are in the current buffer
-  bs_print ("peek: headbufavail is %d\n", bs->headbufavail);
-  if (len <= bs->headbufavail) {
-    bs_print ("peek: there are enough bytes in headbuf (need %d, have %d)\n", len, bs->headbufavail);
-    // create a sub-buffer of the headbuf
-    retbuf = gst_buffer_create_sub_loc (GST_WHERE_VARS_ headbuf, GST_BUFFER_SIZE (headbuf) - bs->headbufavail, len);
+      gst_buffer_unref (bs->peek);
+      bs->peek = NULL;
+    }
 
-    // otherwise we need to figure out how to assemble one
-  }
-  else {
-    bs_print ("peek: current buffer is not big enough for len %d\n", len);
+  // copy the data from the curbuf
+  buf = _headbuf(bs);
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
+
+  copied = _headbufavail (bs);
+  memcpy (data, GST_BUFFER_DATA (buf) + bs->flushed, copied);
+
+  // enough buffers will exist in the list
 
-    retbuf = gst_buffer_new_loc (GST_WHERE_VARS);
-    GST_BUFFER_SIZE (retbuf) = len;
-    GST_BUFFER_DATA (retbuf) = gst_bytestream_assemble (bs, len);
-    if (GST_BUFFER_OFFSET (headbuf) != -1)
-      GST_BUFFER_OFFSET (retbuf) = GST_BUFFER_OFFSET (headbuf) + (GST_BUFFER_SIZE (headbuf) - bs->headbufavail);
+  walk = g_slist_next (bs->buflist);
+  while (copied < len) {
+    g_assert (walk);
+
+    buf = GST_BUFFER (walk->data);
+    if (GST_BUFFER_SIZE (buf) < (len - copied)) {
+      bs_print ("assemble: copying %d bytes from buf to output offset %d\n", GST_BUFFER_SIZE (buf), copied);
+      memcpy (data + copied, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+      copied += GST_BUFFER_SIZE (buf);
+    }
+    else {
+      bs_print ("assemble: copying %d bytes from buf to output offset %d\n", len - copied, copied);
+      memcpy (data + copied, GST_BUFFER_DATA (buf), len - copied);
+      copied = len;
+    }
+    walk = g_slist_next (walk);
   }
 
-  return retbuf;
+  buf = gst_buffer_new ();
+  GST_BUFFER_DATA (buf) = data;
+  GST_BUFFER_SIZE (buf) = copied;
+  GST_BUFFER_TIMESTAMP (buf) = timestamp;
+  bs->peek = buf;
 }
 
-guint8 *
-gst_bytestream_peek_bytes (GstByteStream * bs, guint32 len)
+GstBuffer *
+gst_bytestream_peek_loc (GST_WHERE_ARGS_ GstByteStream * bs, guint32 len)
 {
-  GstBuffer *headbuf;
-  guint8 *data = NULL;
-
-  g_return_val_if_fail (bs != NULL, NULL);
+  g_return_val_if_fail (bs, NULL);
   g_return_val_if_fail (len > 0, NULL);
 
-  bs_print ("peek_bytes: asking for %d bytes\n", len);
-
   // make sure we have enough
-  bs_print ("peek_bytes: there are %d bytes in the list\n", bs->listavail);
   if (len > bs->listavail) {
     if (!gst_bytestream_fill_bytes (bs, len))
       return NULL;
-    bs_print ("peek_bytes: there are now %d bytes in the list\n", bs->listavail);
+    bs_print ("peek: there are now %d bytes in the list\n", bs->listavail);
   }
-  bs_status (bs);
 
-  // extract the head buffer
-  headbuf = GST_BUFFER (bs->buflist->data);
+  if (len <= _headbufavail (bs))
+    return gst_buffer_create_sub_loc (GST_WHERE_VARS_
+				      _headbuf(bs), bs->flushed, len);
 
-  // if the requested bytes are in the current buffer
-  bs_print ("peek_bytes: headbufavail is %d\n", bs->headbufavail);
-  if (len <= bs->headbufavail) {
-    bs_print ("peek_bytes: there are enough bytes in headbuf (need %d, have %d)\n", len, bs->headbufavail);
-    // create a sub-buffer of the headbuf
-    data = GST_BUFFER_DATA (headbuf) + (GST_BUFFER_SIZE (headbuf) - bs->headbufavail);
+  gst_bytestream_assemble (bs, len);
 
-    // otherwise we need to figure out how to assemble one
-  }
-  else {
-    bs_print ("peek_bytes: current buffer is not big enough for len %d\n", len);
-
-    data = gst_bytestream_assemble (bs, len);
-  }
+  gst_buffer_ref (bs->peek);
 
-  return data;
+  return bs->peek;
 }
 
 guint8 *
-gst_bytestream_assemble (GstByteStream * bs, guint32 len)
+gst_bytestream_peek_bytes (GstByteStream * bs, guint32 len)
 {
-  guint8 *data = g_malloc (len);
-  GSList *walk;
-  guint32 copied = 0;
-  GstBuffer *buf;
-
-  g_assert (len <= bs->listavail);
-
-  // copy the data from the curbuf
-  buf = GST_BUFFER (bs->buflist->data);
-  bs_print ("assemble: copying %d bytes from curbuf at %d to *data\n", bs->headbufavail,
-	    GST_BUFFER_SIZE (buf) - bs->headbufavail);
-  memcpy (data, GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf) - bs->headbufavail, bs->headbufavail);
-  copied += bs->headbufavail;
-
-  // asumption is made that the buffers all exist in the list
-  walk = g_slist_next (bs->buflist);
-  while (copied < len) {
-    g_assert (walk);
+  g_return_val_if_fail (bs, NULL);
+  g_return_val_if_fail (len > 0, NULL);
 
-    buf = GST_BUFFER (walk->data);
-    if (GST_BUFFER_SIZE (buf) < (len - copied)) {
-      bs_print ("assemble: copying %d bytes from buf to output offset %d\n", GST_BUFFER_SIZE (buf), copied);
-      memcpy (data + copied, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
-      copied += GST_BUFFER_SIZE (buf);
-    }
-    else {
-      bs_print ("assemble: copying %d bytes from buf to output offset %d\n", len - copied, copied);
-      memcpy (data + copied, GST_BUFFER_DATA (buf), len - copied);
-      copied = len;
-    }
-    walk = g_slist_next (walk);
+  // make sure we have enough
+  if (len > bs->listavail) {
+    if (!gst_bytestream_fill_bytes (bs, len))
+      return NULL;
+    bs_print ("peek: there are now %d bytes in the list\n", bs->listavail);
   }
 
-  return data;
+  if (len <= _headbufavail (bs))
+    return GST_BUFFER_DATA (_headbuf (bs)) + bs->flushed;
+    
+  gst_bytestream_assemble (bs, len);
+
+  return GST_BUFFER_DATA (bs->peek);
 }
 
 gboolean
 gst_bytestream_flush (GstByteStream * bs, guint32 len)
 {
-  bs_print ("flush: flushing %d bytes\n", len);
+  bs_print ("flush: flushing %d of %d bytes\n", len, bs->listavail);
 
-  // make sure we have enough
-  bs_print ("flush: there are %d bytes in the list\n", bs->listavail);
   if (len > bs->listavail) {
     if (!gst_bytestream_fill_bytes (bs, len))
       {
@@ -369,41 +366,39 @@ gst_bytestream_flush_fast (GstByteStream
   g_return_if_fail (bs);
   g_assert (len <= bs->listavail);
 
+  if (bs->peek)
+    {
+      gst_buffer_unref (bs->peek);
+      bs->peek = NULL;
+    }
+
   while (len > 0) {
     headbuf = GST_BUFFER (bs->buflist->data);
 
     bs_print ("flush: analyzing buffer that's %d bytes long, offset %d\n", GST_BUFFER_SIZE (headbuf),
 	      GST_BUFFER_OFFSET (headbuf));
 
-    // if there's enough to complete the flush
-    if (bs->headbufavail > len) {
-      // just trim it off
+    if (_headbufavail (bs) > len) {
+      // if there's enough to complete the flush
+
       bs_print ("flush: trimming %d bytes off end of headbuf\n", len);
-      bs->headbufavail -= len;
       bs->listavail -= len;
-      len = 0;
+      bs->flushed += len;
+
+      return;
 
+    } else {
       // otherwise we have to trim the whole buffer
-    }
-    else {
+
       bs_print ("flush: removing head buffer completely\n");
-      // remove it from the list
+
+      bs->listavail -= _headbufavail (bs);
+      len -= _headbufavail (bs);
+
       bs->buflist = g_slist_delete_link (bs->buflist, bs->buflist);
-      // trim it from the avail size
-      bs->listavail -= bs->headbufavail;
-      // record that we've trimmed this many bytes
-      len -= bs->headbufavail;
-      // unref it
       gst_buffer_unref (headbuf);
 
-      // record the new headbufavail
-      if (bs->buflist) {
-	bs->headbufavail = GST_BUFFER_SIZE (GST_BUFFER (bs->buflist->data));
-	bs_print ("flush: next headbuf is %d bytes\n", bs->headbufavail);
-      }
-      else {
-	bs_print ("flush: no more bytes at all\n");
-      }
+      bs->flushed = 0;
     }
 
     bs_print ("flush: bottom of while(), len is now %d\n", len);
@@ -425,7 +420,7 @@ gst_bytestream_print_status (GstByteStre
   GSList *walk;
   GstBuffer *buf;
 
-  bs_print ("STATUS: head buffer has %d bytes available\n", bs->headbufavail);
+  bs_print ("STATUS: head buffer has %d bytes available\n", _headbufavail(bs));
   bs_print ("STATUS: list has %d bytes available\n", bs->listavail);
   walk = bs->buflist;
   while (walk) {
diff -up 'gst.head/libs/bytestream/gstbytestream.h' 'events1/libs/bytestream/gstbytestream.h'
Index: ././libs/bytestream/gstbytestream.h
--- ././libs/bytestream/gstbytestream.h	Fri Sep 28 22:09:31 2001
+++ ././libs/bytestream/gstbytestream.h	Fri Sep 28 16:50:33 2001
@@ -28,14 +28,6 @@ extern "C" {
 
 typedef struct _GstByteStream GstByteStream;
 
-struct _GstByteStream {
-  GstPad *pad;
-
-  GSList *buflist;
-  guint32 headbufavail;
-  guint32 listavail;
-};
-
 GstByteStream*		gst_bytestream_new		(GstPad *pad);
 void			gst_bytestream_destroy		(GstByteStream *bs);
 


More information about the gstreamer-devel mailing list