| 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 24 matching lines...) Expand all Loading... |
| 35 import javax.microedition.khronos.opengles.GL10; | 35 import javax.microedition.khronos.opengles.GL10; |
| 36 | 36 |
| 37 import android.annotation.SuppressLint; | 37 import android.annotation.SuppressLint; |
| 38 import android.graphics.Point; | 38 import android.graphics.Point; |
| 39 import android.graphics.Rect; | 39 import android.graphics.Rect; |
| 40 import android.graphics.SurfaceTexture; | 40 import android.graphics.SurfaceTexture; |
| 41 import android.opengl.EGL14; | 41 import android.opengl.EGL14; |
| 42 import android.opengl.EGLContext; | 42 import android.opengl.EGLContext; |
| 43 import android.opengl.GLES20; | 43 import android.opengl.GLES20; |
| 44 import android.opengl.GLSurfaceView; | 44 import android.opengl.GLSurfaceView; |
| 45 import android.opengl.Matrix; | |
| 46 import android.util.Log; | 45 import android.util.Log; |
| 47 | 46 |
| 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. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 66 // If true then for every newly created yuv image renderer createTexture() | 65 // If true then for every newly created yuv image renderer createTexture() |
| 67 // should be called. The variable is accessed on multiple threads and | 66 // should be called. The variable is accessed on multiple threads and |
| 68 // all accesses are synchronized on yuvImageRenderers' object lock. | 67 // all accesses are synchronized on yuvImageRenderers' object lock. |
| 69 private boolean onSurfaceCreatedCalled; | 68 private boolean onSurfaceCreatedCalled; |
| 70 private int screenWidth; | 69 private int screenWidth; |
| 71 private int screenHeight; | 70 private int screenHeight; |
| 72 // List of yuv renderers. | 71 // List of yuv renderers. |
| 73 private final ArrayList<YuvImageRenderer> yuvImageRenderers; | 72 private final ArrayList<YuvImageRenderer> yuvImageRenderers; |
| 74 // |drawer| is synchronized on |yuvImageRenderers|. | 73 // |drawer| is synchronized on |yuvImageRenderers|. |
| 75 private GlRectDrawer drawer; | 74 private GlRectDrawer drawer; |
| 76 // The minimum fraction of the frame content that will be shown for |SCALE_ASP
ECT_BALANCED|. | |
| 77 // This limits excessive cropping when adjusting display size. | |
| 78 private static float BALANCED_VISIBLE_FRACTION = 0.56f; | |
| 79 // Types of video scaling: | |
| 80 // SCALE_ASPECT_FIT - video frame is scaled to fit the size of the view by | |
| 81 // maintaining the aspect ratio (black borders may be displayed). | |
| 82 // SCALE_ASPECT_FILL - video frame is scaled to fill the size of the view by | |
| 83 // maintaining the aspect ratio. Some portion of the video frame may be | |
| 84 // clipped. | |
| 85 // SCALE_ASPECT_BALANCED - Compromise between FIT and FILL. Video frame will f
ill as much as | |
| 86 // possible of the view while maintaining aspect ratio, under the constraint t
hat at least | |
| 87 // |BALANCED_VISIBLE_FRACTION| of the frame content will be shown. | |
| 88 public static enum ScalingType | |
| 89 { SCALE_ASPECT_FIT, SCALE_ASPECT_FILL, SCALE_ASPECT_BALANCED } | |
| 90 private static final int EGL14_SDK_VERSION = | 75 private static final int EGL14_SDK_VERSION = |
| 91 android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; | 76 android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; |
| 92 // Current SDK version. | 77 // Current SDK version. |
| 93 private static final int CURRENT_SDK_VERSION = | 78 private static final int CURRENT_SDK_VERSION = |
| 94 android.os.Build.VERSION.SDK_INT; | 79 android.os.Build.VERSION.SDK_INT; |
| 95 | 80 |
| 96 private VideoRendererGui(GLSurfaceView surface) { | 81 private VideoRendererGui(GLSurfaceView surface) { |
| 97 this.surface = surface; | 82 this.surface = surface; |
| 98 // Create an OpenGL ES 2.0 context. | 83 // Create an OpenGL ES 2.0 context. |
| 99 surface.setPreserveEGLContextOnPause(true); | 84 surface.setPreserveEGLContextOnPause(true); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 // an offer (writing I420Frame to render) and early-returns (recording | 124 // an offer (writing I420Frame to render) and early-returns (recording |
| 140 // a dropped frame) if that queue is full. draw() call does a peek(), | 125 // a dropped frame) if that queue is full. draw() call does a peek(), |
| 141 // copies frame to texture and then removes it from a queue using poll(). | 126 // copies frame to texture and then removes it from a queue using poll(). |
| 142 private final LinkedBlockingQueue<I420Frame> frameToRenderQueue; | 127 private final LinkedBlockingQueue<I420Frame> frameToRenderQueue; |
| 143 // Local copy of incoming video frame. Synchronized on |frameToRenderQueue|. | 128 // Local copy of incoming video frame. Synchronized on |frameToRenderQueue|. |
| 144 private I420Frame yuvFrameToRender; | 129 private I420Frame yuvFrameToRender; |
| 145 private I420Frame textureFrameToRender; | 130 private I420Frame textureFrameToRender; |
| 146 // Type of video frame used for recent frame rendering. | 131 // Type of video frame used for recent frame rendering. |
| 147 private static enum RendererType { RENDERER_YUV, RENDERER_TEXTURE }; | 132 private static enum RendererType { RENDERER_YUV, RENDERER_TEXTURE }; |
| 148 private RendererType rendererType; | 133 private RendererType rendererType; |
| 149 private ScalingType scalingType; | 134 private RendererCommon.ScalingType scalingType; |
| 150 private boolean mirror; | 135 private boolean mirror; |
| 151 private RendererEvents rendererEvents; | 136 private RendererCommon.RendererEvents rendererEvents; |
| 152 // Flag if renderFrame() was ever called. | 137 // Flag if renderFrame() was ever called. |
| 153 boolean seenFrame; | 138 boolean seenFrame; |
| 154 // Total number of video frames received in renderFrame() call. | 139 // Total number of video frames received in renderFrame() call. |
| 155 private int framesReceived; | 140 private int framesReceived; |
| 156 // Number of video frames dropped by renderFrame() because previous | 141 // Number of video frames dropped by renderFrame() because previous |
| 157 // frame has not been rendered yet. | 142 // frame has not been rendered yet. |
| 158 private int framesDropped; | 143 private int framesDropped; |
| 159 // Number of rendered video frames. | 144 // Number of rendered video frames. |
| 160 private int framesRendered; | 145 private int framesRendered; |
| 161 // Time in ns when the first video frame was rendered. | 146 // Time in ns when the first video frame was rendered. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 183 private int videoWidth; | 168 private int videoWidth; |
| 184 private int videoHeight; | 169 private int videoHeight; |
| 185 | 170 |
| 186 // This is the degree that the frame should be rotated clockwisely to have | 171 // This is the degree that the frame should be rotated clockwisely to have |
| 187 // it rendered up right. | 172 // it rendered up right. |
| 188 private int rotationDegree; | 173 private int rotationDegree; |
| 189 | 174 |
| 190 private YuvImageRenderer( | 175 private YuvImageRenderer( |
| 191 GLSurfaceView surface, int id, | 176 GLSurfaceView surface, int id, |
| 192 int x, int y, int width, int height, | 177 int x, int y, int width, int height, |
| 193 ScalingType scalingType, boolean mirror) { | 178 RendererCommon.ScalingType scalingType, boolean mirror) { |
| 194 Log.d(TAG, "YuvImageRenderer.Create id: " + id); | 179 Log.d(TAG, "YuvImageRenderer.Create id: " + id); |
| 195 this.surface = surface; | 180 this.surface = surface; |
| 196 this.id = id; | 181 this.id = id; |
| 197 this.scalingType = scalingType; | 182 this.scalingType = scalingType; |
| 198 this.mirror = mirror; | 183 this.mirror = mirror; |
| 199 frameToRenderQueue = new LinkedBlockingQueue<I420Frame>(1); | 184 frameToRenderQueue = new LinkedBlockingQueue<I420Frame>(1); |
| 200 layoutInPercentage = new Rect(x, y, Math.min(100, x + width), Math.min(100
, y + height)); | 185 layoutInPercentage = new Rect(x, y, Math.min(100, x + width), Math.min(100
, y + height)); |
| 201 updateTextureProperties = false; | 186 updateTextureProperties = false; |
| 202 rotationDegree = 0; | 187 rotationDegree = 0; |
| 203 } | 188 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 225 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, | 210 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, |
| 226 GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); | 211 GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); |
| 227 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, | 212 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, |
| 228 GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); | 213 GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); |
| 229 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, | 214 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, |
| 230 GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); | 215 GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); |
| 231 } | 216 } |
| 232 GlUtil.checkNoGLES2Error("y/u/v glGenTextures"); | 217 GlUtil.checkNoGLES2Error("y/u/v glGenTextures"); |
| 233 } | 218 } |
| 234 | 219 |
| 235 private static float convertScalingTypeToVisibleFraction(ScalingType scaling
Type) { | |
| 236 switch (scalingType) { | |
| 237 case SCALE_ASPECT_FIT: | |
| 238 return 1.0f; | |
| 239 case SCALE_ASPECT_FILL: | |
| 240 return 0.0f; | |
| 241 case SCALE_ASPECT_BALANCED: | |
| 242 return BALANCED_VISIBLE_FRACTION; | |
| 243 default: | |
| 244 throw new IllegalArgumentException(); | |
| 245 } | |
| 246 } | |
| 247 | |
| 248 private static Point getDisplaySize(float minVisibleFraction, float videoAsp
ectRatio, | |
| 249 int maxDisplayWidth, int maxDisplayHeight) { | |
| 250 // If there is no constraint on the amount of cropping, fill the allowed d
isplay area. | |
| 251 if (minVisibleFraction == 0) { | |
| 252 return new Point(maxDisplayWidth, maxDisplayHeight); | |
| 253 } | |
| 254 // Each dimension is constrained on max display size and how much we are a
llowed to crop. | |
| 255 final int width = Math.min(maxDisplayWidth, | |
| 256 (int) (maxDisplayHeight / minVisibleFraction * videoAspectRatio)); | |
| 257 final int height = Math.min(maxDisplayHeight, | |
| 258 (int) (maxDisplayWidth / minVisibleFraction / videoAspectRatio)); | |
| 259 return new Point(width, height); | |
| 260 } | |
| 261 | |
| 262 private void checkAdjustTextureCoords() { | 220 private void checkAdjustTextureCoords() { |
| 263 synchronized(updateTextureLock) { | 221 synchronized(updateTextureLock) { |
| 264 if (!updateTextureProperties) { | 222 if (!updateTextureProperties) { |
| 265 return; | 223 return; |
| 266 } | 224 } |
| 267 // Initialize to maximum allowed area. Round to integer coordinates inwa
rds the layout | 225 // Initialize to maximum allowed area. Round to integer coordinates inwa
rds the layout |
| 268 // bounding box (ceil left/top and floor right/bottom) to not break cons
traints. | 226 // bounding box (ceil left/top and floor right/bottom) to not break cons
traints. |
| 269 displayLayout.set( | 227 displayLayout.set( |
| 270 (screenWidth * layoutInPercentage.left + 99) / 100, | 228 (screenWidth * layoutInPercentage.left + 99) / 100, |
| 271 (screenHeight * layoutInPercentage.top + 99) / 100, | 229 (screenHeight * layoutInPercentage.top + 99) / 100, |
| 272 (screenWidth * layoutInPercentage.right) / 100, | 230 (screenWidth * layoutInPercentage.right) / 100, |
| 273 (screenHeight * layoutInPercentage.bottom) / 100); | 231 (screenHeight * layoutInPercentage.bottom) / 100); |
| 274 Log.d(TAG, "ID: " + id + ". AdjustTextureCoords. Allowed display size:
" | 232 Log.d(TAG, "ID: " + id + ". AdjustTextureCoords. Allowed display size:
" |
| 275 + displayLayout.width() + " x " + displayLayout.height() + ". Video:
" + videoWidth | 233 + displayLayout.width() + " x " + displayLayout.height() + ". Video:
" + videoWidth |
| 276 + " x " + videoHeight + ". Rotation: " + rotationDegree + ". Mirror:
" + mirror); | 234 + " x " + videoHeight + ". Rotation: " + rotationDegree + ". Mirror:
" + mirror); |
| 277 final float videoAspectRatio = (rotationDegree % 180 == 0) | 235 final float videoAspectRatio = (rotationDegree % 180 == 0) |
| 278 ? (float) videoWidth / videoHeight | 236 ? (float) videoWidth / videoHeight |
| 279 : (float) videoHeight / videoWidth; | 237 : (float) videoHeight / videoWidth; |
| 280 // Adjust display size based on |scalingType|. | 238 // Adjust display size based on |scalingType|. |
| 281 final float minVisibleFraction = convertScalingTypeToVisibleFraction(sca
lingType); | 239 final Point displaySize = RendererCommon.getDisplaySize(scalingType, |
| 282 final Point displaySize = getDisplaySize(minVisibleFraction, videoAspect
Ratio, | 240 videoAspectRatio, displayLayout.width(), displayLayout.height()); |
| 283 displayLayout.width(), displayLayout.height()); | |
| 284 displayLayout.inset((displayLayout.width() - displaySize.x) / 2, | 241 displayLayout.inset((displayLayout.width() - displaySize.x) / 2, |
| 285 (displayLayout.height() - displaySize.y) / 2); | 242 (displayLayout.height() - displaySize.y) / 2); |
| 286 Log.d(TAG, " Adjusted display size: " + displayLayout.width() + " x " | 243 Log.d(TAG, " Adjusted display size: " + displayLayout.width() + " x " |
| 287 + displayLayout.height()); | 244 + displayLayout.height()); |
| 288 // The matrix stack is using post-multiplication, which means that matri
x operations: | 245 RendererCommon.getTextureMatrix(texMatrix, rotationDegree, mirror, video
AspectRatio, |
| 289 // A; B; C; will end up as A * B * C. When you apply this to a vertex, i
t will result in: | 246 (float) displayLayout.width() / displayLayout.height()); |
| 290 // v' = A * B * C * v, i.e. the last matrix operation is the first thing
that affects the | |
| 291 // vertex. This is the opposite of what you might expect. | |
| 292 Matrix.setIdentityM(texMatrix, 0); | |
| 293 // Move coordinates back to [0,1]x[0,1]. | |
| 294 Matrix.translateM(texMatrix, 0, 0.5f, 0.5f, 0.0f); | |
| 295 // Rotate frame clockwise in the XY-plane (around the Z-axis). | |
| 296 Matrix.rotateM(texMatrix, 0, -rotationDegree, 0, 0, 1); | |
| 297 // Scale one dimension until video and display size have same aspect rat
io. | |
| 298 final float displayAspectRatio = (float) displayLayout.width() / display
Layout.height(); | |
| 299 if (displayAspectRatio > videoAspectRatio) { | |
| 300 Matrix.scaleM(texMatrix, 0, 1, videoAspectRatio / displayAspectRatio
, 1); | |
| 301 } else { | |
| 302 Matrix.scaleM(texMatrix, 0, displayAspectRatio / videoAspectRatio, 1
, 1); | |
| 303 } | |
| 304 // TODO(magjed): We currently ignore the texture transform matrix from t
he SurfaceTexture. | |
| 305 // It contains a vertical flip that is hardcoded here instead. | |
| 306 Matrix.scaleM(texMatrix, 0, 1, -1, 1); | |
| 307 // Apply optional horizontal flip. | |
| 308 if (mirror) { | |
| 309 Matrix.scaleM(texMatrix, 0, -1, 1, 1); | |
| 310 } | |
| 311 // Center coordinates around origin. | |
| 312 Matrix.translateM(texMatrix, 0, -0.5f, -0.5f, 0.0f); | |
| 313 updateTextureProperties = false; | 247 updateTextureProperties = false; |
| 314 Log.d(TAG, " AdjustTextureCoords done"); | 248 Log.d(TAG, " AdjustTextureCoords done"); |
| 315 } | 249 } |
| 316 } | 250 } |
| 317 | 251 |
| 318 private void draw(GlRectDrawer drawer) { | 252 private void draw(GlRectDrawer drawer) { |
| 319 if (!seenFrame) { | 253 if (!seenFrame) { |
| 320 // No frame received yet - nothing to render. | 254 // No frame received yet - nothing to render. |
| 321 return; | 255 return; |
| 322 } | 256 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 } | 335 } |
| 402 Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setScreenSize: " + | 336 Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setScreenSize: " + |
| 403 screenWidth + " x " + screenHeight); | 337 screenWidth + " x " + screenHeight); |
| 404 this.screenWidth = screenWidth; | 338 this.screenWidth = screenWidth; |
| 405 this.screenHeight = screenHeight; | 339 this.screenHeight = screenHeight; |
| 406 updateTextureProperties = true; | 340 updateTextureProperties = true; |
| 407 } | 341 } |
| 408 } | 342 } |
| 409 | 343 |
| 410 public void setPosition(int x, int y, int width, int height, | 344 public void setPosition(int x, int y, int width, int height, |
| 411 ScalingType scalingType, boolean mirror) { | 345 RendererCommon.ScalingType scalingType, boolean mirror) { |
| 412 final Rect layoutInPercentage = | 346 final Rect layoutInPercentage = |
| 413 new Rect(x, y, Math.min(100, x + width), Math.min(100, y + height)); | 347 new Rect(x, y, Math.min(100, x + width), Math.min(100, y + height)); |
| 414 synchronized(updateTextureLock) { | 348 synchronized(updateTextureLock) { |
| 415 if (layoutInPercentage.equals(this.layoutInPercentage) && scalingType ==
this.scalingType | 349 if (layoutInPercentage.equals(this.layoutInPercentage) && scalingType ==
this.scalingType |
| 416 && mirror == this.mirror) { | 350 && mirror == this.mirror) { |
| 417 return; | 351 return; |
| 418 } | 352 } |
| 419 Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setPosition: (" + x + ", "
+ y + | 353 Log.d(TAG, "ID: " + id + ". YuvImageRenderer.setPosition: (" + x + ", "
+ y + |
| 420 ") " + width + " x " + height + ". Scaling: " + scalingType + | 354 ") " + width + " x " + height + ". Scaling: " + scalingType + |
| 421 ". Mirror: " + mirror); | 355 ". Mirror: " + mirror); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 surface.requestRender(); | 455 surface.requestRender(); |
| 522 } | 456 } |
| 523 | 457 |
| 524 // TODO(guoweis): Remove this once chrome code base is updated. | 458 // TODO(guoweis): Remove this once chrome code base is updated. |
| 525 @Override | 459 @Override |
| 526 public boolean canApplyRotation() { | 460 public boolean canApplyRotation() { |
| 527 return true; | 461 return true; |
| 528 } | 462 } |
| 529 } | 463 } |
| 530 | 464 |
| 531 /** Interface for reporting rendering events. */ | |
| 532 public static interface RendererEvents { | |
| 533 /** | |
| 534 * Callback fired once first frame is rendered. | |
| 535 */ | |
| 536 public void onFirstFrameRendered(); | |
| 537 | |
| 538 /** | |
| 539 * Callback fired when rendered frame resolution or rotation has changed. | |
| 540 */ | |
| 541 public void onFrameResolutionChanged(int videoWidth, int videoHeight, int ro
tation); | |
| 542 } | |
| 543 | |
| 544 /** Passes GLSurfaceView to video renderer. */ | 465 /** Passes GLSurfaceView to video renderer. */ |
| 545 public static synchronized void setView(GLSurfaceView surface, | 466 public static synchronized void setView(GLSurfaceView surface, |
| 546 Runnable eglContextReadyCallback) { | 467 Runnable eglContextReadyCallback) { |
| 547 Log.d(TAG, "VideoRendererGui.setView"); | 468 Log.d(TAG, "VideoRendererGui.setView"); |
| 548 instance = new VideoRendererGui(surface); | 469 instance = new VideoRendererGui(surface); |
| 549 eglContextReady = eglContextReadyCallback; | 470 eglContextReady = eglContextReadyCallback; |
| 550 } | 471 } |
| 551 | 472 |
| 552 public static synchronized EGLContext getEGLContext() { | 473 public static synchronized EGLContext getEGLContext() { |
| 553 return eglContext; | 474 return eglContext; |
| 554 } | 475 } |
| 555 | 476 |
| 556 /** | 477 /** |
| 557 * Creates VideoRenderer with top left corner at (x, y) and resolution | 478 * Creates VideoRenderer with top left corner at (x, y) and resolution |
| 558 * (width, height). All parameters are in percentage of screen resolution. | 479 * (width, height). All parameters are in percentage of screen resolution. |
| 559 */ | 480 */ |
| 560 public static VideoRenderer createGui(int x, int y, int width, int height, | 481 public static VideoRenderer createGui(int x, int y, int width, int height, |
| 561 ScalingType scalingType, boolean mirror) throws Exception { | 482 RendererCommon.ScalingType scalingType, boolean mirror) throws Exception { |
| 562 YuvImageRenderer javaGuiRenderer = create( | 483 YuvImageRenderer javaGuiRenderer = create( |
| 563 x, y, width, height, scalingType, mirror); | 484 x, y, width, height, scalingType, mirror); |
| 564 return new VideoRenderer(javaGuiRenderer); | 485 return new VideoRenderer(javaGuiRenderer); |
| 565 } | 486 } |
| 566 | 487 |
| 567 public static VideoRenderer.Callbacks createGuiRenderer( | 488 public static VideoRenderer.Callbacks createGuiRenderer( |
| 568 int x, int y, int width, int height, | 489 int x, int y, int width, int height, |
| 569 ScalingType scalingType, boolean mirror) { | 490 RendererCommon.ScalingType scalingType, boolean mirror) { |
| 570 return create(x, y, width, height, scalingType, mirror); | 491 return create(x, y, width, height, scalingType, mirror); |
| 571 } | 492 } |
| 572 | 493 |
| 573 /** | 494 /** |
| 574 * Creates VideoRenderer.Callbacks with top left corner at (x, y) and | 495 * Creates VideoRenderer.Callbacks with top left corner at (x, y) and |
| 575 * resolution (width, height). All parameters are in percentage of | 496 * resolution (width, height). All parameters are in percentage of |
| 576 * screen resolution. | 497 * screen resolution. |
| 577 */ | 498 */ |
| 578 public static synchronized YuvImageRenderer create(int x, int y, int width, in
t height, | 499 public static synchronized YuvImageRenderer create(int x, int y, int width, in
t height, |
| 579 ScalingType scalingType, boolean mirror) { | 500 RendererCommon.ScalingType scalingType, boolean mirror) { |
| 580 // Check display region parameters. | 501 // Check display region parameters. |
| 581 if (x < 0 || x > 100 || y < 0 || y > 100 || | 502 if (x < 0 || x > 100 || y < 0 || y > 100 || |
| 582 width < 0 || width > 100 || height < 0 || height > 100 || | 503 width < 0 || width > 100 || height < 0 || height > 100 || |
| 583 x + width > 100 || y + height > 100) { | 504 x + width > 100 || y + height > 100) { |
| 584 throw new RuntimeException("Incorrect window parameters."); | 505 throw new RuntimeException("Incorrect window parameters."); |
| 585 } | 506 } |
| 586 | 507 |
| 587 if (instance == null) { | 508 if (instance == null) { |
| 588 throw new RuntimeException( | 509 throw new RuntimeException( |
| 589 "Attempt to create yuv renderer before setting GLSurfaceView"); | 510 "Attempt to create yuv renderer before setting GLSurfaceView"); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 612 throw new RuntimeException(e); | 533 throw new RuntimeException(e); |
| 613 } | 534 } |
| 614 } | 535 } |
| 615 // Add yuv renderer to rendering list. | 536 // Add yuv renderer to rendering list. |
| 616 instance.yuvImageRenderers.add(yuvImageRenderer); | 537 instance.yuvImageRenderers.add(yuvImageRenderer); |
| 617 } | 538 } |
| 618 return yuvImageRenderer; | 539 return yuvImageRenderer; |
| 619 } | 540 } |
| 620 | 541 |
| 621 public static synchronized void update( | 542 public static synchronized void update( |
| 622 VideoRenderer.Callbacks renderer, | 543 VideoRenderer.Callbacks renderer, int x, int y, int width, int height, |
| 623 int x, int y, int width, int height, ScalingType scalingType, boolean mirr
or) { | 544 RendererCommon.ScalingType scalingType, boolean mirror) { |
| 624 Log.d(TAG, "VideoRendererGui.update"); | 545 Log.d(TAG, "VideoRendererGui.update"); |
| 625 if (instance == null) { | 546 if (instance == null) { |
| 626 throw new RuntimeException( | 547 throw new RuntimeException( |
| 627 "Attempt to update yuv renderer before setting GLSurfaceView"); | 548 "Attempt to update yuv renderer before setting GLSurfaceView"); |
| 628 } | 549 } |
| 629 synchronized (instance.yuvImageRenderers) { | 550 synchronized (instance.yuvImageRenderers) { |
| 630 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { | 551 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { |
| 631 if (yuvImageRenderer == renderer) { | 552 if (yuvImageRenderer == renderer) { |
| 632 yuvImageRenderer.setPosition(x, y, width, height, scalingType, mirror)
; | 553 yuvImageRenderer.setPosition(x, y, width, height, scalingType, mirror)
; |
| 633 } | 554 } |
| 634 } | 555 } |
| 635 } | 556 } |
| 636 } | 557 } |
| 637 | 558 |
| 638 public static synchronized void setRendererEvents( | 559 public static synchronized void setRendererEvents( |
| 639 VideoRenderer.Callbacks renderer, RendererEvents rendererEvents) { | 560 VideoRenderer.Callbacks renderer, RendererCommon.RendererEvents rendererEv
ents) { |
| 640 Log.d(TAG, "VideoRendererGui.setRendererEvents"); | 561 Log.d(TAG, "VideoRendererGui.setRendererEvents"); |
| 641 if (instance == null) { | 562 if (instance == null) { |
| 642 throw new RuntimeException( | 563 throw new RuntimeException( |
| 643 "Attempt to set renderer events before setting GLSurfaceView"); | 564 "Attempt to set renderer events before setting GLSurfaceView"); |
| 644 } | 565 } |
| 645 synchronized (instance.yuvImageRenderers) { | 566 synchronized (instance.yuvImageRenderers) { |
| 646 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { | 567 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { |
| 647 if (yuvImageRenderer == renderer) { | 568 if (yuvImageRenderer == renderer) { |
| 648 yuvImageRenderer.rendererEvents = rendererEvents; | 569 yuvImageRenderer.rendererEvents = rendererEvents; |
| 649 } | 570 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 GLES20.glViewport(0, 0, screenWidth, screenHeight); | 639 GLES20.glViewport(0, 0, screenWidth, screenHeight); |
| 719 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); | 640 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); |
| 720 synchronized (yuvImageRenderers) { | 641 synchronized (yuvImageRenderers) { |
| 721 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { | 642 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { |
| 722 yuvImageRenderer.draw(drawer); | 643 yuvImageRenderer.draw(drawer); |
| 723 } | 644 } |
| 724 } | 645 } |
| 725 } | 646 } |
| 726 | 647 |
| 727 } | 648 } |
| OLD | NEW |