Queue Flow Control req'd by GstBaseSink or GST_BUFFER_TIMESTAMP problems?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Queue Flow Control req'd by GstBaseSink or GST_BUFFER_TIMESTAMP problems?

HaroldJRoth
I'm working with a custom plugin that extends GstBaseSink.  I add this and a queue to my pipeline.  E.g.

gst_bin_add(GST_BIN(mGstPipeline), mVideoQueue);
gst_bin_add(GST_BIN(mGstPipeline), mVideoSnoop);
gst_element_link(mVideoQueue, mVideoSnoop);

I link this queue/GstBaseSink pair to a decodebin2 manually when a video pad appears.  E.g.

mDecoderOutput = gst_element_factory_make("decodebin2", "decoder");
g_signal_connect(mDecoderOutput, "new-decoded-pad", G_CALLBACK(cb_newpad), this);

The difficulty I find is that my GstBaseSink causes the pipeline to pause.  It doesn't grab the buffers and so the queue fills up.  This pauses the stream both upstream and downstream.

What I'm wondering is whether this is

a)  Because I'm using an appsrc, but I'm not setting the timestamp properly.  E.g.

GstBuffer * buffer = gst_buffer_new();
GST_BUFFER_SIZE (buffer) = g_data_packet.pkt_len;
GST_BUFFER_MALLOCDATA (buffer) = (guint8*)g_malloc (g_data_packet.pkt_len);
GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);

GST_DEBUG ("feed buffer %p, len -%u", buffer, g_data_packet.pkt_len);

// @todo change to memcpy or something sensible
for (int i = 0 ; i < g_data_packet.pkt_len; i++) {
        GST_BUFFER_DATA(buffer)[i] = g_data_packet.data[i];
}
GST_BUFFER_TIMESTAMP(buffer)   =GST_CLOCK_TIME_NONE;
 
of b) should I revise the GstBaseSink to restart the pipeline?  (Don't know what the code would look like)

Reply | Threaded
Open this post in threaded view
|

Re: Queue Flow Control req'd by GstBaseSink or GST_BUFFER_TIMESTAMP problems?

Marco Ballesio
Hi,

On Wed, Nov 3, 2010 at 8:24 PM, HaroldJRoth <[hidden email]> wrote:

I'm working with a custom plugin that extends GstBaseSink.  I add this and a
queue to my pipeline.  E.g.

gst_bin_add(GST_BIN(mGstPipeline), mVideoQueue);
gst_bin_add(GST_BIN(mGstPipeline), mVideoSnoop);
gst_element_link(mVideoQueue, mVideoSnoop);

I link this queue/GstBaseSink pair to a decodebin2 manually when a video pad
appears.  E.g.

mDecoderOutput = gst_element_factory_make("decodebin2", "decoder");
g_signal_connect(mDecoderOutput, "new-decoded-pad", G_CALLBACK(cb_newpad),
this);

The difficulty I find is that my GstBaseSink causes the pipeline to pause.
It doesn't grab the buffers and so the queue fills up.  This pauses the
stream both upstream and downstream.

What I'm wondering is whether this is

a)  Because I'm using an appsrc, but I'm not setting the timestamp properly.

likely basesink is dropping the buffers. What if you sent your sink's property "sync" to false?
 
E.g.

GstBuffer * buffer = gst_buffer_new();
GST_BUFFER_SIZE (buffer) = g_data_packet.pkt_len;
GST_BUFFER_MALLOCDATA (buffer) = (guint8*)g_malloc (g_data_packet.pkt_len);
GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);

GST_DEBUG ("feed buffer %p, len -%u", buffer, g_data_packet.pkt_len);

// @todo change to memcpy or something sensible
for (int i = 0 ; i < g_data_packet.pkt_len; i++) {
       GST_BUFFER_DATA(buffer)[i] = g_data_packet.data[i];
}
GST_BUFFER_TIMESTAMP(buffer)   =GST_CLOCK_TIME_NONE;

I suggest you to fix this event if the "sync=false" works , unless it is really what you want.
 

of b) should I revise the GstBaseSink to restart the pipeline?  (Don't know
what the code would look like)

I'm not a great expert about dynamic pipelines, but afaik you should add all the elements when the pipeline is in NULL (or PAUSED) state, then trigger the state changes to PLAYING.

At least in my experience, violations may bring you to unpredictable results (and extra-hackish-code to write for manually dealing with state changes).

Regards
 


--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Queue-Flow-Control-req-d-by-GstBaseSink-or-GST-BUFFER-TIMESTAMP-problems-tp3025912p3025912.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.

------------------------------------------------------------------------------
Achieve Improved Network Security with IP and DNS Reputation.
Defend against bad network traffic, including botnets, malware,
phishing sites, and compromised hosts - saving your company time,
money, and embarrassment.   Learn More!
http://p.sf.net/sfu/hpdev2dev-nov
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel


------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Queue Flow Control req'd by GstBaseSink or GST_BUFFER_TIMESTAMP problems?

HaroldJRoth
Marco Ballesio wrote
Hi,

On Wed, Nov 3, 2010 at 8:24 PM, HaroldJRoth <dlafferty@gmail.com> wrote:

>
> I'm working with a custom plugin that extends GstBaseSink.  I add this and
> a
> queue to my pipeline.  E.g.
>
> gst_bin_add(GST_BIN(mGstPipeline), mVideoQueue);
> gst_bin_add(GST_BIN(mGstPipeline), mVideoSnoop);
> gst_element_link(mVideoQueue, mVideoSnoop);
>
> I link this queue/GstBaseSink pair to a decodebin2 manually when a video
> pad
> appears.  E.g.
>
> mDecoderOutput = gst_element_factory_make("decodebin2", "decoder");
> g_signal_connect(mDecoderOutput, "new-decoded-pad", G_CALLBACK(cb_newpad),
> this);
>
> The difficulty I find is that my GstBaseSink causes the pipeline to pause.
> It doesn't grab the buffers and so the queue fills up.  This pauses the
> stream both upstream and downstream.
>
> What I'm wondering is whether this is
>
> a)  Because I'm using an appsrc, but I'm not setting the timestamp
> properly.
>

likely basesink is dropping the buffers. What if you sent your sink's
property "sync" to false?
GstBaseSink doesn't drop the buffers.  If it did, the queue element would not be able to fill up.  I'm pretty sure that the "sync" is set to false.  So, I'm guessing that my GstBaseSink specialisation does not properly pull an element out of the queue buffer.  Either my GstBaseSink should signal that its ready to take another, or my GstBaseSink should signal that an item has been removed.  Currently, my GstBaseSink carries out the default behaviour, which results in it getting Paused by what I beleive to be a signal coming from the queue.

BTW, do you know of a mechanism for viewing the signal processing in the GstBaseSink?


Marco Ballesio wrote
> E.g.
>
> GstBuffer * buffer = gst_buffer_new();
> GST_BUFFER_SIZE (buffer) = g_data_packet.pkt_len;
> GST_BUFFER_MALLOCDATA (buffer) = (guint8*)g_malloc (g_data_packet.pkt_len);
> GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
>
> GST_DEBUG ("feed buffer %p, len -%u", buffer, g_data_packet.pkt_len);
>
> // @todo change to memcpy or something sensible
> for (int i = 0 ; i < g_data_packet.pkt_len; i++) {
>        GST_BUFFER_DATA(buffer)[i] = g_data_packet.data[i];
> }
> GST_BUFFER_TIMESTAMP(buffer)   =GST_CLOCK_TIME_NONE;
>

I suggest you to fix this event if the "sync=false" works , unless it is
really what you want.


>
> of b) should I revise the GstBaseSink to restart the pipeline?  (Don't know
> what the code would look like)
>

I'm not a great expert about dynamic pipelines, but afaik you should add all
the elements when the pipeline is in NULL (or PAUSED) state, then trigger
the state changes to PLAYING.

At least in my experience, violations may bring you to unpredictable results
(and extra-hackish-code to write for manually dealing with state changes).

Regards
The elements in my pipeline are fixed.  I don't add or remove elements.  I am talking about sending a signal from the GstBaseSink to it upstream, and adjacent, queue.  However, I don't think I can get away with telling the queue to state transition from PAUSED to PLAYING, as its buffer is full.
Reply | Threaded
Open this post in threaded view
|

Re: Queue Flow Control req'd by GstBaseSink or GST_BUFFER_TIMESTAMP problems?

Marco Ballesio
Hi,

On Thu, Nov 4, 2010 at 11:35 AM, HaroldJRoth <[hidden email]> wrote:
GstBaseSink doesn't drop the buffers.  If it did, the queue element would
not be able to fill up.  

right.
 
I'm pretty sure that the "sync" is set to false.

if you're using the default value, it's TRUE. You may try and set the max-lateness property but using GST_CLOCK_TIME_NONE for your timestamps makes the basesink log out a message (you can see it with GST_DEBUG=basesink:5) and not to drop anything.
 
So, I'm guessing that my GstBaseSink specialisation does not properly pull
an element out of the queue buffer.  Either my GstBaseSink should signal
that its ready to take another, or my GstBaseSink should signal that an item
has been removed.  Currently, my GstBaseSink carries out the default
behaviour, which results in it getting Paused by what I beleive to be a
signal coming from the queue.

it's likely that basesink behaves that way because of the timestamps you're feeding it with and its default working mode. Either you set your sink's sync property to FALSE or (better) you  fix the timestamps in the source element.
 

BTW, do you know of a mechanism for viewing the signal processing in the
GstBaseSink?

GST_DEBUG=basesink:5 is the best I'm aware of. You can also do like gst-launch and connect an handler to the deep-notify signal in your pipeline (you'll get plenty of data).

http://www.gstreamer.net/data/doc/gstreamer/head/gstreamer/html/GstObject.html#GstObject-deep-notify

Regards
 



Marco Ballesio wrote:
>
>> E.g.
>>
>> GstBuffer * buffer = gst_buffer_new();
>> GST_BUFFER_SIZE (buffer) = g_data_packet.pkt_len;
>> GST_BUFFER_MALLOCDATA (buffer) = (guint8*)g_malloc
>> (g_data_packet.pkt_len);
>> GST_BUFFER_DATA (buffer) = GST_BUFFER_MALLOCDATA (buffer);
>>
>> GST_DEBUG ("feed buffer %p, len -%u", buffer, g_data_packet.pkt_len);
>>
>> // @todo change to memcpy or something sensible
>> for (int i = 0 ; i < g_data_packet.pkt_len; i++) {
>>        GST_BUFFER_DATA(buffer)[i] = g_data_packet.data[i];
>> }
>> GST_BUFFER_TIMESTAMP(buffer)   =GST_CLOCK_TIME_NONE;
>>
>
> I suggest you to fix this event if the "sync=false" works , unless it is
> really what you want.
>
>
>>
>> of b) should I revise the GstBaseSink to restart the pipeline?  (Don't
>> know
>> what the code would look like)
>>
>
> I'm not a great expert about dynamic pipelines, but afaik you should add
> all
> the elements when the pipeline is in NULL (or PAUSED) state, then trigger
> the state changes to PLAYING.
>
> At least in my experience, violations may bring you to unpredictable
> results
> (and extra-hackish-code to write for manually dealing with state changes).
>
> Regards
>
>

The elements in my pipeline are fixed.  I don't add or remove elements.  I
am talking about sending a signal from the GstBaseSink to it upstream, and
adjacent, queue.  However, I don't think I can get away with telling the
queue to state transition from PAUSED to PLAYING, as its buffer is full.
--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Queue-Flow-Control-req-d-by-GstBaseSink-or-GST-BUFFER-TIMESTAMP-problems-tp3025912p3026734.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.

------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel


------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Queue Flow Control req'd by GstBaseSink or GST_BUFFER_TIMESTAMP problems?

HaroldJRoth
Marco Ballesio wrote
Hi,

On Thu, Nov 4, 2010 at 11:35 AM, HaroldJRoth <dlafferty@gmail.com> wrote:

> I'm pretty sure that the "sync" is set to false.
>

if you're using the default value, it's TRUE. You may try and set the
max-lateness property but using GST_CLOCK_TIME_NONE for your timestamps
makes the basesink log out a message (you can see it with
GST_DEBUG=basesink:5) and not to drop anything.
Definitely setting "sync" to FALSE, e.g.

g_object_set(G_OBJECT(mVideoSnoop), "sync", FALSE, NULL);

That said, I took your advice on the GST_DEBUG, and found my GstBaseSink blocked in the preroll.  E.g.

basesink gstbasesink.c:1914:gst_base_sink_get_sync_times:<videoSnoop> got times start: 0:00:00.000000000, stop: 0:00:00.040000000, do_sync 1
basesink gstbasesink.c:2197:gst_base_sink_do_preroll:<videoSnoop> prerolling object 0x7ff498185c30
basesink gstbasesink.c:2984:gst_base_sink_preroll_object:<videoSnoop> prerolling object 0x7ff498185c30
basesink gstbasesink.c:2148:gst_base_sink_wait_preroll:<videoSnoop> waiting in preroll for flush or PLAYING


Since I set the overall pipeline to PLAYING, I'm confused why a PLAYING message is not received.


BTW, do you know of any sample 'render' implementations.  Mine does not seem to release the GstBuffer after it is called.  Nor does it do any internal locking.  E.g

static GstFlowReturn render (GstBaseSink *sink, GstBuffer* buf) {
  GstTaMediaSnoop *mediaSnoop;
  mediaSnoop = GST_TAMEDIASNOOP (sink);
   
  //Dump the frame on the heap
  gchar *bufferData = malloc(buf->size + 8);
  if(!bufferData) {
    GST_WARNING("Warning - taMediaSnoop element could not malloc data\n");
    return GST_FLOW_ERROR;
  }
  memcpy(bufferData, buf->data, buf->size);
  guint64 timestamp = GST_BUFFER_TIMESTAMP(buf);
  memcpy(bufferData + buf->size, ×tamp, 8);
 
  //And tell the application where it is
  g_signal_emit(G_OBJECT(mediaSnoop), signalIds[FRAME_READY_SIGNAL], 0, buf->size, bufferData);
  //NOTE: It is left to the application to free the frame when it is done!
  //gst_buffer_unref(buf);

  /* just push out the incoming buffer without touching it */
  return GST_FLOW_OK;
}

Reply | Threaded
Open this post in threaded view
|

Re: Queue Flow Control req'd by GstBaseSink or GST_BUFFER_TIMESTAMP problems?

Marco Ballesio
Hi,

On Thu, Nov 4, 2010 at 1:32 PM, HaroldJRoth <[hidden email]> wrote:
..snip..
 

That said, I took your advice on the GST_DEBUG, and found my GstBaseSink
blocked in the preroll.  E.g.

basesink gstbasesink.c:1914:gst_base_sink_get_sync_times:<videoSnoop> [00m
got times start: 0:00:00.000000000, stop: 0:00:00.040000000, do_sync 1
basesink gstbasesink.c:2197:gst_base_sink_do_preroll:<videoSnoop> [00m
prerolling object 0x7ff498185c30
basesink gstbasesink.c:2984:gst_base_sink_preroll_object:<videoSnoop> [00m
prerolling object 0x7ff498185c30
basesink gstbasesink.c:2148:gst_base_sink_wait_preroll:<videoSnoop> [00m
waiting in preroll for flush or PLAYING

so you're not successfully completing the transition to PLAYING state because you're prerolling. You may try and implement the virtual method preroll to make it returning GST_FLOW_OK.
 

Since I set the overall pipeline to PLAYING, I'm confused why a PLAYING
message is not received.


A pipeline goes to playing when all of its elements complete the transition to that state. In your case the sink element does not complete the transition because it waits for prerolling to complete forever. The reason for this is, quite obviously, because it can't synchronise to the clock as described here:

http://www.gstreamer.net/data/doc/gstreamer/head/gstreamer-libs/html/GstBaseSink.html

(search for "prerolling correctly" ;)

again, I suggest you to properly set the timestamps in your buffer, but maybe just implementing the preroll() virtual function will do the trick here.
 

BTW, do you know of any sample 'render' implementations.  

Imo no "real" sinks could handle properly the clock sync with the timestamps you're passing. Btw, if you like challenges, I think fakesink is the closest thing to what you need:

http://cgit.freedesktop.org/gstreamer/gstreamer/tree/plugins/elements/gstfakesink.c

 
Mine does not seem
to release the GstBuffer after it is called.  Nor does it do any internal
locking.  E.g

static GstFlowReturn render (GstBaseSink *sink, GstBuffer* buf) {
 GstTaMediaSnoop *mediaSnoop;
 mediaSnoop = GST_TAMEDIASNOOP (sink);

 //Dump the frame on the heap
 gchar *bufferData = malloc(buf->size + 8);
 if(!bufferData) {
   GST_WARNING("Warning - taMediaSnoop element could not malloc data\n");
   return GST_FLOW_ERROR;
 }
 memcpy(bufferData, buf->data, buf->size);

I don't know what actually your app is supposed to do, but maybe referencing the buffer passed from the pipeline and unreferencing it after the application is done would save you from extra mallocs + memory copies (indeed you'll need some more signaling from the app).

Btw maybe an appsink would even be simpler in this case.

Regards
 
 guint64 timestamp = GST_BUFFER_TIMESTAMP(buf);
 memcpy(bufferData + buf->size, &timestamp, 8);

 //And tell the application where it is
 g_signal_emit(G_OBJECT(mediaSnoop), signalIds[FRAME_READY_SIGNAL], 0,
buf->size, bufferData);
 //NOTE: It is left to the application to free the frame when it is done!
 //gst_buffer_unref(buf);

 /* just push out the incoming buffer without touching it */
 return GST_FLOW_OK;


 

--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Queue-Flow-Control-req-d-by-GstBaseSink-or-GST-BUFFER-TIMESTAMP-problems-tp3025912p3026862.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.

------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel


------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel