Mark WebGL conformance test 'texture-upload-size' as flaky.
[chromium-blink-merge.git] / media / formats / mp2t / es_parser_h264_unittest.cc
blob5228b6e8a1e58884cae9950accfe0297530353f1
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <sstream>
6 #include <string>
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/time/time.h"
13 #include "media/base/stream_parser_buffer.h"
14 #include "media/filters/h264_parser.h"
15 #include "media/formats/mp2t/es_parser_h264.h"
16 #include "media/formats/mp2t/es_parser_test_base.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace media {
20 class VideoDecoderConfig;
22 namespace mp2t {
24 class EsParserH264Test : public EsParserTestBase,
25 public testing::Test {
26 public:
27 EsParserH264Test() {}
28 virtual ~EsParserH264Test() {}
30 protected:
31 void LoadH264Stream(const char* filename);
32 void GetPesTimestamps(std::vector<Packet>* pes_packets);
33 bool Process(const std::vector<Packet>& pes_packets, bool force_timing);
34 void CheckAccessUnits();
36 // Access units of the stream with AUD NALUs.
37 std::vector<Packet> access_units_;
39 private:
40 // Get the offset of the start of each access unit of |stream_|.
41 // This function assumes there is only one slice per access unit.
42 // This is a very simplified access unit segmenter that is good
43 // enough for unit tests.
44 void GetAccessUnits();
46 // Insert an AUD before each access unit.
47 // Update |stream_| and |access_units_| accordingly.
48 void InsertAUD();
50 DISALLOW_COPY_AND_ASSIGN(EsParserH264Test);
53 void EsParserH264Test::LoadH264Stream(const char* filename) {
54 // Load the input H264 file and segment it into access units.
55 LoadStream(filename);
56 GetAccessUnits();
57 ASSERT_GT(access_units_.size(), 0u);
59 // Insert AUDs into the stream.
60 InsertAUD();
62 // Generate some timestamps based on a 25fps stream.
63 for (size_t k = 0; k < access_units_.size(); k++)
64 access_units_[k].pts = base::TimeDelta::FromMilliseconds(k * 40u);
67 void EsParserH264Test::GetAccessUnits() {
68 access_units_.resize(0);
69 bool start_access_unit = true;
71 // In a first pass, retrieve the offsets of all access units.
72 size_t offset = 0;
73 while (true) {
74 // Find the next start code.
75 off_t relative_offset = 0;
76 off_t start_code_size = 0;
77 bool success = H264Parser::FindStartCode(
78 &stream_[offset], stream_.size() - offset,
79 &relative_offset, &start_code_size);
80 if (!success)
81 break;
82 offset += relative_offset;
84 if (start_access_unit) {
85 Packet cur_access_unit;
86 cur_access_unit.offset = offset;
87 access_units_.push_back(cur_access_unit);
88 start_access_unit = false;
91 // Get the NALU type.
92 offset += start_code_size;
93 if (offset >= stream_.size())
94 break;
95 int nal_unit_type = stream_[offset] & 0x1f;
97 // We assume there is only one slice per access unit.
98 if (nal_unit_type == H264NALU::kIDRSlice ||
99 nal_unit_type == H264NALU::kNonIDRSlice) {
100 start_access_unit = true;
104 ComputePacketSize(&access_units_);
107 void EsParserH264Test::InsertAUD() {
108 uint8 aud[] = { 0x00, 0x00, 0x01, 0x09 };
110 std::vector<uint8> stream_with_aud(
111 stream_.size() + access_units_.size() * sizeof(aud));
112 std::vector<EsParserTestBase::Packet> access_units_with_aud(
113 access_units_.size());
115 size_t offset = 0;
116 for (size_t k = 0; k < access_units_.size(); k++) {
117 access_units_with_aud[k].offset = offset;
118 access_units_with_aud[k].size = access_units_[k].size + sizeof(aud);
120 memcpy(&stream_with_aud[offset], aud, sizeof(aud));
121 offset += sizeof(aud);
123 memcpy(&stream_with_aud[offset],
124 &stream_[access_units_[k].offset], access_units_[k].size);
125 offset += access_units_[k].size;
128 // Update the stream and access units used for the test.
129 stream_ = stream_with_aud;
130 access_units_ = access_units_with_aud;
133 void EsParserH264Test::GetPesTimestamps(std::vector<Packet>* pes_packets_ptr) {
134 DCHECK(pes_packets_ptr);
135 const std::vector<Packet>& pes_packets = *pes_packets_ptr;
137 // Default: set to a negative timestamp to be able to differentiate from
138 // real timestamps.
139 // Note: we don't use kNoTimestamp() here since this one has already
140 // a special meaning in EsParserH264. The negative timestamps should be
141 // ultimately discarded by the H264 parser since not relevant.
142 for (size_t k = 0; k < pes_packets.size(); k++) {
143 (*pes_packets_ptr)[k].pts = base::TimeDelta::FromMilliseconds(-1);
146 // Set a valid timestamp for PES packets which include the start
147 // of an H264 access unit.
148 size_t pes_idx = 0;
149 for (size_t k = 0; k < access_units_.size(); k++) {
150 for (; pes_idx < pes_packets.size(); pes_idx++) {
151 size_t pes_start = pes_packets[pes_idx].offset;
152 size_t pes_end = pes_packets[pes_idx].offset + pes_packets[pes_idx].size;
153 if (pes_start <= access_units_[k].offset &&
154 pes_end > access_units_[k].offset) {
155 (*pes_packets_ptr)[pes_idx].pts = access_units_[k].pts;
156 break;
162 bool EsParserH264Test::Process(
163 const std::vector<Packet>& pes_packets,
164 bool force_timing) {
165 EsParserH264 es_parser(
166 base::Bind(&EsParserH264Test::NewVideoConfig, base::Unretained(this)),
167 base::Bind(&EsParserH264Test::EmitBuffer, base::Unretained(this)));
168 return ProcessPesPackets(&es_parser, pes_packets, force_timing);
171 void EsParserH264Test::CheckAccessUnits() {
172 EXPECT_EQ(buffer_count_, access_units_.size());
174 std::stringstream buffer_timestamps_stream;
175 for (size_t k = 0; k < access_units_.size(); k++) {
176 buffer_timestamps_stream << "("
177 << access_units_[k].pts.InMilliseconds()
178 << ") ";
180 std::string buffer_timestamps = buffer_timestamps_stream.str();
181 base::TrimWhitespaceASCII(
182 buffer_timestamps, base::TRIM_ALL, &buffer_timestamps);
183 EXPECT_EQ(buffer_timestamps_, buffer_timestamps);
186 TEST_F(EsParserH264Test, OneAccessUnitPerPes) {
187 LoadH264Stream("bear.h264");
189 // One to one equivalence between PES packets and access units.
190 std::vector<Packet> pes_packets(access_units_);
191 GetPesTimestamps(&pes_packets);
193 // Process each PES packet.
194 EXPECT_TRUE(Process(pes_packets, false));
195 CheckAccessUnits();
198 TEST_F(EsParserH264Test, NonAlignedPesPacket) {
199 LoadH264Stream("bear.h264");
201 // Generate the PES packets.
202 std::vector<Packet> pes_packets;
203 Packet cur_pes_packet;
204 cur_pes_packet.offset = 0;
205 for (size_t k = 0; k < access_units_.size(); k++) {
206 pes_packets.push_back(cur_pes_packet);
208 // The current PES packet includes the remaining bytes of the previous
209 // access unit and some bytes of the current access unit
210 // (487 bytes in this unit test but no more than the current access unit
211 // size).
212 cur_pes_packet.offset = access_units_[k].offset +
213 std::min<size_t>(487u, access_units_[k].size);
215 ComputePacketSize(&pes_packets);
216 GetPesTimestamps(&pes_packets);
218 // Process each PES packet.
219 EXPECT_TRUE(Process(pes_packets, false));
220 CheckAccessUnits();
223 TEST_F(EsParserH264Test, SeveralPesPerAccessUnit) {
224 LoadH264Stream("bear.h264");
226 // Get the minimum size of an access unit.
227 size_t min_access_unit_size = stream_.size();
228 for (size_t k = 0; k < access_units_.size(); k++) {
229 if (min_access_unit_size >= access_units_[k].size)
230 min_access_unit_size = access_units_[k].size;
233 // Use a small PES packet size or the minimum access unit size
234 // if it is even smaller.
235 size_t pes_size = 512;
236 if (min_access_unit_size < pes_size)
237 pes_size = min_access_unit_size;
239 std::vector<Packet> pes_packets;
240 Packet cur_pes_packet;
241 cur_pes_packet.offset = 0;
242 while (cur_pes_packet.offset < stream_.size()) {
243 pes_packets.push_back(cur_pes_packet);
244 cur_pes_packet.offset += pes_size;
246 ComputePacketSize(&pes_packets);
247 GetPesTimestamps(&pes_packets);
249 // Process each PES packet.
250 EXPECT_TRUE(Process(pes_packets, false));
251 CheckAccessUnits();
253 // Process PES packets forcing timings for each PES packet.
254 EXPECT_TRUE(Process(pes_packets, true));
255 CheckAccessUnits();
258 } // namespace mp2t
259 } // namespace media