mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 14:08:56 +00:00
cutter: add audio-level-meta
Set GstAudioLevelMeta on buffers Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5771>
This commit is contained in:
parent
60d9cfc954
commit
34741e1db2
3 changed files with 58 additions and 1 deletions
|
@ -4293,6 +4293,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"audio-level-meta": {
|
||||||
|
"blurb": "Set GstAudioLevelMeta on buffers",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "false",
|
||||||
|
"mutable": "null",
|
||||||
|
"readable": true,
|
||||||
|
"type": "gboolean",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"leaky": {
|
"leaky": {
|
||||||
"blurb": "do we leak buffers when below threshold ?",
|
"blurb": "do we leak buffers when below threshold ?",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
|
|
@ -54,6 +54,7 @@ GST_DEBUG_CATEGORY_STATIC (cutter_debug);
|
||||||
#define CUTTER_DEFAULT_THRESHOLD_LEVEL 0.1
|
#define CUTTER_DEFAULT_THRESHOLD_LEVEL 0.1
|
||||||
#define CUTTER_DEFAULT_THRESHOLD_LENGTH (500 * GST_MSECOND)
|
#define CUTTER_DEFAULT_THRESHOLD_LENGTH (500 * GST_MSECOND)
|
||||||
#define CUTTER_DEFAULT_PRE_LENGTH (200 * GST_MSECOND)
|
#define CUTTER_DEFAULT_PRE_LENGTH (200 * GST_MSECOND)
|
||||||
|
#define EPSILON 1e-35f
|
||||||
|
|
||||||
static GstStaticPadTemplate cutter_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
static GstStaticPadTemplate cutter_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
|
@ -81,7 +82,8 @@ enum
|
||||||
PROP_THRESHOLD_DB,
|
PROP_THRESHOLD_DB,
|
||||||
PROP_RUN_LENGTH,
|
PROP_RUN_LENGTH,
|
||||||
PROP_PRE_LENGTH,
|
PROP_PRE_LENGTH,
|
||||||
PROP_LEAKY
|
PROP_LEAKY,
|
||||||
|
PROP_AUDIO_LEVEL_META,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define gst_cutter_parent_class parent_class
|
#define gst_cutter_parent_class parent_class
|
||||||
|
@ -135,6 +137,17 @@ gst_cutter_class_init (GstCutterClass * klass)
|
||||||
g_param_spec_boolean ("leaky", "Leaky",
|
g_param_spec_boolean ("leaky", "Leaky",
|
||||||
"do we leak buffers when below threshold ?",
|
"do we leak buffers when below threshold ?",
|
||||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
/**
|
||||||
|
* GstCutter:audio-level-meta:
|
||||||
|
*
|
||||||
|
* If %TRUE, generate or update GstAudioLevelMeta on output buffers.
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_AUDIO_LEVEL_META,
|
||||||
|
g_param_spec_boolean ("audio-level-meta", "Audio Level Meta",
|
||||||
|
"Set GstAudioLevelMeta on buffers", FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (cutter_debug, "cutter", 0, "Audio cutting");
|
GST_DEBUG_CATEGORY_INIT (cutter_debug, "cutter", 0, "Audio cutting");
|
||||||
|
|
||||||
|
@ -175,6 +188,7 @@ gst_cutter_init (GstCutter * filter)
|
||||||
filter->pre_run_length = 0 * GST_SECOND;
|
filter->pre_run_length = 0 * GST_SECOND;
|
||||||
filter->pre_buffer = NULL;
|
filter->pre_buffer = NULL;
|
||||||
filter->leaky = FALSE;
|
filter->leaky = FALSE;
|
||||||
|
filter->audio_level_meta = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstMessage *
|
static GstMessage *
|
||||||
|
@ -293,6 +307,23 @@ gst_cutter_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_audio_level_meta (GstBuffer * buffer, guint8 level)
|
||||||
|
{
|
||||||
|
GstAudioLevelMeta *meta;
|
||||||
|
|
||||||
|
/* Update the existing meta, if any, so we can have an upstream element
|
||||||
|
* filling the voice activity part of the meta. */
|
||||||
|
meta = gst_buffer_get_audio_level_meta (buffer);
|
||||||
|
if (meta) {
|
||||||
|
meta->level = level;
|
||||||
|
} else {
|
||||||
|
/* Assume audio does not contain voice, it can be detected by another
|
||||||
|
* downstream element. */
|
||||||
|
gst_buffer_add_audio_level_meta (buffer, level, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_cutter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
gst_cutter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
|
@ -355,6 +386,13 @@ gst_cutter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||||
GST_LOG_OBJECT (filter, "buffer stats: NMS %f, RMS %f, audio length %f", NMS,
|
GST_LOG_OBJECT (filter, "buffer stats: NMS %f, RMS %f, audio length %f", NMS,
|
||||||
RMS, gst_guint64_to_gdouble (duration));
|
RMS, gst_guint64_to_gdouble (duration));
|
||||||
|
|
||||||
|
if (filter->audio_level_meta) {
|
||||||
|
gdouble RMSdB = 20 * log10 (RMS + EPSILON);
|
||||||
|
|
||||||
|
buf = gst_buffer_make_writable (buf);
|
||||||
|
set_audio_level_meta (buf, -RMSdB);
|
||||||
|
}
|
||||||
|
|
||||||
if (RMS < filter->threshold_level)
|
if (RMS < filter->threshold_level)
|
||||||
filter->silent_run_length += gst_guint64_to_gdouble (duration);
|
filter->silent_run_length += gst_guint64_to_gdouble (duration);
|
||||||
else {
|
else {
|
||||||
|
@ -469,6 +507,9 @@ gst_cutter_set_property (GObject * object, guint prop_id,
|
||||||
/* set if the pre-record buffer is leaky or not */
|
/* set if the pre-record buffer is leaky or not */
|
||||||
filter->leaky = g_value_get_boolean (value);
|
filter->leaky = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_AUDIO_LEVEL_META:
|
||||||
|
filter->audio_level_meta = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -500,6 +541,9 @@ gst_cutter_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_LEAKY:
|
case PROP_LEAKY:
|
||||||
g_value_set_boolean (value, filter->leaky);
|
g_value_set_boolean (value, filter->leaky);
|
||||||
break;
|
break;
|
||||||
|
case PROP_AUDIO_LEVEL_META:
|
||||||
|
g_value_set_boolean (value, filter->audio_level_meta);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -62,6 +62,7 @@ struct _GstCutter
|
||||||
double pre_run_length; /* how long is it currently ? */
|
double pre_run_length; /* how long is it currently ? */
|
||||||
GList *pre_buffer; /* list of GstBuffers in pre-record buffer */
|
GList *pre_buffer; /* list of GstBuffers in pre-record buffer */
|
||||||
gboolean leaky; /* do we leak an overflowing prebuffer ? */
|
gboolean leaky; /* do we leak an overflowing prebuffer ? */
|
||||||
|
gboolean audio_level_meta; /* whether or not generate GstAudioLevelMeta */
|
||||||
|
|
||||||
GstAudioInfo info;
|
GstAudioInfo info;
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
|
|
Loading…
Reference in a new issue