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 |