basescope: allow subclasses telling how many sample they need per frame

This allows e.g. FFT based elements to require enough data. If they need more
data than what we get, we flush less from the adapter.

https://bugzilla.gnome.org/show_bug.cgi?id=651536
This commit is contained in:
Stefan Kost 2011-05-27 23:12:00 +03:00
parent 46e3bc48af
commit 2271946d73
3 changed files with 23 additions and 13 deletions

View file

@ -278,13 +278,15 @@ gst_base_scope_src_setcaps (GstPad * pad, GstCaps * caps)
scope->fps_d, scope->fps_n);
scope->spf = gst_util_uint64_scale_int (scope->rate,
scope->fps_d, scope->fps_n);
scope->req_spf = scope->spf;
if (klass->setup)
res = klass->setup (scope);
GST_DEBUG_OBJECT (scope, "video: dimension %dx%d, framerate %d/%d, spf %d",
scope->width, scope->height, scope->fps_n, scope->fps_d, scope->spf);
GST_DEBUG_OBJECT (scope, "video: dimension %dx%d, framerate %d/%d",
scope->width, scope->height, scope->fps_n, scope->fps_d);
GST_DEBUG_OBJECT (scope, "blocks: spf %u, req_spf %u",
scope->spf, scope->req_spf);
done:
gst_object_unref (scope);
return res;
@ -306,7 +308,7 @@ gst_base_scope_chain (GstPad * pad, GstBuffer * buffer)
GstBaseScope *scope;
GstBaseScopeClass *klass;
GstBuffer *inbuf;
guint32 avail, bytesperread;
guint avail, sbpf;
guint bpp;
gboolean (*render) (GstBaseScope * scope, GstBuffer * audio,
GstBuffer * video);
@ -336,7 +338,7 @@ gst_base_scope_chain (GstPad * pad, GstBuffer * buffer)
gst_adapter_push (scope->adapter, buffer);
/* this is what we want */
bytesperread = scope->spf * scope->channels * sizeof (gint16);
sbpf = scope->req_spf * scope->channels * sizeof (gint16);
bpp = gst_video_format_get_pixel_stride (scope->video_format, 0);
@ -346,7 +348,7 @@ gst_base_scope_chain (GstPad * pad, GstBuffer * buffer)
/* this is what we have */
avail = gst_adapter_available (scope->adapter);
while (avail > bytesperread) {
while (avail > sbpf) {
GstBuffer *outbuf;
ret = gst_pad_alloc_buffer_and_set_caps (scope->srcpad,
@ -363,8 +365,8 @@ gst_base_scope_chain (GstPad * pad, GstBuffer * buffer)
memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf));
GST_BUFFER_DATA (inbuf) =
(guint8 *) gst_adapter_peek (scope->adapter, bytesperread);
GST_BUFFER_SIZE (inbuf) = bytesperread;
(guint8 *) gst_adapter_peek (scope->adapter, sbpf);
GST_BUFFER_SIZE (inbuf) = sbpf;
/* call class->render() vmethod */
if (render)
@ -375,10 +377,13 @@ gst_base_scope_chain (GstPad * pad, GstBuffer * buffer)
ret = gst_pad_push (scope->srcpad, outbuf);
outbuf = NULL;
/* FIXME: we want to ev. take less
* we need to align the audio-rate, video-rate and blocksize for render
*/
gst_adapter_flush (scope->adapter, bytesperread);
GST_LOG_OBJECT (scope, "avail: %u, bpf: %u", avail, sbpf);
/* we want to take less or more, depending on spf : req_spf */
if (avail - sbpf > sbpf)
gst_adapter_flush (scope->adapter, sbpf);
else if (avail - sbpf > 0)
gst_adapter_flush (scope->adapter, (avail - sbpf));
avail = gst_adapter_available (scope->adapter);
if (ret != GST_FLOW_OK)
break;

View file

@ -51,6 +51,7 @@ struct _GstBaseScope
guint64 frame_duration;
guint bps; /* bytes per sample */
guint spf; /* samples per video frame */
guint req_spf; /* min samples per frame wanted by the subclass */
/* video state */
GstVideoFormat video_format;

View file

@ -125,8 +125,12 @@ gst_spectra_scope_setup (GstBaseScope * bscope)
gst_fft_s16_free (scope->fft_ctx);
if (scope->freq_data)
g_free (scope->freq_data);
scope->fft_ctx = gst_fft_s16_new (bscope->width * 2 - 2, FALSE);
/* we'd need this amount of samples per render() call */
bscope->req_spf = bscope->width * 2 - 2;
scope->fft_ctx = gst_fft_s16_new (bscope->req_spf, FALSE);
scope->freq_data = g_new (GstFFTS16Complex, bscope->width);
return TRUE;
}