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" | 7 #include "base/basictypes.h" |
8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
9 #include "media/base/decrypt_config.h" | 9 #include "media/base/decrypt_config.h" |
10 #include "media/base/stream_parser_buffer.h" | 10 #include "media/base/stream_parser_buffer.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 case H264NALU::kReserved18: | 103 case H264NALU::kReserved18: |
104 case H264NALU::kCodedSliceAux: | 104 case H264NALU::kCodedSliceAux: |
105 case H264NALU::kCodedSliceExtension: | 105 case H264NALU::kCodedSliceExtension: |
106 CHECK(false) << "Unexpected type: " << type; | 106 CHECK(false) << "Unexpected type: " << type; |
107 break; | 107 break; |
108 }; | 108 }; |
109 | 109 |
110 return "UnsupportedType"; | 110 return "UnsupportedType"; |
111 } | 111 } |
112 | 112 |
113 static void WriteStartCodeAndNALUType(std::vector<uint8>* buffer, | |
114 const std::string& nal_unit_type) { | |
115 buffer->push_back(0x00); | |
116 buffer->push_back(0x00); | |
117 buffer->push_back(0x00); | |
118 buffer->push_back(0x01); | |
119 buffer->push_back(StringToNALUType(nal_unit_type)); | |
120 | |
xhwang
2014/07/10 06:23:01
remove empty lines here
acolwell GONE FROM CHROMIUM
2014/07/15 22:10:44
Done.
| |
121 | |
122 } | |
123 | |
113 void StringToAnnexB(const std::string& str, std::vector<uint8>* buffer, | 124 void StringToAnnexB(const std::string& str, std::vector<uint8>* buffer, |
114 std::vector<SubsampleEntry>* subsamples) { | 125 std::vector<SubsampleEntry>* subsamples) { |
115 DCHECK(!str.empty()); | 126 DCHECK(!str.empty()); |
116 | 127 |
117 std::vector<std::string> tokens; | 128 std::vector<std::string> tokens; |
118 EXPECT_GT(Tokenize(str, " ", &tokens), 0u); | 129 EXPECT_GT(Tokenize(str, " ", &tokens), 0u); |
119 | 130 |
120 buffer->clear(); | 131 buffer->clear(); |
121 for (size_t i = 0; i < tokens.size(); ++i) { | 132 for (size_t i = 0; i < tokens.size(); ++i) { |
122 SubsampleEntry entry; | 133 SubsampleEntry entry; |
123 size_t start = buffer->size(); | 134 size_t start = buffer->size(); |
124 | 135 |
125 // Write the start code. | 136 WriteStartCodeAndNALUType(buffer, tokens[i]); |
126 buffer->push_back(0x00); | |
127 buffer->push_back(0x00); | |
128 buffer->push_back(0x00); | |
129 buffer->push_back(0x01); | |
130 | |
131 // Write NALU type. | |
132 buffer->push_back(StringToNALUType(tokens[i])); | |
133 | 137 |
134 entry.clear_bytes = buffer->size() - start; | 138 entry.clear_bytes = buffer->size() - start; |
135 | 139 |
136 // Write junk for the payload since the current code doesn't | 140 // Write junk for the payload since the current code doesn't |
137 // actually look at it. | 141 // actually look at it. |
138 buffer->push_back(0x32); | 142 buffer->push_back(0x32); |
139 buffer->push_back(0x12); | 143 buffer->push_back(0x12); |
140 buffer->push_back(0x67); | 144 buffer->push_back(0x67); |
141 | 145 |
146 if (subsamples) { | |
147 // Simulate the encrypted bits containing something that looks | |
148 // like a SPS NALU. | |
149 WriteStartCodeAndNALUType(buffer, "SPS"); | |
150 } | |
151 | |
142 entry.cypher_bytes = buffer->size() - start - entry.clear_bytes; | 152 entry.cypher_bytes = buffer->size() - start - entry.clear_bytes; |
143 | 153 |
144 if (subsamples) { | 154 if (subsamples) { |
145 subsamples->push_back(entry); | 155 subsamples->push_back(entry); |
146 } | 156 } |
147 } | 157 } |
148 } | 158 } |
149 | 159 |
150 std::string AnnexBToString(const std::vector<uint8>& buffer) { | 160 std::string AnnexBToString(const std::vector<uint8>& buffer, |
161 const std::vector<SubsampleEntry>& subsamples) { | |
151 std::stringstream ss; | 162 std::stringstream ss; |
152 | 163 |
153 H264Parser parser; | 164 H264Parser parser; |
154 parser.SetStream(&buffer[0], buffer.size()); | 165 parser.SetStream(&buffer[0], buffer.size(), subsamples); |
155 | 166 |
156 H264NALU nalu; | 167 H264NALU nalu; |
157 bool first = true; | 168 bool first = true; |
158 while (parser.AdvanceToNextNALU(&nalu) == H264Parser::kOk) { | 169 while (parser.AdvanceToNextNALU(&nalu) == H264Parser::kOk) { |
159 if (!first) | 170 if (!first) |
160 ss << " "; | 171 ss << " "; |
161 else | 172 else |
162 first = false; | 173 first = false; |
163 | 174 |
164 ss << NALUTypeToString(nalu.nal_unit_type); | 175 ss << NALUTypeToString(nalu.nal_unit_type); |
(...skipping 19 matching lines...) Expand all Loading... | |
184 buf->insert(buf->end(), kNALU1, kNALU1 + sizeof(kNALU1)); | 195 buf->insert(buf->end(), kNALU1, kNALU1 + sizeof(kNALU1)); |
185 | 196 |
186 WriteLength(length_size, sizeof(kNALU2), buf); | 197 WriteLength(length_size, sizeof(kNALU2), buf); |
187 buf->insert(buf->end(), kNALU2, kNALU2 + sizeof(kNALU2)); | 198 buf->insert(buf->end(), kNALU2, kNALU2 + sizeof(kNALU2)); |
188 } | 199 } |
189 | 200 |
190 }; | 201 }; |
191 | 202 |
192 TEST_P(AVCConversionTest, ParseCorrectly) { | 203 TEST_P(AVCConversionTest, ParseCorrectly) { |
193 std::vector<uint8> buf; | 204 std::vector<uint8> buf; |
205 std::vector<SubsampleEntry> subsamples; | |
194 MakeInputForLength(GetParam(), &buf); | 206 MakeInputForLength(GetParam(), &buf); |
195 EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf)); | 207 EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf)); |
196 EXPECT_TRUE(AVC::IsValidAnnexB(buf)); | 208 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)); |
197 EXPECT_EQ(buf.size(), sizeof(kExpected)); | 209 EXPECT_EQ(buf.size(), sizeof(kExpected)); |
198 EXPECT_EQ(0, memcmp(kExpected, &buf[0], sizeof(kExpected))); | 210 EXPECT_EQ(0, memcmp(kExpected, &buf[0], sizeof(kExpected))); |
199 EXPECT_EQ("P SDC", AnnexBToString(buf)); | 211 EXPECT_EQ("P SDC", AnnexBToString(buf, subsamples)); |
200 } | 212 } |
201 | 213 |
202 // Intentionally write NALU sizes that are larger than the buffer. | 214 // Intentionally write NALU sizes that are larger than the buffer. |
203 TEST_P(AVCConversionTest, NALUSizeTooLarge) { | 215 TEST_P(AVCConversionTest, NALUSizeTooLarge) { |
204 std::vector<uint8> buf; | 216 std::vector<uint8> buf; |
205 WriteLength(GetParam(), 10 * sizeof(kNALU1), &buf); | 217 WriteLength(GetParam(), 10 * sizeof(kNALU1), &buf); |
206 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); | 218 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); |
207 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf)); | 219 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf)); |
208 } | 220 } |
209 | 221 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 avc_config.pps_list.resize(1); | 268 avc_config.pps_list.resize(1); |
257 avc_config.pps_list[0].push_back(0x68); | 269 avc_config.pps_list[0].push_back(0x68); |
258 avc_config.pps_list[0].push_back(0x56); | 270 avc_config.pps_list[0].push_back(0x56); |
259 avc_config.pps_list[0].push_back(0x78); | 271 avc_config.pps_list[0].push_back(0x78); |
260 | 272 |
261 std::vector<uint8> buf; | 273 std::vector<uint8> buf; |
262 std::vector<SubsampleEntry> subsamples; | 274 std::vector<SubsampleEntry> subsamples; |
263 EXPECT_TRUE(AVC::ConvertConfigToAnnexB(avc_config, &buf, &subsamples)); | 275 EXPECT_TRUE(AVC::ConvertConfigToAnnexB(avc_config, &buf, &subsamples)); |
264 EXPECT_EQ(0, memcmp(kExpectedParamSets, &buf[0], | 276 EXPECT_EQ(0, memcmp(kExpectedParamSets, &buf[0], |
265 sizeof(kExpectedParamSets))); | 277 sizeof(kExpectedParamSets))); |
266 EXPECT_EQ("SPS SPS PPS", AnnexBToString(buf)); | 278 EXPECT_EQ("SPS SPS PPS", AnnexBToString(buf, subsamples)); |
267 } | 279 } |
268 | 280 |
269 // Verify that we can round trip string -> Annex B -> string. | 281 // Verify that we can round trip string -> Annex B -> string. |
270 TEST_F(AVCConversionTest, StringConversionFunctions) { | 282 TEST_F(AVCConversionTest, StringConversionFunctions) { |
271 std::string str = | 283 std::string str = |
272 "AUD SPS SPSExt SPS PPS SEI SEI R14 I P FILL EOSeq EOStr"; | 284 "AUD SPS SPSExt SPS PPS SEI SEI R14 I P FILL EOSeq EOStr"; |
273 std::vector<uint8> buf; | 285 std::vector<uint8> buf; |
274 StringToAnnexB(str, &buf, NULL); | 286 std::vector<SubsampleEntry> subsamples; |
287 StringToAnnexB(str, &buf, &subsamples); | |
288 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)); | |
275 | 289 |
276 EXPECT_TRUE(AVC::IsValidAnnexB(buf)); | 290 EXPECT_EQ(str, AnnexBToString(buf, subsamples)); |
277 | |
278 EXPECT_EQ(str, AnnexBToString(buf)); | |
279 } | 291 } |
280 | 292 |
281 TEST_F(AVCConversionTest, ValidAnnexBConstructs) { | 293 TEST_F(AVCConversionTest, ValidAnnexBConstructs) { |
282 const char* test_cases[] = { | 294 const char* test_cases[] = { |
283 "I", | 295 "I", |
284 "I I I I", | 296 "I I I I", |
285 "AUD I", | 297 "AUD I", |
286 "AUD SPS PPS I", | 298 "AUD SPS PPS I", |
287 "I EOSeq", | 299 "I EOSeq", |
288 "I EOSeq EOStr", | 300 "I EOSeq EOStr", |
289 "I EOStr", | 301 "I EOStr", |
290 "P", | 302 "P", |
291 "P P P P", | 303 "P P P P", |
292 "AUD SPS PPS P", | 304 "AUD SPS PPS P", |
293 "SEI SEI I", | 305 "SEI SEI I", |
294 "SEI SEI R14 I", | 306 "SEI SEI R14 I", |
295 "SPS SPSExt SPS PPS I P", | 307 "SPS SPSExt SPS PPS I P", |
296 "R14 SEI I", | 308 "R14 SEI I", |
297 }; | 309 }; |
298 | 310 |
299 for (size_t i = 0; i < arraysize(test_cases); ++i) { | 311 for (size_t i = 0; i < arraysize(test_cases); ++i) { |
300 std::vector<uint8> buf; | 312 std::vector<uint8> buf; |
313 std::vector<SubsampleEntry> subsamples; | |
301 StringToAnnexB(test_cases[i], &buf, NULL); | 314 StringToAnnexB(test_cases[i], &buf, NULL); |
302 EXPECT_TRUE(AVC::IsValidAnnexB(buf)) << "'" << test_cases[i] << "' failed"; | 315 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) << "'" << test_cases[i] |
316 << "' failed"; | |
303 } | 317 } |
304 } | 318 } |
305 | 319 |
306 TEST_F(AVCConversionTest, InvalidAnnexBConstructs) { | 320 TEST_F(AVCConversionTest, InvalidAnnexBConstructs) { |
307 static const char* test_cases[] = { | 321 static const char* test_cases[] = { |
308 "AUD", // No VCL present. | 322 "AUD", // No VCL present. |
309 "SPS PPS", // No VCL present. | 323 "SPS PPS", // No VCL present. |
310 "SPS PPS AUD I", // Parameter sets must come after AUD. | 324 "SPS PPS AUD I", // Parameter sets must come after AUD. |
311 "SPSExt SPS P", // SPS must come before SPSExt. | 325 "SPSExt SPS P", // SPS must come before SPSExt. |
312 "SPS PPS SPSExt P", // SPSExt must follow an SPS. | 326 "SPS PPS SPSExt P", // SPSExt must follow an SPS. |
313 "EOSeq", // EOSeq must come after a VCL. | 327 "EOSeq", // EOSeq must come after a VCL. |
314 "EOStr", // EOStr must come after a VCL. | 328 "EOStr", // EOStr must come after a VCL. |
315 "I EOStr EOSeq", // EOSeq must come before EOStr. | 329 "I EOStr EOSeq", // EOSeq must come before EOStr. |
316 "I R14", // Reserved14-18 must come before first VCL. | 330 "I R14", // Reserved14-18 must come before first VCL. |
317 "I SEI", // SEI must come before first VCL. | 331 "I SEI", // SEI must come before first VCL. |
318 "P SPS P", // SPS after first VCL would indicate a new access unit. | 332 "P SPS P", // SPS after first VCL would indicate a new access unit. |
319 }; | 333 }; |
320 | 334 |
321 for (size_t i = 0; i < arraysize(test_cases); ++i) { | 335 for (size_t i = 0; i < arraysize(test_cases); ++i) { |
322 std::vector<uint8> buf; | 336 std::vector<uint8> buf; |
337 std::vector<SubsampleEntry> subsamples; | |
323 StringToAnnexB(test_cases[i], &buf, NULL); | 338 StringToAnnexB(test_cases[i], &buf, NULL); |
324 EXPECT_FALSE(AVC::IsValidAnnexB(buf)) << "'" << test_cases[i] << "' failed"; | 339 EXPECT_FALSE(AVC::IsValidAnnexB(buf, subsamples)) << "'" << test_cases[i] |
340 << "' failed"; | |
325 } | 341 } |
326 } | 342 } |
327 | 343 |
328 typedef struct { | 344 typedef struct { |
329 const char* input; | 345 const char* input; |
330 const char* expected; | 346 const char* expected; |
331 } InsertTestCases; | 347 } InsertTestCases; |
332 | 348 |
333 TEST_F(AVCConversionTest, InsertParamSetsAnnexB) { | 349 TEST_F(AVCConversionTest, InsertParamSetsAnnexB) { |
334 static const InsertTestCases test_cases[] = { | 350 static const InsertTestCases test_cases[] = { |
(...skipping 19 matching lines...) Expand all Loading... | |
354 avc_config.pps_list[0].push_back(0x78); | 370 avc_config.pps_list[0].push_back(0x78); |
355 | 371 |
356 for (size_t i = 0; i < arraysize(test_cases); ++i) { | 372 for (size_t i = 0; i < arraysize(test_cases); ++i) { |
357 std::vector<uint8> buf; | 373 std::vector<uint8> buf; |
358 std::vector<SubsampleEntry> subsamples; | 374 std::vector<SubsampleEntry> subsamples; |
359 | 375 |
360 StringToAnnexB(test_cases[i].input, &buf, &subsamples); | 376 StringToAnnexB(test_cases[i].input, &buf, &subsamples); |
361 | 377 |
362 EXPECT_TRUE(AVC::InsertParamSetsAnnexB(avc_config, &buf, &subsamples)) | 378 EXPECT_TRUE(AVC::InsertParamSetsAnnexB(avc_config, &buf, &subsamples)) |
363 << "'" << test_cases[i].input << "' insert failed."; | 379 << "'" << test_cases[i].input << "' insert failed."; |
364 EXPECT_TRUE(AVC::IsValidAnnexB(buf)) | 380 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) |
365 << "'" << test_cases[i].input << "' created invalid AnnexB."; | 381 << "'" << test_cases[i].input << "' created invalid AnnexB."; |
366 EXPECT_EQ(test_cases[i].expected, AnnexBToString(buf)) | 382 EXPECT_EQ(test_cases[i].expected, AnnexBToString(buf, subsamples)) |
367 << "'" << test_cases[i].input << "' generated unexpected output."; | 383 << "'" << test_cases[i].input << "' generated unexpected output."; |
368 } | 384 } |
369 } | 385 } |
370 | 386 |
371 } // namespace mp4 | 387 } // namespace mp4 |
372 } // namespace media | 388 } // namespace media |
OLD | NEW |