| 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 |