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