Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(694)

Side by Side Diff: media/base/android/java/src/org/chromium/media/ScreenCapture.java

Issue 1140113002: Implement screen capture for android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add ScreenCaptureMachineAndroid which inherited from content::VideoCaptureMachine Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.media;
6
7 import android.app.Activity;
8 import android.app.Fragment;
9 import android.app.FragmentManager;
10 import android.app.FragmentTransaction;
11 import android.content.Context;
12 import android.content.Intent;
13 import android.graphics.PixelFormat;
14 import android.hardware.display.DisplayManager;
15 import android.hardware.display.VirtualDisplay;
16 import android.media.Image;
17 import android.media.ImageReader;
18 //import android.media.projection.MediaProjection.Callback;
whywhat 2015/08/17 13:58:46 nit: Uncomment or remove?
19 import android.media.projection.MediaProjection;
20 import android.media.projection.MediaProjectionManager;
21 import android.os.Handler;
22 import android.os.HandlerThread;
23 import android.util.DisplayMetrics;
24 import android.view.Display;
25 import android.view.Surface;
26
27 import org.chromium.base.BaseChromiumApplication;
28 import org.chromium.base.CalledByNative;
29 import org.chromium.base.JNINamespace;
30 import org.chromium.base.Log;
31
32 import java.nio.ByteBuffer;
33
34 /**
35 * This class implements Screen Capture using projection API, introduced in Andr oid
36 * API 21 (L Release). Capture takes place in the current Looper, while pixel
37 * download takes place in another thread used by ImageReader.
38 **/
39 @JNINamespace("media")
40 public class ScreenCapture extends Fragment {
41
42 // Internal class implementing the ImageReader listener. Gets pinged when a
43 // new frame is been captured and downloaded to memory-backed buffers.
44 private class CrImageReaderListener implements ImageReader.OnImageAvailableL istener {
45 @Override
46 public void onImageAvailable(ImageReader reader) {
47 Image image = null;
48 try {
49 image = reader.acquireLatestImage();
50 if (image == null) return;
51 if (image.getFormat() != PixelFormat.RGBA_8888) {
52 Log.e(TAG, "Unexpected image format: " + image.getFormat()
53 + " or #planes: " + image.getPlanes().length);
54 return;
55 }
56
57 Image.Plane[] planes = image.getPlanes();
58 ByteBuffer buffer = (ByteBuffer) planes[0].getBuffer();
59 buffer.get(mCapturedData);
60
61 nativeOnFrameAvailable(mNativeScreenCaptureMachineAndroid,
62 mCapturedData,
63 image.getCropRect().width(),
64 image.getCropRect().height(),
65 image.getTimestamp());
66
67 } catch (IllegalStateException ex) {
68 Log.e(TAG, "acquireLatestImage():" + ex);
69 return;
70 } finally {
71 if (image != null) {
whywhat 2015/08/17 13:58:46 nit: a one liner
72 image.close();
73 }
74 }
75 }
76 };
77
78 private class MediaProjectionCallback extends MediaProjection.Callback {
79 @Override
80 public void onStop() {
81 mMediaProjection = null;
82 if (mVirtualDisplay == null) {
whywhat 2015/08/17 13:58:46 nit: one liner
83 return;
84 }
85 mVirtualDisplay.release();
86 mVirtualDisplay = null;
87 }
88 }
89
90 private byte[] mCapturedData;
91 private final Context mContext;
92
93 private MediaProjection mMediaProjection;
94 private MediaProjectionManager mMediaProjectionManager;
95 private VirtualDisplay mVirtualDisplay;
96 private static final int REQUEST_MEDIA_PROJECTION = 1;
97
98 private Surface mSurface;
99 private ImageReader mImageReader = null;
100 private int mScreenDensity;
101 private int mWidth;
102 private int mHeight;
103 private int mResultCode;
104 private Intent mResultData;
105
106 // Native callback context variable.
107 private final long mNativeScreenCaptureMachineAndroid;
108
109 private static final String TAG = "ScreenCaptureMachine";
110
111 ScreenCapture(Context context, long nativeScreenCaptureMachineAndroid) {
112 mContext = context;
113 mNativeScreenCaptureMachineAndroid = nativeScreenCaptureMachineAndroid;
114 try {
115 BaseChromiumApplication ba = (BaseChromiumApplication) mContext;
116 Activity activity = ba.getActivity();
117 if (activity == null) {
118 Log.e(TAG, "activity is null");
119 return;
120 }
121
122 FragmentManager fragmentManager = activity.getFragmentManager();
123 FragmentTransaction fragmentTransaction = fragmentManager.beginTrans action();
124 fragmentTransaction.add(this, "screencapture");
125 fragmentTransaction.commit();
126
127 DisplayMetrics metrics = new DisplayMetrics();
128 Display display = activity.getWindowManager().getDefaultDisplay();
129 display.getMetrics(metrics);
130 mScreenDensity = metrics.densityDpi;
131 } catch (Exception e) {
132 Log.e(TAG, "ScreenCaptureExcaption " + e);
133 }
134 }
135
136 @Override
137 public void onDetach() {
138 super.onDetach();
139 Log.i(TAG, "onDetach");
140 stopCapture();
141 }
142
143 @CalledByNative
144 public boolean startPrompt(int width, int height) {
145 Log.i(TAG, "startPrompt");
146 try {
147 if (!isAdded()) {
148 Log.e(TAG, "the fragment hasn't been added to an activity");
149 return false;
150 }
151 mWidth = width;
152 mHeight = height;
153 int expectedFrameSize = mWidth * mHeight * 4;
154 mCapturedData = new byte[expectedFrameSize];
155
156 mMediaProjectionManager = (MediaProjectionManager)
157 mContext.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
158 if (mMediaProjectionManager == null) {
159 Log.e(TAG, "mMediaProjectionManager is null");
160 return false;
161 }
162
163 startActivityForResult(mMediaProjectionManager.createScreenCaptureIn tent(),
164 REQUEST_MEDIA_PROJECTION);
165 } catch (Exception e) {
166 Log.e(TAG, "ScreenCaptureExcaption " + e);
167 return false;
168 }
169 return true;
170 }
171
172 @Override
173 public void onActivityResult(int requestCode, int resultCode, Intent data) {
174 if (requestCode == REQUEST_MEDIA_PROJECTION) {
175 int result;
176 if (resultCode != Activity.RESULT_OK) {
177 result = 0;
178 } else {
179 result = 1;
180 mResultCode = resultCode;
181 mResultData = data;
182 }
183 nativeOnActivityResult(mNativeScreenCaptureMachineAndroid, result);
184 }
185 }
186
187 // start screen capture.
whywhat 2015/08/17 13:58:46 nit: follow Javadoc style for public/protected cla
188 @CalledByNative
189 public void startCapture() {
190 Log.i(TAG, "startCapture");
whywhat 2015/08/17 13:58:46 nit: s/Log.i/Log.d?
191 mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCod e, mResultData);
192 if (mMediaProjection == null) {
193 Log.i(TAG, "mMediaProjection is null");
194 return;
195 }
196 mMediaProjection.registerCallback(new MediaProjectionCallback(), null);
197
198 final int maxImages = 2;
199 mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA _8888, maxImages);
200 mSurface = mImageReader.getSurface();
201 HandlerThread thread = new HandlerThread("Screen");
202 thread.start();
203 final Handler backgroundHandler = new Handler(thread.getLooper());
204 final CrImageReaderListener imageReaderListener = new CrImageReaderListe ner();
205 mImageReader.setOnImageAvailableListener(imageReaderListener,
206 backgroundHandler);
207
208 mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenCapture",
209 mWidth, mHeight, mScreenDensity,
210 DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
211 mSurface, null, null);
212 }
213
214 // Stops screen capture.
215 @CalledByNative
216 public void stopCapture() {
217 Log.i(TAG, "stopCapture");
whywhat 2015/08/17 13:58:46 ditto
218 if (mMediaProjection != null) {
219 mMediaProjection.stop();
whywhat 2015/08/17 13:58:46 nit: fits on one line
220 }
221 }
222
223 // Method for ScreenCapture implementations to call back native code.
224 public native void nativeOnFrameAvailable(long nativeScreenCaptureMachineAnd roid,
225 byte[] data,
226 int cropWidth,
227 int cropHeight,
228 long timestamp);
229
230 // Method for ScreenCapture implementations to call back native code.
231 public native void nativeOnActivityResult(long nativeScreenCaptureMachineAnd roid,
whywhat 2015/08/17 13:58:46 Do these or @CalledByNative methdos have to be pub
232 int result);
233
234 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698