After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 706083 - v4l2src: UVC Allocated buffers wrapped in GstBuffer get orphaned by GstBuffer API
v4l2src: UVC Allocated buffers wrapped in GstBuffer get orphaned by GstBuffer...
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-good
git master
Other Linux
: Normal blocker
: 1.2.0
Assigned To: GStreamer Maintainers
GStreamer Maintainers
: 699517 706069 (view as bug list)
Depends on: 707534
Blocks:
 
 
Reported: 2013-08-15 19:08 UTC by Robert Krakora
Modified: 2013-09-23 16:05 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Fix for orphaned UVC driver allocated buffers in v4l2src... (790 bytes, patch)
2013-08-15 19:08 UTC, Robert Krakora
reviewed Details | Review
Patch for v4l2src to put back replaced buffer...and fix race condition... (2.99 KB, patch)
2013-08-16 16:05 UTC, Robert Krakora
none Details | Review
Patch for v4l2src to put back replaced buffer...and fix race condition... (3.36 KB, patch)
2013-08-16 16:27 UTC, Robert Krakora
none Details | Review
Patch for v4l2src to put back replaced buffer...and fix race condition... (3.48 KB, patch)
2013-08-16 16:33 UTC, Robert Krakora
none Details | Review
Patch for v4l2src to put back replaced buffer...and fix race condition... (3.58 KB, patch)
2013-08-16 19:02 UTC, Robert Krakora
none Details | Review
Patch for v4l2src to put back replaced buffer...and fix race condition... (3.69 KB, patch)
2013-08-16 22:05 UTC, Robert Krakora
none Details | Review
Patch for v4l2src to put back replaced buffer...and fix race condition... (6.09 KB, patch)
2013-08-17 19:07 UTC, Robert Krakora
none Details | Review
Git formatted patch to address this bug... (6.74 KB, patch)
2013-08-19 19:23 UTC, Robert Krakora
needs-work Details | Review
Git Formatted Patch (6.40 KB, patch)
2013-09-19 14:57 UTC, Robert Krakora
needs-work Details | Review
Git Formatted Patch Revised (5.12 KB, patch)
2013-09-19 20:36 UTC, Robert Krakora
none Details | Review
v4l2bufferpool: Restore original GstMemory in buffer if it has been changed (3.51 KB, patch)
2013-09-19 21:42 UTC, Olivier Crête
committed Details | Review

Description Robert Krakora 2013-08-15 19:08:02 UTC
Created attachment 251764 [details] [review]
Fix for orphaned UVC driver allocated buffers in v4l2src...

So, I was able to "fix" an issue with v4l2src UVC driver allocated buffers
being replaced (orphaned) by the GstBuffer API (gst_buffer_resize() for
example) with the patch below which "puts back" the UVC driver allocated
buffers to the GstBuffers in which they were initially placed when allocated
and wrapped in a GstMemory object.

diff -rupN gst-plugins-good-1.1.3/sys/v4l2/gstv4l2bufferpool.c
gst-plugins-good-1.1.3.new/sys/v4l2/gstv4l2bufferpool.c
--- gst-plugins-good-1.1.3/sys/v4l2/gstv4l2bufferpool.c    2013-07-08
10:27:16.000000000 -0400
+++ gst-plugins-good-1.1.3.new/sys/v4l2/gstv4l2bufferpool.c    2013-08-14
17:21:42.801320440 -0400
@@ -678,6 +678,12 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2Buffer
   if (v4l2_ioctl (pool->video_fd, VIDIOC_QBUF, &meta->vbuffer) < 0)
     goto queue_failed;

+  /* Memory may have been replaced in GstBuffer so put it back using meta
cookie */
+  gst_buffer_replace_memory (buf, 0,
+    gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
+        meta->mem, meta->vbuffer.length, 0, meta->vbuffer.length, NULL,
+        NULL));
+
   pool->buffers[index] = buf;
   pool->num_queued++;
Comment 1 Tim-Philipp Müller 2013-08-15 19:18:54 UTC
*** Bug 706069 has been marked as a duplicate of this bug. ***
Comment 2 Sebastian Dröge (slomo) 2013-08-16 07:51:39 UTC
This is also in bug #699517, should we continue this patch here or there? See my comments there (comment 35).
Comment 3 Olivier Crête 2013-08-16 14:48:02 UTC
Isn't the real solution here to eliminate the custom bufferpool entirely ?
Comment 4 Robert Krakora 2013-08-16 14:54:53 UTC
Would that mean copying the v4l2 driver allocated user space mapped buffers to freshly allocated memory?  Seems to be happening anyway implicitly at times via the GstBuffer API resize and map functions.  Is it not desirable to minimize alloc/copy/free in the pipeline to minimize CPU consumption?
Comment 5 Robert Krakora 2013-08-16 16:05:35 UTC
Created attachment 251906 [details] [review]
Patch for v4l2src to put back replaced buffer...and fix race condition...

Through extended 24 hour testing, I found a race condition between dqbuf and qbuf functions that can undermine replacement of original buffer in the qbuf function.  This warranted the introduction of mutex protection in both the aforementioned functions.
Comment 6 Robert Krakora 2013-08-16 16:27:40 UTC
Created attachment 251911 [details] [review]
Patch for v4l2src to put back replaced buffer...and fix race condition...
Comment 7 Robert Krakora 2013-08-16 16:33:11 UTC
Created attachment 251912 [details] [review]
Patch for v4l2src to put back replaced buffer...and fix race condition...

Forgot about some short circuit returns...
Comment 8 Robert Krakora 2013-08-16 19:02:20 UTC
Created attachment 251932 [details] [review]
Patch for v4l2src to put back replaced buffer...and fix race condition...

Moved mutex initialization...
Comment 9 Robert Krakora 2013-08-16 22:05:36 UTC
Created attachment 251955 [details] [review]
Patch for v4l2src to put back replaced buffer...and fix race condition...

Still had mutex messed up...
Comment 10 Robert Krakora 2013-08-17 19:07:47 UTC
Created attachment 252068 [details] [review]
Patch for v4l2src to put back replaced buffer...and fix race condition...

Do GstBuffer memory replacement with resized v4l2 buffer to bytes used wrapped GstMemory object so that it is not replaced with system memory GstMemory object.
Comment 11 Robert Krakora 2013-08-19 19:23:58 UTC
Created attachment 252279 [details] [review]
Git formatted patch to address this bug...
Comment 12 Robert Krakora 2013-08-20 18:21:50 UTC
Does this patch have a chance of making it in to the next release...?  :-)
Comment 13 Olivier Crête 2013-09-05 04:43:29 UTC
*** Bug 699517 has been marked as a duplicate of this bug. ***
Comment 14 Olivier Crête 2013-09-18 17:14:43 UTC
Review of attachment 252279 [details] [review]:

I think we should put something along those lines in 1.2.

::: sys/v4l2/gstv4l2bufferpool.c
@@ +666,2 @@
   index = meta->vbuffer.index;
+  meta->vbuffer.bytesused = 0;

This will break v4l2sink I think, it needs to know how much of the buffer is valid when it is queued.

@@ +675,3 @@
+  if (pool->buffers[index] != NULL) {
+      goto already_queued;
+  }

Why the extra {} ?

@@ +775,3 @@
+        gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
+            meta->mem, vbuffer.bytesused, 0, vbuffer.bytesused, NULL,
+            NULL));

Didn't you already replace the memory when doing the qbuf ?

@@ +894,3 @@
 
+            /* copy the buffer with memory, but not the meta data */
+            copy = gst_buffer_copy_region (*buffer, GST_BUFFER_COPY_MEMORY, 0, -1);

Why not copy the metadata also ? Don't you want GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP ?

::: sys/v4l2/gstv4l2bufferpool.h
@@ +34,2 @@
 #include "gstv4l2object.h"
+#include <gst/glib-compat-private.h>

What are you using from glib-compat-private ?

@@ +67,2 @@
   GstBuffer **buffers;
+  GMutex lock;

Why do you add a new lock here? Any reason to not use the GstObject lock ?
Comment 15 Robert Krakora 2013-09-18 18:41:37 UTC
Review of attachment 252279 [details] [review]:

::: sys/v4l2/gstv4l2bufferpool.c
@@ +666,2 @@
   index = meta->vbuffer.index;
+  meta->vbuffer.bytesused = 0;

You are correct.  Don't know why I did that.

@@ +675,3 @@
+  if (pool->buffers[index] != NULL) {
+      goto already_queued;
+  }

The {} can be removed.

@@ +686,3 @@
   pool->buffers[index] = buf;
   pool->num_queued++;
+  GST_V4L2_BUFFER_POOL_UNLOCK (pool);

GST_V4L2_BUFFER_POOL_UNLOCK (pool) not needed.

@@ +736,3 @@
+  }
+
+  GST_V4L2_BUFFER_POOL_LOCK (pool);

GST_V4L2_BUFFER_POOL_LOCK (pool) not needed.

@@ +743,3 @@
   outbuf = pool->buffers[vbuffer.index];
+  if (outbuf == NULL) {
+    GST_V4L2_BUFFER_POOL_UNLOCK (pool);

GST_V4L2_BUFFER_POOL_UNLOCK (pool) not needed and {} can be removed.

@@ +775,3 @@
+        gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
+            meta->mem, vbuffer.bytesused, 0, vbuffer.bytesused, NULL,
+            NULL));

This resizes without replacing the dequeued buffer as does gst_buffer_resize().  I believe that there is work underway to prevent the replacement of wrapped memory by the GstBuffer class.  This is a temporary workaround.

@@ +784,1 @@
 

GST_V4L2_BUFFER_POOL_UNLOCK (pool) not needed and {} can be removed.

@@ +894,3 @@
 
+            /* copy the buffer with memory, but not the meta data */
+            copy = gst_buffer_copy_region (*buffer, GST_BUFFER_COPY_MEMORY, 0, -1);

Trying to be efficient...gst_buffer_copy() can be used instead as it was in the original source.

* To efficiently create a smaller buffer out of an existing one, you can
 * use gst_buffer_copy_region(). This method tries to share the memory objects
 * between the two buffers.

@@ +1006,3 @@
+                gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
+                    meta->mem, meta->vbuffer.length, 0, meta->vbuffer.length, NULL,
+                    NULL));

This resizes without replacing the dequeued buffer as does gst_buffer_resize().  I believe that there is work underway to prevent the replacement of wrapped memory by the GstBuffer class.  This is a temporary workaround.

@@ +1054,3 @@
 gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
 {
+  g_mutex_init(&pool->lock);

g_mutex_init (&pool->lock) not needed.

::: sys/v4l2/gstv4l2bufferpool.h
@@ +34,2 @@
 #include "gstv4l2object.h"
+#include <gst/glib-compat-private.h>

For the added lock which is not needed.

@@ +67,2 @@
   GstBuffer **buffers;
+  GMutex lock;

It is not needed.

@@ +93,3 @@
 
+#define GST_V4L2_BUFFER_POOL_LOCK(pool)     g_mutex_lock (&(pool)->lock)
+#define GST_V4L2_BUFFER_POOL_UNLOCK(pool)   g_mutex_unlock (&(pool)->lock)

These are not needed.
Comment 16 Olivier Crête 2013-09-18 23:41:49 UTC
Any chance you can provide an updated patch ?

(In reply to comment #15)
> Review of attachment 252279 [details] [review]:
> @@ +775,3 @@
> +        gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
> +            meta->mem, vbuffer.bytesused, 0, vbuffer.bytesused, NULL,
> +            NULL));
> 
> This resizes without replacing the dequeued buffer as does gst_buffer_resize().
>  I believe that there is work underway to prevent the replacement of wrapped
> memory by the GstBuffer class.  This is a temporary workaround.
> 
> @@ +894,3 @@
> 
> +            /* copy the buffer with memory, but not the meta data */
> +            copy = gst_buffer_copy_region (*buffer, GST_BUFFER_COPY_MEMORY, 0,
> -1);
> 
> Trying to be efficient...gst_buffer_copy() can be used instead as it was in the
> original source.

actually, gst_buffer_copy() won't do as it doesn't make a copy of the actual memory, you do want GST_BUFFER_COPY_DEEP

> * To efficiently create a smaller buffer out of an existing one, you can
>  * use gst_buffer_copy_region(). This method tries to share the memory objects
>  * between the two buffers.

You don't want to share the memory, as the next step is to give it back to the driver.

> @@ +1006,3 @@
> +                gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
> +                    meta->mem, meta->vbuffer.length, 0, meta->vbuffer.length,
> NULL,
> +                    NULL));
> 
> This resizes without replacing the dequeued buffer as does gst_buffer_resize().
>  I believe that there is work underway to prevent the replacement of wrapped
> memory by the GstBuffer class.  This is a temporary workaround.

I also think that's the correct workaround as I don't think the rework in bug #707534 can land in time for 1.2
Comment 17 Robert Krakora 2013-09-19 00:31:12 UTC
I will have one for you tomorrow morning after I have tested it, is that OK?
Comment 18 Robert Krakora 2013-09-19 13:19:19 UTC
I am testing the revamped code and will generated a patch after letting it run for a couple of hours...
Comment 19 Robert Krakora 2013-09-19 14:57:14 UTC
Created attachment 255308 [details] [review]
Git Formatted Patch

Here is a revised patch.  I left the lock in as I cannot confirm that it is not needed.  I took all the other suggestions from the patch review.
Comment 20 Olivier Crête 2013-09-19 19:15:54 UTC
Review of attachment 255308 [details] [review]:

::: sys/v4l2/gstv4l2bufferpool.c
@@ +681,2 @@
   index = meta->vbuffer.index;
+  meta->vbuffer.bytesused = meta->vbuffer.length;

Again, this won't work for v4l2sink, you have to leave bytesused to the current buffer size, this is what the application has filled.

@@ +695,3 @@
+    gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
+        meta->mem, meta->vbuffer.length, 0, meta->vbuffer.length, NULL,
+        NULL));

This won't work for v4l2sink if the memory has been changed., but it is broken anyway right now, so it won't hurt more

@@ +794,3 @@
+            meta->mem, vbuffer.bytesused, 0, vbuffer.bytesused, NULL,
+            NULL));
+  }

This shouldn't be needed, the GstMemory should be writable at this point.

@@ +800,2 @@
   *buffer = outbuf;
+  GST_V4L2_BUFFER_POOL_UNLOCK (pool);

Why do you release the lock this late? why not just after decrementing num_queued ?

@@ +912,3 @@
 
+            /* copy the buffer with memory */
+            copy = gst_buffer_copy_region (*buffer, GST_BUFFER_COPY_DEEP, 0, -1);

You want GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, the metadata is also important

@@ -994,3 @@
-            /* reset to the full length, in case it was changed */
-            gst_buffer_resize (buffer, 0, meta->vbuffer.length);
-

In the playback case, why do you remove the resize? The size may have changed..

::: sys/v4l2/gstv4l2bufferpool.h
@@ +34,2 @@
 #include "gstv4l2object.h"
+#include <gst/glib-compat-private.h>

Really, this is not needed even if you add a lock.

@@ +67,2 @@
   GstBuffer **buffers;
+  GMutex lock;

Why not just use GST_OBJECT_LOCK/UNLOCK instead of adding an extra mutex ?
Comment 21 Robert Krakora 2013-09-19 19:47:02 UTC
Review of attachment 255308 [details] [review]:

::: sys/v4l2/gstv4l2bufferpool.c
@@ +681,2 @@
   index = meta->vbuffer.index;
+  meta->vbuffer.bytesused = meta->vbuffer.length;

So, vbuffer.length is the size of the v4l2 buffer and vbuffer.bytesused the actual number of bytes used in the buffer.  So, IMHO, this should be valid.  The meta data obtained from the GstBuffer is used to obtain the length of the vbuffer.

@@ +695,3 @@
+    gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
+        meta->mem, meta->vbuffer.length, 0, meta->vbuffer.length, NULL,
+        NULL));

Why not?

@@ +794,3 @@
+            meta->mem, vbuffer.bytesused, 0, vbuffer.bytesused, NULL,
+            NULL));
+  /* with vbuffer.bytesused as the size and replace the    */

Huh?  gst_buffer_resize() is the problem.  It can replace the wrapped memory object referenced by the GstBuffer with a new one that meets the new size constraint and then the previously wrapped memory object, which wraps a v4l2 buffer, is "lost in space".

@@ +800,2 @@
   *buffer = outbuf;
+  GST_V4L2_BUFFER_POOL_UNLOCK (pool);

Trying to protect the pool structure from being accessed on different thread times.  I am assuming that a buffer can get dequeued on another thread time.

@@ +912,3 @@
 
+            /* copy the buffer with memory */
+            copy = gst_buffer_copy_region (*buffer, GST_BUFFER_COPY_DEEP, 0, -1);

O.K.
Comment 22 Robert Krakora 2013-09-19 19:50:09 UTC
Review of attachment 255308 [details] [review]:

::: sys/v4l2/gstv4l2bufferpool.h
@@ +34,2 @@
 #include "gstv4l2object.h"
+#include <gst/glib-compat-private.h>

Maybe not, but the code would not build without it.  Please suggest an alternative.

@@ +67,2 @@
   GstBuffer **buffers;
+  GMutex lock;

GST_OBJECT_LOCK/UNLOCK is kind of a big mutex for this job.  I took this from the 0.10 v4l2src buffer pool source.
Comment 23 Olivier Crête 2013-09-19 19:53:25 UTC
Actually, I'm pretty sure that you don't need to do any extra locking there.
Comment 24 Robert Krakora 2013-09-19 19:56:30 UTC
OK...I will remove it then.  :-)  I am new to 1.xx framework as I have just recently moved to it after years of working in 0.10 framework.  Also, v4l2sink was not on my mind when I proposed this patch.
Comment 25 Olivier Crête 2013-09-19 20:00:17 UTC
(In reply to comment #21)
> Review of attachment 255308 [details] [review]:
> 
> ::: sys/v4l2/gstv4l2bufferpool.c
> @@ +681,2 @@
>    index = meta->vbuffer.index;
> +  meta->vbuffer.bytesused = meta->vbuffer.length;
> 
> So, vbuffer.length is the size of the v4l2 buffer and vbuffer.bytesused the
> actual number of bytes used in the buffer.  So, IMHO, this should be valid. 
> The meta data obtained from the GstBuffer is used to obtain the length of the
> vbuffer.

In this case, the buffer length is what the application put into it (for v4l2sink), which may be smaller than the allocated buffer.

> @@ +695,3 @@
> +    gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
> +        meta->mem, meta->vbuffer.length, 0, meta->vbuffer.length, NULL,
> +        NULL));
> 
> Why not?

Again in the v4l2sink case, the application has written something in the memory that's in the buffer, so you can't just ignore it.


> @@ +794,3 @@
> +            meta->mem, vbuffer.bytesused, 0, vbuffer.bytesused, NULL,
> +            NULL));
> +  /* with vbuffer.bytesused as the size and replace the    */
> 
> Huh?  gst_buffer_resize() is the problem.  It can replace the wrapped memory
> object referenced by the GstBuffer with a new one that meets the new size
> constraint and then the previously wrapped memory object, which wraps a v4l2
> buffer, is "lost in space".

In this case, it will only shrink the buffer, so that should never happen.

> @@ +800,2 @@
>    *buffer = outbuf;
> +  GST_V4L2_BUFFER_POOL_UNLOCK (pool);
> 
> Trying to protect the pool structure from being accessed on different thread
> times.  I am assuming that a buffer can get dequeued on another thread time.

The same buffers[x] member will only be accessed once you got the buffer back from the kernel, so only that thread owns it at this point.
Comment 26 Robert Krakora 2013-09-19 20:05:22 UTC
>> @@ +794,3 @@
>> +            meta->mem, vbuffer.bytesused, 0, vbuffer.bytesused, NULL,
>> +            NULL));
>> +  /* with vbuffer.bytesused as the size and replace the    */
>> 
>> Huh?  gst_buffer_resize() is the problem.  It can replace the wrapped memory
>> object referenced by the GstBuffer with a new one that meets the new size
>> constraint and then the previously wrapped memory object, which wraps a v4l2
>> buffer, is "lost in space".
>
>In this case, it will only shrink the buffer, so that should never happen.

With all do respect, gst_buffer_resize() does replace the memory object.  I have followed the code path and put a ton of debug print statements in the code.  Without this change, there is no point in going through with a patch for this bug.
Comment 27 Robert Krakora 2013-09-19 20:18:09 UTC
I am submitting another patch shortly...:-)
Comment 28 Robert Krakora 2013-09-19 20:36:53 UTC
Created attachment 255345 [details] [review]
Git Formatted Patch Revised

I have revised the patch again...

...you are right about the code that I put in that bashes v4l2sink...sorry about that...
Comment 29 Olivier Crête 2013-09-19 21:42:06 UTC
Created attachment 255355 [details] [review]
v4l2bufferpool: Restore original GstMemory in buffer if it has been changed

I simplified your patch a little, fixed the coding style. I also removed the playback (sink) bits, since we're not actually fixing it now.
Comment 30 Robert Krakora 2013-09-19 23:58:13 UTC
Thanks...I will test it tonight.  Sorry for the original patch being so convoluted.  :-)
Comment 31 Robert Krakora 2013-09-20 12:38:27 UTC
For my own edification, I thought that using gst_buffer_replace_memory() would kill two birds with one stone versus gst_buffer_remove_all_memory() and gst_buffer_append_memory() as you used or am I missing something?

+  if (obj->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+    gst_buffer_remove_all_memory (outbuf);
+    gst_buffer_append_memory (outbuf,
+        gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE,
+            meta->mem, vbuffer.length, 0, vbuffer.bytesused, NULL, NULL));
Comment 32 Robert Krakora 2013-09-20 12:40:45 UTC
My assumption was that there is only one memory object in the GstBuffer, which may be a bad assumption.  Using the two functions to remove all memory and then append makes sense to me as all of the memory objects are removed.  Good call!
Comment 33 Robert Krakora 2013-09-20 22:28:37 UTC
Thanks...I will test it tonight.  Sorry for the original patch being so convoluted.  :-)
Comment 34 Sebastian Dröge (slomo) 2013-09-21 07:31:24 UTC
Review of attachment 255355 [details] [review]:

Looks good in general to me, please push after Robert has tested it and:

::: sys/v4l2/gstv4l2bufferpool.c
@@ +897,3 @@
+            /* copy the buffer */
+            copy = gst_buffer_copy_region (*buffer,
+                GST_BUFFER_COPY_ALL | GST_BUFFER_COPY_DEEP, 0, -1);

Why are you doing a deep copy here? Please add at least a comment :)
Comment 35 Sebastian Dröge (slomo) 2013-09-22 12:48:57 UTC
Robert, any news on testing? :)
Comment 36 Robert Krakora 2013-09-23 00:03:15 UTC
Sorry, our gateway went down.  Testing just started...I am going to let it run for a few hours.
Comment 37 Robert Krakora 2013-09-23 13:04:49 UTC
Testing has went well and CPU consumption by v4l2src is low.  Looks good so far.
Comment 38 Olivier Crête 2013-09-23 16:05:04 UTC
Pushed

commit 141a1fc296b9d98179f09aaca578b4c1fccbaef7
Author: Robert Krakora <rob.krakora@messagenetsystems.com>
Date:   Thu Sep 19 17:11:34 2013 -0400

    v4l2bufferpool: Restore original GstMemory in buffer if it has been changed
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706083