mirror of
https://github.com/samsonjs/media.git
synced 2026-03-27 09:45:47 +00:00
Add SurfaceCapturer base class, and provide the first implementation
Use PixelCopy API for the first SurfaceCapturer implementation. This supports devices from API 24+. Github: #3609. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=197732711
This commit is contained in:
parent
a98d8fedfa
commit
0cb34dcd1c
5 changed files with 127 additions and 5 deletions
BIN
library/core/src/androidTest/assets/bitmap/image_256_256.png
Normal file
BIN
library/core/src/androidTest/assets/bitmap/image_256_256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
library/core/src/androidTest/assets/bitmap/image_80_60.bmp
Normal file
BIN
library/core/src/androidTest/assets/bitmap/image_80_60.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.surfacecapturer;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.Surface;
|
||||
|
||||
/**
|
||||
* A surface capturer, which captures image drawn into its surface as bitmaps.
|
||||
*
|
||||
* <p>It constructs a {@link Surface}, which can be used as the output surface for an image producer
|
||||
* to draw images to. As images are being drawn into this surface, this capturer will capture these
|
||||
* images, and return them via {@link Callback}. The output images will have a fixed frame size of
|
||||
* (width, height), and any image drawn into the surface will be stretched to fit this frame size.
|
||||
*/
|
||||
public abstract class SurfaceCapturer {
|
||||
|
||||
/** The callback to be notified of the image capturing result. */
|
||||
public interface Callback {
|
||||
|
||||
/**
|
||||
* Called when the surface capturer has been able to capture its surface into a {@link Bitmap}.
|
||||
* This will happen whenever the producer updates the image on the wrapped surface.
|
||||
*/
|
||||
void onSurfaceCaptured(Bitmap bitmap);
|
||||
|
||||
/** Called when the surface capturer couldn't capture its surface due to an error. */
|
||||
void onSurfaceCaptureError(Exception e);
|
||||
}
|
||||
|
||||
/** The callback to be notified of the image capturing result. */
|
||||
private final Callback callback;
|
||||
/** The width of the output images. */
|
||||
private final int outputWidth;
|
||||
/** The height of the output images. */
|
||||
private final int outputHeight;
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param callback See {@link #callback}.
|
||||
* @param outputWidth See {@link #outputWidth}.
|
||||
* @param outputHeight See {@link #outputHeight}.
|
||||
*/
|
||||
protected SurfaceCapturer(Callback callback, int outputWidth, int outputHeight) {
|
||||
this.callback = callback;
|
||||
this.outputWidth = outputWidth;
|
||||
this.outputHeight = outputHeight;
|
||||
}
|
||||
|
||||
/** Returns the callback to be notified of the image capturing result. */
|
||||
protected Callback getCallback() {
|
||||
return callback;
|
||||
}
|
||||
|
||||
/** Returns the width of the output images. */
|
||||
public int getOutputWidth() {
|
||||
return outputWidth;
|
||||
}
|
||||
|
||||
/** Returns the height of the output images. */
|
||||
public int getOutputHeight() {
|
||||
return outputHeight;
|
||||
}
|
||||
|
||||
/** Returns a {@link Surface} that image producers (camera, video codec etc...) can draw to. */
|
||||
public abstract Surface getSurface();
|
||||
|
||||
/** Releases all kept resources. This instance cannot be used after this call. */
|
||||
public abstract void release();
|
||||
}
|
||||
|
|
@ -33,6 +33,12 @@ import java.lang.annotation.RetentionPolicy;
|
|||
@TargetApi(17)
|
||||
public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableListener, Runnable {
|
||||
|
||||
/** Listener to be called when the texture image on {@link SurfaceTexture} has been updated. */
|
||||
public interface TextureImageListener {
|
||||
/** Called when the {@link SurfaceTexture} receives a new frame from its image producer. */
|
||||
void onFrameAvailable();
|
||||
}
|
||||
|
||||
/** Secure mode to be used by the EGL surface and context. */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({SECURE_MODE_NONE, SECURE_MODE_SURFACELESS_CONTEXT, SECURE_MODE_PROTECTED_PBUFFER})
|
||||
|
|
@ -45,6 +51,9 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
|
|||
/** Creating a secure surface backed by a pixel buffer. */
|
||||
public static final int SECURE_MODE_PROTECTED_PBUFFER = 2;
|
||||
|
||||
private static final int EGL_SURFACE_WIDTH = 1;
|
||||
private static final int EGL_SURFACE_HEIGHT = 1;
|
||||
|
||||
private static final int[] EGL_CONFIG_ATTRIBUTES =
|
||||
new int[] {
|
||||
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
|
||||
|
|
@ -69,6 +78,7 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
|
|||
|
||||
private final Handler handler;
|
||||
private final int[] textureIdHolder;
|
||||
private final @Nullable TextureImageListener callback;
|
||||
|
||||
private @Nullable EGLDisplay display;
|
||||
private @Nullable EGLContext context;
|
||||
|
|
@ -82,7 +92,21 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
|
|||
* looper.
|
||||
*/
|
||||
public EGLSurfaceTexture(Handler handler) {
|
||||
this(handler, /* callback= */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param handler The {@link Handler} that will be used to call {@link
|
||||
* SurfaceTexture#updateTexImage()} to update images on the {@link SurfaceTexture}. Note that
|
||||
* {@link #init(int)} has to be called on the same looper thread as the looper of the {@link
|
||||
* Handler}.
|
||||
* @param callback The {@link TextureImageListener} to be called when the texture image on {@link
|
||||
* SurfaceTexture} has been updated. This callback will be called on the same handler thread
|
||||
* as the {@code handler}.
|
||||
*/
|
||||
public EGLSurfaceTexture(Handler handler, @Nullable TextureImageListener callback) {
|
||||
this.handler = handler;
|
||||
this.callback = callback;
|
||||
textureIdHolder = new int[1];
|
||||
}
|
||||
|
||||
|
|
@ -142,8 +166,20 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
// Run on the provided handler thread when a new image frame is available.
|
||||
dispatchOnFrameAvailable();
|
||||
if (texture != null) {
|
||||
texture.updateTexImage();
|
||||
try {
|
||||
texture.updateTexImage();
|
||||
} catch (RuntimeException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchOnFrameAvailable() {
|
||||
if (callback != null) {
|
||||
callback.onFrameAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,9 +256,9 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
|
|||
pbufferAttributes =
|
||||
new int[] {
|
||||
EGL14.EGL_WIDTH,
|
||||
1,
|
||||
EGL_SURFACE_WIDTH,
|
||||
EGL14.EGL_HEIGHT,
|
||||
1,
|
||||
EGL_SURFACE_HEIGHT,
|
||||
EGL_PROTECTED_CONTENT_EXT,
|
||||
EGL14.EGL_TRUE,
|
||||
EGL14.EGL_NONE
|
||||
|
|
@ -230,8 +266,10 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
|
|||
} else {
|
||||
pbufferAttributes =
|
||||
new int[] {
|
||||
EGL14.EGL_WIDTH, 1,
|
||||
EGL14.EGL_HEIGHT, 1,
|
||||
EGL14.EGL_WIDTH,
|
||||
EGL_SURFACE_WIDTH,
|
||||
EGL14.EGL_HEIGHT,
|
||||
EGL_SURFACE_HEIGHT,
|
||||
EGL14.EGL_NONE
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue