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

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: rename variable and format 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 30 matching lines...) Expand all
53 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; 51 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
54 52
55 if (!oracle_proxy_->ObserveEventAndDecideCapture( 53 if (!oracle_proxy_->ObserveEventAndDecideCapture(
56 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) { 54 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) {
57 return; 55 return;
58 } 56 }
59 57
60 DCHECK(frame->format() == PIXEL_FORMAT_I420 || 58 DCHECK(frame->format() == PIXEL_FORMAT_I420 ||
61 frame->format() == PIXEL_FORMAT_YV12); 59 frame->format() == PIXEL_FORMAT_YV12);
62 60
63 scoped_refptr<VideoFrame> unscaled_frame = frame; 61 scoped_refptr<VideoFrame> temp_frame = frame;
64 if (frame->visible_rect().width() != width || 62 if (frame->visible_rect().width() != width ||
65 frame->visible_rect().height() != height) { 63 frame->visible_rect().height() != height) {
66 unscaled_frame = VideoFrame::CreateFrame( 64 temp_frame = VideoFrame::CreateFrame(
67 PIXEL_FORMAT_I420, gfx::Size(width, height), gfx::Rect(width, height), 65 PIXEL_FORMAT_I420, gfx::Size(width, height), gfx::Rect(width, height),
68 gfx::Size(width, height), base::TimeDelta()); 66 gfx::Size(width, height), base::TimeDelta());
69 } 67 }
70 68
71 uint8_t* const src = 69 uint8_t* const src =
72 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(buf)); 70 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(buf));
73 CHECK(src); 71 CHECK(src);
74 72
75 const int offset = top * row_stride + left * 4; 73 const int offset = top * row_stride + left * 4;
76 // ABGR little endian (rgba in memory) to I420. 74 // ABGR little endian (rgba in memory) to I420.
77 libyuv::ABGRToI420(src + offset, row_stride, 75 libyuv::ABGRToI420(
78 unscaled_frame->visible_data(VideoFrame::kYPlane), 76 src + offset, row_stride, temp_frame->visible_data(VideoFrame::kYPlane),
mcasas 2016/07/20 18:26:50 A similar thing came up recently. I'm still not su
79 unscaled_frame->stride(VideoFrame::kYPlane), 77 temp_frame->stride(VideoFrame::kYPlane),
80 unscaled_frame->visible_data(VideoFrame::kUPlane), 78 temp_frame->visible_data(VideoFrame::kUPlane),
81 unscaled_frame->stride(VideoFrame::kUPlane), 79 temp_frame->stride(VideoFrame::kUPlane),
82 unscaled_frame->visible_data(VideoFrame::kVPlane), 80 temp_frame->visible_data(VideoFrame::kVPlane),
83 unscaled_frame->stride(VideoFrame::kVPlane), 81 temp_frame->stride(VideoFrame::kVPlane),
84 unscaled_frame->visible_rect().width(), 82 temp_frame->visible_rect().width(), temp_frame->visible_rect().height());
85 unscaled_frame->visible_rect().height());
86 83
87 if (unscaled_frame != frame) { 84 if (temp_frame != frame) {
88 libyuv::I420Scale(unscaled_frame->visible_data(VideoFrame::kYPlane), 85 libyuv::I420Scale(
89 unscaled_frame->stride(VideoFrame::kYPlane), 86 temp_frame->visible_data(VideoFrame::kYPlane),
90 unscaled_frame->visible_data(VideoFrame::kUPlane), 87 temp_frame->stride(VideoFrame::kYPlane),
91 unscaled_frame->stride(VideoFrame::kUPlane), 88 temp_frame->visible_data(VideoFrame::kUPlane),
92 unscaled_frame->visible_data(VideoFrame::kVPlane), 89 temp_frame->stride(VideoFrame::kUPlane),
93 unscaled_frame->stride(VideoFrame::kVPlane), 90 temp_frame->visible_data(VideoFrame::kVPlane),
94 unscaled_frame->visible_rect().width(), 91 temp_frame->stride(VideoFrame::kVPlane),
95 unscaled_frame->visible_rect().height(), 92 temp_frame->visible_rect().width(), temp_frame->visible_rect().height(),
96 frame->visible_data(VideoFrame::kYPlane), 93 frame->visible_data(VideoFrame::kYPlane),
97 frame->stride(VideoFrame::kYPlane), 94 frame->stride(VideoFrame::kYPlane),
98 frame->visible_data(VideoFrame::kUPlane), 95 frame->visible_data(VideoFrame::kUPlane),
99 frame->stride(VideoFrame::kUPlane), 96 frame->stride(VideoFrame::kUPlane),
100 frame->visible_data(VideoFrame::kVPlane), 97 frame->visible_data(VideoFrame::kVPlane),
101 frame->stride(VideoFrame::kVPlane), 98 frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(),
102 frame->visible_rect().width(), 99 frame->visible_rect().height(), libyuv::kFilterBilinear);
103 frame->visible_rect().height(), libyuv::kFilterBilinear);
104 } 100 }
105 101
106 capture_frame_cb.Run(frame, start_time, true); 102 capture_frame_cb.Run(frame, start_time, true);
107 103
108 lastFrame_ = frame; 104 lastFrame_ = frame;
109 } 105 }
110 106
111 void ScreenCaptureMachineAndroid::OnI420FrameAvailable(JNIEnv* env, 107 void ScreenCaptureMachineAndroid::OnI420FrameAvailable(JNIEnv* env,
112 jobject obj, 108 jobject obj,
113 jobject y_buffer, 109 jobject y_buffer,
(...skipping 16 matching lines...) Expand all
130 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb; 126 ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
131 127
132 if (!oracle_proxy_->ObserveEventAndDecideCapture( 128 if (!oracle_proxy_->ObserveEventAndDecideCapture(
133 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) { 129 event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) {
134 return; 130 return;
135 } 131 }
136 132
137 DCHECK(frame->format() == PIXEL_FORMAT_I420 || 133 DCHECK(frame->format() == PIXEL_FORMAT_I420 ||
138 frame->format() == PIXEL_FORMAT_YV12); 134 frame->format() == PIXEL_FORMAT_YV12);
139 135
136 scoped_refptr<VideoFrame> temp_frame = frame;
137 if (frame->visible_rect().width() != width ||
138 frame->visible_rect().height() != height) {
139 temp_frame = VideoFrame::CreateFrame(
140 PIXEL_FORMAT_I420, gfx::Size(width, height), gfx::Rect(width, height),
141 gfx::Size(width, height), base::TimeDelta());
142 }
143
140 uint8_t* const y_src = 144 uint8_t* const y_src =
141 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer)); 145 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer));
142 CHECK(y_src); 146 CHECK(y_src);
143 uint8_t* u_src = 147 uint8_t* u_src =
144 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer)); 148 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer));
145 CHECK(u_src); 149 CHECK(u_src);
146 uint8_t* v_src = 150 uint8_t* v_src =
147 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer)); 151 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer));
148 CHECK(v_src); 152 CHECK(v_src);
149 153
150 // De-interleave the U and V planes into temporary buffers, if needed. 154 const int y_offset = top * y_stride + left;
151 int uv_stride = uv_row_stride; 155 const int uv_offset = (top / 2) * uv_row_stride + left / 2;
152 std::unique_ptr<uint8_t[]> u_tmp, v_tmp; 156 libyuv::Android420ToI420(
153 if (uv_pixel_stride != 1) { 157 y_src + y_offset, y_stride, u_src + uv_offset, uv_row_stride,
154 // U and V planes are actually interleaved, unpack them here. 158 v_src + uv_offset, uv_row_stride, uv_pixel_stride,
155 // TODO(braveyao): According to 159 temp_frame->visible_data(VideoFrame::kYPlane),
156 // https://developer.android.com/reference/android/graphics/ImageFormat.html #YUV_420_888, 160 temp_frame->stride(VideoFrame::kYPlane),
157 // how U and V planes are interlaced is not guaranteed, so there is no an 161 temp_frame->visible_data(VideoFrame::kUPlane),
158 // existing libyuv function suitable for such a job. Filed a request at 162 temp_frame->stride(VideoFrame::kUPlane),
159 // https://bugs.chromium.org/p/libyuv/issues/detail?id=604. Switch to new 163 temp_frame->visible_data(VideoFrame::kVPlane),
160 // function when it's available. 164 temp_frame->stride(VideoFrame::kVPlane),
161 const int uv_plane_len = (int)env->GetDirectBufferCapacity(u_buffer); 165 temp_frame->visible_rect().width(), temp_frame->visible_rect().height());
162 u_tmp.reset(new uint8_t[(uv_plane_len + 1) / uv_pixel_stride]); 166
163 v_tmp.reset(new uint8_t[(uv_plane_len + 1) / uv_pixel_stride]); 167 if (temp_frame != frame) {
164 for (int index = 0; index * uv_pixel_stride <= uv_plane_len; index++) { 168 libyuv::I420Scale(
165 u_tmp[index] = u_src[index * uv_pixel_stride]; 169 temp_frame->visible_data(VideoFrame::kYPlane),
166 v_tmp[index] = v_src[index * uv_pixel_stride]; 170 temp_frame->stride(VideoFrame::kYPlane),
167 } 171 temp_frame->visible_data(VideoFrame::kUPlane),
168 u_src = u_tmp.get(); 172 temp_frame->stride(VideoFrame::kUPlane),
169 v_src = v_tmp.get(); 173 temp_frame->visible_data(VideoFrame::kVPlane),
170 uv_stride /= uv_pixel_stride; 174 temp_frame->stride(VideoFrame::kVPlane),
175 temp_frame->visible_rect().width(), temp_frame->visible_rect().height(),
176 frame->visible_data(VideoFrame::kYPlane),
177 frame->stride(VideoFrame::kYPlane),
178 frame->visible_data(VideoFrame::kUPlane),
179 frame->stride(VideoFrame::kUPlane),
180 frame->visible_data(VideoFrame::kVPlane),
181 frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(),
182 frame->visible_rect().height(), libyuv::kFilterBilinear);
171 } 183 }
172 184
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); 185 capture_frame_cb.Run(frame, start_time, true);
189 186
190 lastFrame_ = frame; 187 lastFrame_ = frame;
191 } 188 }
192 189
193 void ScreenCaptureMachineAndroid::OnActivityResult(JNIEnv* env, 190 void ScreenCaptureMachineAndroid::OnActivityResult(JNIEnv* env,
194 jobject obj, 191 jobject obj,
195 jboolean result) { 192 jboolean result) {
196 if (!result) { 193 if (!result) {
197 oracle_proxy_->ReportError(FROM_HERE, "The user denied screen capture"); 194 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), 266 frame->visible_data(VideoFrame::kUPlane),
270 frame->stride(VideoFrame::kUPlane), 267 frame->stride(VideoFrame::kUPlane),
271 frame->visible_data(VideoFrame::kVPlane), 268 frame->visible_data(VideoFrame::kVPlane),
272 frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(), 269 frame->stride(VideoFrame::kVPlane), frame->visible_rect().width(),
273 frame->visible_rect().height(), libyuv::kFilterBilinear); 270 frame->visible_rect().height(), libyuv::kFilterBilinear);
274 271
275 capture_frame_cb.Run(frame, start_time, true); 272 capture_frame_cb.Run(frame, start_time, true);
276 } 273 }
277 274
278 } // namespace media 275 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698