summaryrefslogtreecommitdiff
path: root/ext/opus/gstopusdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/opus/gstopusdec.c')
-rw-r--r--ext/opus/gstopusdec.c133
1 files changed, 62 insertions, 71 deletions
diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c
index 23649d2ab..8ca2809a3 100644
--- a/ext/opus/gstopusdec.c
+++ b/ext/opus/gstopusdec.c
@@ -47,6 +47,7 @@
#include "gstopusheader.h"
#include "gstopuscommon.h"
#include "gstopusdec.h"
+#include <gst/pbutils/pbutils.h>
GST_DEBUG_CATEGORY_STATIC (opusdec_debug);
#define GST_CAT_DEFAULT opusdec_debug
@@ -225,6 +226,8 @@ gst_opus_dec_negotiate (GstOpusDec * dec, const GstAudioChannelPosition * pos)
GstAudioInfo info;
if (caps) {
+ gint rate, channels;
+
caps = gst_caps_truncate (caps);
caps = gst_caps_make_writable (caps);
s = gst_caps_get_structure (caps, 0);
@@ -233,13 +236,15 @@ gst_opus_dec_negotiate (GstOpusDec * dec, const GstAudioChannelPosition * pos)
gst_structure_fixate_field_nearest_int (s, "rate", dec->sample_rate);
else
gst_structure_set (s, "rate", G_TYPE_INT, dec->sample_rate, NULL);
- gst_structure_get_int (s, "rate", &dec->sample_rate);
+ gst_structure_get_int (s, "rate", &rate);
+ dec->sample_rate = rate;
if (gst_structure_has_field (s, "channels"))
gst_structure_fixate_field_nearest_int (s, "channels", dec->n_channels);
else
gst_structure_set (s, "channels", G_TYPE_INT, dec->n_channels, NULL);
- gst_structure_get_int (s, "channels", &dec->n_channels);
+ gst_structure_get_int (s, "channels", &channels);
+ dec->n_channels = channels;
gst_caps_unref (caps);
}
@@ -273,7 +278,6 @@ gst_opus_dec_negotiate (GstOpusDec * dec, const GstAudioChannelPosition * pos)
/* but we still need the opus order for later reordering */
if (pos) {
memcpy (dec->opus_pos, pos, sizeof (pos[0]) * dec->n_channels);
- gst_audio_channel_positions_to_valid_order (dec->opus_pos, dec->n_channels);
} else {
dec->opus_pos[0] = GST_AUDIO_CHANNEL_POSITION_INVALID;
}
@@ -284,79 +288,64 @@ gst_opus_dec_negotiate (GstOpusDec * dec, const GstAudioChannelPosition * pos)
static GstFlowReturn
gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf)
{
- const guint8 *data;
GstAudioChannelPosition pos[64];
const GstAudioChannelPosition *posn = NULL;
- GstMapInfo map;
if (!gst_opus_header_is_id_header (buf)) {
GST_ERROR_OBJECT (dec, "Header is not an Opus ID header");
return GST_FLOW_ERROR;
}
- gst_buffer_map (buf, &map, GST_MAP_READ);
- data = map.data;
-
- dec->n_channels = data[9];
- dec->sample_rate = GST_READ_UINT32_LE (data + 12);
- if (dec->sample_rate == 0)
- dec->sample_rate = 48000;
- dec->pre_skip = GST_READ_UINT16_LE (data + 10);
- dec->r128_gain = GST_READ_UINT16_LE (data + 16);
+ if (!gst_codec_utils_opus_parse_header (buf,
+ &dec->sample_rate,
+ &dec->n_channels,
+ &dec->channel_mapping_family,
+ &dec->n_streams,
+ &dec->n_stereo_streams,
+ dec->channel_mapping, &dec->pre_skip, &dec->r128_gain)) {
+ GST_ERROR_OBJECT (dec, "Failed to parse Opus ID header");
+ return GST_FLOW_ERROR;
+ }
dec->r128_gain_volume = gst_opus_dec_get_r128_volume (dec->r128_gain);
+
GST_INFO_OBJECT (dec,
"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 = data[18];
- if (dec->channel_mapping_family == 0) {
- /* implicit mapping */
- GST_INFO_OBJECT (dec, "Channel mapping family 0, implicit mapping");
- dec->n_streams = dec->n_stereo_streams = 1;
- dec->channel_mapping[0] = 0;
- dec->channel_mapping[1] = 1;
- } else {
- dec->n_streams = data[19];
- dec->n_stereo_streams = data[20];
- memcpy (dec->channel_mapping, data + 21, dec->n_channels);
-
- if (dec->channel_mapping_family == 1) {
- GST_INFO_OBJECT (dec, "Channel mapping family 1, Vorbis mapping");
- switch (dec->n_channels) {
- case 1:
- case 2:
- /* nothing */
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- posn = gst_opus_channel_positions[dec->n_channels - 1];
- break;
- default:{
- gint i;
-
- GST_ELEMENT_WARNING (GST_ELEMENT (dec), STREAM, DECODE,
- (NULL), ("Using NONE channel layout for more than 8 channels"));
-
- for (i = 0; i < dec->n_channels; i++)
- pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
-
- posn = pos;
- }
+ if (dec->channel_mapping_family == 1) {
+ GST_INFO_OBJECT (dec, "Channel mapping family 1, Vorbis mapping");
+ switch (dec->n_channels) {
+ case 1:
+ case 2:
+ /* nothing */
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ posn = gst_opus_channel_positions[dec->n_channels - 1];
+ break;
+ default:{
+ gint i;
+
+ GST_ELEMENT_WARNING (GST_ELEMENT (dec), STREAM, DECODE,
+ (NULL), ("Using NONE channel layout for more than 8 channels"));
+
+ for (i = 0; i < dec->n_channels; i++)
+ pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+
+ posn = pos;
}
- } else {
- GST_INFO_OBJECT (dec, "Channel mapping family %d",
- dec->channel_mapping_family);
}
+ } else {
+ GST_INFO_OBJECT (dec, "Channel mapping family %d",
+ dec->channel_mapping_family);
}
gst_opus_dec_negotiate (dec, posn);
- gst_buffer_unmap (buf, &map);
-
return GST_FLOW_OK;
}
@@ -660,8 +649,10 @@ gst_opus_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps)
if (header && G_VALUE_HOLDS (header, GST_TYPE_BUFFER)) {
buf = gst_value_get_buffer (header);
res = gst_opus_dec_parse_header (dec, buf);
- if (res != GST_FLOW_OK)
+ if (res != GST_FLOW_OK) {
+ ret = FALSE;
goto done;
+ }
gst_buffer_replace (&dec->streamheader, buf);
}
@@ -669,26 +660,26 @@ gst_opus_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps)
if (vorbiscomment && G_VALUE_HOLDS (vorbiscomment, GST_TYPE_BUFFER)) {
buf = gst_value_get_buffer (vorbiscomment);
res = gst_opus_dec_parse_comments (dec, buf);
- if (res != GST_FLOW_OK)
+ if (res != GST_FLOW_OK) {
+ ret = FALSE;
goto done;
+ }
gst_buffer_replace (&dec->vorbiscomment, buf);
}
} else {
- /* defaults if not in the caps */
- dec->n_channels = 2;
- dec->sample_rate = 48000;
+ const GstAudioChannelPosition *posn = NULL;
- gst_structure_get_int (s, "channels", &dec->n_channels);
- gst_structure_get_int (s, "rate", &dec->sample_rate);
+ if (!gst_codec_utils_opus_parse_caps (caps, &dec->sample_rate,
+ &dec->n_channels, &dec->channel_mapping_family, &dec->n_streams,
+ &dec->n_stereo_streams, dec->channel_mapping)) {
+ ret = FALSE;
+ goto done;
+ }
- /* default stereo mapping */
- dec->channel_mapping_family = 0;
- dec->channel_mapping[0] = 0;
- dec->channel_mapping[1] = 1;
- dec->n_streams = 1;
- dec->n_stereo_streams = 1;
+ if (dec->channel_mapping_family == 1 && dec->n_channels <= 8)
+ posn = gst_opus_channel_positions[dec->n_channels - 1];
- gst_opus_dec_negotiate (dec, NULL);
+ gst_opus_dec_negotiate (dec, posn);
}
done: