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}
This commit is contained in:
nisse 2016-08-30 08:45:44 -07:00 committed by Commit bot
parent c31446f49e
commit d50747269e
9 changed files with 114 additions and 50 deletions

View File

@ -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<I420Buffer> CopyKeepStride(
const rtc::scoped_refptr<VideoFrameBuffer>& 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<VideoFrameBuffer> Rotate(
const rtc::scoped_refptr<VideoFrameBuffer>& src,
VideoRotation rotation);
protected:
~I420Buffer() override;

View File

@ -216,6 +216,7 @@ void I420Buffer::ScaleFrom(const rtc::scoped_refptr<VideoFrameBuffer>& src) {
CropAndScaleFrom(src, 0, 0, src->width(), src->height());
}
// static
rtc::scoped_refptr<I420Buffer> I420Buffer::CopyKeepStride(
const rtc::scoped_refptr<VideoFrameBuffer>& source) {
int width = source->width();
@ -236,6 +237,41 @@ rtc::scoped_refptr<I420Buffer> I420Buffer::CopyKeepStride(
return target;
}
// static
rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::Rotate(
const rtc::scoped_refptr<VideoFrameBuffer>& 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<webrtc::I420Buffer> 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<libyuv::RotationMode>(rotation));
RTC_DCHECK_EQ(res, 0);
return buffer;
}
NativeHandleBuffer::NativeHandleBuffer(void* native_handle,
int width,
int height)

View File

@ -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();

View File

@ -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<VideoRenderer> 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);
}

View File

@ -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.

View File

@ -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<size_t>(frame->width()) *
frame->height() * 4,
frame->width() * 4);
frame.ConvertToRgbBuffer(cricket::FOURCC_ABGR,
image_.get(),
static_cast<size_t>(frame.width()) *
frame.height() * 4,
frame.width() * 4);
}
// Trigger a repaint event for the whole window.

View File

@ -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<WPARAM>(frame), 0);
if (SetSize(frame.width(), frame.height())) {
SendMessage(handle(), kRenderFrameMsg, reinterpret_cast<WPARAM>(&frame), 0);
}
}

View File

@ -17,7 +17,7 @@
#include <gtk/gtk.h>
#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<size_t>(frame->width()) *
frame->height() * 4,
frame->width() * 4);
frame.ConvertToRgbBuffer(cricket::FOURCC_ABGR,
image_.get(),
static_cast<size_t>(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();

View File

@ -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<WebRtcVideoFrame*>(static_cast<const WebRtcVideoFrame*>(
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