Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(468)

Unified Diff: talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java

Issue 1394103005: Revert "Android MediaCodecVideoDecoder: Manage lifetime of texture frames" (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fork NativeHandleImpl and disable texture capture, plus some revert rebase nits Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java
diff --git a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java
index a1cc041c416d4699417e892b4acc8507f4533639..515186ac78a628357e983f6988716e967f4f764e 100644
--- a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java
+++ b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java
@@ -27,20 +27,23 @@
package org.webrtc;
+import android.graphics.SurfaceTexture;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecList;
import android.media.MediaFormat;
+import android.opengl.EGLContext;
+import android.opengl.GLES11Ext;
+import android.opengl.GLES20;
import android.os.Build;
import android.view.Surface;
import org.webrtc.Logging;
import java.nio.ByteBuffer;
-import java.util.Arrays;
import java.util.List;
-import java.util.concurrent.TimeUnit;
+import java.util.Arrays;
// Java-side of peerconnection_jni.cc:MediaCodecVideoDecoder.
// This class is an implementation detail of the Java PeerConnection API.
@@ -91,11 +94,10 @@ public class MediaCodecVideoDecoder {
private int stride;
private int sliceHeight;
private boolean useSurface;
- // |isWaitingForTexture| is true when waiting for the transition:
- // MediaCodec.releaseOutputBuffer() -> onTextureFrameAvailable().
- private boolean isWaitingForTexture = false;
- private TextureListener textureListener;
+ private int textureID = 0;
+ private SurfaceTexture surfaceTexture = null;
private Surface surface = null;
+ private EglBase eglBase;
private MediaCodecVideoDecoder() {
instance = this;
@@ -193,13 +195,12 @@ public class MediaCodecVideoDecoder {
}
}
- // Pass null in |surfaceTextureHelper| to configure the codec for ByteBuffer output.
- private boolean initDecode(
- VideoCodecType type, int width, int height, SurfaceTextureHelper surfaceTextureHelper) {
+ // Pass null in |sharedContext| to configure the codec for ByteBuffer output.
+ private boolean initDecode(VideoCodecType type, int width, int height, EGLContext sharedContext) {
if (mediaCodecThread != null) {
throw new RuntimeException("Forgot to release()?");
}
- useSurface = (surfaceTextureHelper != null);
+ useSurface = (sharedContext != null);
String mime = null;
String[] supportedCodecPrefixes = null;
if (type == VideoCodecType.VIDEO_CODEC_VP8) {
@@ -218,6 +219,9 @@ public class MediaCodecVideoDecoder {
Logging.d(TAG, "Java initDecode: " + type + " : "+ width + " x " + height +
". Color: 0x" + Integer.toHexString(properties.colorFormat) +
". Use Surface: " + useSurface);
+ if (sharedContext != null) {
+ Logging.d(TAG, "Decoder shared EGL Context: " + sharedContext);
+ }
mediaCodecThread = Thread.currentThread();
try {
this.width = width;
@@ -226,8 +230,16 @@ public class MediaCodecVideoDecoder {
sliceHeight = height;
if (useSurface) {
- textureListener = new TextureListener(surfaceTextureHelper);
- surface = new Surface(surfaceTextureHelper.getSurfaceTexture());
+ // Create shared EGL context.
+ eglBase = new EglBase(sharedContext, EglBase.ConfigType.PIXEL_BUFFER);
+ eglBase.createDummyPbufferSurface();
+ eglBase.makeCurrent();
+
+ // Create output surface
+ textureID = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
+ Logging.d(TAG, "Video decoder TextureID = " + textureID);
+ surfaceTexture = new SurfaceTexture(textureID);
+ surface = new Surface(surfaceTexture);
}
MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
@@ -270,7 +282,11 @@ public class MediaCodecVideoDecoder {
if (useSurface) {
surface.release();
surface = null;
- textureListener.release();
+ Logging.d(TAG, "Delete video decoder TextureID " + textureID);
+ GLES20.glDeleteTextures(1, new int[] {textureID}, 0);
+ textureID = 0;
+ eglBase.release();
+ eglBase = null;
}
Logging.d(TAG, "Java releaseDecoder done");
}
@@ -319,72 +335,11 @@ public class MediaCodecVideoDecoder {
private static class DecodedTextureBuffer {
private final int textureID;
- private final float[] transformMatrix;
- private final long timestampNs;
+ private final long presentationTimestampUs;
- public DecodedTextureBuffer(int textureID, float[] transformMatrix, long timestampNs) {
+ public DecodedTextureBuffer(int textureID, long presentationTimestampUs) {
this.textureID = textureID;
- this.transformMatrix = transformMatrix;
- this.timestampNs = timestampNs;
- }
- }
-
- // Poll based texture listener.
- private static class TextureListener
- implements SurfaceTextureHelper.OnTextureFrameAvailableListener {
- private final SurfaceTextureHelper surfaceTextureHelper;
- private DecodedTextureBuffer textureBuffer;
- // |newFrameLock| is used to synchronize arrival of new frames with wait()/notifyAll().
- private final Object newFrameLock = new Object();
-
- public TextureListener(SurfaceTextureHelper surfaceTextureHelper) {
- this.surfaceTextureHelper = surfaceTextureHelper;
- surfaceTextureHelper.setListener(this);
- }
-
- // Callback from |surfaceTextureHelper|. May be called on an arbitrary thread.
- @Override
- public void onTextureFrameAvailable(
- int oesTextureId, float[] transformMatrix, long timestampNs) {
- synchronized (newFrameLock) {
- if (textureBuffer != null) {
- Logging.e(TAG,
- "Unexpected onTextureFrameAvailable() called while already holding a texture.");
- throw new IllegalStateException("Already holding a texture.");
- }
- textureBuffer = new DecodedTextureBuffer(oesTextureId, transformMatrix, timestampNs);
- newFrameLock.notifyAll();
- }
- }
-
- // Dequeues and returns a texture buffer if available, or null otherwise.
- public DecodedTextureBuffer dequeueTextureFrame(int timeoutMs) {
- synchronized (newFrameLock) {
- if (textureBuffer == null && timeoutMs > 0) {
- try {
- newFrameLock.wait(timeoutMs);
- } catch(InterruptedException e) {
- // Restore the interrupted status by reinterrupting the thread.
- Thread.currentThread().interrupt();
- }
- }
- final DecodedTextureBuffer textureBuffer = this.textureBuffer;
- this.textureBuffer = null;
- return textureBuffer;
- }
- }
-
- public void release() {
- // SurfaceTextureHelper.disconnect() will block until any onTextureFrameAvailable() in
- // progress is done. Therefore, the call to disconnect() must be outside any synchronized
- // statement that is also used in the onTextureFrameAvailable() above to avoid deadlocks.
- surfaceTextureHelper.disconnect();
- synchronized (newFrameLock) {
- if (textureBuffer != null) {
- surfaceTextureHelper.returnTextureFrame();
- textureBuffer = null;
- }
- }
+ this.presentationTimestampUs = presentationTimestampUs;
}
}
@@ -393,25 +348,14 @@ public class MediaCodecVideoDecoder {
// Throws IllegalStateException if call is made on the wrong thread, if color format changes to an
// unsupported format, or if |mediaCodec| is not in the Executing state. Throws CodecException
// upon codec error.
- private Object dequeueOutputBuffer(int dequeueTimeoutMs)
+ private Object dequeueOutputBuffer(int dequeueTimeoutUs)
throws IllegalStateException, MediaCodec.CodecException {
checkOnMediaCodecThread();
- // Calling multiple MediaCodec.releaseOutputBuffer() with render=true in a row will result in
- // dropped texture frames. Therefore, wait for any pending onTextureFrameAvailable() before
- // proceeding.
- if (isWaitingForTexture) {
- final DecodedTextureBuffer textureBuffer =
- textureListener.dequeueTextureFrame(dequeueTimeoutMs);
- isWaitingForTexture = (textureBuffer == null);
- return textureBuffer;
- }
-
// Drain the decoder until receiving a decoded buffer or hitting
// MediaCodec.INFO_TRY_AGAIN_LATER.
final MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
while (true) {
- final int result = mediaCodec.dequeueOutputBuffer(
- info, TimeUnit.MILLISECONDS.toMicros(dequeueTimeoutMs));
+ final int result = mediaCodec.dequeueOutputBuffer(info, dequeueTimeoutUs);
switch (result) {
case MediaCodec.INFO_TRY_AGAIN_LATER:
return null;
@@ -445,10 +389,9 @@ public class MediaCodecVideoDecoder {
// Output buffer decoded.
if (useSurface) {
mediaCodec.releaseOutputBuffer(result, true /* render */);
- final DecodedTextureBuffer textureBuffer =
- textureListener.dequeueTextureFrame(dequeueTimeoutMs);
- isWaitingForTexture = (textureBuffer == null);
- return textureBuffer;
+ // TODO(magjed): Wait for SurfaceTexture.onFrameAvailable() before returning a texture
+ // frame.
+ return new DecodedTextureBuffer(textureID, info.presentationTimeUs);
} else {
return new DecodedByteBuffer(result, info.offset, info.size, info.presentationTimeUs);
}

Powered by Google App Engine
This is Rietveld 408576698