diff --git a/src/opus.h b/src/opus.h index d4d62587..a3aed136 100644 --- a/src/opus.h +++ b/src/opus.h @@ -148,6 +148,13 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...); void opus_decoder_destroy(OpusDecoder *st); +int opus_packet_get_bandwidth(const unsigned char *data); +int opus_packet_get_samples_per_frame(const unsigned char *data, int Fs); +int opus_packet_get_nb_channels(const unsigned char *data); +int opus_packet_get_nb_frames(const unsigned char packet[], int len); +int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len); + + #if OPUS_TEST_RANGE_CODER_STATE int opus_encoder_get_final_range(OpusEncoder *st); int opus_decoder_get_final_range(OpusDecoder *st); diff --git a/src/opus_decoder.c b/src/opus_decoder.c index 27ff1ff0..7069b30c 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -84,6 +84,22 @@ static void smooth_fade(const short *in1, const short *in2, short *out, int over } } +static int opus_packet_get_mode(const unsigned char *data) +{ + int mode; + if (data[0]&0x80) + { + mode = MODE_CELT_ONLY; + } else if ((data[0]&0x60) == 0x60) + { + mode = MODE_HYBRID; + } else { + + mode = MODE_SILK_ONLY; + } + return mode; +} + int opus_decode(OpusDecoder *st, const unsigned char *data, int len, short *pcm, int frame_size, int decode_fec) { @@ -109,32 +125,14 @@ int opus_decode(OpusDecoder *st, const unsigned char *data, if (data != NULL) { - /* Decoding mode/bandwidth/framesize from first byte */ - if (data[0]&0x80) - { - mode = MODE_CELT_ONLY; - st->bandwidth = BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3); - if (st->bandwidth == BANDWIDTH_MEDIUMBAND) - st->bandwidth = BANDWIDTH_NARROWBAND; - audiosize = ((data[0]>>3)&0x3); - audiosize = (st->Fs<bandwidth = (data[0]&0x10) ? BANDWIDTH_FULLBAND : BANDWIDTH_SUPERWIDEBAND; - audiosize = (data[0]&0x08) ? st->Fs/50 : st->Fs/100; - } else { - - mode = MODE_SILK_ONLY; - st->bandwidth = BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3); - audiosize = ((data[0]>>3)&0x3); - if (audiosize == 3) - audiosize = st->Fs*60/1000; - else - audiosize = (st->Fs<stream_channels = (data[0]&0x4) ? 2 : 1; - /*printf ("%d %d %d\n", st->mode, st->bandwidth, audiosize);*/ + mode =opus_packet_get_mode(data); + st->bandwidth = opus_packet_get_bandwidth(data); + audiosize = opus_packet_get_samples_per_frame(data, st->Fs); + st->stream_channels = opus_packet_get_nb_channels(data); + if (opus_packet_get_nb_frames(data, len)>1) + { + /* FIXME: Handle the case of multiple frames */ + } len -= 1; data += 1; @@ -373,3 +371,77 @@ int opus_decoder_get_final_range(OpusDecoder *st) return st->rangeFinal; } #endif + + +int opus_packet_get_bandwidth(const unsigned char *data) +{ + int bandwidth; + if (data[0]&0x80) + { + bandwidth = BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3); + if (bandwidth == BANDWIDTH_MEDIUMBAND) + bandwidth = BANDWIDTH_NARROWBAND; + } else if ((data[0]&0x60) == 0x60) + { + bandwidth = (data[0]&0x10) ? BANDWIDTH_FULLBAND : BANDWIDTH_SUPERWIDEBAND; + } else { + + bandwidth = BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3); + } + return bandwidth; +} + +int opus_packet_get_samples_per_frame(const unsigned char *data, int Fs) +{ + int audiosize; + if (data[0]&0x80) + { + audiosize = ((data[0]>>3)&0x3); + audiosize = (Fs<>3)&0x3); + if (audiosize == 3) + audiosize = Fs*60/1000; + else + audiosize = (Fs<Fs); + /* Can't have more than 120 ms */ + if (samples*25 > dec->Fs*3) + return OPUS_CORRUPTED_DATA; + else + return samples; +} +