OLD | NEW |
---|---|
(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 #include "media/screen_capture/android/screen_capture_machine_android.h" | |
6 | |
7 #include "base/android/jni_android.h" | |
8 #include "base/android/scoped_java_ref.h" | |
9 #include "content/browser/media/capture/video_capture_oracle.h" | |
10 #include "jni/ScreenCapture_jni.h" | |
11 #include "media/base/video_capture_types.h" | |
12 #include "media/base/yuv_convert.h" | |
13 #include "media/screen_capture/android/screen_capture_factory_android.h" | |
14 #include "third_party/libyuv/include/libyuv.h" | |
15 | |
16 using base::android::AttachCurrentThread; | |
17 | |
18 namespace media { | |
19 | |
20 // static | |
21 bool ScreenCaptureMachineAndroid::RegisterScreenCaptureMachine(JNIEnv* env) { | |
22 return media::RegisterNativesImpl(env); | |
23 } | |
24 | |
25 | |
26 ScreenCaptureMachineAndroid::ScreenCaptureMachineAndroid() {} | |
27 | |
28 ScreenCaptureMachineAndroid::~ScreenCaptureMachineAndroid() {} | |
29 | |
30 void ScreenCaptureMachineAndroid::OnFrameAvailable(JNIEnv* env, | |
31 jobject obj, | |
32 jbyteArray data, | |
33 jint cropWidth, | |
34 jint cropHeight, | |
35 jlong timestamp) { | |
36 const content::VideoCaptureOracle::Event event = | |
37 content::VideoCaptureOracle::kCompositorUpdate; | |
38 uint64_t absolute_micro = | |
39 static_cast<int64>(timestamp / base::Time::kNanosecondsPerMicrosecond); | |
40 const base::TimeTicks start_time = | |
41 base::TimeTicks::FromInternalValue(absolute_micro); | |
42 scoped_refptr<media::VideoFrame> frame; | |
43 content::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; | |
44 | |
45 bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( | |
46 event, gfx::Rect(), start_time, &frame, &capture_frame_cb); | |
47 | |
48 if (!oracle_decision) { | |
whywhat
2015/08/17 13:58:46
nit: no need for {} for a one line if statement.
| |
49 return; | |
50 } | |
51 | |
52 jbyte* buffer = env->GetByteArrayElements(data, NULL); | |
53 if (!buffer) { | |
54 return; | |
whywhat
2015/08/17 13:58:46
ditto
| |
55 } | |
56 | |
57 uint8* source_argb = reinterpret_cast<uint8_t*>(buffer); | |
58 int source_stride = cropWidth * 4; | |
59 // If needed, scale the captured frame to the required size. | |
60 if (gfx::Size(cropWidth, cropHeight) != frame->visible_rect().size()) { | |
61 scoped_ptr<uint8[]> scaled_frame_data; | |
62 scaled_frame_data.reset(new uint8[ | |
63 frame->visible_rect().width() * frame->visible_rect().height() * 4]); | |
64 libyuv::ARGBScale(source_argb, | |
65 source_stride, | |
66 cropWidth, | |
67 cropHeight, | |
68 scaled_frame_data.get(), | |
69 frame->visible_rect().width() * 4, | |
70 frame->visible_rect().width(), | |
71 frame->visible_rect().height(), | |
72 libyuv::kFilterBilinear); | |
73 source_argb = scaled_frame_data.get(); | |
74 source_stride = frame->visible_rect().width() * 4; | |
75 } | |
76 | |
77 // Populate the VideoFrame. | |
78 DCHECK(frame->format() == media::VideoFrame::I420 || | |
79 frame->format() == media::VideoFrame::YV12); | |
80 | |
81 media::ConvertRGB32ToYUV(source_argb, | |
82 frame->visible_data(media::VideoFrame::kYPlane), | |
83 frame->visible_data(media::VideoFrame::kUPlane), | |
84 frame->visible_data(media::VideoFrame::kVPlane), | |
85 frame->visible_rect().width(), | |
86 frame->visible_rect().height(), | |
87 source_stride, | |
88 frame->stride(media::VideoFrame::kYPlane), | |
89 frame->stride(media::VideoFrame::kUPlane)); | |
90 | |
91 // Deliver the populated VideoFrame. | |
92 capture_frame_cb.Run(frame, start_time, true); | |
93 | |
94 env->ReleaseByteArrayElements(data, buffer, JNI_ABORT); | |
95 } | |
96 | |
97 void ScreenCaptureMachineAndroid::OnActivityResult(JNIEnv* env, | |
98 jobject obj, | |
99 jint result) { | |
100 if (result == 0) { | |
101 oracle_proxy_->ReportError("The user denied screen capture"); | |
102 return; | |
103 } | |
104 | |
105 media::Java_ScreenCapture_startCapture(env, obj); | |
106 } | |
107 | |
108 void ScreenCaptureMachineAndroid::Start( | |
109 const scoped_refptr<content::ThreadSafeCaptureOracle>& oracle_proxy, | |
110 const media::VideoCaptureParams& params, | |
111 const base::Callback<void(bool)> callback) { | |
112 DCHECK(oracle_proxy.get()); | |
113 oracle_proxy_ = oracle_proxy; | |
114 | |
115 j_capture_.Reset(media::ScreenCaptureFactoryAndroid | |
116 ::createScreenCaptureMachineAndroid(reinterpret_cast<intptr_t>(this))); | |
117 | |
118 if (j_capture_.obj() == NULL) { | |
119 LOG(ERROR) << "Failed to createScreenCaptureAndroid," | |
120 " Maybe android version is too low"; | |
121 callback.Run(false); | |
122 return; | |
123 } | |
124 | |
125 power_save_blocker_.reset( | |
126 content::PowerSaveBlocker::Create( | |
127 content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, | |
128 content::PowerSaveBlocker::kReasonOther, | |
129 "ScreenCaptureMachineAndroid is running").release()); | |
130 | |
131 capture_format_ = params.requested_format; | |
132 // This capturer always outputs ARGB, non-interlaced. | |
133 capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB; | |
134 | |
135 CHECK(capture_format_.frame_size.GetArea() > 0); | |
136 CHECK(!(capture_format_.frame_size.width() % 2)); | |
137 CHECK(!(capture_format_.frame_size.height() % 2)); | |
138 | |
139 JNIEnv* env = AttachCurrentThread(); | |
140 jboolean ret = media::Java_ScreenCapture_startPrompt(env, j_capture_.obj(), | |
141 capture_format_.frame_size.width(), capture_format_.frame_size.height()); | |
142 if (!ret) { | |
143 callback.Run(false); | |
144 return; | |
145 } | |
146 | |
147 callback.Run(true); | |
148 } | |
149 | |
150 void ScreenCaptureMachineAndroid::Stop(const base::Closure& callback) { | |
151 power_save_blocker_.reset(); | |
152 | |
153 JNIEnv* env = AttachCurrentThread(); | |
154 Java_ScreenCapture_stopCapture(env, j_capture_.obj()); | |
155 | |
156 callback.Run(); | |
157 } | |
158 | |
159 } // namespace content | |
OLD | NEW |