1 /*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "api/video/nv12_buffer.h"
12
13 #include "api/video/i420_buffer.h"
14 #include "test/frame_utils.h"
15 #include "test/gmock.h"
16 #include "test/gtest.h"
17
18 namespace webrtc {
19
20 namespace {
GetY(rtc::scoped_refptr<NV12BufferInterface> buf,int col,int row)21 int GetY(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) {
22 return buf->DataY()[row * buf->StrideY() + col];
23 }
24
GetU(rtc::scoped_refptr<NV12BufferInterface> buf,int col,int row)25 int GetU(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) {
26 return buf->DataUV()[(row / 2) * buf->StrideUV() + (col / 2) * 2];
27 }
28
GetV(rtc::scoped_refptr<NV12BufferInterface> buf,int col,int row)29 int GetV(rtc::scoped_refptr<NV12BufferInterface> buf, int col, int row) {
30 return buf->DataUV()[(row / 2) * buf->StrideUV() + (col / 2) * 2 + 1];
31 }
32
FillNV12Buffer(rtc::scoped_refptr<NV12Buffer> buf)33 void FillNV12Buffer(rtc::scoped_refptr<NV12Buffer> buf) {
34 const uint8_t Y = 1;
35 const uint8_t U = 2;
36 const uint8_t V = 3;
37 for (int row = 0; row < buf->height(); ++row) {
38 for (int col = 0; col < buf->width(); ++col) {
39 buf->MutableDataY()[row * buf->StrideY() + col] = Y;
40 }
41 }
42 // Fill interleaving UV values.
43 for (int row = 0; row < buf->ChromaHeight(); row++) {
44 for (int col = 0; col < buf->StrideUV(); col += 2) {
45 int uv_index = row * buf->StrideUV() + col;
46 buf->MutableDataUV()[uv_index] = U;
47 buf->MutableDataUV()[uv_index + 1] = V;
48 }
49 }
50 }
51
52 } // namespace
53
TEST(NV12BufferTest,InitialData)54 TEST(NV12BufferTest, InitialData) {
55 constexpr int stride_y = 3;
56 constexpr int stride_uv = 4;
57 constexpr int width = 3;
58 constexpr int height = 3;
59
60 rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height));
61 EXPECT_EQ(width, nv12_buffer->width());
62 EXPECT_EQ(height, nv12_buffer->height());
63 EXPECT_EQ(stride_y, nv12_buffer->StrideY());
64 EXPECT_EQ(stride_uv, nv12_buffer->StrideUV());
65 EXPECT_EQ(2, nv12_buffer->ChromaWidth());
66 EXPECT_EQ(2, nv12_buffer->ChromaHeight());
67 }
68
TEST(NV12BufferTest,ReadPixels)69 TEST(NV12BufferTest, ReadPixels) {
70 constexpr int width = 3;
71 constexpr int height = 3;
72
73 rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height));
74 // Y = 1, U = 2, V = 3.
75 FillNV12Buffer(nv12_buffer);
76 for (int row = 0; row < height; row++) {
77 for (int col = 0; col < width; col++) {
78 EXPECT_EQ(1, GetY(nv12_buffer, col, row));
79 EXPECT_EQ(2, GetU(nv12_buffer, col, row));
80 EXPECT_EQ(3, GetV(nv12_buffer, col, row));
81 }
82 }
83 }
84
TEST(NV12BufferTest,ToI420)85 TEST(NV12BufferTest, ToI420) {
86 constexpr int width = 3;
87 constexpr int height = 3;
88 constexpr int size_y = width * height;
89 constexpr int size_u = (width + 1) / 2 * (height + 1) / 2;
90 constexpr int size_v = (width + 1) / 2 * (height + 1) / 2;
91 rtc::scoped_refptr<I420Buffer> reference(I420Buffer::Create(width, height));
92 memset(reference->MutableDataY(), 8, size_y);
93 memset(reference->MutableDataU(), 4, size_u);
94 memset(reference->MutableDataV(), 2, size_v);
95
96 rtc::scoped_refptr<NV12Buffer> nv12_buffer(NV12Buffer::Create(width, height));
97 // Convert the reference buffer to NV12.
98 memset(nv12_buffer->MutableDataY(), 8, size_y);
99 // Interleaving u/v values.
100 for (int i = 0; i < size_u + size_v; i += 2) {
101 nv12_buffer->MutableDataUV()[i] = 4;
102 nv12_buffer->MutableDataUV()[i + 1] = 2;
103 }
104 // Confirm YUV values are as expected.
105 for (int row = 0; row < height; row++) {
106 for (int col = 0; col < width; col++) {
107 EXPECT_EQ(8, GetY(nv12_buffer, col, row));
108 EXPECT_EQ(4, GetU(nv12_buffer, col, row));
109 EXPECT_EQ(2, GetV(nv12_buffer, col, row));
110 }
111 }
112
113 rtc::scoped_refptr<I420BufferInterface> i420_buffer(nv12_buffer->ToI420());
114 EXPECT_EQ(height, i420_buffer->height());
115 EXPECT_EQ(width, i420_buffer->width());
116 EXPECT_TRUE(test::FrameBufsEqual(reference, i420_buffer));
117 }
118
119 } // namespace webrtc
120