diff --git a/src/opus.h b/src/opus.h index 1cf61cf1e70cbc5b7f6ce631f286cdf36f676f56..a95659375701a3a29e00e709cfdfac24d7b5086e 100644 --- a/src/opus.h +++ b/src/opus.h @@ -33,11 +33,11 @@ extern "C" { #endif #if defined(__GNUC__) && defined(OPUS_BUILD) -#define EXPORT __attribute__ ((visibility ("default"))) +#define OPUS_EXPORT __attribute__ ((visibility ("default"))) #elif defined(WIN32) -#define EXPORT __declspec(dllexport) +#define OPUS_EXPORT __declspec(dllexport) #else -#define EXPORT +#define OPUS_EXPORT #endif #define __check_int(x) (((void)((x) == (int)0)), (int)(x)) @@ -133,36 +133,40 @@ extern "C" { typedef struct OpusEncoder OpusEncoder; typedef struct OpusDecoder OpusDecoder; -EXPORT OpusEncoder *opus_encoder_create(int Fs, int channels); +OPUS_EXPORT OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels); + +OPUS_EXPORT OpusEncoder *opus_encoder_create(int Fs, int channels); /* returns length of data payload (in bytes) */ -EXPORT int opus_encode(OpusEncoder *st, const short *pcm, int frame_size, +OPUS_EXPORT int opus_encode(OpusEncoder *st, const short *pcm, int frame_size, unsigned char *data, int max_data_bytes); -EXPORT void opus_encoder_destroy(OpusEncoder *st); +OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st); + +OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...); -EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...); +OPUS_EXPORT OpusDecoder *opus_decoder_init(OpusDecoder *st, int Fs, int channels); -EXPORT OpusDecoder *opus_decoder_create(int Fs, int channels); +OPUS_EXPORT OpusDecoder *opus_decoder_create(int Fs, int channels); /* returns (CELT) error code */ -EXPORT int opus_decode(OpusDecoder *st, const unsigned char *data, int len, +OPUS_EXPORT int opus_decode(OpusDecoder *st, const unsigned char *data, int len, short *pcm, int frame_size, int decode_fec); -EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...); +OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...); -EXPORT void opus_decoder_destroy(OpusDecoder *st); +OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st); -EXPORT int opus_packet_get_bandwidth(const unsigned char *data); -EXPORT int opus_packet_get_samples_per_frame(const unsigned char *data, int Fs); -EXPORT int opus_packet_get_nb_channels(const unsigned char *data); -EXPORT int opus_packet_get_nb_frames(const unsigned char packet[], int len); -EXPORT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len); +OPUS_EXPORT int opus_packet_get_bandwidth(const unsigned char *data); +OPUS_EXPORT int opus_packet_get_samples_per_frame(const unsigned char *data, int Fs); +OPUS_EXPORT int opus_packet_get_nb_channels(const unsigned char *data); +OPUS_EXPORT int opus_packet_get_nb_frames(const unsigned char packet[], int len); +OPUS_EXPORT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len); #if OPUS_TEST_RANGE_CODER_STATE -EXPORT int opus_encoder_get_final_range(OpusEncoder *st); -EXPORT int opus_decoder_get_final_range(OpusDecoder *st); +OPUS_EXPORT int opus_encoder_get_final_range(OpusEncoder *st); +OPUS_EXPORT int opus_decoder_get_final_range(OpusDecoder *st); #endif diff --git a/src/opus_decoder.c b/src/opus_decoder.c index 9a4757bc136299b3e82fe163676d7e6b6137f9aa..82453cdf2bfdc410b95ea1ee551d027ec0185bea 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -29,6 +29,7 @@ #include "config.h" #endif +#include <string.h> #include <stdlib.h> #include <stdio.h> #include <stdarg.h> @@ -38,27 +39,44 @@ #include "modes.h" #include "SKP_Silk_SDK_API.h" +/* Make sure everything's aligned to 4 bytes (this may need to be increased + on really weird architectures) */ +static inline int align(int i) +{ + return (i+3)&-4; +} -OpusDecoder *opus_decoder_create(int Fs, int channels) +int opus_decoder_get_size(int channels) +{ + int silkDecSizeBytes, celtDecSizeBytes; + int ret; + ret = SKP_Silk_SDK_Get_Decoder_Size( &silkDecSizeBytes ); + if(ret) + return 0; + silkDecSizeBytes = align(silkDecSizeBytes); + celtDecSizeBytes = celt_decoder_get_size(channels); + return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes; + +} + +OpusDecoder *opus_decoder_init(OpusDecoder *st, int Fs, int channels) { void *silk_dec; CELTDecoder *celt_dec; - char *raw_state; int ret, silkDecSizeBytes, celtDecSizeBytes; - OpusDecoder *st; + memset(st, 0, sizeof(OpusDecoder)); /* Initialize SILK encoder */ ret = SKP_Silk_SDK_Get_Decoder_Size( &silkDecSizeBytes ); if( ret ) { - /* Handle error */ + return NULL; } + silkDecSizeBytes = align(silkDecSizeBytes); celtDecSizeBytes = celt_decoder_get_size(channels); - raw_state = calloc(sizeof(OpusDecoder)+silkDecSizeBytes+celtDecSizeBytes, 1); - st = (OpusDecoder*)raw_state; - st->silk_dec_offset = sizeof(OpusDecoder); - st->celt_dec_offset = sizeof(OpusDecoder)+silkDecSizeBytes; - silk_dec = raw_state+st->silk_dec_offset; - celt_dec = (CELTDecoder*)(raw_state+st->celt_dec_offset); + st->silk_dec_offset = align(sizeof(OpusDecoder)); + st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes; + silk_dec = (char*)st+st->silk_dec_offset; + celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset); st->stream_channels = st->channels = channels; st->Fs = Fs; @@ -66,15 +84,28 @@ OpusDecoder *opus_decoder_create(int Fs, int channels) /* Reset decoder */ ret = SKP_Silk_SDK_InitDecoder( silk_dec ); if( ret ) { - /* Handle error */ + goto failure; } /* Initialize CELT decoder */ - celt_decoder_init(celt_dec, Fs, channels, NULL); + celt_decoder_init(celt_dec, Fs, channels, &ret); + if (ret != CELT_OK) + goto failure; celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0)); st->prev_mode = 0; return st; +failure: + free(st); + return NULL; +} + +OpusDecoder *opus_decoder_create(int Fs, int channels) +{ + char *raw_state = malloc(opus_decoder_get_size(channels)); + if (raw_state == NULL) + return NULL; + return opus_decoder_init((OpusDecoder*)raw_state, Fs, channels); } static void smooth_fade(const short *in1, const short *in2, short *out, diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 117c8b5a82456be5b46959db8036da7e110163c4..ca302ee99fbd82844a998bcb9fd170a864c12c20 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -29,6 +29,7 @@ #include "config.h" #endif +#include <string.h> #include <stdlib.h> #include <stdio.h> #include <stdarg.h> @@ -54,27 +55,42 @@ static const int audio_bandwidth_thresholds[10] = { 33000, 2000, /* SWB<->FB */ }; +/* Make sure everything's aligned to 4 bytes (this may need to be increased + on really weird architectures) */ +static inline int align(int i) +{ + return (i+3)&-4; +} -OpusEncoder *opus_encoder_create(int Fs, int channels) +int opus_encoder_get_size(int channels) +{ + int silkEncSizeBytes, celtEncSizeBytes; + int ret; + ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes ); + if(ret) + return 0; + silkEncSizeBytes = align(silkEncSizeBytes); + celtEncSizeBytes = celt_encoder_get_size(channels); + return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes; + +} + +OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels) { void *silk_enc; CELTEncoder *celt_enc; int err; - char *raw_state; - OpusEncoder *st; int ret, silkEncSizeBytes, celtEncSizeBytes; + memset(st, 0, sizeof(OpusEncoder)); /* Create SILK encoder */ ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes ); if( ret ) return NULL; + silkEncSizeBytes = align(silkEncSizeBytes); celtEncSizeBytes = celt_encoder_get_size(channels); - raw_state = calloc(sizeof(OpusEncoder)+silkEncSizeBytes+celtEncSizeBytes, 1); - if (raw_state == NULL) - return NULL; - st = (OpusEncoder*)raw_state; - st->silk_enc_offset = sizeof(OpusEncoder); - st->celt_enc_offset = sizeof(OpusEncoder)+silkEncSizeBytes; + st->silk_enc_offset = align(sizeof(OpusEncoder)); + st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes; silk_enc = (char*)st+st->silk_enc_offset; celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); @@ -123,6 +139,14 @@ failure: return NULL; } +OpusEncoder *opus_encoder_create(int Fs, int channels) +{ + char *raw_state = malloc(opus_encoder_get_size(channels)); + if (raw_state == NULL) + return NULL; + return opus_encoder_init((OpusEncoder*)raw_state, Fs, channels); +} + int opus_encode(OpusEncoder *st, const short *pcm, int frame_size, unsigned char *data, int max_data_bytes) {