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 |