in nlsCppSdk/encoder/oggopusEncoder.cpp [169:327]
int OggOpusDataEncoder::OggopusEncoderCreate(
EncodedDataCallback encoded_data_callback, void *user_data,
int samplerate) {
sample_rate_ = samplerate;
if (ogg_opus_para_) {
delete ogg_opus_para_;
ogg_opus_para_ = NULL;
}
ogg_opus_para_ = new OggOpusDataEncoderPara();
if (NULL == ogg_opus_para_) {
return -(OggOpusCreateFailed);
}
is_first_frame_processed_ = false;
ResetParameters(encoded_data_callback, user_data); // 初始化ogg_opus_para_
// OpusTags0007opus_version0000,这个指向ogg_encode_opt.comments
ogg_opus_para_->InitComment();
// OpusTags0007opus_version0000ENCODER=opusenc from xxxxx,
// 继续指向ogg_encode_opt.comments
ogg_opus_para_->AddComment();
/* 填充read_func和read_info */
ogg_opus_para_->audio_functions->open_func(&ogg_opus_para_->ogg_encode_opt);
SetupPadder(&ogg_opus_para_->ogg_encode_opt,
&ogg_opus_para_->original_sample_number);
/* reset opus header */
ogg_opus_para_->header.version = 0;
ogg_opus_para_->header.channels = channel_num_;
ogg_opus_para_->header.nb_streams = 1;
ogg_opus_para_->header.nb_coupled = 0;
ogg_opus_para_->header.input_sample_rate = sample_rate_;
ogg_opus_para_->header.gain = 0;
ogg_opus_para_->header.channel_mapping = 0;
memset(ogg_opus_para_->header.stream_map, 0,
sizeof(ogg_opus_para_->header.stream_map));
int ret = OPUS_OK;
ogg_opus_para_->opus_multistream_encoder =
/* 分配和初始化多流编码器状态 */
opus_multistream_encoder_create(
/* 解码的采样率(Hz) */
sample_rate_,
/* 输入信号中的通道数 */
channel_num_,
/* 输入要编码的数据流的总数,必须不能超过通道数 */
ogg_opus_para_->header.nb_streams,
/* 要编码的组对(2通道)数据流的总数,必须不大于数据流的总数 */
ogg_opus_para_->header.nb_coupled,
/* 被编码通道与输入通道的映射关系表 */
ogg_opus_para_->header.stream_map,
/* 目标编码器应用程序, 偏好与原始输入的正确性 */
OPUS_APPLICATION_AUDIO, &ret);
if (ret != OPUS_OK) {
LOG_ERROR("error cannot create encoder: %s", opus_strerror(ret));
exit(1);
} else {
LOG_DEBUG(
"opus_multistream_encoder_create success. sample_rate_:%d "
"channel_num_:%d",
sample_rate_, channel_num_);
}
ogg_opus_para_->packet = reinterpret_cast<unsigned char *>(
malloc(sizeof(unsigned char) * ogg_opus_para_->max_frame_bytes));
if (ogg_opus_para_->packet == NULL) {
LOG_ERROR("error allocating packet buffer.");
exit(1);
}
memset(ogg_opus_para_->packet, 0,
sizeof(unsigned char) * ogg_opus_para_->max_frame_bytes);
LOG_INFO("nb_streams %d, nb_coupled %d, bitrate %d, max frame bytes: %d",
ogg_opus_para_->header.nb_streams, ogg_opus_para_->header.nb_coupled,
ogg_opus_para_->bitrate, ogg_opus_para_->max_frame_bytes);
ret = opus_multistream_encoder_ctl(/* 向一个Opus多流编码器执行一个CTL函数 */
ogg_opus_para_->opus_multistream_encoder,
OPUS_SET_BITRATE(ogg_opus_para_->bitrate));
if (ret != OPUS_OK) {
LOG_ERROR("error OPUS_SET_BITRATE returned: %s", opus_strerror(ret));
exit(1);
}
ret = opus_multistream_encoder_ctl(ogg_opus_para_->opus_multistream_encoder,
OPUS_SET_VBR(true));
if (ret != OPUS_OK) {
LOG_ERROR("error OPUS_SET_VBR returned: %s", opus_strerror(ret));
exit(1);
}
ret = opus_multistream_encoder_ctl(ogg_opus_para_->opus_multistream_encoder,
OPUS_SET_VBR_CONSTRAINT(0));
if (ret != OPUS_OK) {
LOG_ERROR("error OPUS_SET_VBR_CONSTRAINT returned: %s", opus_strerror(ret));
exit(1);
}
ret = opus_multistream_encoder_ctl(
ogg_opus_para_->opus_multistream_encoder,
OPUS_SET_COMPLEXITY(ogg_opus_para_->complexity));
if (ret != OPUS_OK) {
LOG_ERROR("error OPUS_SET_COMPLEXITY returned: %s", opus_strerror(ret));
exit(1);
}
ret = opus_multistream_encoder_ctl(ogg_opus_para_->opus_multistream_encoder,
OPUS_SET_PACKET_LOSS_PERC(0));
if (ret != OPUS_OK) {
LOG_ERROR("error OPUS_SET_PACKET_LOSS_PERC returned: %s",
opus_strerror(ret));
exit(1);
}
#ifdef OPUS_SET_LSB_DEPTH
ret = opus_multistream_encoder_ctl(
ogg_opus_para_->opus_multistream_encoder,
OPUS_SET_LSB_DEPTH(ogg_opus_para_->ogg_encode_opt.sample_bits));
if (ret != OPUS_OK) {
LOG_ERROR("warning OPUS_SET_LSB_DEPTH returned: %s", opus_strerror(ret));
}
#endif
/* get lookahead value */
ret = opus_multistream_encoder_ctl(
ogg_opus_para_->opus_multistream_encoder,
OPUS_GET_LOOKAHEAD(&ogg_opus_para_->lookahead));
if (ret != OPUS_OK) {
LOG_ERROR("error OPUS_GET_LOOKAHEAD returned: %s", opus_strerror(ret));
exit(1);
}
ogg_opus_para_->ogg_encode_opt.skip += ogg_opus_para_->lookahead;
ogg_opus_para_->header.preskip = ogg_opus_para_->ogg_encode_opt.skip * 3.0;
ogg_opus_para_->ogg_encode_opt.extraout = ogg_opus_para_->header.preskip / 3;
if (ogg_stream_init(&ogg_opus_para_->os, ogg_opus_para_->serialno) == -1) {
LOG_ERROR("error: stream init failed");
exit(1);
}
ogg_opus_para_->input = reinterpret_cast<float *>(
malloc(sizeof(float) * frame_sample_num_ * channel_num_));
if (ogg_opus_para_->input == NULL) {
LOG_ERROR("error: couldn't allocate sample buffer.");
exit(1);
}
memset(ogg_opus_para_->input, 0,
sizeof(float) * frame_sample_num_ * channel_num_);
// prepare for encoding
ogg_opus_para_->op.e_o_s = 0;
ogg_opus_para_->nb_samples = -1;
is_first_frame_processed_ = false;
return Success;
}