зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1248861: P4. Add AudioConfig and introduce channel layout definition. r=cpearce
Long term goal would be to merge AudioConfig with the existing AudioInfo class which doesn't provide sufficient data to properly determine how to play multichannel audio. MozReview-Commit-ID: 3UDpZWPBUvS
This commit is contained in:
Родитель
ec928c4c2f
Коммит
dd9f244fa3
|
@ -0,0 +1,168 @@
|
|||
/* -*- 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 "MediaInfo.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
|
||||
*/
|
||||
|
||||
void
|
||||
AudioConfig::ChannelLayout::UpdateChannelMap()
|
||||
{
|
||||
mChannelMap = 0;
|
||||
mValid = mChannels.Length() <= MAX_AUDIO_CHANNELS;
|
||||
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)) {
|
||||
mValid = false;
|
||||
}
|
||||
mChannelMap |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ const AudioConfig::Channel*
|
||||
AudioConfig::ChannelLayout::SMPTEDefault(uint32_t aChannels) const
|
||||
{
|
||||
switch (aChannels) {
|
||||
case 1: // MONO
|
||||
{
|
||||
static const Channel config[] = { CHANNEL_MONO };
|
||||
return config;
|
||||
}
|
||||
case 2: // STEREO
|
||||
{
|
||||
static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT };
|
||||
return config;
|
||||
}
|
||||
case 3: // 3F
|
||||
{
|
||||
static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER };
|
||||
return config;
|
||||
}
|
||||
case 4: // 2F2
|
||||
{
|
||||
static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LS, CHANNEL_RS };
|
||||
return config;
|
||||
}
|
||||
case 5: // 3F2
|
||||
{
|
||||
static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LS, CHANNEL_RS };
|
||||
return config;
|
||||
}
|
||||
case 6: // 3F2-LFE
|
||||
{
|
||||
static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_LS, CHANNEL_RS };
|
||||
return config;
|
||||
}
|
||||
case 7: // 3F3R-LFE
|
||||
{
|
||||
static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RCENTER, CHANNEL_LS, CHANNEL_RS };
|
||||
return config;
|
||||
}
|
||||
case 8: // 3F4-LFE
|
||||
{
|
||||
static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RLS, CHANNEL_RRS, CHANNEL_LS, CHANNEL_RS };
|
||||
return config;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
|
@ -474,6 +474,143 @@ public:
|
|||
const nsCString& mMimeType;
|
||||
};
|
||||
|
||||
// Maximum channel number we can currently handle (7.1)
|
||||
#define MAX_AUDIO_CHANNELS 8
|
||||
|
||||
class AudioConfig {
|
||||
public:
|
||||
enum Channel {
|
||||
CHANNEL_INVALID = -1,
|
||||
CHANNEL_MONO = 0,
|
||||
CHANNEL_LEFT,
|
||||
CHANNEL_RIGHT,
|
||||
CHANNEL_CENTER,
|
||||
CHANNEL_LS,
|
||||
CHANNEL_RS,
|
||||
CHANNEL_RLS,
|
||||
CHANNEL_RCENTER,
|
||||
CHANNEL_RRS,
|
||||
CHANNEL_LFE,
|
||||
};
|
||||
|
||||
class ChannelLayout {
|
||||
public:
|
||||
ChannelLayout()
|
||||
: mChannelMap(0)
|
||||
, mValid(false)
|
||||
{}
|
||||
explicit ChannelLayout(uint32_t aChannels)
|
||||
: ChannelLayout(aChannels, SMPTEDefault(aChannels))
|
||||
{}
|
||||
ChannelLayout(uint32_t aChannels, const Channel* aConfig)
|
||||
{
|
||||
mChannels.AppendElements(aConfig, aChannels);
|
||||
UpdateChannelMap();
|
||||
}
|
||||
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
|
||||
{
|
||||
return mChannelMap;
|
||||
}
|
||||
bool IsValid() const {
|
||||
return mValid;
|
||||
}
|
||||
bool HasChannel(Channel aChannel) const
|
||||
{
|
||||
return mChannelMap & (1 << aChannel);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -220,6 +220,7 @@ UNIFIED_SOURCES += [
|
|||
'MediaDeviceInfo.cpp',
|
||||
'MediaDevices.cpp',
|
||||
'MediaFormatReader.cpp',
|
||||
'MediaInfo.cpp',
|
||||
'MediaManager.cpp',
|
||||
'MediaRecorder.cpp',
|
||||
'MediaResource.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче