summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dom/base/nsDOMWindowUtils.cpp7
-rw-r--r--dom/interfaces/base/nsIDOMWindowUtils.idl5
-rw-r--r--dom/media/AccurateSeekTask.cpp3
-rw-r--r--dom/media/AudioConverter.cpp2
-rw-r--r--dom/media/AudioStream.cpp3
-rw-r--r--dom/media/AudioStream.h5
-rw-r--r--dom/media/CubebUtils.h3
-rw-r--r--dom/media/MediaData.cpp3
-rw-r--r--dom/media/MediaData.h144
-rw-r--r--dom/media/MediaInfo.cpp194
-rw-r--r--dom/media/MediaInfo.h7
-rw-r--r--dom/media/MediaPrefs.h6
-rw-r--r--dom/media/mediasink/DecodedAudioDataSink.cpp22
-rw-r--r--dom/media/platforms/agnostic/VorbisDecoder.cpp59
-rw-r--r--dom/media/platforms/apple/AppleATDecoder.cpp28
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp5
-rw-r--r--dom/media/platforms/wmf/WMFAudioMFTManager.cpp13
-rw-r--r--dom/media/platforms/wmf/WMFAudioMFTManager.h1
18 files changed, 427 insertions, 83 deletions
diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
index 3606a1b0bc..eb09a6f14f 100644
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2379,13 +2379,6 @@ nsDOMWindowUtils::GetCurrentMaxAudioChannels(uint32_t* aChannels)
}
NS_IMETHODIMP
-nsDOMWindowUtils::GetCurrentPreferredChannelLayout(nsAString& aLayout)
-{
- CubebUtils::GetPreferredChannelLayout(aLayout);
- return NS_OK;
-}
-
-NS_IMETHODIMP
nsDOMWindowUtils::GetCurrentPreferredSampleRate(uint32_t* aRate)
{
*aRate = CubebUtils::PreferredSampleRate();
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
index e563a19985..200bd3caf6 100644
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1432,11 +1432,6 @@ interface nsIDOMWindowUtils : nsISupports {
readonly attribute unsigned long currentMaxAudioChannels;
/**
- * Returns the preferred channel layout of the current audio device.
- */
- readonly attribute AString currentPreferredChannelLayout;
-
- /**
* Returns the preferred sample rate of the current audio device.
*/
readonly attribute unsigned long currentPreferredSampleRate;
diff --git a/dom/media/AccurateSeekTask.cpp b/dom/media/AccurateSeekTask.cpp
index 30eeb59049..88ac673860 100644
--- a/dom/media/AccurateSeekTask.cpp
+++ b/dom/media/AccurateSeekTask.cpp
@@ -182,7 +182,8 @@ AccurateSeekTask::DropAudioUpToSeekTarget(MediaData* aSample)
frames,
Move(audioData),
channels,
- audio->mRate));
+ audio->mRate,
+ audio->mChannelMap));
MOZ_ASSERT(!mSeekedAudioData, "Should be the 1st sample after seeking");
mSeekedAudioData = data;
mDoneAudioSeeking = true;
diff --git a/dom/media/AudioConverter.cpp b/dom/media/AudioConverter.cpp
index ab9b11543d..a77ea57f4a 100644
--- a/dom/media/AudioConverter.cpp
+++ b/dom/media/AudioConverter.cpp
@@ -143,7 +143,7 @@ AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aFrames) const
mIn.Format() == AudioConfig::FORMAT_FLT);
MOZ_DIAGNOSTIC_ASSERT(mIn.Channels() >= mOut.Channels());
MOZ_DIAGNOSTIC_ASSERT(
- mIn.Layout() == AudioConfig::ChannelLayout(mIn.Channels()),
+ mIn.Layout() == AudioConfig::ChannelLayout::SMPTEDefault(mIn.Layout()),
"Can only downmix input data in SMPTE layout");
MOZ_DIAGNOSTIC_ASSERT(mOut.Layout() == AudioConfig::ChannelLayout(2) ||
mOut.Layout() == AudioConfig::ChannelLayout(1),
diff --git a/dom/media/AudioStream.cpp b/dom/media/AudioStream.cpp
index 77ed512eee..dc1daa2e07 100644
--- a/dom/media/AudioStream.cpp
+++ b/dom/media/AudioStream.cpp
@@ -317,7 +317,7 @@ int AudioStream::InvokeCubeb(Function aFunction, Args&&... aArgs)
}
nsresult
-AudioStream::Init(uint32_t aNumChannels, uint32_t aRate,
+AudioStream::Init(uint32_t aNumChannels, uint32_t aChannelMap, uint32_t aRate,
const dom::AudioChannel aAudioChannel)
{
auto startTime = TimeStamp::Now();
@@ -331,6 +331,7 @@ AudioStream::Init(uint32_t aNumChannels, uint32_t aRate,
cubeb_stream_params params;
params.rate = aRate;
params.channels = mOutChannels;
+ params.layout = CUBEB_LAYOUT_UNDEFINED;
params.format = ToCubebFormat<AUDIO_OUTPUT_FORMAT>::value;
mAudioClock.Init(aRate);
diff --git a/dom/media/AudioStream.h b/dom/media/AudioStream.h
index 199314d4b6..e138ab991a 100644
--- a/dom/media/AudioStream.h
+++ b/dom/media/AudioStream.h
@@ -192,9 +192,10 @@ public:
explicit AudioStream(DataSource& aSource);
// Initialize the audio stream. aNumChannels is the number of audio
- // channels (1 for mono, 2 for stereo, etc) and aRate is the sample rate
+ // channels (1 for mono, 2 for stereo, etc), aChannelMap is the indicator for
+ // channel layout(mono, stereo, 5.1 or 7.1 ) and aRate is the sample rate
// (22050Hz, 44100Hz, etc).
- nsresult Init(uint32_t aNumChannels, uint32_t aRate,
+ nsresult Init(uint32_t aNumChannels, uint32_t aChannelMap, uint32_t aRate,
const dom::AudioChannel aAudioStreamChannel);
// Closes the stream. All future use of the stream is an error.
diff --git a/dom/media/CubebUtils.h b/dom/media/CubebUtils.h
index 2e2e4ba3b5..8449462442 100644
--- a/dom/media/CubebUtils.h
+++ b/dom/media/CubebUtils.h
@@ -8,6 +8,7 @@
#define CubebUtils_h_
#include "cubeb/cubeb.h"
+#include "mozilla/dom/AudioDeviceInfo.h"
#include "mozilla/dom/AudioChannelBinding.h"
#include "mozilla/Maybe.h"
@@ -45,7 +46,7 @@ uint32_t GetCubebMSGLatencyInFrames(cubeb_stream_params * params);
bool CubebLatencyPrefSet();
void GetCurrentBackend(nsAString& aBackend);
void GetDeviceCollection(nsTArray<RefPtr<AudioDeviceInfo>>& aDeviceInfos,
- Side aSide);
+ Side aSide);
} // namespace CubebUtils
} // namespace mozilla
diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp
index fb3eff7b51..5b68200eff 100644
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -76,7 +76,8 @@ AudioData::TransferAndUpdateTimestampAndDuration(AudioData* aOther,
aOther->mFrames,
Move(aOther->mAudioData),
aOther->mChannels,
- aOther->mRate);
+ aOther->mRate,
+ aOther->mChannelMap);
return v.forget();
}
diff --git a/dom/media/MediaData.h b/dom/media/MediaData.h
index 909841eb98..dd1d0243e0 100644
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -27,18 +27,29 @@ namespace mozilla {
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_MONO = 0,
- CHANNEL_LEFT,
- CHANNEL_RIGHT,
- CHANNEL_CENTER,
- CHANNEL_LS,
- CHANNEL_RS,
- CHANNEL_RLS,
- CHANNEL_RCENTER,
- CHANNEL_RRS,
+ 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 {
@@ -48,18 +59,22 @@ public:
, mValid(false)
{}
explicit ChannelLayout(uint32_t aChannels)
- : ChannelLayout(aChannels, SMPTEDefault(aChannels))
+ : ChannelLayout(aChannels, DefaultLayoutForChannels(aChannels))
{}
ChannelLayout(uint32_t aChannels, const Channel* aConfig)
: ChannelLayout()
{
- if (!aConfig) {
+ 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;
@@ -76,10 +91,8 @@ public:
{
return mChannels.Length();
}
- uint32_t Map() const
- {
- return mChannelMap;
- }
+ 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]].
@@ -97,9 +110,98 @@ public:
{
return mChannelMap & (1 << aChannel);
}
+
+ static ChannelLayout SMPTEDefault(
+ const ChannelLayout& aChannelLayout);
+ static ChannelLayout SMPTEDefault(uint32_t aMap);
+
+ static constexpr uint32_t UNKNOWN_MAP = 0;
+
+ // 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;
+ const Channel* DefaultLayoutForChannels(uint32_t aChannels) const;
AutoTArray<Channel, MAX_AUDIO_CHANNELS> mChannels;
uint32_t mChannelMap;
bool mValid;
@@ -189,6 +291,7 @@ private:
bool mInterleaved;
};
+
namespace layers {
class Image;
class ImageContainer;
@@ -542,9 +645,11 @@ public:
uint32_t aFrames,
AlignedAudioBuffer&& aData,
uint32_t aChannels,
- uint32_t aRate)
+ uint32_t aRate,
+ uint32_t aChannelMap = AudioConfig::ChannelLayout::UNKNOWN_MAP)
: MediaData(sType, aOffset, aTime, aDuration, aFrames)
, mChannels(aChannels)
+ , mChannelMap(aChannelMap)
, mRate(aRate)
, mAudioData(Move(aData)) {}
@@ -570,6 +675,11 @@ public:
bool IsAudible() const;
const uint32_t mChannels;
+ // The AudioConfig::ChannelLayout map. Channels are ordered as per SMPTE
+ // definition. A value of UNKNOWN_MAP indicates unknown layout.
+ // ChannelMap is an unsigned bitmap compatible with Windows' WAVE and FFmpeg
+ // channel map.
+ const uint32_t mChannelMap;
const uint32_t mRate;
// At least one of mAudioBuffer/mAudioData must be non-null.
// mChannels channels, each with mFrames frames
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
diff --git a/dom/media/MediaInfo.h b/dom/media/MediaInfo.h
index 658c7c3fa7..29dcf2cc97 100644
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -314,6 +314,7 @@ public:
EmptyString(), EmptyString(), true, 1)
, mRate(0)
, mChannels(0)
+ , mChannelMap(AudioConfig::ChannelLayout::UNKNOWN_MAP)
, mBitDepth(0)
, mProfile(0)
, mExtendedProfile(0)
@@ -326,6 +327,7 @@ public:
: TrackInfo(aOther)
, mRate(aOther.mRate)
, mChannels(aOther.mChannels)
+ , mChannelMap(aOther.mChannelMap)
, mBitDepth(aOther.mBitDepth)
, mProfile(aOther.mProfile)
, mExtendedProfile(aOther.mExtendedProfile)
@@ -362,6 +364,11 @@ public:
// Number of audio channels.
uint32_t mChannels;
+ // The AudioConfig::ChannelLayout map. Channels are ordered as per SMPTE
+ // definition. A value of UNKNOWN_MAP indicates unknown layout.
+ // ChannelMap is an unsigned bitmap compatible with Windows' WAVE and FFmpeg
+ // channel map.
+ uint32_t mChannelMap;
// Bits per sample.
uint32_t mBitDepth;
diff --git a/dom/media/MediaPrefs.h b/dom/media/MediaPrefs.h
index c1e66a3cee..84163353a5 100644
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -86,8 +86,12 @@ private:
DECL_MEDIA_PREF("accessibility.monoaudio.enable", MonoAudio, bool, false);
DECL_MEDIA_PREF("media.resampling.enabled", AudioSinkResampling, bool, false);
DECL_MEDIA_PREF("media.resampling.rate", AudioSinkResampleRate, uint32_t, 48000);
+#ifdef XP_WIN
+ // Enable multichannel support on Windows.
+ DECL_MEDIA_PREF("media.forcestereo.enabled", AudioSinkForceStereo, bool, false);
+#else
DECL_MEDIA_PREF("media.forcestereo.enabled", AudioSinkForceStereo, bool, true);
-
+#endif
// VideoSink
DECL_MEDIA_PREF("media.ruin-av-sync.enabled", RuinAvSync, bool, false);
diff --git a/dom/media/mediasink/DecodedAudioDataSink.cpp b/dom/media/mediasink/DecodedAudioDataSink.cpp
index e7fcffe4f3..d20eac8acb 100644
--- a/dom/media/mediasink/DecodedAudioDataSink.cpp
+++ b/dom/media/mediasink/DecodedAudioDataSink.cpp
@@ -195,7 +195,15 @@ nsresult
DecodedAudioDataSink::InitializeAudioStream(const PlaybackParams& aParams)
{
mAudioStream = new AudioStream(*this);
- nsresult rv = mAudioStream->Init(mOutputChannels, mOutputRate, mChannel);
+ // When AudioQueue is empty, there is no way to know the channel layout of
+ // the coming audio data, so we use the predefined channel map instead.
+ uint32_t channelMap = mConverter
+ ? mConverter->OutputConfig().Layout().Map()
+ : AudioConfig::ChannelLayout(mOutputChannels).Map();
+ // This layout map is already processed by mConverter with mOutputChannels
+ // into SMPTE format, so there is no need to worry whether
+ // MediaPrefs::MonoAudio() or MediaPrefs::AudioSinkForceStereo() is applied.
+ nsresult rv = mAudioStream->Init(mOutputChannels, channelMap, mOutputRate, mChannel);
if (NS_FAILED(rv)) {
mAudioStream->Shutdown();
mAudioStream = nullptr;
@@ -410,10 +418,18 @@ DecodedAudioDataSink::NotifyAudioNeeded()
mFramesParsed = result.value();
}
+ const AudioConfig::ChannelLayout inputLayout =
+ data->mChannelMap
+ ? AudioConfig::ChannelLayout::SMPTEDefault(data->mChannelMap)
+ : AudioConfig::ChannelLayout(data->mChannels);
+ const AudioConfig::ChannelLayout outputLayout =
+ mOutputChannels == data->mChannels
+ ? inputLayout
+ : AudioConfig::ChannelLayout(mOutputChannels);
mConverter =
MakeUnique<AudioConverter>(
- AudioConfig(data->mChannels, data->mRate),
- AudioConfig(mOutputChannels, mOutputRate));
+ AudioConfig(inputLayout, data->mRate),
+ AudioConfig(outputLayout, mOutputRate));
}
// See if there's a gap in the audio. If there is, push silence into the
diff --git a/dom/media/platforms/agnostic/VorbisDecoder.cpp b/dom/media/platforms/agnostic/VorbisDecoder.cpp
index ed8b90dbd4..f842e64905 100644
--- a/dom/media/platforms/agnostic/VorbisDecoder.cpp
+++ b/dom/media/platforms/agnostic/VorbisDecoder.cpp
@@ -302,47 +302,78 @@ VorbisDataDecoder::VorbisLayout(uint32_t aChannels)
switch (aChannels) {
case 1: // the stream is monophonic
{
- static const Channel config[] = { AudioConfig::CHANNEL_MONO };
+ static const Channel config[] = { AudioConfig::CHANNEL_FRONT_CENTER };
return config;
}
case 2: // the stream is stereo. channel order: left, right
{
- static const Channel config[] = { AudioConfig::CHANNEL_LEFT, AudioConfig::CHANNEL_RIGHT };
+ static const Channel config[] = { AudioConfig::CHANNEL_FRONT_LEFT,
+ AudioConfig::CHANNEL_FRONT_RIGHT };
return config;
}
- case 3: // the stream is a 1d-surround encoding. channel order: left, center, right
+ case 3: // the stream is a 1d-surround encoding. channel order: left,
+ // center, right
{
- static const Channel config[] = { AudioConfig::CHANNEL_LEFT, AudioConfig::CHANNEL_CENTER, AudioConfig::CHANNEL_RIGHT };
+ static const Channel config[] = { AudioConfig::CHANNEL_FRONT_LEFT,
+ AudioConfig::CHANNEL_FRONT_CENTER,
+ AudioConfig::CHANNEL_FRONT_RIGHT };
return config;
}
- case 4: // the stream is quadraphonic surround. channel order: front left, front right, rear left, rear right
+ case 4: // the stream is quadraphonic surround. channel order: front left,
+ // front right, rear left, rear right
{
- static const Channel config[] = { AudioConfig::CHANNEL_LEFT, AudioConfig::CHANNEL_RIGHT, AudioConfig::CHANNEL_LS, AudioConfig::CHANNEL_RS };
+ static const Channel config[] = { AudioConfig::CHANNEL_FRONT_LEFT,
+ AudioConfig::CHANNEL_FRONT_RIGHT,
+ AudioConfig::CHANNEL_BACK_LEFT,
+ AudioConfig::CHANNEL_BACK_RIGHT };
return config;
}
- case 5: // the stream is five-channel surround. channel order: front left, center, front right, rear left, rear right
+ case 5: // the stream is five-channel surround. channel order: front left,
+ // center, front right, rear left, rear right
{
- static const Channel config[] = { AudioConfig::CHANNEL_LEFT, AudioConfig::CHANNEL_CENTER, AudioConfig::CHANNEL_RIGHT, AudioConfig::CHANNEL_LS, AudioConfig::CHANNEL_RS };
+ static const Channel config[] = { AudioConfig::CHANNEL_FRONT_LEFT,
+ AudioConfig::CHANNEL_FRONT_CENTER,
+ AudioConfig::CHANNEL_FRONT_RIGHT,
+ AudioConfig::CHANNEL_BACK_LEFT,
+ AudioConfig::CHANNEL_BACK_RIGHT };
return config;
}
- case 6: // the stream is 5.1 surround. channel order: front left, center, front right, rear left, rear right, LFE
+ case 6: // the stream is 5.1 surround. channel order: front left, center,
+ // front right, rear left, rear right, LFE
{
- static const Channel config[] = { AudioConfig::CHANNEL_LEFT, AudioConfig::CHANNEL_CENTER, AudioConfig::CHANNEL_RIGHT, AudioConfig::CHANNEL_LS, AudioConfig::CHANNEL_RS, AudioConfig::CHANNEL_LFE };
+ static const Channel config[] = {
+ AudioConfig::CHANNEL_FRONT_LEFT, AudioConfig::CHANNEL_FRONT_CENTER,
+ AudioConfig::CHANNEL_FRONT_RIGHT, AudioConfig::CHANNEL_BACK_LEFT,
+ AudioConfig::CHANNEL_BACK_RIGHT, AudioConfig::CHANNEL_LFE
+ };
return config;
}
- case 7: // surround. channel order: front left, center, front right, side left, side right, rear center, LFE
+ case 7: // surround. channel order: front left, center, front right, side
+ // left, side right, rear center, LFE
{
- static const Channel config[] = { AudioConfig::CHANNEL_LEFT, AudioConfig::CHANNEL_CENTER, AudioConfig::CHANNEL_RIGHT, AudioConfig::CHANNEL_LS, AudioConfig::CHANNEL_RS, AudioConfig::CHANNEL_RCENTER, AudioConfig::CHANNEL_LFE };
+ static const Channel config[] = {
+ AudioConfig::CHANNEL_FRONT_LEFT, AudioConfig::CHANNEL_FRONT_CENTER,
+ AudioConfig::CHANNEL_FRONT_RIGHT, AudioConfig::CHANNEL_SIDE_LEFT,
+ AudioConfig::CHANNEL_SIDE_RIGHT, AudioConfig::CHANNEL_BACK_CENTER,
+ AudioConfig::CHANNEL_LFE
+ };
return config;
}
- case 8: // the stream is 7.1 surround. channel order: front left, center, front right, side left, side right, rear left, rear right, LFE
+ case 8: // the stream is 7.1 surround. channel order: front left, center,
+ // front right, side left, side right, rear left, rear right, LFE
{
- static const Channel config[] = { AudioConfig::CHANNEL_LEFT, AudioConfig::CHANNEL_CENTER, AudioConfig::CHANNEL_RIGHT, AudioConfig::CHANNEL_LS, AudioConfig::CHANNEL_RS, AudioConfig::CHANNEL_RLS, AudioConfig::CHANNEL_RRS, AudioConfig::CHANNEL_LFE };
+ static const Channel config[] = {
+ AudioConfig::CHANNEL_FRONT_LEFT, AudioConfig::CHANNEL_FRONT_CENTER,
+ AudioConfig::CHANNEL_FRONT_RIGHT, AudioConfig::CHANNEL_SIDE_LEFT,
+ AudioConfig::CHANNEL_SIDE_RIGHT, AudioConfig::CHANNEL_BACK_LEFT,
+ AudioConfig::CHANNEL_BACK_RIGHT, AudioConfig::CHANNEL_LFE
+ };
return config;
}
default:
return nullptr;
}
+
}
} // namespace mozilla
diff --git a/dom/media/platforms/apple/AppleATDecoder.cpp b/dom/media/platforms/apple/AppleATDecoder.cpp
index 65794d82c8..9466a4e8be 100644
--- a/dom/media/platforms/apple/AppleATDecoder.cpp
+++ b/dom/media/platforms/apple/AppleATDecoder.cpp
@@ -323,8 +323,9 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample)
return NS_ERROR_OUT_OF_MEMORY;
}
if (mChannelLayout && !mAudioConverter) {
- AudioConfig in(*mChannelLayout.get(), rate);
- AudioConfig out(channels, rate);
+ AudioConfig in(*mChannelLayout, rate);
+ AudioConfig out(AudioConfig::ChannelLayout::SMPTEDefault(*mChannelLayout),
+ rate);
if (!in.IsValid() || !out.IsValid()) {
return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
RESULT_DETAIL("Invalid audio config"));
@@ -342,7 +343,9 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample)
numFrames,
data.Forget(),
channels,
- rate);
+ rate,
+ mChannelLayout ? mChannelLayout->Map()
+ : AudioConfig::ChannelLayout::UNKNOWN_MAP);
mCallback->Output(audio);
return NS_OK;
}
@@ -428,26 +431,25 @@ AudioConfig::Channel
ConvertChannelLabel(AudioChannelLabel id)
{
switch (id) {
- case kAudioChannelLabel_Mono:
- return AudioConfig::CHANNEL_MONO;
case kAudioChannelLabel_Left:
- return AudioConfig::CHANNEL_LEFT;
+ return AudioConfig::CHANNEL_FRONT_LEFT;
case kAudioChannelLabel_Right:
- return AudioConfig::CHANNEL_RIGHT;
+ return AudioConfig::CHANNEL_FRONT_RIGHT;
+ case kAudioChannelLabel_Mono:
case kAudioChannelLabel_Center:
- return AudioConfig::CHANNEL_CENTER;
+ return AudioConfig::CHANNEL_FRONT_CENTER;
case kAudioChannelLabel_LFEScreen:
return AudioConfig::CHANNEL_LFE;
case kAudioChannelLabel_LeftSurround:
- return AudioConfig::CHANNEL_LS;
+ return AudioConfig::CHANNEL_SIDE_LEFT;
case kAudioChannelLabel_RightSurround:
- return AudioConfig::CHANNEL_RS;
+ return AudioConfig::CHANNEL_SIDE_RIGHT;
case kAudioChannelLabel_CenterSurround:
- return AudioConfig::CHANNEL_RCENTER;
+ return AudioConfig::CHANNEL_BACK_CENTER;
case kAudioChannelLabel_RearSurroundLeft:
- return AudioConfig::CHANNEL_RLS;
+ return AudioConfig::CHANNEL_BACK_LEFT;
case kAudioChannelLabel_RearSurroundRight:
- return AudioConfig::CHANNEL_RRS;
+ return AudioConfig::CHANNEL_BACK_RIGHT;
default:
return AudioConfig::CHANNEL_INVALID;
}
diff --git a/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp
index f867ec4942..7e91987251 100644
--- a/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp
+++ b/dom/media/platforms/ffmpeg/FFmpegAudioDecoder.cpp
@@ -117,6 +117,8 @@ CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames)
return audio;
}
+typedef AudioConfig::ChannelLayout ChannelLayout;
+
MediaResult
FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample)
{
@@ -188,7 +190,8 @@ FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample)
mFrame->nb_samples,
Move(audio),
numChannels,
- samplingRate);
+ samplingRate,
+ mCodecContext->channel_layout);
mCallback->Output(data);
pts += duration;
if (!pts.IsValid()) {
diff --git a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
index 3dacdf0aad..cf1ebb1cff 100644
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
@@ -84,6 +84,7 @@ AACAudioSpecificConfigToUserData(uint8_t aAACProfileLevelIndication,
WMFAudioMFTManager::WMFAudioMFTManager(
const AudioInfo& aConfig)
: mAudioChannels(aConfig.mChannels)
+ , mChannelsMap(AudioConfig::ChannelLayout::UNKNOWN_MAP)
, mAudioRate(aConfig.mRate)
, mAudioFrameSum(0)
, mMustRecaptureAudioPosition(true)
@@ -212,6 +213,15 @@ WMFAudioMFTManager::UpdateOutputType()
hr = type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &mAudioChannels);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+ uint32_t channelsMap;
+ hr = type->GetUINT32(MF_MT_AUDIO_CHANNEL_MASK, &channelsMap);
+ if (SUCCEEDED(hr)) {
+ mChannelsMap = channelsMap;
+ } else {
+ LOG("Unable to retrieve channel layout. Ignoring");
+ mChannelsMap = AudioConfig::ChannelLayout::UNKNOWN_MAP;
+ }
+
AudioConfig::ChannelLayout layout(mAudioChannels);
if (!layout.IsValid()) {
return E_FAIL;
@@ -338,7 +348,8 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset,
numFrames,
Move(audioData),
mAudioChannels,
- mAudioRate);
+ mAudioRate,
+ mChannelsMap);
#ifdef LOG_SAMPLE_DECODE
LOG("Decoded audio sample! timestamp=%lld duration=%lld currentLength=%u",
diff --git a/dom/media/platforms/wmf/WMFAudioMFTManager.h b/dom/media/platforms/wmf/WMFAudioMFTManager.h
index 5bbbc6108a..1f803a0e98 100644
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.h
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.h
@@ -47,6 +47,7 @@ private:
HRESULT UpdateOutputType();
uint32_t mAudioChannels;
+ uint32_t mChannelsMap;
uint32_t mAudioRate;
nsTArray<BYTE> mUserData;