OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2016 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 "webrtc/modules/video_coding/utility/ivf_file_writer.h" |
| 12 |
| 13 #include <memory> |
| 14 |
| 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "webrtc/base/fileutils.h" |
| 17 #include "webrtc/base/logging.h" |
| 18 #include "webrtc/base/pathutils.h" |
| 19 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| 20 |
| 21 namespace webrtc { |
| 22 |
| 23 namespace { |
| 24 static const size_t kHeaderSize = 32; |
| 25 const size_t kFrameHeaderSize = 12; |
| 26 uint8_t dummy_payload[4] = {0, 1, 2, 3}; |
| 27 } // namespace |
| 28 |
| 29 class IvfFileWriterTest : public ::testing::Test { |
| 30 protected: |
| 31 void SetUp() override { |
| 32 ASSERT_TRUE(rtc::CreateUniqueFile(file_name_, false)); |
| 33 } |
| 34 |
| 35 bool WriteDummyTestFrames(int width, int height, int num_frames) { |
| 36 EncodedImage frame; |
| 37 frame._buffer = dummy_payload; |
| 38 frame._encodedWidth = width; |
| 39 frame._encodedHeight = height; |
| 40 for (int i = 0; i < num_frames; ++i) { |
| 41 frame._length = i % sizeof(dummy_payload); |
| 42 frame.ntp_time_ms_ = i; |
| 43 if (!file_writer_->WriteFrame(frame)) |
| 44 return false; |
| 45 } |
| 46 return true; |
| 47 } |
| 48 |
| 49 void VerifyIvfHeader(const uint8_t* data, |
| 50 const uint8_t fourcc[4], |
| 51 int width, |
| 52 int height, |
| 53 uint32_t num_frames) { |
| 54 uint8_t dkif[4] = {'D', 'K', 'I', 'F'}; |
| 55 EXPECT_EQ(0, memcmp(dkif, data, 4)); |
| 56 EXPECT_EQ(0, ByteReader<uint16_t>::ReadLittleEndian(&data[4])); |
| 57 EXPECT_EQ(32, ByteReader<uint16_t>::ReadLittleEndian(&data[6])); |
| 58 EXPECT_EQ(0, memcmp(fourcc, &data[8], 4)); |
| 59 EXPECT_EQ(width, ByteReader<uint16_t>::ReadLittleEndian(&data[12])); |
| 60 EXPECT_EQ(height, ByteReader<uint16_t>::ReadLittleEndian(&data[14])); |
| 61 EXPECT_EQ(1000u, ByteReader<uint32_t>::ReadLittleEndian(&data[16])); |
| 62 EXPECT_EQ(1u, ByteReader<uint32_t>::ReadLittleEndian(&data[20])); |
| 63 EXPECT_EQ(num_frames, ByteReader<uint32_t>::ReadLittleEndian(&data[24])); |
| 64 EXPECT_EQ(0u, ByteReader<uint32_t>::ReadLittleEndian(&data[28])); |
| 65 } |
| 66 |
| 67 void VerifyDummyTestFrames(const uint8_t* data, |
| 68 size_t size, |
| 69 uint32_t num_frames) { |
| 70 size_t bytes_read = 0; |
| 71 for (uint32_t i = 0; i < num_frames; ++i) { |
| 72 ASSERT_LE(bytes_read + kFrameHeaderSize, size); |
| 73 uint32_t frame_length = |
| 74 ByteReader<uint32_t>::ReadLittleEndian(&data[bytes_read]); |
| 75 EXPECT_EQ(i % 4, frame_length); |
| 76 uint64_t timestamp = |
| 77 ByteReader<uint64_t>::ReadLittleEndian(&data[bytes_read + 4]); |
| 78 EXPECT_EQ(i, timestamp); |
| 79 bytes_read += kFrameHeaderSize; |
| 80 |
| 81 ASSERT_LE(bytes_read + frame_length, size); |
| 82 EXPECT_EQ(0, memcmp(&data[bytes_read], dummy_payload, frame_length)); |
| 83 bytes_read += frame_length; |
| 84 } |
| 85 } |
| 86 |
| 87 void RunBasicFileStructureTest(RtpVideoCodecTypes codec_type, |
| 88 const uint8_t fourcc[4]) { |
| 89 rtc::MemoryStream* out_stream = new rtc::MemoryStream(); |
| 90 file_writer_ = IvfFileWriter::Open(out_stream, codec_type); |
| 91 ASSERT_TRUE(file_writer_.get()); |
| 92 const int kWidth = 320; |
| 93 const int kHeight = 240; |
| 94 const int kNumFrames = 257; |
| 95 EXPECT_TRUE(WriteDummyTestFrames(kWidth, kHeight, kNumFrames)); |
| 96 |
| 97 size_t size = 0; |
| 98 ASSERT_TRUE(out_stream->GetSize(&size)); |
| 99 ASSERT_GE(size, kHeaderSize); |
| 100 EXPECT_TRUE(file_writer_->Close()); |
| 101 |
| 102 const uint8_t* out_buffer = |
| 103 reinterpret_cast<const uint8_t*>(out_stream->GetBuffer()); |
| 104 VerifyIvfHeader(out_buffer, fourcc, kWidth, kHeight, kNumFrames); |
| 105 VerifyDummyTestFrames(&out_buffer[kHeaderSize], size - kHeaderSize, |
| 106 kNumFrames); |
| 107 |
| 108 EXPECT_TRUE(file_writer_->Close()); |
| 109 } |
| 110 |
| 111 rtc::Pathname file_name_; |
| 112 std::unique_ptr<IvfFileWriter> file_writer_; |
| 113 }; |
| 114 |
| 115 TEST_F(IvfFileWriterTest, RemovesUnusedFile) { |
| 116 file_writer_ = IvfFileWriter::Open(file_name_, kRtpVideoVp8); |
| 117 ASSERT_TRUE(file_writer_.get()); |
| 118 rtc::FilesystemInterface* file_system = rtc::Filesystem::default_filesystem(); |
| 119 EXPECT_FALSE(file_system->IsAbsent(file_name_)); |
| 120 EXPECT_TRUE(file_writer_->Close()); |
| 121 EXPECT_TRUE(file_system->IsAbsent(file_name_)); |
| 122 EXPECT_FALSE(file_writer_->Close()); // Can't close twice. |
| 123 } |
| 124 |
| 125 TEST_F(IvfFileWriterTest, WritesBasicVP8File) { |
| 126 const uint8_t fourcc[4] = {'V', 'P', '8', '0'}; |
| 127 RunBasicFileStructureTest(kRtpVideoVp8, fourcc); |
| 128 } |
| 129 |
| 130 TEST_F(IvfFileWriterTest, WritesBasicVP9File) { |
| 131 const uint8_t fourcc[4] = {'V', 'P', '9', '0'}; |
| 132 RunBasicFileStructureTest(kRtpVideoVp9, fourcc); |
| 133 } |
| 134 |
| 135 TEST_F(IvfFileWriterTest, WritesBasicH264File) { |
| 136 const uint8_t fourcc[4] = {'H', '2', '6', '4'}; |
| 137 RunBasicFileStructureTest(kRtpVideoH264, fourcc); |
| 138 } |
| 139 |
| 140 } // namespace webrtc |
OLD | NEW |