| 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..6d6f7ff54fd5b3137242c5fdd107356097f68829 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,99 @@ 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 expects contiguous layout of image planes as input.
|
| + // 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() ?
|
| + 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);
|
| +
|
| + 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 center = (src_width + 1) / 2;
|
| + const uint8* src_u = src->data(media::VideoFrame::kUPlane) +
|
| + (center * vert_crop + horiz_crop) / 2;
|
| + const uint8* src_v = src->data(media::VideoFrame::kVPlane) +
|
| + (center * 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
|
|
|