Chromium Code Reviews| Index: content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc |
| diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc |
| index bf7f8dd3e585b3cebb5064e2cbde65ca4b02f208..61975c75d187902948e9b2ec7ce2274e9053e17f 100644 |
| --- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc |
| +++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc |
| @@ -6,17 +6,22 @@ |
| #include "base/bind.h" |
| #include "base/debug/trace_event.h" |
| +#include "base/memory/aligned_memory.h" |
| #include "media/base/video_frame.h" |
| +#include "third_party/libyuv/include/libyuv/convert.h" |
| namespace content { |
| WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast) |
| : is_screencast_(is_screencast), |
| - running_(false) { |
| + running_(false), |
| + buffer_(NULL), |
| + buffer_size_(0) { |
| } |
| WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() { |
| DVLOG(3) << " WebRtcVideoCapturerAdapter::dtor"; |
| + base::AlignedFree(buffer_); |
| } |
| void WebRtcVideoCapturerAdapter::SetRequestedFormat( |
| @@ -91,31 +96,100 @@ bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat( |
| void WebRtcVideoCapturerAdapter::OnFrameCaptured( |
| const scoped_refptr<media::VideoFrame>& frame) { |
| - DCHECK_EQ(media::VideoFrame::I420, frame->format()); |
| + DCHECK(media::VideoFrame::I420 == frame->format() || |
| + media::VideoFrame::YV12 == frame->format()); |
| if (first_frame_timestamp_ == media::kNoTimestamp()) |
| first_frame_timestamp_ = frame->GetTimestamp(); |
| - // Currently, |fourcc| is always I420. |
| cricket::CapturedFrame captured_frame; |
| - captured_frame.width = frame->coded_size().width(); |
| - captured_frame.height = frame->coded_size().height(); |
| - captured_frame.fourcc = cricket::FOURCC_I420; |
| + captured_frame.width = frame->visible_rect().width(); |
| + captured_frame.height = frame->visible_rect().height(); |
| // cricket::CapturedFrame time is in nanoseconds. |
| captured_frame.elapsed_time = |
| (frame->GetTimestamp() - first_frame_timestamp_).InMicroseconds() * |
| base::Time::kNanosecondsPerMicrosecond; |
| captured_frame.time_stamp = frame->GetTimestamp().InMicroseconds() * |
| base::Time::kNanosecondsPerMicrosecond; |
| - // TODO(sheu): we assume contiguous layout of image planes. |
| - captured_frame.data = frame->data(0); |
| - captured_frame.data_size = |
| - media::VideoFrame::AllocationSize(frame->format(), frame->coded_size()); |
| captured_frame.pixel_height = 1; |
| captured_frame.pixel_width = 1; |
| + // TODO(perkj): |
| + // 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.
|
| + // The only format where that is true in Chrome is I420 where the |
| + // coded_size == visible_rect().size(). |
| + if (frame->format() != media::VideoFrame::I420 || |
| + frame->coded_size() != frame->visible_rect().size()) { |
| + // Cropping and or switching UV planes is needed. |
| + UpdateI420Buffer(frame); |
| + captured_frame.data = buffer_; |
| + captured_frame.data_size = buffer_size_; |
| + captured_frame.fourcc = cricket::FOURCC_I420; |
| + } else { |
| + captured_frame.fourcc = |
| + 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.
|
| + cricket::FOURCC_I420 : cricket::FOURCC_YV12; |
| + captured_frame.data = frame->data(0); |
| + captured_frame.data_size = |
| + media::VideoFrame::AllocationSize(frame->format(), frame->coded_size()); |
| + } |
| + |
| // This signals to libJingle that a new VideoFrame is available. |
| // libJingle have no assumptions on what thread this signal come from. |
| SignalFrameCaptured(this, &captured_frame); |
| } |
| +void WebRtcVideoCapturerAdapter::UpdateI420Buffer( |
| + const scoped_refptr<media::VideoFrame>& src) { |
| + const int src_width = src->coded_size().width(); |
| + const int src_height = src->coded_size().height(); |
| + const int dst_width = src->visible_rect().width(); |
| + const int dst_height = src->visible_rect().height(); |
| + 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.
|
| + |
| + const int horiz_crop = src->visible_rect().x(); |
| + const int vert_crop = src->visible_rect().y(); |
| + |
| + const uint8* src_y = src->data(media::VideoFrame::kYPlane) + |
| + (src_width * vert_crop + horiz_crop); |
| + 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.
|
| + const uint8* src_u = src->data(media::VideoFrame::kUPlane) + |
| + (halfwidth * vert_crop + horiz_crop) / 2; |
| + const uint8* src_v = src->data(media::VideoFrame::kVPlane) + |
| + (halfwidth * vert_crop + horiz_crop) / 2; |
| + |
| + const size_t dst_size = |
| + media::VideoFrame::AllocationSize(src->format(), |
| + src->visible_rect().size()); |
| + |
| + if (dst_size != buffer_size_) { |
| + base::AlignedFree(buffer_); |
| + buffer_ = reinterpret_cast<uint8*>( |
| + base::AlignedAlloc(dst_size + media::VideoFrame::kFrameSizePadding, |
| + media::VideoFrame::kFrameAddressAlignment)); |
| + buffer_size_ = dst_size; |
| + } |
| + |
| + uint8* dst_y = buffer_; |
| + const int dst_stride_y = dst_width; |
| + uint8* dst_u = dst_y + dst_width * dst_height; |
| + const int dst_halfwidth = (dst_width + 1) / 2; |
| + const int dst_halfheight = (dst_height + 1) / 2; |
| + uint8* dst_v = dst_u + dst_halfwidth * dst_halfheight; |
| + |
| + libyuv::I420Copy(src_y, |
| + src->stride(media::VideoFrame::kYPlane), |
| + src_u, |
| + src->stride(media::VideoFrame::kUPlane), |
| + src_v, |
| + src->stride(media::VideoFrame::kVPlane), |
| + dst_y, |
| + dst_stride_y, |
| + dst_u, |
| + dst_halfwidth, |
| + dst_v, |
| + dst_halfwidth, |
| + dst_width, |
| + dst_height); |
| +} |
| + |
| } // namespace content |