baseaudioencoder: minor fixes and code simplifications

Also modify and elaborate a bit on pre_push (though currently unused to no harm).
This commit is contained in:
Mark Nauwelaerts 2011-03-10 14:28:48 +01:00 committed by Tim-Philipp Müller
parent d0e9fbf3db
commit 9ce2edc918
2 changed files with 29 additions and 43 deletions

View file

@ -196,10 +196,6 @@ struct _GstBaseAudioEncoderPrivate
GstAdapter *adapter; GstAdapter *adapter;
/* offset in adapter up to which already supplied to encoder */ /* offset in adapter up to which already supplied to encoder */
gint offset; gint offset;
/* collected encoded data */
GstAdapter *adapter_out;
/* (estimated) samples (w.r.t. input rate) represented in adapter_out */
gint samples_out;
/* mark outgoing discont */ /* mark outgoing discont */
gboolean discont; gboolean discont;
/* to guess duration of drained data */ /* to guess duration of drained data */
@ -375,7 +371,6 @@ gst_base_audio_encoder_init (GstBaseAudioEncoder * enc,
GST_DEBUG_OBJECT (enc, "src created"); GST_DEBUG_OBJECT (enc, "src created");
enc->priv->adapter = gst_adapter_new (); enc->priv->adapter = gst_adapter_new ();
enc->priv->adapter_out = gst_adapter_new ();
enc->ctx = &enc->priv->ctx; enc->ctx = &enc->priv->ctx;
/* property default */ /* property default */
@ -409,14 +404,12 @@ gst_base_audio_encoder_reset (GstBaseAudioEncoder * enc, gboolean full)
gst_segment_init (&enc->segment, GST_FORMAT_TIME); gst_segment_init (&enc->segment, GST_FORMAT_TIME);
gst_adapter_clear (enc->priv->adapter); gst_adapter_clear (enc->priv->adapter);
gst_adapter_clear (enc->priv->adapter_out);
enc->priv->got_data = FALSE; enc->priv->got_data = FALSE;
enc->priv->drained = TRUE; enc->priv->drained = TRUE;
enc->priv->offset = 0; enc->priv->offset = 0;
enc->priv->base_ts = GST_CLOCK_TIME_NONE; enc->priv->base_ts = GST_CLOCK_TIME_NONE;
enc->priv->base_gp = -1; enc->priv->base_gp = -1;
enc->priv->samples = 0; enc->priv->samples = 0;
enc->priv->samples_out = 0;
enc->priv->discont = FALSE; enc->priv->discont = FALSE;
GST_OBJECT_UNLOCK (enc); GST_OBJECT_UNLOCK (enc);
@ -428,7 +421,6 @@ gst_base_audio_encoder_finalize (GObject * object)
GstBaseAudioEncoder *enc = GST_BASE_AUDIO_ENCODER (object); GstBaseAudioEncoder *enc = GST_BASE_AUDIO_ENCODER (object);
g_object_unref (enc->priv->adapter); g_object_unref (enc->priv->adapter);
g_object_unref (enc->priv->adapter_out);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -464,7 +456,6 @@ gst_base_audio_encoder_finish_frame (GstBaseAudioEncoder * enc, GstBuffer * buf,
GstBaseAudioEncoderPrivate *priv; GstBaseAudioEncoderPrivate *priv;
GstBaseAudioEncoderContext *ctx; GstBaseAudioEncoderContext *ctx;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
gint av;
klass = GST_BASE_AUDIO_ENCODER_GET_CLASS (enc); klass = GST_BASE_AUDIO_ENCODER_GET_CLASS (enc);
priv = enc->priv; priv = enc->priv;
@ -487,8 +478,8 @@ gst_base_audio_encoder_finish_frame (GstBaseAudioEncoder * enc, GstBuffer * buf,
samples = (enc->priv->offset / ctx->state.bpf); samples = (enc->priv->offset / ctx->state.bpf);
if (G_LIKELY (samples)) { if (G_LIKELY (samples)) {
/* track upstream ts at output collection start if so configured */ /* track upstream ts if so configured */
if (!enc->perfect_ts && !priv->samples_out) { if (!enc->perfect_ts) {
guint64 ts, distance; guint64 ts, distance;
ts = gst_adapter_prev_timestamp (priv->adapter, &distance); ts = gst_adapter_prev_timestamp (priv->adapter, &distance);
@ -544,21 +535,12 @@ gst_base_audio_encoder_finish_frame (GstBaseAudioEncoder * enc, GstBuffer * buf,
if (G_UNLIKELY (gst_adapter_available (priv->adapter) == 0)) if (G_UNLIKELY (gst_adapter_available (priv->adapter) == 0))
gst_adapter_clear (priv->adapter); gst_adapter_clear (priv->adapter);
} }
if (G_LIKELY (buf)) { /* sample count advanced below after buffer handling */
priv->samples_out += samples;
samples = 0;
}
/* otherwise retain count of to-be-discarded samples */
} }
/* collect output */ /* collect output */
if (G_LIKELY (buf)) if (G_LIKELY (buf)) {
gst_adapter_push (enc->priv->adapter_out, buf); GST_LOG_OBJECT (enc, "taking %d bytes for output", GST_BUFFER_SIZE (buf));
av = gst_adapter_available (priv->adapter_out);
if (av) {
GST_LOG_OBJECT (enc, "collecting all %d bytes for output", av);
buf = gst_adapter_take_buffer (priv->adapter_out, av);
buf = gst_buffer_make_metadata_writable (buf); buf = gst_buffer_make_metadata_writable (buf);
/* decorate */ /* decorate */
@ -570,10 +552,9 @@ gst_base_audio_encoder_finish_frame (GstBaseAudioEncoder * enc, GstBuffer * buf,
GST_BUFFER_TIMESTAMP (buf) = priv->base_ts + GST_BUFFER_TIMESTAMP (buf) = priv->base_ts +
gst_util_uint64_scale (priv->samples - ctx->lookahead, GST_SECOND, gst_util_uint64_scale (priv->samples - ctx->lookahead, GST_SECOND,
ctx->state.rate); ctx->state.rate);
GST_DEBUG_OBJECT (enc, "out samples %d", (gint) priv->samples_out); GST_DEBUG_OBJECT (enc, "out samples %d", samples);
if (G_LIKELY (priv->samples_out > 0)) { if (G_LIKELY (samples > 0)) {
priv->samples += priv->samples_out; priv->samples += samples;
priv->samples_out = 0;
GST_BUFFER_DURATION (buf) = priv->base_ts + GST_BUFFER_DURATION (buf) = priv->base_ts +
gst_util_uint64_scale (priv->samples - ctx->lookahead, GST_SECOND, gst_util_uint64_scale (priv->samples - ctx->lookahead, GST_SECOND,
ctx->state.rate) - GST_BUFFER_TIMESTAMP (buf); ctx->state.rate) - GST_BUFFER_TIMESTAMP (buf);
@ -599,29 +580,39 @@ gst_base_audio_encoder_finish_frame (GstBaseAudioEncoder * enc, GstBuffer * buf,
} }
} }
priv->bytes_out += GST_BUFFER_SIZE (buf);
if (G_UNLIKELY (priv->discont)) { if (G_UNLIKELY (priv->discont)) {
GST_LOG_OBJECT (enc, "marking discont"); GST_LOG_OBJECT (enc, "marking discont");
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
priv->discont = FALSE; priv->discont = FALSE;
} }
// TODO return value ?
if (klass->pre_push) if (klass->pre_push) {
klass->pre_push (enc, buf); /* last chance for subclass to do some dirty stuff */
ret = klass->pre_push (enc, &buf);
if (ret != GST_FLOW_OK || !buf) {
GST_DEBUG_OBJECT (enc, "subclass returned %s, buf %p",
gst_flow_get_name (ret), buf);
if (buf)
gst_buffer_unref (buf);
goto exit;
}
}
GST_LOG_OBJECT (enc, "pushing buffer of size %d with ts %" GST_TIME_FORMAT GST_LOG_OBJECT (enc, "pushing buffer of size %d with ts %" GST_TIME_FORMAT
", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf), ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
priv->bytes_out += GST_BUFFER_SIZE (buf);
ret = gst_pad_push (enc->srcpad, buf); ret = gst_pad_push (enc->srcpad, buf);
GST_LOG_OBJECT (enc, "buffer pushed: %s", gst_flow_get_name (ret)); GST_LOG_OBJECT (enc, "buffer pushed: %s", gst_flow_get_name (ret));
} else {
/* merely advance samples, most work for that already done above */
priv->samples += samples;
} }
/* account for discarded */ exit:
priv->samples += samples;
return ret; return ret;
/* ERRORS */ /* ERRORS */
@ -657,10 +648,6 @@ gst_base_audio_encoder_push_buffers (GstBaseAudioEncoder * enc, gboolean force)
priv = enc->priv; priv = enc->priv;
ctx = enc->ctx; ctx = enc->ctx;
/* ensure clear start */
gst_adapter_clear (priv->adapter_out);
priv->samples_out = 0;
while (ret == GST_FLOW_OK) { while (ret == GST_FLOW_OK) {
buf = NULL; buf = NULL;
@ -723,9 +710,6 @@ gst_base_audio_encoder_push_buffers (GstBaseAudioEncoder * enc, gboolean force)
} }
} }
if (gst_adapter_available (priv->adapter_out))
gst_base_audio_encoder_finish_frame (enc, NULL, 0);
return ret; return ret;
} }

View file

@ -188,6 +188,8 @@ struct _GstBaseAudioEncoder {
* (i.e. not unref'ed). * (i.e. not unref'ed).
* @pre_push: Optional. * @pre_push: Optional.
* Called just prior to pushing (encoded data) buffer downstream. * Called just prior to pushing (encoded data) buffer downstream.
* Subclass has full discretionary access to buffer,
* and a not OK flow return will abort downstream pushing.
* @getcaps: Optional. * @getcaps: Optional.
* Allows for a custom sink getcaps implementation (e.g. * Allows for a custom sink getcaps implementation (e.g.
* for multichannel input specification). If not implemented, * for multichannel input specification). If not implemented,
@ -216,7 +218,7 @@ struct _GstBaseAudioEncoderClass {
void (*flush) (GstBaseAudioEncoder *enc); void (*flush) (GstBaseAudioEncoder *enc);
GstFlowReturn (*pre_push) (GstBaseAudioEncoder *enc, GstFlowReturn (*pre_push) (GstBaseAudioEncoder *enc,
GstBuffer *buffer); GstBuffer **buffer);
gboolean (*event) (GstBaseAudioEncoder *enc, gboolean (*event) (GstBaseAudioEncoder *enc,
GstEvent *event); GstEvent *event);