ext/libpng/gstpngenc.*: Preallocate the output buffer so that g_memdup() and gst_buff...
authorAlessandro Decina <alessandro@nnva.org>
Tue, 29 Jan 2008 18:43:32 +0000 (18:43 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Tue, 29 Jan 2008 18:43:32 +0000 (18:43 +0000)
Original commit message from CVS:
Patch by: Alessandro Decina <alessandro at nnva dot org>
* ext/libpng/gstpngenc.c: (user_write_data), (gst_pngenc_chain):
* ext/libpng/gstpngenc.h:
Preallocate the output buffer so that g_memdup() and
gst_buffer_merge() aren't needed anymore. This greatly improves
performances and fixes #512544.

ChangeLog
ext/libpng/gstpngenc.c
ext/libpng/gstpngenc.h

index 984a2ad..d8471ed 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2008-01-29  Wim Taymans  <wim.taymans@collabora.co.uk>
 
+       Patch by: Alessandro Decina <alessandro at nnva dot org>
+
+       * ext/libpng/gstpngenc.c: (user_write_data), (gst_pngenc_chain):
+       * ext/libpng/gstpngenc.h:
+       Preallocate the output buffer so that g_memdup() and
+       gst_buffer_merge() aren't needed anymore. This greatly improves
+       performances and fixes #512544.
+
+2008-01-29  Wim Taymans  <wim.taymans@collabora.co.uk>
+
        * gst/avi/gstavidemux.c: (gst_avi_demux_process_next_entry),
        (gst_avi_demux_stream_data):
        GStreamer timestamps are PTS values while AVI only knows about DTS
index 0ca9bb3..1d26ef7 100644 (file)
@@ -222,25 +222,21 @@ user_flush_data (png_structp png_ptr)
 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->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);
 
-  if (pngenc->buffer_out) {
-    GstBuffer *merge;
+    /* 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 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf)
   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 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf)
         (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 @@ gst_pngenc_chain (GstPad * pad, GstBuffer * buf)
 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 571d16f..848d15e 100644 (file)
@@ -44,6 +44,7 @@ struct _GstPngEnc
 
   GstPad *sinkpad, *srcpad;
   GstBuffer *buffer_out;
+  guint written;
 
   png_structp png_struct_ptr;
   png_infop png_info_ptr;