[gst-devel] non-leaky bytestream

vishnu at pobox.com vishnu at pobox.com
Fri Sep 28 18:24:02 CEST 2001


Oops, the previous patch was still leaky.  How about this one?

-- 
Victory to the Divine Mother!!
  http://sahajayoga.org
-------------- next part --------------
? bs
Index: gstbytestream.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/libs/bytestream/Attic/gstbytestream.c,v
retrieving revision 1.1.2.13
diff -u -p -r1.1.2.13 gstbytestream.c
--- gstbytestream.c	2001/09/28 22:58:38	1.1.2.13
+++ gstbytestream.c	2001/09/29 01:21:54
@@ -37,8 +37,29 @@
 #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:
  * @pad: the pad to attach the bytestream to
@@ -55,8 +76,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 +95,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 +193,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 +213,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;
@@ -214,139 +232,114 @@ 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;
+  // pad len to 32 align XXX
 
-  g_return_val_if_fail (bs != NULL, NULL);
-  g_return_val_if_fail (len > 0, NULL);
+  guint8 *data = g_malloc (len);
+  GSList *walk;
+  gint64 timestamp;
+  guint32 copied;
+  GstBuffer *buf;
 
-  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);
+  if (bs->peek)
+    {
+      if (GST_BUFFER_SIZE (bs->peek) <= len)
+	return;
 
-  // extract the head buffer
-  headbuf = GST_BUFFER (bs->buflist->data);
+      gst_buffer_unref (bs->peek);
+      bs->peek = NULL;
+    }
 
-  // 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);
+  // copy the data from the curbuf
+  buf = _headbuf(bs);
+  timestamp = GST_BUFFER_TIMESTAMP (buf);
 
-    // 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);
+  copied = _headbufavail (bs);
+  memcpy (data, GST_BUFFER_DATA (buf) + bs->flushed, copied);
 
-    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);
+  // enough buffers will exist in the list
+
+  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);
   }
+
+  if (len <= _headbufavail (bs))
+    return GST_BUFFER_DATA (_headbuf (bs)) + bs->flushed;
+    
+  gst_bytestream_assemble (bs, len);
 
-  return data;
+  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 +362,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 +416,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) {
Index: gstbytestream.h
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/libs/bytestream/Attic/gstbytestream.h,v
retrieving revision 1.1.2.8
diff -u -p -r1.1.2.8 gstbytestream.h
--- gstbytestream.h	2001/09/28 22:58:38	1.1.2.8
+++ gstbytestream.h	2001/09/29 01:21:54
@@ -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