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:
Jean-Yves Avenard 2016-04-06 10:20:42 +10:00
Родитель ec928c4c2f
Коммит dd9f244fa3
3 изменённых файлов: 306 добавлений и 0 удалений

168
dom/media/MediaInfo.cpp Normal file
Просмотреть файл

@ -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',