OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" | 5 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "base/memory/aligned_memory.h" | |
9 #include "media/base/video_frame.h" | 10 #include "media/base/video_frame.h" |
11 #include "third_party/libyuv/include/libyuv/convert.h" | |
10 | 12 |
11 namespace content { | 13 namespace content { |
12 | 14 |
13 WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast) | 15 WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast) |
14 : is_screencast_(is_screencast), | 16 : is_screencast_(is_screencast), |
15 running_(false) { | 17 running_(false), |
18 buffer_(NULL), | |
19 buffer_size_(0) { | |
16 } | 20 } |
17 | 21 |
18 WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() { | 22 WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() { |
19 DVLOG(3) << " WebRtcVideoCapturerAdapter::dtor"; | 23 DVLOG(3) << " WebRtcVideoCapturerAdapter::dtor"; |
24 base::AlignedFree(buffer_); | |
20 } | 25 } |
21 | 26 |
22 void WebRtcVideoCapturerAdapter::SetRequestedFormat( | 27 void WebRtcVideoCapturerAdapter::SetRequestedFormat( |
23 const media::VideoCaptureFormat& format) { | 28 const media::VideoCaptureFormat& format) { |
24 DCHECK_EQ(media::PIXEL_FORMAT_I420, format.pixel_format); | 29 DCHECK_EQ(media::PIXEL_FORMAT_I420, format.pixel_format); |
25 DVLOG(3) << "WebRtcVideoCapturerAdapter::SetRequestedFormat" | 30 DVLOG(3) << "WebRtcVideoCapturerAdapter::SetRequestedFormat" |
26 << " w = " << format.frame_size.width() | 31 << " w = " << format.frame_size.width() |
27 << " h = " << format.frame_size.height(); | 32 << " h = " << format.frame_size.height(); |
28 cricket::VideoFormat supported_format(format.frame_size.width(), | 33 cricket::VideoFormat supported_format(format.frame_size.width(), |
29 format.frame_size.height(), | 34 format.frame_size.height(), |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 // Use the desired format as the best format. | 89 // Use the desired format as the best format. |
85 best_format->width = desired.width; | 90 best_format->width = desired.width; |
86 best_format->height = desired.height; | 91 best_format->height = desired.height; |
87 best_format->fourcc = cricket::FOURCC_I420; | 92 best_format->fourcc = cricket::FOURCC_I420; |
88 best_format->interval = desired.interval; | 93 best_format->interval = desired.interval; |
89 return true; | 94 return true; |
90 } | 95 } |
91 | 96 |
92 void WebRtcVideoCapturerAdapter::OnFrameCaptured( | 97 void WebRtcVideoCapturerAdapter::OnFrameCaptured( |
93 const scoped_refptr<media::VideoFrame>& frame) { | 98 const scoped_refptr<media::VideoFrame>& frame) { |
94 DCHECK_EQ(media::VideoFrame::I420, frame->format()); | 99 DCHECK(media::VideoFrame::I420 == frame->format() || |
100 media::VideoFrame::YV12 == frame->format()); | |
95 if (first_frame_timestamp_ == media::kNoTimestamp()) | 101 if (first_frame_timestamp_ == media::kNoTimestamp()) |
96 first_frame_timestamp_ = frame->GetTimestamp(); | 102 first_frame_timestamp_ = frame->GetTimestamp(); |
97 | 103 |
98 // Currently, |fourcc| is always I420. | |
99 cricket::CapturedFrame captured_frame; | 104 cricket::CapturedFrame captured_frame; |
100 captured_frame.width = frame->coded_size().width(); | 105 captured_frame.width = frame->visible_rect().width(); |
101 captured_frame.height = frame->coded_size().height(); | 106 captured_frame.height = frame->visible_rect().height(); |
102 captured_frame.fourcc = cricket::FOURCC_I420; | |
103 // cricket::CapturedFrame time is in nanoseconds. | 107 // cricket::CapturedFrame time is in nanoseconds. |
104 captured_frame.elapsed_time = | 108 captured_frame.elapsed_time = |
105 (frame->GetTimestamp() - first_frame_timestamp_).InMicroseconds() * | 109 (frame->GetTimestamp() - first_frame_timestamp_).InMicroseconds() * |
106 base::Time::kNanosecondsPerMicrosecond; | 110 base::Time::kNanosecondsPerMicrosecond; |
107 captured_frame.time_stamp = frame->GetTimestamp().InMicroseconds() * | 111 captured_frame.time_stamp = frame->GetTimestamp().InMicroseconds() * |
108 base::Time::kNanosecondsPerMicrosecond; | 112 base::Time::kNanosecondsPerMicrosecond; |
109 // TODO(sheu): we assume contiguous layout of image planes. | |
110 captured_frame.data = frame->data(0); | |
111 captured_frame.data_size = | |
112 media::VideoFrame::AllocationSize(frame->format(), frame->coded_size()); | |
113 captured_frame.pixel_height = 1; | 113 captured_frame.pixel_height = 1; |
114 captured_frame.pixel_width = 1; | 114 captured_frame.pixel_width = 1; |
115 | 115 |
116 // TODO(perkj): | |
117 // Libjingle expect contiguous layout of image planes as input. | |
tommi (sloooow) - chröme
2014/03/06 10:14:09
expects
perkj_chrome
2014/03/06 12:45:42
Done.
| |
118 // The only format where that is true in Chrome is I420 where the | |
119 // coded_size == visible_rect().size(). | |
120 if (frame->format() != media::VideoFrame::I420 || | |
121 frame->coded_size() != frame->visible_rect().size()) { | |
122 // Cropping and or switching UV planes is needed. | |
123 UpdateI420Buffer(frame); | |
124 captured_frame.data = buffer_; | |
125 captured_frame.data_size = buffer_size_; | |
126 captured_frame.fourcc = cricket::FOURCC_I420; | |
127 } else { | |
128 captured_frame.fourcc = | |
129 media::VideoFrame::I420 == frame->format() ? | |
tommi (sloooow) - chröme
2014/03/06 10:14:09
fix indent
perkj_chrome
2014/03/06 12:45:42
Done.
| |
130 cricket::FOURCC_I420 : cricket::FOURCC_YV12; | |
131 captured_frame.data = frame->data(0); | |
132 captured_frame.data_size = | |
133 media::VideoFrame::AllocationSize(frame->format(), frame->coded_size()); | |
134 } | |
135 | |
116 // This signals to libJingle that a new VideoFrame is available. | 136 // This signals to libJingle that a new VideoFrame is available. |
117 // libJingle have no assumptions on what thread this signal come from. | 137 // libJingle have no assumptions on what thread this signal come from. |
118 SignalFrameCaptured(this, &captured_frame); | 138 SignalFrameCaptured(this, &captured_frame); |
119 } | 139 } |
120 | 140 |
141 void WebRtcVideoCapturerAdapter::UpdateI420Buffer( | |
142 const scoped_refptr<media::VideoFrame>& src) { | |
143 const int src_width = src->coded_size().width(); | |
144 const int src_height = src->coded_size().height(); | |
145 const int dst_width = src->visible_rect().width(); | |
146 const int dst_height = src->visible_rect().height(); | |
147 DCHECK(src_width > dst_width || src_height > dst_height); | |
tommi (sloooow) - chröme
2014/03/06 10:14:09
should these checks be >= ?
also, should the || b
perkj_chrome
2014/03/06 12:45:42
Done.
| |
148 | |
149 const int horiz_crop = src->visible_rect().x(); | |
150 const int vert_crop = src->visible_rect().y(); | |
151 | |
152 const uint8* src_y = src->data(media::VideoFrame::kYPlane) + | |
153 (src_width * vert_crop + horiz_crop); | |
154 const int halfwidth = (src_width + 1) / 2; | |
tommi (sloooow) - chröme
2014/03/06 10:14:09
half_width
(or center depending on how you prefer
perkj_chrome
2014/03/06 12:45:42
Done.
| |
155 const uint8* src_u = src->data(media::VideoFrame::kUPlane) + | |
156 (halfwidth * vert_crop + horiz_crop) / 2; | |
157 const uint8* src_v = src->data(media::VideoFrame::kVPlane) + | |
158 (halfwidth * vert_crop + horiz_crop) / 2; | |
159 | |
160 const size_t dst_size = | |
161 media::VideoFrame::AllocationSize(src->format(), | |
162 src->visible_rect().size()); | |
163 | |
164 if (dst_size != buffer_size_) { | |
165 base::AlignedFree(buffer_); | |
166 buffer_ = reinterpret_cast<uint8*>( | |
167 base::AlignedAlloc(dst_size + media::VideoFrame::kFrameSizePadding, | |
168 media::VideoFrame::kFrameAddressAlignment)); | |
169 buffer_size_ = dst_size; | |
170 } | |
171 | |
172 uint8* dst_y = buffer_; | |
173 const int dst_stride_y = dst_width; | |
174 uint8* dst_u = dst_y + dst_width * dst_height; | |
175 const int dst_halfwidth = (dst_width + 1) / 2; | |
176 const int dst_halfheight = (dst_height + 1) / 2; | |
177 uint8* dst_v = dst_u + dst_halfwidth * dst_halfheight; | |
178 | |
179 libyuv::I420Copy(src_y, | |
180 src->stride(media::VideoFrame::kYPlane), | |
181 src_u, | |
182 src->stride(media::VideoFrame::kUPlane), | |
183 src_v, | |
184 src->stride(media::VideoFrame::kVPlane), | |
185 dst_y, | |
186 dst_stride_y, | |
187 dst_u, | |
188 dst_halfwidth, | |
189 dst_v, | |
190 dst_halfwidth, | |
191 dst_width, | |
192 dst_height); | |
193 } | |
194 | |
121 } // namespace content | 195 } // namespace content |
OLD | NEW |