Beispiel #1
0
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;
}
Beispiel #3
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
-1
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
}