guint64 samples_out;
/* bytes flushed during parsing */
guint sync_flush;
+ /* error count */
+ gint error_count;
/* codec id tag */
GstTagList *taglist;
dec->priv->bytes_in = 0;
dec->priv->samples_out = 0;
dec->priv->agg = -1;
+ dec->priv->error_count = 0;
gst_base_audio_decoder_clear_queues (dec);
g_free (dec->ctx->state.channel_pos);
}
priv->samples += samples;
priv->samples_out += samples;
+
+ /* we got data, so note things are looking up */
+ if (G_UNLIKELY (dec->priv->error_count))
+ dec->priv->error_count--;
}
return gst_base_audio_decoder_output (dec, buf);
ret = gst_base_audio_decoder_drain (dec);
} else {
gst_segment_init (&dec->segment, GST_FORMAT_TIME);
+ dec->priv->error_count = 0;
}
/* only bother subclass with flushing if known it is already alive
* and kicking out stuff */
return GST_STATE_CHANGE_FAILURE;
}
}
+
+GstFlowReturn
+_gst_base_audio_decoder_error (GstBaseAudioDecoder * dec, gint weight,
+ GQuark domain, gint code, gchar * txt, gchar * dbg, const gchar * file,
+ const gchar * function, gint line)
+{
+ if (txt)
+ GST_WARNING_OBJECT (dec, "error: %s", txt);
+ if (dbg)
+ GST_WARNING_OBJECT (dec, "error: %s", dbg);
+ dec->priv->error_count += weight;
+ dec->priv->discont = TRUE;
+ if (dec->ctx->max_errors < dec->priv->error_count) {
+ gst_element_message_full (GST_ELEMENT (dec), GST_MESSAGE_ERROR,
+ domain, code, txt, dbg, file, function, line);
+ return GST_FLOW_ERROR;
+ } else {
+ return GST_FLOW_OK;
+ }
+}
typedef struct _GstBaseAudioDecoderPrivate GstBaseAudioDecoderPrivate;
typedef struct _GstBaseAudioDecoderContext GstBaseAudioDecoderContext;
+/* do not use this one, use macro below */
+GstFlowReturn _gst_base_audio_decoder_error (GstBaseAudioDecoder *dec, gint weight,
+ GQuark domain, gint code,
+ gchar *txt, gchar *debug,
+ const gchar *file, const gchar *function,
+ gint line);
+
+/**
+ * GST_BASE_AUDIO_DECODER_ERROR:
+ * @el: the base audio decoder element that generates the error
+ * @weight: element defined weight of the error, added to error count
+ * @domain: like CORE, LIBRARY, RESOURCE or STREAM (see #gstreamer-GstGError)
+ * @code: error code defined for that domain (see #gstreamer-GstGError)
+ * @text: the message to display (format string and args enclosed in
+ * parentheses)
+ * @debug: debugging information for the message (format string and args
+ * enclosed in parentheses)
+ * @ret: variable to receive return value
+ *
+ * Utility function that audio decoder elements can use in case they encountered
+ * a data processing error that may be fatal for the current "data unit" but
+ * need not prevent subsequent decoding. Such errors are counted and if there
+ * are too many, as configured in the context's max_errors, the pipeline will
+ * post an error message and the application will be requested to stop further
+ * media processing. Otherwise, it is considered a "glitch" and only a warning
+ * is logged. In either case, @ret is set to the proper value to
+ * return to upstream/caller (indicating either GST_FLOW_ERROR or GST_FLOW_OK).
+ */
+#define GST_BASE_AUDIO_DECODER_ERROR(el, w, domain, code, text, debug, ret) \
+G_STMT_START { \
+ gchar *__txt = _gst_element_error_printf text; \
+ gchar *__dbg = _gst_element_error_printf debug; \
+ GstBaseAudioDecoder *dec = GST_BASE_AUDIO_DECODER (el); \
+ ret = _gst_base_audio_decoder_error (dec, w, GST_ ## domain ## _ERROR, \
+ GST_ ## domain ## _ERROR_ ## code, __txt, __dbg, __FILE__, \
+ GST_FUNCTION, __LINE__); \
+} G_STMT_END
+
/**
* GstBaseAudioDecoderContext:
* @state: a #GstAudioState describing input audio format
/* output */
gboolean do_plc;
gboolean do_byte_time;
+ gint max_errors;
/* MT-protected (with LOCK) */
GstClockTime min_latency;
GstClockTime max_latency;