Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement IAMF v1.0.0 errata changes #3337

Draft
wants to merge 4 commits into
base: 24.lts.1+
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cobalt/media/sandbox/format_guesstimator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ using ::media::ChunkDemuxer;
const std::vector<std::string> kSupportedMimeTypes = {
"audio/mp4; codecs=\"ac-3\"",
"audio/mp4; codecs=\"ec-3\"",
"audio/mp4; codecs=\"iamf\"",
"audio/mp4; codecs=\"mp4a.40.2\"",
"audio/webm; codecs=\"opus\"",

Expand Down
2 changes: 1 addition & 1 deletion starboard/shared/starboard/media/codec_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ SbMediaAudioCodec GetAudioCodecFromString(const char* codec,
}
#endif // SB_API_VERSION >= 14
#if SB_API_VERSION >= 15
if (strncmp(codec, "iamf.", 5) == 0) {
if (strcmp(codec, "iamf") == 0 || strncmp(codec, "iamf.", 5) == 0) {
return kSbMediaAudioCodecIamf;
}
#endif // SB_API_VERSION >= 15
Expand Down
1 change: 1 addition & 0 deletions third_party/chromium/media/BUILD.gn.chromium
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ buildflag_header("media_buildflags") {
"ENABLE_MEDIA_REMOTING=$enable_media_remoting",
"ENABLE_MEDIA_REMOTING_RPC=$enable_media_remoting_rpc",
"ENABLE_OPENH264=$media_use_openh264",
"ENABLE_PLATFORM_IAMF_AUDIO=$enable_platform_iamf_audio",
"ENABLE_PLATFORM_MPEG_H_AUDIO=$enable_platform_mpeg_h_audio",
"ENABLE_MSE_MPEG2TS_STREAM_PARSER=$enable_mse_mpeg2ts_stream_parser",
"ENABLE_CAST_STREAMING_RENDERER=$enable_cast_streaming_renderer",
Expand Down
122 changes: 122 additions & 0 deletions third_party/chromium/media/base/audio_codecs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include <ostream>

#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"

namespace media {
Expand Down Expand Up @@ -37,6 +39,8 @@ std::string GetCodecName(AudioCodec codec) {
return "gsm_ms";
case AudioCodec::kOpus:
return "opus";
case AudioCodec::kIAMF:
return "iamf";
case AudioCodec::kPCM_ALAW:
return "pcm_alaw";
case AudioCodec::kEAC3:
Expand All @@ -56,6 +60,10 @@ std::string GetProfileName(AudioCodecProfile profile) {
return "unknown";
case AudioCodecProfile::kXHE_AAC:
return "xhe-aac";
case AudioCodecProfile::kIAMF_SIMPLE:
return "iamf-simple";
case AudioCodecProfile::kIAMF_BASE:
return "iamf-base";
}
}

Expand All @@ -82,11 +90,125 @@ AudioCodec StringToAudioCodec(const std::string& codec_id) {
return AudioCodec::kVorbis;
if (base::StartsWith(codec_id, "mp4a.40.", base::CompareCase::SENSITIVE))
return AudioCodec::kAAC;
if (codec_id == "iamf" ||
base::StartsWith(codec_id, "iamf.", base::CompareCase::SENSITIVE)) {
return AudioCodec::kIAMF;
}
return AudioCodec::kUnknown;
}

std::ostream& operator<<(std::ostream& os, const AudioCodec& codec) {
return os << GetCodecName(codec);
}

#if BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
bool ParseIamfCodecId(std::string codec_id,
uint8_t* primary_profilec,
uint8_t* additional_profilec) {
// Reference: Immersive Audio Model and Formats;
// v1.0.0
// 6.3. Codecs Parameter String
// (https://aomediacodec.github.io/iamf/v1.0.0.html#codecsparameter)
if (!(std::string(codec_id).find("iamf") == 0)) {
return false;
}

// For test purposes only, just "iamf" is acceptable.
if (codec_id == "iamf") {
return true;
}

constexpr int kMaxIamfCodecIdLength =
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", "ipcm".

if (codec_id.size() > kMaxIamfCodecIdLength) {
DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")";
return false;
}

std::vector<std::string> elem = base::SplitString(
codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
if (elem.size() < 4) {
DVLOG(4) << __func__ << ": invalid IAMF codec id:" << codec_id;
return false;
}

DCHECK_EQ(elem[0], "iamf");

if (StringToAudioCodec(elem[0]) != AudioCodec::kIAMF) {
DVLOG(4) << __func__ << ": invalid IAMF codec id:" << codec_id;
return false;
}

// The primary profile string should be three digits, and should be between 0
// and 255 inclusive.
uint32_t primary_profile = 0;
if (elem[1].size() != 3 || !base::StringToUint(elem[1], &primary_profile) ||
primary_profile > 0xFF) {
DVLOG(4) << __func__ << ": invalid IAMF primary profile: " << elem[1];
return false;
}

// The additional profile string should be three digits, and should be between
// 0 and 255 inclusive.
uint32_t additional_profile = 0;
if (elem[2].size() != 3 ||
!base::StringToUint(elem[2], &additional_profile) ||
additional_profile > 0xFF) {
DVLOG(4) << __func__ << ": invalid IAMF additional profile: " << elem[2];
return false;
}

// The codec string should be one of "opus", "mp4a", "flac", or "ipcm".
std::string codec = base::ToLowerASCII(elem[3]);
if (codec.size() != 4 || ((codec != "opus") && (codec != "mp4a") &&
(codec != "flac") && (codec != "ipcm"))) {
DVLOG(4) << __func__ << ": invalid IAMF stream codec: " << elem[3];
return false;
}

if (codec == "mp4a") {
if (elem.size() != 6) {
DVLOG(4) << __func__
<< ": incorrect mp4a codec string syntax:" << codec_id;
return false;
}

// The fields following "mp4a" should be "40" and "2" to signal AAC-LC.
uint32_t object_type_indication = 0;
if (elem[4].size() != 2 ||
!base::HexStringToUInt(elem[4], &object_type_indication) ||
object_type_indication != 0x40) {
DVLOG(4) << __func__
<< ": invalid mp4a Object Type Indication:" << codec_id;
return false;
}

uint32_t audio_object_type = 0;
if (elem[5].size() != 1 ||
!base::HexStringToUInt(elem[5], &audio_object_type) ||
audio_object_type != 0x02) {
DVLOG(4) << __func__ << ": invalid mp4a Audio Object Type:" << codec_id;
return false;
}
}

if (primary_profilec) {
*primary_profilec = primary_profile;
}

if (additional_profilec) {
*additional_profilec = additional_profile;
}

return true;
}
#endif // BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
} // namespace media
16 changes: 14 additions & 2 deletions third_party/chromium/media/base/audio_codecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
#ifndef MEDIA_BASE_AUDIO_CODECS_H_
#define MEDIA_BASE_AUDIO_CODECS_H_

#include <stdint.h>

#include <string>

#include "media/base/media_export.h"
#include "media/media_buildflags.h"

namespace media {

Expand All @@ -33,13 +37,14 @@ enum class AudioCodec {
kALAC = 15,
kAC3 = 16,
kMpegHAudio = 17,
kIAMF = 22,
// DO NOT ADD RANDOM AUDIO CODECS!
//
// The only acceptable time to add a new codec is if there is production code
// that uses said codec in the same CL.

// Must always be equal to the largest entry ever logged.
kMaxValue = kMpegHAudio,
kMaxValue = kIAMF,
};

enum class AudioCodecProfile {
Expand All @@ -49,7 +54,9 @@ enum class AudioCodecProfile {
// kMaxValue to equal the new codec.
kUnknown = 0,
kXHE_AAC = 1,
kMaxValue = kXHE_AAC,
kIAMF_SIMPLE = 2,
kIAMF_BASE = 3,
kMaxValue = kIAMF_BASE,
};

std::string MEDIA_EXPORT GetCodecName(AudioCodec codec);
Expand All @@ -58,6 +65,11 @@ std::string MEDIA_EXPORT GetProfileName(AudioCodecProfile profile);
MEDIA_EXPORT std::ostream& operator<<(std::ostream& os,
const AudioCodec& codec);
MEDIA_EXPORT AudioCodec StringToAudioCodec(const std::string& codec_id);
#if BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
MEDIA_EXPORT bool ParseIamfCodecId(std::string codec_id,
uint8_t* primary_profilec,
uint8_t* additional_profilec);
#endif // BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)

} // namespace media

Expand Down
4 changes: 4 additions & 0 deletions third_party/chromium/media/base/eme_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum EmeCodec : uint32_t {
EME_CODEC_FLAC = 1 << 13,
EME_CODEC_AV1 = 1 << 14,
EME_CODEC_HEVC_PROFILE_MAIN10 = 1 << 15,
EME_CODEC_IAMF = 1 << 23,
};

// *_ALL values should only be used for masking, do not use them to specify
Expand All @@ -60,6 +61,9 @@ constexpr SupportedCodecs GetMp4AudioCodecs() {
codecs |= EME_CODEC_MPEG_H_AUDIO;
#endif // BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO)
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
#if BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
codecs |= EME_CODEC_IAMF;
#endif // BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
return codecs;
}

Expand Down
2 changes: 2 additions & 0 deletions third_party/chromium/media/base/key_systems.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ EmeCodec ToAudioEmeCodec(AudioCodec codec) {
return EME_CODEC_EAC3;
case AudioCodec::kAC3:
return EME_CODEC_AC3;
case AudioCodec::kIAMF:
return EME_CODEC_IAMF;
case AudioCodec::kMpegHAudio:
return EME_CODEC_MPEG_H_AUDIO;
default:
Expand Down
15 changes: 15 additions & 0 deletions third_party/chromium/media/base/mime_util_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ AudioCodec MimeUtilToAudioCodec(MimeUtil::Codec codec) {
return AudioCodec::kOpus;
case MimeUtil::FLAC:
return AudioCodec::kFLAC;
case MimeUtil::IAMF:
return AudioCodec::kIAMF;
default:
break;
}
Expand Down Expand Up @@ -345,6 +347,10 @@ void MimeUtil::AddSupportedMediaFormats() {
mp4_video_codecs.emplace(AV1);
#endif

#if BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
mp4_audio_codecs.emplace(IAMF);
#endif // BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)

CodecSet mp4_codecs(mp4_audio_codecs);
mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end());

Expand Down Expand Up @@ -670,6 +676,8 @@ bool MimeUtil::IsCodecSupportedOnAndroid(
#else
return false;
#endif
case IAMF:
return false;
}

return false;
Expand Down Expand Up @@ -863,6 +871,13 @@ bool MimeUtil::ParseCodecHelper(const std::string& mime_type_lower_case,
}
#endif

#if BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
if (ParseIamfCodecId(codec_id.data(), nullptr, nullptr)) {
out_result->codec = MimeUtil::IAMF;
return true;
}
#endif

DVLOG(2) << __func__ << ": Unrecognized codec id \"" << codec_id << "\"";
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion third_party/chromium/media/base/mime_util_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ class MEDIA_EXPORT MimeUtil {
DOLBY_VISION,
AV1,
MPEG_H_AUDIO,
LAST_CODEC = MPEG_H_AUDIO
IAMF,
LAST_CODEC = IAMF
};

// Platform configuration structure. Controls which codecs are supported at
Expand Down
8 changes: 8 additions & 0 deletions third_party/chromium/media/base/mime_util_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,10 @@ TEST(IsCodecSupportedOnAndroidTest, EncryptedCodecBehavior) {
case MimeUtil::AV1:
EXPECT_EQ(BUILDFLAG(ENABLE_AV1_DECODER), result);
break;

case MimeUtil::IAMF:
EXPECT_EQ(HasIamfSupport(), result);
break;
}
});
}
Expand Down Expand Up @@ -677,6 +681,10 @@ TEST(IsCodecSupportedOnAndroidTest, ClearCodecBehavior) {
case MimeUtil::AV1:
EXPECT_EQ(BUILDFLAG(ENABLE_AV1_DECODER), result);
break;

case MimeUtil::IAMF:
EXPECT_EQ(HasIamfSupport(), result);
break;
}
});
}
Expand Down
11 changes: 7 additions & 4 deletions third_party/chromium/media/base/starboard_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,15 @@ SbMediaAudioCodec MediaAudioCodecToSbMediaAudioCodec(AudioCodec codec) {
return kSbMediaAudioCodecPcm;
#endif // SB_API_VERSION >= 14
#if SB_API_VERSION >= 15
// TODO(b/271301103): Enable this once IAMF is added to Chromium.
// case AudioCodec::kIAMF:
// return kSbMediaAudioCodecPcm;
case AudioCodec::kIAMF:
LOG(INFO) << "MediaAudioCodecToSbMediaAudioCodec() returns kSbMediaAudioCodecIamf.";
LOG(INFO) << "Current SB_API_VERSION " << SB_API_VERSION;
return kSbMediaAudioCodecIamf;
#endif // SB_API_VERSION >= 15
default:
// Cobalt only supports a subset of audio codecs defined by Chromium.
DLOG(ERROR) << "Unsupported audio codec " << GetCodecName(codec);
LOG(ERROR) << "Unsupported audio codec " << GetCodecName(codec);
LOG(INFO) << "Current SB_API_VERSION " << SB_API_VERSION;
return kSbMediaAudioCodecNone;
}
NOTREACHED();
Expand Down Expand Up @@ -167,6 +169,7 @@ SbMediaAudioStreamInfo MediaAudioConfigToSbMediaAudioStreamInfo(
audio_stream_info.audio_specific_config = extra_data.data();
}

LOG(INFO) << "SbMediaAudioStreamInfo.codec is " << audio_stream_info.codec;
return audio_stream_info;
}

Expand Down
2 changes: 2 additions & 0 deletions third_party/chromium/media/base/supported_types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ bool IsAudioCodecProprietary(AudioCodec codec) {
return true;

case AudioCodec::kFLAC:
case AudioCodec::kIAMF:
case AudioCodec::kMP3:
case AudioCodec::kOpus:
case AudioCodec::kVorbis:
Expand Down Expand Up @@ -291,6 +292,7 @@ bool IsDefaultSupportedAudioType(const AudioType& type) {
case AudioCodec::kALAC:
case AudioCodec::kAC3:
case AudioCodec::kMpegHAudio:
case AudioCodec::kIAMF:
case AudioCodec::kUnknown:
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ void MediaCodecAudioDecoder::Initialize(const AudioDecoderConfig& config,
config.codec() == AudioCodec::kFLAC ||
config.codec() == AudioCodec::kAAC ||
config.codec() == AudioCodec::kOpus ||
config.codec() == AudioCodec::kIAMF ||
is_passthrough_;
if (!is_codec_supported) {
DVLOG(1) << "Unsuported codec " << GetCodecName(config.codec());
Expand Down
Loading
Loading