Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: media/capture/content/android/screen_capture_machine_android.cc

Issue 2156003006: Android video capture: use new libyuv::Android420ToI420 API for format converting. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/capture/content/android/screen_capture_machine_android.h" 5 #include "media/capture/content/android/screen_capture_machine_android.h"
6 6
7 #include "base/android/context_utils.h" 7 #include "base/android/context_utils.h"
8 #include "base/android/jni_android.h" 8 #include "base/android/jni_android.h"
9 #include "base/android/scoped_java_ref.h" 9 #include "base/android/scoped_java_ref.h"
10 #include "jni/ScreenCapture_jni.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/capture/content/video_capture_oracle.h" 11 #include "media/capture/content/video_capture_oracle.h"
14 #include "third_party/libyuv/include/libyuv.h" 12 #include "third_party/libyuv/include/libyuv.h"
15 13
16 using base::android::AttachCurrentThread; 14 using base::android::AttachCurrentThread;
17 15
18 namespace media { 16 namespace media {
19 17
20 // static 18 // static
21 bool ScreenCaptureMachineAndroid::RegisterScreenCaptureMachine(JNIEnv* env) { 19 bool ScreenCaptureMachineAndroid::RegisterScreenCaptureMachine(JNIEnv* env) {
22 return RegisterNativesImpl(env); 20 return RegisterNativesImpl(env);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; 128 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
131 129
132 if (!oracle_proxy_->ObserveEventAndDecideCapture( 130 if (!oracle_proxy_->ObserveEventAndDecideCapture(
133 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) { 131 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) {
134 return; 132 return;
135 } 133 }
136 134
137 DCHECK(frame->format() == PIXEL_FORMAT_I420 || 135 DCHECK(frame->format() == PIXEL_FORMAT_I420 ||
138 frame->format() == PIXEL_FORMAT_YV12); 136 frame->format() == PIXEL_FORMAT_YV12);
139 137
138 scoped_refptr<VideoFrame> unscaled_frame = frame;
mcasas 2016/07/19 01:22:58 I found |unscaled_frame| a bit non intuitive, beca
braveyao 2016/07/19 19:06:01 |temp_| is more neutral, but I prefer |unscaled_|
braveyao 2016/07/20 18:05:20 Done.
139 if (frame->visible_rect().width() != width ||
140 frame->visible_rect().height() != height) {
141 unscaled_frame = VideoFrame::CreateFrame(
142 PIXEL_FORMAT_I420, gfx::Size(width, height), gfx::Rect(width, height),
143 gfx::Size(width, height), base::TimeDelta());
144 }
145
140 uint8_t* const y_src = 146 uint8_t* const y_src =
141 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer)); 147 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer));
142 CHECK(y_src); 148 CHECK(y_src);
143 uint8_t* u_src = 149 uint8_t* u_src =
144 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer)); 150 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer));
145 CHECK(u_src); 151 CHECK(u_src);
146 uint8_t* v_src = 152 uint8_t* v_src =
147 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer)); 153 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer));
148 CHECK(v_src); 154 CHECK(v_src);
149 155
150 // De-interleave the U and V planes into temporary buffers, if needed. 156 const int y_offset = top * y_stride + left;
151 int uv_stride = uv_row_stride; 157 const int uv_offset = (top / 2) * uv_row_stride + left / 2;
152 std::unique_ptr<uint8_t[]> u_tmp, v_tmp; 158 libyuv::Android420ToI420(y_src + y_offset, y_stride, u_src + uv_offset,
153 if (uv_pixel_stride != 1) { 159 uv_row_stride, v_src + uv_offset, uv_row_stride,
154 // U and V planes are actually interleaved, unpack them here. 160 uv_pixel_stride,
155 // TODO(braveyao): According to 161 unscaled_frame->visible_data(VideoFrame::kYPlane),
156 // https://developer.android.com/reference/android/graphics/ImageFormat.html #YUV_420_888, 162 unscaled_frame->stride(VideoFrame::kYPlane),
157 // how U and V planes are interlaced is not guaranteed, so there is no an 163 unscaled_frame->visible_data(VideoFrame::kUPlane),
158 // existing libyuv function suitable for such a job. Filed a request at 164 unscaled_frame->stride(VideoFrame::kUPlane),
159 // https://bugs.chromium.org/p/libyuv/issues/detail?id=604. Switch to new 165 unscaled_frame->visible_data(VideoFrame::kVPlane),
160 // function when it's available. 166 unscaled_frame->stride(VideoFrame::kVPlane),
161 const int uv_plane_len = (int)env->GetDirectBufferCapacity(u_buffer); 167 unscaled_frame->visible_rect().width(),
162 u_tmp.reset(new uint8_t[(uv_plane_len + 1) / uv_pixel_stride]); 168 unscaled_frame->visible_rect().height());
163 v_tmp.reset(new uint8_t[(uv_plane_len + 1) / uv_pixel_stride]); 169
164 for (int index = 0; index * uv_pixel_stride <= uv_plane_len; index++) { 170 if (unscaled_frame != frame) {
165 u_tmp[index] = u_src[index * uv_pixel_stride]; 171 libyuv::I420Scale(unscaled_frame->visible_data(VideoFrame::kYPlane),
166 v_tmp[index] = v_src[index * uv_pixel_stride]; 172 unscaled_frame->stride(VideoFrame::kYPlane),
167 } 173 unscaled_frame->visible_data(VideoFrame::kUPlane),
168 u_src = u_tmp.get(); 174 unscaled_frame->stride(VideoFrame::kUPlane),
169 v_src = v_tmp.get(); 175 unscaled_frame->visible_data(VideoFrame::kVPlane),
170 uv_stride /= uv_pixel_stride; 176 unscaled_frame->stride(VideoFrame::kVPlane),
177 unscaled_frame->visible_rect().width(),
178 unscaled_frame->visible_rect().height(),
179 frame->visible_data(VideoFrame::kYPlane),
180 frame->stride(VideoFrame::kYPlane),
181 frame->visible_data(VideoFrame::kUPlane),
182 frame->stride(VideoFrame::kUPlane),
183 frame->visible_data(VideoFrame::kVPlane),
184 frame->stride(VideoFrame::kVPlane),
185 frame->visible_rect().width(),
186 frame->visible_rect().height(), libyuv::kFilterBilinear);
171 } 187 }
172 188
173 const int y_offset = top * y_stride + left;
174 const int uv_offset = (top / 2) * uv_stride + left / 2;
175 // Note: If source width/height are same as the frame's width/height, the
176 // following will, internally, just perform a copy without scaling.
177 libyuv::I420Scale(y_src + y_offset, y_stride, u_src + uv_offset, uv_stride,
178 v_src + uv_offset, uv_stride, width, height,
179 frame->visible_data(VideoFrame::kYPlane),
180 frame->stride(VideoFrame::kYPlane),
181 frame->visible_data(VideoFrame::kUPlane),
182 frame->stride(VideoFrame::kUPlane),
183 frame->visible_data(VideoFrame::kVPlane),
184 frame->stride(VideoFrame::kVPlane),
185 frame->visible_rect().width(),
186 frame->visible_rect().height(), libyuv::kFilterBilinear);
187
188 capture_frame_cb.Run(frame, start_time, true); 189 capture_frame_cb.Run(frame, start_time, true);
189 190
190 lastFrame_ = frame; 191 lastFrame_ = frame;
191 } 192 }
192 193
193 void ScreenCaptureMachineAndroid::OnActivityResult(JNIEnv* env, 194 void ScreenCaptureMachineAndroid::OnActivityResult(JNIEnv* env,
194 jobject obj, 195 jobject obj,
195 jboolean result) { 196 jboolean result) {
196 if (!result) { 197 if (!result) {
197 oracle_proxy_->ReportError(FROM_HERE, "The user denied screen capture"); 198 oracle_proxy_->ReportError(FROM_HERE, "The user denied screen capture");
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 frame->visible_data(VideoFrame::kUPlane), 270 frame->visible_data(VideoFrame::kUPlane),
270 frame->stride(VideoFrame::kUPlane), 271 frame->stride(VideoFrame::kUPlane),
271 frame->visible_data(VideoFrame::kVPlane), 272 frame->visible_data(VideoFrame::kVPlane),
272 frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(), 273 frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(),
273 frame->visible_rect().height(), libyuv::kFilterBilinear); 274 frame->visible_rect().height(), libyuv::kFilterBilinear);
274 275
275 capture_frame_cb.Run(frame, start_time, true); 276 capture_frame_cb.Run(frame, start_time, true);
276 } 277 }
277 278
278 } // namespace media 279 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698