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

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: Created 5 years, 7 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.graphics.Point;
15 import android.hardware.display.DisplayManager;
16 import android.hardware.display.VirtualDisplay;
17 import android.media.Image;
18 import android.media.ImageReader;
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(mNativeScreenCapturerAndroid,
miu 2015/05/20 03:33:27 You need to pass extra values here: 1. image.getC
62 mCapturedData,
63 mWidth,
64 mHeight);
65
66 } catch (IllegalStateException ex) {
67 Log.e(TAG, "acquireLatestImage():" + ex);
68 return;
69 } finally {
70 if (image != null) {
71 image.close();
72 }
73 }
74 }
75 };
76
77 private byte[] mCapturedData;
78 private final Context mContext;
79
80 private MediaProjection mMediaProjection;
81 private MediaProjectionManager mMediaProjectionManager;
82 private VirtualDisplay mVirtualDisplay;
83 private static final int REQUEST_MEDIA_PROJECTION = 1;
84
85 private Surface mSurface;
86 private ImageReader mImageReader = null;
87 private int mScreenDensity;
88 private int mWidth;
89 private int mHeight;
90 private int mResultCode;
91 private Intent mResultData;
92 // Native callback context variable.
93 private final long mNativeScreenCapturerAndroid;
94
95 private static final String TAG = "ScreenCaptureAndroid";
96
97 ScreenCapture(Context context, long nativeScreenCapturerAndroid) {
98 mContext = context;
99 mNativeScreenCapturerAndroid = nativeScreenCapturerAndroid;
100 }
101
102 @CalledByNative
103 public void start() {
104 Log.i(TAG, "start");
105 try {
106 BaseChromiumApplication ba = (BaseChromiumApplication) mContext;
107 Activity activity = ba.getActivity();
108 if (activity == null) {
109 Log.e(TAG, "activity is null");
110 return;
111 }
112
113 FragmentManager fragmentManager = activity.getFragmentManager();
114 FragmentTransaction fragmentTransaction = fragmentManager.beginTrans action();
115 fragmentTransaction.add(this, "screencapture");
116 fragmentTransaction.commit();
117
118 DisplayMetrics metrics = new DisplayMetrics();
119 Point size = new Point();
120 Display display = activity.getWindowManager().getDefaultDisplay();
121 display.getMetrics(metrics);
122 display.getSize(size);
123 mScreenDensity = metrics.densityDpi;
124 //mWidth = size.x;
miu 2015/05/20 03:33:27 Did you mean to fix these LOC rather than hard-cod
125 //mHeight = size.y;
126 // Fixeme: If use size.x and size.y as the width and height, the scr een image
127 // will be disordered.
128 mWidth = 640;
129 mHeight = 480;
130 int expectedFrameSize = mWidth * mHeight * 4;
131 mCapturedData = new byte[expectedFrameSize];
132 } catch (Exception e) {
133 Log.e(TAG, "ScreenCapture " + e);
134 return;
135 }
136
137 mMediaProjectionManager = (MediaProjectionManager)
138 mContext.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
139 if (mMediaProjectionManager == null) {
140 Log.e(TAG, "mMediaProjectionManager is null");
141 return;
142 }
143
144 startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent (),
145 REQUEST_MEDIA_PROJECTION);
146 }
147
148 @Override
149 public void onActivityResult(int requestCode, int resultCode, Intent data) {
150 if (requestCode == REQUEST_MEDIA_PROJECTION) {
151 int result;
152 if (resultCode != Activity.RESULT_OK) {
153 result = 0;
154 } else {
155 result = 1;
156 mResultCode = resultCode;
157 mResultData = data;
158 }
159 nativeOnActivityResult(mNativeScreenCapturerAndroid, result);
160 }
161 }
162
163 // start screen capture.
164 @CalledByNative
165 public void startCapture() {
166 Log.i(TAG, "startCapture");
167 mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCod e, mResultData);
168 if (mMediaProjection == null) {
169 Log.i(TAG, "mMediaProjection is null");
170 return;
171 }
172
173 mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA _8888, 2);
miu 2015/05/20 03:33:27 Could you add a comment here about why "2" is a re
174 mSurface = mImageReader.getSurface();
175 HandlerThread thread = new HandlerThread("ScreenPreview");
miu 2015/05/20 03:33:27 ScreenPreview?
176 thread.start();
177 final Handler backgroundHandler = new Handler(thread.getLooper());
178 final CrImageReaderListener imageReaderListener = new CrImageReaderListe ner();
179 mImageReader.setOnImageAvailableListener(imageReaderListener,
180 backgroundHandler);
181
182 mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenCapture",
183 mWidth, mHeight, mScreenDensity,
184 DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
185 mSurface, null, null);
186 }
187
188 // Stops screen capture.
189 @CalledByNative
190 public void stopCapture() {
191 Log.i(TAG, "stopCapture");
192 if (mImageReader != null) mImageReader.close();
193
194 if (mVirtualDisplay != null) {
195 mVirtualDisplay.release();
196 mVirtualDisplay = null;
197 }
198 if (mMediaProjection != null) {
199 mMediaProjection.stop();
200 mMediaProjection = null;
201 }
202 }
203
204 // Method for ScreenCapture implementations to call back native code.
205 public native void nativeOnFrameAvailable(long nativeScreenCapturerAndroid,
206 byte[] data,
207 int width,
208 int height);
209
210 // Method for ScreenCapture implementations to call back native code.
211 public native void nativeOnActivityResult(long nativeScreenCapturerAndroid,
212 int result);
213
214 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698