From d50747269e6a3de5c05288184c5f58a11eb6d268 Mon Sep 17 00:00:00 2001 From: nisse Date: Tue, 30 Aug 2016 08:45:44 -0700 Subject: [PATCH] New static I420Buffer::Rotate method, to replace GetCopyWithRotationApplied. GetCopyWithRotationApplied is not yet deleted; downstream projects must be updated first. BUG=webrtc:5682 Review-Url: https://codereview.webrtc.org/2285693002 Cr-Commit-Position: refs/heads/master@{#13973} --- .../common_video/include/video_frame_buffer.h | 8 +++++ webrtc/common_video/video_frame_buffer.cc | 36 +++++++++++++++++++ .../peerconnection/client/linux/main_wnd.cc | 16 +++++---- .../peerconnection/client/main_wnd.cc | 19 +++++----- webrtc/media/base/videoframe.h | 6 ++-- webrtc/media/devices/carbonvideorenderer.cc | 17 +++++---- webrtc/media/devices/gdivideorenderer.cc | 11 +++--- webrtc/media/devices/gtkvideorenderer.cc | 25 +++++++------ .../media/engine/webrtcvideoframe_unittest.cc | 26 ++++++++------ 9 files changed, 114 insertions(+), 50 deletions(-) diff --git a/webrtc/common_video/include/video_frame_buffer.h b/webrtc/common_video/include/video_frame_buffer.h index 94b3d5d833..6743970203 100644 --- a/webrtc/common_video/include/video_frame_buffer.h +++ b/webrtc/common_video/include/video_frame_buffer.h @@ -18,6 +18,7 @@ #include "webrtc/base/callback.h" #include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/common_video/rotation.h" #include "webrtc/system_wrappers/include/aligned_malloc.h" namespace webrtc { @@ -130,6 +131,13 @@ class I420Buffer : public VideoFrameBuffer { static rtc::scoped_refptr CopyKeepStride( const rtc::scoped_refptr& buffer); + // Returns a rotated versions of |src|. Native buffers are not + // supported. The reason this function doesn't return an I420Buffer, + // is that it returns |src| unchanged in case |rotation| is zero. + static rtc::scoped_refptr Rotate( + const rtc::scoped_refptr& src, + VideoRotation rotation); + protected: ~I420Buffer() override; diff --git a/webrtc/common_video/video_frame_buffer.cc b/webrtc/common_video/video_frame_buffer.cc index fd20e564f5..2d7e7f4565 100644 --- a/webrtc/common_video/video_frame_buffer.cc +++ b/webrtc/common_video/video_frame_buffer.cc @@ -216,6 +216,7 @@ void I420Buffer::ScaleFrom(const rtc::scoped_refptr& src) { CropAndScaleFrom(src, 0, 0, src->width(), src->height()); } +// static rtc::scoped_refptr I420Buffer::CopyKeepStride( const rtc::scoped_refptr& source) { int width = source->width(); @@ -236,6 +237,41 @@ rtc::scoped_refptr I420Buffer::CopyKeepStride( return target; } +// static +rtc::scoped_refptr I420Buffer::Rotate( + const rtc::scoped_refptr& src, + VideoRotation rotation) { + RTC_DCHECK(src->DataY()); + RTC_DCHECK(src->DataU()); + RTC_DCHECK(src->DataV()); + + if (rotation == webrtc::kVideoRotation_0) { + return src; + } + + int rotated_width = src->width(); + int rotated_height = src->height(); + if (rotation == webrtc::kVideoRotation_90 || + rotation == webrtc::kVideoRotation_270) { + std::swap(rotated_width, rotated_height); + } + + rtc::scoped_refptr buffer = + I420Buffer::Create(rotated_width, rotated_height); + + int res = libyuv::I420Rotate( + src->DataY(), src->StrideY(), + src->DataU(), src->StrideU(), + src->DataV(), src->StrideV(), + buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(), + buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(), + src->width(), src->height(), + static_cast(rotation)); + RTC_DCHECK_EQ(res, 0); + + return buffer; +} + NativeHandleBuffer::NativeHandleBuffer(void* native_handle, int width, int height) diff --git a/webrtc/examples/peerconnection/client/linux/main_wnd.cc b/webrtc/examples/peerconnection/client/linux/main_wnd.cc index e2ed0085e0..95229c9e13 100644 --- a/webrtc/examples/peerconnection/client/linux/main_wnd.cc +++ b/webrtc/examples/peerconnection/client/linux/main_wnd.cc @@ -18,6 +18,7 @@ #include "webrtc/base/common.h" #include "webrtc/base/logging.h" #include "webrtc/base/stringutils.h" +#include "webrtc/media/engine/webrtcvideoframe.h" using rtc::sprintfn; @@ -484,16 +485,19 @@ void GtkMainWnd::VideoRenderer::OnFrame( const cricket::VideoFrame& video_frame) { gdk_threads_enter(); - const cricket::VideoFrame* frame = video_frame.GetCopyWithRotationApplied(); + const cricket::WebRtcVideoFrame frame( + webrtc::I420Buffer::Rotate(video_frame.video_frame_buffer(), + video_frame.rotation()), + webrtc::kVideoRotation_0, video_frame.timestamp_us()); - SetSize(frame->width(), frame->height()); + SetSize(frame.width(), frame.height()); int size = width_ * height_ * 4; // TODO(henrike): Convert directly to RGBA - frame->ConvertToRgbBuffer(cricket::FOURCC_ARGB, - image_.get(), - size, - width_ * 4); + frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB, + image_.get(), + size, + width_ * 4); // Convert the B,G,R,A frame to R,G,B,A, which is accepted by GTK. // The 'A' is just padding for GTK, so we can use it as temp. uint8_t* pix = image_.get(); diff --git a/webrtc/examples/peerconnection/client/main_wnd.cc b/webrtc/examples/peerconnection/client/main_wnd.cc index 91e66cd519..ea2c366785 100644 --- a/webrtc/examples/peerconnection/client/main_wnd.cc +++ b/webrtc/examples/peerconnection/client/main_wnd.cc @@ -16,6 +16,7 @@ #include "webrtc/base/arraysize.h" #include "webrtc/base/common.h" #include "webrtc/base/logging.h" +#include "webrtc/media/engine/webrtcvideoframe.h" ATOM MainWnd::wnd_class_ = 0; const wchar_t MainWnd::kClassName[] = L"WebRTC_MainWnd"; @@ -604,17 +605,19 @@ void MainWnd::VideoRenderer::OnFrame( { AutoLock lock(this); - const cricket::VideoFrame* frame = - video_frame.GetCopyWithRotationApplied(); + const cricket::WebRtcVideoFrame frame( + webrtc::I420Buffer::Rotate(video_frame.video_frame_buffer(), + video_frame.rotation()), + webrtc::kVideoRotation_0, video_frame.timestamp_us()); - SetSize(frame->width(), frame->height()); + SetSize(frame.width(), frame.height()); ASSERT(image_.get() != NULL); - frame->ConvertToRgbBuffer(cricket::FOURCC_ARGB, - image_.get(), - bmi_.bmiHeader.biSizeImage, - bmi_.bmiHeader.biWidth * - bmi_.bmiHeader.biBitCount / 8); + frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB, + image_.get(), + bmi_.bmiHeader.biSizeImage, + bmi_.bmiHeader.biWidth * + bmi_.bmiHeader.biBitCount / 8); } InvalidateRect(wnd_, NULL, TRUE); } diff --git a/webrtc/media/base/videoframe.h b/webrtc/media/base/videoframe.h index 88d97358f1..ba020bd89d 100644 --- a/webrtc/media/base/videoframe.h +++ b/webrtc/media/base/videoframe.h @@ -58,9 +58,9 @@ class VideoFrame { // Return a copy of frame which has its pending rotation applied. The // ownership of the returned frame is held by this frame. - // TODO(nisse): Deprecated. Should be moved or deleted in the - // cricket::VideoFrame and webrtc::VideoFrame merge, possibly with a helper - // method on VideoFrameBuffer. + // TODO(nisse): Deprecated, no longer used within webrtc. Should be + // deleted as soon as downstream applications are updated. Use + // webrtc::I420Buffer::Rotate instead. virtual const VideoFrame* GetCopyWithRotationApplied() const = 0; // Converts the I420 data to RGB of a certain type such as ARGB and ABGR. diff --git a/webrtc/media/devices/carbonvideorenderer.cc b/webrtc/media/devices/carbonvideorenderer.cc index a1ff630620..766904231c 100644 --- a/webrtc/media/devices/carbonvideorenderer.cc +++ b/webrtc/media/devices/carbonvideorenderer.cc @@ -106,19 +106,22 @@ bool CarbonVideoRenderer::SetSize(int width, int height) { void CarbonVideoRenderer::OnFrame(const VideoFrame& video_frame) { { - const VideoFrame* frame = video_frame->GetCopyWithRotationApplied(); + const cricket::WebRtcVideoFrame frame( + webrtc::I420Buffer::Rotate(video_frame.video_frame_buffer(), + video_frame.rotation()), + webrtc::kVideoRotation_0, video_frame.timestamp_us()); - if (!SetSize(frame->width(), frame->height())) { + if (!SetSize(frame.width(), frame.height())) { return false; } // Grab the image lock so we are not trashing up the image being drawn. rtc::CritScope cs(&image_crit_); - frame->ConvertToRgbBuffer(cricket::FOURCC_ABGR, - image_.get(), - static_cast(frame->width()) * - frame->height() * 4, - frame->width() * 4); + frame.ConvertToRgbBuffer(cricket::FOURCC_ABGR, + image_.get(), + static_cast(frame.width()) * + frame.height() * 4, + frame.width() * 4); } // Trigger a repaint event for the whole window. diff --git a/webrtc/media/devices/gdivideorenderer.cc b/webrtc/media/devices/gdivideorenderer.cc index bd67b68edd..320b479a47 100644 --- a/webrtc/media/devices/gdivideorenderer.cc +++ b/webrtc/media/devices/gdivideorenderer.cc @@ -17,7 +17,7 @@ #include "webrtc/base/thread.h" #include "webrtc/base/win32window.h" #include "webrtc/media/base/videocommon.h" -#include "webrtc/media/base/videoframe.h" +#include "webrtc/media/engine/webrtcvideoframe.h" namespace cricket { @@ -135,10 +135,13 @@ void GdiVideoRenderer::VideoWindow::OnFrame(const VideoFrame& video_frame) { return; } - const VideoFrame* frame = video_frame.GetCopyWithRotationApplied(); + const cricket::WebRtcVideoFrame frame( + webrtc::I420Buffer::Rotate(video_frame.video_frame_buffer(), + video_frame.rotation()), + webrtc::kVideoRotation_0, video_frame.timestamp_us()); - if (SetSize(frame->width(), frame->height())) { - SendMessage(handle(), kRenderFrameMsg, reinterpret_cast(frame), 0); + if (SetSize(frame.width(), frame.height())) { + SendMessage(handle(), kRenderFrameMsg, reinterpret_cast(&frame), 0); } } diff --git a/webrtc/media/devices/gtkvideorenderer.cc b/webrtc/media/devices/gtkvideorenderer.cc index d7a4d6fb6c..8fad53d794 100644 --- a/webrtc/media/devices/gtkvideorenderer.cc +++ b/webrtc/media/devices/gtkvideorenderer.cc @@ -17,7 +17,7 @@ #include #include "webrtc/media/base/videocommon.h" -#include "webrtc/media/base/videoframe.h" +#include "webrtc/media/engine/webrtcvideoframe.h" namespace cricket { @@ -81,19 +81,22 @@ bool GtkVideoRenderer::SetSize(int width, int height) { } void GtkVideoRenderer::OnFrame(const VideoFrame& video_frame) { - const VideoFrame* frame = video_frame.GetCopyWithRotationApplied(); + const cricket::WebRtcVideoFrame frame( + webrtc::I420Buffer::Rotate(video_frame.video_frame_buffer(), + video_frame.rotation()), + webrtc::kVideoRotation_0, video_frame.timestamp_us()); // Need to set size as the frame might be rotated. - if (!SetSize(frame->width(), frame->height())) { + if (!SetSize(frame.width(), frame.height())) { return; } // convert I420 frame to ABGR format, which is accepted by GTK - frame->ConvertToRgbBuffer(cricket::FOURCC_ABGR, - image_.get(), - static_cast(frame->width()) * - frame->height() * 4, - frame->width() * 4); + frame.ConvertToRgbBuffer(cricket::FOURCC_ABGR, + image_.get(), + static_cast(frame.width()) * + frame.height() * 4, + frame.width() * 4); ScopedGdkLock lock; @@ -106,11 +109,11 @@ void GtkVideoRenderer::OnFrame(const VideoFrame& video_frame) { draw_area_->style->fg_gc[GTK_STATE_NORMAL], 0, 0, - frame->width(), - frame->height(), + frame.width(), + frame.height(), GDK_RGB_DITHER_MAX, image_.get(), - frame->width() * 4); + frame.width() * 4); // Run the Gtk main loop to refresh the window. Pump(); diff --git a/webrtc/media/engine/webrtcvideoframe_unittest.cc b/webrtc/media/engine/webrtcvideoframe_unittest.cc index 9d6bd5f7b5..336cff4a97 100644 --- a/webrtc/media/engine/webrtcvideoframe_unittest.cc +++ b/webrtc/media/engine/webrtcvideoframe_unittest.cc @@ -275,22 +275,26 @@ TEST_F(WebRtcVideoFrameTest, ApplyRotationToFrame) { // Claim that this frame needs to be rotated for 90 degree. SetFrameRotation(&applied0, webrtc::kVideoRotation_90); + EXPECT_EQ(applied0.rotation(), webrtc::kVideoRotation_90); // Apply rotation on frame 1. Output should be different from frame 1. - WebRtcVideoFrame* applied90 = - const_cast(static_cast( - applied0.GetCopyWithRotationApplied())); - EXPECT_TRUE(applied90); - EXPECT_EQ(applied90->rotation(), webrtc::kVideoRotation_0); - EXPECT_FALSE(IsEqual(applied0, *applied90, 0)); + WebRtcVideoFrame applied90( + webrtc::I420Buffer::Rotate(applied0.video_frame_buffer(), + applied0.rotation()), + webrtc::kVideoRotation_0, applied0.timestamp_us()); + + EXPECT_EQ(applied90.rotation(), webrtc::kVideoRotation_0); + EXPECT_FALSE(IsEqual(applied0, applied90, 0)); // Claim the frame 2 needs to be rotated for another 270 degree. The output // from frame 2 rotation should be the same as frame 1. - SetFrameRotation(applied90, webrtc::kVideoRotation_270); - const VideoFrame* applied360 = applied90->GetCopyWithRotationApplied(); - EXPECT_TRUE(applied360); - EXPECT_EQ(applied360->rotation(), webrtc::kVideoRotation_0); - EXPECT_TRUE(IsEqual(applied0, *applied360, 0)); + SetFrameRotation(&applied90, webrtc::kVideoRotation_270); + WebRtcVideoFrame applied360( + webrtc::I420Buffer::Rotate(applied90.video_frame_buffer(), + applied90.rotation()), + webrtc::kVideoRotation_0, applied90.timestamp_us()); + EXPECT_EQ(applied360.rotation(), webrtc::kVideoRotation_0); + EXPECT_TRUE(IsEqual(applied0, applied360, 0)); } } // namespace cricket