зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1431221 - P5. Split AudioConfig.{h,cpp} from MediaInfo. r=padenot
MozReview-Commit-ID: EzaC19HS2B8
This commit is contained in:
Родитель
e9e8bc2708
Коммит
48cf8d7243
|
@ -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
|
|
@ -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
|
|
@ -50,8 +50,9 @@
|
||||||
#define MASK_3F1 (AudioConfig::ChannelLayout::L3F1_MAP)
|
#define MASK_3F1 (AudioConfig::ChannelLayout::L3F1_MAP)
|
||||||
#define MASK_3F1_LFE (AudioConfig::ChannelLayout::L3F1_LFE_MAP)
|
#define MASK_3F1_LFE (AudioConfig::ChannelLayout::L3F1_LFE_MAP)
|
||||||
#define MASK_2F2 (AudioConfig::ChannelLayout::L2F2_MAP)
|
#define MASK_2F2 (AudioConfig::ChannelLayout::L2F2_MAP)
|
||||||
#define MASK_QUAD (AudioConfig::ChannelLayout::LQUAD_MAP)
|
|
||||||
#define MASK_2F2_LFE (AudioConfig::ChannelLayout::L2F2_LFE_MAP)
|
#define MASK_2F2_LFE (AudioConfig::ChannelLayout::L2F2_LFE_MAP)
|
||||||
|
#define MASK_QUAD (AudioConfig::ChannelLayout::LQUAD_MAP)
|
||||||
|
#define MASK_QUAD_LFE (AudioConfig::ChannelLayout::LQUAD_MAP_LFE)
|
||||||
#define MASK_3F2 (AudioConfig::ChannelLayout::L3F2_MAP)
|
#define MASK_3F2 (AudioConfig::ChannelLayout::L3F2_MAP)
|
||||||
#define MASK_3F2_LFE (AudioConfig::ChannelLayout::L3F2_LFE_MAP)
|
#define MASK_3F2_LFE (AudioConfig::ChannelLayout::L3F2_LFE_MAP)
|
||||||
#define MASK_3F3R_LFE (AudioConfig::ChannelLayout::L3F3R_LFE_MAP)
|
#define MASK_3F3R_LFE (AudioConfig::ChannelLayout::L3F3R_LFE_MAP)
|
||||||
|
@ -183,8 +184,10 @@ const layoutInfo kLayoutInfos[CUBEB_LAYOUT_MAX] = {
|
||||||
{ "2f1 lfe", 4, MASK_2F1_LFE }, // CUBEB_LAYOUT_2F1_LFE
|
{ "2f1 lfe", 4, MASK_2F1_LFE }, // CUBEB_LAYOUT_2F1_LFE
|
||||||
{ "3f1", 4, MASK_3F1 }, // CUBEB_LAYOUT_3F1
|
{ "3f1", 4, MASK_3F1 }, // CUBEB_LAYOUT_3F1
|
||||||
{ "3f1 lfe", 5, MASK_3F1_LFE }, // CUBEB_LAYOUT_3F1_LFE
|
{ "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
|
{ "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", 5, MASK_3F2 }, // CUBEB_LAYOUT_3F2
|
||||||
{ "3f2 lfe", 6, MASK_3F2_LFE }, // CUBEB_LAYOUT_3F2_LFE
|
{ "3f2 lfe", 6, MASK_3F2_LFE }, // CUBEB_LAYOUT_3F2_LFE
|
||||||
{ "3f3r lfe", 7, MASK_3F3R_LFE }, // CUBEB_LAYOUT_3F3R_LFE
|
{ "3f3r lfe", 7, MASK_3F3R_LFE }, // CUBEB_LAYOUT_3F3R_LFE
|
||||||
|
@ -655,6 +658,8 @@ cubeb_channel_layout ConvertChannelMapToCubebLayout(uint32_t aChannelMap)
|
||||||
case MASK_3F1_LFE: return CUBEB_LAYOUT_3F1_LFE;
|
case MASK_3F1_LFE: return CUBEB_LAYOUT_3F1_LFE;
|
||||||
case MASK_2F2: return CUBEB_LAYOUT_2F2;
|
case MASK_2F2: return CUBEB_LAYOUT_2F2;
|
||||||
case MASK_2F2_LFE: return CUBEB_LAYOUT_2F2_LFE;
|
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: return CUBEB_LAYOUT_3F2;
|
||||||
case MASK_3F2_LFE: return CUBEB_LAYOUT_3F2_LFE;
|
case MASK_3F2_LFE: return CUBEB_LAYOUT_3F2_LFE;
|
||||||
case MASK_3F3R_LFE: return CUBEB_LAYOUT_3F3R_LFE;
|
case MASK_3F3R_LFE: return CUBEB_LAYOUT_3F3R_LFE;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#if !defined(MediaData_h)
|
#if !defined(MediaData_h)
|
||||||
#define MediaData_h
|
#define MediaData_h
|
||||||
|
|
||||||
|
#include "AudioConfig.h"
|
||||||
#include "AudioSampleFormat.h"
|
#include "AudioSampleFormat.h"
|
||||||
#include "ImageTypes.h"
|
#include "ImageTypes.h"
|
||||||
#include "SharedBuffer.h"
|
#include "SharedBuffer.h"
|
||||||
|
|
|
@ -25,318 +25,4 @@ TrackTypeToStr(TrackInfo::TrackType aTrack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
} // namespace mozilla
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
#include "AudioConfig.h"
|
||||||
#include "ImageTypes.h"
|
#include "ImageTypes.h"
|
||||||
#include "MediaData.h"
|
#include "MediaData.h"
|
||||||
#include "TrackID.h" // for TrackID
|
#include "TrackID.h" // for TrackID
|
||||||
|
@ -39,9 +40,6 @@ public:
|
||||||
|
|
||||||
typedef nsDataHashtable<nsCStringHashKey, nsCString> MetadataTags;
|
typedef nsDataHashtable<nsCStringHashKey, nsCString> MetadataTags;
|
||||||
|
|
||||||
// Maximum channel number we can currently handle (7.1)
|
|
||||||
#define MAX_AUDIO_CHANNELS 8
|
|
||||||
|
|
||||||
class TrackInfo
|
class TrackInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -613,268 +611,6 @@ public:
|
||||||
const nsCString& mMimeType;
|
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
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // MediaInfo_h
|
#endif // MediaInfo_h
|
||||||
|
|
|
@ -92,6 +92,7 @@ EXPORTS += [
|
||||||
'AudioBufferUtils.h',
|
'AudioBufferUtils.h',
|
||||||
'AudioChannelFormat.h',
|
'AudioChannelFormat.h',
|
||||||
'AudioCompactor.h',
|
'AudioCompactor.h',
|
||||||
|
'AudioConfig.h',
|
||||||
'AudioConverter.h',
|
'AudioConverter.h',
|
||||||
'AudioMixer.h',
|
'AudioMixer.h',
|
||||||
'AudioPacketizer.h',
|
'AudioPacketizer.h',
|
||||||
|
@ -208,6 +209,7 @@ UNIFIED_SOURCES += [
|
||||||
'AudioCaptureStream.cpp',
|
'AudioCaptureStream.cpp',
|
||||||
'AudioChannelFormat.cpp',
|
'AudioChannelFormat.cpp',
|
||||||
'AudioCompactor.cpp',
|
'AudioCompactor.cpp',
|
||||||
|
'AudioConfig.cpp',
|
||||||
'AudioConverter.cpp',
|
'AudioConverter.cpp',
|
||||||
'AudioDeviceInfo.cpp',
|
'AudioDeviceInfo.cpp',
|
||||||
'AudioSegment.cpp',
|
'AudioSegment.cpp',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче