| 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( |
| 17 const LpcmStreamType& in_type, | 17 const LpcmStreamType& in_type, |
| 18 const LpcmStreamTypeSet& out_type); | 18 const LpcmStreamTypeSet& out_type); |
| 19 | 19 |
| 20 ~LpcmReformatterImpl() override; | 20 ~LpcmReformatterImpl() override; |
| 21 | 21 |
| 22 // LpcmTransform implementation. | 22 // Transform implementation. |
| 23 const LpcmStreamType& input_stream_type() const override; | 23 bool TransformPacket( |
| 24 | 24 const PacketPtr& input, |
| 25 const LpcmStreamType& output_stream_type() const override; | 25 bool new_input, |
| 26 | 26 PayloadAllocator* allocator, |
| 27 void TransformFrames( | 27 PacketPtr* output) override; |
| 28 LpcmFrameBuffer* source, | |
| 29 LpcmFrameBuffer* dest, | |
| 30 bool mix) override; | |
| 31 | 28 |
| 32 private: | 29 private: |
| 33 LpcmStreamType in_type_; | 30 LpcmStreamType in_type_; |
| 34 LpcmStreamType out_type_; | 31 LpcmStreamType out_type_; |
| 35 }; | 32 }; |
| 36 | 33 |
| 37 LpcmReformatterPtr LpcmReformatter::Create( | 34 std::shared_ptr<LpcmReformatter> LpcmReformatter::Create( |
| 38 const LpcmStreamType& in_type, | 35 const LpcmStreamType& in_type, |
| 39 const LpcmStreamTypeSet& out_type) { | 36 const LpcmStreamTypeSet& out_type) { |
| 40 LpcmReformatter* result = nullptr; | 37 LpcmReformatter* result = nullptr; |
| 41 | 38 |
| 42 switch (in_type.sample_format()) { | 39 switch (in_type.sample_format()) { |
| 43 case LpcmStreamType::SampleFormat::kUnsigned8: | 40 case LpcmStreamType::SampleFormat::kUnsigned8: |
| 44 switch (out_type.sample_format()) { | 41 switch (out_type.sample_format()) { |
| 45 case LpcmStreamType::SampleFormat::kUnsigned8: | 42 case LpcmStreamType::SampleFormat::kUnsigned8: |
| 46 case LpcmStreamType::SampleFormat::kAny: | 43 case LpcmStreamType::SampleFormat::kAny: |
| 47 result = new LpcmReformatterImpl<uint8_t, uint8_t>( | 44 result = new LpcmReformatterImpl<uint8_t, uint8_t>( |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 result = nullptr; | 135 result = nullptr; |
| 139 break; | 136 break; |
| 140 } | 137 } |
| 141 break; | 138 break; |
| 142 default: | 139 default: |
| 143 NOTREACHED() << "unsupported sample format"; | 140 NOTREACHED() << "unsupported sample format"; |
| 144 result = nullptr; | 141 result = nullptr; |
| 145 break; | 142 break; |
| 146 } | 143 } |
| 147 | 144 |
| 148 return LpcmReformatterPtr(result); | 145 return std::shared_ptr<LpcmReformatter>(result); |
| 149 } | 146 } |
| 150 | 147 |
| 151 template<typename TIn, typename TOut> | 148 template<typename TIn, typename TOut> |
| 152 LpcmReformatterImpl<TIn, TOut>::LpcmReformatterImpl( | 149 LpcmReformatterImpl<TIn, TOut>::LpcmReformatterImpl( |
| 153 const LpcmStreamType& in_type, | 150 const LpcmStreamType& in_type, |
| 154 const LpcmStreamTypeSet& out_type) : | 151 const LpcmStreamTypeSet& out_type) : |
| 155 in_type_(in_type), | 152 in_type_(in_type), |
| 156 out_type_( | 153 out_type_( |
| 157 out_type.sample_format() == LpcmStreamType::SampleFormat::kAny ? | 154 out_type.sample_format() == LpcmStreamType::SampleFormat::kAny ? |
| 158 in_type.sample_format() : | 155 in_type.sample_format() : |
| (...skipping 18 matching lines...) Expand all Loading... |
| 177 inline constexpr float Clamp(float val) { | 174 inline constexpr float Clamp(float val) { |
| 178 return Clamp(val, -1.0f, 1.0f); | 175 return Clamp(val, -1.0f, 1.0f); |
| 179 } | 176 } |
| 180 | 177 |
| 181 template <> | 178 template <> |
| 182 inline constexpr int32_t Clamp(int32_t val) { | 179 inline constexpr int32_t Clamp(int32_t val) { |
| 183 return Clamp(val, 1 << 23, -(1 << 23)); | 180 return Clamp(val, 1 << 23, -(1 << 23)); |
| 184 } | 181 } |
| 185 | 182 |
| 186 template<typename TIn, typename TOut> | 183 template<typename TIn, typename TOut> |
| 187 inline void CopySample(TOut* dest, TIn* source) { | 184 inline void CopySample(TOut* dest, const TIn* source) { |
| 188 *dest = static_cast<TOut>(*source); | 185 *dest = static_cast<TOut>(*source); |
| 189 } | 186 } |
| 190 | 187 |
| 191 inline void CopySample(uint8_t* dest, int16_t* source) { | 188 inline void CopySample(uint8_t* dest, const int16_t* source) { |
| 192 *dest = static_cast<uint8_t>((*source >> 8) ^ 0x80); | 189 *dest = static_cast<uint8_t>((*source >> 8) ^ 0x80); |
| 193 } | 190 } |
| 194 | 191 |
| 195 inline void CopySample(uint8_t* dest, int32_t* source) { | 192 inline void CopySample(uint8_t* dest, const int32_t* source) { |
| 196 *dest = static_cast<uint8_t>((Clamp(*source) >> 16) ^ 0x80); | 193 *dest = static_cast<uint8_t>((Clamp(*source) >> 16) ^ 0x80); |
| 197 } | 194 } |
| 198 | 195 |
| 199 inline void CopySample(uint8_t* dest, float* source) { | 196 inline void CopySample(uint8_t* dest, const float* source) { |
| 200 *dest = static_cast<uint8_t>((Clamp(*source) * 0x7f) + 128); | 197 *dest = static_cast<uint8_t>((Clamp(*source) * 0x7f) + 128); |
| 201 } | 198 } |
| 202 | 199 |
| 203 inline void CopySample(int16_t* dest, uint8_t* source) { | 200 inline void CopySample(int16_t* dest, const uint8_t* source) { |
| 204 *dest = static_cast<int16_t>(*source ^ 0x80) << 8; | 201 *dest = static_cast<int16_t>(*source ^ 0x80) << 8; |
| 205 } | 202 } |
| 206 | 203 |
| 207 inline void CopySample(int16_t* dest, int32_t* source) { | 204 inline void CopySample(int16_t* dest, const int32_t* source) { |
| 208 *dest = static_cast<int16_t>(Clamp(*source) >> 8); | 205 *dest = static_cast<int16_t>(Clamp(*source) >> 8); |
| 209 } | 206 } |
| 210 | 207 |
| 211 inline void CopySample(int16_t* dest, float* source) { | 208 inline void CopySample(int16_t* dest, const float* source) { |
| 212 *dest = static_cast<int16_t>(Clamp(*source) * 0x7fff); | 209 *dest = static_cast<int16_t>(Clamp(*source) * 0x7fff); |
| 213 } | 210 } |
| 214 | 211 |
| 215 inline void CopySample(int32_t* dest, uint8_t* source) { | 212 inline void CopySample(int32_t* dest, const uint8_t* source) { |
| 216 *dest = static_cast<int32_t>(*source ^ 0x80) << 16; | 213 *dest = static_cast<int32_t>(*source ^ 0x80) << 16; |
| 217 } | 214 } |
| 218 | 215 |
| 219 inline void CopySample(int32_t* dest, int16_t* source) { | 216 inline void CopySample(int32_t* dest, const int16_t* source) { |
| 220 *dest = static_cast<int32_t>(*source << 8); | 217 *dest = static_cast<int32_t>(*source << 8); |
| 221 } | 218 } |
| 222 | 219 |
| 223 inline void CopySample(int32_t* dest, float* source) { | 220 inline void CopySample(int32_t* dest, const float* source) { |
| 224 *dest = static_cast<int32_t>(Clamp(*source) * 0x7fffff); | 221 *dest = static_cast<int32_t>(Clamp(*source) * 0x7fffff); |
| 225 } | 222 } |
| 226 | 223 |
| 227 inline void CopySample(float* dest, uint8_t* source) { | 224 inline void CopySample(float* dest, const uint8_t* source) { |
| 228 *dest = static_cast<float>(*source ^ 0x80) / 0x80; | 225 *dest = static_cast<float>(*source ^ 0x80) / 0x80; |
| 229 } | 226 } |
| 230 | 227 |
| 231 inline void CopySample(float* dest, int16_t* source) { | 228 inline void CopySample(float* dest, const int16_t* source) { |
| 232 *dest = static_cast<float>(*source) / 0x8000; | 229 *dest = static_cast<float>(*source) / 0x8000; |
| 233 } | 230 } |
| 234 | 231 |
| 235 inline void CopySample(float* dest, int32_t* source) { | 232 inline void CopySample(float* dest, const int32_t* source) { |
| 236 *dest = static_cast<float>(Clamp(*source)) / 0x800000; | 233 *dest = static_cast<float>(Clamp(*source)) / 0x800000; |
| 237 } | 234 } |
| 238 | 235 |
| 239 template<typename TIn, typename TOut> | |
| 240 inline void MixSample(TOut* dest, TIn* source) { | |
| 241 *dest += static_cast<TOut>(*source); | |
| 242 } | |
| 243 | |
| 244 inline void MixSample(uint8_t* dest, int16_t* source) { | |
| 245 *dest += static_cast<uint8_t>((*source >> 8) ^ 0x80); | |
| 246 } | |
| 247 | |
| 248 inline void MixSample(uint8_t* dest, int32_t* source) { | |
| 249 *dest += static_cast<uint8_t>((Clamp(*source) >> 16) ^ 0x80); | |
| 250 } | |
| 251 | |
| 252 inline void MixSample(uint8_t* dest, float* source) { | |
| 253 *dest += static_cast<uint8_t>((Clamp(*source) * 0x7f) + 128); | |
| 254 } | |
| 255 | |
| 256 inline void MixSample(int16_t* dest, uint8_t* source) { | |
| 257 *dest += static_cast<int16_t>(*source ^ 0x80) << 8; | |
| 258 } | |
| 259 | |
| 260 inline void MixSample(int16_t* dest, int32_t* source) { | |
| 261 *dest += static_cast<int16_t>(Clamp(*source) >> 8); | |
| 262 } | |
| 263 | |
| 264 inline void MixSample(int16_t* dest, float* source) { | |
| 265 *dest += static_cast<int16_t>(Clamp(*source) * 0x7fff); | |
| 266 } | |
| 267 | |
| 268 inline void MixSample(int32_t* dest, uint8_t* source) { | |
| 269 *dest += static_cast<int32_t>(*source ^ 0x80) << 16; | |
| 270 } | |
| 271 | |
| 272 inline void MixSample(int32_t* dest, int16_t* source) { | |
| 273 *dest += static_cast<int32_t>(*source << 8); | |
| 274 } | |
| 275 | |
| 276 inline void MixSample(int32_t* dest, float* source) { | |
| 277 *dest += static_cast<int32_t>(Clamp(*source) * 0x7fffff); | |
| 278 } | |
| 279 | |
| 280 inline void MixSample(float* dest, uint8_t* source) { | |
| 281 *dest += static_cast<float>(*source ^ 0x80) / 0x80; | |
| 282 } | |
| 283 | |
| 284 inline void MixSample(float* dest, int16_t* source) { | |
| 285 *dest += static_cast<float>(*source) / 0x8000; | |
| 286 } | |
| 287 | |
| 288 inline void MixSample(float* dest, int32_t* source) { | |
| 289 *dest += static_cast<float>(Clamp(*source)) / 0x800000; | |
| 290 } | |
| 291 | |
| 292 } // namespace | 236 } // namespace |
| 293 | 237 |
| 294 template<typename TIn, typename TOut> | 238 template<typename TIn, typename TOut> |
| 295 const LpcmStreamType& LpcmReformatterImpl<TIn, TOut>::input_stream_type() | 239 bool LpcmReformatterImpl<TIn, TOut>::TransformPacket( |
| 296 const { | 240 const PacketPtr& input, |
| 297 return in_type_; | 241 bool new_input, |
| 298 } | 242 PayloadAllocator* allocator, |
| 243 PacketPtr* output) { |
| 244 DCHECK(input); |
| 245 DCHECK(allocator); |
| 246 DCHECK(output); |
| 299 | 247 |
| 300 template<typename TIn, typename TOut> | 248 uint64_t in_size = input->size(); |
| 301 const LpcmStreamType& LpcmReformatterImpl<TIn, TOut>::output_stream_type() | 249 if (in_size == 0) { |
| 302 const { | 250 // Zero-sized input packet. Make a copy. |
| 303 return out_type_; | 251 *output = Packet::Create( |
| 304 } | 252 input->presentation_time(), |
| 253 input->duration(), |
| 254 input->end_of_stream(), |
| 255 0, |
| 256 nullptr, |
| 257 nullptr); |
| 258 return true; |
| 259 } |
| 305 | 260 |
| 306 template<typename TIn, typename TOut> | 261 size_t frame_count = input->duration(); |
| 307 void LpcmReformatterImpl<TIn, TOut>::TransformFrames( | 262 uint64_t out_size = out_type_.min_buffer_size(frame_count); |
| 308 LpcmFrameBuffer* source, | |
| 309 LpcmFrameBuffer* dest, | |
| 310 bool mix) { | |
| 311 DCHECK(source); | |
| 312 DCHECK(dest); | |
| 313 DCHECK(source->buffer()); | |
| 314 DCHECK(source->frame_count()); | |
| 315 DCHECK(dest->buffer()); | |
| 316 DCHECK(dest->frame_count()); | |
| 317 | 263 |
| 318 uint64_t frame_count = std::min(source->frame_count(), dest->frame_count()); | 264 void* buffer = allocator->AllocatePayloadBuffer(out_size); |
| 265 if (buffer == nullptr) { |
| 266 LOG(WARNING) << "lpcm reformatter starved for buffers"; |
| 267 // Starved for buffer space. Can't process now. |
| 268 *output = nullptr; |
| 269 return false; |
| 270 } |
| 319 | 271 |
| 320 uint8_t* in_channel = static_cast<uint8_t*>(source->buffer()); | 272 const TIn* in_channel = static_cast<const TIn*>(input->payload()); |
| 321 uint8_t* out_channel = static_cast<uint8_t*>(dest->buffer()); | 273 TOut* out_channel = static_cast<TOut*>(buffer); |
| 322 | 274 |
| 323 for (uint32_t channel = 0; channel < in_type_.channels(); channel++) { | 275 for (uint32_t channel = 0; channel < in_type_.channels(); channel++) { |
| 324 TIn* in_sample = reinterpret_cast<TIn*>(in_channel); | 276 const TIn* in_sample = in_channel; |
| 325 TOut* out_sample = reinterpret_cast<TOut*>(out_channel); | 277 TOut* out_sample = out_channel; |
| 326 if (mix) { | 278 for (size_t sample = 0; sample < frame_count; sample++) { |
| 327 for (uint64_t sample = 0; sample < frame_count; sample++) { | 279 CopySample(out_sample, in_sample); |
| 328 MixSample(out_sample, in_sample); | 280 in_sample += in_type_.channels(); |
| 329 in_sample += in_type_.channels(); | 281 out_sample += out_type_.channels(); |
| 330 out_sample += out_type_.channels(); | |
| 331 } | |
| 332 } else { | |
| 333 for (uint64_t sample = 0; sample < frame_count; sample++) { | |
| 334 CopySample(out_sample, in_sample); | |
| 335 in_sample += in_type_.channels(); | |
| 336 out_sample += out_type_.channels(); | |
| 337 } | |
| 338 } | 282 } |
| 339 in_channel += in_type_.sample_size(); | 283 ++in_channel; |
| 340 out_channel += out_type_.sample_size(); | 284 ++out_channel; |
| 341 } | 285 } |
| 342 | 286 |
| 343 source->Advance(frame_count); | 287 *output = Packet::Create( |
| 344 dest->Advance(frame_count); | 288 input->presentation_time(), |
| 289 frame_count, |
| 290 input->end_of_stream(), |
| 291 out_size, |
| 292 buffer, |
| 293 allocator); |
| 294 |
| 295 return true; |
| 345 } | 296 } |
| 346 | 297 |
| 347 } // namespace media | 298 } // namespace media |
| 348 } // namespace mojo | 299 } // namespace mojo |
| OLD | NEW |