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 4809cf65b29b13d7d59b0bf623b4b657f489a7c6..8c1293c47286ea68a38aa1e3acbe2088c31797f8 100644 |
--- a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java |
+++ b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java |
@@ -27,7 +27,6 @@ |
package org.webrtc; |
-import android.graphics.SurfaceTexture; |
import android.media.MediaCodec; |
import android.media.MediaCodecInfo; |
import android.media.MediaCodecInfo.CodecCapabilities; |
@@ -47,7 +46,8 @@ import java.nio.ByteBuffer; |
// This class is an implementation detail of the Java PeerConnection API. |
// MediaCodec is thread-hostile so this class must be operated on a single |
// thread. |
-public class MediaCodecVideoDecoder { |
+public class MediaCodecVideoDecoder |
+ implements SurfaceTextureHelper.OnTextureFrameAvailableListener { |
// This class is constructed, operated, and destroyed by its C++ incarnation, |
// so the class and its methods have non-public visibility. The API this |
// class exposes aims to mimic the webrtc::VideoDecoder API as closely as |
@@ -91,11 +91,11 @@ public class MediaCodecVideoDecoder { |
private int height; |
private int stride; |
private int sliceHeight; |
+ // |nativeDecoder| is a webrc_jni::MediaCodecVideoDecoder* pointer to the parent. |
+ private long nativeDecoder; |
private boolean useSurface; |
- private int textureID = -1; |
- private SurfaceTexture surfaceTexture = null; |
- private Surface surface = null; |
- private EglBase eglBase; |
+ private Surface surface; |
+ private SurfaceTextureHelper surfaceTextureHelper; |
private MediaCodecVideoDecoder() { } |
@@ -180,10 +180,12 @@ public class MediaCodecVideoDecoder { |
} |
// Pass null in |sharedContext| to configure the codec for ByteBuffer output. |
- private boolean initDecode(VideoCodecType type, int width, int height, EGLContext sharedContext) { |
+ private boolean initDecode(long nativeDecoder, VideoCodecType type, int width, int height, |
+ EGLContext sharedContext) { |
if (mediaCodecThread != null) { |
throw new RuntimeException("Forgot to release()?"); |
} |
+ this.nativeDecoder = nativeDecoder; |
useSurface = (sharedContext != null); |
String mime = null; |
String[] supportedCodecPrefixes = null; |
@@ -208,24 +210,14 @@ public class MediaCodecVideoDecoder { |
} |
mediaCodecThread = Thread.currentThread(); |
try { |
- Surface decodeSurface = null; |
this.width = width; |
this.height = height; |
stride = width; |
sliceHeight = height; |
if (useSurface) { |
- // 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); |
- decodeSurface = surface; |
+ surfaceTextureHelper = new SurfaceTextureHelper(sharedContext, this); |
+ surface = new Surface(surfaceTextureHelper.getSurfaceTexture()); |
} |
MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); |
@@ -238,7 +230,7 @@ public class MediaCodecVideoDecoder { |
if (mediaCodec == null) { |
return false; |
} |
- mediaCodec.configure(format, decodeSurface, null, 0); |
+ mediaCodec.configure(format, surface, null, 0); |
mediaCodec.start(); |
colorFormat = properties.colorFormat; |
outputBuffers = mediaCodec.getOutputBuffers(); |
@@ -265,16 +257,22 @@ public class MediaCodecVideoDecoder { |
mediaCodecThread = null; |
if (useSurface) { |
surface.release(); |
- if (textureID != 0) { |
- Logging.d(TAG, "Delete video decoder TextureID " + textureID); |
- GLES20.glDeleteTextures(1, new int[] {textureID}, 0); |
- textureID = 0; |
- } |
- eglBase.release(); |
- eglBase = null; |
+ surface = null; |
+ surfaceTextureHelper.disconnect(); |
+ surfaceTextureHelper = null; |
} |
} |
+ @Override |
+ public void onTextureFrameAvailable(int oesTextureId, float[] transformMatrix, long timestampNs) { |
+ // Forward to JNI class. |
+ nativeOnTextureFrame(nativeDecoder, width, height, oesTextureId, transformMatrix, timestampNs); |
+ } |
+ |
+ public void returnTextureFrame() { |
+ surfaceTextureHelper.returnTextureFrame(); |
+ } |
+ |
// Dequeue an input buffer and return its index, -1 if no input buffer is |
// available, or -2 if the codec is no longer operative. |
private int dequeueInputBuffer() { |
@@ -387,4 +385,7 @@ public class MediaCodecVideoDecoder { |
return false; |
} |
} |
+ |
+ private static native void nativeOnTextureFrame(long nativeDecoder, int width, int height, |
+ int oesTextureId, float[] transformMatrix, long timestampNs); |
} |