OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 package org.webrtc; | 11 package org.webrtc; |
12 | 12 |
13 import android.graphics.SurfaceTexture; | 13 import android.graphics.SurfaceTexture; |
14 import android.opengl.GLES11Ext; | 14 import android.opengl.GLES11Ext; |
15 import android.opengl.GLES20; | 15 import android.opengl.GLES20; |
16 import android.os.Build; | 16 import android.os.Build; |
17 import android.os.Handler; | 17 import android.os.Handler; |
18 import android.os.HandlerThread; | 18 import android.os.HandlerThread; |
19 import android.os.SystemClock; | 19 import android.os.SystemClock; |
20 import java.nio.ByteBuffer; | 20 import java.nio.ByteBuffer; |
21 import java.nio.FloatBuffer; | 21 import java.nio.FloatBuffer; |
22 import java.util.concurrent.Callable; | 22 import java.util.concurrent.Callable; |
23 import java.util.concurrent.TimeUnit; | 23 import java.util.concurrent.TimeUnit; |
| 24 import org.webrtc.VideoFrame.I420Buffer; |
| 25 import org.webrtc.VideoFrame.TextureBuffer; |
24 | 26 |
25 /** | 27 /** |
26 * Helper class to create and synchronize access to a SurfaceTexture. The caller
will get notified | 28 * Helper class to create and synchronize access to a SurfaceTexture. The caller
will get notified |
27 * of new frames in onTextureFrameAvailable(), and should call returnTextureFram
e() when done with | 29 * of new frames in onTextureFrameAvailable(), and should call returnTextureFram
e() when done with |
28 * the frame. Only one texture frame can be in flight at once, so returnTextureF
rame() must be | 30 * the frame. Only one texture frame can be in flight at once, so returnTextureF
rame() must be |
29 * called in order to receive a new frame. Call stopListening() to stop receivei
ng new frames. Call | 31 * called in order to receive a new frame. Call stopListening() to stop receivei
ng new frames. Call |
30 * dispose to release all resources once the texture frame is returned. | 32 * dispose to release all resources once the texture frame is returned. |
31 * Note that there is a C++ counter part of this class that optionally can be us
ed. It is used for | 33 * Note that there is a C++ counter part of this class that optionally can be us
ed. It is used for |
32 * wrapping texture frames into webrtc::VideoFrames and also handles calling ret
urnTextureFrame() | 34 * wrapping texture frames into webrtc::VideoFrames and also handles calling ret
urnTextureFrame() |
33 * when the webrtc::VideoFrame is no longer used. | 35 * when the webrtc::VideoFrame is no longer used. |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 throw new IllegalStateException("Unexpected release."); | 272 throw new IllegalStateException("Unexpected release."); |
271 } | 273 } |
272 if (yuvConverter != null) { | 274 if (yuvConverter != null) { |
273 yuvConverter.release(); | 275 yuvConverter.release(); |
274 } | 276 } |
275 GLES20.glDeleteTextures(1, new int[] {oesTextureId}, 0); | 277 GLES20.glDeleteTextures(1, new int[] {oesTextureId}, 0); |
276 surfaceTexture.release(); | 278 surfaceTexture.release(); |
277 eglBase.release(); | 279 eglBase.release(); |
278 handler.getLooper().quit(); | 280 handler.getLooper().quit(); |
279 } | 281 } |
| 282 |
| 283 /** |
| 284 * Creates a VideoFrame buffer backed by this helper's texture. The |width| an
d |height| should |
| 285 * match the dimensions of the data placed in the texture. The correct |transf
ormMatrix| may be |
| 286 * obtained from callbacks to OnTextureFrameAvailableListener. |
| 287 * |
| 288 * The returned TextureBuffer holds a reference to the SurfaceTextureHelper th
at created it. The |
| 289 * buffer calls returnTextureFrame() when it is released. |
| 290 */ |
| 291 public TextureBuffer createTextureBuffer(int width, int height, float[] transf
ormMatrix) { |
| 292 return new OesTextureBuffer(oesTextureId, width, height, transformMatrix, th
is); |
| 293 } |
| 294 |
| 295 /** |
| 296 * Android OES texture buffer backed by a SurfaceTextureHelper's texture. The
buffer calls |
| 297 * returnTextureFrame() when it is released. |
| 298 */ |
| 299 private static class OesTextureBuffer implements TextureBuffer { |
| 300 private final int id; |
| 301 private final int width; |
| 302 private final int height; |
| 303 private final float[] transformMatrix; |
| 304 private final SurfaceTextureHelper helper; |
| 305 private int refCount; |
| 306 |
| 307 OesTextureBuffer( |
| 308 int id, int width, int height, float[] transformMatrix, SurfaceTextureHe
lper helper) { |
| 309 this.id = id; |
| 310 this.width = width; |
| 311 this.height = height; |
| 312 this.transformMatrix = transformMatrix; |
| 313 this.helper = helper; |
| 314 this.refCount = 1; // Creator implicitly holds a reference. |
| 315 } |
| 316 |
| 317 @Override |
| 318 public TextureBuffer.Type getType() { |
| 319 return TextureBuffer.Type.OES; |
| 320 } |
| 321 |
| 322 @Override |
| 323 public int getTextureId() { |
| 324 return id; |
| 325 } |
| 326 |
| 327 @Override |
| 328 public int getWidth() { |
| 329 return width; |
| 330 } |
| 331 |
| 332 @Override |
| 333 public int getHeight() { |
| 334 return height; |
| 335 } |
| 336 |
| 337 @Override |
| 338 public I420Buffer toI420() { |
| 339 // SurfaceTextureHelper requires a stride that is divisible by 8. Round w
idth up. |
| 340 // See SurfaceTextureHelper for details on the size and format. |
| 341 int stride = ((width + 7) / 8) * 8; |
| 342 int uvHeight = (height + 1) / 2; |
| 343 // Due to the layout used by SurfaceTextureHelper, vPos + stride * uvHeigh
t would overrun the |
| 344 // buffer. Add one row at the bottom to compensate for this. There will
never be data in the |
| 345 // extra row, but now other code does not have to deal with v stride * v h
eight exceeding the |
| 346 // buffer's capacity. |
| 347 int size = stride * (height + uvHeight + 1); |
| 348 ByteBuffer buffer = ByteBuffer.allocateDirect(size); |
| 349 helper.textureToYUV(buffer, width, height, stride, id, transformMatrix); |
| 350 |
| 351 int yPos = 0; |
| 352 int uPos = yPos + stride * height; |
| 353 // Rows of U and V alternate in the buffer, so V data starts after the fir
st row of U. |
| 354 int vPos = yPos + stride / 2; |
| 355 |
| 356 // SurfaceTextureHelper uses the same stride for Y, U, and V data. |
| 357 return new I420BufferImpl( |
| 358 buffer, width, height, yPos, stride, uPos, stride, vPos, stride, null)
; |
| 359 } |
| 360 |
| 361 @Override |
| 362 public void retain() { |
| 363 ++refCount; |
| 364 } |
| 365 |
| 366 @Override |
| 367 public void release() { |
| 368 if (--refCount == 0) { |
| 369 helper.returnTextureFrame(); |
| 370 } |
| 371 } |
| 372 } |
280 } | 373 } |
OLD | NEW |