diff --git a/starboard/common/BUILD.gn b/starboard/common/BUILD.gn index efe6da76e6fe..452b49bc36f9 100644 --- a/starboard/common/BUILD.gn +++ b/starboard/common/BUILD.gn @@ -110,6 +110,7 @@ target(gtest_target_type, "common_test") { "memory_test.cc", "player_test.cc", "socket_test.cc", + "string_test.cc", "test_main.cc", ] deps = [ diff --git a/starboard/common/string.h b/starboard/common/string.h index 49e6a1bbe7f5..b78b6b9ea1d2 100644 --- a/starboard/common/string.h +++ b/starboard/common/string.h @@ -103,6 +103,33 @@ static SB_C_FORCE_INLINE int strlcat(CHAR* dst, const CHAR* src, int dst_size) { dst_length; } +// Splits a string on a char delimiter. +inline std::vector SplitString(const std::string& input, + char delimiter) { + std::vector output; + if (input.empty()) { + return output; + } + + size_t start = 0; + while (start != std::string::npos) { + size_t end = input.find_first_of(delimiter, start); + std::string piece; + + if (end == std::string::npos) { + piece = input.substr(start); + start = std::string::npos; + } else { + piece = input.substr(start, end - start); + start = end + 1; + } + + output.emplace_back(piece); + } + + return output; +} + } // namespace starboard #endif // STARBOARD_COMMON_STRING_H_ diff --git a/starboard/common/string_test.cc b/starboard/common/string_test.cc new file mode 100644 index 000000000000..06f9daaf18be --- /dev/null +++ b/starboard/common/string_test.cc @@ -0,0 +1,98 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "starboard/common/string.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace { + +TEST(StringTest, SplitString) { + std::string str = "The quick brown fox jumps over the lazy dog"; + std::vector output = SplitString(str, '.'); + ASSERT_EQ(output.size(), 1); + ASSERT_EQ(output[0], str); + + std::vector vec = {"The", "quick", "brown", "fox", "jumps", + "over", "the", "lazy", "dog"}; + output = SplitString(str, ' '); + ASSERT_EQ(output.size(), vec.size()); + for (int i = 0; i < vec.size(); ++i) { + ASSERT_EQ(output[i], vec[i]); + } + + str = "iamf.001.001.Opus"; + output = SplitString(str, '.'); + vec = {"iamf", "001", "001", "Opus"}; + ASSERT_EQ(output.size(), vec.size()); + for (int i = 0; i < vec.size(); ++i) { + ASSERT_EQ(output[i], vec[i]); + } +} + +TEST(StringTest, SplitStringEmptyInput) { + std::string str; + std::vector output = SplitString(str, '.'); + ASSERT_TRUE(output.empty()); +} + +TEST(StringTest, SplitStringNullDelimiter) { + std::string str = "The quick brown fox jumps over the lazy dog"; + std::vector output = SplitString(str, '\0'); + ASSERT_EQ(output.size(), 1); + ASSERT_EQ(output[0], str); +} + +TEST(StringTest, SplitStringIrregularDelimiterPositions) { + std::string str = ".string.starts.with.delimiter"; + std::vector output = SplitString(str, '.'); + std::vector vec = {"", "string", "starts", "with", "delimiter"}; + ASSERT_EQ(output.size(), vec.size()); + for (int i = 0; i < vec.size(); ++i) { + ASSERT_EQ(output[i], vec[i]); + } + + str = "string.ends.with.delimiter."; + output = SplitString(str, '.'); + vec = {"string", "ends", "with", "delimiter", ""}; + ASSERT_EQ(output.size(), vec.size()); + for (int i = 0; i < vec.size(); ++i) { + ASSERT_EQ(output[i], vec[i]); + } + + str = ".delimiters.on.both.sides."; + output = SplitString(str, '.'); + vec = {"", "delimiters", "on", "both", "sides", ""}; + ASSERT_EQ(output.size(), vec.size()); + for (int i = 0; i < vec.size(); ++i) { + ASSERT_EQ(output[i], vec[i]); + } +} + +TEST(StringTest, SplitStringOnlyDelimiters) { + std::string str = "...."; + std::vector output = SplitString(str, '.'); + std::vector vec = {"", "", "", "", ""}; + ASSERT_EQ(output.size(), vec.size()); + for (int i = 0; i < vec.size(); ++i) { + ASSERT_EQ(output[i], vec[i]); + } +} + +} // namespace +} // namespace starboard diff --git a/starboard/shared/starboard/media/BUILD.gn b/starboard/shared/starboard/media/BUILD.gn index 480d46052e1f..3d2eaf44bb31 100644 --- a/starboard/shared/starboard/media/BUILD.gn +++ b/starboard/shared/starboard/media/BUILD.gn @@ -19,6 +19,8 @@ static_library("media_util") { "//starboard/shared/starboard/media/avc_util.h", "//starboard/shared/starboard/media/codec_util.cc", "//starboard/shared/starboard/media/codec_util.h", + "//starboard/shared/starboard/media/iamf_util.cc", + "//starboard/shared/starboard/media/iamf_util.h", "//starboard/shared/starboard/media/key_system_supportability_cache.cc", "//starboard/shared/starboard/media/key_system_supportability_cache.h", "//starboard/shared/starboard/media/media_support_internal.h", diff --git a/starboard/shared/starboard/media/codec_util.cc b/starboard/shared/starboard/media/codec_util.cc index c34a1084d262..3cbd49540821 100644 --- a/starboard/shared/starboard/media/codec_util.cc +++ b/starboard/shared/starboard/media/codec_util.cc @@ -22,6 +22,7 @@ #include "starboard/common/string.h" #include "starboard/configuration.h" #include "starboard/configuration_constants.h" +#include "starboard/shared/starboard/media/iamf_util.h" namespace starboard { namespace shared { @@ -111,7 +112,7 @@ SbMediaAudioCodec GetAudioCodecFromString(const char* codec, return kSbMediaAudioCodecPcm; } #if SB_API_VERSION >= 15 - if (strcmp(codec, "iamf") == 0 || strncmp(codec, "iamf.", 5) == 0) { + if (strcmp(codec, "iamf") == 0 || IamfMimeUtil(codec).is_valid()) { return kSbMediaAudioCodecIamf; } #endif // SB_API_VERSION >= 15 diff --git a/starboard/shared/starboard/media/codec_util_test.cc b/starboard/shared/starboard/media/codec_util_test.cc index 9ec4d5833a6e..9e72f7c20610 100644 --- a/starboard/shared/starboard/media/codec_util_test.cc +++ b/starboard/shared/starboard/media/codec_util_test.cc @@ -278,6 +278,22 @@ TEST(CodecUtilTest, ParsesIamfCodec) { kSbMediaAudioCodecIamf); EXPECT_EQ(GetAudioCodecFromString("iamf.000.000.ipcm", ""), kSbMediaAudioCodecIamf); + EXPECT_EQ(GetAudioCodecFromString("iamf.001.000.ipcm", ""), + kSbMediaAudioCodecIamf); + EXPECT_EQ(GetAudioCodecFromString("iamf.255.255.ipcm", ""), + kSbMediaAudioCodecIamf); + + // Invalid codec types + EXPECT_EQ(GetAudioCodecFromString("iamf.000.256.Opus", ""), + kSbMediaAudioCodecNone); + EXPECT_EQ(GetAudioCodecFromString("iamf.000.000.invalid", ""), + kSbMediaAudioCodecNone); + EXPECT_EQ(GetAudioCodecFromString("Iamf.000.000.fLaC", ""), + kSbMediaAudioCodecNone); + EXPECT_EQ(GetAudioCodecFromString("iamf.000.000.mp4a.40.3", ""), + kSbMediaAudioCodecNone); + EXPECT_EQ(GetAudioCodecFromString("iamf.000.0000.Opus", ""), + kSbMediaAudioCodecNone); } #endif // SB_API_VERSION >= 15 diff --git a/starboard/shared/starboard/media/iamf_util.cc b/starboard/shared/starboard/media/iamf_util.cc new file mode 100644 index 000000000000..0d486e51ddc3 --- /dev/null +++ b/starboard/shared/starboard/media/iamf_util.cc @@ -0,0 +1,131 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/shared/starboard/media/iamf_util.h" + +#include +#include +#include +#include + +#include "starboard/common/string.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace media { +namespace { +// Checks if |input| is a valid IAMF profile value, and stores the converted +// value in |*profile| if so. +bool StringToProfile(const std::string& input, uint32_t* profile) { + SB_DCHECK(profile); + + if (input.size() != 3) { + return false; + } + + if (!std::isdigit(input[0]) || !std::isdigit(input[1]) || + !std::isdigit(input[2])) { + return false; + } + + uint32_t converted_val = static_cast(std::atoi(input.c_str())); + if (converted_val > kIamfProfileMax) { + return false; + } + *profile = converted_val; + return true; +} +} // namespace + +IamfMimeUtil::IamfMimeUtil(const std::string& mime_type) { + // Reference: Immersive Audio Model and Formats; + // v1.0.0 + // 6.3. Codecs Parameter String + // (https://aomediacodec.github.io/iamf/v1.0.0-errata.html#codecsparameter) + if (mime_type.find("iamf") != 0) { + return; + } + + // 4 FOURCC string "iamf". + // +1 delimiting period. + // +3 primary_profile as 3 digit string. + // +1 delimiting period. + // +3 additional_profile as 3 digit string. + // +1 delimiting period. + // +9 The remaining string is one of "Opus", "mp4a.40.2", "fLaC", or "ipcm". + constexpr int kMaxIamfCodecIdLength = 22; + if (mime_type.size() > kMaxIamfCodecIdLength) { + return; + } + + const std::vector vec = SplitString(mime_type, '.'); + // The mime type must be in 4 parts for all substreams other than AAC, which + // is 6 parts. + if (vec.size() != 4 && vec.size() != 6) { + return; + } + + // The primary profile must be between 0 and 255 inclusive. + uint32_t primary_profile = 0; + if (!StringToProfile(vec[1], &primary_profile)) { + return; + } + + // The additional profile must be between 0 and 255 inclusive. + uint32_t additional_profile = 0; + if (!StringToProfile(vec[2], &additional_profile)) { + return; + } + + // The codec string should be one of "Opus", "mp4a", "fLaC", or "ipcm". + std::string codec = vec[3]; + if ((codec != "Opus") && (codec != "mp4a") && (codec != "fLaC") && + (codec != "ipcm")) { + return; + } + + // Only IAMF codec parameter strings with "mp4a" should be greater than 4 + // elements. + if (codec == "mp4a") { + if (vec.size() != 6) { + return; + } + + // The fields following "mp4a" should be "40" and "2" to signal AAC-LC. + if (vec[4] != "40" || vec[5] != "2") { + return; + } + substream_codec_ = kIamfSubstreamCodecMp4a; + } else { + if (vec.size() > 4) { + return; + } + if (codec == "Opus") { + substream_codec_ = kIamfSubstreamCodecOpus; + } else if (codec == "fLaC") { + substream_codec_ = kIamfSubstreamCodecFlac; + } else { + substream_codec_ = kIamfSubstreamCodecIpcm; + } + } + + primary_profile_ = primary_profile; + additional_profile_ = additional_profile; +} + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/starboard/media/iamf_util.h b/starboard/shared/starboard/media/iamf_util.h new file mode 100644 index 000000000000..ff3aee47e023 --- /dev/null +++ b/starboard/shared/starboard/media/iamf_util.h @@ -0,0 +1,78 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_IAMF_UTIL_H_ +#define STARBOARD_SHARED_STARBOARD_MEDIA_IAMF_UTIL_H_ + +#include +#include + +#include "starboard/common/log.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace media { + +enum IamfSubstreamCodec { + kIamfSubstreamCodecUnknown, + kIamfSubstreamCodecOpus, + kIamfSubstreamCodecMp4a, + kIamfSubstreamCodecFlac, + kIamfSubstreamCodecIpcm +}; + +// These values must match the profile values defined in +// https://aomediacodec.github.io/iamf/v1.0.0-errata.html#profiles +constexpr uint32_t kIamfProfileSimple = 0; +constexpr uint32_t kIamfProfileBase = 1; +constexpr uint32_t kIamfProfileMax = 255; + +// Parses an IAMF codecs parameter string following the convention defined in +// https://aomediacodec.github.io/iamf/v1.0.0-errata.html#codecsparameter. +// Always check is_valid() before calling the getter functions. +class IamfMimeUtil { + public: + explicit IamfMimeUtil(const std::string& mime_type); + + bool is_valid() const { + return primary_profile_ <= kIamfProfileMax && + additional_profile_ <= kIamfProfileMax && + substream_codec_ != kIamfSubstreamCodecUnknown; + } + int primary_profile() const { + SB_DCHECK(is_valid()); + return primary_profile_; + } + int additional_profile() const { + SB_DCHECK(is_valid()); + return additional_profile_; + } + IamfSubstreamCodec substream_codec() const { + SB_DCHECK(is_valid()); + return substream_codec_; + } + + private: + int primary_profile_ = std::numeric_limits::max(); + int additional_profile_ = std::numeric_limits::max(); + IamfSubstreamCodec substream_codec_ = kIamfSubstreamCodecUnknown; +}; + +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard + +#endif // STARBOARD_SHARED_STARBOARD_MEDIA_IAMF_UTIL_H_ diff --git a/starboard/shared/starboard/media/iamf_util_test.cc b/starboard/shared/starboard/media/iamf_util_test.cc new file mode 100644 index 000000000000..68ea2817a3ff --- /dev/null +++ b/starboard/shared/starboard/media/iamf_util_test.cc @@ -0,0 +1,259 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "starboard/shared/starboard/media/iamf_util.h" + +#include + +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace media { +namespace { + +TEST(IamfUtilTest, Valid) { + std::string codec_param = "iamf.000.000.Opus"; + IamfMimeUtil util(codec_param); + EXPECT_TRUE(util.is_valid()); + + codec_param = "iamf.000.000.fLaC"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); + + codec_param = "iamf.000.000.ipcm"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); + + codec_param = "iamf.000.000.mp4a.40.2"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); +} + +TEST(IamfUtilTest, Invalid) { + // Invalid substream codec + std::string codec_param = "iamf.000.000.vorbis"; + IamfMimeUtil util(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid codec capitalization + codec_param = "iamf.000.000.opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + codec_param = "iamf.000.000.flac"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + codec_param = "iamf.000.000.FlAc"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + codec_param = "iamf.000.000.MP4a.40.2"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + codec_param = "IAMF.000.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid additional profile value + codec_param = "iamf.000.999.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid primary profile value + codec_param = "iamf.999.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid leading codec param + codec_param = "iacb.000.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid length for Opus substream + codec_param = "iamf.000.000.Opus.40.2"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid length for AAC-LC substream + codec_param = "iamf.000.000.mp4a"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid param for AAC-LC substream + codec_param = "iamf.000.000.mp4a.40.3"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid param for AAC-LC substream + codec_param = "iamf.000.000.mp4a.40.20"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Too many delimiting periods + codec_param = "iamf.000.000..Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Leading delimiting period + codec_param = ".iamf.000.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Trailing delimiting period + codec_param = "iamf.000.000.Opus."; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // No delimiting period between codec param string and primary profile + codec_param = "iamf000.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid primary profile length + codec_param = "iamf.00.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + codec_param = "iamf.0000.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid additional profile length + codec_param = "iamf.000.00.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + codec_param = "iamf.000.0000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Letters in primary profile value + codec_param = "iamf.0aa.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + codec_param = "iamf.xxx.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Letters in additional profile value + codec_param = "iamf.000.0aa.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + codec_param = "iamf.000.xxx.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Letter in primary profile value + codec_param = "iamf.0a0.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Invalid additional profile with AAC-LC substream + codec_param = "iamf.000.00.mp4a.40.2"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Misplaced delimiting period for AAC-LC substream + codec_param = "iamf.000.000.mp4a.402."; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Negative primary profile value + codec_param = "iamf.-12.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Empty param + codec_param = ""; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Leading whitespace + codec_param = " iamf.000.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Trailing whitespace + codec_param = "iamf.000.000.Opus "; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Whitespace in the middle + codec_param = "iamf.00 0.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // HE-AAC substream param + codec_param = "iamf.000.000.mp4a.40.5"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); + + // Non IAMF codec param + codec_param = "ec-3"; + util = IamfMimeUtil(codec_param); + EXPECT_FALSE(util.is_valid()); +} + +TEST(IamfUtilTest, SubstreamCodec) { + std::string codec_param = "iamf.000.000.Opus"; + IamfMimeUtil util(codec_param); + EXPECT_TRUE(util.is_valid()); + EXPECT_EQ(util.substream_codec(), kIamfSubstreamCodecOpus); + + codec_param = "iamf.000.000.fLaC"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); + EXPECT_EQ(util.substream_codec(), kIamfSubstreamCodecFlac); + + codec_param = "iamf.000.000.ipcm"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); + EXPECT_EQ(util.substream_codec(), kIamfSubstreamCodecIpcm); + + codec_param = "iamf.000.000.mp4a.40.2"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); + EXPECT_EQ(util.substream_codec(), kIamfSubstreamCodecMp4a); +} + +TEST(IamfUtilTest, Profile) { + std::string codec_param = "iamf.000.000.Opus"; + IamfMimeUtil util(codec_param); + EXPECT_TRUE(util.is_valid()); + EXPECT_EQ(util.primary_profile(), kIamfProfileSimple); + EXPECT_EQ(util.additional_profile(), kIamfProfileSimple); + + codec_param = "iamf.001.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); + EXPECT_EQ(util.primary_profile(), kIamfProfileBase); + EXPECT_EQ(util.additional_profile(), kIamfProfileSimple); + + codec_param = "iamf.000.001.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); + EXPECT_EQ(util.primary_profile(), kIamfProfileSimple); + EXPECT_EQ(util.additional_profile(), kIamfProfileBase); + + codec_param = "iamf.002.000.Opus"; + util = IamfMimeUtil(codec_param); + EXPECT_TRUE(util.is_valid()); + ASSERT_NE(util.primary_profile(), kIamfProfileSimple); + ASSERT_NE(util.primary_profile(), kIamfProfileBase); + ASSERT_EQ(util.primary_profile(), 2); +} + +} // namespace +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard diff --git a/starboard/shared/starboard/media/media_tests.gni b/starboard/shared/starboard/media/media_tests.gni index 269a60c13f75..091aa9768ae8 100644 --- a/starboard/shared/starboard/media/media_tests.gni +++ b/starboard/shared/starboard/media/media_tests.gni @@ -15,6 +15,7 @@ media_tests_sources = [ "//starboard/shared/starboard/media/avc_util_test.cc", "//starboard/shared/starboard/media/codec_util_test.cc", + "//starboard/shared/starboard/media/iamf_util_test.cc", "//starboard/shared/starboard/media/media_util_test.cc", "//starboard/shared/starboard/media/mime_type_test.cc", "//starboard/shared/starboard/media/mime_util_test.cc",