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:
Vincent Penquerc'h 2011-11-23 17:49:58 +00:00
parent e4ae3e89fa
commit 670c365400
4 changed files with 49 additions and 24 deletions

View file

@ -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) {

View file

@ -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;

View file

@ -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:

View file

@ -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;