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

Unified Diff: content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc

Issue 183113004: Make sure MediaStreamVideoSource support cropping. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed extra spaces in content_unittests Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698