? .gstpngenc.c.swp
? a.png
? b.png
Index: gstpngenc.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-good/ext/libpng/gstpngenc.c,v
retrieving revision 1.47
diff -u -r1.47 gstpngenc.c
--- gstpngenc.c	20 Nov 2007 12:11:13 -0000	1.47
+++ gstpngenc.c	28 Jan 2008 11:17:04 -0000
@@ -222,25 +222,21 @@
 static void
 user_write_data (png_structp png_ptr, png_bytep data, png_uint_32 length)
 {
-  GstBuffer *buffer;
   GstPngEnc *pngenc;
 
   pngenc = (GstPngEnc *) png_get_io_ptr (png_ptr);
 
-  buffer = gst_buffer_new ();
-  GST_BUFFER_MALLOCDATA (buffer) = g_memdup (data, length);
-  GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
-  GST_BUFFER_SIZE (buffer) = length;
-
-  if (pngenc->buffer_out) {
-    GstBuffer *merge;
+  if (pngenc->written + length >= GST_BUFFER_SIZE (pngenc->buffer_out)) {
+    GST_ERROR_OBJECT (pngenc, "output buffer bigger than the input buffer!?");
+    /* yuck */
+    longjmp (pngenc->png_struct_ptr->jmpbuf, 1);
+    
+    /* never reached */
+    return;
+  }
 
-    merge = gst_buffer_merge (pngenc->buffer_out, buffer);
-    gst_buffer_unref (buffer);
-    gst_buffer_unref (pngenc->buffer_out);
-    pngenc->buffer_out = merge;
-  } else
-    pngenc->buffer_out = buffer;
+  memcpy (GST_BUFFER_DATA (pngenc->buffer_out) + pngenc->written, data, length);
+  pngenc->written += length;
 }
 
 static GstFlowReturn
@@ -250,13 +246,12 @@
   gint row_index;
   png_byte *row_pointers[MAX_HEIGHT];
   GstFlowReturn ret = GST_FLOW_OK;
+  GstBuffer *encoded_buf = NULL;
 
   pngenc = GST_PNGENC (gst_pad_get_parent (pad));
 
   GST_DEBUG_OBJECT (pngenc, "BEGINNING");
 
-  pngenc->buffer_out = NULL;
-
   /* initialize png struct stuff */
   pngenc->png_struct_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
       (png_voidp) NULL, user_error_fn, user_warning_fn);
@@ -309,20 +304,26 @@
         (row_index * pngenc->stride);
   }
 
+  /* allocate the output buffer */
+  pngenc->buffer_out =
+      gst_buffer_new_and_alloc (pngenc->height * pngenc->stride);
+  pngenc->written = 0;
+
   png_write_info (pngenc->png_struct_ptr, pngenc->png_info_ptr);
   png_write_image (pngenc->png_struct_ptr, row_pointers);
   png_write_end (pngenc->png_struct_ptr, NULL);
 
   user_flush_data (pngenc->png_struct_ptr);
 
+  encoded_buf = gst_buffer_create_sub (pngenc->buffer_out, 0, pngenc->written);
+
   png_destroy_info_struct (pngenc->png_struct_ptr, &pngenc->png_info_ptr);
   png_destroy_write_struct (&pngenc->png_struct_ptr, (png_infopp) NULL);
-  gst_buffer_copy_metadata (pngenc->buffer_out, buf,
-      GST_BUFFER_COPY_TIMESTAMPS);
+  gst_buffer_copy_metadata (encoded_buf, buf, GST_BUFFER_COPY_TIMESTAMPS);
   gst_buffer_unref (buf);
-  gst_buffer_set_caps (pngenc->buffer_out, GST_PAD_CAPS (pngenc->srcpad));
+  gst_buffer_set_caps (encoded_buf, GST_PAD_CAPS (pngenc->srcpad));
 
-  if ((ret = gst_pad_push (pngenc->srcpad, pngenc->buffer_out)) != GST_FLOW_OK)
+  if ((ret = gst_pad_push (pngenc->srcpad, encoded_buf)) != GST_FLOW_OK)
     goto done;
 
   if (pngenc->snapshot) {
@@ -339,6 +340,11 @@
 done:
   GST_DEBUG_OBJECT (pngenc, "END, ret:%d", ret);
 
+  if (pngenc->buffer_out != NULL) {
+    gst_buffer_unref (pngenc->buffer_out);
+    pngenc->buffer_out = NULL;
+  }
+
   gst_object_unref (pngenc);
   return ret;
 }
Index: gstpngenc.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-good/ext/libpng/gstpngenc.h,v
retrieving revision 1.11
diff -u -r1.11 gstpngenc.h
--- gstpngenc.h	27 Oct 2006 17:10:42 -0000	1.11
+++ gstpngenc.h	28 Jan 2008 11:17:04 -0000
@@ -44,6 +44,7 @@
 
   GstPad *sinkpad, *srcpad;
   GstBuffer *buffer_out;
+  guint written;
 
   png_structp png_struct_ptr;
   png_infop png_info_ptr;
