static GstFlowReturn gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf) { GstAudioChannelPosition pos[64]; const GstAudioChannelPosition *posn = NULL; if (!gst_opus_header_is_id_header (buf)) { GST_ELEMENT_ERROR (dec, STREAM, FORMAT, (NULL), ("Header is not an Opus ID header")); return GST_FLOW_ERROR; } 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_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("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); 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); } if (!gst_opus_dec_negotiate (dec, posn)) return GST_FLOW_NOT_NEGOTIATED; return GST_FLOW_OK; }
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; if (!(dec->n_channels == 0 || dec->n_channels == data[9])) { gst_buffer_unmap (buf, &map); GST_ERROR_OBJECT (dec, "Opus ID header has invalid channels"); return GST_FLOW_ERROR; } dec->n_channels = data[9]; dec->sample_rate = GST_READ_UINT32_LE (data + 12); dec->pre_skip = GST_READ_UINT16_LE (data + 10); dec->r128_gain = GST_READ_UINT16_LE (data + 16); 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; } } } 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; }
static GstFlowReturn gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf) { const guint8 *data = GST_BUFFER_DATA (buf); GstCaps *caps; const GstAudioChannelPosition *pos = NULL; if (!gst_opus_header_is_id_header (buf)) { GST_ERROR_OBJECT (dec, "Header is not an Opus ID header"); return GST_FLOW_ERROR; } if (!(dec->n_channels == 0 || dec->n_channels == data[9])) { GST_ERROR_OBJECT (dec, "Opus ID header has invalid channels"); return GST_FLOW_ERROR; } dec->n_channels = data[9]; dec->pre_skip = GST_READ_UINT16_LE (data + 10); dec->r128_gain = GST_READ_UINT16_LE (data + 16); 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: pos = gst_opus_channel_positions[dec->n_channels - 1]; break; default:{ gint i; GstAudioChannelPosition *posn = g_new (GstAudioChannelPosition, dec->n_channels); 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++) posn[i] = GST_AUDIO_CHANNEL_POSITION_NONE; pos = posn; } } } else { GST_INFO_OBJECT (dec, "Channel mapping family %d", dec->channel_mapping_family); } } caps = gst_opus_dec_negotiate (dec); if (pos) { GST_DEBUG_OBJECT (dec, "Setting channel positions on caps"); gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } if (dec->n_channels > 8) { g_free ((GstAudioChannelPosition *) pos); } GST_INFO_OBJECT (dec, "Setting src caps to %" GST_PTR_FORMAT, caps); gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), caps); gst_caps_unref (caps); return GST_FLOW_OK; }