@Test @Config(minSdk = LOLLIPOP) public void presentsOutputBufferAfterQueuingInputBuffer() { ArgumentCaptor<Integer> indexCaptor = ArgumentCaptor.forClass(Integer.class); verify(callback).onInputBufferAvailable(same(codec), indexCaptor.capture()); ByteBuffer buffer = codec.getInputBuffer(indexCaptor.getValue()); int start = buffer.position(); // "Write" to the buffer. buffer.position(buffer.limit()); codec.queueInputBuffer( indexCaptor.getValue(), /* offset= */ start, /* size= */ buffer.position() - start, /* presentationTimeUs= */ 0, /* flags= */ 0); verify(callback).onOutputBufferAvailable(same(codec), anyInt(), any()); }
encoder.queueInputBuffer(inputBufIndex, 0, 0, ptsUsec, MediaCodec.BUFFER_FLAG_END_OF_STREAM); inputDone = true; encoder.queueInputBuffer(inputBufIndex, 0, frameData.length, ptsUsec, 0); drainEncoder(false, info);
@Test @Config(minSdk = LOLLIPOP) public void passesEndOfStreamFlagWithFinalOutputBuffer() { ArgumentCaptor<Integer> indexCaptor = ArgumentCaptor.forClass(Integer.class); verify(callback).onInputBufferAvailable(same(codec), indexCaptor.capture()); ByteBuffer buffer = codec.getInputBuffer(indexCaptor.getValue()); int start = buffer.position(); // "Write" to the buffer. buffer.position(buffer.limit()); codec.queueInputBuffer( indexCaptor.getValue(), /* offset= */ start, /* size= */ buffer.position() - start, /* presentationTimeUs= */ 0, /* flags= */ MediaCodec.BUFFER_FLAG_END_OF_STREAM); ArgumentCaptor<BufferInfo> infoCaptor = ArgumentCaptor.forClass(BufferInfo.class); verify(callback) .onOutputBufferAvailable(same(codec), indexCaptor.capture(), infoCaptor.capture()); assertThat(infoCaptor.getValue().flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM).isNotEqualTo(0); }
@Test @Config(minSdk = LOLLIPOP) public void providesValidOutputBuffer() { ArgumentCaptor<Integer> indexCaptor = ArgumentCaptor.forClass(Integer.class); verify(callback).onInputBufferAvailable(same(codec), indexCaptor.capture()); ByteBuffer buffer = codec.getInputBuffer(indexCaptor.getValue()); int start = buffer.position(); // "Write" to the buffer. buffer.position(buffer.limit()); codec.queueInputBuffer( indexCaptor.getValue(), /* offset= */ start, /* size= */ buffer.position() - start, /* presentationTimeUs= */ 0, /* flags= */ 0); verify(callback).onOutputBufferAvailable(same(codec), indexCaptor.capture(), any()); buffer = codec.getOutputBuffer(indexCaptor.getValue()); assertThat(buffer.remaining()).isGreaterThan(0); }
@Test @Config(minSdk = LOLLIPOP) public void presentsInputBufferAfterReleasingOutputBufferWhenNotFinished() { ArgumentCaptor<Integer> indexCaptor = ArgumentCaptor.forClass(Integer.class); verify(callback).onInputBufferAvailable(same(codec), indexCaptor.capture()); ByteBuffer buffer = codec.getInputBuffer(indexCaptor.getValue()); int start = buffer.position(); // "Write" to the buffer. buffer.position(buffer.limit()); codec.queueInputBuffer( indexCaptor.getValue(), /* offset= */ start, /* size= */ buffer.position() - start, /* presentationTimeUs= */ 0, /* flags= */ 0); verify(callback).onOutputBufferAvailable(same(codec), indexCaptor.capture(), any()); codec.releaseOutputBuffer(indexCaptor.getValue(), /* render= */ false); verify(callback, times(2)).onInputBufferAvailable(same(codec), anyInt()); }
@Test @Config(minSdk = LOLLIPOP) public void doesNotPresentInputBufferAfterReleasingOutputBufferFinished() { ArgumentCaptor<Integer> indexCaptor = ArgumentCaptor.forClass(Integer.class); verify(callback).onInputBufferAvailable(same(codec), indexCaptor.capture()); ByteBuffer buffer = codec.getInputBuffer(indexCaptor.getValue()); int start = buffer.position(); // "Write" to the buffer. buffer.position(buffer.limit()); codec.queueInputBuffer( indexCaptor.getValue(), /* offset= */ start, /* size= */ buffer.position() - start, /* presentationTimeUs= */ 0, /* flags= */ MediaCodec.BUFFER_FLAG_END_OF_STREAM); verify(callback).onOutputBufferAvailable(same(codec), indexCaptor.capture(), any()); codec.releaseOutputBuffer(indexCaptor.getValue(), /* render= */ false); verify(callback, times(1)).onInputBufferAvailable(same(codec), anyInt()); }
synchronized void offerEncoder(byte[] input) { if(mMediaCodec == null) { return; } ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers(); ByteBuffer[] outputBuffers = mMediaCodec.getOutputBuffers(); int inputBufferIndex = mMediaCodec.dequeueInputBuffer(12000); if (inputBufferIndex >= 0) { ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); inputBuffer.put(input); mMediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0); } int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 12000); while (outputBufferIndex >= 0) { ByteBuffer outputBuffer = outputBuffers[outputBufferIndex]; if(mListener != null) { mListener.onAudioEncode(outputBuffer, mBufferInfo); } mMediaCodec.releaseOutputBuffer(outputBufferIndex, false); outputBufferIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 0); } } }
codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); resetInputBuffer(); codecNeedsAdaptationWorkaroundBuffer = false; buffer.data.put(ADAPTATION_WORKAROUND_BUFFER); codec.queueInputBuffer(inputIndex, 0, ADAPTATION_WORKAROUND_BUFFER.length, 0, 0); resetInputBuffer(); codecReceivedBuffers = true; codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); resetInputBuffer(); codec.queueSecureInputBuffer(inputIndex, 0, cryptoInfo, presentationTimeUs, 0); } else { codec.queueInputBuffer(inputIndex, 0, buffer.data.limit(), presentationTimeUs, 0);
if (hasOverflow) { final long presentationTimeUs = drainOverflow(outBuffer); mEncoder.queueInputBuffer(encoderInBuffIndex, 0, outBuffer.position() * BYTES_PER_SHORT, presentationTimeUs, 0); mEncoder.queueInputBuffer(encoderInBuffIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); return false; mEncoder.queueInputBuffer(encoderInBuffIndex, 0, outBuffer.position() * BYTES_PER_SHORT, presentationTimeUs, 0);
private int drainExtractor(long timeoutUs) { if (mIsExtractorEOS) return DRAIN_STATE_NONE; int trackIndex = mExtractor.getSampleTrackIndex(); if (trackIndex >= 0 && trackIndex != mTrackIndex) { return DRAIN_STATE_NONE; } int result = mDecoder.dequeueInputBuffer(timeoutUs); if (result < 0) return DRAIN_STATE_NONE; if (trackIndex < 0) { mIsExtractorEOS = true; mDecoder.queueInputBuffer(result, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); return DRAIN_STATE_NONE; } int sampleSize = mExtractor.readSampleData(mDecoderInputBuffers[result], 0); boolean isKeyFrame = (mExtractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) != 0; mDecoder.queueInputBuffer(result, 0, sampleSize, mExtractor.getSampleTime(), isKeyFrame ? MediaCodec.BUFFER_FLAG_SYNC_FRAME : 0); mExtractor.advance(); return DRAIN_STATE_CONSUMED; }
private int drainExtractor(long timeoutUs) { if (mIsExtractorEOS) return DRAIN_STATE_NONE; int trackIndex = mExtractor.getSampleTrackIndex(); if (trackIndex >= 0 && trackIndex != mTrackIndex) { return DRAIN_STATE_NONE; } final int result = mDecoder.dequeueInputBuffer(timeoutUs); if (result < 0) return DRAIN_STATE_NONE; if (trackIndex < 0) { mIsExtractorEOS = true; mDecoder.queueInputBuffer(result, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); return DRAIN_STATE_NONE; } final int sampleSize = mExtractor.readSampleData(mDecoderBuffers.getInputBuffer(result), 0); final boolean isKeyFrame = (mExtractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) != 0; mDecoder.queueInputBuffer(result, 0, sampleSize, mExtractor.getSampleTime(), isKeyFrame ? MediaCodec.BUFFER_FLAG_SYNC_FRAME : 0); mExtractor.advance(); return DRAIN_STATE_CONSUMED; }
@Override public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec, int i) { ByteBuffer inputBuffer = mediaCodec.getInputBuffer(i); if (inputBuffer == null) return; MediaCodec.BufferInfo info = AudioDecoder.super.onInputBufferAvailable(extractor, inputBuffer); mediaCodec.queueInputBuffer(i, info.offset, info.size, info.presentationTimeUs, info.flags); }
private void drainAudio(boolean endOfStream) { // LogUtils.v(String.format("drainAudio %b", endOfStream)); ByteBuffer[] inputBuffers = mEncoder.getInputBuffers(); int bufferIndex = mEncoder.dequeueInputBuffer(-1); // wait indefinitely if (bufferIndex >= 0) { ByteBuffer inputBuffer = inputBuffers[bufferIndex]; inputBuffer.clear(); int len = mAudioRecord.read(inputBuffer, SAMPLES_PER_FRAME * 2); // read blocking long ptsUs = System.nanoTime() / 1000; if (endOfStream) { mEncoder.queueInputBuffer(bufferIndex, 0, len, ptsUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); } else { mEncoder.queueInputBuffer(bufferIndex, 0, len, ptsUs, 0); } } } }
void encode() throws Exception { ByteBuffer[] inputs = codec.getInputBuffers(); while (!recorder.doneCoding) { int bufIndex = codec.dequeueInputBuffer(1024); if (bufIndex < 0) continue; ByteBuffer b = inputs[bufIndex]; b.clear(); int size = record.read(b, b.capacity()); size = size < 0 ? 0 : size; b.clear(); codec.queueInputBuffer(bufIndex, 0, size, System.nanoTime() / 1000L, 0); } int bufIndex = codec.dequeueInputBuffer(-1); codec.queueInputBuffer(bufIndex, 0, 0, System.nanoTime() / 1000L, MediaCodec.BUFFER_FLAG_END_OF_STREAM); } }
private boolean queueInputBuffer(int inputBufferIndex, int size, long presentationTimeStamUs, long timeStampMs, long ntpTimeStamp) { checkOnMediaCodecThread(); try { inputBuffers[inputBufferIndex].position(0); inputBuffers[inputBufferIndex].limit(size); decodeStartTimeMs.add( new TimeStamps(SystemClock.elapsedRealtime(), timeStampMs, ntpTimeStamp)); mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, presentationTimeStamUs, 0); return true; } catch (IllegalStateException e) { Logging.e(TAG, "decode failed", e); return false; } }
public void finishWriting() throws IOException { int index; do { index = codec.dequeueInputBuffer(kTimeoutUs /* timeoutUs */); if (index >= 0) codec.queueInputBuffer(index, 0 /* offset */, 0 /* size */, 0 /* timeUs */, MediaCodec.BUFFER_FLAG_END_OF_STREAM); writeOutput(); } while (index < 0); Log.d(TAG, "queued input EOS."); while (!doneDequeing) writeOutput(); }
protected long handleInput(final long presentationTimeUs) { long result = presentationTimeUs; final int inputBufIndex = mMediaCodec.dequeueInputBuffer(TIMEOUT_USEC); if (inputBufIndex >= 0) { final int size = mMediaExtractor.readSampleData(mInputBuffers[inputBufIndex], 0); // if (DEBUG) Log.v(TAG, "handleInput:readSampleData=" + size); if (size > 0) { mMediaCodec.queueInputBuffer(inputBufIndex, 0, size, presentationTimeUs, 0); } mMediaExtractor.advance(); result = -1; } return result; }
private int drainExtractor(long timeoutUs) { if (mIsExtractorEOS) return DRAIN_STATE_NONE; int trackIndex = mExtractor.getSampleTrackIndex(); if (trackIndex >= 0 && trackIndex != mTrackIndex) { return DRAIN_STATE_NONE; } int result = mDecoder.dequeueInputBuffer(timeoutUs); if (result < 0) return DRAIN_STATE_NONE; if (trackIndex < 0) { mIsExtractorEOS = true; mDecoder.queueInputBuffer(result, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); return DRAIN_STATE_NONE; } int sampleSize = mExtractor.readSampleData(mDecoderInputBuffers[result], 0); boolean isKeyFrame = (mExtractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) != 0; mDecoder.queueInputBuffer(result, 0, sampleSize, mExtractor.getSampleTime(), isKeyFrame ? MediaCodec.BUFFER_FLAG_SYNC_FRAME : 0); mExtractor.advance(); return DRAIN_STATE_CONSUMED; }
private int drainExtractor() { if (isExtractorEOS) return DRAIN_STATE_NONE; int trackIndex = mediaExtractor.getSampleTrackIndex(); if (trackIndex >= 0 && trackIndex != this.trackIndex) { return DRAIN_STATE_NONE; } int result = decoder.dequeueInputBuffer(0); if (result < 0) return DRAIN_STATE_NONE; if (trackIndex < 0) { isExtractorEOS = true; decoder.queueInputBuffer(result, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); return DRAIN_STATE_NONE; } int sampleSize = mediaExtractor.readSampleData(decoderInputBuffers[result], 0); boolean isKeyFrame = (mediaExtractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) != 0; decoder.queueInputBuffer(result, 0, sampleSize, mediaExtractor.getSampleTime() / timeScale, isKeyFrame ? MediaCodec.BUFFER_FLAG_SYNC_FRAME : 0); mediaExtractor.advance(); return DRAIN_STATE_CONSUMED; }
private int drainExtractor(long timeoutUs) { if (mIsExtractorEOS) return DRAIN_STATE_NONE; int trackIndex = mExtractor.getSampleTrackIndex(); if (trackIndex >= 0 && trackIndex != mTrackIndex) { return DRAIN_STATE_NONE; } final int result = mDecoder.dequeueInputBuffer(timeoutUs); if (result < 0) return DRAIN_STATE_NONE; if (trackIndex < 0) { mIsExtractorEOS = true; mDecoder.queueInputBuffer(result, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); return DRAIN_STATE_NONE; } final int sampleSize = mExtractor.readSampleData(mDecoderBuffers.getInputBuffer(result), 0); final boolean isKeyFrame = (mExtractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) != 0; mDecoder.queueInputBuffer(result, 0, sampleSize, mExtractor.getSampleTime(), isKeyFrame ? MediaCodec.BUFFER_FLAG_SYNC_FRAME : 0); mExtractor.advance(); return DRAIN_STATE_CONSUMED; }