diff options
author | Jeremy Andrews <athenian200@outlook.com> | 2021-08-24 16:07:22 -0500 |
---|---|---|
committer | Jeremy Andrews <athenian200@outlook.com> | 2021-08-24 16:07:22 -0500 |
commit | 89c3761e5c995efbd5d6039f938773c5259e947d (patch) | |
tree | 8eeb25f606609001ff30ee287ad74c8356a90c17 /dom/media/MediaInfo.cpp | |
parent | 893fc903790e1ca5bba598113c49d94a165e333b (diff) | |
download | uxp-89c3761e5c995efbd5d6039f938773c5259e947d.tar.gz |
Issue #1806 - Part 5: Add multichannel audio capability.
I'm positive this works on Windows at the very least. Cubeb added proper channel map support at some point, and this allows us to take advantage of that.
Ref: BZ 1431221, BZ 1432779
Diffstat (limited to 'dom/media/MediaInfo.cpp')
-rw-r--r-- | dom/media/MediaInfo.cpp | 194 |
1 files changed, 180 insertions, 14 deletions
diff --git a/dom/media/MediaInfo.cpp b/dom/media/MediaInfo.cpp index 568183e688..28b9e77828 100644 --- a/dom/media/MediaInfo.cpp +++ b/dom/media/MediaInfo.cpp @@ -35,69 +35,235 @@ typedef AudioConfig::ChannelLayout ChannelLayout; 3F4-LFE L R C LFE Rls Rrs LS RS */ +ChannelLayout ChannelLayout::LMONO{ AudioConfig::CHANNEL_FRONT_CENTER }; +ChannelLayout ChannelLayout::LMONO_LFE{ AudioConfig::CHANNEL_FRONT_CENTER, AudioConfig::CHANNEL_LFE }; +ChannelLayout ChannelLayout::LSTEREO{ AudioConfig::CHANNEL_FRONT_LEFT, AudioConfig::CHANNEL_FRONT_RIGHT }; +ChannelLayout ChannelLayout::LSTEREO_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_LFE }; +ChannelLayout ChannelLayout::L3F{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_FRONT_CENTER }; +ChannelLayout ChannelLayout::L3F_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_FRONT_CENTER, + AudioConfig::CHANNEL_LFE }; +ChannelLayout ChannelLayout::L2F1{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_BACK_CENTER }; +ChannelLayout ChannelLayout::L2F1_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_LFE, + AudioConfig::CHANNEL_BACK_CENTER }; +ChannelLayout ChannelLayout::L3F1{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_FRONT_CENTER, + AudioConfig::CHANNEL_BACK_CENTER }; +ChannelLayout ChannelLayout::LSURROUND = ChannelLayout::L3F1; +ChannelLayout ChannelLayout::L3F1_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_FRONT_CENTER, + AudioConfig::CHANNEL_LFE, + AudioConfig::CHANNEL_BACK_CENTER }; +ChannelLayout ChannelLayout::L2F2{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_SIDE_LEFT, + AudioConfig::CHANNEL_SIDE_RIGHT }; +ChannelLayout ChannelLayout::L2F2_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_LFE, + AudioConfig::CHANNEL_SIDE_LEFT, + AudioConfig::CHANNEL_SIDE_RIGHT }; +ChannelLayout ChannelLayout::LQUAD{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_BACK_LEFT, + AudioConfig::CHANNEL_BACK_RIGHT }; +ChannelLayout ChannelLayout::LQUAD_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_LFE, + AudioConfig::CHANNEL_BACK_LEFT, + AudioConfig::CHANNEL_BACK_RIGHT }; +ChannelLayout ChannelLayout::L3F2{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_FRONT_CENTER, + AudioConfig::CHANNEL_SIDE_LEFT, + AudioConfig::CHANNEL_SIDE_RIGHT }; +ChannelLayout ChannelLayout::L3F2_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_FRONT_CENTER, + AudioConfig::CHANNEL_LFE, + AudioConfig::CHANNEL_SIDE_LEFT, + AudioConfig::CHANNEL_SIDE_RIGHT }; +ChannelLayout ChannelLayout::L5POINT1_SURROUND = ChannelLayout::L3F2_LFE; + +ChannelLayout ChannelLayout::L3F3R_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_FRONT_CENTER, + AudioConfig::CHANNEL_LFE, + AudioConfig::CHANNEL_BACK_CENTER, + AudioConfig::CHANNEL_SIDE_LEFT, + AudioConfig::CHANNEL_SIDE_RIGHT }; +ChannelLayout ChannelLayout::L3F4_LFE{ AudioConfig::CHANNEL_FRONT_LEFT, + AudioConfig::CHANNEL_FRONT_RIGHT, + AudioConfig::CHANNEL_FRONT_CENTER, + AudioConfig::CHANNEL_LFE, + AudioConfig::CHANNEL_BACK_LEFT, + AudioConfig::CHANNEL_BACK_RIGHT, + AudioConfig::CHANNEL_SIDE_LEFT, + AudioConfig::CHANNEL_SIDE_RIGHT }; +ChannelLayout ChannelLayout::L7POINT1_SURROUND = ChannelLayout::L3F4_LFE; + void AudioConfig::ChannelLayout::UpdateChannelMap() { - mChannelMap = 0; 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)) { - mValid = false; + // Invalid configuration. + return 0; } - mChannelMap |= mask; + map |= mask; } + return map; } -/* static */ const AudioConfig::Channel* -AudioConfig::ChannelLayout::SMPTEDefault(uint32_t aChannels) const +const AudioConfig::Channel* +AudioConfig::ChannelLayout::DefaultLayoutForChannels(uint32_t aChannels) const { switch (aChannels) { case 1: // MONO { - static const Channel config[] = { CHANNEL_MONO }; + static const Channel config[] = { CHANNEL_FRONT_CENTER }; return config; } case 2: // STEREO { - static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT }; + static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT }; return config; } case 3: // 3F { - static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER }; + static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER }; return config; } - case 4: // 2F2 + case 4: // QUAD { - static const Channel config[] = { CHANNEL_LEFT, CHANNEL_RIGHT, CHANNEL_LS, CHANNEL_RS }; + 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_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LS, CHANNEL_RS }; + 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_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_LS, CHANNEL_RS }; + 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_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RCENTER, CHANNEL_LS, CHANNEL_RS }; + 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_LEFT, CHANNEL_RIGHT, CHANNEL_CENTER, CHANNEL_LFE, CHANNEL_RLS, CHANNEL_RRS, CHANNEL_LS, CHANNEL_RS }; + 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(uint32_t 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 = 0; + while (aMap) { + if (aMap & 1) { + layout.AppendElement(static_cast<Channel>(i)); + channels++; + if (channels > MAX_AUDIO_CHANNELS) { + return ChannelLayout(); + } + } + aMap >>= 1; + i++; + } + return ChannelLayout(channels, layout.Elements()); +} + + bool AudioConfig::ChannelLayout::MappingTable(const ChannelLayout& aOther, uint8_t* aMap) const |