Chromium Code Reviews| Index: media/capture/content/android/screen_capture_machine_android.cc |
| diff --git a/media/capture/content/android/screen_capture_machine_android.cc b/media/capture/content/android/screen_capture_machine_android.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..02d9c8861a0dc1177db9c88a6c967a8c057e4b55 |
| --- /dev/null |
| +++ b/media/capture/content/android/screen_capture_machine_android.cc |
| @@ -0,0 +1,146 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "media/capture/content/android/screen_capture_machine_android.h" |
| + |
| +#include "base/android/jni_android.h" |
| +#include "base/android/scoped_java_ref.h" |
| +#include "jni/ScreenCapture_jni.h" |
| +#include "media/base/video_capture_types.h" |
| +#include "media/base/yuv_convert.h" |
| +#include "media/capture/content/android/screen_capture_factory_android.h" |
| +#include "media/capture/content/video_capture_oracle.h" |
| +#include "third_party/libyuv/include/libyuv.h" |
| + |
| +using base::android::AttachCurrentThread; |
| + |
| +namespace media { |
| + |
| +// static |
| +bool ScreenCaptureMachineAndroid::RegisterScreenCaptureMachine(JNIEnv* env) { |
| + return media::RegisterNativesImpl(env); |
| +} |
| + |
| +ScreenCaptureMachineAndroid::ScreenCaptureMachineAndroid() {} |
| + |
| +ScreenCaptureMachineAndroid::~ScreenCaptureMachineAndroid() {} |
| + |
| +void ScreenCaptureMachineAndroid::OnFrameAvailable(JNIEnv* env, |
| + jobject obj, |
| + jbyteArray data, |
| + jint cropWidth, |
| + jint cropHeight, |
| + jlong timestamp) { |
| + const media::VideoCaptureOracle::Event event = |
| + media::VideoCaptureOracle::kCompositorUpdate; |
| + uint64_t absolute_micro = |
| + static_cast<int64>(timestamp / base::Time::kNanosecondsPerMicrosecond); |
| + const base::TimeTicks start_time = |
| + base::TimeTicks::FromInternalValue(absolute_micro); |
| + scoped_refptr<media::VideoFrame> frame; |
| + media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; |
| + |
| + bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture( |
|
miu
2016/04/27 05:24:53
I'm not familiar with the API provided by the Andr
braveyao
2016/05/04 18:49:41
Android will send a copy of the whole display when
miu
2016/05/10 00:29:00
Acknowledged. Seems the API designer assumed the p
|
| + event, gfx::Rect(), start_time, &frame, &capture_frame_cb); |
| + |
| + if (!oracle_decision) |
| + return; |
| + |
| + jbyte* buffer = env->GetByteArrayElements(data, NULL); |
| + if (!buffer) |
| + return; |
| + |
| + uint8* source_argb = reinterpret_cast<uint8_t*>(buffer); |
| + int source_stride = cropWidth * 4; |
| + // If needed, scale the captured frame to the required size. |
| + if (gfx::Size(cropWidth, cropHeight) != frame->visible_rect().size()) { |
| + std::unique_ptr<uint8[]> scaled_frame_data; |
| + scaled_frame_data.reset(new uint8[frame->visible_rect().width() * |
| + frame->visible_rect().height() * 4]); |
| + libyuv::ARGBScale(source_argb, source_stride, cropWidth, cropHeight, |
|
miu
2016/04/27 05:24:53
Can the platform do this? Usually scaling is much
braveyao
2016/05/04 18:49:41
Exactly. You can do the setting to VirtualDisplay
miu
2016/05/10 00:29:00
On second thought, if the frame->visible_rect() is
braveyao
2016/05/18 00:41:46
Done.
|
| + scaled_frame_data.get(), |
| + frame->visible_rect().width() * 4, |
| + frame->visible_rect().width(), |
| + frame->visible_rect().height(), libyuv::kFilterBilinear); |
| + source_argb = scaled_frame_data.get(); |
| + source_stride = frame->visible_rect().width() * 4; |
| + } |
| + |
| + // Populate the VideoFrame. |
| + DCHECK(frame->format() == PIXEL_FORMAT_I420 || |
| + frame->format() == PIXEL_FORMAT_YV12); |
| + |
| + media::ConvertRGB32ToYUV( |
|
miu
2016/04/27 05:24:53
Is it possible to push colorspace conversion upstr
braveyao
2016/05/04 18:49:41
Thanks for the advice. I didn't consider this befo
miu
2016/05/10 00:29:00
In Chromium code, we have to work on many differen
braveyao
2016/05/18 00:41:46
Done.
BTW: YUV420 has better performance, but wor
|
| + source_argb, frame->visible_data(media::VideoFrame::kYPlane), |
| + frame->visible_data(media::VideoFrame::kUPlane), |
| + frame->visible_data(media::VideoFrame::kVPlane), |
| + frame->visible_rect().width(), frame->visible_rect().height(), |
| + source_stride, frame->stride(media::VideoFrame::kYPlane), |
| + frame->stride(media::VideoFrame::kUPlane)); |
| + |
| + // Deliver the populated VideoFrame. |
| + capture_frame_cb.Run(frame, start_time, true); |
| + |
| + env->ReleaseByteArrayElements(data, buffer, JNI_ABORT); |
| +} |
| + |
| +void ScreenCaptureMachineAndroid::OnActivityResult(JNIEnv* env, |
| + jobject obj, |
| + jint result) { |
| + if (result == 0) { |
| + oracle_proxy_->ReportError(FROM_HERE, "The user denied screen capture"); |
| + return; |
| + } |
| + |
| + media::Java_ScreenCapture_startCapture(env, obj); |
| +} |
| + |
| +void ScreenCaptureMachineAndroid::Start( |
| + const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, |
| + const media::VideoCaptureParams& params, |
| + const base::Callback<void(bool)> callback) { |
| + DCHECK(oracle_proxy.get()); |
| + oracle_proxy_ = oracle_proxy; |
| + |
| + j_capture_.Reset( |
| + media::ScreenCaptureFactoryAndroid::createScreenCaptureMachineAndroid( |
| + reinterpret_cast<intptr_t>(this))); |
| + |
| + if (j_capture_.obj() == NULL) { |
| + LOG(ERROR) << "Failed to createScreenCaptureAndroid," |
| + " Maybe android version is too low"; |
| + callback.Run(false); |
| + return; |
| + } |
| + |
| + capture_format_ = params.requested_format; |
| + // This capturer always outputs ARGB, non-interlaced. |
| + capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB; |
|
miu
2016/04/27 05:24:53
I believe the |params| would specify I420 or YV12,
braveyao
2016/05/04 18:49:41
Yes, |params| asks for I420. Same as above comment
miu
2016/05/10 00:29:00
This is orthogonal to the other comment. The |capt
|
| + |
| + CHECK(capture_format_.frame_size.GetArea() > 0); |
| + CHECK(!(capture_format_.frame_size.width() % 2)); |
| + CHECK(!(capture_format_.frame_size.height() % 2)); |
| + |
| + JNIEnv* env = AttachCurrentThread(); |
| + jboolean ret = media::Java_ScreenCapture_startPrompt( |
| + env, j_capture_.obj(), capture_format_.frame_size.width(), |
| + capture_format_.frame_size.height()); |
| + if (!ret) { |
| + callback.Run(false); |
| + return; |
| + } |
| + |
| + callback.Run(true); |
| +} |
| + |
| +void ScreenCaptureMachineAndroid::Stop(const base::Closure& callback) { |
| + JNIEnv* env = AttachCurrentThread(); |
| + Java_ScreenCapture_stopCapture(env, j_capture_.obj()); |
| + |
| + callback.Run(); |
| +} |
| + |
| +void ScreenCaptureMachineAndroid::MaybeCaptureForRefresh() {} |
|
miu
2016/04/27 05:24:53
Depending on the behavior of the platform, you may
braveyao
2016/05/04 18:49:41
Thanks for explaining this new method.
Android als
miu
2016/05/10 00:29:00
There are concerns on the consuming-end of these v
braveyao
2016/05/18 00:41:46
Done.
|
| + |
| +} // namespace media |