mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
opus: switch to multistream API
It's very similar to the basic API, and is a superset ot it, which will allow encoding and decoding more than 2 channels.
This commit is contained in:
parent
e4ae3e89fa
commit
670c365400
4 changed files with 49 additions and 24 deletions
|
@ -150,7 +150,7 @@ gst_opus_dec_reset (GstOpusDec * dec)
|
||||||
{
|
{
|
||||||
dec->packetno = 0;
|
dec->packetno = 0;
|
||||||
if (dec->state) {
|
if (dec->state) {
|
||||||
opus_decoder_destroy (dec->state);
|
opus_multistream_decoder_destroy (dec->state);
|
||||||
dec->state = NULL;
|
dec->state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +228,16 @@ gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf)
|
||||||
"Found pre-skip of %u samples, R128 gain %d (volume %f)",
|
"Found pre-skip of %u samples, R128 gain %d (volume %f)",
|
||||||
dec->pre_skip, dec->r128_gain, dec->r128_gain_volume);
|
dec->pre_skip, dec->r128_gain, dec->r128_gain_volume);
|
||||||
|
|
||||||
|
dec->channel_mapping_family = GST_BUFFER_DATA (buf)[18];
|
||||||
|
if (dec->channel_mapping_family != 0) {
|
||||||
|
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
||||||
|
("Decoding error: unsupported channel nmapping family %d",
|
||||||
|
dec->channel_mapping_family), (NULL));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
dec->channel_mapping[0] = 0;
|
||||||
|
dec->channel_mapping[1] = 1;
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +308,8 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "Creating decoder with %d channels, %d Hz",
|
GST_DEBUG_OBJECT (dec, "Creating decoder with %d channels, %d Hz",
|
||||||
dec->n_channels, dec->sample_rate);
|
dec->n_channels, dec->sample_rate);
|
||||||
dec->state = opus_decoder_create (dec->sample_rate, dec->n_channels, &err);
|
dec->state = opus_multistream_decoder_create (dec->sample_rate,
|
||||||
|
dec->n_channels, 1, 1, dec->channel_mapping, &err);
|
||||||
if (!dec->state || err != OPUS_OK)
|
if (!dec->state || err != OPUS_OK)
|
||||||
goto creation_failed;
|
goto creation_failed;
|
||||||
}
|
}
|
||||||
|
@ -350,14 +361,16 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
|
||||||
if (dec->use_inband_fec) {
|
if (dec->use_inband_fec) {
|
||||||
if (dec->last_buffer) {
|
if (dec->last_buffer) {
|
||||||
/* normal delayed decode */
|
/* normal delayed decode */
|
||||||
n = opus_decode (dec->state, data, size, out_data, samples, 0);
|
n = opus_multistream_decode (dec->state, data, size, out_data, samples,
|
||||||
|
0);
|
||||||
} else {
|
} else {
|
||||||
/* FEC reconstruction decode */
|
/* FEC reconstruction decode */
|
||||||
n = opus_decode (dec->state, data, size, out_data, samples, 1);
|
n = opus_multistream_decode (dec->state, data, size, out_data, samples,
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* normal decode */
|
/* normal decode */
|
||||||
n = opus_decode (dec->state, data, size, out_data, samples, 0);
|
n = opus_multistream_decode (dec->state, data, size, out_data, samples, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/audio/gstaudiodecoder.h>
|
#include <gst/audio/gstaudiodecoder.h>
|
||||||
#include <opus/opus.h>
|
#include <opus/opus_multistream.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ typedef struct _GstOpusDecClass GstOpusDecClass;
|
||||||
struct _GstOpusDec {
|
struct _GstOpusDec {
|
||||||
GstAudioDecoder element;
|
GstAudioDecoder element;
|
||||||
|
|
||||||
OpusDecoder *state;
|
OpusMSDecoder *state;
|
||||||
|
|
||||||
guint64 packetno;
|
guint64 packetno;
|
||||||
|
|
||||||
|
@ -55,6 +55,8 @@ struct _GstOpusDec {
|
||||||
int n_channels;
|
int n_channels;
|
||||||
guint32 pre_skip;
|
guint32 pre_skip;
|
||||||
gint16 r128_gain;
|
gint16 r128_gain;
|
||||||
|
guint8 channel_mapping_family;
|
||||||
|
guint8 channel_mapping[256];
|
||||||
|
|
||||||
gboolean apply_gain;
|
gboolean apply_gain;
|
||||||
double r128_gain_volume;
|
double r128_gain_volume;
|
||||||
|
|
|
@ -355,7 +355,7 @@ gst_opus_enc_stop (GstAudioEncoder * benc)
|
||||||
GST_DEBUG_OBJECT (enc, "stop");
|
GST_DEBUG_OBJECT (enc, "stop");
|
||||||
enc->header_sent = FALSE;
|
enc->header_sent = FALSE;
|
||||||
if (enc->state) {
|
if (enc->state) {
|
||||||
opus_encoder_destroy (enc->state);
|
opus_multistream_encoder_destroy (enc->state);
|
||||||
enc->state = NULL;
|
enc->state = NULL;
|
||||||
}
|
}
|
||||||
gst_tag_list_free (enc->tags);
|
gst_tag_list_free (enc->tags);
|
||||||
|
@ -435,7 +435,7 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
|
||||||
|
|
||||||
/* handle reconfigure */
|
/* handle reconfigure */
|
||||||
if (enc->state) {
|
if (enc->state) {
|
||||||
opus_encoder_destroy (enc->state);
|
opus_multistream_encoder_destroy (enc->state);
|
||||||
enc->state = NULL;
|
enc->state = NULL;
|
||||||
}
|
}
|
||||||
if (!gst_opus_enc_setup (enc))
|
if (!gst_opus_enc_setup (enc))
|
||||||
|
@ -455,24 +455,34 @@ static gboolean
|
||||||
gst_opus_enc_setup (GstOpusEnc * enc)
|
gst_opus_enc_setup (GstOpusEnc * enc)
|
||||||
{
|
{
|
||||||
int error = OPUS_OK;
|
int error = OPUS_OK;
|
||||||
|
unsigned char mapping[256];
|
||||||
|
int n;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (enc, "setup");
|
GST_DEBUG_OBJECT (enc, "setup");
|
||||||
|
|
||||||
enc->state = opus_encoder_create (enc->sample_rate, enc->n_channels,
|
for (n = 0; n < enc->n_channels; ++n)
|
||||||
|
mapping[n] = n;
|
||||||
|
|
||||||
|
enc->state =
|
||||||
|
opus_multistream_encoder_create (enc->sample_rate, enc->n_channels,
|
||||||
|
(enc->n_channels + 1) / 2, enc->n_channels / 2, mapping,
|
||||||
enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP,
|
enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP,
|
||||||
&error);
|
&error);
|
||||||
if (!enc->state || error != OPUS_OK)
|
if (!enc->state || error != OPUS_OK)
|
||||||
goto encoder_creation_failed;
|
goto encoder_creation_failed;
|
||||||
|
|
||||||
opus_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
|
opus_multistream_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
|
||||||
opus_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth), 0);
|
opus_multistream_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth),
|
||||||
opus_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0);
|
|
||||||
opus_encoder_ctl (enc->state, OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr),
|
|
||||||
0);
|
0);
|
||||||
opus_encoder_ctl (enc->state, OPUS_SET_COMPLEXITY (enc->complexity), 0);
|
opus_multistream_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0);
|
||||||
opus_encoder_ctl (enc->state, OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
|
opus_multistream_encoder_ctl (enc->state,
|
||||||
opus_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
|
OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr), 0);
|
||||||
opus_encoder_ctl (enc->state,
|
opus_multistream_encoder_ctl (enc->state,
|
||||||
|
OPUS_SET_COMPLEXITY (enc->complexity), 0);
|
||||||
|
opus_multistream_encoder_ctl (enc->state,
|
||||||
|
OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
|
||||||
|
opus_multistream_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
|
||||||
|
opus_multistream_encoder_ctl (enc->state,
|
||||||
OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0);
|
OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0);
|
||||||
|
|
||||||
GST_LOG_OBJECT (enc, "we have frame size %d", enc->frame_size);
|
GST_LOG_OBJECT (enc, "we have frame size %d", enc->frame_size);
|
||||||
|
@ -557,8 +567,8 @@ gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
|
||||||
enc->frame_samples);
|
enc->frame_samples);
|
||||||
|
|
||||||
outsize =
|
outsize =
|
||||||
opus_encode (enc->state, (const gint16 *) data, enc->frame_samples,
|
opus_multistream_encode (enc->state, (const gint16 *) data,
|
||||||
GST_BUFFER_DATA (outbuf), enc->max_payload_size);
|
enc->frame_samples, GST_BUFFER_DATA (outbuf), enc->max_payload_size);
|
||||||
|
|
||||||
if (outsize < 0) {
|
if (outsize < 0) {
|
||||||
GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize);
|
GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize);
|
||||||
|
@ -694,7 +704,7 @@ gst_opus_enc_set_property (GObject * object, guint prop_id,
|
||||||
g_mutex_lock (enc->property_lock); \
|
g_mutex_lock (enc->property_lock); \
|
||||||
enc->prop = g_value_get_##type (value); \
|
enc->prop = g_value_get_##type (value); \
|
||||||
if (enc->state) { \
|
if (enc->state) { \
|
||||||
opus_encoder_ctl (enc->state, OPUS_SET_##ctl (enc->prop)); \
|
opus_multistream_encoder_ctl (enc->state, OPUS_SET_##ctl (enc->prop)); \
|
||||||
} \
|
} \
|
||||||
g_mutex_unlock (enc->property_lock); \
|
g_mutex_unlock (enc->property_lock); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
@ -720,7 +730,7 @@ gst_opus_enc_set_property (GObject * object, guint prop_id,
|
||||||
/* this one has an opposite meaning to the opus ctl... */
|
/* this one has an opposite meaning to the opus ctl... */
|
||||||
g_mutex_lock (enc->property_lock);
|
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));
|
opus_multistream_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr));
|
||||||
g_mutex_unlock (enc->property_lock);
|
g_mutex_unlock (enc->property_lock);
|
||||||
break;
|
break;
|
||||||
case PROP_CONSTRAINED_VBR:
|
case PROP_CONSTRAINED_VBR:
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/audio/gstaudioencoder.h>
|
#include <gst/audio/gstaudioencoder.h>
|
||||||
|
|
||||||
#include <opus/opus.h>
|
#include <opus/opus_multistream.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ typedef struct _GstOpusEncClass GstOpusEncClass;
|
||||||
struct _GstOpusEnc {
|
struct _GstOpusEnc {
|
||||||
GstAudioEncoder element;
|
GstAudioEncoder element;
|
||||||
|
|
||||||
OpusEncoder *state;
|
OpusMSEncoder *state;
|
||||||
|
|
||||||
/* Locks those properties which may be changed at play time */
|
/* Locks those properties which may be changed at play time */
|
||||||
GMutex *property_lock;
|
GMutex *property_lock;
|
||||||
|
|
Loading…
Reference in a new issue