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 expects contiguous layout of image planes as input. |
| 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 = media::VideoFrame::I420 == frame->format() ? |
| 129 cricket::FOURCC_I420 : cricket::FOURCC_YV12; |
| 130 captured_frame.data = frame->data(0); |
| 131 captured_frame.data_size = |
| 132 media::VideoFrame::AllocationSize(frame->format(), frame->coded_size()); |
| 133 } |
| 134 |
116 // This signals to libJingle that a new VideoFrame is available. | 135 // This signals to libJingle that a new VideoFrame is available. |
117 // libJingle have no assumptions on what thread this signal come from. | 136 // libJingle have no assumptions on what thread this signal come from. |
118 SignalFrameCaptured(this, &captured_frame); | 137 SignalFrameCaptured(this, &captured_frame); |
119 } | 138 } |
120 | 139 |
| 140 void WebRtcVideoCapturerAdapter::UpdateI420Buffer( |
| 141 const scoped_refptr<media::VideoFrame>& src) { |
| 142 const int src_width = src->coded_size().width(); |
| 143 const int src_height = src->coded_size().height(); |
| 144 const int dst_width = src->visible_rect().width(); |
| 145 const int dst_height = src->visible_rect().height(); |
| 146 DCHECK(src_width >= dst_width && src_height >= dst_height); |
| 147 |
| 148 const int horiz_crop = src->visible_rect().x(); |
| 149 const int vert_crop = src->visible_rect().y(); |
| 150 |
| 151 const uint8* src_y = src->data(media::VideoFrame::kYPlane) + |
| 152 (src_width * vert_crop + horiz_crop); |
| 153 const int center = (src_width + 1) / 2; |
| 154 const uint8* src_u = src->data(media::VideoFrame::kUPlane) + |
| 155 (center * vert_crop + horiz_crop) / 2; |
| 156 const uint8* src_v = src->data(media::VideoFrame::kVPlane) + |
| 157 (center * vert_crop + horiz_crop) / 2; |
| 158 |
| 159 const size_t dst_size = |
| 160 media::VideoFrame::AllocationSize(src->format(), |
| 161 src->visible_rect().size()); |
| 162 |
| 163 if (dst_size != buffer_size_) { |
| 164 base::AlignedFree(buffer_); |
| 165 buffer_ = reinterpret_cast<uint8*>( |
| 166 base::AlignedAlloc(dst_size + media::VideoFrame::kFrameSizePadding, |
| 167 media::VideoFrame::kFrameAddressAlignment)); |
| 168 buffer_size_ = dst_size; |
| 169 } |
| 170 |
| 171 uint8* dst_y = buffer_; |
| 172 const int dst_stride_y = dst_width; |
| 173 uint8* dst_u = dst_y + dst_width * dst_height; |
| 174 const int dst_halfwidth = (dst_width + 1) / 2; |
| 175 const int dst_halfheight = (dst_height + 1) / 2; |
| 176 uint8* dst_v = dst_u + dst_halfwidth * dst_halfheight; |
| 177 |
| 178 libyuv::I420Copy(src_y, |
| 179 src->stride(media::VideoFrame::kYPlane), |
| 180 src_u, |
| 181 src->stride(media::VideoFrame::kUPlane), |
| 182 src_v, |
| 183 src->stride(media::VideoFrame::kVPlane), |
| 184 dst_y, |
| 185 dst_stride_y, |
| 186 dst_u, |
| 187 dst_halfwidth, |
| 188 dst_v, |
| 189 dst_halfwidth, |
| 190 dst_width, |
| 191 dst_height); |
| 192 } |
| 193 |
121 } // namespace content | 194 } // namespace content |
OLD | NEW |