desc:录音测试,经测试单独录制音频毫无问题

main
xiaowusky 1 year ago
parent 6671c991c0
commit e4df5f1f55

@ -12,9 +12,6 @@ import android.view.Surface;
import com.common.commonlib.utils.LogUtils; import com.common.commonlib.utils.LogUtils;
import org.easydarwin.PushHelper;
import org.easydarwin.easypusher.BuildConfig;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -34,13 +31,15 @@ public class AudioEncoderCore extends MediaEncoderCore implements Runnable {
protected static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; protected static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
private int mSampleRate = 8000; private int mSampleRate = 44100;
private int mChannelCount = 1; private int mChannelCount = 1;
private int mBitRate = 16000; private int mBitRate = 128000;
// private int mMaxInputSize = 16384;
private int mMaxInputSize = 1920; int AUDIO_BUFFER_SIZE;
private AudioRecord mAudioRecord; private AudioRecord mAudioRecord;
@ -63,14 +62,14 @@ public class AudioEncoderCore extends MediaEncoderCore implements Runnable {
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRate); format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRate);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, mChannelCount); format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, mChannelCount);
format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate); format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, mMaxInputSize); // format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, mMaxInputSize);
// Create a MediaCodec encoder, and configure it with our format. Get a Surface // Create a MediaCodec encoder, and configure it with our format. Get a Surface
// we can use for input and wrap it with a class that handles the EGL work. // we can use for input and wrap it with a class that handles the EGL work.
try { try {
mEncoder = MediaCodec.createEncoderByType(MIME_TYPE); mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
} catch (IOException e) { } catch (IOException e) {
LogUtils.e(e); e.printStackTrace();
} }
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
@ -79,6 +78,8 @@ public class AudioEncoderCore extends MediaEncoderCore implements Runnable {
LogUtils.v(String.format("%s prepareEncoder, mEncoder = %s", getClass().getSimpleName(), mEncoder)); LogUtils.v(String.format("%s prepareEncoder, mEncoder = %s", getClass().getSimpleName(), mEncoder));
} }
int minBufferSize;
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
private void prepareRecorder() { private void prepareRecorder() {
switch (mChannelCount) { switch (mChannelCount) {
@ -92,24 +93,25 @@ public class AudioEncoderCore extends MediaEncoderCore implements Runnable {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
int minBufferSize = AudioRecord.getMinBufferSize(mSampleRate, minBufferSize = AudioRecord.getMinBufferSize(mSampleRate,
mChannelConfig, AUDIO_FORMAT); mChannelConfig, AUDIO_FORMAT);
AUDIO_BUFFER_SIZE = 2 * minBufferSize;
mAudioRecord = new AudioRecord( mAudioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, // source MediaRecorder.AudioSource.CAMCORDER, // source
mSampleRate, // sample rate, hz mSampleRate, // sample rate, hz
mChannelConfig, // channels mChannelConfig, // channels
AUDIO_FORMAT, // audio format AUDIO_FORMAT, // audio format
minBufferSize); // buffer size (bytes) AUDIO_BUFFER_SIZE); // buffer size (bytes)
} }
@Override @Override
public void start() { public void start() {
if (!mRecording) { if (!mRecording) {
// mRecording = true; mRecording = true;
// mAudioRecord.startRecording(); mAudioRecord.startRecording();
//
// TaskUtils.execute(this); new Thread(this).start();
} }
} }
@ -123,6 +125,87 @@ public class AudioEncoderCore extends MediaEncoderCore implements Runnable {
return null; return null;
} }
@Override
public void drainEncoder(boolean endOfStream) {
// LogUtils.v(String.format("%s drainEncoder: end = %b", getClass().getSimpleName(), endOfStream));
final int TIMEOUT_USEC = 10000;
if (VERBOSE) Log.d(TAG, "drainEncoder(" + endOfStream + ")");
if (endOfStream && isSurfaceInput()) {
if (VERBOSE) Log.d(TAG, "sending EOS to encoder");
mEncoder.signalEndOfInputStream();
}
ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
while (true) {
int encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
// no output available yet
if (!endOfStream) {
break; // out of while
} else {
if (VERBOSE) Log.d(TAG, "no output available, spinning to await EOS");
}
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
// not expected for an encoder
encoderOutputBuffers = mEncoder.getOutputBuffers();
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// should happen before receiving buffers, and should only happen once
MediaFormat newFormat = mEncoder.getOutputFormat();
Log.d(TAG, "encoder output format changed: " + newFormat);
// now that we have the Magic Goodies, start the muxer
mTrackIndex = mMuxer.addTrack(newFormat);
} else if (encoderStatus < 0) {
Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: " +
encoderStatus);
// let's ignore it
} else {
ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
if (encodedData == null) {
throw new RuntimeException("encoderOutputBuffer " + encoderStatus +
" was null");
}
if (!mMuxer.isStarted()) {
mBufferInfo.size = 0;
}
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
// The codec config data was pulled out and fed to the muxer when we got
// the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
if (VERBOSE) Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
mBufferInfo.size = 0;
}
if (mBufferInfo.size != 0) {
// adjust the ByteBuffer values to match BufferInfo (not needed?)
encodedData.position(mBufferInfo.offset);
encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
mMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
if (VERBOSE) {
Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer, ts=" +
mBufferInfo.presentationTimeUs);
}
}
mEncoder.releaseOutputBuffer(encoderStatus, false);
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
if (!endOfStream) {
Log.w(TAG, "reached end of stream unexpectedly");
} else {
if (VERBOSE) Log.d(TAG, "end of stream reached");
}
break; // out of while
}
}
}
}
@Override @Override
protected boolean isSurfaceInput() { protected boolean isSurfaceInput() {
return false; return false;
@ -131,14 +214,14 @@ public class AudioEncoderCore extends MediaEncoderCore implements Runnable {
@Override @Override
public void run() { public void run() {
while (mRecording) { while (mRecording) {
// drainEncoder(false); drainAudio(false);
// drainAudio(false); drainEncoder(false);
} }
// drainAudio(true); drainAudio(true);
mAudioRecord.stop(); mAudioRecord.stop();
// drainEncoder(true); drainEncoder(true);
release(); release();
} }
@ -146,104 +229,32 @@ public class AudioEncoderCore extends MediaEncoderCore implements Runnable {
private void drainAudio(boolean endOfStream) { private void drainAudio(boolean endOfStream) {
// LogUtils.v(String.format("drainAudio %b", endOfStream)); // LogUtils.v(String.format("drainAudio %b", endOfStream));
ByteBuffer[] inputBuffers = mEncoder.getInputBuffers();
int bufferIndex = mEncoder.dequeueInputBuffer(-1); // wait indefinitely int bufferIndex = mEncoder.dequeueInputBuffer(-1); // wait indefinitely
if (bufferIndex >= 0) { if (bufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[bufferIndex]; ByteBuffer inputBuffer = mEncoder.getInputBuffer(bufferIndex);
inputBuffer.clear(); inputBuffer.clear();
// byte[] buffer = new byte[minBufferSize];
int len = mAudioRecord.read(inputBuffer, SAMPLES_PER_FRAME * 2); // read blocking // int len = mAudioRecord.read(buffer, 0, minBufferSize); // read blocking
long ptsUs = System.nanoTime() / 1000; // long ptsUs = System.nanoTime() / 1000;
// if (len > 0) {
// inputBuffer.put(buffer);
// if (endOfStream) {
// mEncoder.queueInputBuffer(bufferIndex, 0, buffer.length, ptsUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
// } else {
// mEncoder.queueInputBuffer(bufferIndex, 0, buffer.length, ptsUs, 0);
// }
// }
int bytesRead = mAudioRecord.read(inputBuffer, AUDIO_BUFFER_SIZE);
long presentationTimeUs = System.nanoTime() / 1000;
if (endOfStream) { if (endOfStream) {
mEncoder.queueInputBuffer(bufferIndex, 0, len, ptsUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); mEncoder.queueInputBuffer(bufferIndex, 0, bytesRead, presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
} else {
mEncoder.queueInputBuffer(bufferIndex, 0, len, ptsUs, 0);
}
}
}
@Override
public void drainEncoder(boolean endOfStream) {
final int TIMEOUT_USEC = 10000;
if (VERBOSE) Log.d(TAG, "drainEncoder(" + endOfStream + ")");
if (endOfStream && isSurfaceInput()) {
if (VERBOSE) Log.d(TAG, "sending EOS to encoder");
mEncoder.signalEndOfInputStream();
}
ByteBuffer mBuffer = ByteBuffer.allocate(10240);
ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
int encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
// no output available yet
if (!endOfStream) {
} else { } else {
if (VERBOSE) Log.d(TAG, "no output available, spinning to await EOS"); mEncoder.queueInputBuffer(bufferIndex, 0, bytesRead,
} presentationTimeUs, 0);
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
// not expected for an encoder
encoderOutputBuffers = mEncoder.getOutputBuffers();
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// should happen before receiving buffers, and should only happen once
MediaFormat newFormat = mEncoder.getOutputFormat();
Log.d(TAG, "encoder output format changed: " + newFormat);
// now that we have the Magic Goodies, start the muxer
// mTrackIndex = mMuxer.addTrack(newFormat);
} else if (encoderStatus < 0) {
Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: " +
encoderStatus);
// let's ignore it
} else {
ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
if (encodedData == null) {
throw new RuntimeException("encoderOutputBuffer " + encoderStatus +
" was null");
}
if (!mMuxer.isStarted()) {
mBufferInfo.size = 0;
}
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
// The codec config data was pulled out and fed to the muxer when we got
// the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
if (VERBOSE) Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
mBufferInfo.size = 0;
} }
if (mBufferInfo.size != 0) {
encodedData.get(mBuffer.array(), 7, mBufferInfo.size);
encodedData.clear();
mBuffer.position(7 + mBufferInfo.size);
addADTStoPacket(mBuffer.array(), mBufferInfo.size + 7);
mBuffer.flip();
PushHelper.INSTANCE.pushData(mBuffer.array(), mBufferInfo.size + 7, mBufferInfo.presentationTimeUs / 1000);
if (BuildConfig.DEBUG)
Log.i(TAG, String.format("push audio stamp:%d", mBufferInfo.presentationTimeUs / 1000));
}
mEncoder.releaseOutputBuffer(encoderStatus, false);
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
if (!endOfStream) {
Log.w(TAG, "reached end of stream unexpectedly");
} else {
if (VERBOSE) Log.d(TAG, "end of stream reached");
}
}
} }
}
private void addADTStoPacket(byte[] packet, int packetLen) {
packet[0] = (byte) 0xFF;
packet[1] = (byte) 0xF1;
packet[2] = (byte) (((2 - 1) << 6) + (11 << 2) + (1 >> 2));
packet[3] = (byte) (((1 & 3) << 6) + (packetLen >> 11));
packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
packet[6] = (byte) 0xFC;
} }
} }

Loading…
Cancel
Save