Delete wrapper API ConvertToI420 for YUV conversion to I420
Directly use the libyuv API for YUV conversion to I420
Bug: None
Change-Id: Iea6e8fa8f7179c800ea850305170002398cb00dc
Reviewed-on: https://webrtc-review.googlesource.com/17260
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Alex Glaznev <glaznev@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20681}diff --git a/AUTHORS b/AUTHORS
index 285cde4..3a73bd61 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -28,6 +28,7 @@
Jiawei Ou <jiawei.ou@gmail.com>
Jie Mao <maojie0924@gmail.com>
Luke Weber <luke.weber@gmail.com>
+Mallikarjuna Rao V <vm.arjun@samsung.com>
Manish Jethani <manish.jethani@gmail.com>
Martin Storsjo <martin@martin.st>
Matthias Liebig <matthias.gcode@gmail.com>
diff --git a/common_video/libyuv/include/webrtc_libyuv.h b/common_video/libyuv/include/webrtc_libyuv.h
index 8230c1f..5b2a3af 100644
--- a/common_video/libyuv/include/webrtc_libyuv.h
+++ b/common_video/libyuv/include/webrtc_libyuv.h
@@ -24,7 +24,6 @@
namespace webrtc {
-class I420Buffer;
// This is the max PSNR value our algorithms can return.
const double kPerfectPSNR = 48.0f;
@@ -64,34 +63,6 @@
size_t size,
uint8_t* buffer);
int ExtractBuffer(const VideoFrame& input_frame, size_t size, uint8_t* buffer);
-// Convert To I420
-// Input:
-// - src_video_type : Type of input video.
-// - src_frame : Pointer to a source frame.
-// - crop_x/crop_y : Starting positions for cropping (0 for no crop).
-// - src_width : src width in pixels.
-// - src_height : src height in pixels.
-// - sample_size : Required only for the parsing of MJPG (set to 0 else).
-// - rotate : Rotation mode of output image.
-// Output:
-// - dst_buffer : Reference to a destination frame buffer.
-// Return value: 0 if OK, < 0 otherwise.
-
-// TODO(nisse): Delete this wrapper, and let users call libyuv directly. Most
-// calls pass |src_video_type| == kI420, and should use libyuv::I420Copy. Also
-// remember to delete the I420Buffer forward declaration above. The only
-// exception at the time of this writing is VideoCaptureImpl::IncomingFrame,
-// which still needs libyuv::ConvertToI420.
-int ConvertToI420(VideoType src_video_type,
- const uint8_t* src_frame,
- int crop_x,
- int crop_y,
- int src_width,
- int src_height,
- size_t sample_size,
- VideoRotation rotation,
- I420Buffer* dst_buffer);
-
// Convert From I420
// Input:
// - src_frame : Reference to a source frame.
@@ -147,6 +118,9 @@
std::vector<uint8_t> tmp_uv_planes_;
};
+// Convert VideoType to libyuv FourCC type
+int ConvertVideoType(VideoType video_type);
+
} // namespace webrtc
#endif // COMMON_VIDEO_LIBYUV_INCLUDE_WEBRTC_LIBYUV_H_
diff --git a/common_video/libyuv/libyuv_unittest.cc b/common_video/libyuv/libyuv_unittest.cc
index 4e3a1ac..e5a09bf 100644
--- a/common_video/libyuv/libyuv_unittest.cc
+++ b/common_video/libyuv/libyuv_unittest.cc
@@ -16,6 +16,7 @@
#include "api/video/i420_buffer.h"
#include "api/video/video_frame.h"
#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "libyuv.h" // NOLINT
#include "test/frame_utils.h"
#include "test/gmock.h"
#include "test/gtest.h"
@@ -96,9 +97,16 @@
std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]);
EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kI420, 0,
out_i420_buffer.get()));
- EXPECT_EQ(0,
- ConvertToI420(VideoType::kI420, out_i420_buffer.get(), 0, 0, width_,
- height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+ int y_size = width_ * height_;
+ int u_size = res_i420_buffer->ChromaWidth() * res_i420_buffer->ChromaHeight();
+ int ret = libyuv::I420Copy(
+ out_i420_buffer.get(), width_, out_i420_buffer.get() + y_size,
+ width_ >> 1, out_i420_buffer.get() + y_size + u_size, width_ >> 1,
+ res_i420_buffer.get()->MutableDataY(), res_i420_buffer.get()->StrideY(),
+ res_i420_buffer.get()->MutableDataU(), res_i420_buffer.get()->StrideU(),
+ res_i420_buffer.get()->MutableDataV(), res_i420_buffer.get()->StrideV(),
+ width_, height_);
+ EXPECT_EQ(0, ret);
if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
return;
@@ -119,10 +127,15 @@
EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kRGB24, 0,
res_rgb_buffer2.get()));
- EXPECT_EQ(
- 0, ConvertToI420(VideoType::kRGB24, res_rgb_buffer2.get(), 0, 0, width_,
- height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+ ret = libyuv::ConvertToI420(
+ res_rgb_buffer2.get(), 0, res_i420_buffer.get()->MutableDataY(),
+ res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+ res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+ res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+ res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+ ConvertVideoType(VideoType::kRGB24));
+ EXPECT_EQ(0, ret);
if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
return;
}
@@ -137,9 +150,16 @@
std::unique_ptr<uint8_t[]> out_uyvy_buffer(new uint8_t[width_ * height_ * 2]);
EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kUYVY, 0,
out_uyvy_buffer.get()));
- EXPECT_EQ(0,
- ConvertToI420(VideoType::kUYVY, out_uyvy_buffer.get(), 0, 0, width_,
- height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+
+ ret = libyuv::ConvertToI420(
+ out_uyvy_buffer.get(), 0, res_i420_buffer.get()->MutableDataY(),
+ res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+ res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+ res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+ res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+ ConvertVideoType(VideoType::kUYVY));
+
+ EXPECT_EQ(0, ret);
psnr =
I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
EXPECT_EQ(48.0, psnr);
@@ -153,9 +173,15 @@
EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kYUY2, 0,
out_yuy2_buffer.get()));
- EXPECT_EQ(0,
- ConvertToI420(VideoType::kYUY2, out_yuy2_buffer.get(), 0, 0, width_,
- height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+ ret = libyuv::ConvertToI420(
+ out_yuy2_buffer.get(), 0, res_i420_buffer.get()->MutableDataY(),
+ res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+ res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+ res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+ res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+ ConvertVideoType(VideoType::kYUY2));
+
+ EXPECT_EQ(0, ret);
if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
return;
@@ -171,9 +197,15 @@
EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kRGB565, 0,
out_rgb565_buffer.get()));
- EXPECT_EQ(0, ConvertToI420(VideoType::kRGB565, out_rgb565_buffer.get(), 0, 0,
- width_, height_, 0, kVideoRotation_0,
- res_i420_buffer.get()));
+ ret = libyuv::ConvertToI420(
+ out_rgb565_buffer.get(), 0, res_i420_buffer.get()->MutableDataY(),
+ res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+ res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+ res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+ res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+ ConvertVideoType(VideoType::kRGB565));
+
+ EXPECT_EQ(0, ret);
if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
return;
}
@@ -192,9 +224,15 @@
EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kARGB, 0,
out_argb8888_buffer.get()));
- EXPECT_EQ(0, ConvertToI420(VideoType::kARGB, out_argb8888_buffer.get(), 0, 0,
- width_, height_, 0, kVideoRotation_0,
- res_i420_buffer.get()));
+ ret = libyuv::ConvertToI420(
+ out_argb8888_buffer.get(), 0, res_i420_buffer.get()->MutableDataY(),
+ res_i420_buffer.get()->StrideY(), res_i420_buffer.get()->MutableDataU(),
+ res_i420_buffer.get()->StrideU(), res_i420_buffer.get()->MutableDataV(),
+ res_i420_buffer.get()->StrideV(), 0, 0, width_, height_,
+ res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
+ ConvertVideoType(VideoType::kARGB));
+
+ EXPECT_EQ(0, ret);
if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
return;
@@ -227,9 +265,17 @@
std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]);
EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kI420, 0,
out_i420_buffer.get()));
- EXPECT_EQ(0,
- ConvertToI420(VideoType::kI420, out_i420_buffer.get(), 0, 0, width_,
- height_, 0, kVideoRotation_0, res_i420_buffer.get()));
+ int y_size = width_ * height_;
+ int u_size = res_i420_buffer->ChromaWidth() * res_i420_buffer->ChromaHeight();
+ int ret = libyuv::I420Copy(
+ out_i420_buffer.get(), width_, out_i420_buffer.get() + y_size,
+ width_ >> 1, out_i420_buffer.get() + y_size + u_size, width_ >> 1,
+ res_i420_buffer.get()->MutableDataY(), res_i420_buffer.get()->StrideY(),
+ res_i420_buffer.get()->MutableDataU(), res_i420_buffer.get()->StrideU(),
+ res_i420_buffer.get()->MutableDataV(), res_i420_buffer.get()->StrideV(),
+ width_, height_);
+
+ EXPECT_EQ(0, ret);
if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
return;
@@ -239,33 +285,6 @@
EXPECT_EQ(48.0, psnr);
}
-TEST_F(TestLibYuv, RotateTest) {
- // Use ConvertToI420 for multiple rotations - see that nothing breaks, all
- // memory is properly allocated and end result is equal to the starting point.
- int rotated_width = height_;
- int rotated_height = width_;
- int stride_y;
- int stride_uv;
-
- // Assume compact layout, no padding.
- const uint8_t* orig_buffer =
- orig_frame_->video_frame_buffer()->GetI420()->DataY();
-
- Calc16ByteAlignedStride(rotated_width, &stride_y, &stride_uv);
- rtc::scoped_refptr<I420Buffer> rotated_res_i420_buffer = I420Buffer::Create(
- rotated_width, rotated_height, stride_y, stride_uv, stride_uv);
- EXPECT_EQ(
- 0, ConvertToI420(VideoType::kI420, orig_buffer, 0, 0, width_, height_, 0,
- kVideoRotation_90, rotated_res_i420_buffer.get()));
- EXPECT_EQ(
- 0, ConvertToI420(VideoType::kI420, orig_buffer, 0, 0, width_, height_, 0,
- kVideoRotation_270, rotated_res_i420_buffer.get()));
- rotated_res_i420_buffer = I420Buffer::Create(width_, height_);
- EXPECT_EQ(
- 0, ConvertToI420(VideoType::kI420, orig_buffer, 0, 0, width_, height_, 0,
- kVideoRotation_180, rotated_res_i420_buffer.get()));
-}
-
static uint8_t Average(int a, int b, int c, int d) {
return (a + b + c + d + 2) / 4;
}
diff --git a/common_video/libyuv/webrtc_libyuv.cc b/common_video/libyuv/webrtc_libyuv.cc
index 4cb8686..4384b85 100644
--- a/common_video/libyuv/webrtc_libyuv.cc
+++ b/common_video/libyuv/webrtc_libyuv.cc
@@ -13,7 +13,6 @@
#include <string.h>
#include "rtc_base/checks.h"
-// TODO(nisse): Only needed for the deprecated ConvertToI420.
#include "api/video/i420_buffer.h"
// NOTE(ajm): Path provided by gn.
@@ -155,21 +154,6 @@
width, height);
}
-libyuv::RotationMode ConvertRotationMode(VideoRotation rotation) {
- switch (rotation) {
- case kVideoRotation_0:
- return libyuv::kRotate0;
- case kVideoRotation_90:
- return libyuv::kRotate90;
- case kVideoRotation_180:
- return libyuv::kRotate180;
- case kVideoRotation_270:
- return libyuv::kRotate270;
- }
- RTC_NOTREACHED();
- return libyuv::kRotate0;
-}
-
int ConvertVideoType(VideoType video_type) {
switch (video_type) {
case VideoType::kUnknown:
@@ -208,35 +192,6 @@
return libyuv::FOURCC_ANY;
}
-// TODO(nisse): Delete this wrapper, let callers use libyuv directly.
-int ConvertToI420(VideoType src_video_type,
- const uint8_t* src_frame,
- int crop_x,
- int crop_y,
- int src_width,
- int src_height,
- size_t sample_size,
- VideoRotation rotation,
- I420Buffer* dst_buffer) {
- int dst_width = dst_buffer->width();
- int dst_height = dst_buffer->height();
- // LibYuv expects pre-rotation values for dst.
- // Stride values should correspond to the destination values.
- if (rotation == kVideoRotation_90 || rotation == kVideoRotation_270) {
- std::swap(dst_width, dst_height);
- }
- return libyuv::ConvertToI420(
- src_frame, sample_size,
- dst_buffer->MutableDataY(), dst_buffer->StrideY(),
- dst_buffer->MutableDataU(), dst_buffer->StrideU(),
- dst_buffer->MutableDataV(), dst_buffer->StrideV(),
- crop_x, crop_y,
- src_width, src_height,
- dst_width, dst_height,
- ConvertRotationMode(rotation),
- ConvertVideoType(src_video_type));
-}
-
int ConvertFromI420(const VideoFrame& src_frame,
VideoType dst_video_type,
int dst_sample_size,
diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc
index 6a24f80..1eb77ee 100644
--- a/modules/video_capture/video_capture_impl.cc
+++ b/modules/video_capture/video_capture_impl.cc
@@ -14,6 +14,7 @@
#include "api/video/i420_buffer.h"
#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "libyuv.h" // NOLINT
#include "modules/include/module_common_types.h"
#include "modules/video_capture/video_capture_config.h"
#include "rtc_base/logging.h"
@@ -164,10 +165,32 @@
// TODO(nisse): Use a pool?
rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(
target_width, abs(target_height), stride_y, stride_uv, stride_uv);
- const int conversionResult = ConvertToI420(
- frameInfo.videoType, videoFrame, 0, 0, // No cropping
- width, height, videoFrameLength,
- apply_rotation ? _rotateFrame : kVideoRotation_0, buffer.get());
+
+ libyuv::RotationMode rotation_mode = libyuv::kRotate0;
+ if (apply_rotation) {
+ switch (_rotateFrame) {
+ case kVideoRotation_0:
+ rotation_mode = libyuv::kRotate0;
+ break;
+ case kVideoRotation_90:
+ rotation_mode = libyuv::kRotate90;
+ break;
+ case kVideoRotation_180:
+ rotation_mode = libyuv::kRotate180;
+ break;
+ case kVideoRotation_270:
+ rotation_mode = libyuv::kRotate270;
+ break;
+ }
+ }
+
+ const int conversionResult = libyuv::ConvertToI420(
+ videoFrame, videoFrameLength, buffer.get()->MutableDataY(),
+ buffer.get()->StrideY(), buffer.get()->MutableDataU(),
+ buffer.get()->StrideU(), buffer.get()->MutableDataV(),
+ buffer.get()->StrideV(), 0, 0, // No Cropping
+ width, height, target_width, target_height, rotation_mode,
+ ConvertVideoType(frameInfo.videoType));
if (conversionResult < 0) {
RTC_LOG(LS_ERROR) << "Failed to convert capture frame from type "
<< static_cast<int>(frameInfo.videoType) << "to I420.";
diff --git a/modules/video_coding/codecs/i420/i420.cc b/modules/video_coding/codecs/i420/i420.cc
index 2749d0e..8c8c3f0 100644
--- a/modules/video_coding/codecs/i420/i420.cc
+++ b/modules/video_coding/codecs/i420/i420.cc
@@ -15,6 +15,7 @@
#include "api/video/i420_buffer.h"
#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "libyuv.h" // NOLINT
namespace {
const size_t kI420HeaderSize = 4;
@@ -204,8 +205,16 @@
I420Buffer::Create(_width, _height);
// Converting from raw buffer I420Buffer.
- int ret = ConvertToI420(VideoType::kI420, buffer, 0, 0, _width, _height, 0,
- kVideoRotation_0, frame_buffer.get());
+ int y_stride = 16 * ((_width + 15) / 16);
+ int uv_stride = 16 * ((_width + 31) / 32);
+ int y_size = y_stride * height;
+ int u_size = uv_stride * frame_buffer->ChromaHeight();
+ int ret = libyuv::I420Copy(
+ buffer, y_stride, buffer + y_size, uv_stride, buffer + y_size + u_size,
+ uv_stride, frame_buffer.get()->MutableDataY(),
+ frame_buffer.get()->StrideY(), frame_buffer.get()->MutableDataU(),
+ frame_buffer.get()->StrideU(), frame_buffer.get()->MutableDataV(),
+ frame_buffer.get()->StrideV(), _width, _height);
if (ret < 0) {
return WEBRTC_VIDEO_CODEC_MEMORY;
}