1 /*
2  *  Copyright (c) 2015 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 <stdio.h>
12 #include <string>
13 
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "webrtc/base/scoped_ptr.h"
16 #include "webrtc/test/frame_generator.h"
17 #include "webrtc/test/testsupport/fileutils.h"
18 
19 namespace webrtc {
20 namespace test {
21 
22 static const int kFrameWidth = 4;
23 static const int kFrameHeight = 4;
24 
25 class FrameGeneratorTest : public ::testing::Test {
26  public:
SetUp()27   void SetUp() override {
28     two_frame_filename_ =
29         test::TempFilename(test::OutputPath(), "2_frame_yuv_file");
30     one_frame_filename_ =
31         test::TempFilename(test::OutputPath(), "1_frame_yuv_file");
32 
33     FILE* file = fopen(two_frame_filename_.c_str(), "wb");
34     WriteYuvFile(file, 0, 0, 0);
35     WriteYuvFile(file, 127, 127, 127);
36     fclose(file);
37     file = fopen(one_frame_filename_.c_str(), "wb");
38     WriteYuvFile(file, 255, 255, 255);
39     fclose(file);
40   }
TearDown()41   void TearDown() override {
42     remove(one_frame_filename_.c_str());
43     remove(two_frame_filename_.c_str());
44   }
45 
46  protected:
WriteYuvFile(FILE * file,uint8_t y,uint8_t u,uint8_t v)47   void WriteYuvFile(FILE* file, uint8_t y, uint8_t u, uint8_t v) {
48     assert(file);
49     rtc::scoped_ptr<uint8_t[]> plane_buffer(new uint8_t[y_size]);
50     memset(plane_buffer.get(), y, y_size);
51     fwrite(plane_buffer.get(), 1, y_size, file);
52     memset(plane_buffer.get(), u, uv_size);
53     fwrite(plane_buffer.get(), 1, uv_size, file);
54     memset(plane_buffer.get(), v, uv_size);
55     fwrite(plane_buffer.get(), 1, uv_size, file);
56   }
57 
CheckFrameAndMutate(VideoFrame * frame,uint8_t y,uint8_t u,uint8_t v)58   void CheckFrameAndMutate(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v) {
59     // Check that frame is valid, has the correct color and timestamp are clean.
60     ASSERT_NE(nullptr, frame);
61     uint8_t* buffer;
62     ASSERT_EQ(y_size, frame->allocated_size(PlaneType::kYPlane));
63     buffer = frame->buffer(PlaneType::kYPlane);
64     for (int i = 0; i < y_size; ++i)
65       ASSERT_EQ(y, buffer[i]);
66     ASSERT_EQ(uv_size, frame->allocated_size(PlaneType::kUPlane));
67     buffer = frame->buffer(PlaneType::kUPlane);
68     for (int i = 0; i < uv_size; ++i)
69       ASSERT_EQ(u, buffer[i]);
70     ASSERT_EQ(uv_size, frame->allocated_size(PlaneType::kVPlane));
71     buffer = frame->buffer(PlaneType::kVPlane);
72     for (int i = 0; i < uv_size; ++i)
73       ASSERT_EQ(v, buffer[i]);
74     EXPECT_EQ(0, frame->ntp_time_ms());
75     EXPECT_EQ(0, frame->render_time_ms());
76     EXPECT_EQ(0u, frame->timestamp());
77 
78     // Mutate to something arbitrary non-zero.
79     frame->set_ntp_time_ms(11);
80     frame->set_render_time_ms(12);
81     frame->set_timestamp(13);
82   }
83 
84   std::string two_frame_filename_;
85   std::string one_frame_filename_;
86   const int y_size = kFrameWidth * kFrameHeight;
87   const int uv_size = ((kFrameHeight + 1) / 2) * ((kFrameWidth + 1) / 2);
88 };
89 
TEST_F(FrameGeneratorTest,SingleFrameFile)90 TEST_F(FrameGeneratorTest, SingleFrameFile) {
91   rtc::scoped_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
92       std::vector<std::string>(1, one_frame_filename_), kFrameWidth,
93       kFrameHeight, 1));
94   CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
95   CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
96 }
97 
TEST_F(FrameGeneratorTest,TwoFrameFile)98 TEST_F(FrameGeneratorTest, TwoFrameFile) {
99   rtc::scoped_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
100       std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
101       kFrameHeight, 1));
102   CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
103   CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
104   CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
105 }
106 
TEST_F(FrameGeneratorTest,MultipleFrameFiles)107 TEST_F(FrameGeneratorTest, MultipleFrameFiles) {
108   std::vector<std::string> files;
109   files.push_back(two_frame_filename_);
110   files.push_back(one_frame_filename_);
111 
112   rtc::scoped_ptr<FrameGenerator> generator(
113       FrameGenerator::CreateFromYuvFile(files, kFrameWidth, kFrameHeight, 1));
114   CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
115   CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
116   CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
117   CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
118 }
119 
TEST_F(FrameGeneratorTest,TwoFrameFileWithRepeat)120 TEST_F(FrameGeneratorTest, TwoFrameFileWithRepeat) {
121   const int kRepeatCount = 3;
122   rtc::scoped_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
123       std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
124       kFrameHeight, kRepeatCount));
125   for (int i = 0; i < kRepeatCount; ++i)
126     CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
127   for (int i = 0; i < kRepeatCount; ++i)
128     CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
129   CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
130 }
131 
TEST_F(FrameGeneratorTest,MultipleFrameFilesWithRepeat)132 TEST_F(FrameGeneratorTest, MultipleFrameFilesWithRepeat) {
133   const int kRepeatCount = 3;
134   std::vector<std::string> files;
135   files.push_back(two_frame_filename_);
136   files.push_back(one_frame_filename_);
137   rtc::scoped_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
138       files, kFrameWidth, kFrameHeight, kRepeatCount));
139   for (int i = 0; i < kRepeatCount; ++i)
140     CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
141   for (int i = 0; i < kRepeatCount; ++i)
142     CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
143   for (int i = 0; i < kRepeatCount; ++i)
144     CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
145   CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
146 }
147 
148 }  // namespace test
149 }  // namespace webrtc
150