| Index: media/screen_capture/android/screen_capturer2_android.cc
|
| diff --git a/media/screen_capture/android/screen_capturer2_android.cc b/media/screen_capture/android/screen_capturer2_android.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ca4c381be68d1db7928ac05ed0cc74c7a8c177b1
|
| --- /dev/null
|
| +++ b/media/screen_capture/android/screen_capturer2_android.cc
|
| @@ -0,0 +1,162 @@
|
| +// Copyright (c) 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/screen_capture/android/screen_capturer2_android.h"
|
| +
|
| +#include "base/android/jni_android.h"
|
| +#include "base/android/scoped_java_ref.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "jni/ScreenCapture_jni.h"
|
| +#include "media/base/video_capture_types.h"
|
| +#include "media/screen_capture/android/screen_capture_factory_android.h"
|
| +
|
| +using base::android::AttachCurrentThread;
|
| +
|
| +namespace media {
|
| +
|
| +// static
|
| +bool ScreenCapturer2Android::RegisterScreenCapturer2(JNIEnv* env) {
|
| + return media::RegisterNativesImpl(env);
|
| +}
|
| +
|
| +ScreenCapturer2Android::ScreenCapturer2Android()
|
| + : state_(kIdle), got_first_frame_(false) {}
|
| +
|
| +ScreenCapturer2Android::~ScreenCapturer2Android() {
|
| + StopAndDeAllocate();
|
| +}
|
| +
|
| +void ScreenCapturer2Android::OnFrameAvailable(JNIEnv* env,
|
| + jobject obj,
|
| + jbyteArray data,
|
| + jint length) {
|
| + base::AutoLock lock(lock_);
|
| + if (state_ != kCapturing || !client_.get())
|
| + return;
|
| +
|
| + jbyte* buffer = env->GetByteArrayElements(data, NULL);
|
| + if (!buffer) {
|
| + LOG(ERROR) << "ScreenCapturer2Android::OnFrameAvailable: "
|
| + "failed to GetByteArrayElements";
|
| + return;
|
| + }
|
| +
|
| + base::TimeTicks current_time = base::TimeTicks::Now();
|
| + if (!got_first_frame_) {
|
| + // Set aside one frame allowance for fluctuation.
|
| + expected_next_frame_time_ = current_time - frame_interval_;
|
| + got_first_frame_ = true;
|
| + }
|
| +
|
| + // Deliver the frame when it doesn't arrive too early.
|
| + if (expected_next_frame_time_ <= current_time) {
|
| + expected_next_frame_time_ += frame_interval_;
|
| +
|
| + client_->OnIncomingCapturedData(reinterpret_cast<uint8*>(buffer),
|
| + length,
|
| + capture_format_,
|
| + 0,
|
| + base::TimeTicks::Now());
|
| + }
|
| +
|
| + env->ReleaseByteArrayElements(data, buffer, JNI_ABORT);
|
| +}
|
| +
|
| +void ScreenCapturer2Android::OnActivityResult(JNIEnv* env,
|
| + jobject obj,
|
| + jint result) {
|
| + if (result == 0) {
|
| + state_ = kIdle;
|
| + return;
|
| + }
|
| +
|
| + media::Java_ScreenCapture_startCapture(env, obj);
|
| +
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + state_ = kCapturing;
|
| + }
|
| +}
|
| +
|
| +bool ScreenCapturer2Android::Init() {
|
| + j_capture_.Reset(media::ScreenCaptureFactoryAndroid
|
| + ::createScreenCapture2Android(reinterpret_cast<intptr_t>(this)));
|
| +
|
| + if (j_capture_.obj() == NULL) {
|
| + LOG(ERROR) << "ScreenCapturer2Android::Init"
|
| + " failed to createScreenCaptureAndroid,"
|
| + " Maybe android version is too low";
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void ScreenCapturer2Android::AllocateAndStart(
|
| + const VideoCaptureParams& params,
|
| + scoped_ptr<Client> client) {
|
| + DVLOG(1) << "ScreenCapturer2Android::AllocateAndStart";
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + if (state_ != kIdle)
|
| + return;
|
| + client_ = client.Pass();
|
| + got_first_frame_ = false;
|
| + }
|
| +/*
|
| + // Store current width and height.
|
| + capture_format_.frame_size.SetSize(
|
| + params.requested_format.frame_size.width(),
|
| + params.requested_format.frame_size.height());
|
| + capture_format_.frame_rate = params.requested_format.frame_rate;
|
| +*/
|
| + capture_format_ = params.requested_format;
|
| + // This capturer always outputs ARGB, non-interlaced.
|
| + capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB;
|
| +
|
| + CHECK(capture_format_.frame_size.GetArea() > 0);
|
| + CHECK(!(capture_format_.frame_size.width() % 2));
|
| + CHECK(!(capture_format_.frame_size.height() % 2));
|
| +
|
| + if (capture_format_.frame_rate > 0) {
|
| + frame_interval_ = base::TimeDelta::FromMicroseconds(
|
| + (base::Time::kMicrosecondsPerSecond + capture_format_.frame_rate - 1) /
|
| + capture_format_.frame_rate);
|
| + }
|
| +
|
| + DVLOG(1) << "ScreenCapturer2Android::AllocateAndStart: queried frame_size="
|
| + << capture_format_.frame_size.ToString()
|
| + << ", frame_rate=" << capture_format_.frame_rate;
|
| +
|
| + JNIEnv* env = AttachCurrentThread();
|
| + jboolean ret = media::Java_ScreenCapture_start(env, j_capture_.obj(),
|
| + capture_format_.frame_size.width(), capture_format_.frame_size.height());
|
| + if (!ret) {
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + state_ = kError;
|
| + }
|
| + client_->OnError("Failed to start");
|
| + return;
|
| + }
|
| +}
|
| +
|
| +void ScreenCapturer2Android::StopAndDeAllocate() {
|
| + DVLOG(1) << "ScreenCapturer2Android::StopAndDeAllocate";
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + if (state_ != kCapturing && state_ != kError)
|
| + return;
|
| + }
|
| +
|
| + JNIEnv* env = AttachCurrentThread();
|
| + Java_ScreenCapture_stopCapture(env, j_capture_.obj());
|
| +
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + state_ = kIdle;
|
| + client_.reset();
|
| + }
|
| +}
|
| +
|
| +} // namespace media
|
|
|