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

Side by Side Diff: webrtc/api/androidvideotracksource.cc

Issue 2127893002: AndroidVideoTrackSource implementation (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@magjed-init
Patch Set: Change videoSourceStopped to videoCapturerStopped. 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
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/api/androidvideotracksource.h"
12
13 namespace webrtc {
14
15 AndroidVideoTrackSource::AndroidVideoTrackSource(rtc::Thread* signaling_thread,
16 JNIEnv* jni,
17 jobject j_egl_context)
18 : signaling_thread_(signaling_thread),
19 surface_texture_helper_(webrtc_jni::SurfaceTextureHelper::create(
20 jni,
21 "Camera SurfaceTextureHelper",
22 j_egl_context)) {
23 LOG(LS_INFO) << "AndroidVideoTrackSource ctor";
24 worker_thread_checker_.DetachFromThread();
25 camera_thread_checker_.DetachFromThread();
26 }
27
28 AndroidVideoTrackSource::~AndroidVideoTrackSource() {
29 LOG(LS_INFO) << "AndroidVideoTrackSource dtor";
magjed_webrtc 2016/07/19 12:57:47 I don't think this log is necessary, so you can re
sakal 2016/07/19 13:46:23 Done.
30 }
31
32 bool AndroidVideoTrackSource::GetStats(AndroidVideoTrackSource::Stats* stats) {
33 rtc::CritScope lock(&stats_crit_);
34
35 if (!stats_) {
36 return false;
37 }
38
39 *stats = *stats_;
40 return true;
41 }
42
43 void AndroidVideoTrackSource::SetState(SourceState state) {
44 if (rtc::Thread::Current() != signaling_thread_) {
45 invoker_.AsyncInvoke<void>(
46 RTC_FROM_HERE, signaling_thread_,
47 rtc::Bind(&AndroidVideoTrackSource::SetState, this, state));
48 return;
49 }
50
51 if (state_ != state) {
52 state_ = state;
53 FireOnChanged();
54 }
55 }
56
57 void AndroidVideoTrackSource::AddOrUpdateSink(
58 rtc::VideoSinkInterface<cricket::VideoFrame>* sink,
59 const rtc::VideoSinkWants& wants) {
60 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
61
62 broadcaster_.AddOrUpdateSink(sink, wants);
63 OnSinkWantsChanged(broadcaster_.wants());
64 }
65
66 void AndroidVideoTrackSource::RemoveSink(
67 rtc::VideoSinkInterface<cricket::VideoFrame>* sink) {
68 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
69
70 broadcaster_.RemoveSink(sink);
71 OnSinkWantsChanged(broadcaster_.wants());
72 }
73
74 void AndroidVideoTrackSource::OnSinkWantsChanged(
75 const rtc::VideoSinkWants& wants) {
magjed_webrtc 2016/07/19 12:57:47 Only called on worker thread?
sakal 2016/07/19 13:46:23 Added a lock.
76 apply_rotation_ = wants.rotation_applied;
77
78 video_adapter_.OnResolutionRequest(wants.max_pixel_count,
79 wants.max_pixel_count_step_up);
80 }
81
82 void AndroidVideoTrackSource::OnFrame(const cricket::VideoFrame& frame,
83 int width,
84 int height) {
85 {
86 rtc::CritScope lock(&stats_crit_);
87 stats_ = rtc::Optional<AndroidVideoTrackSource::Stats>({width, height});
88 }
89
90 broadcaster_.OnFrame(frame);
91 }
92
93 void AndroidVideoTrackSource::OnByteBufferFrameCaptured(const void* frame_data,
94 int length,
95 int width,
96 int height,
97 int rotation,
98 int64_t timestamp_ns) {
99 RTC_DCHECK(camera_thread_checker_.CalledOnValidThread());
100
101 RTC_DCHECK(rotation == 0 || rotation == 90 || rotation == 180 ||
102 rotation == 270);
103
104 int adapted_width;
105 int adapted_height;
106 int crop_width;
107 int crop_height;
108 int crop_x;
109 int crop_y;
110 int64_t translated_camera_time_us;
111
112 if (!AdaptFrame(width, height, timestamp_ns / rtc::kNumNanosecsPerMicrosec,
113 rtc::TimeMicros(), &adapted_width, &adapted_height,
114 &crop_width, &crop_height, &crop_x, &crop_y,
115 &translated_camera_time_us)) {
116 return;
117 }
118
119 int rotated_width = crop_width;
120 int rotated_height = crop_height;
121
122 if (apply_rotation_ && (rotation == 90 || rotation == 270)) {
123 std::swap(adapted_width, adapted_height);
124 std::swap(rotated_width, rotated_height);
125 }
126
127 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer =
128 pre_scale_pool_.CreateBuffer(rotated_width, rotated_height);
129
130 const uint8_t* y_plane = static_cast<const uint8_t*>(frame_data);
131 const uint8_t* uv_plane = y_plane + width * height;
132 int uv_width = (width + 1) / 2;
133
134 // TODO(sakal): Add some kind of check
135 // RTC_CHECK_EQ(uv_plane + uv_width * height - y_plane, length);
magjed_webrtc 2016/07/19 12:57:47 Add this check: RTC_CHECK_GE(length, width * heigh
sakal 2016/07/19 13:46:23 Done.
136
137 // Can only crop at even pixels.
138 crop_x &= ~1;
139 crop_y &= ~1;
140
141 libyuv::NV12ToI420Rotate(
142 y_plane + width * crop_y + crop_x, width,
143 uv_plane + uv_width * crop_y + crop_x, width, buffer->MutableDataY(),
144 buffer->StrideY(),
145 // Swap U and V, since we have NV21, not NV12.
146 buffer->MutableDataV(), buffer->StrideV(), buffer->MutableDataU(),
147 buffer->StrideU(), crop_width, crop_height,
148 static_cast<libyuv::RotationMode>(apply_rotation_ ? rotation : 0));
149
150 if (adapted_width != buffer->width() || adapted_height != buffer->height()) {
151 rtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer(
152 post_scale_pool_.CreateBuffer(adapted_width, adapted_height));
153 scaled_buffer->ScaleFrom(buffer);
154 buffer = scaled_buffer;
155 }
156
157 OnFrame(cricket::WebRtcVideoFrame(
158 buffer,
159 apply_rotation_ ? webrtc::kVideoRotation_0
160 : static_cast<webrtc::VideoRotation>(rotation),
161 translated_camera_time_us),
162 width, height);
163 }
164
165 void AndroidVideoTrackSource::OnTextureFrameCaptured(
166 int width,
167 int height,
168 int rotation,
169 int64_t timestamp_ns,
170 const webrtc_jni::NativeHandleImpl& handle) {
171 RTC_DCHECK(camera_thread_checker_.CalledOnValidThread());
172
173 RTC_DCHECK(rotation == 0 || rotation == 90 || rotation == 180 ||
174 rotation == 270);
175
176 int adapted_width;
177 int adapted_height;
178 int crop_width;
179 int crop_height;
180 int crop_x;
181 int crop_y;
182 int64_t translated_camera_time_us;
183
184 if (!AdaptFrame(width, height, timestamp_ns / rtc::kNumNanosecsPerMicrosec,
185 rtc::TimeMicros(), &adapted_width, &adapted_height,
186 &crop_width, &crop_height, &crop_x, &crop_y,
187 &translated_camera_time_us)) {
188 surface_texture_helper_->ReturnTextureFrame();
189 return;
190 }
191
192 webrtc_jni::Matrix matrix = handle.sampling_matrix;
193
194 matrix.Crop(crop_width / static_cast<float>(width),
195 crop_height / static_cast<float>(height),
196 crop_x / static_cast<float>(width),
197 crop_y / static_cast<float>(height));
198
199 if (apply_rotation_) {
200 if (rotation == webrtc::kVideoRotation_90 ||
201 rotation == webrtc::kVideoRotation_270) {
202 std::swap(adapted_width, adapted_height);
203 }
204 matrix.Rotate(static_cast<webrtc::VideoRotation>(rotation));
205 }
206
207 OnFrame(cricket::WebRtcVideoFrame(
208 surface_texture_helper_->CreateTextureFrame(
209 adapted_width, adapted_height,
210 webrtc_jni::NativeHandleImpl(handle.oes_texture_id, matrix)),
211 apply_rotation_ ? webrtc::kVideoRotation_0
212 : static_cast<webrtc::VideoRotation>(rotation),
213 translated_camera_time_us),
214 width, height);
215 }
216
217 void AndroidVideoTrackSource::OnOutputFormatRequest(int width,
218 int height,
219 int fps) {
220 RTC_DCHECK(camera_thread_checker_.CalledOnValidThread());
221
222 cricket::VideoFormat format(width, height,
223 cricket::VideoFormat::FpsToInterval(fps), 0);
224 video_adapter_.OnOutputFormatRequest(format);
225 }
226
227 bool AndroidVideoTrackSource::AdaptFrame(int width,
228 int height,
229 int64_t camera_time_us,
230 int64_t system_time_us,
magjed_webrtc 2016/07/19 12:57:47 Remove system_time_us as argument and add 'int64_t
sakal 2016/07/19 13:46:23 Done.
231 int* out_width,
232 int* out_height,
233 int* crop_width,
234 int* crop_height,
235 int* crop_x,
236 int* crop_y,
237 int64_t* translated_camera_time_us) {
238 RTC_DCHECK(camera_thread_checker_.CalledOnValidThread());
239
240 int64_t offset_us =
241 translated_camera_time_us
magjed_webrtc 2016/07/19 12:57:47 This if-statement is not necessary, we always pass
sakal 2016/07/19 13:46:23 Done.
242 ? timestamp_aligner_.UpdateOffset(camera_time_us, system_time_us)
243 : 0;
244
245 if (!broadcaster_.frame_wanted()) {
246 return false;
247 }
248
249 if (!video_adapter_.AdaptFrameResolution(
250 width, height, camera_time_us * rtc::kNumNanosecsPerMicrosec,
251 crop_width, crop_height, out_width, out_height)) {
252 // VideoAdapter dropped the frame.
253 return false;
254 }
255 *crop_x = (width - *crop_width) / 2;
256 *crop_y = (height - *crop_height) / 2;
257
258 if (translated_camera_time_us) {
magjed_webrtc 2016/07/19 12:57:47 This if-statement is not necessary, we always pass
sakal 2016/07/19 13:46:23 Done.
259 *translated_camera_time_us = timestamp_aligner_.ClipTimestamp(
260 camera_time_us + offset_us, system_time_us);
261 }
262 return true;
263 }
264 }
magjed_webrtc 2016/07/19 12:57:47 empty line between }:s and comment "// namespace w
sakal 2016/07/19 13:46:23 Done.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698