OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error) { int ret; OpusDecoder *st = NULL; if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000) || (channels!=1&&channels!=2)) { if (error) *error = OPUS_BAD_ARG; return NULL; } if (STATIC_DECODER_SIZE >= opus_decoder_get_size(channels)) st = (OpusDecoder *)s_dec; else st = (OpusDecoder *)opus_alloc(opus_decoder_get_size(channels)); if (st == NULL) { if (error) *error = OPUS_ALLOC_FAIL; return NULL; } ret = opus_decoder_init(st, Fs, channels); if (error) *error = ret; if (ret != OPUS_OK) { opus_free(st); st = NULL; } return st; }
opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams) { int coupled_size; int mono_size; if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0; coupled_size = opus_decoder_get_size(2); mono_size = opus_decoder_get_size(1); return align(sizeof(OpusMSDecoder)) + nb_coupled_streams * align(coupled_size) + (nb_streams-nb_coupled_streams) * align(mono_size); }
bool FVoiceDecoderOpus::Init(int32 InSampleRate, int32 InNumChannels) { UE_LOG(LogVoiceDecode, Display, TEXT("DecoderVersion: %s"), ANSI_TO_TCHAR(opus_get_version_string())); SampleRate = InSampleRate; NumChannels = InNumChannels; FrameSize = SampleRate / 50; int32 DecSize = 0; int32 DecError = 0; #if USE_UE4_MEM_ALLOC DecSize = opus_decoder_get_size(NumChannels); Decoder = (OpusDecoder*)FMemory::Malloc(DecSize); DecError = opus_decoder_init(Decoder, SampleRate, NumChannels); #else Decoder = opus_decoder_create(SampleRate, NumChannels, &DecError); #endif if (DecError != OPUS_OK) { UE_LOG(LogVoiceDecode, Warning, TEXT("Failed to init Opus Decoder: %s"), ANSI_TO_TCHAR(opus_strerror(DecError))); Destroy(); } return DecError == OPUS_OK; }
int opus_multistream_decoder_init( OpusMSDecoder *st, opus_int32 Fs, int channels, int streams, int coupled_streams, const unsigned char *mapping ) { int coupled_size; int mono_size; int i, ret; char *ptr; if ((channels>255) || (channels<1) || (coupled_streams>streams) || (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) return OPUS_BAD_ARG; st->layout.nb_channels = channels; st->layout.nb_streams = streams; st->layout.nb_coupled_streams = coupled_streams; for (i=0;i<st->layout.nb_channels;i++) st->layout.mapping[i] = mapping[i]; if (!validate_layout(&st->layout)) return OPUS_BAD_ARG; ptr = (char*)st + align(sizeof(OpusMSDecoder)); coupled_size = opus_decoder_get_size(2); mono_size = opus_decoder_get_size(1); for (i=0;i<st->layout.nb_coupled_streams;i++) { ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2); if(ret!=OPUS_OK)return ret; ptr += align(coupled_size); } for (;i<st->layout.nb_streams;i++) { ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1); if(ret!=OPUS_OK)return ret; ptr += align(mono_size); } return OPUS_OK; }
JNIEXPORT jboolean JNICALL Java_com_score_rahasak_utils_OpusDecoder_nativeInitDecoder (JNIEnv *env, jobject obj, jint samplingRate, jint numberOfChannels, jint frameSize) { FRAME_SIZE = frameSize; SAMPLING_RATE = samplingRate; CHANNELS = numberOfChannels; int size; int error; size = opus_decoder_get_size(CHANNELS); dec = malloc(size); error = opus_decoder_init(dec, SAMPLING_RATE, CHANNELS); sprintf(logMsg, "Initialized Decoder with ErrorCode: %d", error); __android_log_write(ANDROID_LOG_DEBUG, "Native Code:", logMsg); return error; }
int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels) { void *silk_dec; CELTDecoder *celt_dec; int ret, silkDecSizeBytes; if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000) || (channels!=1&&channels!=2)) return OPUS_BAD_ARG; OPUS_CLEAR((char*)st, opus_decoder_get_size(channels)); /* Initialize SILK encoder */ ret = silk_Get_Decoder_Size(&silkDecSizeBytes); if (ret) return OPUS_INTERNAL_ERROR; silkDecSizeBytes = align(silkDecSizeBytes); 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; st->DecControl.API_sampleRate = st->Fs; st->DecControl.nChannelsAPI = st->channels; st->arch = opus_select_arch(); /* Reset decoder */ ret = silk_InitDecoder( silk_dec ); if(ret)return OPUS_INTERNAL_ERROR; /* Initialize CELT decoder */ ret = celt_decoder_init(celt_dec, Fs, channels); if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR; celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0)); st->prev_mode = 0; st->frame_size = Fs/400; return OPUS_OK; }
int test_decoder_code0(int no_fuzz) { static const opus_int32 fsv[5]={48000,24000,16000,12000,8000}; int err,skip,plen; int out_samples,fec; int t; opus_int32 i; OpusDecoder *dec[5*2]; opus_int32 decsize; OpusDecoder *decbak; opus_uint32 dec_final_range1,dec_final_range2,dec_final_acc; unsigned char *packet; unsigned char modes[4096]; short *outbuf_int; short *outbuf; dec_final_range1=dec_final_range2=2; packet=malloc(sizeof(unsigned char)*MAX_PACKET); if(packet==NULL)test_failed(); outbuf_int=malloc(sizeof(short)*(MAX_FRAME_SAMP+16)*2); for(i=0;i<(MAX_FRAME_SAMP+16)*2;i++)outbuf_int[i]=32749; outbuf=&outbuf_int[8*2]; fprintf(stdout," Starting %d decoders...\n",5*2); for(t=0;t<5*2;t++) { int fs=fsv[t>>1]; int c=(t&1)+1; err=OPUS_INTERNAL_ERROR; dec[t] = opus_decoder_create(fs, c, &err); if(err!=OPUS_OK || dec[t]==NULL)test_failed(); fprintf(stdout," opus_decoder_create(%5d,%d) OK. Copy ",fs,c); { OpusDecoder *dec2; /*The opus state structures contain no pointers and can be freely copied*/ dec2=(OpusDecoder *)malloc(opus_decoder_get_size(c)); if(dec2==NULL)test_failed(); memcpy(dec2,dec[t],opus_decoder_get_size(c)); memset(dec[t],255,opus_decoder_get_size(c)); opus_decoder_destroy(dec[t]); printf("OK.\n"); dec[t]=dec2; } } decsize=opus_decoder_get_size(1); decbak=(OpusDecoder *)malloc(decsize); if(decbak==NULL)test_failed(); for(t=0;t<5*2;t++) { int factor=48000/fsv[t>>1]; for(fec=0;fec<2;fec++) { opus_int32 dur; /*Test PLC on a fresh decoder*/ out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor, fec); if(out_samples!=120/factor)test_failed(); if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); if(dur!=120/factor)test_failed(); /*Test on a size which isn't a multiple of 2.5ms*/ out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor+2, fec); if(out_samples!=OPUS_BAD_ARG)test_failed(); /*Test null pointer input*/ out_samples = opus_decode(dec[t], 0, -1, outbuf, 120/factor, fec); if(out_samples!=120/factor)test_failed(); out_samples = opus_decode(dec[t], 0, 1, outbuf, 120/factor, fec); if(out_samples!=120/factor)test_failed(); out_samples = opus_decode(dec[t], 0, 10, outbuf, 120/factor, fec); if(out_samples!=120/factor)test_failed(); out_samples = opus_decode(dec[t], 0, fast_rand(), outbuf, 120/factor, fec); if(out_samples!=120/factor)test_failed(); if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); if(dur!=120/factor)test_failed(); /*Zero lengths*/ out_samples = opus_decode(dec[t], packet, 0, outbuf, 120/factor, fec); if(out_samples!=120/factor)test_failed(); /*Zero buffer*/ outbuf[0]=32749; out_samples = opus_decode(dec[t], packet, 0, outbuf, 0, fec); if(out_samples>0)test_failed(); #if !defined(OPUS_BUILD) && (OPUS_GNUC_PREREQ(4, 6) || (defined(__clang_major__) && __clang_major__ >= 3)) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnonnull" #endif out_samples = opus_decode(dec[t], packet, 0, 0, 0, fec); #if !defined(OPUS_BUILD) && (OPUS_GNUC_PREREQ(4, 6) || (defined(__clang_major__) && __clang_major__ >= 3)) #pragma GCC diagnostic pop #endif if(out_samples>0)test_failed(); if(outbuf[0]!=32749)test_failed(); /*Invalid lengths*/ out_samples = opus_decode(dec[t], packet, -1, outbuf, MAX_FRAME_SAMP, fec); if(out_samples>=0)test_failed(); out_samples = opus_decode(dec[t], packet, INT_MIN, outbuf, MAX_FRAME_SAMP, fec); if(out_samples>=0)test_failed(); out_samples = opus_decode(dec[t], packet, -1, outbuf, -1, fec); if(out_samples>=0)test_failed(); /*Crazy FEC values*/ out_samples = opus_decode(dec[t], packet, 1, outbuf, MAX_FRAME_SAMP, fec?-1:2); if(out_samples>=0)test_failed(); /*Reset the decoder*/ if(opus_decoder_ctl(dec[t], OPUS_RESET_STATE)!=OPUS_OK)test_failed(); } } fprintf(stdout," dec[all] initial frame PLC OK.\n"); /*Count code 0 tests*/ for(i=0;i<64;i++) { opus_int32 dur; int j,expected[5*2]; packet[0]=i<<2; packet[1]=255; packet[2]=255; err=opus_packet_get_nb_channels(packet); if(err!=(i&1)+1)test_failed(); for(t=0;t<5*2;t++){ expected[t]=opus_decoder_get_nb_samples(dec[t],packet,1); if(expected[t]>2880)test_failed(); } for(j=0;j<256;j++) { packet[1]=j; for(t=0;t<5*2;t++) { out_samples = opus_decode(dec[t], packet, 3, outbuf, MAX_FRAME_SAMP, 0); if(out_samples!=expected[t])test_failed(); if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); if(dur!=out_samples)test_failed(); opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1)); if(t==0)dec_final_range2=dec_final_range1; else if(dec_final_range1!=dec_final_range2)test_failed(); } } for(t=0;t<5*2;t++){ int factor=48000/fsv[t>>1]; /* The PLC is run for 6 frames in order to get better PLC coverage. */ for(j=0;j<6;j++) { out_samples = opus_decode(dec[t], 0, 0, outbuf, expected[t], 0); if(out_samples!=expected[t])test_failed(); if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); if(dur!=out_samples)test_failed(); } /* Run the PLC once at 2.5ms, as a simulation of someone trying to do small drift corrections. */ if(expected[t]!=120/factor) { out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor, 0); if(out_samples!=120/factor)test_failed(); if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); if(dur!=out_samples)test_failed(); } out_samples = opus_decode(dec[t], packet, 2, outbuf, expected[t]-1, 0); if(out_samples>0)test_failed(); } } fprintf(stdout," dec[all] all 2-byte prefix for length 3 and PLC, all modes (64) OK.\n"); if(no_fuzz) { fprintf(stdout," Skipping many tests which fuzz the decoder as requested.\n"); free(decbak); for(t=0;t<5*2;t++)opus_decoder_destroy(dec[t]); printf(" Decoders stopped.\n"); err=0; for(i=0;i<8*2;i++)err|=outbuf_int[i]!=32749; for(i=MAX_FRAME_SAMP*2;i<(MAX_FRAME_SAMP+8)*2;i++)err|=outbuf[i]!=32749; if(err)test_failed(); free(outbuf_int); free(packet); return 0; } { /*We only test a subset of the modes here simply because the longer durations end up taking a long time.*/ static const int cmodes[4]={16,20,24,28}; static const opus_uint32 cres[4]={116290185,2172123586u,2172123586u,2172123586u}; static const opus_uint32 lres[3]={3285687739u,1481572662,694350475}; static const int lmodes[3]={0,4,8}; int mode=fast_rand()%4; packet[0]=cmodes[mode]<<3; dec_final_acc=0; t=fast_rand()%10; for(i=0;i<65536;i++) { int factor=48000/fsv[t>>1]; packet[1]=i>>8; packet[2]=i&255; packet[3]=255; out_samples = opus_decode(dec[t], packet, 4, outbuf, MAX_FRAME_SAMP, 0); if(out_samples!=120/factor)test_failed(); opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1)); dec_final_acc+=dec_final_range1; } if(dec_final_acc!=cres[mode])test_failed(); fprintf(stdout," dec[%3d] all 3-byte prefix for length 4, mode %2d OK.\n",t,cmodes[mode]); mode=fast_rand()%3; packet[0]=lmodes[mode]<<3; dec_final_acc=0; t=fast_rand()%10; for(i=0;i<65536;i++) { int factor=48000/fsv[t>>1]; packet[1]=i>>8; packet[2]=i&255; packet[3]=255; out_samples = opus_decode(dec[t], packet, 4, outbuf, MAX_FRAME_SAMP, 0); if(out_samples!=480/factor)test_failed(); opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1)); dec_final_acc+=dec_final_range1; } if(dec_final_acc!=lres[mode])test_failed(); fprintf(stdout," dec[%3d] all 3-byte prefix for length 4, mode %2d OK.\n",t,lmodes[mode]); } skip=fast_rand()%7; for(i=0;i<64;i++) { int j,expected[5*2]; packet[0]=i<<2; for(t=0;t<5*2;t++)expected[t]=opus_decoder_get_nb_samples(dec[t],packet,1); for(j=2+skip;j<1275;j+=4) { int jj; for(jj=0;jj<j;jj++)packet[jj+1]=fast_rand()&255; for(t=0;t<5*2;t++) { out_samples = opus_decode(dec[t], packet, j+1, outbuf, MAX_FRAME_SAMP, 0); if(out_samples!=expected[t])test_failed(); opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1)); if(t==0)dec_final_range2=dec_final_range1; else if(dec_final_range1!=dec_final_range2)test_failed(); } } } fprintf(stdout," dec[all] random packets, all modes (64), every 8th size from from %d bytes to maximum OK.\n",2+skip); debruijn2(64,modes); plen=(fast_rand()%18+3)*8+skip+3; for(i=0;i<4096;i++) { int j,expected[5*2]; packet[0]=modes[i]<<2; for(t=0;t<5*2;t++)expected[t]=opus_decoder_get_nb_samples(dec[t],packet,plen); for(j=0;j<plen;j++)packet[j+1]=(fast_rand()|fast_rand())&255; memcpy(decbak,dec[0],decsize); if(opus_decode(decbak, packet, plen+1, outbuf, expected[0], 1)!=expected[0])test_failed(); memcpy(decbak,dec[0],decsize); if(opus_decode(decbak, 0, 0, outbuf, MAX_FRAME_SAMP, 1)<20)test_failed(); memcpy(decbak,dec[0],decsize); if(opus_decode(decbak, 0, 0, outbuf, MAX_FRAME_SAMP, 0)<20)test_failed(); for(t=0;t<5*2;t++) { opus_int32 dur; out_samples = opus_decode(dec[t], packet, plen+1, outbuf, MAX_FRAME_SAMP, 0); if(out_samples!=expected[t])test_failed(); if(t==0)dec_final_range2=dec_final_range1; else if(dec_final_range1!=dec_final_range2)test_failed(); if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); if(dur!=out_samples)test_failed(); } } fprintf(stdout," dec[all] random packets, all mode pairs (4096), %d bytes/frame OK.\n",plen+1); plen=(fast_rand()%18+3)*8+skip+3; t=rand()&3; for(i=0;i<4096;i++) { int count,j,expected; packet[0]=modes[i]<<2; expected=opus_decoder_get_nb_samples(dec[t],packet,plen); for(count=0;count<10;count++) { for(j=0;j<plen;j++)packet[j+1]=(fast_rand()|fast_rand())&255; out_samples = opus_decode(dec[t], packet, plen+1, outbuf, MAX_FRAME_SAMP, 0); if(out_samples!=expected)test_failed(); } } fprintf(stdout," dec[%3d] random packets, all mode pairs (4096)*10, %d bytes/frame OK.\n",t,plen+1); { int tmodes[1]={25<<2}; opus_uint32 tseeds[1]={140441}; int tlen[1]={157}; opus_int32 tret[1]={480}; t=fast_rand()&1; for(i=0;i<1;i++) { int j; packet[0]=tmodes[i]; Rw=Rz=tseeds[i]; for(j=1;j<tlen[i];j++)packet[j]=fast_rand()&255; out_samples=opus_decode(dec[t], packet, tlen[i], outbuf, MAX_FRAME_SAMP, 0); if(out_samples!=tret[i])test_failed(); } fprintf(stdout," dec[%3d] pre-selected random packets OK.\n",t); } free(decbak); for(t=0;t<5*2;t++)opus_decoder_destroy(dec[t]); printf(" Decoders stopped.\n"); err=0; for(i=0;i<8*2;i++)err|=outbuf_int[i]!=32749; for(i=MAX_FRAME_SAMP*2;i<(MAX_FRAME_SAMP+8)*2;i++)err|=outbuf[i]!=32749; if(err)test_failed(); free(outbuf_int); free(packet); return 0; }
/* * Open codec. */ static pj_status_t codec_open( pjmedia_codec *codec, pjmedia_codec_param *attr ) { struct opus_data *opus_data = (struct opus_data *)codec->codec_data; int idx, err; PJ_ASSERT_RETURN(codec && attr && opus_data, PJ_EINVAL); pj_mutex_lock (opus_data->mutex); TRACE_((THIS_FILE, "%s:%d: - TRACE", __FUNCTION__, __LINE__)); opus_data->cfg.sample_rate = attr->info.clock_rate; opus_data->cfg.channel_cnt = attr->info.channel_cnt; opus_data->ptime = attr->info.frm_ptime; /* Allocate memory used by the codec */ if (!opus_data->enc) { /* Allocate memory for max 2 channels */ opus_data->enc = pj_pool_zalloc(opus_data->pool, opus_encoder_get_size(2)); } if (!opus_data->dec) { /* Allocate memory for max 2 channels */ opus_data->dec = pj_pool_zalloc(opus_data->pool, opus_decoder_get_size(2)); } if (!opus_data->enc_packer) { opus_data->enc_packer = pj_pool_zalloc(opus_data->pool, opus_repacketizer_get_size()); } if (!opus_data->dec_packer) { opus_data->dec_packer = pj_pool_zalloc(opus_data->pool, opus_repacketizer_get_size()); } if (!opus_data->enc || !opus_data->dec || !opus_data->enc_packer || !opus_data->dec_packer) { PJ_LOG(2, (THIS_FILE, "Unable to allocate memory for the codec")); pj_mutex_unlock (opus_data->mutex); return PJ_ENOMEM; } /* Check max average bit rate */ idx = find_fmtp(&attr->setting.enc_fmtp, &STR_MAX_BIT_RATE, PJ_FALSE); if (idx >= 0) { unsigned rate; rate = (unsigned)pj_strtoul(&attr->setting.enc_fmtp.param[idx].val); if (rate < attr->info.avg_bps) attr->info.avg_bps = rate; } /* Check plc */ idx = find_fmtp(&attr->setting.enc_fmtp, &STR_INBAND_FEC, PJ_FALSE); if (idx >= 0) { unsigned plc; plc = (unsigned) pj_strtoul(&attr->setting.enc_fmtp.param[idx].val); attr->setting.plc = plc > 0? PJ_TRUE: PJ_FALSE; } /* Check vad */ idx = find_fmtp(&attr->setting.enc_fmtp, &STR_DTX, PJ_FALSE); if (idx >= 0) { unsigned vad; vad = (unsigned) pj_strtoul(&attr->setting.enc_fmtp.param[idx].val); attr->setting.vad = vad > 0? PJ_TRUE: PJ_FALSE; } /* Check cbr */ idx = find_fmtp(&attr->setting.enc_fmtp, &STR_CBR, PJ_FALSE); if (idx >= 0) { unsigned cbr; cbr = (unsigned) pj_strtoul(&attr->setting.enc_fmtp.param[idx].val); opus_data->cfg.cbr = cbr > 0? PJ_TRUE: PJ_FALSE; } /* Check max average bit rate */ idx = find_fmtp(&attr->setting.dec_fmtp, &STR_MAX_BIT_RATE, PJ_FALSE); if (idx >= 0) { unsigned rate; rate = (unsigned) pj_strtoul(&attr->setting.dec_fmtp.param[idx].val); if (rate < attr->info.avg_bps) attr->info.avg_bps = rate; } TRACE_((THIS_FILE, "%s:%d: sample_rate: %u", __FUNCTION__, __LINE__, opus_data->cfg.sample_rate)); /* Initialize encoder */ err = opus_encoder_init(opus_data->enc, opus_data->cfg.sample_rate, attr->info.channel_cnt, OPUS_APPLICATION_VOIP); if (err != OPUS_OK) { PJ_LOG(2, (THIS_FILE, "Unable to create encoder")); return PJMEDIA_CODEC_EFAILED; } /* Set signal type */ opus_encoder_ctl(opus_data->enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE)); /* Set bitrate */ opus_encoder_ctl(opus_data->enc, OPUS_SET_BITRATE(attr->info.avg_bps)); /* Set VAD */ opus_encoder_ctl(opus_data->enc, OPUS_SET_DTX(attr->setting.vad ? 1 : 0)); /* Set PLC */ opus_encoder_ctl(opus_data->enc, OPUS_SET_INBAND_FEC(attr->setting.plc ? 1 : 0)); /* Set bandwidth */ opus_encoder_ctl(opus_data->enc, OPUS_SET_MAX_BANDWIDTH(get_opus_bw_constant( opus_data->cfg.sample_rate))); /* Set expected packet loss */ opus_encoder_ctl(opus_data->enc, OPUS_SET_PACKET_LOSS_PERC(opus_data->cfg.packet_loss)); /* Set complexity */ opus_encoder_ctl(opus_data->enc, OPUS_SET_COMPLEXITY(opus_data->cfg.complexity)); /* Set constant bit rate */ opus_encoder_ctl(opus_data->enc, OPUS_SET_VBR(opus_data->cfg.cbr ? 0 : 1)); PJ_LOG(5, (THIS_FILE, "Initialize Opus encoder, sample rate: %d, " "avg bitrate: %d, vad: %d, plc: %d, pkt loss: %d, " "complexity: %d, constant bit rate: %d", opus_data->cfg.sample_rate, attr->info.avg_bps, attr->setting.vad?1:0, attr->setting.plc?1:0, opus_data->cfg.packet_loss, opus_data->cfg.complexity, opus_data->cfg.cbr?1:0)); /* Initialize decoder */ err = opus_decoder_init (opus_data->dec, opus_data->cfg.sample_rate, attr->info.channel_cnt); if (err != OPUS_OK) { PJ_LOG(2, (THIS_FILE, "Unable to initialize decoder")); return PJMEDIA_CODEC_EFAILED; } /* Initialize temporary decode frames used for FEC */ opus_data->dec_frame[0].type = PJMEDIA_FRAME_TYPE_NONE; opus_data->dec_frame[0].buf = pj_pool_zalloc(opus_data->pool, (opus_data->cfg.sample_rate / 1000) * 60 * attr->info.channel_cnt * 2 /* bytes per sample */); opus_data->dec_frame[1].type = PJMEDIA_FRAME_TYPE_NONE; opus_data->dec_frame[1].buf = pj_pool_zalloc(opus_data->pool, (opus_data->cfg.sample_rate / 1000) * 60 * attr->info.channel_cnt * 2 /* bytes per sample */); opus_data->dec_frame_index = -1; /* Initialize the repacketizers */ opus_repacketizer_init(opus_data->enc_packer); opus_repacketizer_init(opus_data->dec_packer); pj_mutex_unlock (opus_data->mutex); return PJ_SUCCESS; }
/* * Open codec. */ static pj_status_t opus_codec_open(pjmedia_codec *codec, pjmedia_codec_param *attr) { pj_status_t status; struct opus_private *opus; int id, ret = 0; unsigned i; int structSizeBytes; int tmpFmtpVal = 0; unsigned max_nsamples; const pj_str_t STR_FMTP_USE_INBAND_FEC = {"useinbandfec", 12}; const pj_str_t STR_FMTP_MAX_AVERAGE_BITRATE = {"maxaveragebitrate", 17}; const pj_str_t STR_FMTP_MAX_CODED_AUDIO_BANDWIDTH = {"maxplaybackrate", 15}; const pj_str_t STR_FMTP_USE_DTX = {"usedtx", 6}; opus = (struct opus_private *)codec->codec_data; pj_assert(opus != NULL); pj_assert(opus->enc_ready == PJ_FALSE && opus->dec_ready == PJ_FALSE); PJ_LOG(4, (THIS_FILE, "Clock rate is %d ", attr->info.clock_rate)); opus->externalFs = attr->info.clock_rate; /* Create Encoder */ structSizeBytes = opus_encoder_get_size(attr->info.channel_cnt); opus->psEnc = pj_pool_zalloc(opus->pool, structSizeBytes); ret = opus_encoder_init(opus->psEnc, opus->externalFs, attr->info.channel_cnt, OPUS_APPLICATION_VOIP); if (ret) { PJ_LOG(1, (THIS_FILE, "Unable to init encoder : %d", ret)); return PJ_EINVAL; } /* * Set Encoder parameters * TODO : have it configurable */ opus_encoder_ctl(opus->psEnc, OPUS_SET_COMPLEXITY(2)); opus_encoder_ctl(opus->psEnc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE)); /* Apply fmtp params to Encoder */ for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) { if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_FMTP_USE_INBAND_FEC) == 0) { tmpFmtpVal = (int)(pj_strtoul(&attr->setting.enc_fmtp.param[i].val)); opus_encoder_ctl(opus->psEnc, OPUS_SET_INBAND_FEC(tmpFmtpVal)); break; } else if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_FMTP_MAX_AVERAGE_BITRATE) == 0) { tmpFmtpVal = (int)(pj_strtoul(&attr->setting.enc_fmtp.param[i].val)); if (tmpFmtpVal >= 6000 && tmpFmtpVal <= 510000) { opus_encoder_ctl(opus->psEnc, OPUS_SET_BITRATE(tmpFmtpVal)); } } else if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_FMTP_MAX_CODED_AUDIO_BANDWIDTH) == 0) { tmpFmtpVal = (int)(pj_strtoul(&attr->setting.enc_fmtp.param[i].val)); if (tmpFmtpVal <= 8000) { opus_encoder_ctl(opus->psEnc, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND)); } else if (tmpFmtpVal <= 12000) { opus_encoder_ctl(opus->psEnc, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_MEDIUMBAND)); } else if (tmpFmtpVal <= 16000) { opus_encoder_ctl(opus->psEnc, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND)); } else if (tmpFmtpVal <= 24000) { opus_encoder_ctl(opus->psEnc, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND)); } else if (tmpFmtpVal <= 48000) { opus_encoder_ctl(opus->psEnc, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); } } else if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_FMTP_USE_DTX) == 0) { tmpFmtpVal = (int)(pj_strtoul(&attr->setting.enc_fmtp.param[i].val)); opus_encoder_ctl(opus->psEnc, OPUS_SET_DTX(tmpFmtpVal)); } } opus->enc_ready = PJ_TRUE; /* Decoder buffer */ opus->pcm_bytes_per_sample = attr->info.pcm_bits_per_sample / 8; max_nsamples = 120 * OPUS_CLOCK_RATE / 1000; /* 120ms is max frame time */ opus->dec_buf_max_size = max_nsamples * opus->pcm_bytes_per_sample; opus->dec_buf = pj_pool_alloc(opus->pool, opus->dec_buf_max_size); /* Create decoder */ structSizeBytes = opus_decoder_get_size(attr->info.channel_cnt); opus->psDec = pj_pool_zalloc(opus->pool, structSizeBytes); ret = opus_decoder_init(opus->psDec, opus->externalFs, attr->info.channel_cnt); if (ret) { PJ_LOG(1, (THIS_FILE, "Unable to init decoder : %d", ret)); return PJ_EINVAL; } opus->dec_ready = PJ_TRUE; return PJ_SUCCESS; }
int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) { va_list ap; int coupled_size, mono_size; char *ptr; int ret = OPUS_OK; va_start(ap, request); coupled_size = opus_decoder_get_size(2); mono_size = opus_decoder_get_size(1); ptr = (char*)st + align(sizeof(OpusMSDecoder)); switch (request) { case OPUS_GET_BANDWIDTH_REQUEST: case OPUS_GET_SAMPLE_RATE_REQUEST: case OPUS_GET_GAIN_REQUEST: case OPUS_GET_LAST_PACKET_DURATION_REQUEST: { OpusDecoder *dec; /* For int32* GET params, just query the first stream */ opus_int32 *value = va_arg(ap, opus_int32*); dec = (OpusDecoder*)ptr; ret = opus_decoder_ctl(dec, request, value); } break; case OPUS_GET_FINAL_RANGE_REQUEST: { int s; opus_uint32 *value = va_arg(ap, opus_uint32*); opus_uint32 tmp; *value = 0; for (s=0;s<st->layout.nb_streams;s++) { OpusDecoder *dec; dec = (OpusDecoder*)ptr; if (s < st->layout.nb_coupled_streams) ptr += align(coupled_size); else ptr += align(mono_size); ret = opus_decoder_ctl(dec, request, &tmp); if (ret != OPUS_OK) break; *value ^= tmp; } } break; case OPUS_RESET_STATE: { int s; for (s=0;s<st->layout.nb_streams;s++) { OpusDecoder *dec; dec = (OpusDecoder*)ptr; if (s < st->layout.nb_coupled_streams) ptr += align(coupled_size); else ptr += align(mono_size); ret = opus_decoder_ctl(dec, OPUS_RESET_STATE); if (ret != OPUS_OK) break; } } break; case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST: { int s; opus_int32 stream_id; OpusDecoder **value; stream_id = va_arg(ap, opus_int32); if (stream_id<0 || stream_id >= st->layout.nb_streams) ret = OPUS_BAD_ARG; value = va_arg(ap, OpusDecoder**); for (s=0;s<stream_id;s++) { if (s < st->layout.nb_coupled_streams) ptr += align(coupled_size); else ptr += align(mono_size); } *value = (OpusDecoder*)ptr; } break; case OPUS_SET_GAIN_REQUEST: { int s; /* This works for int32 params */ opus_int32 value = va_arg(ap, opus_int32); for (s=0;s<st->layout.nb_streams;s++) { OpusDecoder *dec; dec = (OpusDecoder*)ptr; if (s < st->layout.nb_coupled_streams) ptr += align(coupled_size); else ptr += align(mono_size); ret = opus_decoder_ctl(dec, request, value); if (ret != OPUS_OK) break; } } break; default: ret = OPUS_UNIMPLEMENTED; break; } va_end(ap); return ret; }
static int opus_multistream_decode_native( OpusMSDecoder *st, const unsigned char *data, opus_int32 len, void *pcm, opus_copy_channel_out_func copy_channel_out, int frame_size, int decode_fec, int soft_clip ) { opus_int32 Fs; int coupled_size; int mono_size; int s, c; char *ptr; int do_plc=0; VARDECL(opus_val16, buf); ALLOC_STACK; /* Limit frame_size to avoid excessive stack allocations. */ opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)); frame_size = IMIN(frame_size, Fs/25*3); ALLOC(buf, 2*frame_size, opus_val16); ptr = (char*)st + align(sizeof(OpusMSDecoder)); coupled_size = opus_decoder_get_size(2); mono_size = opus_decoder_get_size(1); if (len==0) do_plc = 1; if (len < 0) return OPUS_BAD_ARG; if (!do_plc && len < 2*st->layout.nb_streams-1) return OPUS_INVALID_PACKET; for (s=0;s<st->layout.nb_streams;s++) { OpusDecoder *dec; int packet_offset, ret; dec = (OpusDecoder*)ptr; ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size); if (!do_plc && len<=0) { RESTORE_STACK; return OPUS_INVALID_PACKET; } packet_offset = 0; ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip); data += packet_offset; len -= packet_offset; if (ret > frame_size) { RESTORE_STACK; return OPUS_BUFFER_TOO_SMALL; } if (s>0 && ret != frame_size) { RESTORE_STACK; return OPUS_INVALID_PACKET; } if (ret <= 0) { RESTORE_STACK; return ret; } frame_size = ret; if (s < st->layout.nb_coupled_streams) { int chan, prev; prev = -1; /* Copy "left" audio to the channel(s) where it belongs */ while ( (chan = get_left_channel(&st->layout, s, prev)) != -1) { (*copy_channel_out)(pcm, st->layout.nb_channels, chan, buf, 2, frame_size); prev = chan; } prev = -1; /* Copy "right" audio to the channel(s) where it belongs */ while ( (chan = get_right_channel(&st->layout, s, prev)) != -1) { (*copy_channel_out)(pcm, st->layout.nb_channels, chan, buf+1, 2, frame_size); prev = chan; } } else { int chan, prev; prev = -1; /* Copy audio to the channel(s) where it belongs */ while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1) { (*copy_channel_out)(pcm, st->layout.nb_channels, chan, buf, 1, frame_size); prev = chan; } } } /* Handle muted channels */ for (c=0;c<st->layout.nb_channels;c++) { if (st->layout.mapping[c] == 255) { (*copy_channel_out)(pcm, st->layout.nb_channels, c, NULL, 0, frame_size); } } RESTORE_STACK; return frame_size; }
static int opus_multistream_decode_native( OpusMSDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec ) { int coupled_size; int mono_size; int s, i, c; char *ptr; int do_plc=0; VARDECL(opus_val16, buf); ALLOC_STACK; ALLOC(buf, 2*frame_size, opus_val16); ptr = (char*)st + align(sizeof(OpusMSDecoder)); coupled_size = opus_decoder_get_size(2); mono_size = opus_decoder_get_size(1); if (len==0) do_plc = 1; if (len < 0) return OPUS_BAD_ARG; if (!do_plc && len < 2*st->layout.nb_streams-1) return OPUS_INVALID_PACKET; for (s=0;s<st->layout.nb_streams;s++) { OpusDecoder *dec; int packet_offset, ret; dec = (OpusDecoder*)ptr; ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size); if (!do_plc && len<=0) { RESTORE_STACK; return OPUS_INVALID_PACKET; } packet_offset = 0; ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset); data += packet_offset; len -= packet_offset; if (ret > frame_size) { RESTORE_STACK; return OPUS_BUFFER_TOO_SMALL; } if (s>0 && ret != frame_size) { RESTORE_STACK; return OPUS_INVALID_PACKET; } if (ret <= 0) { RESTORE_STACK; return ret; } frame_size = ret; if (s < st->layout.nb_coupled_streams) { int chan, prev; prev = -1; /* Copy "left" audio to the channel(s) where it belongs */ while ( (chan = get_left_channel(&st->layout, s, prev)) != -1) { for (i=0;i<frame_size;i++) pcm[st->layout.nb_channels*i+chan] = buf[2*i]; prev = chan; } prev = -1; /* Copy "right" audio to the channel(s) where it belongs */ while ( (chan = get_right_channel(&st->layout, s, prev)) != -1) { for (i=0;i<frame_size;i++) pcm[st->layout.nb_channels*i+chan] = buf[2*i+1]; prev = chan; } } else { int chan, prev; prev = -1; /* Copy audio to the channel(s) where it belongs */ while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1) { for (i=0;i<frame_size;i++) pcm[st->layout.nb_channels*i+chan] = buf[i]; prev = chan; } } } /* Handle muted channels */ for (c=0;c<st->layout.nb_channels;c++) { if (st->layout.mapping[c] == 255) { for (i=0;i<frame_size;i++) pcm[st->layout.nb_channels*i+c] = 0; } } RESTORE_STACK; return frame_size; }
JNIEXPORT jint JNICALL Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_decoder_1get_1size (JNIEnv *env, jclass clazz, jint channels) { return opus_decoder_get_size(channels); }