Ejemplo n.º 1
0
long opus_create(const char* format_parameters, const char** format_parameters_out,
		 amci_codec_fmt_info_t** format_description) {
  opus_state_t* codec_inst;
  int error;

  unsigned int maxbandwidth = _OPUS_RATE;
  int useinbandfec = _OPUS_INBAND_FEC_;
  int stereo = 0;

  if (format_parameters) {
    DBG("OPUS params: >>%s<<.\n", format_parameters);
    decode_format_parameters(format_parameters, &maxbandwidth, &useinbandfec, &stereo);
  } 
    
  codec_inst = (opus_state_t*)malloc(sizeof(opus_state_t));

  if (!codec_inst) 
    return -1;

  DBG("OPUS: creating encoder with maxbandwidth=%u, stereo=%s, useinbandfec=%s\n",
      maxbandwidth, stereo?"true":"false", useinbandfec?"true":"false");

  codec_inst->opus_enc = opus_encoder_create(_OPUS_RATE,1,_OPUS_APPLICATION_,&error);
  if (error) {
    DBG("OPUS: error %d while creating encoder state.\n", error);
    return -1;
  }

  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_FORCE_CHANNELS(stereo ? 2:1));

  unsigned int opus_set_bw = _OPUS_RATE;
  if (maxbandwidth <= 8000) {
    opus_set_bw = OPUS_BANDWIDTH_NARROWBAND;
  } else if (maxbandwidth <= 12000) {
    opus_set_bw = OPUS_BANDWIDTH_MEDIUMBAND;
  } else if (maxbandwidth <= 16000) {
    opus_set_bw = OPUS_BANDWIDTH_WIDEBAND;
  } else if (maxbandwidth <= 24000) {
    opus_set_bw = OPUS_BANDWIDTH_SUPERWIDEBAND;
  } else {
    opus_set_bw = OPUS_BANDWIDTH_FULLBAND;
  }
  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_MAX_BANDWIDTH(opus_set_bw));

  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_PACKET_LOSS_PERC(_OPUS_PKT_LOSS_PCT_));
  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_COMPLEXITY(_OPUS_COMPLEXITY_));
  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_INBAND_FEC(useinbandfec ? 1:0));
  opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_DTX(_OPUS_DTX_));

  codec_inst->opus_dec = opus_decoder_create(_OPUS_RATE,1,&error);
  if (error) {
    DBG("OPUS: error %d while creating decoder state.\n", error);
    opus_encoder_destroy(codec_inst->opus_enc);
    return -1;
  }

  *format_description = opus_fmt_description;

  return (long)codec_inst;
}
Ejemplo n.º 2
0
static int alloc(struct aucodec_st **stp, struct aucodec *ac,
		 struct aucodec_prm *encp, struct aucodec_prm *decp,
		 const char *fmtp)
{
	struct aucodec_st *st;
	const uint32_t srate = aucodec_srate(ac);
	const uint8_t ch = aucodec_ch(ac);
	uint32_t ptime = DEFAULT_PTIME;
	int use_inbandfec;
	int use_dtx;
	int err = 0;
	int opuserr;

	(void)decp;
	(void)fmtp;

	st = mem_zalloc(sizeof(*st), destructor);
	if (!st)
		return ENOMEM;

	if (encp && encp->ptime)
		ptime = encp->ptime;

	st->ac         = mem_ref(ac);
	st->frame_size = srate * ptime / 1000;
	st->fsize      = 2 * st->frame_size * ch;

	/* Encoder */
	st->enc = opus_encoder_create(srate, ch, opus.app, &opuserr);
	if (!st->enc) {
		err = ENOMEM;
		goto out;
	}

	use_inbandfec = 1;
	use_dtx = 1;

	opus_encoder_ctl(st->enc, OPUS_SET_BITRATE(opus.bitrate));
	opus_encoder_ctl(st->enc, OPUS_SET_BANDWIDTH(opus.bandwidth));
	opus_encoder_ctl(st->enc, OPUS_SET_VBR(opus.vbr));
	opus_encoder_ctl(st->enc, OPUS_SET_COMPLEXITY(opus.complex));
	opus_encoder_ctl(st->enc, OPUS_SET_INBAND_FEC(use_inbandfec));
	opus_encoder_ctl(st->enc, OPUS_SET_DTX(use_dtx));

	/* Decoder */
	st->dec = opus_decoder_create(srate, ch, &opuserr);
	if (!st->dec) {
		err = ENOMEM;
		goto out;
	}

 out:
	if (err)
		mem_deref(st);
	else
		*stp = st;

	return err;
}
Ejemplo n.º 3
0
    virtual bool OnChangedOptions()
    {
      if (m_encoder == NULL)
        return false;

      opus_encoder_ctl(m_encoder, OPUS_SET_INBAND_FEC(m_useInBandFEC));
      opus_encoder_ctl(m_encoder, OPUS_SET_DTX(m_useDTX));
      opus_encoder_ctl(m_encoder, OPUS_SET_BITRATE(m_bitRate));
      return true;
    }
Ejemplo n.º 4
0
bool OpusEncode::SetFEC(bool enable)
{
    assert(m_encoder);
    if(!m_encoder)
        return false;

    int value = enable;
    int err = opus_encoder_ctl(m_encoder, OPUS_SET_INBAND_FEC(value));
    assert(err == 0);
    return err == 0;
}
JNIEXPORT jint JNICALL
Java_org_jitsi_impl_neomedia_codec_audio_opus_Opus_encoder_1set_1inband_1fec
    (JNIEnv *env, jclass clazz, jlong encoder, jint inbandFEC)
{
    opus_int32 x = inbandFEC;

    return
        opus_encoder_ctl(
                (OpusEncoder *) (intptr_t) encoder,
                OPUS_SET_INBAND_FEC(x));
}
Ejemplo n.º 6
0
static int ms_opus_enc_set_inbandfec(MSFilter *f) {
	OpusEncData *d = (OpusEncData *)f->data;
	int error;

	if (d->state) {
		error = opus_encoder_ctl(d->state, OPUS_SET_INBAND_FEC(d->useinbandfec));
		if (error != OPUS_OK) {
			ms_error("could not set inband FEC to opus encoder: %s", opus_strerror(error));
		}
	}

	return 0;
}
Ejemplo n.º 7
0
OpusEncoder *create_audio_encoder(Logger *log, int32_t bit_rate, int32_t sampling_rate, int32_t channel_count)
{
    int status = OPUS_OK;
    OpusEncoder *rc = opus_encoder_create(sampling_rate, channel_count, OPUS_APPLICATION_VOIP, &status);

    if (status != OPUS_OK) {
        LOGGER_ERROR(log, "Error while starting audio encoder: %s", opus_strerror(status));
        return NULL;
    }

    status = opus_encoder_ctl(rc, OPUS_SET_BITRATE(bit_rate));

    if (status != OPUS_OK) {
        LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status));
        goto FAILURE;
    }

    /* Enable in-band forward error correction in codec */
    status = opus_encoder_ctl(rc, OPUS_SET_INBAND_FEC(1));

    if (status != OPUS_OK) {
        LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status));
        goto FAILURE;
    }

    /* Make codec resistant to up to 10% packet loss
     * NOTE This could also be adjusted on the fly, rather than hard-coded,
     *      with feedback from the receiving client.
     */
    status = opus_encoder_ctl(rc, OPUS_SET_PACKET_LOSS_PERC(10));

    if (status != OPUS_OK) {
        LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status));
        goto FAILURE;
    }

    /* Set algorithm to the highest complexity, maximizing compression */
    status = opus_encoder_ctl(rc, OPUS_SET_COMPLEXITY(10));

    if (status != OPUS_OK) {
        LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status));
        goto FAILURE;
    }

    return rc;

FAILURE:
    opus_encoder_destroy(rc);
    return NULL;
}
Ejemplo n.º 8
0
static gboolean
gst_opus_enc_setup (GstOpusEnc * enc)
{
  int error = OPUS_OK;

#ifndef GST_DISABLE_DEBUG
  GST_DEBUG_OBJECT (enc,
      "setup: %d Hz, %d channels, %d stereo streams, family %d",
      enc->sample_rate, enc->n_channels, enc->n_stereo_streams,
      enc->channel_mapping_family);
  GST_INFO_OBJECT (enc, "Mapping tables built: %d channels, %d stereo streams",
      enc->n_channels, enc->n_stereo_streams);
  gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
      "Encoding mapping table", enc->n_channels, enc->encoding_channel_mapping);
  gst_opus_common_log_channel_mapping_table (GST_ELEMENT (enc), opusenc_debug,
      "Decoding mapping table", enc->n_channels, enc->decoding_channel_mapping);
#endif

  enc->state = opus_multistream_encoder_create (enc->sample_rate,
      enc->n_channels, enc->n_channels - enc->n_stereo_streams,
      enc->n_stereo_streams, enc->encoding_channel_mapping,
      enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP,
      &error);
  if (!enc->state || error != OPUS_OK)
    goto encoder_creation_failed;

  opus_multistream_encoder_ctl (enc->state, OPUS_SET_BITRATE (enc->bitrate), 0);
  opus_multistream_encoder_ctl (enc->state, OPUS_SET_BANDWIDTH (enc->bandwidth),
      0);
  opus_multistream_encoder_ctl (enc->state, OPUS_SET_VBR (!enc->cbr), 0);
  opus_multistream_encoder_ctl (enc->state,
      OPUS_SET_VBR_CONSTRAINT (enc->constrained_vbr), 0);
  opus_multistream_encoder_ctl (enc->state,
      OPUS_SET_COMPLEXITY (enc->complexity), 0);
  opus_multistream_encoder_ctl (enc->state,
      OPUS_SET_INBAND_FEC (enc->inband_fec), 0);
  opus_multistream_encoder_ctl (enc->state, OPUS_SET_DTX (enc->dtx), 0);
  opus_multistream_encoder_ctl (enc->state,
      OPUS_SET_PACKET_LOSS_PERC (enc->packet_loss_percentage), 0);

  GST_LOG_OBJECT (enc, "we have frame size %d", enc->frame_size);

  return TRUE;

encoder_creation_failed:
  GST_ERROR_OBJECT (enc, "Encoder creation failed");
  return FALSE;
}
Ejemplo n.º 9
0
bool FVoiceEncoderOpus::Init(int32 InSampleRate, int32 InNumChannels)
{
	UE_LOG(LogVoiceEncode, Display, TEXT("EncoderVersion: %s"), ANSI_TO_TCHAR(opus_get_version_string()));

	SampleRate = InSampleRate;
	NumChannels = InNumChannels;

	// 20ms frame sizes are a good choice for most applications (1000ms / 20ms = 50)
	FrameSize = SampleRate / NUM_OPUS_FRAMES_PER_SEC;
	//MaxFrameSize = FrameSize * MAX_OPUS_FRAMES;

	int32 EncError = 0;

#if USE_UE4_MEM_ALLOC
	int32 EncSize = opus_encoder_get_size(NumChannels);
	Encoder = (OpusEncoder*)FMemory::Malloc(EncSize);
	EncError = opus_encoder_init(Encoder, SampleRate, NumChannels, OPUS_APPLICATION_VOIP);
#else
	Encoder = opus_encoder_create(SampleRate, NumChannels, OPUS_APPLICATION_VOIP, &EncError);
#endif

	if (EncError != OPUS_OK)
	{
		UE_LOG(LogVoiceEncode, Warning, TEXT("Failed to init Opus Encoder: %s"), ANSI_TO_TCHAR(opus_strerror(EncError)));
		Destroy();
	}

	// Turn on variable bit rate encoding
	int32 UseVbr = 1;
	opus_encoder_ctl(Encoder, OPUS_SET_VBR(UseVbr));

	// Turn off constrained VBR
	int32 UseCVbr = 0;
	opus_encoder_ctl(Encoder, OPUS_SET_VBR_CONSTRAINT(UseCVbr));

	// Complexity (1-10)
	int32 Complexity = 1;
	opus_encoder_ctl(Encoder, OPUS_SET_COMPLEXITY(Complexity));

	// Forward error correction
	int32 InbandFEC = 0;
	opus_encoder_ctl(Encoder, OPUS_SET_INBAND_FEC(InbandFEC));

#if DEBUG_OPUS
	DebugEncoderInfo(Encoder);
#endif // DEBUG_OPUS
	return EncError == OPUS_OK;
}
Ejemplo n.º 10
0
/* Helper methods */
static int opus_encoder_construct(struct ast_trans_pvt *pvt, int sampling_rate)
{
	struct opus_coder_pvt *opvt = pvt->pvt;
	int error = 0;

	if (!valid_sampling_rate(sampling_rate)) {
		return -1;
	}

	opvt->sampling_rate = sampling_rate;
	opvt->multiplier = 48000/sampling_rate;
	opvt->fec = USE_FEC;

	opvt->opus = opus_encoder_create(sampling_rate, 1, OPUS_APPLICATION_VOIP, &error);

	if (error != OPUS_OK) {
		ast_log(LOG_ERROR, "Error creating the Opus encoder: %s\n", opus_strerror(error));
		return -1;
	}

	if (sampling_rate == 8000) {
		opus_encoder_ctl(opvt->opus, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
	} else if (sampling_rate == 12000) {
		opus_encoder_ctl(opvt->opus, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_MEDIUMBAND));
	} else if (sampling_rate == 16000) {
		opus_encoder_ctl(opvt->opus, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
	} else if (sampling_rate == 24000) {
		opus_encoder_ctl(opvt->opus, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
	} else if (sampling_rate == 48000) {
		opus_encoder_ctl(opvt->opus, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
	}

	opus_encoder_ctl(opvt->opus, OPUS_SET_INBAND_FEC(opvt->fec));
	opvt->framesize = sampling_rate/50;
	opvt->id = ast_atomic_fetchadd_int(&usage.encoder_id, 1) + 1;

	ast_atomic_fetchadd_int(&usage.encoders, +1);

	ast_debug(3, "Created encoder #%d (%d -> opus)\n", opvt->id, sampling_rate);

	return 0;
}
Ejemplo n.º 11
0
/*
 * Modify codec settings.
 */
static pj_status_t  codec_modify( pjmedia_codec *codec, 
				  const pjmedia_codec_param *attr )
{
    struct opus_data *opus_data = (struct opus_data *)codec->codec_data;

    pj_mutex_lock (opus_data->mutex);

    TRACE_((THIS_FILE, "%s:%d: - TRACE", __FUNCTION__, __LINE__));

    /* Set bitrate */
    opus_data->cfg.bit_rate = attr->info.avg_bps;
    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));

    pj_mutex_unlock (opus_data->mutex);
    return PJ_SUCCESS;
}
Ejemplo n.º 12
0
/**
 * OPUS init
 */
static void
opus_init ()
{
  int err;

  pcm_length = FRAME_SIZE * CHANNELS * sizeof (float);
  pcm_buffer = pa_xmalloc (pcm_length);
  opus_data = GNUNET_malloc (MAX_PAYLOAD_BYTES);
  enc = opus_encoder_create (SAMPLING_RATE,
			     CHANNELS,
			     CONV_OPUS_APP_TYPE,
			     &err);
  opus_encoder_ctl (enc,
		    OPUS_SET_PACKET_LOSS_PERC (CONV_OPUS_PACKET_LOSS_PERCENTAGE));
  opus_encoder_ctl (enc,
		    OPUS_SET_COMPLEXITY (CONV_OPUS_ENCODING_COMPLEXITY));
  opus_encoder_ctl (enc,
		    OPUS_SET_INBAND_FEC (CONV_OPUS_INBAND_FEC));
  opus_encoder_ctl (enc,
		    OPUS_SET_SIGNAL (CONV_OPUS_SIGNAL));
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
/*
 * 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;
}
Ejemplo n.º 15
0
int opus_encode_update(struct auenc_state **aesp, const struct aucodec *ac,
		       struct auenc_param *param, const char *fmtp)
{
	struct auenc_state *aes;
	struct opus_param prm, conf_prm;
	opus_int32 fch, vbr;
	const struct aucodec *auc = ac;

	(void)param;

	if (!aesp || !ac || !ac->ch)
		return EINVAL;

	debug("opus: encoder fmtp (%s)\n", fmtp);

	/* Save the incoming OPUS parameters from SDP offer */
	if (str_isset(fmtp)) {
		opus_mirror_params(fmtp);
	}

	aes = *aesp;

	if (!aes) {
		const opus_int32 complex = 10;
		int opuserr;

		aes = mem_zalloc(sizeof(*aes), destructor);
		if (!aes)
			return ENOMEM;

		aes->ch = ac->ch;

		aes->enc = opus_encoder_create(ac->srate, ac->ch,
					       /* this has big impact on cpu */
					       OPUS_APPLICATION_AUDIO,
					       &opuserr);
		if (!aes->enc) {
			warning("opus: encoder create: %s\n",
				opus_strerror(opuserr));
			mem_deref(aes);
			return ENOMEM;
		}

		(void)opus_encoder_ctl(aes->enc, OPUS_SET_COMPLEXITY(complex));

		*aesp = aes;
	}

	prm.srate      = 48000;
	prm.bitrate    = OPUS_AUTO;
	prm.stereo     = 1;
	prm.cbr        = 0;
	prm.inband_fec = 0;
	prm.dtx        = 0;

	opus_decode_fmtp(&prm, fmtp);

	conf_prm.bitrate = OPUS_AUTO;
	opus_decode_fmtp(&conf_prm, auc->fmtp);

	if ((prm.bitrate == OPUS_AUTO) ||
	    ((conf_prm.bitrate != OPUS_AUTO) &&
	     (conf_prm.bitrate < prm.bitrate)))
		prm.bitrate = conf_prm.bitrate;

	fch = prm.stereo ? OPUS_AUTO : 1;
	vbr = prm.cbr ? 0 : 1;

	(void)opus_encoder_ctl(aes->enc,
			       OPUS_SET_MAX_BANDWIDTH(srate2bw(prm.srate)));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_BITRATE(prm.bitrate));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_FORCE_CHANNELS(fch));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_VBR(vbr));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_INBAND_FEC(prm.inband_fec));
	(void)opus_encoder_ctl(aes->enc, OPUS_SET_DTX(prm.dtx));


#if 0
	{
	opus_int32 bw, complex;

	(void)opus_encoder_ctl(aes->enc, OPUS_GET_MAX_BANDWIDTH(&bw));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_BITRATE(&prm.bitrate));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_FORCE_CHANNELS(&fch));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_VBR(&vbr));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_INBAND_FEC(&prm.inband_fec));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_DTX(&prm.dtx));
	(void)opus_encoder_ctl(aes->enc, OPUS_GET_COMPLEXITY(&complex));

	debug("opus: encode bw=%s bitrate=%i fch=%s "
	      "vbr=%i fec=%i dtx=%i complex=%i\n",
	      bwname(bw), prm.bitrate, chname(fch),
	      vbr, prm.inband_fec, prm.dtx, complex);
	}
#endif

	return 0;
}
Ejemplo n.º 16
0
static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
	struct opus_context *context = NULL;
	int encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
	int decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
	switch_codec_fmtp_t codec_fmtp;
	opus_codec_settings_t opus_codec_settings = { 0 };
    
	if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) {
		return SWITCH_STATUS_FALSE;
	}
    
	context->enc_frame_size = codec->implementation->actual_samples_per_second * (codec->implementation->microseconds_per_packet / 1000) / 1000;


	memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
	codec_fmtp.private_info = &opus_codec_settings;
	switch_opus_fmtp_parse(codec->fmtp_in, &codec_fmtp);

	/* Verify if the local or remote configuration are lowering maxaveragebitrate and/or maxplaybackrate */
	if ( opus_prefs.maxaveragebitrate && (opus_prefs.maxaveragebitrate < opus_codec_settings.maxaveragebitrate || !opus_codec_settings.maxaveragebitrate) ) {
		opus_codec_settings.maxaveragebitrate = opus_prefs.maxaveragebitrate;
	}
	if ( opus_prefs.maxplaybackrate && (opus_prefs.maxplaybackrate < opus_codec_settings.maxplaybackrate || !opus_codec_settings.maxplaybackrate) ) {
		opus_codec_settings.maxplaybackrate = opus_prefs.maxplaybackrate;
	}

	codec->fmtp_out = gen_fmtp(&opus_codec_settings, codec->memory_pool);

	if (encoding) {
		/* come up with a way to specify these */
		int bitrate_bps = OPUS_AUTO;
		int use_vbr = opus_prefs.use_vbr;
		int complexity = opus_prefs.complexity;
		int err;
		int samplerate = opus_codec_settings.samplerate ? opus_codec_settings.samplerate : codec->implementation->actual_samples_per_second;
        
		context->encoder_object = opus_encoder_create(samplerate,
													  codec->implementation->number_of_channels,
													  codec->implementation->number_of_channels == 1 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO, &err);
        
        if (err != OPUS_OK) {
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create encoder: %s\n", opus_strerror(err));
            return SWITCH_STATUS_GENERR;
        }
        

		/* Setting documented in "RTP Payload Format for Opus Speech and Audio Codec"  draft-spittka-payload-rtp-opus-03 */
		if( opus_codec_settings.maxaveragebitrate ) { /* Remote codec settings found in SDP "fmtp", we accept to tune the Encoder */
			opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(opus_codec_settings.maxaveragebitrate));
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus encoder set bitrate based on maxaveragebitrate found in SDP [%dbps]\n", opus_codec_settings.maxaveragebitrate);
		} else {
			/* Default codec settings used, may have been modified by SDP "samplerate" */
			opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps));
			if (codec->implementation->actual_samples_per_second == 8000) {
				opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
				opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
			} else {
				opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
			}
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus encoder set bitrate to local settings [%dbps]\n", bitrate_bps);
		}

		/* Another setting from "RTP Payload Format for Opus Speech and Audio Codec" */
		if ( opus_codec_settings.maxplaybackrate ) {
			if (opus_codec_settings.maxplaybackrate == 8000) {       /* Audio Bandwidth: 0-4000Hz  Sampling Rate: 8000Hz */
				opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
			} else if (opus_codec_settings.maxplaybackrate == 12000) { /* Audio Bandwidth: 0-6000Hz  Sampling Rate: 12000Hz */
				opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_MEDIUMBAND));
			} else if (opus_codec_settings.maxplaybackrate == 16000) { /* Audio Bandwidth: 0-8000Hz  Sampling Rate: 16000Hz */
				opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
			} else if (opus_codec_settings.maxplaybackrate == 24000) { /* Audio Bandwidth: 0-12000Hz Sampling Rate: 24000Hz */
				opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));
			} else if (opus_codec_settings.maxplaybackrate == 48000) { /* Audio Bandwidth: 0-20000Hz Sampling Rate: 48000Hz */
				opus_encoder_ctl(context->encoder_object, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
			}
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus encoder set bandwidth based on maxplaybackrate found in SDP [%dHz]\n", opus_codec_settings.maxplaybackrate);
		}

		if (use_vbr) {
			opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR(use_vbr));
		}
		if (complexity) {
			opus_encoder_ctl(context->encoder_object, OPUS_SET_COMPLEXITY(complexity));
        }

		if (opus_codec_settings.useinbandfec) {
			opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC(opus_codec_settings.useinbandfec));
		}
        
		if (opus_codec_settings.usedtx) {
			opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX(opus_codec_settings.usedtx));
		}
	}
	
	if (decoding) {
		int err;
        
		context->decoder_object = opus_decoder_create(codec->implementation->actual_samples_per_second,
													  codec->implementation->number_of_channels, &err);
        
		
		if (err != OPUS_OK) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create decoder: %s\n", opus_strerror(err));
            
			if (context->encoder_object) {
				opus_encoder_destroy(context->encoder_object);
				context->encoder_object = NULL;
			}
            
			return SWITCH_STATUS_GENERR;
		}
        
	}
    
	codec->private_info = context;
    
	return SWITCH_STATUS_SUCCESS;
}
Ejemplo n.º 17
0
static void ms_opus_enc_process(MSFilter *f) {
	OpusEncData *d = (OpusEncData *)f->data;
	OpusRepacketizer *repacketizer = NULL;
	mblk_t *om = NULL;
	int packet_size, pcm_buffer_size;
	int max_frame_byte_size, ptime = 20;
	int frame_count = 0, frame_size = 0;
	opus_int32 total_length = 0;
	uint8_t *repacketizer_frame_buffer[MAX_INPUT_FRAMES];
	int i;
	ms_filter_lock(f);
	ptime = d->ptime;
	packet_size = d->samplerate * ptime / 1000; /* in samples */
	ms_filter_unlock(f);
	
	switch (ptime) {
		case 10:
			frame_size = d->samplerate * 10 / 1000;
			frame_count = 1;
			break;
		case 20:
			frame_size = d->samplerate * 20 / 1000;
			frame_count = 1;
			break;
		case 40:
			frame_size = d->samplerate * 40 / 1000;
			frame_count = 1;
			break;
		case 60:
			frame_size = d->samplerate * 60 / 1000;
			frame_count = 1;
			break;
		case 80:
			frame_size = d->samplerate * 40 / 1000;
			frame_count = 2;
			break;
		case 100:
			frame_size = d->samplerate * 20 / 1000;
			frame_count = 5;
			break;
		case 120:
			frame_size = d->samplerate * 60 / 1000;
			frame_count = 2;
			break;
		default:
			frame_size = d->samplerate * 20 / 1000;
			frame_count = 1;
	}

	max_frame_byte_size = MAX_BYTES_PER_MS * ptime/frame_count;

	pcm_buffer_size = d->channels * frame_size * SIGNAL_SAMPLE_SIZE;
	if (pcm_buffer_size > d->pcmbufsize){
		if (d->pcmbuffer) ms_free(d->pcmbuffer);
		d->pcmbuffer = ms_malloc(pcm_buffer_size);
		d->pcmbufsize = pcm_buffer_size;
	}
	for (i=0; i<MAX_INPUT_FRAMES; i++) {
		repacketizer_frame_buffer[i]=NULL;
	}

	ms_bufferizer_put_from_queue(d->bufferizer, f->inputs[0]);
	while (ms_bufferizer_get_avail(d->bufferizer) >= (d->channels * packet_size * SIGNAL_SAMPLE_SIZE)) {
		opus_int32 ret = 0;

		if (frame_count == 1) { /* One Opus frame, not using the repacketizer */
			om = allocb(max_frame_byte_size, 0);
			ms_bufferizer_read(d->bufferizer, d->pcmbuffer, frame_size * SIGNAL_SAMPLE_SIZE * d->channels);
			ret = opus_encode(d->state, (opus_int16 *)d->pcmbuffer, frame_size, om->b_wptr, max_frame_byte_size);
			if (ret < 0) {
				freemsg(om);
				om=NULL;
				ms_error("Opus encoder error: %s", opus_strerror(ret));
				break;
			} else {
				total_length = ret;
				om->b_wptr += total_length;
			}
		} else if(frame_count > 1) { /* We have multiple Opus frames we will use the opus repacketizer */

			repacketizer = opus_repacketizer_create();
			opus_repacketizer_init(repacketizer);

			/* Do not include FEC/LBRR in any frame after the first one since it will be sent with the previous one */
			ret = opus_encoder_ctl(d->state, OPUS_SET_INBAND_FEC(0));
			if (ret != OPUS_OK) {
				ms_error("could not set inband FEC to opus encoder: %s", opus_strerror(ret));
			}
			for (i=0; i<frame_count; i++) {
				if(frame_count == i+1){ /* if configured, reactivate FEC on the last frame to tell the encoder he should restart saving LBRR frames */
					ret = opus_encoder_ctl(d->state, OPUS_SET_INBAND_FEC(d->useinbandfec));
					if (ret != OPUS_OK) {
						ms_error("could not set inband FEC to opus encoder: %s", opus_strerror(ret));
					}
				}
				if (!repacketizer_frame_buffer[i]) repacketizer_frame_buffer[i] = ms_malloc(max_frame_byte_size); /* the repacketizer need the pointer to packet to remain valid, so we shall have a buffer for each coded frame */
				ms_bufferizer_read(d->bufferizer, d->pcmbuffer, frame_size * SIGNAL_SAMPLE_SIZE * d->channels);
				ret = opus_encode(d->state, (opus_int16 *)d->pcmbuffer, frame_size, repacketizer_frame_buffer[i], max_frame_byte_size);
				if (ret < 0) {
					ms_error("Opus encoder error: %s", opus_strerror(ret));
					break;
				} else if (ret > 0) {
					int err = opus_repacketizer_cat(repacketizer, repacketizer_frame_buffer[i], ret); /* add the encoded frame into the current packet */
					if (err != OPUS_OK) {
						ms_error("Opus repacketizer error: %s", opus_strerror(err));
						break;
					}
					total_length += ret;
				}
			}

			om = allocb(total_length + frame_count + 1, 0); /* opus repacketizer API: allocate at least number of frame + size of all data added before */
			ret = opus_repacketizer_out(repacketizer, om->b_wptr, total_length+frame_count);
			if(ret < 0){
				freemsg(om);
				om=NULL;
				ms_error("Opus repacketizer out error: %s", opus_strerror(ret));
			} else {
				om->b_wptr += ret;
			}
			opus_repacketizer_destroy(repacketizer);
			for (i=0; i<frame_count; i++) {
				if (repacketizer_frame_buffer[i] != NULL) {
					ms_free(repacketizer_frame_buffer[i]);
				}
			}
		}

		if(om) { /* we have an encoded output message */
			mblk_set_timestamp_info(om, d->ts);
			ms_bufferizer_fill_current_metas(d->bufferizer, om);
			ms_queue_put(f->outputs[0], om);
			d->ts += packet_size*48000/d->samplerate; /* RFC payload RTP opus 03 - section 4: RTP timestamp multiplier : WARNING works only with sr at 48000 */
			total_length = 0;
		}
	}

}
Ejemplo n.º 18
0
static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
{
	struct opus_context *context = NULL;
	int encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
	int decoding = (flags & SWITCH_CODEC_FLAG_DECODE);

	if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) {
		return SWITCH_STATUS_FALSE;
	}

	context->frame_size = codec->implementation->samples_per_packet;
	
	if (encoding) {
		/* come up with a way to specify these */
		int bitrate_bps = codec->implementation->bits_per_second;
		int use_vbr = 1;
		int complexity = 10;
		int use_inbandfec = 1;
		int use_dtx = 1;
		int bandwidth = OPUS_BANDWIDTH_FULLBAND;
		int err;

		context->encoder_object = opus_encoder_create(codec->implementation->actual_samples_per_second, 
													  codec->implementation->number_of_channels,
													  OPUS_APPLICATION_VOIP, &err);

       if (err != OPUS_OK) {
		   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create encoder: %s\n", opus_strerror(err));
		   return SWITCH_STATUS_GENERR;
       }

		opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps));
		opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(bandwidth));
		opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR(use_vbr));
		opus_encoder_ctl(context->encoder_object, OPUS_SET_COMPLEXITY(complexity));
		opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC(use_inbandfec));
		opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX(use_dtx));

	}
	
	if (decoding) {
		int err;

		context->decoder_object = opus_decoder_create(codec->implementation->actual_samples_per_second, 
													  codec->implementation->number_of_channels, &err);

		
		if (err != OPUS_OK) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create decoder: %s\n", opus_strerror(err));

			if (context->encoder_object) {
				opus_encoder_destroy(context->encoder_object);
				context->encoder_object = NULL;
			}

			return SWITCH_STATUS_GENERR;
		}

	}

	codec->private_info = context;

	return SWITCH_STATUS_SUCCESS;
}