mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 15:08:53 +00:00
opusenc: allow setting most properties at PLAYING time
Opus allows these to be changed during encoding, transparently to the decoder.
This commit is contained in:
parent
5367aa8dbf
commit
5e1df00674
2 changed files with 64 additions and 15 deletions
|
@ -291,6 +291,8 @@ gst_opus_enc_finalize (GObject * object)
|
||||||
|
|
||||||
enc = GST_OPUS_ENC (object);
|
enc = GST_OPUS_ENC (object);
|
||||||
|
|
||||||
|
g_mutex_free (enc->property_lock);
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +303,8 @@ gst_opus_enc_init (GstOpusEnc * enc, GstOpusEncClass * klass)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (enc, "init");
|
GST_DEBUG_OBJECT (enc, "init");
|
||||||
|
|
||||||
|
enc->property_lock = g_mutex_new ();
|
||||||
|
|
||||||
enc->n_channels = -1;
|
enc->n_channels = -1;
|
||||||
enc->sample_rate = -1;
|
enc->sample_rate = -1;
|
||||||
enc->frame_samples = 0;
|
enc->frame_samples = 0;
|
||||||
|
@ -329,6 +333,7 @@ gst_opus_enc_start (GstAudioEncoder * benc)
|
||||||
GST_DEBUG_OBJECT (enc, "start");
|
GST_DEBUG_OBJECT (enc, "start");
|
||||||
enc->tags = gst_tag_list_new ();
|
enc->tags = gst_tag_list_new ();
|
||||||
enc->header_sent = FALSE;
|
enc->header_sent = FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,6 +366,18 @@ gst_opus_enc_get_latency (GstOpusEnc * enc)
|
||||||
return latency;
|
return latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_opus_enc_setup_base_class (GstOpusEnc * enc, GstAudioEncoder * benc)
|
||||||
|
{
|
||||||
|
gst_audio_encoder_set_latency (benc,
|
||||||
|
gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
|
||||||
|
gst_audio_encoder_set_frame_samples_min (benc,
|
||||||
|
enc->frame_samples * enc->n_channels * 2);
|
||||||
|
gst_audio_encoder_set_frame_samples_max (benc,
|
||||||
|
enc->frame_samples * enc->n_channels * 2);
|
||||||
|
gst_audio_encoder_set_frame_max (benc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
gst_opus_enc_get_frame_samples (GstOpusEnc * enc)
|
gst_opus_enc_get_frame_samples (GstOpusEnc * enc)
|
||||||
{
|
{
|
||||||
|
@ -399,6 +416,8 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
|
||||||
|
|
||||||
enc = GST_OPUS_ENC (benc);
|
enc = GST_OPUS_ENC (benc);
|
||||||
|
|
||||||
|
g_mutex_lock (enc->property_lock);
|
||||||
|
|
||||||
enc->n_channels = GST_AUDIO_INFO_CHANNELS (info);
|
enc->n_channels = GST_AUDIO_INFO_CHANNELS (info);
|
||||||
enc->sample_rate = GST_AUDIO_INFO_RATE (info);
|
enc->sample_rate = GST_AUDIO_INFO_RATE (info);
|
||||||
GST_DEBUG_OBJECT (benc, "Setup with %d channels, %d Hz", enc->n_channels,
|
GST_DEBUG_OBJECT (benc, "Setup with %d channels, %d Hz", enc->n_channels,
|
||||||
|
@ -415,13 +434,9 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
|
||||||
enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
|
enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
|
||||||
|
|
||||||
/* feedback to base class */
|
/* feedback to base class */
|
||||||
gst_audio_encoder_set_latency (benc,
|
gst_opus_enc_setup_base_class (enc, benc);
|
||||||
gst_opus_enc_get_latency (enc), gst_opus_enc_get_latency (enc));
|
|
||||||
gst_audio_encoder_set_frame_samples_min (benc,
|
g_mutex_unlock (enc->property_lock);
|
||||||
enc->frame_samples * enc->n_channels * 2);
|
|
||||||
gst_audio_encoder_set_frame_samples_max (benc,
|
|
||||||
enc->frame_samples * enc->n_channels * 2);
|
|
||||||
gst_audio_encoder_set_frame_max (benc, 0);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -494,9 +509,12 @@ gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
guint8 *bdata, *data, *mdata = NULL;
|
guint8 *bdata, *data, *mdata = NULL;
|
||||||
gsize bsize, size;
|
gsize bsize, size;
|
||||||
gsize bytes = enc->frame_samples * enc->n_channels * 2;
|
gsize bytes;
|
||||||
gint ret = GST_FLOW_OK;
|
gint ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
g_mutex_lock (enc->property_lock);
|
||||||
|
|
||||||
|
bytes = enc->frame_samples * enc->n_channels * 2;
|
||||||
if (G_LIKELY (buf)) {
|
if (G_LIKELY (buf)) {
|
||||||
bdata = GST_BUFFER_DATA (buf);
|
bdata = GST_BUFFER_DATA (buf);
|
||||||
bsize = GST_BUFFER_SIZE (buf);
|
bsize = GST_BUFFER_SIZE (buf);
|
||||||
|
@ -563,6 +581,8 @@ gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
|
g_mutex_unlock (enc->property_lock);
|
||||||
|
|
||||||
if (mdata)
|
if (mdata)
|
||||||
g_free (mdata);
|
g_free (mdata);
|
||||||
|
|
||||||
|
@ -612,6 +632,8 @@ gst_opus_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
|
|
||||||
enc = GST_OPUS_ENC (object);
|
enc = GST_OPUS_ENC (object);
|
||||||
|
|
||||||
|
g_mutex_lock (enc->property_lock);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_AUDIO:
|
case PROP_AUDIO:
|
||||||
g_value_set_boolean (value, enc->audio_or_voip);
|
g_value_set_boolean (value, enc->audio_or_voip);
|
||||||
|
@ -650,6 +672,8 @@ gst_opus_enc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_mutex_unlock (enc->property_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -660,42 +684,64 @@ gst_opus_enc_set_property (GObject * object, guint prop_id,
|
||||||
|
|
||||||
enc = GST_OPUS_ENC (object);
|
enc = GST_OPUS_ENC (object);
|
||||||
|
|
||||||
|
#define GST_OPUS_UPDATE_PROPERTY(prop,type,ctl) do { \
|
||||||
|
g_mutex_lock (enc->property_lock); \
|
||||||
|
enc->prop = g_value_get_##type (value); \
|
||||||
|
if (enc->state) { \
|
||||||
|
opus_encoder_ctl (enc->state, OPUS_SET_##ctl (enc->prop)); \
|
||||||
|
} \
|
||||||
|
g_mutex_unlock (enc->property_lock); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_AUDIO:
|
case PROP_AUDIO:
|
||||||
enc->audio_or_voip = g_value_get_boolean (value);
|
enc->audio_or_voip = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
case PROP_BITRATE:
|
case PROP_BITRATE:
|
||||||
enc->bitrate = g_value_get_int (value);
|
GST_OPUS_UPDATE_PROPERTY (bitrate, int, BITRATE);
|
||||||
break;
|
break;
|
||||||
case PROP_BANDWIDTH:
|
case PROP_BANDWIDTH:
|
||||||
enc->bandwidth = g_value_get_enum (value);
|
GST_OPUS_UPDATE_PROPERTY (bandwidth, enum, BANDWIDTH);
|
||||||
break;
|
break;
|
||||||
case PROP_FRAME_SIZE:
|
case PROP_FRAME_SIZE:
|
||||||
|
g_mutex_lock (enc->property_lock);
|
||||||
enc->frame_size = g_value_get_enum (value);
|
enc->frame_size = g_value_get_enum (value);
|
||||||
|
enc->frame_samples = gst_opus_enc_get_frame_samples (enc);
|
||||||
|
gst_opus_enc_setup_base_class (enc, GST_AUDIO_ENCODER (enc));
|
||||||
|
g_mutex_unlock (enc->property_lock);
|
||||||
break;
|
break;
|
||||||
case PROP_CBR:
|
case PROP_CBR:
|
||||||
|
/* this one has an opposite meaning to the opus ctl... */
|
||||||
|
g_mutex_lock (enc->property_lock);
|
||||||
enc->cbr = g_value_get_boolean (value);
|
enc->cbr = g_value_get_boolean (value);
|
||||||
|
opus_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr));
|
||||||
|
g_mutex_unlock (enc->property_lock);
|
||||||
break;
|
break;
|
||||||
case PROP_CONSTRAINED_VBR:
|
case PROP_CONSTRAINED_VBR:
|
||||||
enc->constrained_vbr = g_value_get_boolean (value);
|
GST_OPUS_UPDATE_PROPERTY (constrained_vbr, boolean, VBR_CONSTRAINT);
|
||||||
break;
|
break;
|
||||||
case PROP_COMPLEXITY:
|
case PROP_COMPLEXITY:
|
||||||
enc->complexity = g_value_get_int (value);
|
GST_OPUS_UPDATE_PROPERTY (complexity, int, COMPLEXITY);
|
||||||
break;
|
break;
|
||||||
case PROP_INBAND_FEC:
|
case PROP_INBAND_FEC:
|
||||||
enc->inband_fec = g_value_get_boolean (value);
|
GST_OPUS_UPDATE_PROPERTY (inband_fec, boolean, INBAND_FEC);
|
||||||
break;
|
break;
|
||||||
case PROP_DTX:
|
case PROP_DTX:
|
||||||
enc->dtx = g_value_get_boolean (value);
|
GST_OPUS_UPDATE_PROPERTY (dtx, boolean, DTX);
|
||||||
break;
|
break;
|
||||||
case PROP_PACKET_LOSS_PERCENT:
|
case PROP_PACKET_LOSS_PERCENT:
|
||||||
enc->packet_loss_percentage = g_value_get_int (value);
|
GST_OPUS_UPDATE_PROPERTY (packet_loss_percentage, int, PACKET_LOSS_PERC);
|
||||||
break;
|
break;
|
||||||
case PROP_MAX_PAYLOAD_SIZE:
|
case PROP_MAX_PAYLOAD_SIZE:
|
||||||
|
g_mutex_lock (enc->property_lock);
|
||||||
enc->max_payload_size = g_value_get_uint (value);
|
enc->max_payload_size = g_value_get_uint (value);
|
||||||
|
g_mutex_unlock (enc->property_lock);
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef GST_OPUS_UPDATE_PROPERTY
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,9 @@ struct _GstOpusEnc {
|
||||||
|
|
||||||
OpusEncoder *state;
|
OpusEncoder *state;
|
||||||
|
|
||||||
|
/* Locks those properties which may be changed at play time */
|
||||||
|
GMutex *property_lock;
|
||||||
|
|
||||||
/* properties */
|
/* properties */
|
||||||
gboolean audio_or_voip;
|
gboolean audio_or_voip;
|
||||||
gint bitrate;
|
gint bitrate;
|
||||||
|
|
Loading…
Reference in a new issue