Chromium Code Reviews| Index: services/media/audio/platform/generic/output_formatter.cc |
| diff --git a/services/media/audio/platform/generic/output_formatter.cc b/services/media/audio/platform/generic/output_formatter.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8c26c8396132d75bb5bb0b9779f63222228ece33 |
| --- /dev/null |
| +++ b/services/media/audio/platform/generic/output_formatter.cc |
| @@ -0,0 +1,143 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <limits> |
| +#include <type_traits> |
| + |
| +#include "base/logging.h" |
| +#include "mojo/services/media/common/cpp/linear_transform.h" |
| +#include "services/media/audio/platform/generic/output_formatter.h" |
| + |
| +namespace mojo { |
| +namespace media { |
| +namespace audio { |
| + |
| +// Template to produce destination samples from normalized samples. |
| +template <typename DType, typename Enable = void> class DstConverter; |
| + |
| +template <typename DType> |
| +class DstConverter<DType, |
| + typename std::enable_if< |
| + std::is_same<DType, int16_t>::value, |
| + void>::type> { |
| + public: |
| + static inline constexpr DType Convert(int32_t sample) { |
| + return static_cast<DType>(sample); |
| + } |
| +}; |
| + |
|
dalesat
2016/01/24 19:07:39
Can we just define a template function and special
johngro
2016/01/25 18:12:32
Its been a while, but this can fail in some cases
|
| +template <typename DType> |
| +class DstConverter<DType, |
| + typename std::enable_if< |
| + std::is_same<DType, uint8_t>::value, |
| + void>::type> { |
| + public: |
| + static inline constexpr DType Convert(int32_t sample) { |
| + return static_cast<DType>((sample >> 8) + 0x80); |
| + } |
| +}; |
| + |
| +// Template to fill samples with silence based on sample type. |
| +template <typename DType, typename Enable = void> class SilenceMaker; |
| + |
| +template <typename DType> |
| +class SilenceMaker<DType, |
| + typename std::enable_if< |
| + std::is_same<DType, int16_t>::value, |
| + void>::type> { |
| + public: |
| + static inline void Fill(void* dest, size_t samples) { |
| + ::memset(dest, 0, samples * sizeof(DType)); |
| + } |
| +}; |
| + |
| +template <typename DType> |
| +class SilenceMaker<DType, |
| + typename std::enable_if< |
| + std::is_same<DType, uint8_t>::value, |
| + void>::type> { |
| + public: |
| + static inline void Fill(void* dest, size_t samples) { |
| + ::memset(dest, 0x80, samples * sizeof(DType)); |
| + } |
| +}; |
| + |
| +// A templated class which implements the ProduceOutput and FillWithSilence |
| +// methods of OutputFormatter |
| +template <typename DType, uint32_t DChCount> |
| +class OutputFormatterImpl : public OutputFormatter { |
| + public: |
| + explicit OutputFormatterImpl(const LpcmMediaTypeDetailsPtr& format) |
| + : OutputFormatter(format, sizeof(DType), DChCount) {} |
| + |
| + void ProduceOutput(const int32_t* source, |
| + void* dest_void, |
| + uint32_t frames) const override { |
| + using DC = DstConverter<DType>; |
| + DType* dest = static_cast<DType*>(dest_void); |
| + |
| + for (size_t i = 0; i < (static_cast<size_t>(frames) * DChCount); ++i) { |
| + register int32_t val = source[i]; |
|
jeffbrown
2015/12/01 22:13:30
Does the register keyword even do anything these d
johngro
2016/01/25 18:12:32
probably not, but it does not hurt either. It has
|
| + if (val > std::numeric_limits<int16_t>::max()) { |
| + dest[i] = DC::Convert(std::numeric_limits<int16_t>::max()); |
| + } else if (val < std::numeric_limits<int16_t>::min()) { |
| + dest[i] = DC::Convert(std::numeric_limits<int16_t>::min()); |
| + } else { |
| + dest[i] = DC::Convert(val); |
| + } |
| + } |
| + } |
| + |
| + void FillWithSilence(void* dest, uint32_t frames) const override { |
| + SilenceMaker<DType>::Fill(dest, frames * DChCount); |
| + } |
| +}; |
| + |
| +// Constructor/destructor for the bommon OutputFormatter base class. |
|
jeffbrown
2015/12/01 22:13:30
common
johngro
2016/01/25 18:12:32
Done.
|
| +OutputFormatter::OutputFormatter(const LpcmMediaTypeDetailsPtr& format, |
| + uint32_t bytes_per_sample, |
| + uint32_t channels) |
| + : format_(format.Clone()), |
| + channels_(channels), |
| + bytes_per_sample_(bytes_per_sample), |
| + bytes_per_frame_(bytes_per_sample * channels) {} |
| + |
| +OutputFormatter::~OutputFormatter() {} |
| + |
| +// Selection routines which will instantiate a particular templatized version of |
| +// the output formatter. |
| +template <typename DType> |
| +static inline OutputFormatterPtr SelectOF( |
| + const LpcmMediaTypeDetailsPtr& format) { |
| + switch (format->channels) { |
| + case 1: |
| + return OutputFormatterPtr(new OutputFormatterImpl<DType, 1>(format)); |
| + case 2: |
| + return OutputFormatterPtr(new OutputFormatterImpl<DType, 2>(format)); |
| + default: |
| + LOG(ERROR) << "Unsupported output channels " |
| + << format->channels; |
| + return nullptr; |
| + } |
| +} |
| + |
| +OutputFormatterPtr OutputFormatter::Select( |
| + const LpcmMediaTypeDetailsPtr& format) { |
| + DCHECK(format); |
| + |
| + switch (format->sample_format) { |
| + case LpcmSampleFormat::UNSIGNED_8: |
| + return SelectOF<uint8_t>(format); |
| + case LpcmSampleFormat::SIGNED_16: |
| + return SelectOF<int16_t>(format); |
| + default: |
| + LOG(ERROR) << "Unsupported output sample format " |
| + << format->sample_format; |
| + return nullptr; |
| + } |
| +} |
| + |
| +} // namespace audio |
| +} // namespace media |
| +} // namespace mojo |