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 implementation that accepts samples of type TIn and | |
12 // produces samples of type TOut. | |
13 template<typename TIn, typename TOut> | |
14 class LpcmReformatterImpl : public LpcmReformatter { | |
15 public: | |
16 LpcmReformatterImpl( | |
17 const LpcmStreamType& in_type, | |
18 const LpcmStreamTypeSet& out_type); | |
19 | |
20 ~LpcmReformatterImpl() override; | |
21 | |
22 // LpcmTransform implementation. | |
23 const LpcmStreamType& input_stream_type() const override; | |
24 | |
25 const LpcmStreamType& output_stream_type() const override; | |
26 | |
27 void TransformFrames(LpcmFrames* source, LpcmFrames* dest, bool mix) override; | |
28 | |
29 private: | |
30 LpcmStreamType in_type_; | |
31 LpcmStreamType out_type_; | |
32 }; | |
33 | |
34 LpcmReformatterPtr LpcmReformatter::New( | |
35 const LpcmStreamType& in_type, | |
36 const LpcmStreamTypeSet& out_type) { | |
37 LpcmReformatter* result = nullptr; | |
38 | |
39 switch (in_type.sample_format()) { | |
40 case LpcmStreamType::SampleFormat::kUnsigned8: | |
41 switch (out_type.sample_format()) { | |
42 case LpcmStreamType::SampleFormat::kUnsigned8: | |
43 case LpcmStreamType::SampleFormat::kAny: | |
44 result = new LpcmReformatterImpl<uint8_t, uint8_t>( | |
jeffbrown
2016/02/02 05:35:48
Do you think these allocations could become a bott
dalesat
2016/02/02 21:46:40
This is done once per LpcmReformatter, which means
| |
45 in_type, out_type); | |
46 break; | |
47 case LpcmStreamType::SampleFormat::kSigned16: | |
48 result = new LpcmReformatterImpl<uint8_t, int16_t>( | |
49 in_type, out_type); | |
50 break; | |
51 case LpcmStreamType::SampleFormat::kSigned24In32: | |
52 result = new LpcmReformatterImpl<uint8_t, int32_t>( | |
53 in_type, out_type); | |
54 break; | |
55 case LpcmStreamType::SampleFormat::kFloat: | |
56 result = new LpcmReformatterImpl<uint8_t, float>( | |
57 in_type, out_type); | |
58 break; | |
59 default: | |
60 NOTREACHED() << "unsupported sample format"; | |
61 result = nullptr; | |
62 break; | |
63 } | |
64 break; | |
65 case LpcmStreamType::SampleFormat::kSigned16: | |
66 switch (out_type.sample_format()) { | |
67 case LpcmStreamType::SampleFormat::kUnsigned8: | |
68 result = new LpcmReformatterImpl<int16_t, uint8_t>( | |
69 in_type, out_type); | |
70 break; | |
71 case LpcmStreamType::SampleFormat::kSigned16: | |
72 case LpcmStreamType::SampleFormat::kAny: | |
73 result = new LpcmReformatterImpl<int16_t, int16_t>( | |
74 in_type, out_type); | |
75 break; | |
76 case LpcmStreamType::SampleFormat::kSigned24In32: | |
77 result = new LpcmReformatterImpl<int16_t, int32_t>( | |
78 in_type, out_type); | |
79 break; | |
80 case LpcmStreamType::SampleFormat::kFloat: | |
81 result = new LpcmReformatterImpl<int16_t, float>( | |
82 in_type, out_type); | |
83 break; | |
84 default: | |
85 NOTREACHED() << "unsupported sample format"; | |
86 result = nullptr; | |
87 break; | |
88 } | |
89 break; | |
90 case LpcmStreamType::SampleFormat::kSigned24In32: | |
91 switch (out_type.sample_format()) { | |
92 case LpcmStreamType::SampleFormat::kUnsigned8: | |
93 result = new LpcmReformatterImpl<int32_t, uint8_t>( | |
94 in_type, out_type); | |
95 break; | |
96 case LpcmStreamType::SampleFormat::kSigned16: | |
97 result = new LpcmReformatterImpl<int32_t, int16_t>( | |
98 in_type, out_type); | |
99 break; | |
100 case LpcmStreamType::SampleFormat::kSigned24In32: | |
101 case LpcmStreamType::SampleFormat::kAny: | |
102 result = new LpcmReformatterImpl<int32_t, int32_t>( | |
103 in_type, out_type); | |
104 break; | |
105 case LpcmStreamType::SampleFormat::kFloat: | |
106 result = new LpcmReformatterImpl<int32_t, float>( | |
107 in_type, out_type); | |
108 break; | |
109 default: | |
110 NOTREACHED() << "unsupported sample format"; | |
111 result = nullptr; | |
112 break; | |
113 } | |
114 break; | |
115 case LpcmStreamType::SampleFormat::kFloat: | |
116 switch (out_type.sample_format()) { | |
117 case LpcmStreamType::SampleFormat::kUnsigned8: | |
118 result = new LpcmReformatterImpl<float, uint8_t>( | |
119 in_type, out_type); | |
120 break; | |
121 case LpcmStreamType::SampleFormat::kSigned16: | |
122 result = new LpcmReformatterImpl<float, int16_t>( | |
123 in_type, out_type); | |
124 break; | |
125 case LpcmStreamType::SampleFormat::kSigned24In32: | |
126 result = new LpcmReformatterImpl<float, int32_t>( | |
127 in_type, out_type); | |
128 break; | |
129 case LpcmStreamType::SampleFormat::kFloat: | |
130 case LpcmStreamType::SampleFormat::kAny: | |
131 result = new LpcmReformatterImpl<float, float>(in_type, out_type); | |
132 break; | |
133 default: | |
134 NOTREACHED() << "unsupported sample format"; | |
135 result = nullptr; | |
136 break; | |
137 } | |
138 break; | |
139 default: | |
140 NOTREACHED() << "unsupported sample format"; | |
141 result = nullptr; | |
142 break; | |
143 } | |
144 | |
145 return LpcmReformatterPtr(result); | |
146 } | |
147 | |
148 template<typename TIn, typename TOut> | |
149 LpcmReformatterImpl<TIn, TOut>::LpcmReformatterImpl( | |
150 const LpcmStreamType& in_type, | |
151 const LpcmStreamTypeSet& out_type) : | |
152 in_type_(in_type), | |
153 out_type_( | |
154 out_type.sample_format() == LpcmStreamType::SampleFormat::kAny ? | |
155 in_type.sample_format() : | |
156 out_type.sample_format(), | |
157 in_type.channels(), | |
158 in_type.frames_per_second()) {} | |
159 | |
160 template<typename TIn, typename TOut> | |
161 LpcmReformatterImpl<TIn, TOut>::~LpcmReformatterImpl() {} | |
162 | |
163 namespace { | |
164 | |
165 template <typename T> | |
166 inline constexpr T Clamp(T val, T min, T max) { | |
167 return (val > max) ? max : ((val < min) ? min : val); | |
168 } | |
169 | |
170 template <typename T> | |
171 inline constexpr T Clamp(T val); | |
172 | |
173 template <> | |
174 inline constexpr float Clamp(float val) { | |
175 return Clamp(val, -1.0f, 1.0f); | |
176 } | |
177 | |
178 template <> | |
179 inline constexpr int32_t Clamp(int32_t val) { | |
180 return Clamp(val, 1 << 23, -(1 << 23)); | |
181 } | |
182 | |
183 template<typename TIn, typename TOut> | |
184 inline void CopySample(TOut* dest, TIn* source) { | |
185 *dest = static_cast<TOut>(*source); | |
186 } | |
187 | |
188 inline void CopySample(uint8_t* dest, int16_t* source) { | |
189 *dest = static_cast<uint8_t>((*source >> 8) ^ 0x80); | |
190 } | |
191 | |
192 inline void CopySample(uint8_t* dest, int32_t* source) { | |
193 *dest = static_cast<uint8_t>((Clamp(*source) >> 16) ^ 0x80); | |
194 } | |
195 | |
196 inline void CopySample(uint8_t* dest, float* source) { | |
197 *dest = static_cast<uint8_t>((Clamp(*source) * 0x7f) + 128); | |
198 } | |
199 | |
200 inline void CopySample(int16_t* dest, uint8_t* source) { | |
201 *dest = static_cast<int16_t>(*source ^ 0x80) << 8; | |
202 } | |
203 | |
204 inline void CopySample(int16_t* dest, int32_t* source) { | |
205 *dest = static_cast<int16_t>(Clamp(*source) >> 8); | |
206 } | |
207 | |
208 inline void CopySample(int16_t* dest, float* source) { | |
209 *dest = static_cast<int16_t>(Clamp(*source) * 0x7fff); | |
210 } | |
211 | |
212 inline void CopySample(int32_t* dest, uint8_t* source) { | |
213 *dest = static_cast<int32_t>(*source ^ 0x80) << 16; | |
214 } | |
215 | |
216 inline void CopySample(int32_t* dest, int16_t* source) { | |
217 *dest = static_cast<int32_t>(*source << 8); | |
218 } | |
219 | |
220 inline void CopySample(int32_t* dest, float* source) { | |
221 *dest = static_cast<int32_t>(Clamp(*source) * 0x7fffff); | |
222 } | |
223 | |
224 inline void CopySample(float* dest, uint8_t* source) { | |
225 *dest = static_cast<float>(*source ^ 0x80) / 0x80; | |
226 } | |
227 | |
228 inline void CopySample(float* dest, int16_t* source) { | |
229 *dest = static_cast<float>(*source) / 0x8000; | |
230 } | |
231 | |
232 inline void CopySample(float* dest, int32_t* source) { | |
233 *dest = static_cast<float>(Clamp(*source)) / 0x800000; | |
234 } | |
235 | |
236 template<typename TIn, typename TOut> | |
237 inline void MixSample(TOut* dest, TIn* source) { | |
238 *dest += static_cast<TOut>(*source); | |
239 } | |
240 | |
241 inline void MixSample(uint8_t* dest, int16_t* source) { | |
242 *dest += static_cast<uint8_t>((*source >> 8) ^ 0x80); | |
243 } | |
244 | |
245 inline void MixSample(uint8_t* dest, int32_t* source) { | |
246 *dest += static_cast<uint8_t>((Clamp(*source) >> 16) ^ 0x80); | |
247 } | |
248 | |
249 inline void MixSample(uint8_t* dest, float* source) { | |
250 *dest += static_cast<uint8_t>((Clamp(*source) * 0x7f) + 128); | |
251 } | |
252 | |
253 inline void MixSample(int16_t* dest, uint8_t* source) { | |
254 *dest += static_cast<int16_t>(*source ^ 0x80) << 8; | |
255 } | |
256 | |
257 inline void MixSample(int16_t* dest, int32_t* source) { | |
258 *dest += static_cast<int16_t>(Clamp(*source) >> 8); | |
259 } | |
260 | |
261 inline void MixSample(int16_t* dest, float* source) { | |
262 *dest += static_cast<int16_t>(Clamp(*source) * 0x7fff); | |
263 } | |
264 | |
265 inline void MixSample(int32_t* dest, uint8_t* source) { | |
266 *dest += static_cast<int32_t>(*source ^ 0x80) << 16; | |
267 } | |
268 | |
269 inline void MixSample(int32_t* dest, int16_t* source) { | |
270 *dest += static_cast<int32_t>(*source << 8); | |
271 } | |
272 | |
273 inline void MixSample(int32_t* dest, float* source) { | |
274 *dest += static_cast<int32_t>(Clamp(*source) * 0x7fffff); | |
275 } | |
276 | |
277 inline void MixSample(float* dest, uint8_t* source) { | |
278 *dest += static_cast<float>(*source ^ 0x80) / 0x80; | |
279 } | |
280 | |
281 inline void MixSample(float* dest, int16_t* source) { | |
282 *dest += static_cast<float>(*source) / 0x8000; | |
283 } | |
284 | |
285 inline void MixSample(float* dest, int32_t* source) { | |
286 *dest += static_cast<float>(Clamp(*source)) / 0x800000; | |
287 } | |
288 | |
289 } // namespace | |
290 | |
291 template<typename TIn, typename TOut> | |
292 const LpcmStreamType& LpcmReformatterImpl<TIn, TOut>::input_stream_type() | |
293 const { | |
294 return in_type_; | |
295 } | |
296 | |
297 template<typename TIn, typename TOut> | |
298 const LpcmStreamType& LpcmReformatterImpl<TIn, TOut>::output_stream_type() | |
299 const { | |
300 return out_type_; | |
301 } | |
302 | |
303 template<typename TIn, typename TOut> | |
304 void LpcmReformatterImpl<TIn, TOut>::TransformFrames( | |
305 LpcmFrames* source, | |
306 LpcmFrames* dest, | |
307 bool mix) { | |
308 DCHECK(source); | |
309 DCHECK(dest); | |
310 DCHECK(source->buffer()); | |
311 DCHECK(source->frame_count()); | |
312 DCHECK(dest->buffer()); | |
313 DCHECK(dest->frame_count()); | |
314 | |
315 uint64_t frame_count = std::min(source->frame_count(), dest->frame_count()); | |
316 | |
317 uint8_t* in_channel = static_cast<uint8_t*>(source->buffer()); | |
318 uint8_t* out_channel = static_cast<uint8_t*>(dest->buffer()); | |
319 | |
320 for (uint32_t channel = 0; channel < in_type_.channels(); channel++) { | |
321 TIn* in_sample = reinterpret_cast<TIn*>(in_channel); | |
322 TOut* out_sample = reinterpret_cast<TOut*>(out_channel); | |
323 if (mix) { | |
324 for (uint64_t sample = 0; sample < frame_count; sample++) { | |
325 MixSample(out_sample, in_sample); | |
326 in_sample += in_type_.channels(); | |
327 out_sample += out_type_.channels(); | |
328 } | |
329 } else { | |
330 for (uint64_t sample = 0; sample < frame_count; sample++) { | |
331 CopySample(out_sample, in_sample); | |
332 in_sample += in_type_.channels(); | |
333 out_sample += out_type_.channels(); | |
334 } | |
335 } | |
336 in_channel += in_type_.sample_size(); | |
337 out_channel += out_type_.sample_size(); | |
338 } | |
339 | |
340 source->advance(frame_count); | |
341 dest->advance(frame_count); | |
342 } | |
343 | |
344 } // namespace media | |
345 } // namespace mojo | |
OLD | NEW |