| OLD | NEW |
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2014 Google Inc. | 3 * Copyright 2014 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 import android.graphics.Point; | 37 import android.graphics.Point; |
| 38 import android.graphics.Rect; | 38 import android.graphics.Rect; |
| 39 import android.graphics.SurfaceTexture; | 39 import android.graphics.SurfaceTexture; |
| 40 import android.opengl.EGL14; | 40 import android.opengl.EGL14; |
| 41 import android.opengl.EGLContext; | 41 import android.opengl.EGLContext; |
| 42 import android.opengl.GLES20; | 42 import android.opengl.GLES20; |
| 43 import android.opengl.GLSurfaceView; | 43 import android.opengl.GLSurfaceView; |
| 44 import android.opengl.Matrix; | 44 import android.opengl.Matrix; |
| 45 import android.util.Log; | 45 import android.util.Log; |
| 46 | 46 |
| 47 import org.webrtc.Logging; |
| 47 import org.webrtc.VideoRenderer.I420Frame; | 48 import org.webrtc.VideoRenderer.I420Frame; |
| 48 | 49 |
| 49 /** | 50 /** |
| 50 * Efficiently renders YUV frames using the GPU for CSC. | 51 * Efficiently renders YUV frames using the GPU for CSC. |
| 51 * Clients will want first to call setView() to pass GLSurfaceView | 52 * Clients will want first to call setView() to pass GLSurfaceView |
| 52 * and then for each video stream either create instance of VideoRenderer using | 53 * and then for each video stream either create instance of VideoRenderer using |
| 53 * createGui() call or VideoRenderer.Callbacks interface using create() call. | 54 * createGui() call or VideoRenderer.Callbacks interface using create() call. |
| 54 * Only one instance of the class can be created. | 55 * Only one instance of the class can be created. |
| 55 */ | 56 */ |
| 56 public class VideoRendererGui implements GLSurfaceView.Renderer { | 57 public class VideoRendererGui implements GLSurfaceView.Renderer { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 private int videoHeight; | 152 private int videoHeight; |
| 152 | 153 |
| 153 // This is the degree that the frame should be rotated clockwisely to have | 154 // This is the degree that the frame should be rotated clockwisely to have |
| 154 // it rendered up right. | 155 // it rendered up right. |
| 155 private int rotationDegree; | 156 private int rotationDegree; |
| 156 | 157 |
| 157 private YuvImageRenderer( | 158 private YuvImageRenderer( |
| 158 GLSurfaceView surface, int id, | 159 GLSurfaceView surface, int id, |
| 159 int x, int y, int width, int height, | 160 int x, int y, int width, int height, |
| 160 RendererCommon.ScalingType scalingType, boolean mirror) { | 161 RendererCommon.ScalingType scalingType, boolean mirror) { |
| 161 Log.d(TAG, "YuvImageRenderer.Create id: " + id); | 162 Logging.d(TAG, "YuvImageRenderer.Create id: " + id); |
| 162 this.surface = surface; | 163 this.surface = surface; |
| 163 this.id = id; | 164 this.id = id; |
| 164 this.scalingType = scalingType; | 165 this.scalingType = scalingType; |
| 165 this.mirror = mirror; | 166 this.mirror = mirror; |
| 166 layoutInPercentage = new Rect(x, y, Math.min(100, x + width), Math.min(100
, y + height)); | 167 layoutInPercentage = new Rect(x, y, Math.min(100, x + width), Math.min(100
, y + height)); |
| 167 updateLayoutProperties = false; | 168 updateLayoutProperties = false; |
| 168 rotationDegree = 0; | 169 rotationDegree = 0; |
| 169 } | 170 } |
| 170 | 171 |
| 171 private synchronized void release() { | 172 private synchronized void release() { |
| 172 surface = null; | 173 surface = null; |
| 173 synchronized (pendingFrameLock) { | 174 synchronized (pendingFrameLock) { |
| 174 if (pendingFrame != null) { | 175 if (pendingFrame != null) { |
| 175 VideoRenderer.renderFrameDone(pendingFrame); | 176 VideoRenderer.renderFrameDone(pendingFrame); |
| 176 pendingFrame = null; | 177 pendingFrame = null; |
| 177 } | 178 } |
| 178 } | 179 } |
| 179 } | 180 } |
| 180 | 181 |
| 181 private void createTextures() { | 182 private void createTextures() { |
| 182 Log.d(TAG, " YuvImageRenderer.createTextures " + id + " on GL thread:" + | 183 Logging.d(TAG, " YuvImageRenderer.createTextures " + id + " on GL thread:
" + |
| 183 Thread.currentThread().getId()); | 184 Thread.currentThread().getId()); |
| 184 | 185 |
| 185 // Generate 3 texture ids for Y/U/V and place them into |yuvTextures|. | 186 // Generate 3 texture ids for Y/U/V and place them into |yuvTextures|. |
| 186 for (int i = 0; i < 3; i++) { | 187 for (int i = 0; i < 3; i++) { |
| 187 yuvTextures[i] = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D); | 188 yuvTextures[i] = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D); |
| 188 } | 189 } |
| 189 } | 190 } |
| 190 | 191 |
| 191 private void updateLayoutMatrix() { | 192 private void updateLayoutMatrix() { |
| 192 synchronized(updateLayoutLock) { | 193 synchronized(updateLayoutLock) { |
| 193 if (!updateLayoutProperties) { | 194 if (!updateLayoutProperties) { |
| 194 return; | 195 return; |
| 195 } | 196 } |
| 196 // Initialize to maximum allowed area. Round to integer coordinates inwa
rds the layout | 197 // Initialize to maximum allowed area. Round to integer coordinates inwa
rds the layout |
| 197 // bounding box (ceil left/top and floor right/bottom) to not break cons
traints. | 198 // bounding box (ceil left/top and floor right/bottom) to not break cons
traints. |
| 198 displayLayout.set( | 199 displayLayout.set( |
| 199 (screenWidth * layoutInPercentage.left + 99) / 100, | 200 (screenWidth * layoutInPercentage.left + 99) / 100, |
| 200 (screenHeight * layoutInPercentage.top + 99) / 100, | 201 (screenHeight * layoutInPercentage.top + 99) / 100, |
| 201 (screenWidth * layoutInPercentage.right) / 100, | 202 (screenWidth * layoutInPercentage.right) / 100, |
| 202 (screenHeight * layoutInPercentage.bottom) / 100); | 203 (screenHeight * layoutInPercentage.bottom) / 100); |
| 203 Log.d(TAG, "ID: " + id + ". AdjustTextureCoords. Allowed display size:
" | 204 Logging.d(TAG, "ID: " + id + ". AdjustTextureCoords. Allowed display si
ze: " |
| 204 + displayLayout.width() + " x " + displayLayout.height() + ". Video:
" + videoWidth | 205 + displayLayout.width() + " x " + displayLayout.height() + ". Video:
" + videoWidth |
| 205 + " x " + videoHeight + ". Rotation: " + rotationDegree + ". Mirror:
" + mirror); | 206 + " x " + videoHeight + ". Rotation: " + rotationDegree + ". Mirror:
" + mirror); |
| 206 final float videoAspectRatio = (rotationDegree % 180 == 0) | 207 final float videoAspectRatio = (rotationDegree % 180 == 0) |
| 207 ? (float) videoWidth / videoHeight | 208 ? (float) videoWidth / videoHeight |
| 208 : (float) videoHeight / videoWidth; | 209 : (float) videoHeight / videoWidth; |
| 209 // Adjust display size based on |scalingType|. | 210 // Adjust display size based on |scalingType|. |
| 210 final Point displaySize = RendererCommon.getDisplaySize(scalingType, | 211 final Point displaySize = RendererCommon.getDisplaySize(scalingType, |
| 211 videoAspectRatio, displayLayout.width(), displayLayout.height()); | 212 videoAspectRatio, displayLayout.width(), displayLayout.height()); |
| 212 displayLayout.inset((displayLayout.width() - displaySize.x) / 2, | 213 displayLayout.inset((displayLayout.width() - displaySize.x) / 2, |
| 213 (displayLayout.height() - displaySize.y) / 2); | 214 (displayLayout.height() - displaySize.y) / 2); |
| 214 Log.d(TAG, " Adjusted display size: " + displayLayout.width() + " x " | 215 Logging.d(TAG, " Adjusted display size: " + displayLayout.width() + " x
" |
| 215 + displayLayout.height()); | 216 + displayLayout.height()); |
| 216 layoutMatrix = RendererCommon.getLayoutMatrix( | 217 layoutMatrix = RendererCommon.getLayoutMatrix( |
| 217 mirror, videoAspectRatio, (float) displayLayout.width() / displayLay
out.height()); | 218 mirror, videoAspectRatio, (float) displayLayout.width() / displayLay
out.height()); |
| 218 updateLayoutProperties = false; | 219 updateLayoutProperties = false; |
| 219 Log.d(TAG, " AdjustTextureCoords done"); | 220 Logging.d(TAG, " AdjustTextureCoords done"); |
| 220 } | 221 } |
| 221 } | 222 } |
| 222 | 223 |
| 223 private void draw(GlRectDrawer drawer) { | 224 private void draw(GlRectDrawer drawer) { |
| 224 if (!seenFrame) { | 225 if (!seenFrame) { |
| 225 // No frame received yet - nothing to render. | 226 // No frame received yet - nothing to render. |
| 226 return; | 227 return; |
| 227 } | 228 } |
| 228 long now = System.nanoTime(); | 229 long now = System.nanoTime(); |
| 229 | 230 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 framesRendered++; | 277 framesRendered++; |
| 277 drawTimeNs += (System.nanoTime() - now); | 278 drawTimeNs += (System.nanoTime() - now); |
| 278 if ((framesRendered % 300) == 0) { | 279 if ((framesRendered % 300) == 0) { |
| 279 logStatistics(); | 280 logStatistics(); |
| 280 } | 281 } |
| 281 } | 282 } |
| 282 } | 283 } |
| 283 | 284 |
| 284 private void logStatistics() { | 285 private void logStatistics() { |
| 285 long timeSinceFirstFrameNs = System.nanoTime() - startTimeNs; | 286 long timeSinceFirstFrameNs = System.nanoTime() - startTimeNs; |
| 286 Log.d(TAG, "ID: " + id + ". Type: " + rendererType + | 287 Logging.d(TAG, "ID: " + id + ". Type: " + rendererType + |
| 287 ". Frames received: " + framesReceived + | 288 ". Frames received: " + framesReceived + |
| 288 ". Dropped: " + framesDropped + ". Rendered: " + framesRendered); | 289 ". Dropped: " + framesDropped + ". Rendered: " + framesRendered); |
| 289 if (framesReceived > 0 && framesRendered > 0) { | 290 if (framesReceived > 0 && framesRendered > 0) { |
| 290 Log.d(TAG, "Duration: " + (int)(timeSinceFirstFrameNs / 1e6) + | 291 Logging.d(TAG, "Duration: " + (int)(timeSinceFirstFrameNs / 1e6) + |
| 291 " ms. FPS: " + (float)framesRendered * 1e9 / timeSinceFirstFrameNs); | 292 " ms. FPS: " + (float)framesRendered * 1e9 / timeSinceFirstFrameNs); |
| 292 Log.d(TAG, "Draw time: " + | 293 Logging.d(TAG, "Draw time: " + |
| 293 (int) (drawTimeNs / (1000 * framesRendered)) + " us. Copy time: " + | 294 (int) (drawTimeNs / (1000 * framesRendered)) + " us. Copy time: " + |
| 294 (int) (copyTimeNs / (1000 * framesReceived)) + " us"); | 295 (int) (copyTimeNs / (1000 * framesReceived)) + " us"); |
| 295 } | 296 } |
| 296 } | 297 } |
| 297 | 298 |
| 298 public void setScreenSize(final int screenWidth, final int screenHeight) { | 299 public void setScreenSize(final int screenWidth, final int screenHeight) { |
| 299 synchronized(updateLayoutLock) { | 300 synchronized(updateLayoutLock) { |
| 300 if (screenWidth == this.screenWidth && screenHeight == this.screenHeight
) { | 301 if (screenWidth == this.screenWidth && screenHeight == this.screenHeight
) { |
| 301 return; | 302 return; |
| 302 } | 303 } |
| 303 Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setScreenSize: " + | 304 Logging.d(TAG, "ID: " + id + ". YuvImageRenderer.setScreenSize: " + |
| 304 screenWidth + " x " + screenHeight); | 305 screenWidth + " x " + screenHeight); |
| 305 this.screenWidth = screenWidth; | 306 this.screenWidth = screenWidth; |
| 306 this.screenHeight = screenHeight; | 307 this.screenHeight = screenHeight; |
| 307 updateLayoutProperties = true; | 308 updateLayoutProperties = true; |
| 308 } | 309 } |
| 309 } | 310 } |
| 310 | 311 |
| 311 public void setPosition(int x, int y, int width, int height, | 312 public void setPosition(int x, int y, int width, int height, |
| 312 RendererCommon.ScalingType scalingType, boolean mirror) { | 313 RendererCommon.ScalingType scalingType, boolean mirror) { |
| 313 final Rect layoutInPercentage = | 314 final Rect layoutInPercentage = |
| 314 new Rect(x, y, Math.min(100, x + width), Math.min(100, y + height)); | 315 new Rect(x, y, Math.min(100, x + width), Math.min(100, y + height)); |
| 315 synchronized(updateLayoutLock) { | 316 synchronized(updateLayoutLock) { |
| 316 if (layoutInPercentage.equals(this.layoutInPercentage) && scalingType ==
this.scalingType | 317 if (layoutInPercentage.equals(this.layoutInPercentage) && scalingType ==
this.scalingType |
| 317 && mirror == this.mirror) { | 318 && mirror == this.mirror) { |
| 318 return; | 319 return; |
| 319 } | 320 } |
| 320 Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setPosition: (" + x + ", "
+ y + | 321 Logging.d(TAG, "ID: " + id + ". YuvImageRenderer.setPosition: (" + x + "
, " + y + |
| 321 ") " + width + " x " + height + ". Scaling: " + scalingType + | 322 ") " + width + " x " + height + ". Scaling: " + scalingType + |
| 322 ". Mirror: " + mirror); | 323 ". Mirror: " + mirror); |
| 323 this.layoutInPercentage.set(layoutInPercentage); | 324 this.layoutInPercentage.set(layoutInPercentage); |
| 324 this.scalingType = scalingType; | 325 this.scalingType = scalingType; |
| 325 this.mirror = mirror; | 326 this.mirror = mirror; |
| 326 updateLayoutProperties = true; | 327 updateLayoutProperties = true; |
| 327 } | 328 } |
| 328 } | 329 } |
| 329 | 330 |
| 330 private void setSize(final int videoWidth, final int videoHeight, final int
rotation) { | 331 private void setSize(final int videoWidth, final int videoHeight, final int
rotation) { |
| 331 if (videoWidth == this.videoWidth && videoHeight == this.videoHeight | 332 if (videoWidth == this.videoWidth && videoHeight == this.videoHeight |
| 332 && rotation == rotationDegree) { | 333 && rotation == rotationDegree) { |
| 333 return; | 334 return; |
| 334 } | 335 } |
| 335 if (rendererEvents != null) { | 336 if (rendererEvents != null) { |
| 336 Log.d(TAG, "ID: " + id + | 337 Logging.d(TAG, "ID: " + id + |
| 337 ". Reporting frame resolution changed to " + videoWidth + " x " + vi
deoHeight); | 338 ". Reporting frame resolution changed to " + videoWidth + " x " + vi
deoHeight); |
| 338 rendererEvents.onFrameResolutionChanged(videoWidth, videoHeight, rotatio
n); | 339 rendererEvents.onFrameResolutionChanged(videoWidth, videoHeight, rotatio
n); |
| 339 } | 340 } |
| 340 | 341 |
| 341 synchronized (updateLayoutLock) { | 342 synchronized (updateLayoutLock) { |
| 342 Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setSize: " + | 343 Logging.d(TAG, "ID: " + id + ". YuvImageRenderer.setSize: " + |
| 343 videoWidth + " x " + videoHeight + " rotation " + rotation); | 344 videoWidth + " x " + videoHeight + " rotation " + rotation); |
| 344 | 345 |
| 345 this.videoWidth = videoWidth; | 346 this.videoWidth = videoWidth; |
| 346 this.videoHeight = videoHeight; | 347 this.videoHeight = videoHeight; |
| 347 rotationDegree = rotation; | 348 rotationDegree = rotation; |
| 348 updateLayoutProperties = true; | 349 updateLayoutProperties = true; |
| 349 Log.d(TAG, " YuvImageRenderer.setSize done."); | 350 Logging.d(TAG, " YuvImageRenderer.setSize done."); |
| 350 } | 351 } |
| 351 } | 352 } |
| 352 | 353 |
| 353 @Override | 354 @Override |
| 354 public synchronized void renderFrame(I420Frame frame) { | 355 public synchronized void renderFrame(I420Frame frame) { |
| 355 if (surface == null) { | 356 if (surface == null) { |
| 356 // This object has been released. | 357 // This object has been released. |
| 357 VideoRenderer.renderFrameDone(frame); | 358 VideoRenderer.renderFrameDone(frame); |
| 358 return; | 359 return; |
| 359 } | 360 } |
| 360 if (!seenFrame && rendererEvents != null) { | 361 if (!seenFrame && rendererEvents != null) { |
| 361 Log.d(TAG, "ID: " + id + ". Reporting first rendered frame."); | 362 Logging.d(TAG, "ID: " + id + ". Reporting first rendered frame."); |
| 362 rendererEvents.onFirstFrameRendered(); | 363 rendererEvents.onFirstFrameRendered(); |
| 363 } | 364 } |
| 364 framesReceived++; | 365 framesReceived++; |
| 365 synchronized (pendingFrameLock) { | 366 synchronized (pendingFrameLock) { |
| 366 // Check input frame parameters. | 367 // Check input frame parameters. |
| 367 if (frame.yuvFrame) { | 368 if (frame.yuvFrame) { |
| 368 if (frame.yuvStrides[0] < frame.width || | 369 if (frame.yuvStrides[0] < frame.width || |
| 369 frame.yuvStrides[1] < frame.width / 2 || | 370 frame.yuvStrides[1] < frame.width / 2 || |
| 370 frame.yuvStrides[2] < frame.width / 2) { | 371 frame.yuvStrides[2] < frame.width / 2) { |
| 371 Log.e(TAG, "Incorrect strides " + frame.yuvStrides[0] + ", " + | 372 Logging.e(TAG, "Incorrect strides " + frame.yuvStrides[0] + ", " + |
| 372 frame.yuvStrides[1] + ", " + frame.yuvStrides[2]); | 373 frame.yuvStrides[1] + ", " + frame.yuvStrides[2]); |
| 373 VideoRenderer.renderFrameDone(frame); | 374 VideoRenderer.renderFrameDone(frame); |
| 374 return; | 375 return; |
| 375 } | 376 } |
| 376 } | 377 } |
| 377 | 378 |
| 378 if (pendingFrame != null) { | 379 if (pendingFrame != null) { |
| 379 // Skip rendering of this frame if previous frame was not rendered yet
. | 380 // Skip rendering of this frame if previous frame was not rendered yet
. |
| 380 framesDropped++; | 381 framesDropped++; |
| 381 VideoRenderer.renderFrameDone(frame); | 382 VideoRenderer.renderFrameDone(frame); |
| 382 return; | 383 return; |
| 383 } | 384 } |
| 384 pendingFrame = frame; | 385 pendingFrame = frame; |
| 385 } | 386 } |
| 386 setSize(frame.width, frame.height, frame.rotationDegree); | 387 setSize(frame.width, frame.height, frame.rotationDegree); |
| 387 seenFrame = true; | 388 seenFrame = true; |
| 388 | 389 |
| 389 // Request rendering. | 390 // Request rendering. |
| 390 surface.requestRender(); | 391 surface.requestRender(); |
| 391 } | 392 } |
| 392 } | 393 } |
| 393 | 394 |
| 394 /** Passes GLSurfaceView to video renderer. */ | 395 /** Passes GLSurfaceView to video renderer. */ |
| 395 public static synchronized void setView(GLSurfaceView surface, | 396 public static synchronized void setView(GLSurfaceView surface, |
| 396 Runnable eglContextReadyCallback) { | 397 Runnable eglContextReadyCallback) { |
| 397 Log.d(TAG, "VideoRendererGui.setView"); | 398 Logging.d(TAG, "VideoRendererGui.setView"); |
| 398 instance = new VideoRendererGui(surface); | 399 instance = new VideoRendererGui(surface); |
| 399 eglContextReady = eglContextReadyCallback; | 400 eglContextReady = eglContextReadyCallback; |
| 400 } | 401 } |
| 401 | 402 |
| 402 public static synchronized EGLContext getEGLContext() { | 403 public static synchronized EGLContext getEGLContext() { |
| 403 return eglContext; | 404 return eglContext; |
| 404 } | 405 } |
| 405 | 406 |
| 406 /** Releases GLSurfaceView video renderer. */ | 407 /** Releases GLSurfaceView video renderer. */ |
| 407 public static synchronized void dispose() { | 408 public static synchronized void dispose() { |
| 408 if (instance == null){ | 409 if (instance == null){ |
| 409 return; | 410 return; |
| 410 } | 411 } |
| 411 Log.d(TAG, "VideoRendererGui.dispose"); | 412 Logging.d(TAG, "VideoRendererGui.dispose"); |
| 412 synchronized (instance.yuvImageRenderers) { | 413 synchronized (instance.yuvImageRenderers) { |
| 413 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { | 414 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { |
| 414 yuvImageRenderer.release(); | 415 yuvImageRenderer.release(); |
| 415 } | 416 } |
| 416 instance.yuvImageRenderers.clear(); | 417 instance.yuvImageRenderers.clear(); |
| 417 } | 418 } |
| 418 instance.surface = null; | 419 instance.surface = null; |
| 419 eglContext = null; | 420 eglContext = null; |
| 420 eglContextReady = null; | 421 eglContextReady = null; |
| 421 instance = null; | 422 instance = null; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 } | 483 } |
| 483 // Add yuv renderer to rendering list. | 484 // Add yuv renderer to rendering list. |
| 484 instance.yuvImageRenderers.add(yuvImageRenderer); | 485 instance.yuvImageRenderers.add(yuvImageRenderer); |
| 485 } | 486 } |
| 486 return yuvImageRenderer; | 487 return yuvImageRenderer; |
| 487 } | 488 } |
| 488 | 489 |
| 489 public static synchronized void update( | 490 public static synchronized void update( |
| 490 VideoRenderer.Callbacks renderer, int x, int y, int width, int height, | 491 VideoRenderer.Callbacks renderer, int x, int y, int width, int height, |
| 491 RendererCommon.ScalingType scalingType, boolean mirror) { | 492 RendererCommon.ScalingType scalingType, boolean mirror) { |
| 492 Log.d(TAG, "VideoRendererGui.update"); | 493 Logging.d(TAG, "VideoRendererGui.update"); |
| 493 if (instance == null) { | 494 if (instance == null) { |
| 494 throw new RuntimeException( | 495 throw new RuntimeException( |
| 495 "Attempt to update yuv renderer before setting GLSurfaceView"); | 496 "Attempt to update yuv renderer before setting GLSurfaceView"); |
| 496 } | 497 } |
| 497 synchronized (instance.yuvImageRenderers) { | 498 synchronized (instance.yuvImageRenderers) { |
| 498 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { | 499 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { |
| 499 if (yuvImageRenderer == renderer) { | 500 if (yuvImageRenderer == renderer) { |
| 500 yuvImageRenderer.setPosition(x, y, width, height, scalingType, mirror)
; | 501 yuvImageRenderer.setPosition(x, y, width, height, scalingType, mirror)
; |
| 501 } | 502 } |
| 502 } | 503 } |
| 503 } | 504 } |
| 504 } | 505 } |
| 505 | 506 |
| 506 public static synchronized void setRendererEvents( | 507 public static synchronized void setRendererEvents( |
| 507 VideoRenderer.Callbacks renderer, RendererCommon.RendererEvents rendererEv
ents) { | 508 VideoRenderer.Callbacks renderer, RendererCommon.RendererEvents rendererEv
ents) { |
| 508 Log.d(TAG, "VideoRendererGui.setRendererEvents"); | 509 Logging.d(TAG, "VideoRendererGui.setRendererEvents"); |
| 509 if (instance == null) { | 510 if (instance == null) { |
| 510 throw new RuntimeException( | 511 throw new RuntimeException( |
| 511 "Attempt to set renderer events before setting GLSurfaceView"); | 512 "Attempt to set renderer events before setting GLSurfaceView"); |
| 512 } | 513 } |
| 513 synchronized (instance.yuvImageRenderers) { | 514 synchronized (instance.yuvImageRenderers) { |
| 514 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { | 515 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { |
| 515 if (yuvImageRenderer == renderer) { | 516 if (yuvImageRenderer == renderer) { |
| 516 yuvImageRenderer.rendererEvents = rendererEvents; | 517 yuvImageRenderer.rendererEvents = rendererEvents; |
| 517 } | 518 } |
| 518 } | 519 } |
| 519 } | 520 } |
| 520 } | 521 } |
| 521 | 522 |
| 522 public static synchronized void remove(VideoRenderer.Callbacks renderer) { | 523 public static synchronized void remove(VideoRenderer.Callbacks renderer) { |
| 523 Log.d(TAG, "VideoRendererGui.remove"); | 524 Logging.d(TAG, "VideoRendererGui.remove"); |
| 524 if (instance == null) { | 525 if (instance == null) { |
| 525 throw new RuntimeException( | 526 throw new RuntimeException( |
| 526 "Attempt to remove yuv renderer before setting GLSurfaceView"); | 527 "Attempt to remove yuv renderer before setting GLSurfaceView"); |
| 527 } | 528 } |
| 528 synchronized (instance.yuvImageRenderers) { | 529 synchronized (instance.yuvImageRenderers) { |
| 529 final int index = instance.yuvImageRenderers.indexOf(renderer); | 530 final int index = instance.yuvImageRenderers.indexOf(renderer); |
| 530 if (index == -1) { | 531 if (index == -1) { |
| 531 Log.w(TAG, "Couldn't remove renderer (not present in current list)"); | 532 Logging.w(TAG, "Couldn't remove renderer (not present in current list)")
; |
| 532 } else { | 533 } else { |
| 533 instance.yuvImageRenderers.remove(index).release(); | 534 instance.yuvImageRenderers.remove(index).release(); |
| 534 } | 535 } |
| 535 } | 536 } |
| 536 } | 537 } |
| 537 | 538 |
| 538 @SuppressLint("NewApi") | 539 @SuppressLint("NewApi") |
| 539 @Override | 540 @Override |
| 540 public void onSurfaceCreated(GL10 unused, EGLConfig config) { | 541 public void onSurfaceCreated(GL10 unused, EGLConfig config) { |
| 541 Log.d(TAG, "VideoRendererGui.onSurfaceCreated"); | 542 Logging.d(TAG, "VideoRendererGui.onSurfaceCreated"); |
| 542 // Store render EGL context. | 543 // Store render EGL context. |
| 543 if (CURRENT_SDK_VERSION >= EGL14_SDK_VERSION) { | 544 if (CURRENT_SDK_VERSION >= EGL14_SDK_VERSION) { |
| 544 synchronized (VideoRendererGui.class) { | 545 synchronized (VideoRendererGui.class) { |
| 545 eglContext = EGL14.eglGetCurrentContext(); | 546 eglContext = EGL14.eglGetCurrentContext(); |
| 546 Log.d(TAG, "VideoRendererGui EGL Context: " + eglContext); | 547 Logging.d(TAG, "VideoRendererGui EGL Context: " + eglContext); |
| 547 } | 548 } |
| 548 } | 549 } |
| 549 | 550 |
| 550 synchronized (yuvImageRenderers) { | 551 synchronized (yuvImageRenderers) { |
| 551 // Create drawer for YUV/OES frames. | 552 // Create drawer for YUV/OES frames. |
| 552 drawer = new GlRectDrawer(); | 553 drawer = new GlRectDrawer(); |
| 553 // Create textures for all images. | 554 // Create textures for all images. |
| 554 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { | 555 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { |
| 555 yuvImageRenderer.createTextures(); | 556 yuvImageRenderer.createTextures(); |
| 556 } | 557 } |
| 557 onSurfaceCreatedCalled = true; | 558 onSurfaceCreatedCalled = true; |
| 558 } | 559 } |
| 559 GlUtil.checkNoGLES2Error("onSurfaceCreated done"); | 560 GlUtil.checkNoGLES2Error("onSurfaceCreated done"); |
| 560 GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1); | 561 GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1); |
| 561 GLES20.glClearColor(0.15f, 0.15f, 0.15f, 1.0f); | 562 GLES20.glClearColor(0.15f, 0.15f, 0.15f, 1.0f); |
| 562 | 563 |
| 563 // Fire EGL context ready event. | 564 // Fire EGL context ready event. |
| 564 synchronized (VideoRendererGui.class) { | 565 synchronized (VideoRendererGui.class) { |
| 565 if (eglContextReady != null) { | 566 if (eglContextReady != null) { |
| 566 eglContextReady.run(); | 567 eglContextReady.run(); |
| 567 } | 568 } |
| 568 } | 569 } |
| 569 } | 570 } |
| 570 | 571 |
| 571 @Override | 572 @Override |
| 572 public void onSurfaceChanged(GL10 unused, int width, int height) { | 573 public void onSurfaceChanged(GL10 unused, int width, int height) { |
| 573 Log.d(TAG, "VideoRendererGui.onSurfaceChanged: " + | 574 Logging.d(TAG, "VideoRendererGui.onSurfaceChanged: " + |
| 574 width + " x " + height + " "); | 575 width + " x " + height + " "); |
| 575 screenWidth = width; | 576 screenWidth = width; |
| 576 screenHeight = height; | 577 screenHeight = height; |
| 577 synchronized (yuvImageRenderers) { | 578 synchronized (yuvImageRenderers) { |
| 578 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { | 579 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { |
| 579 yuvImageRenderer.setScreenSize(screenWidth, screenHeight); | 580 yuvImageRenderer.setScreenSize(screenWidth, screenHeight); |
| 580 } | 581 } |
| 581 } | 582 } |
| 582 } | 583 } |
| 583 | 584 |
| 584 @Override | 585 @Override |
| 585 public void onDrawFrame(GL10 unused) { | 586 public void onDrawFrame(GL10 unused) { |
| 586 GLES20.glViewport(0, 0, screenWidth, screenHeight); | 587 GLES20.glViewport(0, 0, screenWidth, screenHeight); |
| 587 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); | 588 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); |
| 588 synchronized (yuvImageRenderers) { | 589 synchronized (yuvImageRenderers) { |
| 589 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { | 590 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { |
| 590 yuvImageRenderer.draw(drawer); | 591 yuvImageRenderer.draw(drawer); |
| 591 } | 592 } |
| 592 } | 593 } |
| 593 } | 594 } |
| 594 | 595 |
| 595 } | 596 } |
| OLD | NEW |