OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 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_capturer2_android.h" |
| 6 |
| 7 #include "base/android/jni_android.h" |
| 8 #include "base/android/scoped_java_ref.h" |
| 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "jni/ScreenCapture_jni.h" |
| 11 #include "media/base/video_capture_types.h" |
| 12 #include "media/screen_capture/android/screen_capture_factory_android.h" |
| 13 |
| 14 using base::android::AttachCurrentThread; |
| 15 |
| 16 namespace media { |
| 17 |
| 18 // static |
| 19 bool ScreenCapturer2Android::RegisterScreenCapturer2(JNIEnv* env) { |
| 20 return media::RegisterNativesImpl(env); |
| 21 } |
| 22 |
| 23 ScreenCapturer2Android::ScreenCapturer2Android() |
| 24 : state_(kIdle), got_first_frame_(false) {} |
| 25 |
| 26 ScreenCapturer2Android::~ScreenCapturer2Android() { |
| 27 StopAndDeAllocate(); |
| 28 } |
| 29 |
| 30 void ScreenCapturer2Android::OnFrameAvailable(JNIEnv* env, |
| 31 jobject obj, |
| 32 jbyteArray data, |
| 33 jint length) { |
| 34 base::AutoLock lock(lock_); |
| 35 if (state_ != kCapturing || !client_.get()) |
| 36 return; |
| 37 |
| 38 jbyte* buffer = env->GetByteArrayElements(data, NULL); |
| 39 if (!buffer) { |
| 40 LOG(ERROR) << "ScreenCapturer2Android::OnFrameAvailable: " |
| 41 "failed to GetByteArrayElements"; |
| 42 return; |
| 43 } |
| 44 |
| 45 base::TimeTicks current_time = base::TimeTicks::Now(); |
| 46 if (!got_first_frame_) { |
| 47 // Set aside one frame allowance for fluctuation. |
| 48 expected_next_frame_time_ = current_time - frame_interval_; |
| 49 got_first_frame_ = true; |
| 50 } |
| 51 |
| 52 // Deliver the frame when it doesn't arrive too early. |
| 53 if (expected_next_frame_time_ <= current_time) { |
| 54 expected_next_frame_time_ += frame_interval_; |
| 55 |
| 56 client_->OnIncomingCapturedData(reinterpret_cast<uint8*>(buffer), |
| 57 length, |
| 58 capture_format_, |
| 59 0, |
| 60 base::TimeTicks::Now()); |
| 61 } |
| 62 |
| 63 env->ReleaseByteArrayElements(data, buffer, JNI_ABORT); |
| 64 } |
| 65 |
| 66 void ScreenCapturer2Android::OnActivityResult(JNIEnv* env, |
| 67 jobject obj, |
| 68 jint result) { |
| 69 if (result == 0) { |
| 70 state_ = kIdle; |
| 71 return; |
| 72 } |
| 73 |
| 74 media::Java_ScreenCapture_startCapture(env, obj); |
| 75 |
| 76 { |
| 77 base::AutoLock lock(lock_); |
| 78 state_ = kCapturing; |
| 79 } |
| 80 } |
| 81 |
| 82 bool ScreenCapturer2Android::Init() { |
| 83 j_capture_.Reset(media::ScreenCaptureFactoryAndroid |
| 84 ::createScreenCapture2Android(reinterpret_cast<intptr_t>(this))); |
| 85 |
| 86 if (j_capture_.obj() == NULL) { |
| 87 LOG(ERROR) << "ScreenCapturer2Android::Init" |
| 88 " failed to createScreenCaptureAndroid," |
| 89 " Maybe android version is too low"; |
| 90 return false; |
| 91 } |
| 92 return true; |
| 93 } |
| 94 |
| 95 void ScreenCapturer2Android::AllocateAndStart( |
| 96 const VideoCaptureParams& params, |
| 97 scoped_ptr<Client> client) { |
| 98 DVLOG(1) << "ScreenCapturer2Android::AllocateAndStart"; |
| 99 { |
| 100 base::AutoLock lock(lock_); |
| 101 if (state_ != kIdle) |
| 102 return; |
| 103 client_ = client.Pass(); |
| 104 got_first_frame_ = false; |
| 105 } |
| 106 /* |
| 107 // Store current width and height. |
| 108 capture_format_.frame_size.SetSize( |
| 109 params.requested_format.frame_size.width(), |
| 110 params.requested_format.frame_size.height()); |
| 111 capture_format_.frame_rate = params.requested_format.frame_rate; |
| 112 */ |
| 113 capture_format_ = params.requested_format; |
| 114 // This capturer always outputs ARGB, non-interlaced. |
| 115 capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB; |
| 116 |
| 117 CHECK(capture_format_.frame_size.GetArea() > 0); |
| 118 CHECK(!(capture_format_.frame_size.width() % 2)); |
| 119 CHECK(!(capture_format_.frame_size.height() % 2)); |
| 120 |
| 121 if (capture_format_.frame_rate > 0) { |
| 122 frame_interval_ = base::TimeDelta::FromMicroseconds( |
| 123 (base::Time::kMicrosecondsPerSecond + capture_format_.frame_rate - 1) / |
| 124 capture_format_.frame_rate); |
| 125 } |
| 126 |
| 127 DVLOG(1) << "ScreenCapturer2Android::AllocateAndStart: queried frame_size=" |
| 128 << capture_format_.frame_size.ToString() |
| 129 << ", frame_rate=" << capture_format_.frame_rate; |
| 130 |
| 131 JNIEnv* env = AttachCurrentThread(); |
| 132 jboolean ret = media::Java_ScreenCapture_start(env, j_capture_.obj(), |
| 133 capture_format_.frame_size.width(), capture_format_.frame_size.height()); |
| 134 if (!ret) { |
| 135 { |
| 136 base::AutoLock lock(lock_); |
| 137 state_ = kError; |
| 138 } |
| 139 client_->OnError("Failed to start"); |
| 140 return; |
| 141 } |
| 142 } |
| 143 |
| 144 void ScreenCapturer2Android::StopAndDeAllocate() { |
| 145 DVLOG(1) << "ScreenCapturer2Android::StopAndDeAllocate"; |
| 146 { |
| 147 base::AutoLock lock(lock_); |
| 148 if (state_ != kCapturing && state_ != kError) |
| 149 return; |
| 150 } |
| 151 |
| 152 JNIEnv* env = AttachCurrentThread(); |
| 153 Java_ScreenCapture_stopCapture(env, j_capture_.obj()); |
| 154 |
| 155 { |
| 156 base::AutoLock lock(lock_); |
| 157 state_ = kIdle; |
| 158 client_.reset(); |
| 159 } |
| 160 } |
| 161 |
| 162 } // namespace media |
OLD | NEW |