OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <string.h> | 5 #include <string.h> |
6 | 6 |
7 #include "base/basictypes.h" | |
8 #include "base/strings/string_split.h" | 7 #include "base/strings/string_split.h" |
9 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
10 #include "media/base/decrypt_config.h" | 9 #include "media/base/decrypt_config.h" |
11 #include "media/base/stream_parser_buffer.h" | 10 #include "media/base/stream_parser_buffer.h" |
12 #include "media/filters/h264_parser.h" | 11 #include "media/filters/h264_parser.h" |
13 #include "media/formats/mp4/avc.h" | 12 #include "media/formats/mp4/avc.h" |
14 #include "media/formats/mp4/box_definitions.h" | 13 #include "media/formats/mp4/box_definitions.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
16 | 15 |
17 namespace media { | 16 namespace media { |
18 namespace mp4 { | 17 namespace mp4 { |
19 | 18 |
20 static const uint8 kNALU1[] = { 0x01, 0x02, 0x03 }; | 19 static const uint8_t kNALU1[] = {0x01, 0x02, 0x03}; |
21 static const uint8 kNALU2[] = { 0x04, 0x05, 0x06, 0x07 }; | 20 static const uint8_t kNALU2[] = {0x04, 0x05, 0x06, 0x07}; |
22 static const uint8 kExpected[] = { | 21 static const uint8_t kExpected[] = {0x00, 0x00, 0x00, 0x01, 0x01, |
23 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, | 22 0x02, 0x03, 0x00, 0x00, 0x00, |
24 0x00, 0x00, 0x00, 0x01, 0x04, 0x05, 0x06, 0x07 }; | 23 0x01, 0x04, 0x05, 0x06, 0x07}; |
25 | 24 |
26 static const uint8 kExpectedParamSets[] = { | 25 static const uint8_t kExpectedParamSets[] = { |
27 0x00, 0x00, 0x00, 0x01, 0x67, 0x12, | 26 0x00, 0x00, 0x00, 0x01, 0x67, 0x12, 0x00, 0x00, 0x00, 0x01, |
28 0x00, 0x00, 0x00, 0x01, 0x67, 0x34, | 27 0x67, 0x34, 0x00, 0x00, 0x00, 0x01, 0x68, 0x56, 0x78}; |
29 0x00, 0x00, 0x00, 0x01, 0x68, 0x56, 0x78}; | |
30 | 28 |
31 static H264NALU::Type StringToNALUType(const std::string& name) { | 29 static H264NALU::Type StringToNALUType(const std::string& name) { |
32 if (name == "P") | 30 if (name == "P") |
33 return H264NALU::kNonIDRSlice; | 31 return H264NALU::kNonIDRSlice; |
34 | 32 |
35 if (name == "I") | 33 if (name == "I") |
36 return H264NALU::kIDRSlice; | 34 return H264NALU::kIDRSlice; |
37 | 35 |
38 if (name == "SEI") | 36 if (name == "SEI") |
39 return H264NALU::kSEIMessage; | 37 return H264NALU::kSEIMessage; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 case H264NALU::kReserved18: | 102 case H264NALU::kReserved18: |
105 case H264NALU::kCodedSliceAux: | 103 case H264NALU::kCodedSliceAux: |
106 case H264NALU::kCodedSliceExtension: | 104 case H264NALU::kCodedSliceExtension: |
107 CHECK(false) << "Unexpected type: " << type; | 105 CHECK(false) << "Unexpected type: " << type; |
108 break; | 106 break; |
109 }; | 107 }; |
110 | 108 |
111 return "UnsupportedType"; | 109 return "UnsupportedType"; |
112 } | 110 } |
113 | 111 |
114 static void WriteStartCodeAndNALUType(std::vector<uint8>* buffer, | 112 static void WriteStartCodeAndNALUType(std::vector<uint8_t>* buffer, |
115 const std::string& nal_unit_type) { | 113 const std::string& nal_unit_type) { |
116 buffer->push_back(0x00); | 114 buffer->push_back(0x00); |
117 buffer->push_back(0x00); | 115 buffer->push_back(0x00); |
118 buffer->push_back(0x00); | 116 buffer->push_back(0x00); |
119 buffer->push_back(0x01); | 117 buffer->push_back(0x01); |
120 buffer->push_back(StringToNALUType(nal_unit_type)); | 118 buffer->push_back(StringToNALUType(nal_unit_type)); |
121 } | 119 } |
122 | 120 |
123 // Input string should be one or more NALU types separated with spaces or | 121 // Input string should be one or more NALU types separated with spaces or |
124 // commas. NALU grouped together and separated by commas are placed into the | 122 // commas. NALU grouped together and separated by commas are placed into the |
125 // same subsample, NALU groups separated by spaces are placed into separate | 123 // same subsample, NALU groups separated by spaces are placed into separate |
126 // subsamples. | 124 // subsamples. |
127 // For example: input string "SPS PPS I" produces Annex B buffer containing | 125 // For example: input string "SPS PPS I" produces Annex B buffer containing |
128 // SPS, PPS and I NALUs, each in a separate subsample. While input string | 126 // SPS, PPS and I NALUs, each in a separate subsample. While input string |
129 // "SPS,PPS I" produces Annex B buffer where the first subsample contains SPS | 127 // "SPS,PPS I" produces Annex B buffer where the first subsample contains SPS |
130 // and PPS NALUs and the second subsample contains the I-slice NALU. | 128 // and PPS NALUs and the second subsample contains the I-slice NALU. |
131 // The output buffer will contain a valid-looking Annex B (it's valid-looking in | 129 // The output buffer will contain a valid-looking Annex B (it's valid-looking in |
132 // the sense that it has start codes and correct NALU types, but the actual NALU | 130 // the sense that it has start codes and correct NALU types, but the actual NALU |
133 // payload is junk). | 131 // payload is junk). |
134 void StringToAnnexB(const std::string& str, std::vector<uint8>* buffer, | 132 void StringToAnnexB(const std::string& str, |
| 133 std::vector<uint8_t>* buffer, |
135 std::vector<SubsampleEntry>* subsamples) { | 134 std::vector<SubsampleEntry>* subsamples) { |
136 DCHECK(!str.empty()); | 135 DCHECK(!str.empty()); |
137 | 136 |
138 std::vector<std::string> subsample_specs = base::SplitString( | 137 std::vector<std::string> subsample_specs = base::SplitString( |
139 str, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | 138 str, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
140 EXPECT_GT(subsample_specs.size(), 0u); | 139 EXPECT_GT(subsample_specs.size(), 0u); |
141 | 140 |
142 buffer->clear(); | 141 buffer->clear(); |
143 for (size_t i = 0; i < subsample_specs.size(); ++i) { | 142 for (size_t i = 0; i < subsample_specs.size(); ++i) { |
144 SubsampleEntry entry; | 143 SubsampleEntry entry; |
(...skipping 22 matching lines...) Expand all Loading... |
167 } | 166 } |
168 | 167 |
169 entry.cypher_bytes = buffer->size() - start - entry.clear_bytes; | 168 entry.cypher_bytes = buffer->size() - start - entry.clear_bytes; |
170 | 169 |
171 if (subsamples) { | 170 if (subsamples) { |
172 subsamples->push_back(entry); | 171 subsamples->push_back(entry); |
173 } | 172 } |
174 } | 173 } |
175 } | 174 } |
176 | 175 |
177 std::string AnnexBToString(const std::vector<uint8>& buffer, | 176 std::string AnnexBToString(const std::vector<uint8_t>& buffer, |
178 const std::vector<SubsampleEntry>& subsamples) { | 177 const std::vector<SubsampleEntry>& subsamples) { |
179 std::stringstream ss; | 178 std::stringstream ss; |
180 | 179 |
181 H264Parser parser; | 180 H264Parser parser; |
182 parser.SetEncryptedStream(&buffer[0], buffer.size(), subsamples); | 181 parser.SetEncryptedStream(&buffer[0], buffer.size(), subsamples); |
183 | 182 |
184 H264NALU nalu; | 183 H264NALU nalu; |
185 bool first = true; | 184 bool first = true; |
186 size_t current_subsample_index = 0; | 185 size_t current_subsample_index = 0; |
187 while (parser.AdvanceToNextNALU(&nalu) == H264Parser::kOk) { | 186 while (parser.AdvanceToNextNALU(&nalu) == H264Parser::kOk) { |
188 size_t subsample_index = AVC::FindSubsampleIndex(buffer, &subsamples, | 187 size_t subsample_index = AVC::FindSubsampleIndex(buffer, &subsamples, |
189 nalu.data); | 188 nalu.data); |
190 if (!first) { | 189 if (!first) { |
191 ss << (subsample_index == current_subsample_index ? "," : " "); | 190 ss << (subsample_index == current_subsample_index ? "," : " "); |
192 } else { | 191 } else { |
193 DCHECK_EQ(subsample_index, current_subsample_index); | 192 DCHECK_EQ(subsample_index, current_subsample_index); |
194 first = false; | 193 first = false; |
195 } | 194 } |
196 | 195 |
197 ss << NALUTypeToString(nalu.nal_unit_type); | 196 ss << NALUTypeToString(nalu.nal_unit_type); |
198 current_subsample_index = subsample_index; | 197 current_subsample_index = subsample_index; |
199 } | 198 } |
200 return ss.str(); | 199 return ss.str(); |
201 } | 200 } |
202 | 201 |
203 class AVCConversionTest : public testing::TestWithParam<int> { | 202 class AVCConversionTest : public testing::TestWithParam<int> { |
204 protected: | 203 protected: |
205 void WriteLength(int length_size, int length, std::vector<uint8>* buf) { | 204 void WriteLength(int length_size, int length, std::vector<uint8_t>* buf) { |
206 DCHECK_GE(length, 0); | 205 DCHECK_GE(length, 0); |
207 DCHECK_LE(length, 255); | 206 DCHECK_LE(length, 255); |
208 | 207 |
209 for (int i = 1; i < length_size; i++) | 208 for (int i = 1; i < length_size; i++) |
210 buf->push_back(0); | 209 buf->push_back(0); |
211 buf->push_back(length); | 210 buf->push_back(length); |
212 } | 211 } |
213 | 212 |
214 void MakeInputForLength(int length_size, std::vector<uint8>* buf) { | 213 void MakeInputForLength(int length_size, std::vector<uint8_t>* buf) { |
215 buf->clear(); | 214 buf->clear(); |
216 | 215 |
217 WriteLength(length_size, sizeof(kNALU1), buf); | 216 WriteLength(length_size, sizeof(kNALU1), buf); |
218 buf->insert(buf->end(), kNALU1, kNALU1 + sizeof(kNALU1)); | 217 buf->insert(buf->end(), kNALU1, kNALU1 + sizeof(kNALU1)); |
219 | 218 |
220 WriteLength(length_size, sizeof(kNALU2), buf); | 219 WriteLength(length_size, sizeof(kNALU2), buf); |
221 buf->insert(buf->end(), kNALU2, kNALU2 + sizeof(kNALU2)); | 220 buf->insert(buf->end(), kNALU2, kNALU2 + sizeof(kNALU2)); |
222 } | 221 } |
223 | 222 |
224 }; | 223 }; |
225 | 224 |
226 TEST_P(AVCConversionTest, ParseCorrectly) { | 225 TEST_P(AVCConversionTest, ParseCorrectly) { |
227 std::vector<uint8> buf; | 226 std::vector<uint8_t> buf; |
228 std::vector<SubsampleEntry> subsamples; | 227 std::vector<SubsampleEntry> subsamples; |
229 MakeInputForLength(GetParam(), &buf); | 228 MakeInputForLength(GetParam(), &buf); |
230 EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, &subsamples)); | 229 EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, &subsamples)); |
231 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)); | 230 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)); |
232 EXPECT_EQ(buf.size(), sizeof(kExpected)); | 231 EXPECT_EQ(buf.size(), sizeof(kExpected)); |
233 EXPECT_EQ(0, memcmp(kExpected, &buf[0], sizeof(kExpected))); | 232 EXPECT_EQ(0, memcmp(kExpected, &buf[0], sizeof(kExpected))); |
234 EXPECT_EQ("P,SDC", AnnexBToString(buf, subsamples)); | 233 EXPECT_EQ("P,SDC", AnnexBToString(buf, subsamples)); |
235 } | 234 } |
236 | 235 |
237 // Intentionally write NALU sizes that are larger than the buffer. | 236 // Intentionally write NALU sizes that are larger than the buffer. |
238 TEST_P(AVCConversionTest, NALUSizeTooLarge) { | 237 TEST_P(AVCConversionTest, NALUSizeTooLarge) { |
239 std::vector<uint8> buf; | 238 std::vector<uint8_t> buf; |
240 WriteLength(GetParam(), 10 * sizeof(kNALU1), &buf); | 239 WriteLength(GetParam(), 10 * sizeof(kNALU1), &buf); |
241 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); | 240 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); |
242 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); | 241 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); |
243 } | 242 } |
244 | 243 |
245 TEST_P(AVCConversionTest, NALUSizeIsZero) { | 244 TEST_P(AVCConversionTest, NALUSizeIsZero) { |
246 std::vector<uint8> buf; | 245 std::vector<uint8_t> buf; |
247 WriteLength(GetParam(), 0, &buf); | 246 WriteLength(GetParam(), 0, &buf); |
248 | 247 |
249 WriteLength(GetParam(), sizeof(kNALU1), &buf); | 248 WriteLength(GetParam(), sizeof(kNALU1), &buf); |
250 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); | 249 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); |
251 | 250 |
252 WriteLength(GetParam(), 0, &buf); | 251 WriteLength(GetParam(), 0, &buf); |
253 | 252 |
254 WriteLength(GetParam(), sizeof(kNALU2), &buf); | 253 WriteLength(GetParam(), sizeof(kNALU2), &buf); |
255 buf.insert(buf.end(), kNALU2, kNALU2 + sizeof(kNALU2)); | 254 buf.insert(buf.end(), kNALU2, kNALU2 + sizeof(kNALU2)); |
256 | 255 |
257 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); | 256 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); |
258 } | 257 } |
259 | 258 |
260 TEST_P(AVCConversionTest, SubsampleSizesUpdatedAfterAnnexBConversion) { | 259 TEST_P(AVCConversionTest, SubsampleSizesUpdatedAfterAnnexBConversion) { |
261 std::vector<uint8> buf; | 260 std::vector<uint8_t> buf; |
262 std::vector<SubsampleEntry> subsamples; | 261 std::vector<SubsampleEntry> subsamples; |
263 SubsampleEntry subsample; | 262 SubsampleEntry subsample; |
264 | 263 |
265 // Write the first subsample, consisting of only one NALU | 264 // Write the first subsample, consisting of only one NALU |
266 WriteLength(GetParam(), sizeof(kNALU1), &buf); | 265 WriteLength(GetParam(), sizeof(kNALU1), &buf); |
267 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); | 266 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); |
268 | 267 |
269 subsample.clear_bytes = GetParam() + sizeof(kNALU1); | 268 subsample.clear_bytes = GetParam() + sizeof(kNALU1); |
270 subsample.cypher_bytes = 0; | 269 subsample.cypher_bytes = 0; |
271 subsamples.push_back(subsample); | 270 subsamples.push_back(subsample); |
(...skipping 19 matching lines...) Expand all Loading... |
291 EXPECT_EQ(subsamples.size(), 3u); | 290 EXPECT_EQ(subsamples.size(), 3u); |
292 EXPECT_EQ(subsamples[0].clear_bytes, 4 + sizeof(kNALU1)); | 291 EXPECT_EQ(subsamples[0].clear_bytes, 4 + sizeof(kNALU1)); |
293 EXPECT_EQ(subsamples[0].cypher_bytes, 0u); | 292 EXPECT_EQ(subsamples[0].cypher_bytes, 0u); |
294 EXPECT_EQ(subsamples[1].clear_bytes, 8 + sizeof(kNALU1) + sizeof(kNALU2)); | 293 EXPECT_EQ(subsamples[1].clear_bytes, 8 + sizeof(kNALU1) + sizeof(kNALU2)); |
295 EXPECT_EQ(subsamples[1].cypher_bytes, 0u); | 294 EXPECT_EQ(subsamples[1].cypher_bytes, 0u); |
296 EXPECT_EQ(subsamples[2].clear_bytes, 4 + 1u); | 295 EXPECT_EQ(subsamples[2].clear_bytes, 4 + 1u); |
297 EXPECT_EQ(subsamples[2].cypher_bytes, 0u); | 296 EXPECT_EQ(subsamples[2].cypher_bytes, 0u); |
298 } | 297 } |
299 | 298 |
300 TEST_P(AVCConversionTest, ParsePartial) { | 299 TEST_P(AVCConversionTest, ParsePartial) { |
301 std::vector<uint8> buf; | 300 std::vector<uint8_t> buf; |
302 MakeInputForLength(GetParam(), &buf); | 301 MakeInputForLength(GetParam(), &buf); |
303 buf.pop_back(); | 302 buf.pop_back(); |
304 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); | 303 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); |
305 // This tests a buffer ending in the middle of a NAL length. For length size | 304 // This tests a buffer ending in the middle of a NAL length. For length size |
306 // of one, this can't happen, so we skip that case. | 305 // of one, this can't happen, so we skip that case. |
307 if (GetParam() != 1) { | 306 if (GetParam() != 1) { |
308 MakeInputForLength(GetParam(), &buf); | 307 MakeInputForLength(GetParam(), &buf); |
309 buf.erase(buf.end() - (sizeof(kNALU2) + 1), buf.end()); | 308 buf.erase(buf.end() - (sizeof(kNALU2) + 1), buf.end()); |
310 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); | 309 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); |
311 } | 310 } |
312 } | 311 } |
313 | 312 |
314 TEST_P(AVCConversionTest, ParseEmpty) { | 313 TEST_P(AVCConversionTest, ParseEmpty) { |
315 std::vector<uint8> buf; | 314 std::vector<uint8_t> buf; |
316 EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); | 315 EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf, nullptr)); |
317 EXPECT_EQ(0u, buf.size()); | 316 EXPECT_EQ(0u, buf.size()); |
318 } | 317 } |
319 | 318 |
320 INSTANTIATE_TEST_CASE_P(AVCConversionTestValues, | 319 INSTANTIATE_TEST_CASE_P(AVCConversionTestValues, |
321 AVCConversionTest, | 320 AVCConversionTest, |
322 ::testing::Values(1, 2, 4)); | 321 ::testing::Values(1, 2, 4)); |
323 | 322 |
324 TEST_F(AVCConversionTest, ConvertConfigToAnnexB) { | 323 TEST_F(AVCConversionTest, ConvertConfigToAnnexB) { |
325 AVCDecoderConfigurationRecord avc_config; | 324 AVCDecoderConfigurationRecord avc_config; |
326 avc_config.sps_list.resize(2); | 325 avc_config.sps_list.resize(2); |
327 avc_config.sps_list[0].push_back(0x67); | 326 avc_config.sps_list[0].push_back(0x67); |
328 avc_config.sps_list[0].push_back(0x12); | 327 avc_config.sps_list[0].push_back(0x12); |
329 avc_config.sps_list[1].push_back(0x67); | 328 avc_config.sps_list[1].push_back(0x67); |
330 avc_config.sps_list[1].push_back(0x34); | 329 avc_config.sps_list[1].push_back(0x34); |
331 avc_config.pps_list.resize(1); | 330 avc_config.pps_list.resize(1); |
332 avc_config.pps_list[0].push_back(0x68); | 331 avc_config.pps_list[0].push_back(0x68); |
333 avc_config.pps_list[0].push_back(0x56); | 332 avc_config.pps_list[0].push_back(0x56); |
334 avc_config.pps_list[0].push_back(0x78); | 333 avc_config.pps_list[0].push_back(0x78); |
335 | 334 |
336 std::vector<uint8> buf; | 335 std::vector<uint8_t> buf; |
337 std::vector<SubsampleEntry> subsamples; | 336 std::vector<SubsampleEntry> subsamples; |
338 EXPECT_TRUE(AVC::ConvertConfigToAnnexB(avc_config, &buf)); | 337 EXPECT_TRUE(AVC::ConvertConfigToAnnexB(avc_config, &buf)); |
339 EXPECT_EQ(0, memcmp(kExpectedParamSets, &buf[0], | 338 EXPECT_EQ(0, memcmp(kExpectedParamSets, &buf[0], |
340 sizeof(kExpectedParamSets))); | 339 sizeof(kExpectedParamSets))); |
341 EXPECT_EQ("SPS,SPS,PPS", AnnexBToString(buf, subsamples)); | 340 EXPECT_EQ("SPS,SPS,PPS", AnnexBToString(buf, subsamples)); |
342 } | 341 } |
343 | 342 |
344 // Verify that we can round trip string -> Annex B -> string. | 343 // Verify that we can round trip string -> Annex B -> string. |
345 TEST_F(AVCConversionTest, StringConversionFunctions) { | 344 TEST_F(AVCConversionTest, StringConversionFunctions) { |
346 std::string str = | 345 std::string str = |
347 "AUD SPS SPSExt SPS PPS SEI SEI R14 I P FILL EOSeq EOStr"; | 346 "AUD SPS SPSExt SPS PPS SEI SEI R14 I P FILL EOSeq EOStr"; |
348 std::vector<uint8> buf; | 347 std::vector<uint8_t> buf; |
349 std::vector<SubsampleEntry> subsamples; | 348 std::vector<SubsampleEntry> subsamples; |
350 StringToAnnexB(str, &buf, &subsamples); | 349 StringToAnnexB(str, &buf, &subsamples); |
351 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)); | 350 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)); |
352 | 351 |
353 EXPECT_EQ(str, AnnexBToString(buf, subsamples)); | 352 EXPECT_EQ(str, AnnexBToString(buf, subsamples)); |
354 } | 353 } |
355 | 354 |
356 TEST_F(AVCConversionTest, ValidAnnexBConstructs) { | 355 TEST_F(AVCConversionTest, ValidAnnexBConstructs) { |
357 const char* test_cases[] = { | 356 const char* test_cases[] = { |
358 "I", | 357 "I", |
359 "I I I I", | 358 "I I I I", |
360 "AUD I", | 359 "AUD I", |
361 "AUD SPS PPS I", | 360 "AUD SPS PPS I", |
362 "I EOSeq", | 361 "I EOSeq", |
363 "I EOSeq EOStr", | 362 "I EOSeq EOStr", |
364 "I EOStr", | 363 "I EOStr", |
365 "P", | 364 "P", |
366 "P P P P", | 365 "P P P P", |
367 "AUD SPS PPS P", | 366 "AUD SPS PPS P", |
368 "SEI SEI I", | 367 "SEI SEI I", |
369 "SEI SEI R14 I", | 368 "SEI SEI R14 I", |
370 "SPS SPSExt SPS PPS I P", | 369 "SPS SPSExt SPS PPS I P", |
371 "R14 SEI I", | 370 "R14 SEI I", |
372 "AUD,I", | 371 "AUD,I", |
373 "AUD,SEI I", | 372 "AUD,SEI I", |
374 "AUD,SEI,SPS,PPS,I" | 373 "AUD,SEI,SPS,PPS,I" |
375 }; | 374 }; |
376 | 375 |
377 for (size_t i = 0; i < arraysize(test_cases); ++i) { | 376 for (size_t i = 0; i < arraysize(test_cases); ++i) { |
378 std::vector<uint8> buf; | 377 std::vector<uint8_t> buf; |
379 std::vector<SubsampleEntry> subsamples; | 378 std::vector<SubsampleEntry> subsamples; |
380 StringToAnnexB(test_cases[i], &buf, NULL); | 379 StringToAnnexB(test_cases[i], &buf, NULL); |
381 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) << "'" << test_cases[i] | 380 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) << "'" << test_cases[i] |
382 << "' failed"; | 381 << "' failed"; |
383 } | 382 } |
384 } | 383 } |
385 | 384 |
386 TEST_F(AVCConversionTest, InvalidAnnexBConstructs) { | 385 TEST_F(AVCConversionTest, InvalidAnnexBConstructs) { |
387 static const char* test_cases[] = { | 386 static const char* test_cases[] = { |
388 "AUD", // No VCL present. | 387 "AUD", // No VCL present. |
389 "AUD,SEI", // No VCL present. | 388 "AUD,SEI", // No VCL present. |
390 "SPS PPS", // No VCL present. | 389 "SPS PPS", // No VCL present. |
391 "SPS PPS AUD I", // Parameter sets must come after AUD. | 390 "SPS PPS AUD I", // Parameter sets must come after AUD. |
392 "SPSExt SPS P", // SPS must come before SPSExt. | 391 "SPSExt SPS P", // SPS must come before SPSExt. |
393 "SPS PPS SPSExt P", // SPSExt must follow an SPS. | 392 "SPS PPS SPSExt P", // SPSExt must follow an SPS. |
394 "EOSeq", // EOSeq must come after a VCL. | 393 "EOSeq", // EOSeq must come after a VCL. |
395 "EOStr", // EOStr must come after a VCL. | 394 "EOStr", // EOStr must come after a VCL. |
396 "I EOStr EOSeq", // EOSeq must come before EOStr. | 395 "I EOStr EOSeq", // EOSeq must come before EOStr. |
397 "I R14", // Reserved14-18 must come before first VCL. | 396 "I R14", // Reserved14-18 must come before first VCL. |
398 "I SEI", // SEI must come before first VCL. | 397 "I SEI", // SEI must come before first VCL. |
399 "P SPS P", // SPS after first VCL would indicate a new access unit. | 398 "P SPS P", // SPS after first VCL would indicate a new access unit. |
400 }; | 399 }; |
401 | 400 |
402 for (size_t i = 0; i < arraysize(test_cases); ++i) { | 401 for (size_t i = 0; i < arraysize(test_cases); ++i) { |
403 std::vector<uint8> buf; | 402 std::vector<uint8_t> buf; |
404 std::vector<SubsampleEntry> subsamples; | 403 std::vector<SubsampleEntry> subsamples; |
405 StringToAnnexB(test_cases[i], &buf, NULL); | 404 StringToAnnexB(test_cases[i], &buf, NULL); |
406 EXPECT_FALSE(AVC::IsValidAnnexB(buf, subsamples)) << "'" << test_cases[i] | 405 EXPECT_FALSE(AVC::IsValidAnnexB(buf, subsamples)) << "'" << test_cases[i] |
407 << "' failed"; | 406 << "' failed"; |
408 } | 407 } |
409 } | 408 } |
410 | 409 |
411 typedef struct { | 410 typedef struct { |
412 const char* input; | 411 const char* input; |
413 const char* expected; | 412 const char* expected; |
(...skipping 20 matching lines...) Expand all Loading... |
434 avc_config.sps_list[0].push_back(0x67); | 433 avc_config.sps_list[0].push_back(0x67); |
435 avc_config.sps_list[0].push_back(0x12); | 434 avc_config.sps_list[0].push_back(0x12); |
436 avc_config.sps_list[1].push_back(0x67); | 435 avc_config.sps_list[1].push_back(0x67); |
437 avc_config.sps_list[1].push_back(0x34); | 436 avc_config.sps_list[1].push_back(0x34); |
438 avc_config.pps_list.resize(1); | 437 avc_config.pps_list.resize(1); |
439 avc_config.pps_list[0].push_back(0x68); | 438 avc_config.pps_list[0].push_back(0x68); |
440 avc_config.pps_list[0].push_back(0x56); | 439 avc_config.pps_list[0].push_back(0x56); |
441 avc_config.pps_list[0].push_back(0x78); | 440 avc_config.pps_list[0].push_back(0x78); |
442 | 441 |
443 for (size_t i = 0; i < arraysize(test_cases); ++i) { | 442 for (size_t i = 0; i < arraysize(test_cases); ++i) { |
444 std::vector<uint8> buf; | 443 std::vector<uint8_t> buf; |
445 std::vector<SubsampleEntry> subsamples; | 444 std::vector<SubsampleEntry> subsamples; |
446 | 445 |
447 StringToAnnexB(test_cases[i].input, &buf, &subsamples); | 446 StringToAnnexB(test_cases[i].input, &buf, &subsamples); |
448 | 447 |
449 EXPECT_TRUE(AVC::InsertParamSetsAnnexB(avc_config, &buf, &subsamples)) | 448 EXPECT_TRUE(AVC::InsertParamSetsAnnexB(avc_config, &buf, &subsamples)) |
450 << "'" << test_cases[i].input << "' insert failed."; | 449 << "'" << test_cases[i].input << "' insert failed."; |
451 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) | 450 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) |
452 << "'" << test_cases[i].input << "' created invalid AnnexB."; | 451 << "'" << test_cases[i].input << "' created invalid AnnexB."; |
453 EXPECT_EQ(test_cases[i].expected, AnnexBToString(buf, subsamples)) | 452 EXPECT_EQ(test_cases[i].expected, AnnexBToString(buf, subsamples)) |
454 << "'" << test_cases[i].input << "' generated unexpected output."; | 453 << "'" << test_cases[i].input << "' generated unexpected output."; |
455 } | 454 } |
456 } | 455 } |
457 | 456 |
458 } // namespace mp4 | 457 } // namespace mp4 |
459 } // namespace media | 458 } // namespace media |
OLD | NEW |