Chromium Code Reviews| 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()) + ": "; |