Use libyuv rotate methods
Bug: webrtc:13826 Change-Id: I10a3b291a66eae1b867dd2fa1a1781c235feef33 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/290703 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39060}
This commit is contained in:
parent
143c3b2b4c
commit
bfc26c65e6
@ -66,12 +66,13 @@ rtc::scoped_refptr<I010Buffer> I010Buffer::Copy(
|
||||
const int width = source.width();
|
||||
const int height = source.height();
|
||||
rtc::scoped_refptr<I010Buffer> buffer = Create(width, height);
|
||||
RTC_CHECK_EQ(
|
||||
0, libyuv::I010Copy(
|
||||
source.DataY(), source.StrideY(), source.DataU(), source.StrideU(),
|
||||
source.DataV(), source.StrideV(), buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
|
||||
buffer->MutableDataV(), buffer->StrideV(), width, height));
|
||||
int res = libyuv::I010Copy(
|
||||
source.DataY(), source.StrideY(), source.DataU(), source.StrideU(),
|
||||
source.DataV(), source.StrideV(), buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
|
||||
buffer->MutableDataV(), buffer->StrideV(), width, height);
|
||||
RTC_DCHECK_EQ(res, 0);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -81,12 +82,13 @@ rtc::scoped_refptr<I010Buffer> I010Buffer::Copy(
|
||||
const int width = source.width();
|
||||
const int height = source.height();
|
||||
rtc::scoped_refptr<I010Buffer> buffer = Create(width, height);
|
||||
RTC_CHECK_EQ(
|
||||
0, libyuv::I420ToI010(
|
||||
source.DataY(), source.StrideY(), source.DataU(), source.StrideU(),
|
||||
source.DataV(), source.StrideV(), buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
|
||||
buffer->MutableDataV(), buffer->StrideV(), width, height));
|
||||
int res = libyuv::I420ToI010(
|
||||
source.DataY(), source.StrideY(), source.DataU(), source.StrideU(),
|
||||
source.DataV(), source.StrideV(), buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
|
||||
buffer->MutableDataV(), buffer->StrideV(), width, height);
|
||||
RTC_DCHECK_EQ(res, 0);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -109,52 +111,28 @@ rtc::scoped_refptr<I010Buffer> I010Buffer::Rotate(
|
||||
|
||||
rtc::scoped_refptr<webrtc::I010Buffer> buffer =
|
||||
Create(rotated_width, rotated_height);
|
||||
// TODO(emircan): Remove this when there is libyuv::I010Rotate().
|
||||
for (int x = 0; x < src.width(); x++) {
|
||||
for (int y = 0; y < src.height(); y++) {
|
||||
int dest_x = x;
|
||||
int dest_y = y;
|
||||
switch (rotation) {
|
||||
// This case is covered by the early return.
|
||||
case webrtc::kVideoRotation_0:
|
||||
RTC_DCHECK_NOTREACHED();
|
||||
break;
|
||||
case webrtc::kVideoRotation_90:
|
||||
dest_x = src.height() - y - 1;
|
||||
dest_y = x;
|
||||
break;
|
||||
case webrtc::kVideoRotation_180:
|
||||
dest_x = src.width() - x - 1;
|
||||
dest_y = src.height() - y - 1;
|
||||
break;
|
||||
case webrtc::kVideoRotation_270:
|
||||
dest_x = y;
|
||||
dest_y = src.width() - x - 1;
|
||||
break;
|
||||
}
|
||||
buffer->MutableDataY()[dest_x + buffer->StrideY() * dest_y] =
|
||||
src.DataY()[x + src.StrideY() * y];
|
||||
dest_x /= 2;
|
||||
dest_y /= 2;
|
||||
int src_x = x / 2;
|
||||
int src_y = y / 2;
|
||||
buffer->MutableDataU()[dest_x + buffer->StrideU() * dest_y] =
|
||||
src.DataU()[src_x + src.StrideU() * src_y];
|
||||
buffer->MutableDataV()[dest_x + buffer->StrideV() * dest_y] =
|
||||
src.DataV()[src_x + src.StrideV() * src_y];
|
||||
}
|
||||
}
|
||||
|
||||
int res = libyuv::I010Rotate(
|
||||
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;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<I420BufferInterface> I010Buffer::ToI420() {
|
||||
rtc::scoped_refptr<I420Buffer> i420_buffer =
|
||||
I420Buffer::Create(width(), height());
|
||||
libyuv::I010ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
|
||||
i420_buffer->MutableDataY(), i420_buffer->StrideY(),
|
||||
i420_buffer->MutableDataU(), i420_buffer->StrideU(),
|
||||
i420_buffer->MutableDataV(), i420_buffer->StrideV(),
|
||||
width(), height());
|
||||
int res = libyuv::I010ToI420(
|
||||
DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
|
||||
i420_buffer->MutableDataY(), i420_buffer->StrideY(),
|
||||
i420_buffer->MutableDataU(), i420_buffer->StrideU(),
|
||||
i420_buffer->MutableDataV(), i420_buffer->StrideV(), width(), height());
|
||||
RTC_DCHECK_EQ(res, 0);
|
||||
|
||||
return i420_buffer;
|
||||
}
|
||||
|
||||
|
||||
@ -31,140 +31,6 @@ int I210DataSize(int height, int stride_y, int stride_u, int stride_v) {
|
||||
(stride_y * height + stride_u * height + stride_v * height);
|
||||
}
|
||||
|
||||
void webrtcRotatePlane90_16(const uint16_t* src,
|
||||
int src_stride,
|
||||
uint16_t* dst,
|
||||
int dst_stride,
|
||||
int width,
|
||||
int height) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int dest_x = height - y - 1;
|
||||
int dest_y = x;
|
||||
dst[dest_x + dst_stride * dest_y] = src[x + src_stride * y];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void webrtcRotatePlane180_16(const uint16_t* src,
|
||||
int src_stride,
|
||||
uint16_t* dst,
|
||||
int dst_stride,
|
||||
int width,
|
||||
int height) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int dest_x = width - x - 1;
|
||||
int dest_y = height - y - 1;
|
||||
dst[dest_x + dst_stride * dest_y] = src[x + src_stride * y];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void webrtcRotatePlane270_16(const uint16_t* src,
|
||||
int src_stride,
|
||||
uint16_t* dst,
|
||||
int dst_stride,
|
||||
int width,
|
||||
int height) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int dest_x = y;
|
||||
int dest_y = width - x - 1;
|
||||
dst[dest_x + dst_stride * dest_y] = src[x + src_stride * y];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(sergio.garcia.murillo@gmail.com): Remove as soon it is available in
|
||||
// libyuv. Due to the rotate&scale required, this function may not be merged in
|
||||
// to libyuv inmediatelly.
|
||||
// https://bugs.chromium.org/p/libyuv/issues/detail?id=926
|
||||
// This method assumes continuous allocation of the y-plane, possibly clobbering
|
||||
// any padding between pixel rows.
|
||||
int webrtcI210Rotate(const uint16_t* src_y,
|
||||
int src_stride_y,
|
||||
const uint16_t* src_u,
|
||||
int src_stride_u,
|
||||
const uint16_t* src_v,
|
||||
int src_stride_v,
|
||||
uint16_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint16_t* dst_u,
|
||||
int dst_stride_u,
|
||||
uint16_t* dst_v,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height,
|
||||
enum libyuv::RotationMode mode) {
|
||||
int halfwidth = (width + 1) >> 1;
|
||||
int halfheight = (height + 1) >> 1;
|
||||
if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
|
||||
!dst_u || !dst_v || dst_stride_y < 0) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
src_y = src_y + (height - 1) * src_stride_y;
|
||||
src_u = src_u + (height - 1) * src_stride_u;
|
||||
src_v = src_v + (height - 1) * src_stride_v;
|
||||
src_stride_y = -src_stride_y;
|
||||
src_stride_u = -src_stride_u;
|
||||
src_stride_v = -src_stride_v;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case libyuv::kRotate0:
|
||||
// copy frame
|
||||
libyuv::CopyPlane_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
|
||||
height);
|
||||
libyuv::CopyPlane_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
|
||||
height);
|
||||
libyuv::CopyPlane_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
|
||||
height);
|
||||
return 0;
|
||||
case libyuv::kRotate90:
|
||||
// We need to rotate and rescale, we use plane Y as temporal storage.
|
||||
webrtcRotatePlane90_16(src_u, src_stride_u, dst_y, height, halfwidth,
|
||||
height);
|
||||
libyuv::ScalePlane_16(dst_y, height, height, halfwidth, dst_u, halfheight,
|
||||
halfheight, width, libyuv::kFilterBilinear);
|
||||
webrtcRotatePlane90_16(src_v, src_stride_v, dst_y, height, halfwidth,
|
||||
height);
|
||||
libyuv::ScalePlane_16(dst_y, height, height, halfwidth, dst_v, halfheight,
|
||||
halfheight, width, libyuv::kFilterLinear);
|
||||
webrtcRotatePlane90_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
|
||||
height);
|
||||
return 0;
|
||||
case libyuv::kRotate270:
|
||||
// We need to rotate and rescale, we use plane Y as temporal storage.
|
||||
webrtcRotatePlane270_16(src_u, src_stride_u, dst_y, height, halfwidth,
|
||||
height);
|
||||
libyuv::ScalePlane_16(dst_y, height, height, halfwidth, dst_u, halfheight,
|
||||
halfheight, width, libyuv::kFilterBilinear);
|
||||
webrtcRotatePlane270_16(src_v, src_stride_v, dst_y, height, halfwidth,
|
||||
height);
|
||||
libyuv::ScalePlane_16(dst_y, height, height, halfwidth, dst_v, halfheight,
|
||||
halfheight, width, libyuv::kFilterLinear);
|
||||
webrtcRotatePlane270_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
|
||||
height);
|
||||
|
||||
return 0;
|
||||
case libyuv::kRotate180:
|
||||
webrtcRotatePlane180_16(src_y, src_stride_y, dst_y, dst_stride_y, width,
|
||||
height);
|
||||
webrtcRotatePlane180_16(src_u, src_stride_u, dst_u, dst_stride_u,
|
||||
halfwidth, height);
|
||||
webrtcRotatePlane180_16(src_v, src_stride_v, dst_v, dst_stride_v,
|
||||
halfwidth, height);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
I210Buffer::I210Buffer(int width,
|
||||
@ -246,7 +112,7 @@ rtc::scoped_refptr<I210Buffer> I210Buffer::Rotate(
|
||||
I210Buffer::Create(rotated_width, rotated_height);
|
||||
|
||||
RTC_CHECK_EQ(0,
|
||||
webrtcI210Rotate(
|
||||
libyuv::I210Rotate(
|
||||
src.DataY(), src.StrideY(), src.DataU(), src.StrideU(),
|
||||
src.DataV(), src.StrideV(), buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
|
||||
|
||||
@ -87,12 +87,13 @@ rtc::scoped_refptr<I422Buffer> I422Buffer::Copy(
|
||||
const int width = source.width();
|
||||
const int height = source.height();
|
||||
rtc::scoped_refptr<I422Buffer> buffer = Create(width, height);
|
||||
RTC_CHECK_EQ(
|
||||
0, libyuv::I420ToI422(
|
||||
source.DataY(), source.StrideY(), source.DataU(), source.StrideU(),
|
||||
source.DataV(), source.StrideV(), buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
|
||||
buffer->MutableDataV(), buffer->StrideV(), width, height));
|
||||
int res = libyuv::I420ToI422(
|
||||
source.DataY(), source.StrideY(), source.DataU(), source.StrideU(),
|
||||
source.DataV(), source.StrideV(), buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
|
||||
buffer->MutableDataV(), buffer->StrideV(), width, height);
|
||||
RTC_DCHECK_EQ(res, 0);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -107,11 +108,13 @@ rtc::scoped_refptr<I422Buffer> I422Buffer::Copy(int width,
|
||||
int stride_v) {
|
||||
// Note: May use different strides than the input data.
|
||||
rtc::scoped_refptr<I422Buffer> buffer = Create(width, height);
|
||||
RTC_CHECK_EQ(0, libyuv::I422Copy(data_y, stride_y, data_u, stride_u, data_v,
|
||||
stride_v, buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(),
|
||||
buffer->StrideU(), buffer->MutableDataV(),
|
||||
buffer->StrideV(), width, height));
|
||||
int res = libyuv::I422Copy(data_y, stride_y, data_u, stride_u, data_v,
|
||||
stride_v, buffer->MutableDataY(),
|
||||
buffer->StrideY(), buffer->MutableDataU(),
|
||||
buffer->StrideU(), buffer->MutableDataV(),
|
||||
buffer->StrideV(), width, height);
|
||||
RTC_DCHECK_EQ(res, 0);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -133,13 +136,13 @@ rtc::scoped_refptr<I422Buffer> I422Buffer::Rotate(
|
||||
rtc::scoped_refptr<webrtc::I422Buffer> buffer =
|
||||
I422Buffer::Create(rotated_width, rotated_height);
|
||||
|
||||
RTC_CHECK_EQ(0,
|
||||
libyuv::I422Rotate(
|
||||
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)));
|
||||
int res = libyuv::I422Rotate(
|
||||
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;
|
||||
}
|
||||
@ -147,11 +150,13 @@ rtc::scoped_refptr<I422Buffer> I422Buffer::Rotate(
|
||||
rtc::scoped_refptr<I420BufferInterface> I422Buffer::ToI420() {
|
||||
rtc::scoped_refptr<I420Buffer> i420_buffer =
|
||||
I420Buffer::Create(width(), height());
|
||||
libyuv::I422ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
|
||||
i420_buffer->MutableDataY(), i420_buffer->StrideY(),
|
||||
i420_buffer->MutableDataU(), i420_buffer->StrideU(),
|
||||
i420_buffer->MutableDataV(), i420_buffer->StrideV(),
|
||||
width(), height());
|
||||
int res = libyuv::I422ToI420(
|
||||
DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
|
||||
i420_buffer->MutableDataY(), i420_buffer->StrideY(),
|
||||
i420_buffer->MutableDataU(), i420_buffer->StrideU(),
|
||||
i420_buffer->MutableDataV(), i420_buffer->StrideV(), width(), height());
|
||||
RTC_DCHECK_EQ(res, 0);
|
||||
|
||||
return i420_buffer;
|
||||
}
|
||||
|
||||
@ -226,7 +231,6 @@ void I422Buffer::CropAndScaleFrom(const I422BufferInterface& src,
|
||||
src.StrideV(), crop_width, crop_height, MutableDataY(),
|
||||
StrideY(), MutableDataU(), StrideU(), MutableDataV(),
|
||||
StrideV(), width(), height(), libyuv::kFilterBox);
|
||||
|
||||
RTC_DCHECK_EQ(res, 0);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user