Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
ImageReaderPlatformViewRenderTarget.java
Go to the documentation of this file.
1package io.flutter.plugin.platform;
2
3import static io.flutter.Build.API_LEVELS;
4
5import android.annotation.TargetApi;
6import android.graphics.ImageFormat;
7import android.hardware.HardwareBuffer;
8import android.media.Image;
9import android.media.ImageReader;
10import android.os.Build;
11import android.os.Handler;
12import android.view.Surface;
13import io.flutter.Log;
14import io.flutter.view.TextureRegistry.ImageTextureEntry;
15
16@TargetApi(API_LEVELS.API_29)
18 private ImageTextureEntry textureEntry;
19 private ImageReader reader;
20 private int bufferWidth = 0;
21 private int bufferHeight = 0;
22 private static final String TAG = "ImageReaderPlatformViewRenderTarget";
23 private static final int MAX_IMAGES = 4;
24
25 private void closeReader() {
26 if (this.reader != null) {
27 // Push a null image, forcing the texture entry to close any cached images.
28 textureEntry.pushImage(null);
29 // Close the reader, which also closes any produced images.
30 this.reader.close();
31 this.reader = null;
32 }
33 }
34
35 private final Handler onImageAvailableHandler = new Handler();
36 private final ImageReader.OnImageAvailableListener onImageAvailableListener =
37 new ImageReader.OnImageAvailableListener() {
38 @Override
39 public void onImageAvailable(ImageReader reader) {
40 Image image = null;
41 try {
42 image = reader.acquireLatestImage();
43 } catch (IllegalStateException e) {
44 Log.e(TAG, "onImageAvailable acquireLatestImage failed: " + e.toString());
45 }
46 if (image == null) {
47 return;
48 }
49 textureEntry.pushImage(image);
50 }
51 };
52
53 @TargetApi(API_LEVELS.API_33)
54 protected ImageReader createImageReader33() {
55 final ImageReader.Builder builder = new ImageReader.Builder(bufferWidth, bufferHeight);
56 // Allow for double buffering.
57 builder.setMaxImages(MAX_IMAGES);
58 // Use PRIVATE image format so that we can support video decoding.
59 // TODO(johnmccutchan): Should we always use PRIVATE here? It may impact our ability to read
60 // back texture data. If we don't always want to use it, how do we decide when to use it or not?
61 // Perhaps PlatformViews can indicate if they may contain DRM'd content. I need to investigate
62 // how PRIVATE impacts our ability to take screenshots or capture the output of Flutter
63 // application.
64 builder.setImageFormat(ImageFormat.PRIVATE);
65 // Hint that consumed images will only be read by GPU.
66 builder.setUsage(HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
67 final ImageReader reader = builder.build();
68 reader.setOnImageAvailableListener(this.onImageAvailableListener, onImageAvailableHandler);
69 return reader;
70 }
71
72 @TargetApi(API_LEVELS.API_29)
73 protected ImageReader createImageReader29() {
74 final ImageReader reader =
75 ImageReader.newInstance(
76 bufferWidth,
77 bufferHeight,
78 ImageFormat.PRIVATE,
79 MAX_IMAGES,
80 HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
81 reader.setOnImageAvailableListener(this.onImageAvailableListener, onImageAvailableHandler);
82 return reader;
83 }
84
85 protected ImageReader createImageReader() {
86 if (Build.VERSION.SDK_INT >= API_LEVELS.API_33) {
87 return createImageReader33();
88 } else if (Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
89 return createImageReader29();
90 }
91 throw new UnsupportedOperationException(
92 "ImageReaderPlatformViewRenderTarget requires API version 29+");
93 }
94
95 public ImageReaderPlatformViewRenderTarget(ImageTextureEntry textureEntry) {
96 if (Build.VERSION.SDK_INT < API_LEVELS.API_29) {
97 throw new UnsupportedOperationException(
98 "ImageReaderPlatformViewRenderTarget requires API version 29+");
99 }
100 this.textureEntry = textureEntry;
101 }
102
103 public void resize(int width, int height) {
104 if (this.reader != null && bufferWidth == width && bufferHeight == height) {
105 // No size change.
106 return;
107 }
108 closeReader();
109 bufferWidth = width;
110 bufferHeight = height;
111 this.reader = createImageReader();
112 }
113
114 public int getWidth() {
115 return this.bufferWidth;
116 }
117
118 public int getHeight() {
119 return this.bufferHeight;
120 }
121
122 public long getId() {
123 return this.textureEntry.id();
124 }
125
126 public void release() {
127 closeReader();
128 // textureEntry has a finalizer attached.
129 textureEntry = null;
130 }
131
132 public boolean isReleased() {
133 return this.textureEntry == null;
134 }
135
137 return this.reader.getSurface();
138 }
139}
static void e(@NonNull String tag, @NonNull String message)
Definition Log.java:84
sk_sp< SkImage > image
Definition examples.cpp:29
#define TAG()
int32_t height
int32_t width