| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/logging.h" | 5 #include "base/logging.h" |
| 6 #include "services/media/framework/parts/lpcm_reformatter.h" | 6 #include "services/media/framework/parts/lpcm_reformatter.h" |
| 7 | 7 |
| 8 namespace mojo { | 8 namespace mojo { |
| 9 namespace media { | 9 namespace media { |
| 10 | 10 |
| 11 // LpcmReformatter implementation that accepts samples of type TIn and | 11 // LpcmReformatter implementation that accepts samples of type TIn and |
| 12 // produces samples of type TOut. | 12 // produces samples of type TOut. |
| 13 template<typename TIn, typename TOut> | 13 template <typename TIn, typename TOut> |
| 14 class LpcmReformatterImpl : public LpcmReformatter { | 14 class LpcmReformatterImpl : public LpcmReformatter { |
| 15 public: | 15 public: |
| 16 LpcmReformatterImpl( | 16 LpcmReformatterImpl(const LpcmStreamType& in_type, |
| 17 const LpcmStreamType& in_type, | 17 const LpcmStreamTypeSet& out_type); |
| 18 const LpcmStreamTypeSet& out_type); | |
| 19 | 18 |
| 20 ~LpcmReformatterImpl() override; | 19 ~LpcmReformatterImpl() override; |
| 21 | 20 |
| 22 // Transform implementation. | 21 // Transform implementation. |
| 23 bool TransformPacket( | 22 bool TransformPacket(const PacketPtr& input, |
| 24 const PacketPtr& input, | 23 bool new_input, |
| 25 bool new_input, | 24 PayloadAllocator* allocator, |
| 26 PayloadAllocator* allocator, | 25 PacketPtr* output) override; |
| 27 PacketPtr* output) override; | |
| 28 | 26 |
| 29 private: | 27 private: |
| 30 LpcmStreamType in_type_; | 28 LpcmStreamType in_type_; |
| 31 LpcmStreamType out_type_; | 29 LpcmStreamType out_type_; |
| 32 }; | 30 }; |
| 33 | 31 |
| 34 std::shared_ptr<LpcmReformatter> LpcmReformatter::Create( | 32 std::shared_ptr<LpcmReformatter> LpcmReformatter::Create( |
| 35 const LpcmStreamType& in_type, | 33 const LpcmStreamType& in_type, |
| 36 const LpcmStreamTypeSet& out_type) { | 34 const LpcmStreamTypeSet& out_type) { |
| 37 LpcmReformatter* result = nullptr; | 35 LpcmReformatter* result = nullptr; |
| 38 | 36 |
| 39 switch (in_type.sample_format()) { | 37 switch (in_type.sample_format()) { |
| 40 case LpcmStreamType::SampleFormat::kUnsigned8: | 38 case LpcmStreamType::SampleFormat::kUnsigned8: |
| 41 switch (out_type.sample_format()) { | 39 switch (out_type.sample_format()) { |
| 42 case LpcmStreamType::SampleFormat::kUnsigned8: | 40 case LpcmStreamType::SampleFormat::kUnsigned8: |
| 43 case LpcmStreamType::SampleFormat::kAny: | 41 case LpcmStreamType::SampleFormat::kAny: |
| 44 result = new LpcmReformatterImpl<uint8_t, uint8_t>( | 42 result = new LpcmReformatterImpl<uint8_t, uint8_t>(in_type, out_type); |
| 45 in_type, out_type); | |
| 46 break; | 43 break; |
| 47 case LpcmStreamType::SampleFormat::kSigned16: | 44 case LpcmStreamType::SampleFormat::kSigned16: |
| 48 result = new LpcmReformatterImpl<uint8_t, int16_t>( | 45 result = new LpcmReformatterImpl<uint8_t, int16_t>(in_type, out_type); |
| 49 in_type, out_type); | |
| 50 break; | 46 break; |
| 51 case LpcmStreamType::SampleFormat::kSigned24In32: | 47 case LpcmStreamType::SampleFormat::kSigned24In32: |
| 52 result = new LpcmReformatterImpl<uint8_t, int32_t>( | 48 result = new LpcmReformatterImpl<uint8_t, int32_t>(in_type, out_type); |
| 53 in_type, out_type); | |
| 54 break; | 49 break; |
| 55 case LpcmStreamType::SampleFormat::kFloat: | 50 case LpcmStreamType::SampleFormat::kFloat: |
| 56 result = new LpcmReformatterImpl<uint8_t, float>( | 51 result = new LpcmReformatterImpl<uint8_t, float>(in_type, out_type); |
| 57 in_type, out_type); | |
| 58 break; | 52 break; |
| 59 default: | 53 default: |
| 60 NOTREACHED() << "unsupported sample format"; | 54 NOTREACHED() << "unsupported sample format"; |
| 61 result = nullptr; | 55 result = nullptr; |
| 62 break; | 56 break; |
| 63 } | 57 } |
| 64 break; | 58 break; |
| 65 case LpcmStreamType::SampleFormat::kSigned16: | 59 case LpcmStreamType::SampleFormat::kSigned16: |
| 66 switch (out_type.sample_format()) { | 60 switch (out_type.sample_format()) { |
| 67 case LpcmStreamType::SampleFormat::kUnsigned8: | 61 case LpcmStreamType::SampleFormat::kUnsigned8: |
| 68 result = new LpcmReformatterImpl<int16_t, uint8_t>( | 62 result = new LpcmReformatterImpl<int16_t, uint8_t>(in_type, out_type); |
| 69 in_type, out_type); | |
| 70 break; | 63 break; |
| 71 case LpcmStreamType::SampleFormat::kSigned16: | 64 case LpcmStreamType::SampleFormat::kSigned16: |
| 72 case LpcmStreamType::SampleFormat::kAny: | 65 case LpcmStreamType::SampleFormat::kAny: |
| 73 result = new LpcmReformatterImpl<int16_t, int16_t>( | 66 result = new LpcmReformatterImpl<int16_t, int16_t>(in_type, out_type); |
| 74 in_type, out_type); | |
| 75 break; | 67 break; |
| 76 case LpcmStreamType::SampleFormat::kSigned24In32: | 68 case LpcmStreamType::SampleFormat::kSigned24In32: |
| 77 result = new LpcmReformatterImpl<int16_t, int32_t>( | 69 result = new LpcmReformatterImpl<int16_t, int32_t>(in_type, out_type); |
| 78 in_type, out_type); | |
| 79 break; | 70 break; |
| 80 case LpcmStreamType::SampleFormat::kFloat: | 71 case LpcmStreamType::SampleFormat::kFloat: |
| 81 result = new LpcmReformatterImpl<int16_t, float>( | 72 result = new LpcmReformatterImpl<int16_t, float>(in_type, out_type); |
| 82 in_type, out_type); | |
| 83 break; | 73 break; |
| 84 default: | 74 default: |
| 85 NOTREACHED() << "unsupported sample format"; | 75 NOTREACHED() << "unsupported sample format"; |
| 86 result = nullptr; | 76 result = nullptr; |
| 87 break; | 77 break; |
| 88 } | 78 } |
| 89 break; | 79 break; |
| 90 case LpcmStreamType::SampleFormat::kSigned24In32: | 80 case LpcmStreamType::SampleFormat::kSigned24In32: |
| 91 switch (out_type.sample_format()) { | 81 switch (out_type.sample_format()) { |
| 92 case LpcmStreamType::SampleFormat::kUnsigned8: | 82 case LpcmStreamType::SampleFormat::kUnsigned8: |
| 93 result = new LpcmReformatterImpl<int32_t, uint8_t>( | 83 result = new LpcmReformatterImpl<int32_t, uint8_t>(in_type, out_type); |
| 94 in_type, out_type); | |
| 95 break; | 84 break; |
| 96 case LpcmStreamType::SampleFormat::kSigned16: | 85 case LpcmStreamType::SampleFormat::kSigned16: |
| 97 result = new LpcmReformatterImpl<int32_t, int16_t>( | 86 result = new LpcmReformatterImpl<int32_t, int16_t>(in_type, out_type); |
| 98 in_type, out_type); | |
| 99 break; | 87 break; |
| 100 case LpcmStreamType::SampleFormat::kSigned24In32: | 88 case LpcmStreamType::SampleFormat::kSigned24In32: |
| 101 case LpcmStreamType::SampleFormat::kAny: | 89 case LpcmStreamType::SampleFormat::kAny: |
| 102 result = new LpcmReformatterImpl<int32_t, int32_t>( | 90 result = new LpcmReformatterImpl<int32_t, int32_t>(in_type, out_type); |
| 103 in_type, out_type); | |
| 104 break; | 91 break; |
| 105 case LpcmStreamType::SampleFormat::kFloat: | 92 case LpcmStreamType::SampleFormat::kFloat: |
| 106 result = new LpcmReformatterImpl<int32_t, float>( | 93 result = new LpcmReformatterImpl<int32_t, float>(in_type, out_type); |
| 107 in_type, out_type); | |
| 108 break; | 94 break; |
| 109 default: | 95 default: |
| 110 NOTREACHED() << "unsupported sample format"; | 96 NOTREACHED() << "unsupported sample format"; |
| 111 result = nullptr; | 97 result = nullptr; |
| 112 break; | 98 break; |
| 113 } | 99 } |
| 114 break; | 100 break; |
| 115 case LpcmStreamType::SampleFormat::kFloat: | 101 case LpcmStreamType::SampleFormat::kFloat: |
| 116 switch (out_type.sample_format()) { | 102 switch (out_type.sample_format()) { |
| 117 case LpcmStreamType::SampleFormat::kUnsigned8: | 103 case LpcmStreamType::SampleFormat::kUnsigned8: |
| 118 result = new LpcmReformatterImpl<float, uint8_t>( | 104 result = new LpcmReformatterImpl<float, uint8_t>(in_type, out_type); |
| 119 in_type, out_type); | |
| 120 break; | 105 break; |
| 121 case LpcmStreamType::SampleFormat::kSigned16: | 106 case LpcmStreamType::SampleFormat::kSigned16: |
| 122 result = new LpcmReformatterImpl<float, int16_t>( | 107 result = new LpcmReformatterImpl<float, int16_t>(in_type, out_type); |
| 123 in_type, out_type); | |
| 124 break; | 108 break; |
| 125 case LpcmStreamType::SampleFormat::kSigned24In32: | 109 case LpcmStreamType::SampleFormat::kSigned24In32: |
| 126 result = new LpcmReformatterImpl<float, int32_t>( | 110 result = new LpcmReformatterImpl<float, int32_t>(in_type, out_type); |
| 127 in_type, out_type); | |
| 128 break; | 111 break; |
| 129 case LpcmStreamType::SampleFormat::kFloat: | 112 case LpcmStreamType::SampleFormat::kFloat: |
| 130 case LpcmStreamType::SampleFormat::kAny: | 113 case LpcmStreamType::SampleFormat::kAny: |
| 131 result = new LpcmReformatterImpl<float, float>(in_type, out_type); | 114 result = new LpcmReformatterImpl<float, float>(in_type, out_type); |
| 132 break; | 115 break; |
| 133 default: | 116 default: |
| 134 NOTREACHED() << "unsupported sample format"; | 117 NOTREACHED() << "unsupported sample format"; |
| 135 result = nullptr; | 118 result = nullptr; |
| 136 break; | 119 break; |
| 137 } | 120 } |
| 138 break; | 121 break; |
| 139 default: | 122 default: |
| 140 NOTREACHED() << "unsupported sample format"; | 123 NOTREACHED() << "unsupported sample format"; |
| 141 result = nullptr; | 124 result = nullptr; |
| 142 break; | 125 break; |
| 143 } | 126 } |
| 144 | 127 |
| 145 return std::shared_ptr<LpcmReformatter>(result); | 128 return std::shared_ptr<LpcmReformatter>(result); |
| 146 } | 129 } |
| 147 | 130 |
| 148 template<typename TIn, typename TOut> | 131 template <typename TIn, typename TOut> |
| 149 LpcmReformatterImpl<TIn, TOut>::LpcmReformatterImpl( | 132 LpcmReformatterImpl<TIn, TOut>::LpcmReformatterImpl( |
| 150 const LpcmStreamType& in_type, | 133 const LpcmStreamType& in_type, |
| 151 const LpcmStreamTypeSet& out_type) : | 134 const LpcmStreamTypeSet& out_type) |
| 152 in_type_(in_type), | 135 : in_type_(in_type), |
| 153 out_type_( | 136 out_type_(out_type.sample_format() == LpcmStreamType::SampleFormat::kAny |
| 154 out_type.sample_format() == LpcmStreamType::SampleFormat::kAny ? | 137 ? in_type.sample_format() |
| 155 in_type.sample_format() : | 138 : out_type.sample_format(), |
| 156 out_type.sample_format(), | 139 in_type.channels(), |
| 157 in_type.channels(), | 140 in_type.frames_per_second()) {} |
| 158 in_type.frames_per_second()) {} | |
| 159 | 141 |
| 160 template<typename TIn, typename TOut> | 142 template <typename TIn, typename TOut> |
| 161 LpcmReformatterImpl<TIn, TOut>::~LpcmReformatterImpl() {} | 143 LpcmReformatterImpl<TIn, TOut>::~LpcmReformatterImpl() {} |
| 162 | 144 |
| 163 namespace { | 145 namespace { |
| 164 | 146 |
| 165 template <typename T> | 147 template <typename T> |
| 166 inline constexpr T Clamp(T val, T min, T max) { | 148 inline constexpr T Clamp(T val, T min, T max) { |
| 167 return (val > max) ? max : ((val < min) ? min : val); | 149 return (val > max) ? max : ((val < min) ? min : val); |
| 168 } | 150 } |
| 169 | 151 |
| 170 template <typename T> | 152 template <typename T> |
| 171 inline constexpr T Clamp(T val); | 153 inline constexpr T Clamp(T val); |
| 172 | 154 |
| 173 template <> | 155 template <> |
| 174 inline constexpr float Clamp(float val) { | 156 inline constexpr float Clamp(float val) { |
| 175 return Clamp(val, -1.0f, 1.0f); | 157 return Clamp(val, -1.0f, 1.0f); |
| 176 } | 158 } |
| 177 | 159 |
| 178 template <> | 160 template <> |
| 179 inline constexpr int32_t Clamp(int32_t val) { | 161 inline constexpr int32_t Clamp(int32_t val) { |
| 180 return Clamp(val, 1 << 23, -(1 << 23)); | 162 return Clamp(val, 1 << 23, -(1 << 23)); |
| 181 } | 163 } |
| 182 | 164 |
| 183 template<typename TIn, typename TOut> | 165 template <typename TIn, typename TOut> |
| 184 inline void CopySample(TOut* dest, const TIn* source) { | 166 inline void CopySample(TOut* dest, const TIn* source) { |
| 185 *dest = static_cast<TOut>(*source); | 167 *dest = static_cast<TOut>(*source); |
| 186 } | 168 } |
| 187 | 169 |
| 188 inline void CopySample(uint8_t* dest, const int16_t* source) { | 170 inline void CopySample(uint8_t* dest, const int16_t* source) { |
| 189 *dest = static_cast<uint8_t>((*source >> 8) ^ 0x80); | 171 *dest = static_cast<uint8_t>((*source >> 8) ^ 0x80); |
| 190 } | 172 } |
| 191 | 173 |
| 192 inline void CopySample(uint8_t* dest, const int32_t* source) { | 174 inline void CopySample(uint8_t* dest, const int32_t* source) { |
| 193 *dest = static_cast<uint8_t>((Clamp(*source) >> 16) ^ 0x80); | 175 *dest = static_cast<uint8_t>((Clamp(*source) >> 16) ^ 0x80); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 208 } |
| 227 | 209 |
| 228 inline void CopySample(float* dest, const int16_t* source) { | 210 inline void CopySample(float* dest, const int16_t* source) { |
| 229 *dest = static_cast<float>(*source) / 0x8000; | 211 *dest = static_cast<float>(*source) / 0x8000; |
| 230 } | 212 } |
| 231 | 213 |
| 232 inline void CopySample(float* dest, const int32_t* source) { | 214 inline void CopySample(float* dest, const int32_t* source) { |
| 233 *dest = static_cast<float>(Clamp(*source)) / 0x800000; | 215 *dest = static_cast<float>(Clamp(*source)) / 0x800000; |
| 234 } | 216 } |
| 235 | 217 |
| 236 } // namespace | 218 } // namespace |
| 237 | 219 |
| 238 template<typename TIn, typename TOut> | 220 template <typename TIn, typename TOut> |
| 239 bool LpcmReformatterImpl<TIn, TOut>::TransformPacket( | 221 bool LpcmReformatterImpl<TIn, TOut>::TransformPacket( |
| 240 const PacketPtr& input, | 222 const PacketPtr& input, |
| 241 bool new_input, | 223 bool new_input, |
| 242 PayloadAllocator* allocator, | 224 PayloadAllocator* allocator, |
| 243 PacketPtr* output) { | 225 PacketPtr* output) { |
| 244 DCHECK(input); | 226 DCHECK(input); |
| 245 DCHECK(allocator); | 227 DCHECK(allocator); |
| 246 DCHECK(output); | 228 DCHECK(output); |
| 247 | 229 |
| 248 uint64_t in_size = input->size(); | 230 uint64_t in_size = input->size(); |
| 249 if (in_size == 0) { | 231 if (in_size == 0) { |
| 250 // Zero-sized input packet. Make a copy. | 232 // Zero-sized input packet. Make a copy. |
| 251 *output = Packet::Create( | 233 *output = Packet::Create(input->pts(), input->end_of_stream(), 0, nullptr, |
| 252 input->pts(), | 234 nullptr); |
| 253 input->end_of_stream(), | |
| 254 0, | |
| 255 nullptr, | |
| 256 nullptr); | |
| 257 return true; | 235 return true; |
| 258 } | 236 } |
| 259 | 237 |
| 260 size_t frame_count = in_type_.frame_count(in_size); | 238 size_t frame_count = in_type_.frame_count(in_size); |
| 261 uint64_t out_size = out_type_.min_buffer_size(frame_count); | 239 uint64_t out_size = out_type_.min_buffer_size(frame_count); |
| 262 | 240 |
| 263 void* buffer = allocator->AllocatePayloadBuffer(out_size); | 241 void* buffer = allocator->AllocatePayloadBuffer(out_size); |
| 264 if (buffer == nullptr) { | 242 if (buffer == nullptr) { |
| 265 LOG(WARNING) << "lpcm reformatter starved for buffers"; | 243 LOG(WARNING) << "lpcm reformatter starved for buffers"; |
| 266 // Starved for buffer space. Can't process now. | 244 // Starved for buffer space. Can't process now. |
| 267 *output = nullptr; | 245 *output = nullptr; |
| 268 return false; | 246 return false; |
| 269 } | 247 } |
| 270 | 248 |
| 271 const TIn* in_channel = static_cast<const TIn*>(input->payload()); | 249 const TIn* in_channel = static_cast<const TIn*>(input->payload()); |
| 272 TOut* out_channel = static_cast<TOut*>(buffer); | 250 TOut* out_channel = static_cast<TOut*>(buffer); |
| 273 | 251 |
| 274 for (uint32_t channel = 0; channel < in_type_.channels(); channel++) { | 252 for (uint32_t channel = 0; channel < in_type_.channels(); channel++) { |
| 275 const TIn* in_sample = in_channel; | 253 const TIn* in_sample = in_channel; |
| 276 TOut* out_sample = out_channel; | 254 TOut* out_sample = out_channel; |
| 277 for (size_t sample = 0; sample < frame_count; sample++) { | 255 for (size_t sample = 0; sample < frame_count; sample++) { |
| 278 CopySample(out_sample, in_sample); | 256 CopySample(out_sample, in_sample); |
| 279 in_sample += in_type_.channels(); | 257 in_sample += in_type_.channels(); |
| 280 out_sample += out_type_.channels(); | 258 out_sample += out_type_.channels(); |
| 281 } | 259 } |
| 282 ++in_channel; | 260 ++in_channel; |
| 283 ++out_channel; | 261 ++out_channel; |
| 284 } | 262 } |
| 285 | 263 |
| 286 *output = Packet::Create( | 264 *output = Packet::Create(input->pts(), input->end_of_stream(), out_size, |
| 287 input->pts(), | 265 buffer, allocator); |
| 288 input->end_of_stream(), | |
| 289 out_size, | |
| 290 buffer, | |
| 291 allocator); | |
| 292 | 266 |
| 293 return true; | 267 return true; |
| 294 } | 268 } |
| 295 | 269 |
| 296 } // namespace media | 270 } // namespace media |
| 297 } // namespace mojo | 271 } // namespace mojo |
| OLD | NEW |