GStreamer does not give up her secrets very easily :-)

Andres Gonzalez andres.agoralabs at gmail.com
Fri Feb 12 02:10:07 UTC 2016


Hi,

I am using the following to push my application video buffer data into an
appsrc:

 GstBuffer *pVideoBuffer = gst_buffer_new_wrapped_full
(GST_MEMORY_FLAG_READONLY,
                                pBuffer, m_nSize, 0, m_nSize,
m_pGstStreamBuffers, freeVideoBufferCB);

the m_pGstStreamBuffers is a pointer to a struct so I can print out debug
info in the GDestroyNotify routine freeVideoBufferCB().

then I call: 

tReturnCode =
gst_app_src_push_buffer(GST_APP_SRC(m_pPipelineData->pvideo_appsrc),
pVideoBuffer);
gst_buffer_unref(pVideoBuffer);

The documentation for gst_app_src_push_buffer() says: "This function takes
ownership of the buffer" so I am calling gst_buffer_unref() since its
reference was bumped up by gst_app_src_push_buffer().

However, the buffer is still writable after the call to
gst_app_src_push_buffer() so the reference count was not incremented. 

Looking at the source gst-plugins-base-1.6.3/gst-libs/gst/app/gstappsrc.c
line #1727, gst_app_src_push_buffer() calls gst_app_src_push_buffer_full()
with its 3rd bool arg TRUE.    gst_app_src_push_buffer_full() is on line
#1597 and shows that bool arg to be "steal_ref" and is then tested on line
#1657:

1657   if (!steal_ref)
1658     gst_buffer_ref (buffer);
1659   g_queue_push_tail (priv->queue, buffer);

So it appears the conditional is negated so the reference is NOT bumped up.

Also, for both the flushing and eos error cases:
1667 flushing:
1668   { 
1669     GST_DEBUG_OBJECT (appsrc, "refuse buffer %p, we are flushing",
buffer);
1670     if (steal_ref)
1671       gst_buffer_unref (buffer);
1672     g_mutex_unlock (&priv->mutex);
1673     return GST_FLOW_FLUSHING;
1674   }
1675 eos:
1676   { 
1677     GST_DEBUG_OBJECT (appsrc, "refuse buffer %p, we are EOS", buffer);
1678     if (steal_ref)
1679       gst_buffer_unref (buffer);
1680     g_mutex_unlock (&priv->mutex);
1681     return GST_FLOW_EOS;
1682   }

so the reference IS bumped for the error cases when it probably should not.

The same issue appears for gst_app_src_push_buffer_action() on line #1760
where the comments state that the "buffer is pushed without stealing the ref
on the buffer" and then  gst_app_src_push_buffer_full() is called with a
FALSE 3rd arg, which will then cause the ref bump.

The same issue appears for gst_app_src_push_sample_action() on line #1768
where the comments state that it will "push a sample without stealing the
ref." This then calls gst_app_src_push_sample_internal() which calls
gst_app_src_push_buffer_full() with a FALSE 3rd arg so again the ref is
bumped up.

Getting back to my use case for gst_app_src_push_buffer(), my work around is
the following:

tReturnCode =
gst_app_src_push_buffer(GST_APP_SRC(m_pPipelineData->pvideo_appsrc), 
                                                                
gst_buffer_ref(pVideoBuffer));
gst_buffer_unref(pVideoBuffer);

and this appears to work just fine.

Question: Is this OK or is this not what I should do?

I recognize that my understanding of GStreamer is so shallow that the issues
I pointed out above may perhaps not be problematic and instead the comments
are just wrong, so I am not trying to cast stones here--because I live in a
very fragile glass house myself   :-)

Another thing I do not understand is why the GDestroyNotify routine is never
called until the application exits and the pipeline transitions from PLAYING
to PAUSED. Then the GDestroyNotify routine is called hundreds of times--once
for each video frame processed. It appears that the pipeline is not unrefing
ANY of the buffers after they are used.

I tried to explicitly unref the very first buffer for the very first video
frame after 30 frames have been processed. My reasoning was that after 30
frames have gone through the pipeline I can be rather certain that the very
first frame is not still being used in the pipeline so it is safe to unref
it.  However, when I do this I get the following error:

Feb 11 21:04:53.914  ***: freeVideoBufferCB(): entered, frame_count          
: 31 

(videoCap:1943): GStreamer-CRITICAL **: gst_pad_push: assertion
'GST_IS_BUFFER (buffer)' failed
Feb 11 21:04:53.931  ***: freeVideoBufferCB(): entered, frame_count          
: 30

Another confusing bit is that the GDestroyNotify routine is called twice
when I only unreffed the first buffer. In the above example I stopped
processing after 31 frames so I called gst_buffer_unref() only once for the
very first buffer processed.  The same thing happens if I unref the first
buffer after processing 600 frames.

So, I obviously do not know what I am doing here. 

-Andres



--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/GStreamer-does-not-give-up-her-secrets-very-easily-tp4675807.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.


More information about the gstreamer-devel mailing list