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:

committed by
Commit Bot

parent
fe73d6ab87
commit
12e555b715
1
AUTHORS
1
AUTHORS
@ -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>
|
||||
|
@ -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_
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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.";
|
||||
|
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user