Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/logging.h" | |
| 6 #include "services/media/framework/parts/lpcm_reformatter.h" | |
| 7 | |
| 8 namespace mojo { | |
| 9 namespace media { | |
| 10 | |
| 11 LpcmReformatter* LpcmReformatter::NewImpl( | |
| 12 const LpcmStreamType& in_type, | |
| 13 const LpcmStreamTypeSet& out_type) { | |
| 14 switch (in_type.sample_format()) { | |
|
johngro
2016/01/26 23:47:29
up to you, but you can reduce the amount of duplic
dalesat
2016/01/28 18:49:16
Acknowledged.
| |
| 15 case LpcmStreamType::SampleFormat::kUnsigned8: | |
| 16 switch (out_type.sample_format()) { | |
| 17 case LpcmStreamType::SampleFormat::kUnsigned8: | |
| 18 case LpcmStreamType::SampleFormat::kAny: | |
| 19 return new LpcmReformatterImpl<uint8_t, uint8_t>( | |
| 20 in_type, out_type); | |
| 21 case LpcmStreamType::SampleFormat::kSigned16: | |
| 22 return new LpcmReformatterImpl<uint8_t, int16_t>( | |
| 23 in_type, out_type); | |
| 24 case LpcmStreamType::SampleFormat::kSigned24In32: | |
| 25 return new LpcmReformatterImpl<uint8_t, int32_t>( | |
| 26 in_type, out_type); | |
| 27 case LpcmStreamType::SampleFormat::kFloat: | |
| 28 return new LpcmReformatterImpl<uint8_t, float>( | |
| 29 in_type, out_type); | |
| 30 default: | |
| 31 NOTREACHED() << "unsupported sample format"; | |
| 32 return nullptr; | |
| 33 } | |
| 34 case LpcmStreamType::SampleFormat::kSigned16: | |
| 35 switch (out_type.sample_format()) { | |
| 36 case LpcmStreamType::SampleFormat::kUnsigned8: | |
| 37 return new LpcmReformatterImpl<int16_t, uint8_t>( | |
| 38 in_type, out_type); | |
| 39 case LpcmStreamType::SampleFormat::kSigned16: | |
| 40 case LpcmStreamType::SampleFormat::kAny: | |
| 41 return new LpcmReformatterImpl<int16_t, int16_t>( | |
| 42 in_type, out_type); | |
| 43 case LpcmStreamType::SampleFormat::kSigned24In32: | |
| 44 return new LpcmReformatterImpl<int16_t, int32_t>( | |
| 45 in_type, out_type); | |
| 46 case LpcmStreamType::SampleFormat::kFloat: | |
| 47 return new LpcmReformatterImpl<int16_t, float>( | |
| 48 in_type, out_type); | |
| 49 default: | |
| 50 NOTREACHED() << "unsupported sample format"; | |
| 51 return nullptr; | |
| 52 } | |
| 53 case LpcmStreamType::SampleFormat::kSigned24In32: | |
| 54 switch (out_type.sample_format()) { | |
| 55 case LpcmStreamType::SampleFormat::kUnsigned8: | |
| 56 return new LpcmReformatterImpl<int32_t, uint8_t>( | |
| 57 in_type, out_type); | |
| 58 case LpcmStreamType::SampleFormat::kSigned16: | |
| 59 return new LpcmReformatterImpl<int32_t, int16_t>( | |
| 60 in_type, out_type); | |
| 61 case LpcmStreamType::SampleFormat::kSigned24In32: | |
| 62 case LpcmStreamType::SampleFormat::kAny: | |
| 63 return new LpcmReformatterImpl<int32_t, int32_t>( | |
| 64 in_type, out_type); | |
| 65 case LpcmStreamType::SampleFormat::kFloat: | |
| 66 return new LpcmReformatterImpl<int32_t, float>( | |
| 67 in_type, out_type); | |
| 68 default: | |
| 69 NOTREACHED() << "unsupported sample format"; | |
| 70 return nullptr; | |
| 71 } | |
| 72 case LpcmStreamType::SampleFormat::kFloat: | |
| 73 switch (out_type.sample_format()) { | |
| 74 case LpcmStreamType::SampleFormat::kUnsigned8: | |
| 75 return new LpcmReformatterImpl<float, uint8_t>( | |
| 76 in_type, out_type); | |
| 77 case LpcmStreamType::SampleFormat::kSigned16: | |
| 78 return new LpcmReformatterImpl<float, int16_t>( | |
| 79 in_type, out_type); | |
| 80 case LpcmStreamType::SampleFormat::kSigned24In32: | |
| 81 return new LpcmReformatterImpl<float, int32_t>( | |
| 82 in_type, out_type); | |
| 83 case LpcmStreamType::SampleFormat::kFloat: | |
| 84 case LpcmStreamType::SampleFormat::kAny: | |
| 85 return new LpcmReformatterImpl<float, float>(in_type, out_type); | |
| 86 default: | |
| 87 NOTREACHED() << "unsupported sample format"; | |
| 88 return nullptr; | |
| 89 } | |
| 90 default: | |
| 91 NOTREACHED() << "unsupported sample format"; | |
| 92 return nullptr; | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 template<typename TIn, typename TOut> | |
| 97 LpcmReformatterImpl<TIn, TOut>::LpcmReformatterImpl( | |
| 98 const LpcmStreamType& in_type, | |
| 99 const LpcmStreamTypeSet& out_type) : | |
| 100 in_type_(in_type), | |
| 101 out_type_( | |
| 102 out_type.sample_format() == LpcmStreamType::SampleFormat::kAny ? | |
| 103 in_type.sample_format() : | |
| 104 out_type.sample_format(), | |
| 105 in_type.channels(), | |
| 106 in_type.frames_per_second()) {} | |
| 107 | |
| 108 template<typename TIn, typename TOut> | |
| 109 LpcmReformatterImpl<TIn, TOut>::~LpcmReformatterImpl() {} | |
| 110 | |
| 111 namespace { | |
| 112 | |
| 113 // TODO(dalesat): Limit, optimize. | |
| 114 | |
| 115 template<typename TIn, typename TOut> | |
| 116 inline void CopySample(TOut* dest, TIn* source) { | |
| 117 *dest = static_cast<TOut>(*source); | |
| 118 } | |
| 119 | |
| 120 inline void CopySample(uint8_t* dest, int16_t* source) { | |
| 121 *dest = static_cast<uint8_t>((*source >> 8) ^ 0x80); | |
| 122 } | |
| 123 | |
| 124 inline void CopySample(uint8_t* dest, int32_t* source) { | |
| 125 *dest = static_cast<uint8_t>((*source >> 16) ^ 0x80); | |
| 126 } | |
| 127 | |
| 128 inline void CopySample(uint8_t* dest, float* source) { | |
|
johngro
2016/01/26 23:47:29
Source needs to be clamped to the range [-1.0, 1.0
dalesat
2016/01/28 18:49:15
Done.
| |
| 129 *dest = static_cast<uint8_t>((*source * 0x7f) + 128); | |
| 130 } | |
| 131 | |
| 132 inline void CopySample(int16_t* dest, uint8_t* source) { | |
| 133 *dest = static_cast<int16_t>(*source ^ 0x80) << 8; | |
| 134 } | |
| 135 | |
| 136 inline void CopySample(int16_t* dest, int32_t* source) { | |
| 137 *dest = static_cast<int16_t>(*source >> 8); | |
| 138 } | |
| 139 | |
| 140 inline void CopySample(int16_t* dest, float* source) { | |
| 141 *dest = static_cast<int16_t>(*source * 0x7fff); | |
| 142 } | |
| 143 | |
| 144 inline void CopySample(int32_t* dest, uint8_t* source) { | |
| 145 *dest = static_cast<int32_t>(*source ^ 0x80) << 16; | |
| 146 } | |
| 147 | |
| 148 inline void CopySample(int32_t* dest, int16_t* source) { | |
| 149 *dest = static_cast<int32_t>(*source << 8); | |
| 150 } | |
| 151 | |
| 152 inline void CopySample(int32_t* dest, float* source) { | |
| 153 *dest = static_cast<int32_t>(*source * 0x7fffff); | |
| 154 } | |
| 155 | |
| 156 inline void CopySample(float* dest, uint8_t* source) { | |
| 157 *dest = static_cast<float>(*source ^ 0x80) / 0x80; | |
| 158 } | |
| 159 | |
| 160 inline void CopySample(float* dest, int16_t* source) { | |
| 161 *dest = static_cast<float>(*source) / 0x8000; | |
| 162 } | |
| 163 | |
| 164 inline void CopySample(float* dest, int32_t* source) { | |
| 165 *dest = static_cast<float>(*source) / 0x800000; | |
| 166 } | |
| 167 | |
| 168 template<typename TIn, typename TOut> | |
| 169 inline void MixSample(TOut* dest, TIn* source) { | |
| 170 *dest += static_cast<TOut>(*source); | |
| 171 } | |
| 172 | |
| 173 inline void MixSample(uint8_t* dest, int16_t* source) { | |
| 174 *dest += static_cast<uint8_t>((*source >> 8) ^ 0x80); | |
| 175 } | |
| 176 | |
| 177 inline void MixSample(uint8_t* dest, int32_t* source) { | |
| 178 *dest += static_cast<uint8_t>((*source >> 16) ^ 0x80); | |
| 179 } | |
| 180 | |
| 181 inline void MixSample(uint8_t* dest, float* source) { | |
| 182 *dest += static_cast<uint8_t>((*source * 0x7f) + 128); | |
| 183 } | |
| 184 | |
| 185 inline void MixSample(int16_t* dest, uint8_t* source) { | |
| 186 *dest += static_cast<int16_t>(*source ^ 0x80) << 8; | |
| 187 } | |
| 188 | |
| 189 inline void MixSample(int16_t* dest, int32_t* source) { | |
| 190 *dest += static_cast<int16_t>(*source >> 8); | |
| 191 } | |
| 192 | |
| 193 inline void MixSample(int16_t* dest, float* source) { | |
| 194 *dest += static_cast<int16_t>(*source * 0x7fff); | |
| 195 } | |
| 196 | |
| 197 inline void MixSample(int32_t* dest, uint8_t* source) { | |
| 198 *dest += static_cast<int32_t>(*source ^ 0x80) << 16; | |
| 199 } | |
| 200 | |
| 201 inline void MixSample(int32_t* dest, int16_t* source) { | |
| 202 *dest += static_cast<int32_t>(*source << 8); | |
| 203 } | |
| 204 | |
| 205 inline void MixSample(int32_t* dest, float* source) { | |
| 206 *dest += static_cast<int32_t>(*source * 0x7fffff); | |
| 207 } | |
| 208 | |
| 209 inline void MixSample(float* dest, uint8_t* source) { | |
| 210 *dest += static_cast<float>(*source ^ 0x80) / 0x80; | |
| 211 } | |
| 212 | |
| 213 inline void MixSample(float* dest, int16_t* source) { | |
| 214 *dest += static_cast<float>(*source) / 0x8000; | |
| 215 } | |
| 216 | |
| 217 inline void MixSample(float* dest, int32_t* source) { | |
| 218 *dest += static_cast<float>(*source) / 0x800000; | |
| 219 } | |
| 220 | |
| 221 } // namespace | |
| 222 | |
| 223 template<typename TIn, typename TOut> | |
| 224 const LpcmStreamType& LpcmReformatterImpl<TIn, TOut>::input_stream_type() | |
| 225 const { | |
| 226 return in_type_; | |
| 227 } | |
| 228 | |
| 229 template<typename TIn, typename TOut> | |
| 230 const LpcmStreamType& LpcmReformatterImpl<TIn, TOut>::output_stream_type() | |
| 231 const { | |
| 232 return out_type_; | |
| 233 } | |
| 234 | |
| 235 template<typename TIn, typename TOut> | |
| 236 void LpcmReformatterImpl<TIn, TOut>::TransformFrames( | |
| 237 LpcmFrames* source, | |
| 238 LpcmFrames* dest, | |
| 239 bool mix) { | |
| 240 DCHECK(source); | |
| 241 DCHECK(dest); | |
| 242 DCHECK(source->buffer()); | |
| 243 DCHECK(source->frame_count()); | |
| 244 DCHECK(dest->buffer()); | |
| 245 DCHECK(dest->frame_count()); | |
| 246 | |
| 247 uint64_t frame_count = std::min(source->frame_count(), dest->frame_count()); | |
| 248 | |
| 249 uint8_t* in_channel = reinterpret_cast<uint8_t*>(source->buffer()); | |
| 250 uint8_t* out_channel = reinterpret_cast<uint8_t*>(dest->buffer()); | |
|
johngro
2016/01/26 23:47:29
FWIW - when casing a pointer to a PoD to another p
| |
| 251 | |
| 252 for (uint32_t channel = 0; channel < in_type_.channels(); channel++) { | |
| 253 TIn* in_sample = reinterpret_cast<TIn*>(in_channel); | |
| 254 TOut* out_sample = reinterpret_cast<TOut*>(out_channel); | |
| 255 if (mix) { | |
|
johngro
2016/01/26 23:47:29
if you are going to put the mix decision in here,
dalesat
2016/01/28 18:49:16
The outer loop is per-channel. The test will happe
johngro
2016/02/01 22:38:16
Acknowledged.
| |
| 256 for (uint64_t sample = 0; sample < frame_count; sample++) { | |
| 257 MixSample(out_sample, in_sample); | |
| 258 in_sample += in_type_.channels(); | |
| 259 out_sample += out_type_.channels(); | |
| 260 } | |
| 261 } else { | |
| 262 for (uint64_t sample = 0; sample < frame_count; sample++) { | |
| 263 CopySample(out_sample, in_sample); | |
| 264 in_sample += in_type_.channels(); | |
| 265 out_sample += out_type_.channels(); | |
| 266 } | |
| 267 } | |
| 268 in_channel += in_type_.sample_size(); | |
| 269 out_channel += out_type_.sample_size(); | |
| 270 } | |
| 271 | |
| 272 source->advance(frame_count); | |
| 273 dest->advance(frame_count); | |
| 274 } | |
| 275 | |
| 276 } // namespace media | |
| 277 } // namespace mojo | |
| OLD | NEW |