new file mode 100644
--- /dev/null
+++ b/dom/media/AudioConfig.cpp
@@ -0,0 +1,349 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AudioConfig.h"
+
+namespace mozilla {
+
+typedef AudioConfig::ChannelLayout ChannelLayout;
+
+/**
+ * AudioConfig::ChannelLayout
+ */
+
+/*
+ SMPTE channel layout (also known as wave order)
+ DUAL-MONO L R
+ DUAL-MONO-LFE L R LFE
+ MONO M
+ MONO-LFE M LFE
+ STEREO L R
+ STEREO-LFE L R LFE
+ 3F L R C
+ 3F-LFE L R C LFE
+ 2F1 L R S
+ 2F1-LFE L R LFE S
+ 3F1 L R C S
+ 3F1-LFE L R C LFE S
+ 2F2 L R LS RS
+ 2F2-LFE L R LFE LS RS
+ 3F2 L R C LS RS
+ 3F2-LFE L R C LFE LS RS
+ 3F3R-LFE L R C LFE BC LS RS
+ 3F4-LFE L R C LFE Rls Rrs LS RS
+*/
+
+ChannelLayout ChannelLayout::LMONO{ CHANNEL_FRONT_CENTER };
+ChannelLayout ChannelLayout::LMONO_LFE{ CHANNEL_FRONT_CENTER, CHANNEL_LFE };
+ChannelLayout ChannelLayout::LSTEREO{ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT };
+ChannelLayout ChannelLayout::LSTEREO_LFE{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_LFE };
+ChannelLayout ChannelLayout::L3F{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_FRONT_CENTER };
+ChannelLayout ChannelLayout::L3F_LFE{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_FRONT_CENTER,
+ CHANNEL_LFE };
+ChannelLayout ChannelLayout::L2F1{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_BACK_CENTER };
+ChannelLayout ChannelLayout::L2F1_LFE{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_LFE,
+ CHANNEL_BACK_CENTER };
+ChannelLayout ChannelLayout::L3F1{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_FRONT_CENTER,
+ CHANNEL_BACK_CENTER };
+ChannelLayout ChannelLayout::LSURROUND = ChannelLayout::L3F1;
+ChannelLayout ChannelLayout::L3F1_LFE{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_FRONT_CENTER,
+ CHANNEL_LFE,
+ CHANNEL_BACK_CENTER };
+ChannelLayout ChannelLayout::L2F2{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_SIDE_LEFT,
+ CHANNEL_SIDE_RIGHT };
+ChannelLayout ChannelLayout::L2F2_LFE{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_LFE,
+ CHANNEL_SIDE_LEFT,
+ CHANNEL_SIDE_RIGHT };
+ChannelLayout ChannelLayout::LQUAD{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_BACK_LEFT,
+ CHANNEL_BACK_RIGHT };
+ChannelLayout ChannelLayout::LQUAD_LFE{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_LFE,
+ CHANNEL_BACK_LEFT,
+ CHANNEL_BACK_RIGHT };
+ChannelLayout ChannelLayout::L3F2{ CHANNEL_FRONT_LEFT,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_FRONT_CENTER,
+ CHANNEL_SIDE_LEFT,
+ CHANNEL_SIDE_RIGHT };
+ChannelLayout ChannelLayout::L3F2_LFE{
+ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
+ CHANNEL_LFE, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT
+};
+ChannelLayout ChannelLayout::L5POINT1_SURROUND = ChannelLayout::L3F2_LFE;
+
+ChannelLayout ChannelLayout::L3F3R_LFE{
+ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE,
+ CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT
+};
+ChannelLayout ChannelLayout::L3F4_LFE{
+ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
+ CHANNEL_LFE, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT,
+ CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT
+};
+ChannelLayout ChannelLayout::L7POINT1_SURROUND = ChannelLayout::L3F4_LFE;
+
+void
+AudioConfig::ChannelLayout::UpdateChannelMap()
+{
+ mValid = mChannels.Length() <= MAX_AUDIO_CHANNELS;
+ mChannelMap = 0;
+ if (mValid) {
+ mChannelMap = Map();
+ mValid = mChannelMap > 0;
+ }
+}
+
+auto
+AudioConfig::ChannelLayout::Map() const -> ChannelMap
+{
+ if (mChannelMap) {
+ return mChannelMap;
+ }
+ ChannelMap map = UNKNOWN_MAP;
+ for (size_t i = 0; i < mChannels.Length() && i <= MAX_AUDIO_CHANNELS; i++) {
+ uint32_t mask = 1 << mChannels[i];
+ if (mChannels[i] == CHANNEL_INVALID || (mChannelMap & mask)) {
+ // Invalid configuration.
+ return 0;
+ }
+ map |= mask;
+ }
+ return map;
+}
+
+const AudioConfig::Channel*
+AudioConfig::ChannelLayout::DefaultLayoutForChannels(uint32_t aChannels) const
+{
+ switch (aChannels) {
+ case 1: // MONO
+ {
+ static const Channel config[] = { CHANNEL_FRONT_CENTER };
+ return config;
+ }
+ case 2: // STEREO
+ {
+ static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT };
+ return config;
+ }
+ case 3: // 3F
+ {
+ static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER };
+ return config;
+ }
+ case 4: // QUAD
+ {
+ static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT };
+ return config;
+ }
+ case 5: // 3F2
+ {
+ static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
+ return config;
+ }
+ case 6: // 3F2-LFE
+ {
+ static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
+ return config;
+ }
+ case 7: // 3F3R-LFE
+ {
+ static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
+ return config;
+ }
+ case 8: // 3F4-LFE
+ {
+ static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
+ return config;
+ }
+ default:
+ return nullptr;
+ }
+}
+
+/* static */ AudioConfig::ChannelLayout
+AudioConfig::ChannelLayout::SMPTEDefault(
+ const ChannelLayout& aChannelLayout)
+{
+ if (!aChannelLayout.IsValid()) {
+ return aChannelLayout;
+ }
+ return SMPTEDefault(aChannelLayout.Map());
+}
+
+/* static */ ChannelLayout
+AudioConfig::ChannelLayout::SMPTEDefault(ChannelMap aMap)
+{
+ MOZ_ASSERT(LMONO_MAP == LMONO.Map());
+ MOZ_ASSERT(LMONO_LFE_MAP == LMONO_LFE.Map());
+ MOZ_ASSERT(LSTEREO_MAP == LSTEREO.Map());
+ MOZ_ASSERT(LSTEREO_LFE_MAP == LSTEREO_LFE.Map());
+ MOZ_ASSERT(L3F_MAP == L3F.Map());
+ MOZ_ASSERT(L3F_LFE_MAP == L3F_LFE.Map());
+ MOZ_ASSERT(L2F1_MAP == L2F1.Map());
+ MOZ_ASSERT(L2F1_LFE_MAP == L2F1_LFE.Map());
+ MOZ_ASSERT(L3F1_MAP == L3F1.Map());
+ MOZ_ASSERT(L3F1_LFE_MAP == L3F1_LFE.Map());
+ MOZ_ASSERT(L2F2_MAP == L2F2.Map());
+ MOZ_ASSERT(L2F2_LFE_MAP == L2F2_LFE.Map());
+ MOZ_ASSERT(LQUAD_MAP == LQUAD.Map());
+ MOZ_ASSERT(L3F2_MAP == L3F2.Map());
+ MOZ_ASSERT(L3F2_LFE_MAP == L3F2_LFE.Map());
+ MOZ_ASSERT(L3F3R_LFE_MAP == L3F3R_LFE.Map());
+ MOZ_ASSERT(L3F4_LFE_MAP == L3F4_LFE.Map());
+
+ // First handle the most common cases.
+ switch (aMap) {
+ case LMONO_MAP: return LMONO;
+ case LMONO_LFE_MAP: return LMONO_LFE;
+ case LSTEREO_MAP: return LSTEREO;
+ case LSTEREO_LFE_MAP : return LSTEREO_LFE;
+ case L3F_MAP: return L3F;
+ case L3F_LFE_MAP: return L3F_LFE;
+ case L2F1_MAP: return L2F1;
+ case L2F1_LFE_MAP: return L2F1_LFE;
+ case L3F1_MAP: return L3F1;
+ case L3F1_LFE_MAP: return L3F1_LFE;
+ case L2F2_MAP: return L2F2;
+ case L2F2_LFE_MAP: return L2F2_LFE;
+ case LQUAD_MAP: return LQUAD;
+ case L3F2_MAP: return L3F2;
+ case L3F2_LFE_MAP: return L3F2_LFE;
+ case L3F3R_LFE_MAP: return L3F3R_LFE;
+ case L3F4_LFE_MAP: return L3F4_LFE;
+ default:
+ break;
+ }
+ AutoTArray<Channel, MAX_AUDIO_CHANNELS> layout;
+ uint32_t channels = 0;
+
+ uint32_t i = 1;
+ while (aMap) {
+ if (aMap & 1) {
+ layout.AppendElement(static_cast<Channel>(i));
+ channels++;
+ if (channels > MAX_AUDIO_CHANNELS) {
+ return ChannelLayout();
+ }
+ }
+ aMap >>= 1;
+ }
+ return ChannelLayout(channels, layout.Elements());
+}
+
+bool
+AudioConfig::ChannelLayout::MappingTable(const ChannelLayout& aOther,
+ uint8_t* aMap) const
+{
+ if (!IsValid() || !aOther.IsValid() ||
+ Map() != aOther.Map()) {
+ return false;
+ }
+ if (!aMap) {
+ return true;
+ }
+ for (uint32_t i = 0; i < Count(); i++) {
+ for (uint32_t j = 0; j < Count(); j++) {
+ if (aOther[j] == mChannels[i]) {
+ aMap[j] = i;
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+/**
+ * AudioConfig::ChannelConfig
+ */
+
+/* static */ const char*
+AudioConfig::FormatToString(AudioConfig::SampleFormat aFormat)
+{
+ switch (aFormat) {
+ case FORMAT_U8: return "unsigned 8 bit";
+ case FORMAT_S16: return "signed 16 bit";
+ case FORMAT_S24: return "signed 24 bit MSB";
+ case FORMAT_S24LSB: return "signed 24 bit LSB";
+ case FORMAT_S32: return "signed 32 bit";
+ case FORMAT_FLT: return "32 bit floating point";
+ case FORMAT_NONE: return "none";
+ default: return "unknown";
+ }
+}
+/* static */ uint32_t
+AudioConfig::SampleSize(AudioConfig::SampleFormat aFormat)
+{
+ switch (aFormat) {
+ case FORMAT_U8: return 1;
+ case FORMAT_S16: return 2;
+ case FORMAT_S24: MOZ_FALLTHROUGH;
+ case FORMAT_S24LSB: MOZ_FALLTHROUGH;
+ case FORMAT_S32: MOZ_FALLTHROUGH;
+ case FORMAT_FLT: return 4;
+ case FORMAT_NONE:
+ default: return 0;
+ }
+}
+
+/* static */ uint32_t
+AudioConfig::FormatToBits(AudioConfig::SampleFormat aFormat)
+{
+ switch (aFormat) {
+ case FORMAT_U8: return 8;
+ case FORMAT_S16: return 16;
+ case FORMAT_S24LSB: MOZ_FALLTHROUGH;
+ case FORMAT_S24: return 24;
+ case FORMAT_S32: MOZ_FALLTHROUGH;
+ case FORMAT_FLT: return 32;
+ case FORMAT_NONE: MOZ_FALLTHROUGH;
+ default: return 0;
+ }
+}
+
+AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aRate,
+ AudioConfig::SampleFormat aFormat, bool aInterleaved)
+ : mChannelLayout(aChannelLayout)
+ , mChannels(aChannelLayout.Count())
+ , mRate(aRate)
+ , mFormat(aFormat)
+ , mInterleaved(aInterleaved)
+{
+}
+
+AudioConfig::AudioConfig(uint32_t aChannels,
+ uint32_t aRate,
+ AudioConfig::SampleFormat aFormat,
+ bool aInterleaved)
+ : mChannelLayout(aChannels)
+ , mChannels(aChannels)
+ , mRate(aRate)
+ , mFormat(aFormat)
+ , mInterleaved(aInterleaved)
+{
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/AudioConfig.h
@@ -0,0 +1,277 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#if !defined(AudioLayout_h)
+#define AudioLayout_h
+
+#include <initializer_list>
+#include <cstdint>
+#include "nsTArray.h"
+
+namespace mozilla {
+
+ // Maximum channel number we can currently handle (7.1)
+#define MAX_AUDIO_CHANNELS 8
+
+class AudioConfig
+{
+public:
+ // Channel definition is conveniently defined to be in the same order as
+ // WAVEFORMAT && SMPTE, even though this is unused for now.
+ enum Channel
+ {
+ CHANNEL_INVALID = -1,
+ CHANNEL_FRONT_LEFT = 0,
+ CHANNEL_FRONT_RIGHT,
+ CHANNEL_FRONT_CENTER,
+ CHANNEL_LFE,
+ CHANNEL_BACK_LEFT,
+ CHANNEL_BACK_RIGHT,
+ CHANNEL_FRONT_LEFT_OF_CENTER,
+ CHANNEL_FRONT_RIGHT_OF_CENTER,
+ CHANNEL_BACK_CENTER,
+ CHANNEL_SIDE_LEFT,
+ CHANNEL_SIDE_RIGHT,
+ // From WAVEFORMAT definition.
+ CHANNEL_TOP_CENTER,
+ CHANNEL_TOP_FRONT_LEFT,
+ CHANNEL_TOP_FRONT_CENTER,
+ CHANNEL_TOP_FRONT_RIGHT,
+ CHANNEL_TOP_BACK_LEFT,
+ CHANNEL_TOP_BACK_CENTER,
+ CHANNEL_TOP_BACK_RIGHT
+ };
+
+ class ChannelLayout
+ {
+ public:
+ typedef uint32_t ChannelMap;
+
+ ChannelLayout() : mChannelMap(0), mValid(false) { }
+ explicit ChannelLayout(uint32_t aChannels)
+ : ChannelLayout(aChannels, DefaultLayoutForChannels(aChannels))
+ {
+ }
+ ChannelLayout(uint32_t aChannels, const Channel* aConfig)
+ : ChannelLayout()
+ {
+ if (aChannels == 0 || !aConfig) {
+ mValid = false;
+ return;
+ }
+ mChannels.AppendElements(aConfig, aChannels);
+ UpdateChannelMap();
+ }
+ explicit ChannelLayout(std::initializer_list<Channel> aChannelList)
+ : ChannelLayout(aChannelList.size(), aChannelList.begin())
+ {
+ }
+ bool operator==(const ChannelLayout& aOther) const
+ {
+ return mChannels == aOther.mChannels;
+ }
+ bool operator!=(const ChannelLayout& aOther) const
+ {
+ return mChannels != aOther.mChannels;
+ }
+ const Channel& operator[](uint32_t aIndex) const
+ {
+ return mChannels[aIndex];
+ }
+ uint32_t Count() const
+ {
+ return mChannels.Length();
+ }
+ ChannelMap Map() const;
+
+ // Calculate the mapping table from the current layout to aOther such that
+ // one can easily go from one layout to the other by doing:
+ // out[channel] = in[map[channel]].
+ // Returns true if the reordering is possible or false otherwise.
+ // If true, then aMap, if set, will be updated to contain the mapping table
+ // allowing conversion from the current layout to aOther.
+ // If aMap is nullptr, then MappingTable can be used to simply determine if
+ // the current layout can be easily reordered to aOther.
+ // aMap must be an array of size MAX_AUDIO_CHANNELS.
+ bool MappingTable(const ChannelLayout& aOther, uint8_t* aMap = nullptr) const;
+ bool IsValid() const { return mValid; }
+ bool HasChannel(Channel aChannel) const
+ {
+ return mChannelMap & (1 << aChannel);
+ }
+
+ static ChannelLayout SMPTEDefault(
+ const ChannelLayout& aChannelLayout);
+ static ChannelLayout SMPTEDefault(ChannelMap aMap);
+
+ static constexpr ChannelMap UNKNOWN_MAP = 0;
+
+ // Common channel layout definitions.
+ static ChannelLayout LMONO;
+ static constexpr ChannelMap LMONO_MAP = 1 << CHANNEL_FRONT_CENTER;
+ static ChannelLayout LMONO_LFE;
+ static constexpr ChannelMap LMONO_LFE_MAP =
+ 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE;
+ static ChannelLayout LSTEREO;
+ static constexpr ChannelMap LSTEREO_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT;
+ static ChannelLayout LSTEREO_LFE;
+ static constexpr ChannelMap LSTEREO_LFE_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE;
+ static ChannelLayout L3F;
+ static constexpr ChannelMap L3F_MAP = 1 << CHANNEL_FRONT_LEFT |
+ 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_FRONT_CENTER;
+ static ChannelLayout L3F_LFE;
+ static constexpr ChannelMap L3F_LFE_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE;
+ static ChannelLayout L2F1;
+ static constexpr ChannelMap L2F1_MAP = 1 << CHANNEL_FRONT_LEFT |
+ 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_BACK_CENTER;
+ static ChannelLayout L2F1_LFE;
+ static constexpr ChannelMap L2F1_LFE_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE |
+ 1 << CHANNEL_BACK_CENTER;
+ static ChannelLayout L3F1;
+ static constexpr ChannelMap L3F1_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_BACK_CENTER;
+ static ChannelLayout LSURROUND; // Same as 3F1
+ static constexpr ChannelMap LSURROUND_MAP = L3F1_MAP;
+ static ChannelLayout L3F1_LFE;
+ static constexpr ChannelMap L3F1_LFE_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_BACK_CENTER;
+ static ChannelLayout L2F2;
+ static constexpr ChannelMap L2F2_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_SIDE_LEFT | 1 << CHANNEL_SIDE_RIGHT;
+ static ChannelLayout L2F2_LFE;
+ static constexpr ChannelMap L2F2_LFE_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE |
+ 1 << CHANNEL_SIDE_LEFT | 1 << CHANNEL_SIDE_RIGHT;
+ static ChannelLayout LQUAD;
+ static constexpr ChannelMap LQUAD_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_BACK_LEFT | 1 << CHANNEL_BACK_RIGHT;
+ static ChannelLayout LQUAD_LFE;
+ static constexpr ChannelMap LQUAD_MAP_LFE =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE |
+ 1 << CHANNEL_BACK_LEFT | 1 << CHANNEL_BACK_RIGHT;
+ static ChannelLayout L3F2;
+ static constexpr ChannelMap L3F2_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_SIDE_LEFT |
+ 1 << CHANNEL_SIDE_RIGHT;
+ static ChannelLayout L3F2_LFE;
+ static constexpr ChannelMap L3F2_LFE_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_SIDE_LEFT |
+ 1 << CHANNEL_SIDE_RIGHT;
+ // 3F2_LFE Alias
+ static ChannelLayout L5POINT1_SURROUND;
+ static constexpr ChannelMap L5POINT1_SURROUND_MAP = L3F2_LFE_MAP;
+ static ChannelLayout L3F3R_LFE;
+ static constexpr ChannelMap L3F3R_LFE_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_BACK_CENTER |
+ 1 << CHANNEL_SIDE_LEFT | 1 << CHANNEL_SIDE_RIGHT;
+ static ChannelLayout L3F4_LFE;
+ static constexpr ChannelMap L3F4_LFE_MAP =
+ 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
+ 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_BACK_LEFT |
+ 1 << CHANNEL_BACK_RIGHT | 1 << CHANNEL_SIDE_LEFT |
+ 1 << CHANNEL_SIDE_RIGHT;
+ // 3F4_LFE Alias
+ static ChannelLayout L7POINT1_SURROUND;
+ static constexpr ChannelMap L7POINT1_SURROUND_MAP = L3F4_LFE_MAP;
+
+ private:
+ void UpdateChannelMap();
+ const Channel* DefaultLayoutForChannels(uint32_t aChannels) const;
+ AutoTArray<Channel, MAX_AUDIO_CHANNELS> mChannels;
+ ChannelMap mChannelMap;
+ bool mValid;
+ };
+
+ enum SampleFormat
+ {
+ FORMAT_NONE = 0,
+ FORMAT_U8,
+ FORMAT_S16,
+ FORMAT_S24LSB,
+ FORMAT_S24,
+ FORMAT_S32,
+ FORMAT_FLT,
+#if defined(MOZ_SAMPLE_TYPE_FLOAT32)
+ FORMAT_DEFAULT = FORMAT_FLT
+#elif defined(MOZ_SAMPLE_TYPE_S16)
+ FORMAT_DEFAULT = FORMAT_S16
+#else
+#error "Not supported audio type"
+#endif
+ };
+
+ AudioConfig(const ChannelLayout& aChannelLayout,
+ uint32_t aRate,
+ AudioConfig::SampleFormat aFormat = FORMAT_DEFAULT,
+ bool aInterleaved = true);
+ // Will create a channel configuration from default SMPTE ordering.
+ AudioConfig(uint32_t aChannels,
+ uint32_t aRate,
+ AudioConfig::SampleFormat aFormat = FORMAT_DEFAULT,
+ bool aInterleaved = true);
+
+ const ChannelLayout& Layout() const { return mChannelLayout; }
+ uint32_t Channels() const
+ {
+ if (!mChannelLayout.IsValid()) {
+ return mChannels;
+ }
+ return mChannelLayout.Count();
+ }
+ uint32_t Rate() const { return mRate; }
+ SampleFormat Format() const { return mFormat; }
+ bool Interleaved() const { return mInterleaved; }
+ bool operator==(const AudioConfig& aOther) const
+ {
+ return mChannelLayout == aOther.mChannelLayout && mRate == aOther.mRate &&
+ mFormat == aOther.mFormat && mInterleaved == aOther.mInterleaved;
+ }
+ bool operator!=(const AudioConfig& aOther) const
+ {
+ return !(*this == aOther);
+ }
+
+ bool IsValid() const
+ {
+ return mChannelLayout.IsValid() && Format() != FORMAT_NONE && Rate() > 0;
+ }
+
+ static const char* FormatToString(SampleFormat aFormat);
+ static uint32_t SampleSize(SampleFormat aFormat);
+ static uint32_t FormatToBits(SampleFormat aFormat);
+
+private:
+ // Channels configuration.
+ ChannelLayout mChannelLayout;
+
+ // Channel count.
+ uint32_t mChannels;
+
+ // Sample rate.
+ uint32_t mRate;
+
+ // Sample format.
+ SampleFormat mFormat;
+
+ bool mInterleaved;
+};
+
+} // namespace mozilla
+
+#endif // AudioLayout_h
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -45,18 +45,19 @@
#define MASK_STEREO_LFE (AudioConfig::ChannelLayout::LSTEREO_LFE_MAP)
#define MASK_3F (AudioConfig::ChannelLayout::L3F_MAP)
#define MASK_3F_LFE (AudioConfig::ChannelLayout::L3F_LFE_MAP)
#define MASK_2F1 (AudioConfig::ChannelLayout::L2F1_MAP)
#define MASK_2F1_LFE (AudioConfig::ChannelLayout::L2F1_LFE_MAP)
#define MASK_3F1 (AudioConfig::ChannelLayout::L3F1_MAP)
#define MASK_3F1_LFE (AudioConfig::ChannelLayout::L3F1_LFE_MAP)
#define MASK_2F2 (AudioConfig::ChannelLayout::L2F2_MAP)
+#define MASK_2F2_LFE (AudioConfig::ChannelLayout::L2F2_LFE_MAP)
#define MASK_QUAD (AudioConfig::ChannelLayout::LQUAD_MAP)
-#define MASK_2F2_LFE (AudioConfig::ChannelLayout::L2F2_LFE_MAP)
+#define MASK_QUAD_LFE (AudioConfig::ChannelLayout::LQUAD_MAP_LFE)
#define MASK_3F2 (AudioConfig::ChannelLayout::L3F2_MAP)
#define MASK_3F2_LFE (AudioConfig::ChannelLayout::L3F2_LFE_MAP)
#define MASK_3F3R_LFE (AudioConfig::ChannelLayout::L3F3R_LFE_MAP)
#define MASK_3F4_LFE (AudioConfig::ChannelLayout::L3F4_LFE_MAP)
#if (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID)) || defined(XP_MACOSX)
#define MOZ_CUBEB_REMOTING
#endif
@@ -178,18 +179,20 @@ const layoutInfo kLayoutInfos[CUBEB_LAYO
{ "stereo", 2, MASK_STEREO }, // CUBEB_LAYOUT_STEREO
{ "stereo lfe", 3, MASK_STEREO_LFE }, // CUBEB_LAYOUT_STEREO_LFE
{ "3f", 3, MASK_3F }, // CUBEB_LAYOUT_3F
{ "3f lfe", 4, MASK_3F_LFE }, // CUBEB_LAYOUT_3F_LFE
{ "2f1", 3, MASK_2F1 }, // CUBEB_LAYOUT_2F1
{ "2f1 lfe", 4, MASK_2F1_LFE }, // CUBEB_LAYOUT_2F1_LFE
{ "3f1", 4, MASK_3F1 }, // CUBEB_LAYOUT_3F1
{ "3f1 lfe", 5, MASK_3F1_LFE }, // CUBEB_LAYOUT_3F1_LFE
- { "2f2", 4, MASK_2F2_LFE }, // CUBEB_LAYOUT_2F2
+ { "2f2", 4, MASK_2F2 }, // CUBEB_LAYOUT_2F2
{ "2f2 lfe", 5, MASK_2F2_LFE }, // CUBEB_LAYOUT_2F2_LFE
+ { "quad", 4, MASK_QUAD }, // CUBEB_LAYOUT_QUAD
+ { "quad lfe", 5, MASK_QUAD_LFE }, // CUBEB_LAYOUT_QUAD_LFE
{ "3f2", 5, MASK_3F2 }, // CUBEB_LAYOUT_3F2
{ "3f2 lfe", 6, MASK_3F2_LFE }, // CUBEB_LAYOUT_3F2_LFE
{ "3f3r lfe", 7, MASK_3F3R_LFE }, // CUBEB_LAYOUT_3F3R_LFE
{ "3f4 lfe", 8, MASK_3F4_LFE } // CUBEB_LAYOUT_3F4_LFE
};
// Prefered samplerate, in Hz (characteristic of the hardware, mixer, platform,
// and API used).
@@ -650,16 +653,18 @@ cubeb_channel_layout ConvertChannelMapTo
case MASK_3F: return CUBEB_LAYOUT_3F;
case MASK_3F_LFE: return CUBEB_LAYOUT_3F_LFE;
case MASK_2F1: return CUBEB_LAYOUT_2F1;
case MASK_2F1_LFE: return CUBEB_LAYOUT_2F1_LFE;
case MASK_3F1: return CUBEB_LAYOUT_3F1;
case MASK_3F1_LFE: return CUBEB_LAYOUT_3F1_LFE;
case MASK_2F2: return CUBEB_LAYOUT_2F2;
case MASK_2F2_LFE: return CUBEB_LAYOUT_2F2_LFE;
+ case MASK_QUAD: return CUBEB_LAYOUT_QUAD;
+ case MASK_QUAD_LFE: return CUBEB_LAYOUT_QUAD_LFE;
case MASK_3F2: return CUBEB_LAYOUT_3F2;
case MASK_3F2_LFE: return CUBEB_LAYOUT_3F2_LFE;
case MASK_3F3R_LFE: return CUBEB_LAYOUT_3F3R_LFE;
case MASK_3F4_LFE: return CUBEB_LAYOUT_3F4_LFE;
default:
NS_ERROR("The channel map is unsupported");
return CUBEB_LAYOUT_UNDEFINED;
}
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -1,16 +1,17 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if !defined(MediaData_h)
#define MediaData_h
+#include "AudioConfig.h"
#include "AudioSampleFormat.h"
#include "ImageTypes.h"
#include "SharedBuffer.h"
#include "TimeUnits.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/PodOperations.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Span.h"
--- a/dom/media/MediaInfo.cpp
+++ b/dom/media/MediaInfo.cpp
@@ -20,323 +20,9 @@ TrackTypeToStr(TrackInfo::TrackType aTra
return "Video";
case TrackInfo::kTextTrack:
return "Text";
default:
return "Unknown";
}
}
-typedef AudioConfig::ChannelLayout ChannelLayout;
-
-/**
- * AudioConfig::ChannelLayout
- */
-
-/*
- SMPTE channel layout (also known as wave order)
- DUAL-MONO L R
- DUAL-MONO-LFE L R LFE
- MONO M
- MONO-LFE M LFE
- STEREO L R
- STEREO-LFE L R LFE
- 3F L R C
- 3F-LFE L R C LFE
- 2F1 L R S
- 2F1-LFE L R LFE S
- 3F1 L R C S
- 3F1-LFE L R C LFE S
- 2F2 L R LS RS
- 2F2-LFE L R LFE LS RS
- 3F2 L R C LS RS
- 3F2-LFE L R C LFE LS RS
- 3F3R-LFE L R C LFE BC LS RS
- 3F4-LFE L R C LFE Rls Rrs LS RS
-*/
-
-ChannelLayout ChannelLayout::LMONO{ CHANNEL_FRONT_CENTER };
-ChannelLayout ChannelLayout::LMONO_LFE{ CHANNEL_FRONT_CENTER, CHANNEL_LFE };
-ChannelLayout ChannelLayout::LSTEREO{ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT };
-ChannelLayout ChannelLayout::LSTEREO_LFE{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_LFE };
-ChannelLayout ChannelLayout::L3F{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_FRONT_CENTER };
-ChannelLayout ChannelLayout::L3F_LFE{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_FRONT_CENTER,
- CHANNEL_LFE };
-ChannelLayout ChannelLayout::L2F1{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_BACK_CENTER };
-ChannelLayout ChannelLayout::L2F1_LFE{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_LFE,
- CHANNEL_BACK_CENTER };
-ChannelLayout ChannelLayout::L3F1{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_FRONT_CENTER,
- CHANNEL_BACK_CENTER };
-ChannelLayout ChannelLayout::LSURROUND = ChannelLayout::L3F1;
-ChannelLayout ChannelLayout::L3F1_LFE{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_FRONT_CENTER,
- CHANNEL_LFE,
- CHANNEL_BACK_CENTER };
-ChannelLayout ChannelLayout::L2F2{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_SIDE_LEFT,
- CHANNEL_SIDE_RIGHT };
-ChannelLayout ChannelLayout::L2F2_LFE{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_LFE,
- CHANNEL_SIDE_LEFT,
- CHANNEL_SIDE_RIGHT };
-ChannelLayout ChannelLayout::LQUAD{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_BACK_LEFT,
- CHANNEL_BACK_RIGHT };
-ChannelLayout ChannelLayout::LQUAD_LFE{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_LFE,
- CHANNEL_BACK_LEFT,
- CHANNEL_BACK_RIGHT };
-ChannelLayout ChannelLayout::L3F2{ CHANNEL_FRONT_LEFT,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_FRONT_CENTER,
- CHANNEL_SIDE_LEFT,
- CHANNEL_SIDE_RIGHT };
-ChannelLayout ChannelLayout::L3F2_LFE{
- CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
- CHANNEL_LFE, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT
-};
-ChannelLayout ChannelLayout::L5POINT1_SURROUND = ChannelLayout::L3F2_LFE;
-
-ChannelLayout ChannelLayout::L3F3R_LFE{
- CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE,
- CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT
-};
-ChannelLayout ChannelLayout::L3F4_LFE{
- CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
- CHANNEL_LFE, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT,
- CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT
-};
-ChannelLayout ChannelLayout::L7POINT1_SURROUND = ChannelLayout::L3F4_LFE;
-
-void
-AudioConfig::ChannelLayout::UpdateChannelMap()
-{
- mValid = mChannels.Length() <= MAX_AUDIO_CHANNELS;
- mChannelMap = 0;
- if (mValid) {
- mChannelMap = Map();
- mValid = mChannelMap > 0;
- }
-}
-
-uint32_t
-AudioConfig::ChannelLayout::Map() const
-{
- if (mChannelMap) {
- return mChannelMap;
- }
- uint32_t map = 0;
- for (size_t i = 0; i < mChannels.Length() && i <= MAX_AUDIO_CHANNELS; i++) {
- uint32_t mask = 1 << mChannels[i];
- if (mChannels[i] == CHANNEL_INVALID || (mChannelMap & mask)) {
- // Invalid configuration.
- return 0;
- }
- map |= mask;
- }
- return map;
-}
-
-/* static */ const AudioConfig::Channel*
-AudioConfig::ChannelLayout::SMPTEDefault(uint32_t aChannels) const
-{
- switch (aChannels) {
- case 1: // MONO
- {
- static const Channel config[] = { CHANNEL_FRONT_CENTER };
- return config;
- }
- case 2: // STEREO
- {
- static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT };
- return config;
- }
- case 3: // 3F
- {
- static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER };
- return config;
- }
- case 4: // 2F2
- {
- static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT };
- return config;
- }
- case 5: // 3F2
- {
- static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
- return config;
- }
- case 6: // 3F2-LFE
- {
- static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
- return config;
- }
- case 7: // 3F3R-LFE
- {
- static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
- return config;
- }
- case 8: // 3F4-LFE
- {
- static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
- return config;
- }
- default:
- return nullptr;
- }
-}
-
-/* static */ const AudioConfig::ChannelLayout&
-AudioConfig::ChannelLayout::SMPTEDefault(
- const ChannelLayout& aChannelLayout)
-{
- MOZ_ASSERT(LMONO_MAP == LMONO.Map());
- MOZ_ASSERT(LMONO_LFE_MAP == LMONO_LFE.Map());
- MOZ_ASSERT(LSTEREO_MAP == LSTEREO.Map());
- MOZ_ASSERT(LSTEREO_LFE_MAP == LSTEREO_LFE.Map());
- MOZ_ASSERT(L3F_MAP == L3F.Map());
- MOZ_ASSERT(L3F_LFE_MAP == L3F_LFE.Map());
- MOZ_ASSERT(L2F1_MAP == L2F1.Map());
- MOZ_ASSERT(L2F1_LFE_MAP == L2F1_LFE.Map());
- MOZ_ASSERT(L3F1_MAP == L3F1.Map());
- MOZ_ASSERT(L3F1_LFE_MAP == L3F1_LFE.Map());
- MOZ_ASSERT(L2F2_MAP == L2F2.Map());
- MOZ_ASSERT(L2F2_LFE_MAP == L2F2_LFE.Map());
- MOZ_ASSERT(LQUAD_MAP == LQUAD.Map());
- MOZ_ASSERT(L3F2_MAP == L3F2.Map());
- MOZ_ASSERT(L3F2_LFE_MAP == L3F2_LFE.Map());
- MOZ_ASSERT(L3F3R_LFE_MAP == L3F3R_LFE.Map());
- MOZ_ASSERT(L3F4_LFE_MAP == L3F4_LFE.Map());
-
- if (!aChannelLayout.IsValid()) {
- return aChannelLayout;
- }
- const uint32_t map = aChannelLayout.Map();
- switch (map) {
- case LMONO_MAP: return LMONO;
- case LMONO_LFE_MAP: return LMONO_LFE;
- case LSTEREO_MAP: return LSTEREO;
- case LSTEREO_LFE_MAP : return LSTEREO_LFE;
- case L3F_MAP: return L3F;
- case L3F_LFE_MAP: return L3F_LFE;
- case L2F1_MAP: return L2F1;
- case L2F1_LFE_MAP: return L2F1_LFE;
- case L3F1_MAP: return L3F1;
- case L3F1_LFE_MAP: return L3F1_LFE;
- case L2F2_MAP: return L2F2;
- case L2F2_LFE_MAP: return L2F2_LFE;
- case LQUAD_MAP: return LQUAD;
- case L3F2_MAP: return L3F2;
- case L3F2_LFE_MAP: return L3F2_LFE;
- case L3F3R_LFE_MAP: return L3F3R_LFE;
- case L3F4_LFE_MAP: return L3F4_LFE;
- default:
- // unknown return identical.
- return aChannelLayout;
- }
-}
-
-bool
-AudioConfig::ChannelLayout::MappingTable(const ChannelLayout& aOther,
- uint8_t* aMap) const
-{
- if (!IsValid() || !aOther.IsValid() ||
- Map() != aOther.Map()) {
- return false;
- }
- if (!aMap) {
- return true;
- }
- for (uint32_t i = 0; i < Count(); i++) {
- for (uint32_t j = 0; j < Count(); j++) {
- if (aOther[j] == mChannels[i]) {
- aMap[j] = i;
- break;
- }
- }
- }
- return true;
-}
-
-/**
- * AudioConfig::ChannelConfig
- */
-
-/* static */ const char*
-AudioConfig::FormatToString(AudioConfig::SampleFormat aFormat)
-{
- switch (aFormat) {
- case FORMAT_U8: return "unsigned 8 bit";
- case FORMAT_S16: return "signed 16 bit";
- case FORMAT_S24: return "signed 24 bit MSB";
- case FORMAT_S24LSB: return "signed 24 bit LSB";
- case FORMAT_S32: return "signed 32 bit";
- case FORMAT_FLT: return "32 bit floating point";
- case FORMAT_NONE: return "none";
- default: return "unknown";
- }
-}
-/* static */ uint32_t
-AudioConfig::SampleSize(AudioConfig::SampleFormat aFormat)
-{
- switch (aFormat) {
- case FORMAT_U8: return 1;
- case FORMAT_S16: return 2;
- case FORMAT_S24: MOZ_FALLTHROUGH;
- case FORMAT_S24LSB: MOZ_FALLTHROUGH;
- case FORMAT_S32: MOZ_FALLTHROUGH;
- case FORMAT_FLT: return 4;
- case FORMAT_NONE:
- default: return 0;
- }
-}
-
-/* static */ uint32_t
-AudioConfig::FormatToBits(AudioConfig::SampleFormat aFormat)
-{
- switch (aFormat) {
- case FORMAT_U8: return 8;
- case FORMAT_S16: return 16;
- case FORMAT_S24LSB: MOZ_FALLTHROUGH;
- case FORMAT_S24: return 24;
- case FORMAT_S32: MOZ_FALLTHROUGH;
- case FORMAT_FLT: return 32;
- case FORMAT_NONE: MOZ_FALLTHROUGH;
- default: return 0;
- }
-}
-
-AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aRate,
- AudioConfig::SampleFormat aFormat, bool aInterleaved)
- : mChannelLayout(aChannelLayout)
- , mChannels(aChannelLayout.Count())
- , mRate(aRate)
- , mFormat(aFormat)
- , mInterleaved(aInterleaved)
-{}
-
-AudioConfig::AudioConfig(uint32_t aChannels, uint32_t aRate,
- AudioConfig::SampleFormat aFormat, bool aInterleaved)
- : mChannelLayout(aChannels)
- , mChannels(aChannels)
- , mRate(aRate)
- , mFormat(aFormat)
- , mInterleaved(aInterleaved)
-{}
-
} // namespace mozilla
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -6,16 +6,17 @@
#if !defined(MediaInfo_h)
#define MediaInfo_h
#include "mozilla/UniquePtr.h"
#include "mozilla/RefPtr.h"
#include "nsDataHashtable.h"
#include "nsString.h"
#include "nsTArray.h"
+#include "AudioConfig.h"
#include "ImageTypes.h"
#include "MediaData.h"
#include "TrackID.h" // for TrackID
#include "TimeUnits.h"
#include "mozilla/gfx/Point.h" // for gfx::IntSize
#include "mozilla/gfx/Rect.h" // for gfx::IntRect
namespace mozilla {
@@ -34,19 +35,16 @@ public:
{
}
nsCString mKey;
nsCString mValue;
};
typedef nsDataHashtable<nsCStringHashKey, nsCString> MetadataTags;
- // Maximum channel number we can currently handle (7.1)
-#define MAX_AUDIO_CHANNELS 8
-
class TrackInfo
{
public:
enum TrackType
{
kUndefinedTrack,
kAudioTrack,
kVideoTrack,
@@ -608,273 +606,11 @@ private:
UniquePtr<TrackInfo> mInfo;
// A unique ID, guaranteed to change when changing streams.
uint32_t mStreamSourceID;
public:
const nsCString& mMimeType;
};
-class AudioConfig
-{
-public:
- // Channel definition is conveniently defined to be in the same order as
- // WAVEFORMAT && SMPTE, even though this is unused for now.
- enum Channel
- {
- CHANNEL_INVALID = -1,
- CHANNEL_FRONT_LEFT = 0,
- CHANNEL_FRONT_RIGHT,
- CHANNEL_FRONT_CENTER,
- CHANNEL_LFE,
- CHANNEL_BACK_LEFT,
- CHANNEL_BACK_RIGHT,
- CHANNEL_FRONT_LEFT_OF_CENTER,
- CHANNEL_FRONT_RIGHT_OF_CENTER,
- CHANNEL_BACK_CENTER,
- CHANNEL_SIDE_LEFT,
- CHANNEL_SIDE_RIGHT,
- // From WAVEFORMAT definition.
- CHANNEL_TOP_CENTER,
- CHANNEL_TOP_FRONT_LEFT,
- CHANNEL_TOP_FRONT_CENTER,
- CHANNEL_TOP_FRONT_RIGHT,
- CHANNEL_TOP_BACK_LEFT,
- CHANNEL_TOP_BACK_CENTER,
- CHANNEL_TOP_BACK_RIGHT
- };
-
- class ChannelLayout
- {
- public:
- ChannelLayout() : mChannelMap(0), mValid(false) { }
- explicit ChannelLayout(uint32_t aChannels)
- : ChannelLayout(aChannels, SMPTEDefault(aChannels))
- {
- }
- ChannelLayout(uint32_t aChannels, const Channel* aConfig)
- : ChannelLayout()
- {
- if (aChannels == 0 || !aConfig) {
- mValid = false;
- return;
- }
- mChannels.AppendElements(aConfig, aChannels);
- UpdateChannelMap();
- }
- ChannelLayout(std::initializer_list<Channel> aChannelList)
- : ChannelLayout(aChannelList.size(), aChannelList.begin())
- {
- }
- bool operator==(const ChannelLayout& aOther) const
- {
- return mChannels == aOther.mChannels;
- }
- bool operator!=(const ChannelLayout& aOther) const
- {
- return mChannels != aOther.mChannels;
- }
- const Channel& operator[](uint32_t aIndex) const
- {
- return mChannels[aIndex];
- }
- uint32_t Count() const
- {
- return mChannels.Length();
- }
- uint32_t Map() const;
-
- // Calculate the mapping table from the current layout to aOther such that
- // one can easily go from one layout to the other by doing:
- // out[channel] = in[map[channel]].
- // Returns true if the reordering is possible or false otherwise.
- // If true, then aMap, if set, will be updated to contain the mapping table
- // allowing conversion from the current layout to aOther.
- // If aMap is nullptr, then MappingTable can be used to simply determine if
- // the current layout can be easily reordered to aOther.
- // aMap must be an array of size MAX_AUDIO_CHANNELS.
- bool MappingTable(const ChannelLayout& aOther, uint8_t* aMap = nullptr) const;
- bool IsValid() const { return mValid; }
- bool HasChannel(Channel aChannel) const
- {
- return mChannelMap & (1 << aChannel);
- }
-
- static const ChannelLayout& SMPTEDefault(
- const ChannelLayout& aChannelLayout);
-
- // Common channel layout definitions.
- static ChannelLayout LMONO;
- static constexpr uint32_t LMONO_MAP = 1 << CHANNEL_FRONT_CENTER;
- static ChannelLayout LMONO_LFE;
- static constexpr uint32_t LMONO_LFE_MAP =
- 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE;
- static ChannelLayout LSTEREO;
- static constexpr uint32_t LSTEREO_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT;
- static ChannelLayout LSTEREO_LFE;
- static constexpr uint32_t LSTEREO_LFE_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE;
- static ChannelLayout L3F;
- static constexpr uint32_t L3F_MAP = 1 << CHANNEL_FRONT_LEFT |
- 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_FRONT_CENTER;
- static ChannelLayout L3F_LFE;
- static constexpr uint32_t L3F_LFE_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE;
- static ChannelLayout L2F1;
- static constexpr uint32_t L2F1_MAP = 1 << CHANNEL_FRONT_LEFT |
- 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_BACK_CENTER;
- static ChannelLayout L2F1_LFE;
- static constexpr uint32_t L2F1_LFE_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE |
- 1 << CHANNEL_BACK_CENTER;
- static ChannelLayout L3F1;
- static constexpr uint32_t L3F1_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_BACK_CENTER;
- static ChannelLayout LSURROUND; // Same as 3F1
- static constexpr uint32_t LSURROUND_MAP = L3F1_MAP;
- static ChannelLayout L3F1_LFE;
- static constexpr uint32_t L3F1_LFE_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_BACK_CENTER;
- static ChannelLayout L2F2;
- static constexpr uint32_t L2F2_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_SIDE_LEFT | 1 << CHANNEL_SIDE_RIGHT;
- static ChannelLayout L2F2_LFE;
- static constexpr uint32_t L2F2_LFE_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE |
- 1 << CHANNEL_SIDE_LEFT | 1 << CHANNEL_SIDE_RIGHT;
- static ChannelLayout LQUAD;
- static constexpr uint32_t LQUAD_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_BACK_LEFT | 1 << CHANNEL_BACK_RIGHT;
- static ChannelLayout LQUAD_LFE;
- static constexpr uint32_t LQUAD_MAP_LFE =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT | 1 << CHANNEL_LFE |
- 1 << CHANNEL_BACK_LEFT | 1 << CHANNEL_BACK_RIGHT;
- static ChannelLayout L3F2;
- static constexpr uint32_t L3F2_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_SIDE_LEFT |
- 1 << CHANNEL_SIDE_RIGHT;
- static ChannelLayout L3F2_LFE;
- static constexpr uint32_t L3F2_LFE_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_SIDE_LEFT |
- 1 << CHANNEL_SIDE_RIGHT;
- // 3F2_LFE Alias
- static ChannelLayout L5POINT1_SURROUND;
- static constexpr uint32_t L5POINT1_SURROUND_MAP = L3F2_LFE_MAP;
- static ChannelLayout L3F3R_LFE;
- static constexpr uint32_t L3F3R_LFE_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_BACK_CENTER |
- 1 << CHANNEL_SIDE_LEFT | 1 << CHANNEL_SIDE_RIGHT;
- static ChannelLayout L3F4_LFE;
- static constexpr uint32_t L3F4_LFE_MAP =
- 1 << CHANNEL_FRONT_LEFT | 1 << CHANNEL_FRONT_RIGHT |
- 1 << CHANNEL_FRONT_CENTER | 1 << CHANNEL_LFE | 1 << CHANNEL_BACK_LEFT |
- 1 << CHANNEL_BACK_RIGHT | 1 << CHANNEL_SIDE_LEFT |
- 1 << CHANNEL_SIDE_RIGHT;
- // 3F4_LFE Alias
- static ChannelLayout L7POINT1_SURROUND;
- static constexpr uint32_t L7POINT1_SURROUND_MAP = L3F4_LFE_MAP;
-
- private:
- void UpdateChannelMap();
- const Channel* SMPTEDefault(uint32_t aChannels) const;
- AutoTArray<Channel, MAX_AUDIO_CHANNELS> mChannels;
- uint32_t mChannelMap;
- bool mValid;
- };
-
- enum SampleFormat
- {
- FORMAT_NONE = 0,
- FORMAT_U8,
- FORMAT_S16,
- FORMAT_S24LSB,
- FORMAT_S24,
- FORMAT_S32,
- FORMAT_FLT,
-#if defined(MOZ_SAMPLE_TYPE_FLOAT32)
- FORMAT_DEFAULT = FORMAT_FLT
-#elif defined(MOZ_SAMPLE_TYPE_S16)
- FORMAT_DEFAULT = FORMAT_S16
-#else
-#error "Not supported audio type"
-#endif
- };
-
- AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aRate,
- AudioConfig::SampleFormat aFormat = FORMAT_DEFAULT,
- bool aInterleaved = true);
- // Will create a channel configuration from default SMPTE ordering.
- AudioConfig(uint32_t aChannels, uint32_t aRate,
- AudioConfig::SampleFormat aFormat = FORMAT_DEFAULT,
- bool aInterleaved = true);
-
- const ChannelLayout& Layout() const
- {
- return mChannelLayout;
- }
- uint32_t Channels() const
- {
- if (!mChannelLayout.IsValid()) {
- return mChannels;
- }
- return mChannelLayout.Count();
- }
- uint32_t Rate() const
- {
- return mRate;
- }
- SampleFormat Format() const
- {
- return mFormat;
- }
- bool Interleaved() const
- {
- return mInterleaved;
- }
- bool operator==(const AudioConfig& aOther) const
- {
- return mChannelLayout == aOther.mChannelLayout && mRate == aOther.mRate &&
- mFormat == aOther.mFormat && mInterleaved == aOther.mInterleaved;
- }
- bool operator!=(const AudioConfig& aOther) const
- {
- return !(*this == aOther);
- }
-
- bool IsValid() const
- {
- return mChannelLayout.IsValid() && Format() != FORMAT_NONE && Rate() > 0;
- }
-
- static const char* FormatToString(SampleFormat aFormat);
- static uint32_t SampleSize(SampleFormat aFormat);
- static uint32_t FormatToBits(SampleFormat aFormat);
-
-private:
- // Channels configuration.
- ChannelLayout mChannelLayout;
-
- // Channel count.
- uint32_t mChannels;
-
- // Sample rate.
- uint32_t mRate;
-
- // Sample format.
- SampleFormat mFormat;
-
- bool mInterleaved;
-};
-
} // namespace mozilla
#endif // MediaInfo_h
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -87,16 +87,17 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'dom_media'
EXPORTS += [
'ADTSDecoder.h',
'ADTSDemuxer.h',
'AudioBufferUtils.h',
'AudioChannelFormat.h',
'AudioCompactor.h',
+ 'AudioConfig.h',
'AudioConverter.h',
'AudioMixer.h',
'AudioPacketizer.h',
'AudioSampleFormat.h',
'AudioSegment.h',
'AudioStream.h',
'AutoplayPolicy.h',
'BackgroundVideoDecodingPermissionObserver.h',
@@ -203,16 +204,17 @@ EXPORTS.mozilla.dom += [
]
UNIFIED_SOURCES += [
'ADTSDecoder.cpp',
'ADTSDemuxer.cpp',
'AudioCaptureStream.cpp',
'AudioChannelFormat.cpp',
'AudioCompactor.cpp',
+ 'AudioConfig.cpp',
'AudioConverter.cpp',
'AudioDeviceInfo.cpp',
'AudioSegment.cpp',
'AudioStream.cpp',
'AudioStreamTrack.cpp',
'AudioTrack.cpp',
'AudioTrackList.cpp',
'AutoplayPolicy.cpp',