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;
if (dec->state) {
opus_decoder_destroy (dec->state);
opus_multistream_decoder_destroy (dec->state);
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)",
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;
}
@ -298,7 +308,8 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
GST_DEBUG_OBJECT (dec, "Creating decoder with %d channels, %d Hz",
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)
goto creation_failed;
}
@ -350,14 +361,16 @@ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
if (dec->use_inband_fec) {
if (dec->last_buffer) {
/* 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 {
/* 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 {
/* 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) {

View file

@ -23,7 +23,7 @@
#include <gst/gst.h>
#include <gst/audio/gstaudiodecoder.h>
#include <opus/opus.h>
#include <opus/opus_multistream.h>
G_BEGIN_DECLS
@ -44,7 +44,7 @@ typedef struct _GstOpusDecClass GstOpusDecClass;
struct _GstOpusDec {
GstAudioDecoder element;
OpusDecoder *state;
OpusMSDecoder *state;
guint64 packetno;
@ -55,6 +55,8 @@ struct _GstOpusDec {
int n_channels;
guint32 pre_skip;
gint16 r128_gain;
guint8 channel_mapping_family;
guint8 channel_mapping[256];
gboolean apply_gain;
double r128_gain_volume;

View file

@ -355,7 +355,7 @@ gst_opus_enc_stop (GstAudioEncoder * benc)
GST_DEBUG_OBJECT (enc, "stop");
enc->header_sent = FALSE;
if (enc->state) {
opus_encoder_destroy (enc->state);
opus_multistream_encoder_destroy (enc->state);
enc->state = NULL;
}
gst_tag_list_free (enc->tags);
@ -435,7 +435,7 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
/* handle reconfigure */
if (enc->state) {
opus_encoder_destroy (enc->state);
opus_multistream_encoder_destroy (enc->state);
enc->state = NULL;
}
if (!gst_opus_enc_setup (enc))
@ -455,24 +455,34 @@ static gboolean
gst_opus_enc_setup (GstOpusEnc * enc)
{
int error = OPUS_OK;
unsigned char mapping[256];
int n;
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,
&error);
if (!enc->state || error != OPUS_OK)
goto encoder_creation_failed;
opus_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
opus_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth), 0);
opus_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0);
opus_encoder_ctl (enc->state, OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr),
opus_multistream_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
opus_multistream_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth),
0);
opus_encoder_ctl (enc->state, OPUS_SET_COMPLEXITY (enc->complexity), 0);
opus_encoder_ctl (enc->state, OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
opus_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
opus_encoder_ctl (enc->state,
opus_multistream_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0);
opus_multistream_encoder_ctl (enc->state,
OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr), 0);
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);
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);
outsize =
opus_encode (enc->state, (const gint16 *) data, enc->frame_samples,
GST_BUFFER_DATA (outbuf), enc->max_payload_size);
opus_multistream_encode (enc->state, (const gint16 *) data,
enc->frame_samples, GST_BUFFER_DATA (outbuf), enc->max_payload_size);
if (outsize < 0) {
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); \
enc->prop = g_value_get_##type (value); \
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); \
} 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... */
g_mutex_lock (enc->property_lock);
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);
break;
case PROP_CONSTRAINED_VBR:

View file

@ -26,7 +26,7 @@
#include <gst/gst.h>
#include <gst/audio/gstaudioencoder.h>
#include <opus/opus.h>
#include <opus/opus_multistream.h>
G_BEGIN_DECLS
@ -50,7 +50,7 @@ typedef struct _GstOpusEncClass GstOpusEncClass;
struct _GstOpusEnc {
GstAudioEncoder element;
OpusEncoder *state;
OpusMSEncoder *state;
/* Locks those properties which may be changed at play time */
GMutex *property_lock;