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

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

Issue 1973873003: Delete AndroidVideoCapturer::FrameFactory. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Address nits. Created 4 years, 7 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 /* 1 /*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/api/androidvideocapturer.h" 11 #include "webrtc/api/androidvideocapturer.h"
12 12
13 #include <memory> 13 #include <memory>
14 14
15 #include "webrtc/api/java/jni/native_handle_impl.h" 15 #include "webrtc/api/java/jni/native_handle_impl.h"
16 #include "webrtc/api/java/jni/surfacetexturehelper_jni.h"
16 #include "webrtc/base/common.h" 17 #include "webrtc/base/common.h"
17 #include "webrtc/base/timeutils.h" 18 #include "webrtc/base/timeutils.h"
18 #include "webrtc/media/engine/webrtcvideoframe.h" 19 #include "webrtc/media/engine/webrtcvideoframe.h"
19 20
20 namespace webrtc { 21 namespace webrtc {
21 22
22 // A hack for avoiding deep frame copies in
23 // cricket::VideoCapturer.SignalFrameCaptured() using a custom FrameFactory.
24 // A frame is injected using UpdateCapturedFrame(), and converted into a
25 // cricket::VideoFrame with CreateAliasedFrame(). UpdateCapturedFrame() should
26 // be called before CreateAliasedFrame() for every frame.
27 // TODO(magjed): Add an interface cricket::VideoCapturer::OnFrameCaptured()
28 // for ref counted I420 frames instead of this hack.
29 class AndroidVideoCapturer::FrameFactory : public cricket::VideoFrameFactory {
30 public:
31 explicit FrameFactory(
32 const rtc::scoped_refptr<AndroidVideoCapturerDelegate>& delegate)
33 : delegate_(delegate) {
34 // Create a CapturedFrame that only contains header information, not the
35 // actual pixel data.
36 captured_frame_.pixel_height = 1;
37 captured_frame_.pixel_width = 1;
38 captured_frame_.data = nullptr;
39 captured_frame_.data_size = cricket::CapturedFrame::kUnknownDataSize;
40 captured_frame_.fourcc = static_cast<uint32_t>(cricket::FOURCC_ANY);
41 }
42
43 void UpdateCapturedFrame(
44 const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer,
45 int rotation,
46 int64_t time_stamp_in_ns) {
47 RTC_DCHECK(rotation == 0 || rotation == 90 || rotation == 180 ||
48 rotation == 270);
49 buffer_ = buffer;
50 captured_frame_.width = buffer->width();
51 captured_frame_.height = buffer->height();
52 captured_frame_.time_stamp = time_stamp_in_ns;
53 captured_frame_.rotation = static_cast<webrtc::VideoRotation>(rotation);
54 }
55
56 void ClearCapturedFrame() {
57 buffer_ = nullptr;
58 captured_frame_.width = 0;
59 captured_frame_.height = 0;
60 captured_frame_.time_stamp = 0;
61 }
62
63 const cricket::CapturedFrame* GetCapturedFrame() const {
64 return &captured_frame_;
65 }
66
67 cricket::VideoFrame* CreateAliasedFrame(
68 const cricket::CapturedFrame* captured_frame,
69 int dst_width,
70 int dst_height) const override {
71 // Check that captured_frame is actually our frame.
72 RTC_CHECK(captured_frame == &captured_frame_);
73 RTC_CHECK(buffer_->native_handle() == nullptr);
74
75 std::unique_ptr<cricket::VideoFrame> frame(new cricket::WebRtcVideoFrame(
76 ShallowCenterCrop(buffer_, dst_width, dst_height),
77 captured_frame->time_stamp, captured_frame->rotation));
78 // Caller takes ownership.
79 // TODO(magjed): Change CreateAliasedFrame() to return a std::unique_ptr.
80 return apply_rotation_ ? frame->GetCopyWithRotationApplied()->Copy()
81 : frame.release();
82 }
83
84 cricket::VideoFrame* CreateAliasedFrame(
85 const cricket::CapturedFrame* input_frame,
86 int cropped_input_width,
87 int cropped_input_height,
88 int output_width,
89 int output_height) const override {
90 if (buffer_->native_handle() != nullptr) {
91 rtc::scoped_refptr<webrtc::VideoFrameBuffer> scaled_buffer(
92 static_cast<webrtc_jni::AndroidTextureBuffer*>(buffer_.get())
93 ->CropScaleAndRotate(cropped_input_width, cropped_input_height,
94 output_width, output_height,
95 apply_rotation_ ? input_frame->rotation
96 : webrtc::kVideoRotation_0));
97 return new cricket::WebRtcVideoFrame(
98 scaled_buffer, input_frame->time_stamp,
99 apply_rotation_ ? webrtc::kVideoRotation_0 : input_frame->rotation);
100 }
101 return VideoFrameFactory::CreateAliasedFrame(input_frame,
102 cropped_input_width,
103 cropped_input_height,
104 output_width,
105 output_height);
106 }
107
108 private:
109 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer_;
110 cricket::CapturedFrame captured_frame_;
111 rtc::scoped_refptr<AndroidVideoCapturerDelegate> delegate_;
112 };
113
114 AndroidVideoCapturer::AndroidVideoCapturer( 23 AndroidVideoCapturer::AndroidVideoCapturer(
115 const rtc::scoped_refptr<AndroidVideoCapturerDelegate>& delegate) 24 const rtc::scoped_refptr<AndroidVideoCapturerDelegate>& delegate,
25 rtc::scoped_refptr<webrtc_jni::SurfaceTextureHelper> helper)
116 : running_(false), 26 : running_(false),
117 delegate_(delegate), 27 delegate_(delegate),
118 frame_factory_(NULL), 28 surface_texture_helper_(helper),
119 current_state_(cricket::CS_STOPPED) { 29 current_state_(cricket::CS_STOPPED) {
120 thread_checker_.DetachFromThread(); 30 thread_checker_.DetachFromThread();
121 SetSupportedFormats(delegate_->GetSupportedFormats()); 31 SetSupportedFormats(delegate_->GetSupportedFormats());
122 } 32 }
123 33
124 AndroidVideoCapturer::~AndroidVideoCapturer() { 34 AndroidVideoCapturer::~AndroidVideoCapturer() {
125 RTC_CHECK(!running_); 35 RTC_CHECK(!running_);
126 } 36 }
127 37
128 cricket::CaptureState AndroidVideoCapturer::Start( 38 cricket::CaptureState AndroidVideoCapturer::Start(
129 const cricket::VideoFormat& capture_format) { 39 const cricket::VideoFormat& capture_format) {
130 RTC_CHECK(thread_checker_.CalledOnValidThread()); 40 RTC_CHECK(thread_checker_.CalledOnValidThread());
131 RTC_CHECK(!running_); 41 RTC_CHECK(!running_);
132 const int fps = cricket::VideoFormat::IntervalToFps(capture_format.interval); 42 const int fps = cricket::VideoFormat::IntervalToFps(capture_format.interval);
133 LOG(LS_INFO) << " AndroidVideoCapturer::Start " << capture_format.width << "x" 43 LOG(LS_INFO) << " AndroidVideoCapturer::Start " << capture_format.width << "x"
134 << capture_format.height << "@" << fps; 44 << capture_format.height << "@" << fps;
135 45
136 frame_factory_ = new AndroidVideoCapturer::FrameFactory(delegate_.get());
137 set_frame_factory(frame_factory_);
138
139 running_ = true; 46 running_ = true;
140 delegate_->Start(capture_format.width, capture_format.height, fps, this); 47 delegate_->Start(capture_format.width, capture_format.height, fps, this);
141 SetCaptureFormat(&capture_format); 48 SetCaptureFormat(&capture_format);
142 current_state_ = cricket::CS_STARTING; 49 current_state_ = cricket::CS_STARTING;
143 return current_state_; 50 return current_state_;
144 } 51 }
145 52
146 void AndroidVideoCapturer::Stop() { 53 void AndroidVideoCapturer::Stop() {
147 LOG(LS_INFO) << " AndroidVideoCapturer::Stop "; 54 LOG(LS_INFO) << " AndroidVideoCapturer::Stop ";
148 RTC_CHECK(thread_checker_.CalledOnValidThread()); 55 RTC_CHECK(thread_checker_.CalledOnValidThread());
(...skipping 20 matching lines...) Expand all
169 void AndroidVideoCapturer::OnCapturerStarted(bool success) { 76 void AndroidVideoCapturer::OnCapturerStarted(bool success) {
170 RTC_CHECK(thread_checker_.CalledOnValidThread()); 77 RTC_CHECK(thread_checker_.CalledOnValidThread());
171 cricket::CaptureState new_state = 78 cricket::CaptureState new_state =
172 success ? cricket::CS_RUNNING : cricket::CS_FAILED; 79 success ? cricket::CS_RUNNING : cricket::CS_FAILED;
173 if (new_state == current_state_) 80 if (new_state == current_state_)
174 return; 81 return;
175 current_state_ = new_state; 82 current_state_ = new_state;
176 SetCaptureState(new_state); 83 SetCaptureState(new_state);
177 } 84 }
178 85
179 void AndroidVideoCapturer::OnIncomingFrame( 86 void AndroidVideoCapturer::OnNV21Frame(const uint8_t* video_frame,
180 const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer, 87 int length,
181 int rotation, 88 int width,
182 int64_t time_stamp) { 89 int height,
183 RTC_CHECK(thread_checker_.CalledOnValidThread()); 90 webrtc::VideoRotation rotation,
184 frame_factory_->UpdateCapturedFrame(buffer, rotation, time_stamp); 91 int64_t timestamp_ns) {
185 SignalFrameCaptured(this, frame_factory_->GetCapturedFrame()); 92 int adapted_width;
186 frame_factory_->ClearCapturedFrame(); 93 int adapted_height;
94 int crop_width;
95 int crop_height;
96 int crop_x;
97 int crop_y;
98
99 if (!AdaptFrame(width, height, &adapted_width, &adapted_height,
100 &crop_width, &crop_height, &crop_x, &crop_y)) {
101 return;
102 }
103
104 int rotated_width = crop_width;
105 int rotated_height = crop_height;
106
107 if (apply_rotation() && (rotation == webrtc::kVideoRotation_90 ||
108 rotation == webrtc::kVideoRotation_270)) {
109 std::swap(adapted_width, adapted_height);
110 std::swap(rotated_width, rotated_height);
111 }
112
113 // TODO(nisse): Move buffer_pool_ here (from AndroidVideoCapturerJni)
114 rtc::scoped_refptr<webrtc::I420Buffer> buffer(
115 new rtc::RefCountedObject<I420Buffer>(rotated_width, rotated_height));
116
117 const uint8_t* y_plane = video_frame;
118 const uint8_t* uv_plane = video_frame + width * height;
119
120 // Can only crop at even pixels.
121 crop_x &= ~1;
122
123 libyuv::NV12ToI420Rotate(
124 video_frame + width * crop_y + crop_x, width, // Y plane
125 video_frame + width * (height + crop_y) + crop_x, width, // UV Plane
126 buffer->MutableData(webrtc::kYPlane), buffer->stride(webrtc::kYPlane),
127 // Swap U and V, since we have NV21, not NV12.
128 buffer->MutableData(webrtc::kVPlane), buffer->stride(webrtc::kVPlane),
129 buffer->MutableData(webrtc::kUPlane), buffer->stride(webrtc::kUPlane),
130 crop_width, crop_height,
131 static_cast<libyuv::RotationMode>(
132 apply_rotation() ? rotation : webrtc::kVideoRotation_0));
133
134 if (adapted_width != rotated_width || adapted_height != rotated_height) {
135 buffer = I420Buffer::CropAndScale(
136 buffer, 0, 0, rotated_width, rotated_height,
137 adapted_width, adapted_height);
138 }
139 // TODO(nisse): Use microsecond time instead.
140 OnFrame(cricket::WebRtcVideoFrame(
141 buffer, timestamp_ns,
142 apply_rotation() ? webrtc::kVideoRotation_0 : rotation),
143 width, height);
144 }
145
146 void AndroidVideoCapturer::OnTextureFrame(
147 int width,
148 int height,
149 webrtc::VideoRotation rotation,
150 int64_t timestamp_ns,
151 const webrtc_jni::NativeHandleImpl& handle) {
152 int adapted_width;
153 int adapted_height;
154 int crop_width;
155 int crop_height;
156 int crop_x;
157 int crop_y;
158
159 if (!AdaptFrame(width, height, &adapted_width, &adapted_height,
160 &crop_width, &crop_height, &crop_x, &crop_y)) {
161 return;
162 }
163
164 webrtc_jni::NativeHandleImpl::Matrix matrix = handle.sampling_matrix;
165
166 matrix.Crop(crop_width / static_cast<float>(width),
167 crop_height / static_cast<float>(height),
168 crop_x / static_cast<float>(width),
169 crop_y / static_cast<float>(height));
170
171 if (apply_rotation()) {
172 if (rotation == webrtc::kVideoRotation_90 ||
173 rotation == webrtc::kVideoRotation_270) {
174 std::swap(adapted_width, adapted_height);
175 }
176 matrix.Rotate(rotation);
177 }
178
179 // TODO(nisse): Use microsecond time instead.
180 OnFrame(cricket::WebRtcVideoFrame(
181 surface_texture_helper_->CreateTextureFrame(
182 adapted_width, adapted_height,
183 webrtc_jni::NativeHandleImpl(handle.oes_texture_id, matrix)),
184 timestamp_ns,
185 apply_rotation() ? webrtc::kVideoRotation_0 : rotation),
186 width, height);
187 } 187 }
188 188
189 void AndroidVideoCapturer::OnOutputFormatRequest( 189 void AndroidVideoCapturer::OnOutputFormatRequest(
190 int width, int height, int fps) { 190 int width, int height, int fps) {
191 RTC_CHECK(thread_checker_.CalledOnValidThread()); 191 RTC_CHECK(thread_checker_.CalledOnValidThread());
192 cricket::VideoFormat format(width, height, 192 cricket::VideoFormat format(width, height,
193 cricket::VideoFormat::FpsToInterval(fps), 0); 193 cricket::VideoFormat::FpsToInterval(fps), 0);
194 video_adapter()->OnOutputFormatRequest(format); 194 video_adapter()->OnOutputFormatRequest(format);
195 } 195 }
196 196
197 bool AndroidVideoCapturer::GetBestCaptureFormat( 197 bool AndroidVideoCapturer::GetBestCaptureFormat(
198 const cricket::VideoFormat& desired, 198 const cricket::VideoFormat& desired,
199 cricket::VideoFormat* best_format) { 199 cricket::VideoFormat* best_format) {
200 // Delegate this choice to VideoCapturer.startCapture(). 200 // Delegate this choice to VideoCapturer.startCapture().
201 *best_format = desired; 201 *best_format = desired;
202 return true; 202 return true;
203 } 203 }
204 204
205 } // namespace webrtc 205 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698