Define an extensible audio format description
The new way for describing audio formats which can be used
both in framework <-> framework and framework <-> HAL
interfaces and directly supports extensions by vendors.
The mapping is defined between the legacy audio_format_t
and the new descriptions.
The new description will replace the AudioFormatSys SAIDL enum.
For bitstream types, MIME Media Types are used. Stagefright's
list of media types is extended.
Bug: 188932434
Test: atest audio_aidl_conversion_tests
Change-Id: Id0a0186b44c15dcb65980daf4b8a4257ef6adb72
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 0e98e5d..8f3d996 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -14,6 +14,11 @@
* limitations under the License.
*/
+#include <algorithm>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
#define LOG_TAG "AidlConversion"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -21,6 +26,7 @@
#include "media/AidlConversion.h"
#include <media/ShmemCompat.h>
+#include <media/stagefright/foundation/MediaDefs.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilities
@@ -403,6 +409,401 @@
return static_cast<media::AudioFormatSys>(legacy);
}
+namespace {
+
+namespace detail {
+using AudioFormatPair = std::pair<audio_format_t, media::AudioFormatDescription>;
+using AudioFormatPairs = std::vector<AudioFormatPair>;
+}
+
+media::AudioFormatDescription make_AudioFormatDescription(media::AudioFormatType type) {
+ media::AudioFormatDescription result;
+ result.type = type;
+ return result;
+}
+
+media::AudioFormatDescription make_AudioFormatDescription(media::PcmType pcm) {
+ auto result = make_AudioFormatDescription(media::AudioFormatType::PCM);
+ result.pcm = pcm;
+ return result;
+}
+
+media::AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+ media::AudioFormatDescription result;
+ result.encoding = encoding;
+ return result;
+}
+
+media::AudioFormatDescription make_AudioFormatDescription(media::PcmType transport,
+ const std::string& encoding) {
+ auto result = make_AudioFormatDescription(encoding);
+ result.pcm = transport;
+ return result;
+}
+
+const detail::AudioFormatPairs& getAudioFormatPairs() {
+ static const detail::AudioFormatPairs pairs = {{
+ {
+ AUDIO_FORMAT_INVALID,
+ make_AudioFormatDescription(media::AudioFormatType::SYS_RESERVED_INVALID)
+ },
+ {
+ AUDIO_FORMAT_DEFAULT, media::AudioFormatDescription{}
+ },
+ {
+ AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(media::PcmType::INT_16_BIT)
+ },
+ {
+ AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(media::PcmType::UINT_8_BIT)
+ },
+ {
+ AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(media::PcmType::INT_32_BIT)
+ },
+ {
+ AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(media::PcmType::FIXED_Q_8_24)
+ },
+ {
+ AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(media::PcmType::FLOAT_32_BIT)
+ },
+ {
+ AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(media::PcmType::INT_24_BIT)
+ },
+ {
+ // See the comment in MediaDefs.h.
+ AUDIO_FORMAT_MP3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG)
+ },
+ {
+ AUDIO_FORMAT_AMR_NB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_NB)
+ },
+ {
+ AUDIO_FORMAT_AMR_WB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB)
+ },
+ {
+ // Note: in MediaDefs.cpp MEDIA_MIMETYPE_AUDIO_AAC = "audio/mp4a-latm".
+ AUDIO_FORMAT_AAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_FORMAT)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_MAIN, make_AudioFormatDescription("audio/aac.main")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_LC, make_AudioFormatDescription("audio/aac.lc")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_SSR, make_AudioFormatDescription("audio/aac.ssr")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_LTP, make_AudioFormatDescription("audio/aac.ltp")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_HE_V1, make_AudioFormatDescription("audio/aac.he.v1")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_SCALABLE, make_AudioFormatDescription("audio/aac.scalable")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ERLC, make_AudioFormatDescription("audio/aac.erlc")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_LD, make_AudioFormatDescription("audio/aac.ld")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_HE_V2, make_AudioFormatDescription("audio/aac.he.v2")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ELD, make_AudioFormatDescription("audio/aac.eld")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_XHE, make_AudioFormatDescription("audio/aac.xhe")
+ },
+ // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
+ // ago.
+ {
+ AUDIO_FORMAT_VORBIS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_VORBIS)
+ },
+ {
+ AUDIO_FORMAT_OPUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_OPUS)
+ },
+ {
+ AUDIO_FORMAT_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC3)
+ },
+ {
+ AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_E_AC3_JOC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3_JOC)
+ },
+ {
+ AUDIO_FORMAT_DTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS)
+ },
+ {
+ AUDIO_FORMAT_DTS_HD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_HD)
+ },
+ // In the future, we would like to represent encapsulated bitstreams as
+ // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
+ // specify the format of the encapsulated bitstream.
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_IEC61937,
+ make_AudioFormatDescription(media::PcmType::INT_16_BIT, "audio/x-iec61937")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_DOLBY_TRUEHD, make_AudioFormatDescription("audio/vnd.dolby.truehd")
+ },
+ {
+ AUDIO_FORMAT_EVRC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRC)
+ },
+ {
+ AUDIO_FORMAT_EVRCB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCB)
+ },
+ {
+ AUDIO_FORMAT_EVRCWB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCWB)
+ },
+ {
+ AUDIO_FORMAT_EVRCNW, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCNW)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADIF, make_AudioFormatDescription("audio/aac.adif")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_WMA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_WMA)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")
+ },
+ {
+ AUDIO_FORMAT_AMR_WB_PLUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MP2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)
+ },
+ {
+ AUDIO_FORMAT_QCELP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_QCELP)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")
+ },
+ {
+ AUDIO_FORMAT_FLAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_FLAC)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_ALAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_ALAC)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_MAIN, make_AudioFormatDescription("audio/aac-adts.main")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_LC, make_AudioFormatDescription("audio/aac-adts.lc")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_SSR, make_AudioFormatDescription("audio/aac-adts.ssr")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_LTP, make_AudioFormatDescription("audio/aac-adts.ltp")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_HE_V1, make_AudioFormatDescription("audio/aac-adts.he.v1")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_SCALABLE, make_AudioFormatDescription("audio/aac-adts.scalable")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_ERLC, make_AudioFormatDescription("audio/aac-adts.erlc")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_LD, make_AudioFormatDescription("audio/aac-adts.ld")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_HE_V2, make_AudioFormatDescription("audio/aac-adts.he.v2")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_ELD, make_AudioFormatDescription("audio/aac-adts.eld")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_ADTS_XHE, make_AudioFormatDescription("audio/aac-adts.xhe")
+ },
+ {
+ // Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
+ AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")
+ },
+ {
+ AUDIO_FORMAT_APTX, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_APTX)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")
+ },
+ {
+ // Note: not in the IANA registry. Matches MediaDefs.cpp.
+ AUDIO_FORMAT_AC4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC4)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT, make_AudioFormatDescription("audio/vnd.dolby.mat")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_1_0, make_AudioFormatDescription("audio/vnd.dolby.mat.1.0")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_2_0, make_AudioFormatDescription("audio/vnd.dolby.mat.2.0")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MAT_2_1, make_AudioFormatDescription("audio/vnd.dolby.mat.2.1")
+ },
+ {
+ AUDIO_FORMAT_AAC_LATM, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC)
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_LATM_LC, make_AudioFormatDescription("audio/mp4a-latm.lc")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_LATM_HE_V1, make_AudioFormatDescription("audio/mp4a-latm.he.v1")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_AAC_LATM_HE_V2, make_AudioFormatDescription("audio/mp4a-latm.he.v2")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_ADAPTIVE, make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MPEGH, make_AudioFormatDescription("audio/x-mpegh")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MPEGH_BL_L3, make_AudioFormatDescription("audio/x-mpegh.bl.l3")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MPEGH_BL_L4, make_AudioFormatDescription("audio/x-mpegh.bl.l4")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MPEGH_LC_L3, make_AudioFormatDescription("audio/x-mpegh.lc.l3")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_MPEGH_LC_L4, make_AudioFormatDescription("audio/x-mpegh.lc.l4")
+ },
+ {
+ // Note: not in the IANA registry.
+ AUDIO_FORMAT_IEC60958,
+ make_AudioFormatDescription(media::PcmType::INT_24_BIT, "audio/x-iec60958")
+ },
+ {
+ AUDIO_FORMAT_DTS_UHD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_UHD)
+ },
+ {
+ AUDIO_FORMAT_DRA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DRA)
+ },
+ }};
+ return pairs;
+}
+
+} // namespace
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+ const media::AudioFormatDescription& aidl) {
+ static const std::unordered_map<media::AudioFormatDescription, audio_format_t> m =
+ [](const detail::AudioFormatPairs& f) {
+ std::unordered_map<media::AudioFormatDescription, audio_format_t> r;
+ std::transform(f.begin(), f.end(), std::inserter(r, r.begin()),
+ [](const detail::AudioFormatPair& p) {
+ return std::make_pair(p.second, p.first);
+ });
+ return r;
+ }(getAudioFormatPairs());
+ if (auto it = m.find(aidl); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<media::AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
+ audio_format_t legacy) {
+ static const std::unordered_map<audio_format_t, media::AudioFormatDescription> m =
+ [](const detail::AudioFormatPairs& f) {
+ return std::unordered_map<audio_format_t, media::AudioFormatDescription>(
+ f.begin(), f.end()); }(getAudioFormatPairs());
+ if (auto it = m.find(legacy); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
+ __func__, legacy);
+ return unexpected(BAD_VALUE);
+ }
+}
+
ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(media::AudioGainMode aidl) {
switch (aidl) {
case media::AudioGainMode::JOINT:
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 4652a18..809a26b 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -229,6 +229,7 @@
"libbinder",
"liblog",
"libshmemcompat",
+ "libstagefright_foundation",
"libutils",
"shared-file-region-aidl-cpp",
"framework-permission-aidl-cpp",
@@ -312,6 +313,8 @@
"aidl/android/media/AudioEncapsulationMode.aidl",
"aidl/android/media/AudioEncapsulationMetadataType.aidl",
"aidl/android/media/AudioEncapsulationType.aidl",
+ "aidl/android/media/AudioFormatDescription.aidl",
+ "aidl/android/media/AudioFormatType.aidl",
"aidl/android/media/AudioFormatSys.aidl",
"aidl/android/media/AudioFlag.aidl",
"aidl/android/media/AudioGain.aidl",
@@ -352,6 +355,7 @@
"aidl/android/media/AudioVibratorInfo.aidl",
"aidl/android/media/EffectDescriptor.aidl",
"aidl/android/media/ExtraAudioDescriptor.aidl",
+ "aidl/android/media/PcmType.aidl",
"aidl/android/media/TrackSecondaryOutputInfo.aidl",
],
imports: [
diff --git a/media/libaudioclient/TEST_MAPPING b/media/libaudioclient/TEST_MAPPING
new file mode 100644
index 0000000..d8c18c0
--- /dev/null
+++ b/media/libaudioclient/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "audio_aidl_conversion_tests"
+ }
+ ]
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioFormatDescription.aidl b/media/libaudioclient/aidl/android/media/AudioFormatDescription.aidl
new file mode 100644
index 0000000..a656348
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioFormatDescription.aidl
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.media;
+
+import android.media.AudioFormatType;
+import android.media.PcmType;
+
+/**
+ * An extensible type for specifying audio formats. All formats are largely
+ * divided into two classes: PCM and non-PCM (bitstreams). Bitstreams can
+ * be encapsulated into PCM streams.
+ *
+ * The type defined in a way to make each format uniquely identifiable, so
+ * that if the framework and the HAL construct a value for the same type
+ * (e.g. PCM 16 bit), they will produce identical parcelables which will have
+ * identical hashes. This makes possible deduplicating type descriptions
+ * by the framework when they are received from different HAL modules without
+ * relying on having some centralized registry of enumeration values.
+ *
+ * {@hide}
+ */
+parcelable AudioFormatDescription {
+ /**
+ * The type of the audio format. See the 'AudioFormatType' for the
+ * list of supported values.
+ */
+ AudioFormatType type = AudioFormatType.DEFAULT;
+ /**
+ * The type of the PCM stream or the transport stream for PCM
+ * encapsulations. See 'PcmType' for the list of supported values.
+ */
+ PcmType pcm = PcmType.DEFAULT;
+ /**
+ * Optional encoding specification. Must be left empty when:
+ *
+ * - 'type == DEFAULT && pcm == DEFAULT' -- that means "default" type;
+ * - 'type == PCM' -- that means a regular PCM stream (not an encapsulation
+ * of an encoded bitstream).
+ *
+ * For PCM encapsulations of encoded bitstreams (e.g. an encapsulation
+ * according to IEC-61937 standard), the value of the 'pcm' field must
+ * be set accordingly, as an example, PCM_INT_16_BIT must be used for
+ * IEC-61937. Note that 'type == NON_PCM' in this case.
+ *
+ * Encoding names mostly follow IANA standards for media types (MIME), and
+ * frameworks/av/media/libstagefright/foundation/MediaDefs.cpp with the
+ * latter having priority. Since there are still many audio types not found
+ * in any of these lists, the following rules are applied:
+ *
+ * - If there is a direct MIME type for the encoding, the MIME type name
+ * is used as is, e.g. "audio/eac3" for the EAC-3 format.
+ * - If the encoding is a "subformat" of a MIME-registered format,
+ * the latter is augmented with a suffix, e.g. "audio/eac3-joc" for the
+ * JOC extension of EAC-3.
+ * - If it's a proprietary format, a "vnd." prefix is added, similar to
+ * IANA rules, e.g. "audio/vnd.dolby.truehd".
+ * - Otherwise, "x-" prefix is added, e.g. "audio/x-iec61937".
+ * - All MIME types not found in the IANA formats list have an associated
+ * comment.
+ *
+ * For PCM encapsulations with a known bitstream format, the latter
+ * is added to the encapsulation encoding as a suffix, after a "+" char.
+ * For example, an IEC61937 encapsulation of AC3 has the following
+ * representation:
+ * type = NON_PCM,
+ * pcm = PcmType.INT_16_BIT,
+ * encoding = "audio/x-iec61937+audio/ac3"
+ */
+ @utf8InCpp String encoding;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioFormatType.aidl b/media/libaudioclient/aidl/android/media/AudioFormatType.aidl
new file mode 100644
index 0000000..31ed2be
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioFormatType.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * The type of the audio format. Only used as part of 'AudioFormatDescription'
+ * structure.
+ */
+@Backing(type="byte")
+enum AudioFormatType {
+ /**
+ * "Default" type is used when the client does not care about the actual
+ * format. All fields of 'AudioFormatDescription' must have default / empty
+ * / null values.
+ */
+ DEFAULT = 0,
+ /**
+ * When the 'encoding' field of 'AudioFormatDescription' is not empty, it
+ * specifies the codec used for bitstream (non-PCM) data. It is also used
+ * in the case when the bitstream data is encapsulated into a PCM stream,
+ * see the documentation for 'AudioFormatDescription'.
+ */
+ NON_PCM = DEFAULT,
+ /**
+ * PCM type. The 'pcm' field of 'AudioFormatDescription' is used to specify
+ * the actual sample size and representation.
+ */
+ PCM = 1,
+ /**
+ * Value reserved for system use only. HALs must never return this value to
+ * the system or accept it from the system.
+ */
+ SYS_RESERVED_INVALID = -1,
+}
diff --git a/media/libaudioclient/aidl/android/media/PcmType.aidl b/media/libaudioclient/aidl/android/media/PcmType.aidl
new file mode 100644
index 0000000..c9e327c
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/PcmType.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.media;
+
+/**
+ * The type of the encoding used for representing PCM samples. Only used as
+ * part of 'AudioFormatDescription' structure.
+ */
+@Backing(type="byte")
+enum PcmType {
+ /**
+ * "Default" value used when the type 'AudioFormatDescription' is "default".
+ */
+ DEFAULT = 0,
+ /**
+ * Unsigned 8-bit integer.
+ */
+ UINT_8_BIT = DEFAULT,
+ /**
+ * Signed 16-bit integer.
+ */
+ INT_16_BIT = 1,
+ /**
+ * Signed 32-bit integer.
+ */
+ INT_32_BIT = 2,
+ /**
+ * Q8.24 fixed point format.
+ */
+ FIXED_Q_8_24 = 3,
+ /**
+ * IEEE 754 32-bit floating point format.
+ */
+ FLOAT_32_BIT = 4,
+ /**
+ * Signed 24-bit integer.
+ */
+ INT_24_BIT = 5,
+}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index fc8a1e8..305dbc3 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -30,6 +30,7 @@
#include <android/media/AudioEncapsulationMetadataType.h>
#include <android/media/AudioEncapsulationType.h>
#include <android/media/AudioFlag.h>
+#include <android/media/AudioFormatDescription.h>
#include <android/media/AudioGain.h>
#include <android/media/AudioGainMode.h>
#include <android/media/AudioInputFlags.h>
@@ -138,6 +139,11 @@
ConversionResult<media::AudioFormatSys> legacy2aidl_audio_format_t_AudioFormat(
audio_format_t legacy);
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+ const media::AudioFormatDescription& aidl);
+ConversionResult<media::AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
+ audio_format_t legacy);
+
ConversionResult<audio_gain_mode_t>
aidl2legacy_AudioGainMode_audio_gain_mode_t(media::AudioGainMode aidl);
ConversionResult<media::AudioGainMode>
diff --git a/media/libaudioclient/include/media/AudioCommonTypes.h b/media/libaudioclient/include/media/AudioCommonTypes.h
index 5dfe5fc..607b99c 100644
--- a/media/libaudioclient/include/media/AudioCommonTypes.h
+++ b/media/libaudioclient/include/media/AudioCommonTypes.h
@@ -17,9 +17,39 @@
#pragma once
+#include <functional>
+
+#include <android/media/AudioFormatDescription.h>
+#include <binder/Parcelable.h>
#include <system/audio.h>
#include <system/audio_policy.h>
-#include <binder/Parcelable.h>
+
+namespace {
+// see boost::hash_combine
+#if defined(__clang__)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+static size_t hash_combine(size_t seed, size_t v) {
+ return std::hash<size_t>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+}
+
+namespace std {
+
+// Note: when extending AudioFormatDescription we need to account for the
+// possibility of comparison between different versions of it, e.g. a HAL
+// may be using a previous version of the AIDL interface.
+template<> struct hash<android::media::AudioFormatDescription>
+{
+ std::size_t operator()(const android::media::AudioFormatDescription& afd) const noexcept {
+ return hash_combine(
+ std::hash<android::media::AudioFormatType>{}(afd.type),
+ hash_combine(
+ std::hash<android::media::PcmType>{}(afd.pcm),
+ std::hash<std::string>{}(afd.encoding)));
+ }
+};
+} // namespace std
namespace android {
@@ -45,4 +75,3 @@
static const volume_group_t VOLUME_GROUP_NONE = static_cast<volume_group_t>(-1);
} // namespace android
-
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index def7ca6..2279244 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -9,10 +9,34 @@
cc_defaults {
name: "libaudioclient_tests_defaults",
+ test_suites: ["device-tests"],
cflags: [
"-Wall",
"-Werror",
],
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
+
+cc_test {
+ name: "audio_aidl_conversion_tests",
+ defaults: ["libaudioclient_tests_defaults"],
+ srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "audioclient-types-aidl-cpp",
+ "libaudioclient_aidl_conversion",
+ "libstagefright_foundation",
+ ],
}
cc_test {
@@ -30,8 +54,10 @@
cc_test {
name: "test_create_audiotrack",
defaults: ["libaudioclient_tests_defaults"],
- srcs: ["test_create_audiotrack.cpp",
- "test_create_utils.cpp"],
+ srcs: [
+ "test_create_audiotrack.cpp",
+ "test_create_utils.cpp",
+ ],
header_libs: [
"libmedia_headers",
"libmediametrics_headers",
@@ -49,8 +75,10 @@
cc_test {
name: "test_create_audiorecord",
defaults: ["libaudioclient_tests_defaults"],
- srcs: ["test_create_audiorecord.cpp",
- "test_create_utils.cpp"],
+ srcs: [
+ "test_create_audiorecord.cpp",
+ "test_create_utils.cpp",
+ ],
header_libs: [
"libmedia_headers",
"libmediametrics_headers",
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
new file mode 100644
index 0000000..e4bc9f0
--- /dev/null
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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 <gtest/gtest.h>
+
+#include <media/AudioCommonTypes.h>
+#include <media/AidlConversion.h>
+
+using namespace android;
+using namespace android::aidl_utils;
+
+namespace {
+
+size_t afdHash(const media::AudioFormatDescription& afd) {
+ return std::hash<media::AudioFormatDescription>{}(afd);
+}
+
+media::AudioFormatDescription make_AudioFormatDescription(media::AudioFormatType type) {
+ media::AudioFormatDescription result;
+ result.type = type;
+ return result;
+}
+
+media::AudioFormatDescription make_AudioFormatDescription(media::PcmType pcm) {
+ auto result = make_AudioFormatDescription(media::AudioFormatType::PCM);
+ result.pcm = pcm;
+ return result;
+}
+
+media::AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+ media::AudioFormatDescription result;
+ result.encoding = encoding;
+ return result;
+}
+
+media::AudioFormatDescription make_AudioFormatDescription(media::PcmType transport,
+ const std::string& encoding) {
+ auto result = make_AudioFormatDescription(encoding);
+ result.pcm = transport;
+ return result;
+}
+
+media::AudioFormatDescription make_AFD_Invalid() {
+ return make_AudioFormatDescription(media::AudioFormatType::SYS_RESERVED_INVALID);
+}
+
+media::AudioFormatDescription make_AFD_Pcm16Bit() {
+ return make_AudioFormatDescription(media::PcmType::INT_16_BIT);
+}
+
+media::AudioFormatDescription make_AFD_Bitstream() {
+ return make_AudioFormatDescription("example");
+}
+
+media::AudioFormatDescription make_AFD_Encap() {
+ return make_AudioFormatDescription(media::PcmType::INT_16_BIT, "example.encap");
+}
+
+media::AudioFormatDescription make_AFD_Encap_with_Enc() {
+ auto afd = make_AFD_Encap();
+ afd.encoding += "+example";
+ return afd;
+}
+
+} // namespace
+
+// Verify that two independently constructed AFDs have the same hash.
+// This ensures that regardless of whether the AFD instance originates
+// from, it can be correctly compared to other AFD instance. Thus,
+// for example, a 16-bit integer format description provided by HAL
+// is identical to the same format description constructed by the framework.
+TEST(audio_aidl_legacy_conversion_tests, AudioFormatDescriptionHashIdentity) {
+ EXPECT_EQ(afdHash(make_AFD_Invalid()), afdHash(make_AFD_Invalid()));
+ EXPECT_EQ(afdHash(media::AudioFormatDescription{}), afdHash(media::AudioFormatDescription{}));
+ EXPECT_EQ(afdHash(make_AFD_Pcm16Bit()), afdHash(make_AFD_Pcm16Bit()));
+ EXPECT_NE(afdHash(media::AudioFormatDescription{}), afdHash(make_AFD_Invalid()));
+ EXPECT_NE(afdHash(media::AudioFormatDescription{}), afdHash(make_AFD_Pcm16Bit()));
+ EXPECT_EQ(afdHash(make_AFD_Bitstream()), afdHash(make_AFD_Bitstream()));
+ EXPECT_NE(afdHash(make_AFD_Pcm16Bit()), afdHash(make_AFD_Bitstream()));
+ EXPECT_EQ(afdHash(make_AFD_Encap()), afdHash(make_AFD_Encap()));
+ EXPECT_NE(afdHash(make_AFD_Pcm16Bit()), afdHash(make_AFD_Encap()));
+ EXPECT_EQ(afdHash(make_AFD_Encap_with_Enc()), afdHash(make_AFD_Encap_with_Enc()));
+ EXPECT_NE(afdHash(make_AFD_Encap()), afdHash(make_AFD_Encap_with_Enc()));
+}
+
+class AudioFormatDescriptionRoundTripTest :
+ public testing::TestWithParam<media::AudioFormatDescription> {};
+TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = GetParam();
+ auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_format_t_AudioFormatDescription(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip,
+ AudioFormatDescriptionRoundTripTest,
+ testing::Values(make_AFD_Invalid(), media::AudioFormatDescription{}, make_AFD_Pcm16Bit()));
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index ada5d81..0ec5ad5 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -65,7 +65,17 @@
const char *MEDIA_MIMETYPE_AUDIO_WMA = "audio/x-ms-wma";
const char *MEDIA_MIMETYPE_AUDIO_MS_ADPCM = "audio/x-adpcm-ms";
const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM = "audio/x-adpcm-dvi-ima";
-
+const char *MEDIA_MIMETYPE_AUDIO_DTS = "audio/vnd.dts";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_HD = "audio/vnd.dts.hd";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD = "audio/vnd.dts.uhd";
+const char *MEDIA_MIMETYPE_AUDIO_EVRC = "audio/evrc";
+const char *MEDIA_MIMETYPE_AUDIO_EVRCB = "audio/evrcb";
+const char *MEDIA_MIMETYPE_AUDIO_EVRCWB = "audio/evrcwb";
+const char *MEDIA_MIMETYPE_AUDIO_EVRCNW = "audio/evrcnw";
+const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS = "audio/amr-wb+";
+const char *MEDIA_MIMETYPE_AUDIO_APTX = "audio/aptx";
+const char *MEDIA_MIMETYPE_AUDIO_DRA = "audio/vnd.dra";
+const char *MEDIA_MIMETYPE_AUDIO_AAC_FORMAT = "audio/aac";
const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav";
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index f5cecef..afa0c6d 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -67,7 +67,17 @@
extern const char *MEDIA_MIMETYPE_AUDIO_WMA;
extern const char *MEDIA_MIMETYPE_AUDIO_MS_ADPCM;
extern const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;
-
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_HD;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD;
+extern const char *MEDIA_MIMETYPE_AUDIO_EVRC;
+extern const char *MEDIA_MIMETYPE_AUDIO_EVRCB;
+extern const char *MEDIA_MIMETYPE_AUDIO_EVRCWB;
+extern const char *MEDIA_MIMETYPE_AUDIO_EVRCNW;
+extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS;
+extern const char *MEDIA_MIMETYPE_AUDIO_APTX;
+extern const char *MEDIA_MIMETYPE_AUDIO_DRA;
+extern const char *MEDIA_MIMETYPE_AUDIO_AAC_FORMAT;
extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;