Better error handling in the Opus API

This commit is contained in:
Jean-Marc Valin 2011-08-29 09:40:57 -04:00
parent 3e7c051853
commit 9d8dc3a3cb
4 changed files with 64 additions and 28 deletions

View file

@ -185,10 +185,11 @@ OPUS_EXPORT int opus_encoder_get_size(int channels);
OPUS_EXPORT OpusEncoder *opus_encoder_create( OPUS_EXPORT OpusEncoder *opus_encoder_create(
int Fs, /* Sampling rate of input signal (Hz) */ int Fs, /* Sampling rate of input signal (Hz) */
int channels, /* Number of channels (1/2) in input signal */ int channels, /* Number of channels (1/2) in input signal */
int application /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */ int application, /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
int *error /* Error code */
); );
OPUS_EXPORT OpusEncoder *opus_encoder_init( OPUS_EXPORT int opus_encoder_init(
OpusEncoder *st, /* Encoder state */ OpusEncoder *st, /* Encoder state */
int Fs, /* Sampling rate of input signal (Hz) */ int Fs, /* Sampling rate of input signal (Hz) */
int channels, /* Number of channels (1/2) in input signal */ int channels, /* Number of channels (1/2) in input signal */
@ -223,10 +224,11 @@ OPUS_EXPORT int opus_decoder_get_size(int channels);
OPUS_EXPORT OpusDecoder *opus_decoder_create( OPUS_EXPORT OpusDecoder *opus_decoder_create(
int Fs, /* Sampling rate of output signal (Hz) */ int Fs, /* Sampling rate of output signal (Hz) */
int channels /* Number of channels (1/2) in output signal */ int channels, /* Number of channels (1/2) in output signal */
int *error /* Error code*/
); );
OPUS_EXPORT OpusDecoder *opus_decoder_init(OpusDecoder *st, OPUS_EXPORT int opus_decoder_init(OpusDecoder *st,
int Fs, /* Sampling rate of output signal (Hz) */ int Fs, /* Sampling rate of output signal (Hz) */
int channels /* Number of channels (1/2) in output signal */ int channels /* Number of channels (1/2) in output signal */
); );

View file

@ -86,19 +86,19 @@ int opus_decoder_get_size(int channels)
} }
OpusDecoder *opus_decoder_init(OpusDecoder *st, int Fs, int channels) int opus_decoder_init(OpusDecoder *st, int Fs, int channels)
{ {
void *silk_dec; void *silk_dec;
CELTDecoder *celt_dec; CELTDecoder *celt_dec;
int ret, silkDecSizeBytes; int ret, silkDecSizeBytes;
if (channels<1 || channels > 2) if (channels<1 || channels > 2)
return NULL; return OPUS_BAD_ARG;
memset(st, 0, opus_decoder_get_size(channels)); memset(st, 0, opus_decoder_get_size(channels));
/* Initialize SILK encoder */ /* Initialize SILK encoder */
ret = silk_Get_Decoder_Size( &silkDecSizeBytes ); ret = silk_Get_Decoder_Size( &silkDecSizeBytes );
if( ret ) { if( ret ) {
return NULL; return OPUS_INTERNAL_ERROR;
} }
silkDecSizeBytes = align(silkDecSizeBytes); silkDecSizeBytes = align(silkDecSizeBytes);
st->silk_dec_offset = align(sizeof(OpusDecoder)); st->silk_dec_offset = align(sizeof(OpusDecoder));
@ -123,18 +123,29 @@ OpusDecoder *opus_decoder_init(OpusDecoder *st, int Fs, int channels)
st->prev_mode = 0; st->prev_mode = 0;
st->frame_size = Fs/400; st->frame_size = Fs/400;
return st; return OPUS_OK;
failure: failure:
free(st); free(st);
return NULL; return OPUS_INTERNAL_ERROR;
} }
OpusDecoder *opus_decoder_create(int Fs, int channels) OpusDecoder *opus_decoder_create(int Fs, int channels, int *error)
{ {
char *raw_state = (char*)malloc(opus_decoder_get_size(channels)); int ret;
if (raw_state == NULL) char *raw_state = (char*)malloc(opus_decoder_get_size(channels));
return NULL; if (raw_state == NULL)
return opus_decoder_init((OpusDecoder*)raw_state, Fs, channels); {
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
ret = opus_decoder_init((OpusDecoder*)raw_state, Fs, channels);
if (ret != OPUS_OK)
{
free(raw_state);
raw_state = NULL;
}
return (OpusDecoder*)raw_state;
} }
static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, opus_val16 *out, static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, opus_val16 *out,

View file

@ -110,7 +110,7 @@ int opus_encoder_get_size(int channels)
return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes; return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes;
} }
OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int application) int opus_encoder_init(OpusEncoder* st, int Fs, int channels, int application)
{ {
void *silk_enc; void *silk_enc;
CELTEncoder *celt_enc; CELTEncoder *celt_enc;
@ -118,17 +118,17 @@ OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int applic
int ret, silkEncSizeBytes; int ret, silkEncSizeBytes;
if (channels > 2 || channels < 1) if (channels > 2 || channels < 1)
return NULL; return OPUS_BAD_ARG;
if (application < OPUS_APPLICATION_VOIP || application > OPUS_APPLICATION_AUDIO) if (application < OPUS_APPLICATION_VOIP || application > OPUS_APPLICATION_AUDIO)
return NULL; return OPUS_BAD_ARG;
if (Fs != 8000 && Fs != 12000 && Fs != 16000 && Fs != 24000 && Fs != 48000) if (Fs != 8000 && Fs != 12000 && Fs != 16000 && Fs != 24000 && Fs != 48000)
return NULL; return OPUS_BAD_ARG;
memset(st, 0, opus_encoder_get_size(channels)); memset(st, 0, opus_encoder_get_size(channels));
/* Create SILK encoder */ /* Create SILK encoder */
ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); ret = silk_Get_Encoder_Size( &silkEncSizeBytes );
if (ret) if (ret)
return NULL; return OPUS_BAD_ARG;
silkEncSizeBytes = align(silkEncSizeBytes); silkEncSizeBytes = align(silkEncSizeBytes);
st->silk_enc_offset = align(sizeof(OpusEncoder)); st->silk_enc_offset = align(sizeof(OpusEncoder));
st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes; st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes;
@ -190,11 +190,11 @@ OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int applic
else else
st->delay_compensation += 2; st->delay_compensation += 2;
return st; return OPUS_OK;
failure: failure:
free(st); free(st);
return NULL; return OPUS_INTERNAL_ERROR;
} }
static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels) static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels)
@ -228,12 +228,25 @@ static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channel
toc |= (channels==2)<<2; toc |= (channels==2)<<2;
return toc; return toc;
} }
OpusEncoder *opus_encoder_create(int Fs, int channels, int mode) OpusEncoder *opus_encoder_create(int Fs, int channels, int mode, int *error)
{ {
char *raw_state = (char *)malloc(opus_encoder_get_size(channels)); int ret;
if (raw_state == NULL) char *raw_state = (char *)malloc(opus_encoder_get_size(channels));
return NULL; if (raw_state == NULL)
return opus_encoder_init((OpusEncoder*)raw_state, Fs, channels, mode); {
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
ret = opus_encoder_init((OpusEncoder*)raw_state, Fs, channels, mode);
if (error)
*error = ret;
if (ret != OPUS_OK)
{
free(raw_state);
raw_state = NULL;
}
return (OpusEncoder*)raw_state;
} }
#ifdef FIXED_POINT #ifdef FIXED_POINT
int opus_encode(OpusEncoder *st, const opus_val16 *pcm, int frame_size, int opus_encode(OpusEncoder *st, const opus_val16 *pcm, int frame_size,

View file

@ -257,8 +257,18 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
enc = opus_encoder_create(sampling_rate, channels, application); enc = opus_encoder_create(sampling_rate, channels, application, &err);
dec = opus_decoder_create(sampling_rate, channels); if (err != OPUS_OK)
{
fprintf(stderr, "Cannot create encoder: %s\n", opus_strerror(err));
return 1;
}
dec = opus_decoder_create(sampling_rate, channels, &err);
if (err != OPUS_OK)
{
fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
return 1;
}
if (enc==NULL) if (enc==NULL)
{ {