Index: webrtc/sdk/android/api/org/webrtc/TextureViewRenderer.java |
diff --git a/webrtc/sdk/android/api/org/webrtc/SurfaceViewRenderer.java b/webrtc/sdk/android/api/org/webrtc/TextureViewRenderer.java |
similarity index 80% |
copy from webrtc/sdk/android/api/org/webrtc/SurfaceViewRenderer.java |
copy to webrtc/sdk/android/api/org/webrtc/TextureViewRenderer.java |
index 2a9d04f0460bbf5fdbeff16b157780ffdefc0186..a3dad22c0581c05b355eaa2d099de47cc8f26173 100644 |
--- a/webrtc/sdk/android/api/org/webrtc/SurfaceViewRenderer.java |
+++ b/webrtc/sdk/android/api/org/webrtc/TextureViewRenderer.java |
@@ -12,10 +12,15 @@ package org.webrtc; |
import android.content.Context; |
import android.content.res.Resources.NotFoundException; |
+import android.graphics.Matrix; |
import android.graphics.Point; |
+import android.graphics.SurfaceTexture; |
import android.util.AttributeSet; |
+import android.view.Surface; |
import android.view.SurfaceHolder; |
-import android.view.SurfaceView; |
+import android.view.TextureView; |
+import android.view.TextureView.SurfaceTextureListener; |
+ |
import java.util.concurrent.CountDownLatch; |
/** |
@@ -27,8 +32,8 @@ import java.util.concurrent.CountDownLatch; |
* Interaction from the Activity lifecycle in surfaceCreated, surfaceChanged, and surfaceDestroyed. |
* Interaction with the layout framework in onMeasure and onSizeChanged. |
*/ |
-public class SurfaceViewRenderer |
- extends SurfaceView implements SurfaceHolder.Callback, VideoRenderer.Callbacks { |
+public class TextureViewRenderer extends TextureView |
+ implements SurfaceHolder.Callback, SurfaceTextureListener, VideoRenderer.Callbacks { |
private static final String TAG = "SurfaceViewRenderer"; |
// Cached resource name. |
@@ -54,21 +59,21 @@ public class SurfaceViewRenderer |
/** |
* Standard View constructor. In order to render something, you must first call init(). |
*/ |
- public SurfaceViewRenderer(Context context) { |
+ public TextureViewRenderer(Context context) { |
super(context); |
this.resourceName = getResourceName(); |
eglRenderer = new EglRenderer(resourceName); |
- getHolder().addCallback(this); |
+ setSurfaceTextureListener(this); |
} |
/** |
* Standard View constructor. In order to render something, you must first call init(). |
*/ |
- public SurfaceViewRenderer(Context context, AttributeSet attrs) { |
+ public TextureViewRenderer(Context context, AttributeSet attrs) { |
super(context, attrs); |
this.resourceName = getResourceName(); |
eglRenderer = new EglRenderer(resourceName); |
- getHolder().addCallback(this); |
+ setSurfaceTextureListener(this); |
} |
/** |
@@ -115,7 +120,7 @@ public class SurfaceViewRenderer |
* It should be lightweight and must not call removeFrameListener. |
* @param scale The scale of the Bitmap passed to the callback, or 0 if no Bitmap is |
* required. |
- * @param drawer Custom drawer to use for this frame listener. |
+ * @param drawerParam Custom drawer to use for this frame listener. |
*/ |
public void addFrameListener( |
EglRenderer.FrameListener listener, float scale, RendererCommon.GlDrawer drawerParam) { |
@@ -240,15 +245,45 @@ public class SurfaceViewRenderer |
if (width != surfaceWidth || height != surfaceHeight) { |
surfaceWidth = width; |
surfaceHeight = height; |
- getHolder().setFixedSize(width, height); |
+ adjustAspectRatio(surfaceWidth, surfaceHeight); |
sakal
2017/06/16 07:47:02
This doesn't change the surface size?
|
} |
} else { |
surfaceWidth = surfaceHeight = 0; |
sakal
2017/06/16 07:47:02
We have to somehow reset the surface size
|
- getHolder().setSizeFromLayout(); |
} |
} |
} |
+ /** |
+ * Sets the TextureView transform to preserve the aspect ratio of the video. |
+ */ |
+ private void adjustAspectRatio(int videoWidth, int videoHeight) { |
sakal
2017/06/16 07:47:02
This method is not needed if you correctly call se
|
+ int viewWidth = getWidth(); |
+ int viewHeight = getHeight(); |
+ double aspectRatio = (double) videoHeight / videoWidth; |
+ |
+ int newWidth, newHeight; |
+ if (viewHeight > (int) (viewWidth * aspectRatio)) { |
+ // limited by narrow width; restrict height |
+ newWidth = viewWidth; |
+ newHeight = (int) (viewWidth * aspectRatio); |
+ } else { |
+ // limited by short height; restrict width |
+ newWidth = (int) (viewHeight / aspectRatio); |
+ newHeight = viewHeight; |
+ } |
+ int xoff = (viewWidth - newWidth) / 2; |
+ int yoff = (viewHeight - newHeight) / 2; |
+ logD("video=" + videoWidth + "x" + videoHeight + " view=" + viewWidth + "x" + viewHeight |
+ + " newView=" + newWidth + "x" + newHeight + " off=" + xoff + "," + yoff); |
+ |
+ Matrix txform = new Matrix(); |
+ getTransform(txform); |
+ txform.setScale((float) newWidth / viewWidth, (float) newHeight / viewHeight); |
+ // txform.postRotate(10); // just for fun |
+ txform.postTranslate(xoff, yoff); |
+ setTransform(txform); |
+ } |
+ |
// SurfaceHolder.Callback interface. |
@Override |
public void surfaceCreated(final SurfaceHolder holder) { |
@@ -277,6 +312,38 @@ public class SurfaceViewRenderer |
logD("surfaceChanged: format: " + format + " size: " + width + "x" + height); |
} |
+ // TextureView.SurfaceTextureListener implementation |
+ @Override |
+ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) { |
+ ThreadUtils.checkIsOnMainThread(); |
+ eglRenderer.createEglSurface(new Surface(surfaceTexture)); |
+ surfaceWidth = surfaceHeight = 0; |
+ updateSurfaceSize(); |
+ } |
+ |
+ @Override |
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) { |
+ ThreadUtils.checkIsOnMainThread(); |
+ logD("surfaceChanged: size: " + width + "x" + height); |
+ } |
+ |
+ @Override |
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { |
+ ThreadUtils.checkIsOnMainThread(); |
+ final CountDownLatch completionLatch = new CountDownLatch(1); |
+ eglRenderer.releaseEglSurface(new Runnable() { |
+ @Override |
+ public void run() { |
+ completionLatch.countDown(); |
+ } |
+ }); |
+ ThreadUtils.awaitUninterruptibly(completionLatch); |
+ return true; |
+ } |
+ |
+ @Override |
+ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {} |
+ |
private String getResourceName() { |
try { |
return getResources().getResourceEntryName(getId()) + ": "; |