diff --git a/starboard/shared/starboard/media/codec_util.cc b/starboard/shared/starboard/media/codec_util.cc index 1c2c1b3b7d22..ff3b32563104 100644 --- a/starboard/shared/starboard/media/codec_util.cc +++ b/starboard/shared/starboard/media/codec_util.cc @@ -72,7 +72,8 @@ bool VideoConfig::operator!=(const VideoConfig& that) const { return !(*this == that); } -SbMediaAudioCodec GetAudioCodecFromString(const char* codec) { +SbMediaAudioCodec GetAudioCodecFromString(const char* codec, + const char* subtype) { #if SB_API_VERSION < 15 const bool kCheckAc3Audio = kSbHasAc3Audio; #else @@ -105,7 +106,9 @@ SbMediaAudioCodec GetAudioCodecFromString(const char* codec) { } // For WAV, the "codecs" parameter of a MIME type refers to the WAVE format // ID, where 1 represents PCM: https://datatracker.ietf.org/doc/html/rfc2361 - if (strcmp(codec, "1") == 0) { + const bool is_wav = + strcmp(subtype, "wav") == 0 || strcmp(subtype, "wave") == 0; + if (is_wav && strcmp(codec, "1") == 0) { return kSbMediaAudioCodecPcm; } #endif // SB_API_VERSION >= 14 diff --git a/starboard/shared/starboard/media/codec_util.h b/starboard/shared/starboard/media/codec_util.h index 11f3102ec5ec..b6f6b61513c6 100644 --- a/starboard/shared/starboard/media/codec_util.h +++ b/starboard/shared/starboard/media/codec_util.h @@ -64,7 +64,11 @@ class VideoConfig { optional avc_parameter_sets_; }; -SbMediaAudioCodec GetAudioCodecFromString(const char* codec); +// Attempts to determine an SbMediaAudioCodec from |codec|, returning +// kSbMediaAudioCodecNone if no match is found. |subtype| may be checked in +// cases of ambiguous codec strings. +SbMediaAudioCodec GetAudioCodecFromString(const char* codec, + const char* subtype); } // namespace media } // namespace starboard diff --git a/starboard/shared/starboard/media/codec_util_test.cc b/starboard/shared/starboard/media/codec_util_test.cc index 2a334be21431..a57d7693f533 100644 --- a/starboard/shared/starboard/media/codec_util_test.cc +++ b/starboard/shared/starboard/media/codec_util_test.cc @@ -16,6 +16,7 @@ #include +#include "starboard/media.h" #include "starboard/shared/starboard/media/avc_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -214,6 +215,60 @@ TEST(VideoConfigTest, H264VsVp9) { EXPECT_FALSE(config_h264 == config_vp9); } +TEST(CodecUtilTest, ParsesAacCodecs) { + EXPECT_EQ(GetAudioCodecFromString("mp4a.40.2", ""), kSbMediaAudioCodecAac); + EXPECT_EQ(GetAudioCodecFromString("mp4a.40.5", ""), kSbMediaAudioCodecAac); +} + +#if SB_API_VERSION < 15 +const bool kCheckAc3Audio = kSbHasAc3Audio; +#else +const bool kCheckAc3Audio = true; +#endif // SB_API_VERSION < 15 + +TEST(CodecUtilTest, ParsesAc3CodecIfEnabled) { + EXPECT_EQ(GetAudioCodecFromString("ac-3", ""), + kCheckAc3Audio ? kSbMediaAudioCodecAc3 : kSbMediaAudioCodecNone); +} + +TEST(CodecUtilTest, ParsesEac3CodecIfEnabled) { + EXPECT_EQ(GetAudioCodecFromString("ec-3", ""), + kCheckAc3Audio ? kSbMediaAudioCodecEac3 : kSbMediaAudioCodecNone); +} + +TEST(CodecUtilTest, ParsesOpusCodec) { + EXPECT_EQ(GetAudioCodecFromString("opus", ""), kSbMediaAudioCodecOpus); +} + +TEST(CodecUtilTest, ParsesVorbisCodec) { + EXPECT_EQ(GetAudioCodecFromString("vorbis", ""), kSbMediaAudioCodecVorbis); +} + +#if SB_API_VERSION >= 14 +TEST(CodecUtilTest, ParsesMp3Codecs) { + EXPECT_EQ(GetAudioCodecFromString("mp3", ""), kSbMediaAudioCodecMp3); + EXPECT_EQ(GetAudioCodecFromString("mp4a.69", ""), kSbMediaAudioCodecMp3); + EXPECT_EQ(GetAudioCodecFromString("mp4a.6B", ""), kSbMediaAudioCodecMp3); +} + +TEST(CodecUtilTest, ParsesFlacCodec) { + EXPECT_EQ(GetAudioCodecFromString("flac", ""), kSbMediaAudioCodecFlac); +} + +TEST(CodecUtilTest, ParsesPcmCodecForWav) { + EXPECT_EQ(GetAudioCodecFromString("1", "wav"), kSbMediaAudioCodecPcm); + EXPECT_EQ(GetAudioCodecFromString("1", "wave"), kSbMediaAudioCodecPcm); +} + +TEST(CodecUtilTest, DoesNotParse1AsPcmForNonWavSubtypes) { + EXPECT_EQ(GetAudioCodecFromString("1", ""), kSbMediaAudioCodecNone); + EXPECT_EQ(GetAudioCodecFromString("1", "mp4"), kSbMediaAudioCodecNone); + EXPECT_EQ(GetAudioCodecFromString("1", "mp3"), kSbMediaAudioCodecNone); + EXPECT_EQ(GetAudioCodecFromString("1", "mpeg"), kSbMediaAudioCodecNone); + EXPECT_EQ(GetAudioCodecFromString("1", "webm"), kSbMediaAudioCodecNone); +} +#endif // SB_API_VERSION >= 14 + } // namespace } // namespace media } // namespace starboard diff --git a/starboard/shared/starboard/media/media_tests.gni b/starboard/shared/starboard/media/media_tests.gni index 4777863a3c79..269a60c13f75 100644 --- a/starboard/shared/starboard/media/media_tests.gni +++ b/starboard/shared/starboard/media/media_tests.gni @@ -18,6 +18,7 @@ media_tests_sources = [ "//starboard/shared/starboard/media/media_util_test.cc", "//starboard/shared/starboard/media/mime_type_test.cc", "//starboard/shared/starboard/media/mime_util_test.cc", + "//starboard/shared/starboard/media/parsed_mime_info_test.cc", "//starboard/shared/starboard/media/video_capabilities_test.cc", "//starboard/shared/starboard/media/vp9_util_test.cc", ] diff --git a/starboard/shared/starboard/media/parsed_mime_info.cc b/starboard/shared/starboard/media/parsed_mime_info.cc index e61cb84d7f1f..ae2e1479579c 100644 --- a/starboard/shared/starboard/media/parsed_mime_info.cc +++ b/starboard/shared/starboard/media/parsed_mime_info.cc @@ -101,7 +101,8 @@ bool ParsedMimeInfo::ParseAudioInfo(const std::string& codec) { SB_DCHECK(mime_type_.is_valid()); SB_DCHECK(!has_audio_info()); - SbMediaAudioCodec audio_codec = GetAudioCodecFromString(codec.c_str()); + SbMediaAudioCodec audio_codec = + GetAudioCodecFromString(codec.c_str(), mime_type_.subtype().c_str()); if (audio_codec == kSbMediaAudioCodecNone) { return false; } diff --git a/starboard/shared/starboard/media/parsed_mime_info_test.cc b/starboard/shared/starboard/media/parsed_mime_info_test.cc new file mode 100644 index 000000000000..94c1f7b8ff19 --- /dev/null +++ b/starboard/shared/starboard/media/parsed_mime_info_test.cc @@ -0,0 +1,98 @@ +// Copyright 2023 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/parsed_mime_info.h" + +#include "starboard/media.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace shared { +namespace starboard { +namespace media { +namespace { + +#if SB_API_VERSION < 15 +const bool kCheckAc3Audio = kSbHasAc3Audio; +#else +const bool kCheckAc3Audio = true; +#endif // SB_API_VERSION < 15 + +TEST(ParsedMimeInfoTest, ParsesAacLowComplexityCodec) { + ParsedMimeInfo mime_info("audio/mp4; codecs=\"mp4a.40.2\""); + ASSERT_TRUE(mime_info.has_audio_info()); + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecAac); +} + +TEST(ParsedMimeInfoTest, ParsesAacHighEfficiencyCodec) { + ParsedMimeInfo mime_info("audio/mp4; codecs=\"mp4a.40.5\""); + ASSERT_TRUE(mime_info.has_audio_info()); + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecAac); +} + +TEST(ParsedMimeInfoTest, ParsesAc3Codec) { + ParsedMimeInfo mime_info("audio/mp4; codecs=\"ac-3\""); + ASSERT_EQ(mime_info.has_audio_info(), kCheckAc3Audio); + + if (kCheckAc3Audio) { + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecAc3); + } +} + +TEST(ParsedMimeInfoTest, ParsesEac3Codec) { + ParsedMimeInfo mime_info("audio/mp4; codecs=\"ec-3\""); + ASSERT_EQ(mime_info.has_audio_info(), kCheckAc3Audio); + + if (kCheckAc3Audio) { + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecEac3); + } +} + +TEST(ParsedMimeInfoTest, ParsesOpusCodec) { + ParsedMimeInfo mime_info("audio/webm; codecs=\"opus\""); + ASSERT_TRUE(mime_info.has_audio_info()); + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecOpus); +} + +TEST(ParsedMimeInfoTest, ParsesVorbisCodec) { + ParsedMimeInfo mime_info("audio/webm; codecs=\"vorbis\""); + ASSERT_TRUE(mime_info.has_audio_info()); + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecVorbis); +} + +#if SB_API_VERSION >= 14 +TEST(ParsedMimeInfoTest, ParsesMp3Codec) { + ParsedMimeInfo mime_info("audio/mpeg; codecs=\"mp3\""); + ASSERT_TRUE(mime_info.has_audio_info()); + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecMp3); +} + +TEST(ParsedMimeInfoTest, ParsesFlacCodec) { + ParsedMimeInfo mime_info("audio/ogg; codecs=\"flac\""); + ASSERT_TRUE(mime_info.has_audio_info()); + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecFlac); +} + +TEST(ParsedMimeInfoTest, ParsesPcmCodec) { + ParsedMimeInfo mime_info("audio/wav; codecs=\"1\""); + ASSERT_TRUE(mime_info.has_audio_info()); + EXPECT_EQ(mime_info.audio_info().codec, kSbMediaAudioCodecPcm); +} +#endif // SB_API_VERSION >= 14 + +} // namespace +} // namespace media +} // namespace starboard +} // namespace shared +} // namespace starboard