mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-14 06:10:40 +01:00

This will allow incoming NV12 frames to be encodable by libvpx without requiring a conversion to I420 before encoding. NV12 is supported in libvpx https://chromium.googlesource.com/webm/libvpx/+/master/CHANGELOG Bug: webrtc:11916 Change-Id: I30e9c42c0607bee07691930c0248921bba09134c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/183720 Reviewed-by: Niels Moller <nisse@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Evan Shrubsole <eshr@google.com> Cr-Commit-Position: refs/heads/master@{#32061}
119 lines
3.9 KiB
C++
119 lines
3.9 KiB
C++
/*
|
|
* Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "api/video/nv12_buffer.h"
|
|
|
|
#include "api/video/i420_buffer.h"
|
|
#include "test/frame_utils.h"
|
|
#include "test/gmock.h"
|
|
#include "test/gtest.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
int GetY(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) {
|
|
return buf->DataY()[row * buf->StrideY() + col];
|
|
}
|
|
|
|
int GetU(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) {
|
|
return buf->DataUV()[(row / 2) * buf->StrideUV() + (col / 2) * 2];
|
|
}
|
|
|
|
int GetV(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) {
|
|
return buf->DataUV()[(row / 2) * buf->StrideUV() + (col / 2) * 2 + 1];
|
|
}
|
|
|
|
void FillNV12Buffer(rtc::scoped_refptr<NV12Buffer> buf) {
|
|
const uint8_t Y = 1;
|
|
const uint8_t U = 2;
|
|
const uint8_t V = 3;
|
|
for (int row = 0; row < buf->height(); ++row) {
|
|
for (int col = 0; col < buf->width(); ++col) {
|
|
buf->MutableDataY()[row * buf->StrideY() + col] = Y;
|
|
}
|
|
}
|
|
// Fill interleaving UV values.
|
|
for (int row = 0; row < buf->ChromaHeight(); row++) {
|
|
for (int col = 0; col < buf->StrideUV(); col += 2) {
|
|
int uv_index = row * buf->StrideUV() + col;
|
|
buf->MutableDataUV()[uv_index] = U;
|
|
buf->MutableDataUV()[uv_index + 1] = V;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST(NV12BufferTest, InitialData) {
|
|
constexpr int stride_y = 3;
|
|
constexpr int stride_uv = 4;
|
|
constexpr int width = 3;
|
|
constexpr int height = 3;
|
|
|
|
rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height));
|
|
EXPECT_EQ(width, nv12_buffer->width());
|
|
EXPECT_EQ(height, nv12_buffer->height());
|
|
EXPECT_EQ(stride_y, nv12_buffer->StrideY());
|
|
EXPECT_EQ(stride_uv, nv12_buffer->StrideUV());
|
|
EXPECT_EQ(2, nv12_buffer->ChromaWidth());
|
|
EXPECT_EQ(2, nv12_buffer->ChromaHeight());
|
|
}
|
|
|
|
TEST(NV12BufferTest, ReadPixels) {
|
|
constexpr int width = 3;
|
|
constexpr int height = 3;
|
|
|
|
rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height));
|
|
// Y = 1, U = 2, V = 3.
|
|
FillNV12Buffer(nv12_buffer);
|
|
for (int row = 0; row < height; row++) {
|
|
for (int col = 0; col < width; col++) {
|
|
EXPECT_EQ(1, GetY(nv12_buffer, col, row));
|
|
EXPECT_EQ(2, GetU(nv12_buffer, col, row));
|
|
EXPECT_EQ(3, GetV(nv12_buffer, col, row));
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST(NV12BufferTest, ToI420) {
|
|
constexpr int width = 3;
|
|
constexpr int height = 3;
|
|
constexpr int size_y = width * height;
|
|
constexpr int size_u = (width + 1) / 2 * (height + 1) / 2;
|
|
constexpr int size_v = (width + 1) / 2 * (height + 1) / 2;
|
|
rtc::scoped_refptr<I420Buffer> reference(I420Buffer::Create(width, height));
|
|
memset(reference->MutableDataY(), 8, size_y);
|
|
memset(reference->MutableDataU(), 4, size_u);
|
|
memset(reference->MutableDataV(), 2, size_v);
|
|
|
|
rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height));
|
|
// Convert the reference buffer to NV12.
|
|
memset(nv12_buffer->MutableDataY(), 8, size_y);
|
|
// Interleaving u/v values.
|
|
for (int i = 0; i < size_u + size_v; i += 2) {
|
|
nv12_buffer->MutableDataUV()[i] = 4;
|
|
nv12_buffer->MutableDataUV()[i + 1] = 2;
|
|
}
|
|
// Confirm YUV values are as expected.
|
|
for (int row = 0; row < height; row++) {
|
|
for (int col = 0; col < width; col++) {
|
|
EXPECT_EQ(8, GetY(nv12_buffer, col, row));
|
|
EXPECT_EQ(4, GetU(nv12_buffer, col, row));
|
|
EXPECT_EQ(2, GetV(nv12_buffer, col, row));
|
|
}
|
|
}
|
|
|
|
rtc::scoped_refptr<I420BufferInterface> i420_buffer(nv12_buffer->ToI420());
|
|
EXPECT_EQ(height, i420_buffer->height());
|
|
EXPECT_EQ(width, i420_buffer->width());
|
|
EXPECT_TRUE(test::FrameBufsEqual(reference, i420_buffer));
|
|
}
|
|
|
|
} // namespace webrtc
|