unsigned char* EncodeManager::encodeAudio(const float* frame, int* enc_ret) { unsigned char* data = new unsigned char[_len](); *enc_ret = opus_encode_float(_enc, frame, FRAMES_PER_BUFFER, data, _len); return data; }
JNIEXPORT jint JNICALL Java_org_echocat_jopus_OpusEncoderJNI_encodeFloat (JNIEnv *env, jclass thisClass, jlong handle, jfloatArray pcm, jint frameSize, jbyteArray packet, jint packetLength) { int result = 0; if (Java_org_echocat_jogg_OggJNISupport_checkNotNull(env, pcm) && Java_org_echocat_jogg_OggJNISupport_checkNotNull(env, packet)) { jboolean npcmIsCopy = 0; float* npcm = (*env)->GetPrimitiveArrayCritical(env, pcm, &npcmIsCopy); if (npcm != NULL) { jboolean npacketIsCopy = 0; char* npacket = (*env)->GetPrimitiveArrayCritical(env, packet, &npacketIsCopy); if (npacket != NULL) { result = opus_encode_float((OpusEncoder*) handle, npcm, frameSize, npacket, packetLength); (*env)->ReleasePrimitiveArrayCritical(env, packet, npacket, 0); Java_org_echocat_jogg_OggJNISupport_checkResponse(env, result); } else { Java_org_echocat_jogg_OggJNISupport_throwOutOfMemoryError(env); } (*env)->ReleasePrimitiveArrayCritical(env, pcm, npcm, JNI_ABORT); } else { Java_org_echocat_jogg_OggJNISupport_throwOutOfMemoryError(env); } } return result; }
unsigned char *AudioCodec::AudioEncode(float *frame) { unsigned char *buff = new unsigned char[this->data_size]; int ret = opus_encode_float(this->enc, frame, 240, buff, this->data_size); return (buff); }
/** * Creates OPUS packets from PCM data */ static void packetizer () { char *nbuf; size_t new_size; int32_t len; ogg_packet op; ogg_page og; while (transmit_buffer_length >= transmit_buffer_index + pcm_length) { memcpy (pcm_buffer, &transmit_buffer[transmit_buffer_index], pcm_length); transmit_buffer_index += pcm_length; len = opus_encode_float (enc, pcm_buffer, FRAME_SIZE, opus_data, MAX_PAYLOAD_BYTES); if (len < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("opus_encode_float() failed: %s. Aborting\n"), opus_strerror (len)); quit (5); } if (len > UINT16_MAX - sizeof (struct AudioMessage)) { GNUNET_break (0); continue; } /* As per OggOpus spec, granule is calculated as if the audio had 48kHz sampling rate. */ enc_granulepos += FRAME_SIZE * 48000 / SAMPLING_RATE; op.packet = (unsigned char *) opus_data; op.bytes = len; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = enc_granulepos; op.packetno = packet_id++; ogg_stream_packetin (&os, &op); while (ogg_stream_flush_fill (&os, &og, PAGE_WATERLINE)) { if (og.header_len + og.body_len > UINT16_MAX - sizeof (struct AudioMessage)) { GNUNET_assert (0); continue; } write_page (&og); } } new_size = transmit_buffer_length - transmit_buffer_index; if (0 != new_size) { nbuf = pa_xmalloc (new_size); memmove (nbuf, &transmit_buffer[transmit_buffer_index], new_size); pa_xfree (transmit_buffer); transmit_buffer = nbuf; } else { pa_xfree (transmit_buffer); transmit_buffer = NULL; } transmit_buffer_index = 0; transmit_buffer_length = new_size; }
nsresult OpusTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData) { PROFILER_LABEL("OpusTrackEncoder", "GetEncodedTrack", js::ProfileEntry::Category::OTHER); { ReentrantMonitorAutoEnter mon(mReentrantMonitor); // Wait until initialized or cancelled. while (!mCanceled && !mInitialized) { mReentrantMonitor.Wait(); } if (mCanceled || mEncodingComplete) { return NS_ERROR_FAILURE; } } // calculation below depends on the truth that mInitialized is true. MOZ_ASSERT(mInitialized); // re-sampled frames left last time which didn't fit into an Opus packet duration. const int framesLeft = mResampledLeftover.Length() / mChannels; // When framesLeft is 0, (GetPacketDuration() - framesLeft) is a multiple // of kOpusSamplingRate. There is not precision loss in the integer division // in computing framesToFetch. If frameLeft > 0, we need to add 1 to // framesToFetch to ensure there will be at least n frames after re-sampling. const int frameRoundUp = framesLeft ? 1 : 0; MOZ_ASSERT(GetPacketDuration() >= framesLeft); // Try to fetch m frames such that there will be n frames // where (n + frameLeft) >= GetPacketDuration() after re-sampling. const int framesToFetch = !mResampler ? GetPacketDuration() : (GetPacketDuration() - framesLeft) * mSamplingRate / kOpusSamplingRate + frameRoundUp; { // Move all the samples from mRawSegment to mSourceSegment. We only hold // the monitor in this block. ReentrantMonitorAutoEnter mon(mReentrantMonitor); // Wait until enough raw data, end of stream or cancelled. while (!mCanceled && mRawSegment.GetDuration() + mSourceSegment.GetDuration() < framesToFetch && !mEndOfStream) { mReentrantMonitor.Wait(); } if (mCanceled || mEncodingComplete) { return NS_ERROR_FAILURE; } mSourceSegment.AppendFrom(&mRawSegment); // Pad |mLookahead| samples to the end of source stream to prevent lost of // original data, the pcm duration will be calculated at rate 48K later. if (mEndOfStream && !mEosSetInEncoder) { mEosSetInEncoder = true; mSourceSegment.AppendNullData(mLookahead); } } // Start encoding data. nsAutoTArray<AudioDataValue, 9600> pcm; pcm.SetLength(GetPacketDuration() * mChannels); AudioSegment::ChunkIterator iter(mSourceSegment); int frameCopied = 0; while (!iter.IsEnded() && frameCopied < framesToFetch) { AudioChunk chunk = *iter; // Chunk to the required frame size. int frameToCopy = chunk.GetDuration(); if (frameCopied + frameToCopy > framesToFetch) { frameToCopy = framesToFetch - frameCopied; } if (!chunk.IsNull()) { // Append the interleaved data to the end of pcm buffer. AudioTrackEncoder::InterleaveTrackData(chunk, frameToCopy, mChannels, pcm.Elements() + frameCopied * mChannels); } else { memset(pcm.Elements() + frameCopied * mChannels, 0, frameToCopy * mChannels * sizeof(AudioDataValue)); } frameCopied += frameToCopy; iter.Next(); } RefPtr<EncodedFrame> audiodata = new EncodedFrame(); audiodata->SetFrameType(EncodedFrame::OPUS_AUDIO_FRAME); int framesInPCM = frameCopied; if (mResampler) { nsAutoTArray<AudioDataValue, 9600> resamplingDest; // We want to consume all the input data, so we slightly oversize the // resampled data buffer so we can fit the output data in. We cannot really // predict the output frame count at each call. uint32_t outframes = frameCopied * kOpusSamplingRate / mSamplingRate + 1; uint32_t inframes = frameCopied; resamplingDest.SetLength(outframes * mChannels); #if MOZ_SAMPLE_TYPE_S16 short* in = reinterpret_cast<short*>(pcm.Elements()); short* out = reinterpret_cast<short*>(resamplingDest.Elements()); speex_resampler_process_interleaved_int(mResampler, in, &inframes, out, &outframes); #else float* in = reinterpret_cast<float*>(pcm.Elements()); float* out = reinterpret_cast<float*>(resamplingDest.Elements()); speex_resampler_process_interleaved_float(mResampler, in, &inframes, out, &outframes); #endif MOZ_ASSERT(pcm.Length() >= mResampledLeftover.Length()); PodCopy(pcm.Elements(), mResampledLeftover.Elements(), mResampledLeftover.Length()); uint32_t outframesToCopy = std::min(outframes, static_cast<uint32_t>(GetPacketDuration() - framesLeft)); MOZ_ASSERT(pcm.Length() - mResampledLeftover.Length() >= outframesToCopy * mChannels); PodCopy(pcm.Elements() + mResampledLeftover.Length(), resamplingDest.Elements(), outframesToCopy * mChannels); int frameLeftover = outframes - outframesToCopy; mResampledLeftover.SetLength(frameLeftover * mChannels); PodCopy(mResampledLeftover.Elements(), resamplingDest.Elements() + outframesToCopy * mChannels, mResampledLeftover.Length()); // This is always at 48000Hz. framesInPCM = framesLeft + outframesToCopy; audiodata->SetDuration(framesInPCM); } else { // The ogg time stamping and pre-skip is always timed at 48000. audiodata->SetDuration(frameCopied * (kOpusSamplingRate / mSamplingRate)); } // Remove the raw data which has been pulled to pcm buffer. // The value of frameCopied should equal to (or smaller than, if eos) // GetPacketDuration(). mSourceSegment.RemoveLeading(frameCopied); // Has reached the end of input stream and all queued data has pulled for // encoding. if (mSourceSegment.GetDuration() == 0 && mEndOfStream) { mEncodingComplete = true; LOG("[Opus] Done encoding."); } MOZ_ASSERT(mEndOfStream || framesInPCM == GetPacketDuration()); // Append null data to pcm buffer if the leftover data is not enough for // opus encoder. if (framesInPCM < GetPacketDuration() && mEndOfStream) { PodZero(pcm.Elements() + framesInPCM * mChannels, (GetPacketDuration() - framesInPCM) * mChannels); } nsTArray<uint8_t> frameData; // Encode the data with Opus Encoder. frameData.SetLength(MAX_DATA_BYTES); // result is returned as opus error code if it is negative. int result = 0; #ifdef MOZ_SAMPLE_TYPE_S16 const opus_int16* pcmBuf = static_cast<opus_int16*>(pcm.Elements()); result = opus_encode(mEncoder, pcmBuf, GetPacketDuration(), frameData.Elements(), MAX_DATA_BYTES); #else const float* pcmBuf = static_cast<float*>(pcm.Elements()); result = opus_encode_float(mEncoder, pcmBuf, GetPacketDuration(), frameData.Elements(), MAX_DATA_BYTES); #endif frameData.SetLength(result >= 0 ? result : 0); if (result < 0) { LOG("[Opus] Fail to encode data! Result: %s.", opus_strerror(result)); } if (mEncodingComplete) { if (mResampler) { speex_resampler_destroy(mResampler); mResampler = nullptr; } mResampledLeftover.SetLength(0); } audiodata->SwapInFrameData(frameData); aData.AppendEncodedFrame(audiodata); return result >= 0 ? NS_OK : NS_ERROR_FAILURE; }
void OpusCodec::encodeData(Connector *conn,const float *pcm,int frames) { #ifdef HAVE_OPUS int s; unsigned char data[4096]; if(!opus_prologue_sent) { conn->writeData(0,(const unsigned char *)opus_stream_prologue.constData(), opus_stream_prologue.size()); opus_prologue_sent=true; } if((s=opus_encode_float(opus_encoder,pcm,frames,data,4096))>1) { opus_packet_granulepos+=frames; opus_ogg_packet.packet=data; opus_ogg_packet.bytes=s; opus_ogg_packet.b_o_s=0; opus_ogg_packet.e_o_s=0; opus_ogg_packet.granulepos=opus_packet_granulepos; opus_ogg_packet.packetno=opus_packet_number++; ogg_stream_packetin(&opus_ogg_stream,&opus_ogg_packet); while(ogg_stream_pageout(&opus_ogg_stream,&opus_ogg_page)!=0) { conn-> writeData(frames,opus_ogg_page.header,opus_ogg_page.header_len); conn->writeData(0,opus_ogg_page.body,opus_ogg_page.body_len); } } else { Log(LOG_WARNING,QString().sprintf("opus encoding error %d",s)); } #endif // HAVE_OPUS }