| 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);
 | 
|  }
 | 
| 
 |