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}
This commit is contained in:
mallikarjun82
2017-11-15 14:35:56 +05:30
committed by Commit Bot
parent fe73d6ab87
commit 12e555b715
6 changed files with 109 additions and 128 deletions

View File

@ -28,6 +28,7 @@ Jens Nielsen <jens.nielsen@berotec.se>
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>

View File

@ -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 @@ int ExtractBuffer(const rtc::scoped_refptr<I420BufferInterface>& input_frame,
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 @@ class NV12ToI420Scaler {
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_

View File

@ -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 @@ TEST_F(TestLibYuv, ConvertTest) {
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 @@ TEST_F(TestLibYuv, ConvertTest) {
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 @@ TEST_F(TestLibYuv, ConvertTest) {
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 @@ TEST_F(TestLibYuv, ConvertTest) {
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 @@ TEST_F(TestLibYuv, ConvertTest) {
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 @@ TEST_F(TestLibYuv, ConvertTest) {
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 @@ TEST_F(TestLibYuv, ConvertAlignedFrame) {
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 @@ TEST_F(TestLibYuv, ConvertAlignedFrame) {
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;
}

View File

@ -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 @@ int ConvertRGB24ToARGB(const uint8_t* src_frame, uint8_t* dst_frame,
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 @@ int ConvertVideoType(VideoType video_type) {
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,

View File

@ -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 @@ int32_t VideoCaptureImpl::IncomingFrame(uint8_t* videoFrame,
// 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.";

View File

@ -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 @@ int I420Decoder::Decode(const EncodedImage& inputImage,
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;
}