OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 package org.webrtc; | |
12 | |
13 import android.content.Context; | |
14 import android.hardware.display.VirtualDisplay; | |
15 import android.view.Surface; | |
16 | |
17 import java.util.ArrayList; | |
18 import java.util.List; | |
19 | |
20 /** | |
21 * An implementation of VideoCapturer to capture the screen content as a video s tream. | |
22 * Capturing is done by {@code MediaProjection} on a {@code SurfaceTexture}. We interact with this | |
23 * {@code SurfaceTexture} using a {@code SurfaceTextureHelper}. | |
24 * The {@code SurfaceTextureHelper} is created by the native code and passed to this capturer in | |
25 * {@code VideoCapturer.initialize()}. On receiving a new frame, this capturer p asses it | |
26 * as a texture to the native code via {@code CapturerObserver.onTextureFrameCap tured()}. This takes | |
27 * place on the HandlerThread of the given {@code SurfaceTextureHelper}. When do ne with each frame, | |
28 * the native code returns the buffer to the {@code SurfaceTextureHelper} to be used for new | |
29 * frames. At any time, at most one frame is being processed. | |
30 * | |
31 * Note that startCapture(), stopCapture(), and dispose() are called from native code. | |
32 * Normally, a Java application should interact with {@code }VideSource} API, wh ich indirectly calls | |
33 * these methods on the underlying {@code VideoCapturer}. | |
34 */ | |
magjed_webrtc
2016/08/24 12:19:21
Add @TargetApi(20) here. You need to import androi
arsany
2016/08/26 02:07:36
We actually need API 21 for the media projection.
| |
35 public class ScreenCapturerAndroid implements | |
36 VideoCapturer, SurfaceTextureHelper.OnTextureFrameAvailableListener { | |
37 | |
38 private final static String TAG = "ScreenCapturerAndroid"; | |
magjed_webrtc
2016/08/24 12:19:22
This is currently not used, so you can remove it.
arsany
2016/08/26 02:07:36
Done.
| |
39 | |
40 private int width; | |
41 private int height; | |
42 private VirtualDisplay virtualDisplay; | |
43 private SurfaceTextureHelper surfaceTextureHelper; | |
44 private CapturerObserver capturerObserver; | |
45 private long numCapturedFrames = 0; | |
46 | |
47 // True once the captures has been disposed once. No methods should be called after that; | |
48 // getInstance would return a new instance(); | |
49 private boolean isDisposed; | |
50 | |
51 | |
52 /** | |
53 * Constructs a new Screen Capturer. | |
54 **/ | |
55 public ScreenCapturerAndroid() { | |
56 isDisposed = false; | |
57 } | |
58 | |
59 /** | |
60 * Setup the capturer with the given VirtualDisplay and capture dimensions. | |
61 * This has to be called before the capturer is started the first time. | |
62 * If the dimensions of the captured screen change (e.g. phone orientation cha nged), | |
63 * stop the video source, call this method with the new dimensions, and restar t the source again. | |
64 */ | |
65 public void setup(VirtualDisplay virtualDisplay, int width, int height) { | |
magjed_webrtc
2016/08/24 12:19:22
What's the benefit of creating the VirtualDisplay
arsany
2016/08/26 02:07:36
Originally I made this class create and manage the
magjed_webrtc
2016/08/26 10:23:49
I see. I agree that we should keep the class self-
| |
66 checkNotDisposed(); | |
67 this.width = width; | |
68 this.height = height; | |
69 this.virtualDisplay = virtualDisplay; | |
70 } | |
71 | |
72 private void checkNotDisposed() { | |
73 if (isDisposed) { | |
74 throw new RuntimeException("capturer is disposed."); | |
75 } | |
76 } | |
77 | |
78 @Override | |
79 public synchronized List<CameraEnumerationAndroid.CaptureFormat> getSupportedF ormats() { | |
80 List<CameraEnumerationAndroid.CaptureFormat> supportedFormats = new ArrayLis t<>(); | |
81 supportedFormats.add(new CameraEnumerationAndroid.CaptureFormat( | |
82 width, height, 1 /* minFrameRate */, 30 /* maxFrameRate */)); | |
83 return supportedFormats; | |
84 } | |
85 | |
86 @Override | |
87 public synchronized void initialize( | |
88 final SurfaceTextureHelper surfaceTextureHelper, | |
89 final Context ignored_applicationContext, | |
90 final VideoCapturer.CapturerObserver capturerObserver) { | |
91 checkNotDisposed(); | |
92 | |
93 if (capturerObserver == null) { | |
94 throw new RuntimeException("capturerObserver not set."); | |
95 } | |
96 this.capturerObserver = capturerObserver; | |
97 | |
98 if (surfaceTextureHelper == null) { | |
99 throw new RuntimeException("surfaceTextureHelper not set."); | |
100 } | |
101 this.surfaceTextureHelper = surfaceTextureHelper; | |
102 } | |
103 | |
104 // Initially called by native code. This can also be called from native code w hen the | |
105 // enclosing VideoSource is "restarted" after being stopped. | |
106 @Override | |
107 public synchronized void startCapture( | |
108 final int ignored_width, | |
109 final int ignored_height, | |
110 final int ignored_framerate) { | |
111 checkNotDisposed(); | |
112 | |
113 this.surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(width, he ight); | |
114 virtualDisplay.setSurface(new Surface(surfaceTextureHelper.getSurfaceTexture ())); | |
magjed_webrtc
2016/08/24 12:19:22
This function requires API 20. If we create the Vi
arsany
2016/08/26 02:07:36
I removed this function since I made this class cr
| |
115 capturerObserver.onCapturerStarted(true); | |
116 surfaceTextureHelper.startListening(ScreenCapturerAndroid.this); | |
117 } | |
118 | |
119 // Called by native code to pause capturing. | |
120 @Override | |
121 public synchronized void stopCapture() { | |
122 checkNotDisposed(); | |
123 | |
124 ThreadUtils.invokeAtFrontUninterruptibly(surfaceTextureHelper.getHandler(), new Runnable() { | |
125 @Override | |
126 public void run() { | |
127 surfaceTextureHelper.stopListening(); | |
128 } | |
129 }); | |
130 } | |
131 | |
132 // Called from native code to dispose the capturer when the enclosing VideoSou rce is disposed. | |
133 // The native code calls stopCapture() before calling this method. | |
134 @Override | |
135 public synchronized void dispose() { | |
136 isDisposed = true; | |
137 surfaceTextureHelper = null; | |
138 capturerObserver = null; | |
139 } | |
140 | |
141 @Override | |
142 public void onOutputFormatRequest(int width, int height, int framerate) {} | |
magjed_webrtc
2016/08/24 12:19:22
You can implement this with:
surfaceTextureHelper.
arsany
2016/08/26 02:07:36
Done.
| |
143 | |
144 @Override | |
145 public void changeCaptureFormat(int width, int height, int framerate) {} | |
magjed_webrtc
2016/08/24 12:19:21
Does this function make sense for screencast? We s
arsany
2016/08/26 02:07:36
We actually need this functionality, especially wh
| |
146 | |
147 // This is called on the internal looper thread of {@Code SurfaceTextureHelper }. | |
148 @Override | |
149 public void onTextureFrameAvailable(int oesTextureId, float[] transformMatrix, long timestampNs) { | |
150 numCapturedFrames++; | |
151 capturerObserver.onTextureFrameCaptured(width, height, oesTextureId, transfo rmMatrix, | |
152 0 /* rotation */, timestampNs); | |
153 } | |
154 | |
155 @Override | |
156 public boolean isScreencast() { | |
157 return true; | |
158 } | |
159 | |
160 public long getNumCapturedFrames() { | |
161 return numCapturedFrames; | |
162 } | |
163 } | |
OLD | NEW |