Chromium Code Reviews| 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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 | 112 |
| 113 static void WriteStartCodeAndNALUType(std::vector<uint8>* buffer, | 113 static void WriteStartCodeAndNALUType(std::vector<uint8>* buffer, |
| 114 const std::string& nal_unit_type) { | 114 const std::string& nal_unit_type) { |
| 115 buffer->push_back(0x00); | 115 buffer->push_back(0x00); |
| 116 buffer->push_back(0x00); | 116 buffer->push_back(0x00); |
| 117 buffer->push_back(0x00); | 117 buffer->push_back(0x00); |
| 118 buffer->push_back(0x01); | 118 buffer->push_back(0x01); |
| 119 buffer->push_back(StringToNALUType(nal_unit_type)); | 119 buffer->push_back(StringToNALUType(nal_unit_type)); |
| 120 } | 120 } |
| 121 | 121 |
| 122 void StringToAnnexB(const std::string& str, std::vector<uint8>* buffer, | 122 void StringToAnnexB(const std::string& str, std::vector<uint8>* buffer, |
|
wolenetz
2014/10/07 23:37:40
nit: Document the format of |str| in method commen
servolk
2014/10/07 23:57:19
Done.
| |
| 123 std::vector<SubsampleEntry>* subsamples) { | 123 std::vector<SubsampleEntry>* subsamples) { |
| 124 DCHECK(!str.empty()); | 124 DCHECK(!str.empty()); |
| 125 | 125 |
| 126 std::vector<std::string> tokens; | 126 std::vector<std::string> tokens; |
|
wolenetz
2014/10/07 23:37:40
nit: s/tokens/subsample_specs/
servolk
2014/10/07 23:57:18
Done.
| |
| 127 EXPECT_GT(Tokenize(str, " ", &tokens), 0u); | 127 EXPECT_GT(Tokenize(str, " ", &tokens), 0u); |
| 128 | 128 |
| 129 buffer->clear(); | 129 buffer->clear(); |
| 130 for (size_t i = 0; i < tokens.size(); ++i) { | 130 for (size_t i = 0; i < tokens.size(); ++i) { |
| 131 SubsampleEntry entry; | 131 SubsampleEntry entry; |
| 132 size_t start = buffer->size(); | 132 size_t start = buffer->size(); |
| 133 | 133 |
| 134 WriteStartCodeAndNALUType(buffer, tokens[i]); | 134 std::vector<std::string> subsample_nalus; |
| 135 EXPECT_GT(Tokenize(tokens[i], ",", &subsample_nalus), 0u); | |
| 136 for (size_t j = 0; j < subsample_nalus.size(); ++j) { | |
| 137 WriteStartCodeAndNALUType(buffer, subsample_nalus[j]); | |
| 138 | |
| 139 // Write junk for the payload since the current code doesn't | |
| 140 // actually look at it. | |
| 141 buffer->push_back(0x32); | |
| 142 buffer->push_back(0x12); | |
| 143 buffer->push_back(0x67); | |
| 144 } | |
| 135 | 145 |
| 136 entry.clear_bytes = buffer->size() - start; | 146 entry.clear_bytes = buffer->size() - start; |
| 137 | 147 |
| 138 // Write junk for the payload since the current code doesn't | |
| 139 // actually look at it. | |
| 140 buffer->push_back(0x32); | |
| 141 buffer->push_back(0x12); | |
| 142 buffer->push_back(0x67); | |
| 143 | |
| 144 if (subsamples) { | 148 if (subsamples) { |
| 145 // Simulate the encrypted bits containing something that looks | 149 // Simulate the encrypted bits containing something that looks |
| 146 // like a SPS NALU. | 150 // like a SPS NALU. |
| 147 WriteStartCodeAndNALUType(buffer, "SPS"); | 151 WriteStartCodeAndNALUType(buffer, "SPS"); |
| 148 } | 152 } |
| 149 | 153 |
| 150 entry.cypher_bytes = buffer->size() - start - entry.clear_bytes; | 154 entry.cypher_bytes = buffer->size() - start - entry.clear_bytes; |
| 151 | 155 |
| 152 if (subsamples) { | 156 if (subsamples) { |
| 153 subsamples->push_back(entry); | 157 subsamples->push_back(entry); |
| 154 } | 158 } |
| 155 } | 159 } |
| 156 } | 160 } |
| 157 | 161 |
| 162 int FindSubsampleIndex(const std::vector<uint8>& buffer, | |
| 163 const std::vector<SubsampleEntry>* subsamples, | |
| 164 const uint8* ptr) { | |
| 165 DCHECK(ptr >= &buffer[0]); | |
| 166 DCHECK(ptr <= &buffer[buffer.size()-1]); | |
| 167 if (!subsamples || subsamples->empty()) | |
| 168 return 0; | |
| 169 | |
| 170 const uint8* p = &buffer[0]; | |
| 171 for (size_t i = 0; i < subsamples->size(); ++i) { | |
| 172 p += (*subsamples)[i].clear_bytes + (*subsamples)[i].cypher_bytes; | |
| 173 if (p > ptr) { | |
| 174 return i; | |
| 175 } | |
| 176 } | |
| 177 DCHECK(false); | |
|
wolenetz
2014/10/07 23:37:39
nit: NOTREACHED();
servolk
2014/10/07 23:57:18
Done.
| |
| 178 return 0; | |
| 179 } | |
| 180 | |
| 158 std::string AnnexBToString(const std::vector<uint8>& buffer, | 181 std::string AnnexBToString(const std::vector<uint8>& buffer, |
| 159 const std::vector<SubsampleEntry>& subsamples) { | 182 const std::vector<SubsampleEntry>& subsamples) { |
| 160 std::stringstream ss; | 183 std::stringstream ss; |
| 161 | 184 |
| 162 H264Parser parser; | 185 H264Parser parser; |
| 163 parser.SetEncryptedStream(&buffer[0], buffer.size(), subsamples); | 186 parser.SetEncryptedStream(&buffer[0], buffer.size(), subsamples); |
| 164 | 187 |
| 165 H264NALU nalu; | 188 H264NALU nalu; |
| 166 bool first = true; | 189 bool first = true; |
| 190 size_t current_subsample = 0; | |
|
wolenetz
2014/10/07 23:37:39
nit: s/ple/ple_index/
servolk
2014/10/07 23:57:19
Done.
| |
| 167 while (parser.AdvanceToNextNALU(&nalu) == H264Parser::kOk) { | 191 while (parser.AdvanceToNextNALU(&nalu) == H264Parser::kOk) { |
| 192 size_t subsample = FindSubsampleIndex(buffer, &subsamples, nalu.data); | |
|
wolenetz
2014/10/07 23:37:39
nit: ditto
servolk
2014/10/07 23:57:18
Done.
| |
| 168 if (!first) | 193 if (!first) |
| 169 ss << " "; | 194 ss << (subsample == current_subsample ? "," : " "); |
| 170 else | 195 else |
| 171 first = false; | 196 first = false; |
|
wolenetz
2014/10/07 23:37:39
nit: maybe add a DCHECK_EQ(subsample_index, curren
servolk
2014/10/07 23:57:19
Done.
| |
| 172 | 197 |
| 173 ss << NALUTypeToString(nalu.nal_unit_type); | 198 ss << NALUTypeToString(nalu.nal_unit_type); |
| 199 current_subsample = subsample; | |
| 174 } | 200 } |
| 175 return ss.str(); | 201 return ss.str(); |
| 176 } | 202 } |
| 177 | 203 |
| 178 class AVCConversionTest : public testing::TestWithParam<int> { | 204 class AVCConversionTest : public testing::TestWithParam<int> { |
| 179 protected: | 205 protected: |
| 180 void WriteLength(int length_size, int length, std::vector<uint8>* buf) { | 206 void WriteLength(int length_size, int length, std::vector<uint8>* buf) { |
| 181 DCHECK_GE(length, 0); | 207 DCHECK_GE(length, 0); |
| 182 DCHECK_LE(length, 255); | 208 DCHECK_LE(length, 255); |
| 183 | 209 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 199 }; | 225 }; |
| 200 | 226 |
| 201 TEST_P(AVCConversionTest, ParseCorrectly) { | 227 TEST_P(AVCConversionTest, ParseCorrectly) { |
| 202 std::vector<uint8> buf; | 228 std::vector<uint8> buf; |
| 203 std::vector<SubsampleEntry> subsamples; | 229 std::vector<SubsampleEntry> subsamples; |
| 204 MakeInputForLength(GetParam(), &buf); | 230 MakeInputForLength(GetParam(), &buf); |
| 205 EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf)); | 231 EXPECT_TRUE(AVC::ConvertFrameToAnnexB(GetParam(), &buf)); |
| 206 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)); | 232 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)); |
| 207 EXPECT_EQ(buf.size(), sizeof(kExpected)); | 233 EXPECT_EQ(buf.size(), sizeof(kExpected)); |
| 208 EXPECT_EQ(0, memcmp(kExpected, &buf[0], sizeof(kExpected))); | 234 EXPECT_EQ(0, memcmp(kExpected, &buf[0], sizeof(kExpected))); |
| 209 EXPECT_EQ("P SDC", AnnexBToString(buf, subsamples)); | 235 EXPECT_EQ("P,SDC", AnnexBToString(buf, subsamples)); |
| 210 } | 236 } |
| 211 | 237 |
| 212 // Intentionally write NALU sizes that are larger than the buffer. | 238 // Intentionally write NALU sizes that are larger than the buffer. |
| 213 TEST_P(AVCConversionTest, NALUSizeTooLarge) { | 239 TEST_P(AVCConversionTest, NALUSizeTooLarge) { |
| 214 std::vector<uint8> buf; | 240 std::vector<uint8> buf; |
| 215 WriteLength(GetParam(), 10 * sizeof(kNALU1), &buf); | 241 WriteLength(GetParam(), 10 * sizeof(kNALU1), &buf); |
| 216 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); | 242 buf.insert(buf.end(), kNALU1, kNALU1 + sizeof(kNALU1)); |
| 217 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf)); | 243 EXPECT_FALSE(AVC::ConvertFrameToAnnexB(GetParam(), &buf)); |
| 218 } | 244 } |
| 219 | 245 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 "I EOSeq", | 323 "I EOSeq", |
| 298 "I EOSeq EOStr", | 324 "I EOSeq EOStr", |
| 299 "I EOStr", | 325 "I EOStr", |
| 300 "P", | 326 "P", |
| 301 "P P P P", | 327 "P P P P", |
| 302 "AUD SPS PPS P", | 328 "AUD SPS PPS P", |
| 303 "SEI SEI I", | 329 "SEI SEI I", |
| 304 "SEI SEI R14 I", | 330 "SEI SEI R14 I", |
| 305 "SPS SPSExt SPS PPS I P", | 331 "SPS SPSExt SPS PPS I P", |
| 306 "R14 SEI I", | 332 "R14 SEI I", |
| 333 "AUD,I", | |
| 334 "AUD,SEI I", | |
| 335 "AUD,SEI,SPS,PPS,I" | |
| 307 }; | 336 }; |
| 308 | 337 |
| 309 for (size_t i = 0; i < arraysize(test_cases); ++i) { | 338 for (size_t i = 0; i < arraysize(test_cases); ++i) { |
| 310 std::vector<uint8> buf; | 339 std::vector<uint8> buf; |
| 311 std::vector<SubsampleEntry> subsamples; | 340 std::vector<SubsampleEntry> subsamples; |
| 312 StringToAnnexB(test_cases[i], &buf, NULL); | 341 StringToAnnexB(test_cases[i], &buf, NULL); |
| 313 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) << "'" << test_cases[i] | 342 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) << "'" << test_cases[i] |
| 314 << "' failed"; | 343 << "' failed"; |
| 315 } | 344 } |
| 316 } | 345 } |
| 317 | 346 |
| 318 TEST_F(AVCConversionTest, InvalidAnnexBConstructs) { | 347 TEST_F(AVCConversionTest, InvalidAnnexBConstructs) { |
| 319 static const char* test_cases[] = { | 348 static const char* test_cases[] = { |
| 320 "AUD", // No VCL present. | 349 "AUD", // No VCL present. |
| 350 "AUD,SEI", // No VCL present. | |
| 321 "SPS PPS", // No VCL present. | 351 "SPS PPS", // No VCL present. |
| 322 "SPS PPS AUD I", // Parameter sets must come after AUD. | 352 "SPS PPS AUD I", // Parameter sets must come after AUD. |
| 323 "SPSExt SPS P", // SPS must come before SPSExt. | 353 "SPSExt SPS P", // SPS must come before SPSExt. |
| 324 "SPS PPS SPSExt P", // SPSExt must follow an SPS. | 354 "SPS PPS SPSExt P", // SPSExt must follow an SPS. |
| 325 "EOSeq", // EOSeq must come after a VCL. | 355 "EOSeq", // EOSeq must come after a VCL. |
| 326 "EOStr", // EOStr must come after a VCL. | 356 "EOStr", // EOStr must come after a VCL. |
| 327 "I EOStr EOSeq", // EOSeq must come before EOStr. | 357 "I EOStr EOSeq", // EOSeq must come before EOStr. |
| 328 "I R14", // Reserved14-18 must come before first VCL. | 358 "I R14", // Reserved14-18 must come before first VCL. |
| 329 "I SEI", // SEI must come before first VCL. | 359 "I SEI", // SEI must come before first VCL. |
| 330 "P SPS P", // SPS after first VCL would indicate a new access unit. | 360 "P SPS P", // SPS after first VCL would indicate a new access unit. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 << "'" << test_cases[i].input << "' insert failed."; | 407 << "'" << test_cases[i].input << "' insert failed."; |
| 378 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) | 408 EXPECT_TRUE(AVC::IsValidAnnexB(buf, subsamples)) |
| 379 << "'" << test_cases[i].input << "' created invalid AnnexB."; | 409 << "'" << test_cases[i].input << "' created invalid AnnexB."; |
| 380 EXPECT_EQ(test_cases[i].expected, AnnexBToString(buf, subsamples)) | 410 EXPECT_EQ(test_cases[i].expected, AnnexBToString(buf, subsamples)) |
| 381 << "'" << test_cases[i].input << "' generated unexpected output."; | 411 << "'" << test_cases[i].input << "' generated unexpected output."; |
| 382 } | 412 } |
| 383 } | 413 } |
| 384 | 414 |
| 385 } // namespace mp4 | 415 } // namespace mp4 |
| 386 } // namespace media | 416 } // namespace media |
| OLD | NEW |