☠☠ backed out by 615f67ac2823 ☠ ☠ | |
author | Jean-Yves Avenard <jyavenard@mozilla.com> |
Mon, 04 Apr 2016 18:22:05 +1000 | |
changeset 292298 | d71b93bc6cc7d8acfa97a16a2f0e390a9af0db75 |
parent 292297 | 6e917e5d29c06b11ece21ce6e18c9d82da2829a7 |
child 292299 | 0565edbead7fa107491b3ea72dca001a369a548e |
push id | 74808 |
push user | jyavenard@mozilla.com |
push date | Fri, 08 Apr 2016 07:42:16 +0000 |
treeherder | mozilla-inbound@be02aaa8b2e8 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | cpearce |
bugs | 1248861 |
milestone | 48.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/dom/media/AudioConverter.cpp @@ -0,0 +1,131 @@ +/* -*- 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 "AudioConverter.h" +#include <string.h> + +/* + * Parts derived from MythTV AudioConvert Class + * Created by Jean-Yves Avenard. + * + * Copyright (C) Bubblestuff Pty Ltd 2013 + * Copyright (C) foobum@gmail.com 2010 + */ + +namespace mozilla { + +AudioConverter::AudioConverter(const AudioConfig& aIn, const AudioConfig& aOut) + : mIn(aIn) + , mOut(aOut) +{ + MOZ_DIAGNOSTIC_ASSERT(aIn.Channels() == aOut.Channels() && + aIn.Rate() == aOut.Rate() && + aIn.Format() == aOut.Format() && + aIn.Interleaved() == aOut.Interleaved(), + "Only channel reordering is supported at this stage"); + MOZ_DIAGNOSTIC_ASSERT(aOut.Interleaved(), "planar audio format not supported"); + InitChannelMap(); +} + +bool +AudioConverter::InitChannelMap() +{ + if (!CanReorderAudio()) { + return false; + } + for (uint32_t i = 0; i < mIn.Layout().Count(); i++) { + for (uint32_t j = 0; j < mIn.Layout().Count(); j++) { + if (mOut.Layout()[j] == mIn.Layout()[i]) { + mChannelOrderMap[j] = i; + break; + } + } + } + return true; +} + +bool +AudioConverter::CanWorkInPlace() const +{ + return mIn.Channels() * mIn.Rate() * AudioConfig::SampleSize(mIn.Format()) >= + mOut.Channels() * mOut.Rate() * AudioConfig::SampleSize(mOut.Format()); +} + +size_t +AudioConverter::Process(void* aOut, const void* aIn, size_t aBytes) +{ + if (!CanWorkInPlace()) { + return 0; + } + if (mIn.Layout() != mOut.Layout() && + CanReorderAudio()) { + ReOrderInterleavedChannels(aOut, aIn, aBytes); + } + return aBytes; +} + +// Reorder interleaved channels. +// Can work in place (e.g aOut == aIn). +template <class AudioDataType> +void +_ReOrderInterleavedChannels(AudioDataType* aOut, const AudioDataType* aIn, + uint32_t aFrames, uint32_t aChannels, + const uint32_t* aChannelOrderMap) +{ + MOZ_DIAGNOSTIC_ASSERT(aChannels <= MAX_AUDIO_CHANNELS); + AudioDataType val[MAX_AUDIO_CHANNELS]; + for (uint32_t i = 0; i < aFrames; i++) { + for (uint32_t j = 0; j < aChannels; j++) { + val[j] = aIn[aChannelOrderMap[j]]; + } + for (uint32_t j = 0; j < aChannels; j++) { + aOut[j] = val[j]; + } + aOut += aChannels; + aIn += aChannels; + } +} + +void +AudioConverter::ReOrderInterleavedChannels(void* aOut, const void* aIn, + size_t aDataSize) const +{ + MOZ_DIAGNOSTIC_ASSERT(mIn.Channels() == mOut.Channels()); + + if (mOut.Layout() == mIn.Layout()) { + return; + } + if (mOut.Channels() == 1) { + // If channel count is 1, planar and non-planar formats are the same and + // there's nothing to reorder. + if (aOut != aIn) { + memmove(aOut, aIn, aDataSize); + } + return; + } + + uint32_t bits = AudioConfig::FormatToBits(mOut.Format()); + switch (bits) { + case 8: + _ReOrderInterleavedChannels((uint8_t*)aOut, (const uint8_t*)aIn, + aDataSize/sizeof(uint8_t)/mIn.Channels(), + mIn.Channels(), mChannelOrderMap); + break; + case 16: + _ReOrderInterleavedChannels((int16_t*)aOut,(const int16_t*)aIn, + aDataSize/sizeof(int16_t)/mIn.Channels(), + mIn.Channels(), mChannelOrderMap); + break; + default: + MOZ_DIAGNOSTIC_ASSERT(AudioConfig::SampleSize(mOut.Format()) == 4); + _ReOrderInterleavedChannels((int32_t*)aOut,(const int32_t*)aIn, + aDataSize/sizeof(int32_t)/mIn.Channels(), + mIn.Channels(), mChannelOrderMap); + break; + } +} + +} // namespace mozilla \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/dom/media/AudioConverter.h @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 2; 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(AudioConverter_h) +#define AudioConverter_h + +#include "MediaInfo.h" + +namespace mozilla { + +template <AudioConfig::SampleFormat T> struct AudioDataBufferTypeChooser; +template <> struct AudioDataBufferTypeChooser<AudioConfig::FORMAT_U8> +{ typedef uint8_t Type; }; +template <> struct AudioDataBufferTypeChooser<AudioConfig::FORMAT_S16> +{ typedef int16_t Type; }; +template <> struct AudioDataBufferTypeChooser<AudioConfig::FORMAT_S24LSB> +{ typedef int32_t Type; }; +template <> struct AudioDataBufferTypeChooser<AudioConfig::FORMAT_S24> +{ typedef int32_t Type; }; +template <> struct AudioDataBufferTypeChooser<AudioConfig::FORMAT_S32> +{ typedef int32_t Type; }; +template <> struct AudioDataBufferTypeChooser<AudioConfig::FORMAT_FLT> +{ typedef float Type; }; + +// 'Value' is the type used externally to deal with stored value. +// AudioDataBuffer can perform conversion between different SampleFormat content. +template <AudioConfig::SampleFormat Format, typename Value = typename AudioDataBufferTypeChooser<Format>::Type> +class AudioDataBuffer +{ +public: + AudioDataBuffer() {} + AudioDataBuffer(Value* aBuffer, size_t aLength) + : mBuffer(aBuffer, aLength) + {} + explicit AudioDataBuffer(const AudioDataBuffer& aOther) + : mBuffer(aOther.mBuffer) + {} + AudioDataBuffer(AudioDataBuffer&& aOther) + : mBuffer(Move(aOther.mBuffer)) + {} + template <AudioConfig::SampleFormat OtherFormat, typename OtherValue> + explicit AudioDataBuffer(const AudioDataBuffer<OtherFormat, OtherValue>& other) + { + // TODO: Convert from different type, may use asm routines. + MOZ_CRASH("Conversion not implemented yet"); + } + + // A u8, s16 and float aligned buffer can only be treated as + // FORMAT_U8, FORMAT_S16 and FORMAT_FLT respectively. + // So allow them as copy and move constructors. + explicit AudioDataBuffer(const AlignedByteBuffer& aBuffer) + : mBuffer(aBuffer) + { + static_assert(Format == AudioConfig::FORMAT_U8, + "Conversion not implemented yet"); + } + explicit AudioDataBuffer(const AlignedShortBuffer& aBuffer) + : mBuffer(aBuffer) + { + static_assert(Format == AudioConfig::FORMAT_S16, + "Conversion not implemented yet"); + } + explicit AudioDataBuffer(const AlignedFloatBuffer& aBuffer) + : mBuffer(aBuffer) + { + static_assert(Format == AudioConfig::FORMAT_FLT, + "Conversion not implemented yet"); + } + explicit AudioDataBuffer(AlignedByteBuffer&& aBuffer) + : mBuffer(Move(aBuffer)) + { + static_assert(Format == AudioConfig::FORMAT_U8, + "Conversion not implemented yet"); + } + explicit AudioDataBuffer(AlignedShortBuffer&& aBuffer) + : mBuffer(Move(aBuffer)) + { + static_assert(Format == AudioConfig::FORMAT_S16, + "Conversion not implemented yet"); + } + explicit AudioDataBuffer(const AlignedFloatBuffer&& aBuffer) + : mBuffer(Move(aBuffer)) + { + static_assert(Format == AudioConfig::FORMAT_FLT, + "Conversion not implemented yet"); + } + + Value* Data() const { return mBuffer.Data(); } + size_t Length() const { return mBuffer.Length(); } + size_t Size() const { return mBuffer.Size(); } + AlignedBuffer<Value> Forget() + { + // Correct type -> Just give values as-is. + return Move(mBuffer); + } +private: + AlignedBuffer<Value> mBuffer; +}; + +typedef AudioDataBuffer<AudioConfig::FORMAT_DEFAULT> AudioSampleBuffer; + +class AudioConverter { +public: + AudioConverter(const AudioConfig& aIn, const AudioConfig& aOut); + + // Attempt to convert the AudioDataBuffer in place. + // Will return 0 if the conversion wasn't possible. + // Process may allocate memory internally should intermediary steps be + // required. + template <AudioConfig::SampleFormat Type, typename Value> + size_t Process(AudioDataBuffer<Type, Value>& aBuffer) + { + MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format() && mIn.Format() == Type); + return Process(aBuffer.Data(), aBuffer.Data(), aBuffer.Size()); + } + bool CanWorkInPlace() const; + bool CanReorderAudio() const + { + return mIn.Layout().IsValid() && mOut.Layout().IsValid() && + mIn.Layout().Map() == mOut.Layout().Map(); + } + +private: + const AudioConfig mIn; + const AudioConfig mOut; + uint32_t mChannelOrderMap[MAX_AUDIO_CHANNELS]; + bool InitChannelMap(); + /** + * Process + * Parameters: + * aOut : destination buffer where converted samples will be copied + * aIn : source buffer + * aBytes: size in bytes of source buffer + * + * Return Value: size in bytes of samples converted or 0 if error + */ + size_t Process(void* aOut, const void* aIn, size_t aBytes); + void ReOrderInterleavedChannels(void* aOut, const void* aIn, size_t aDataSize) const; +}; + +} // namespace mozilla + +#endif /* AudioConverter_h */
--- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -84,16 +84,17 @@ XPIDL_MODULE = 'dom_media' EXPORTS += [ 'AbstractMediaDecoder.h', 'ADTSDecoder.h', 'ADTSDemuxer.h', 'AudioBufferUtils.h', 'AudioChannelFormat.h', 'AudioCompactor.h', + 'AudioConverter.h', 'AudioMixer.h', 'AudioPacketizer.h', 'AudioSampleFormat.h', 'AudioSegment.h', 'AudioStream.h', 'Benchmark.h', 'BufferMediaResource.h', 'CubebUtils.h', @@ -191,16 +192,17 @@ EXPORTS.mozilla.dom += [ ] UNIFIED_SOURCES += [ 'ADTSDecoder.cpp', 'ADTSDemuxer.cpp', 'AudioCaptureStream.cpp', 'AudioChannelFormat.cpp', 'AudioCompactor.cpp', + 'AudioConverter.cpp', 'AudioSegment.cpp', 'AudioStream.cpp', 'AudioStreamTrack.cpp', 'AudioTrack.cpp', 'AudioTrackList.cpp', 'Benchmark.cpp', 'CanvasCaptureMediaStream.cpp', 'CubebUtils.cpp',