зеркало из 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_LFE (AudioConfig::ChannelLayout::L3F1_LFE_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_QUAD (AudioConfig::ChannelLayout::LQUAD_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)
|
||||
|
@ -183,8 +184,10 @@ const layoutInfo kLayoutInfos[CUBEB_LAYOUT_MAX] = {
|
|||
{ "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
|
||||
|
@ -655,6 +658,8 @@ cubeb_channel_layout ConvertChannelMapToCubebLayout(uint32_t aChannelMap)
|
|||
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;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#if !defined(MediaData_h)
|
||||
#define MediaData_h
|
||||
|
||||
#include "AudioConfig.h"
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "ImageTypes.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
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsDataHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "AudioConfig.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "MediaData.h"
|
||||
#include "TrackID.h" // for TrackID
|
||||
|
@ -39,9 +40,6 @@ public:
|
|||
|
||||
typedef nsDataHashtable<nsCStringHashKey, nsCString> MetadataTags;
|
||||
|
||||
// Maximum channel number we can currently handle (7.1)
|
||||
#define MAX_AUDIO_CHANNELS 8
|
||||
|
||||
class TrackInfo
|
||||
{
|
||||
public:
|
||||
|
@ -613,268 +611,6 @@ 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
|
||||
|
|
|
@ -92,6 +92,7 @@ EXPORTS += [
|
|||
'AudioBufferUtils.h',
|
||||
'AudioChannelFormat.h',
|
||||
'AudioCompactor.h',
|
||||
'AudioConfig.h',
|
||||
'AudioConverter.h',
|
||||
'AudioMixer.h',
|
||||
'AudioPacketizer.h',
|
||||
|
@ -208,6 +209,7 @@ UNIFIED_SOURCES += [
|
|||
'AudioCaptureStream.cpp',
|
||||
'AudioChannelFormat.cpp',
|
||||
'AudioCompactor.cpp',
|
||||
'AudioConfig.cpp',
|
||||
'AudioConverter.cpp',
|
||||
'AudioDeviceInfo.cpp',
|
||||
'AudioSegment.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче