Replace zero buffer with sample noise

pull/530/head
Mattia Iavarone 6 years ago
parent 8c480f7c68
commit 3d8838409f
  1. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/AudioConfig.java
  2. 32
      cameraview/src/main/java/com/otaliastudios/cameraview/video/encoding/AudioMediaEncoder.java

@ -20,7 +20,7 @@ public class AudioConfig {
final int encoding = AudioFormat.ENCODING_PCM_16BIT; // Determines the sampleSizePerChannel final int encoding = AudioFormat.ENCODING_PCM_16BIT; // Determines the sampleSizePerChannel
// The 44.1KHz frequency is the only setting guaranteed to be available on all devices. // The 44.1KHz frequency is the only setting guaranteed to be available on all devices.
final int samplingFrequency = 44100; // samples/sec final int samplingFrequency = 44100; // samples/sec
final int sampleSizePerChannel = 2; // byte/sample/channel [16bit] final int sampleSizePerChannel = 2; // byte/sample/channel [16bit]. If this changes, review noise introduction
final int byteRatePerChannel = samplingFrequency * sampleSizePerChannel; // byte/sec/channel final int byteRatePerChannel = samplingFrequency * sampleSizePerChannel; // byte/sec/channel
@NonNull @NonNull

@ -1,6 +1,5 @@
package com.otaliastudios.cameraview.video.encoding; package com.otaliastudios.cameraview.video.encoding;
import android.media.AudioFormat;
import android.media.AudioRecord; import android.media.AudioRecord;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
@ -17,6 +16,7 @@ import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
/** /**
@ -31,11 +31,16 @@ public class AudioMediaEncoder extends MediaEncoder {
private static final boolean PERFORMANCE_DEBUG = false; private static final boolean PERFORMANCE_DEBUG = false;
private static final boolean PERFORMANCE_FILL_GAPS = true; private static final boolean PERFORMANCE_FILL_GAPS = true;
private final static Random NOISE = new Random();
private static short noise() {
return (short) NOISE.nextInt(300);
}
private boolean mRequestStop = false; private boolean mRequestStop = false;
private AudioEncodingThread mEncoder; private AudioEncodingThread mEncoder;
private AudioRecordingThread mRecorder; private AudioRecordingThread mRecorder;
private ByteBufferPool mByteBufferPool; private ByteBufferPool mByteBufferPool;
private ByteBuffer mZeroBuffer;
private final AudioTimestamp mTimestamp; private final AudioTimestamp mTimestamp;
private AudioConfig mConfig; private AudioConfig mConfig;
private InputBufferPool mInputBufferPool = new InputBufferPool(); private InputBufferPool mInputBufferPool = new InputBufferPool();
@ -76,7 +81,6 @@ public class AudioMediaEncoder extends MediaEncoder {
mMediaCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mMediaCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mMediaCodec.start(); mMediaCodec.start();
mByteBufferPool = new ByteBufferPool(mConfig.frameSize(), mConfig.bufferPoolMaxSize()); mByteBufferPool = new ByteBufferPool(mConfig.frameSize(), mConfig.bufferPoolMaxSize());
mZeroBuffer = ByteBuffer.allocateDirect(mConfig.frameSize());
} }
@EncoderThread @EncoderThread
@ -253,16 +257,21 @@ public class AudioMediaEncoder extends MediaEncoder {
long frameUs = AudioTimestamp.bytesToUs(mConfig.frameSize(), mConfig.byteRate()); long frameUs = AudioTimestamp.bytesToUs(mConfig.frameSize(), mConfig.byteRate());
LOG.w("read thread - GAPS: trying to add", gaps, "zeroed buffers"); LOG.w("read thread - GAPS: trying to add", gaps, "zeroed buffers");
for (int i = 0; i < gaps; i++) { for (int i = 0; i < gaps; i++) {
ByteBuffer zeroBuffer = mByteBufferPool.get(); ByteBuffer noiseBuffer = mByteBufferPool.get();
if (zeroBuffer == null) { if (noiseBuffer == null) {
LOG.e("read thread - GAPS: aborting because we have no free buffer."); LOG.e("read thread - GAPS: aborting because we have no free buffer.");
break; break;
} }
; noiseBuffer.clear();
zeroBuffer.position(0); while (noiseBuffer.hasRemaining()) {
zeroBuffer.put(mZeroBuffer); // Assume remaining() is not an odd number!
zeroBuffer.clear(); // Also assuming byte order is little endian in Android.
enqueue(zeroBuffer, gapStart, false); short noise = noise();
noiseBuffer.put((byte) noise);
noiseBuffer.put((byte) (noise >> 8));
}
noiseBuffer.rewind();
enqueue(noiseBuffer, gapStart, false);
gapStart += frameUs; gapStart += frameUs;
} }
} }
@ -312,6 +321,7 @@ public class AudioMediaEncoder extends MediaEncoder {
if (PERFORMANCE_DEBUG) { if (PERFORMANCE_DEBUG) {
long sendEnd = System.nanoTime() / 1000000; long sendEnd = System.nanoTime() / 1000000;
Long sendStart = mSendStartMap.remove(inputBuffer.timestamp); Long sendStart = mSendStartMap.remove(inputBuffer.timestamp);
//noinspection StatementWithEmptyBody
if (sendStart != null) { if (sendStart != null) {
mAvgSendDelay = ((mAvgSendDelay * mSendCount) + (sendEnd - sendStart)) / (++mSendCount); mAvgSendDelay = ((mAvgSendDelay * mSendCount) + (sendEnd - sendStart)) / (++mSendCount);
LOG.v("send delay millis:", sendEnd - sendStart, "average:", mAvgSendDelay); LOG.v("send delay millis:", sendEnd - sendStart, "average:", mAvgSendDelay);
@ -357,7 +367,7 @@ public class AudioMediaEncoder extends MediaEncoder {
// NOTE: can consider calling this drainOutput on yet another thread, which would let us // NOTE: can consider calling this drainOutput on yet another thread, which would let us
// use an even smaller BUFFER_POOL_MAX_SIZE without losing audio frames. But this way // use an even smaller BUFFER_POOL_MAX_SIZE without losing audio frames. But this way
// we can accumulate delay on this new thread without noticing (no pool getting empty). // we can accumulate delay on this new thread without noticing (no pool getting empty).
drainOutput(buffer.isEndOfStream); drainOutput(eos);
if (PERFORMANCE_DEBUG) { if (PERFORMANCE_DEBUG) {
long executeEnd = System.nanoTime() / 1000000; long executeEnd = System.nanoTime() / 1000000;

Loading…
Cancel
Save