/** * Skips the output buffer with the specified index. * * @param codec The codec that owns the output buffer. * @param index The index of the output buffer to skip. * @param presentationTimeUs The presentation time of the output buffer, in microseconds. */ protected void skipOutputBuffer(MediaCodec codec, int index, long presentationTimeUs) { TraceUtil.beginSection("skipVideoBuffer"); codec.releaseOutputBuffer(index, false); TraceUtil.endSection(); decoderCounters.skippedOutputBufferCount++; }
codec.releaseOutputBuffer(bufferIndex, false); return true; codec.releaseOutputBuffer(bufferIndex, false); decoderCounters.skippedOutputBufferCount++; audioSink.handleDiscontinuity(); codec.releaseOutputBuffer(bufferIndex, false); decoderCounters.renderedOutputBufferCount++; return true;
/** * Drops the output buffer with the specified index. * * @param codec The codec that owns the output buffer. * @param index The index of the output buffer to drop. * @param presentationTimeUs The presentation time of the output buffer, in microseconds. */ protected void dropOutputBuffer(MediaCodec codec, int index, long presentationTimeUs) { TraceUtil.beginSection("dropVideoBuffer"); codec.releaseOutputBuffer(index, false); TraceUtil.endSection(); updateDroppedBufferCounters(1); }
/** * Renders the output buffer with the specified index. This method is only called if the platform * API version of the device is 21 or later. * * @param codec The codec that owns the output buffer. * @param index The index of the output buffer to drop. * @param presentationTimeUs The presentation time of the output buffer, in microseconds. * @param releaseTimeNs The wallclock time at which the frame should be displayed, in nanoseconds. */ @TargetApi(21) protected void renderOutputBufferV21( MediaCodec codec, int index, long presentationTimeUs, long releaseTimeNs) { maybeNotifyVideoSizeChanged(); TraceUtil.beginSection("releaseOutputBuffer"); codec.releaseOutputBuffer(index, releaseTimeNs); TraceUtil.endSection(); lastRenderTimeUs = SystemClock.elapsedRealtime() * 1000; decoderCounters.renderedOutputBufferCount++; consecutiveDroppedFrameCount = 0; maybeNotifyRenderedFirstFrame(); }
private void drainEncoder() { ByteBuffer[] outBuffers = mMediaCodec.getOutputBuffers(); while (isStarted) { encodeLock.lock(); if(mMediaCodec != null) { int outBufferIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 12000); if (outBufferIndex >= 0) { ByteBuffer bb = outBuffers[outBufferIndex]; if (mListener != null) { mListener.onVideoEncode(bb, mBufferInfo); } mMediaCodec.releaseOutputBuffer(outBufferIndex, false); } else { try { // wait 10ms Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } encodeLock.unlock(); } else { encodeLock.unlock(); break; } } } }
/** * Renders the output buffer with the specified index. This method is only called if the platform * API version of the device is less than 21. * * @param codec The codec that owns the output buffer. * @param index The index of the output buffer to drop. * @param presentationTimeUs The presentation time of the output buffer, in microseconds. */ protected void renderOutputBuffer(MediaCodec codec, int index, long presentationTimeUs) { maybeNotifyVideoSizeChanged(); TraceUtil.beginSection("releaseOutputBuffer"); codec.releaseOutputBuffer(index, true); TraceUtil.endSection(); lastRenderTimeUs = SystemClock.elapsedRealtime() * 1000; decoderCounters.renderedOutputBufferCount++; consecutiveDroppedFrameCount = 0; maybeNotifyRenderedFirstFrame(); }
private void drainEncoder() { ByteBuffer[] outBuffers = mMediaCodec.getOutputBuffers(); while (isStarted) { encodeLock.lock(); if(mMediaCodec != null) { int outBufferIndex = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 12000); if (outBufferIndex >= 0) { ByteBuffer bb = outBuffers[outBufferIndex]; if (mListener != null && !mPause) { mListener.onVideoEncode(bb, mBufferInfo); } mMediaCodec.releaseOutputBuffer(outBufferIndex, false); } else { try { // wait 10ms Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } encodeLock.unlock(); } else { encodeLock.unlock(); break; } } } }
@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()); }
@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()); }
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); } } }
mEncoder.releaseOutputBuffer(encoderStatus, false);
codec.releaseOutputBuffer(outputIndex, false); return true; } else if (outputBufferInfo.size == 0
mEncoder.releaseOutputBuffer(result, false); return DRAIN_STATE_SHOULD_RETRY_IMMEDIATELY; mEncoder.releaseOutputBuffer(result, false); return DRAIN_STATE_CONSUMED;
mEncoder.releaseOutputBuffer(result, false); return DRAIN_STATE_SHOULD_RETRY_IMMEDIATELY; mEncoder.releaseOutputBuffer(result, false); return DRAIN_STATE_CONSUMED;
presentationTimeUs, 0); if (inBuffer != null) { mDecoder.releaseOutputBuffer(inBuffer.bufferIndex, false); mEmptyBuffers.add(inBuffer);
private int drainDecoder(long timeoutUs) { if (mIsDecoderEOS) return DRAIN_STATE_NONE; int result = mDecoder.dequeueOutputBuffer(mBufferInfo, timeoutUs); switch (result) { case MediaCodec.INFO_TRY_AGAIN_LATER: return DRAIN_STATE_NONE; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: return DRAIN_STATE_SHOULD_RETRY_IMMEDIATELY; } if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { mEncoder.signalEndOfInputStream(); mIsDecoderEOS = true; mBufferInfo.size = 0; } boolean doRender = (mBufferInfo.size > 0); // NOTE: doRender will block if buffer (of encoder) is full. // Refer: http://bigflake.com/mediacodec/CameraToMpegTest.java.txt mDecoder.releaseOutputBuffer(result, doRender); if (doRender) { mDecoderOutputSurfaceWrapper.awaitNewImage(); mDecoderOutputSurfaceWrapper.drawImage(); mEncoderInputSurfaceWrapper.setPresentationTime(mBufferInfo.presentationTimeUs * 1000); mEncoderInputSurfaceWrapper.swapBuffers(); } return DRAIN_STATE_CONSUMED; }
onOutputBufferAvailable(MediaCodec codec, int bufferId, BufferInfo info) { // ... if (codec == videoDecoder) { // surface timestamp must contain media presentation time in nanoseconds. codec.releaseOutputBuffer(bufferId, 1000 * info.presentationTime); } else { ByteBuffer audioByteBuffer = codec.getOutputBuffer(bufferId); sync.queueAudio(audioByteBuffer, bufferId, info.presentationTime); } // ...
private void MaybeRenderDecodedTextureBuffer() { if (dequeuedSurfaceOutputBuffers.isEmpty() || textureListener.isWaitingForTexture()) { return; } // Get the first frame in the queue and render to the decoder output surface. final DecodedOutputBuffer buffer = dequeuedSurfaceOutputBuffers.remove(); textureListener.addBufferToRender(buffer); mediaCodec.releaseOutputBuffer(buffer.index, true /* render */); }
private void flushMediaCodec(MediaCodec mc) { int index = 0; BufferInfo info = new BufferInfo(); while (index != MediaCodec.INFO_TRY_AGAIN_LATER) { index = mc.dequeueOutputBuffer(info, 1000000/FRAMERATE); if (index>=0) { mc.releaseOutputBuffer(index, false); } } }
protected void dropOutputBuffer(MediaCodec codec, int bufferIndex) { TraceUtil.beginSection("dropVideoBuffer"); codec.releaseOutputBuffer(bufferIndex, false); TraceUtil.endSection(); codecCounters.droppedOutputBufferCount++; droppedFrameCount++; if (droppedFrameCount == maxDroppedFrameCountToNotify) { maybeNotifyDroppedFrameCount(); } }