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 "services/media/framework/conversion_pipeline_builder.h" | 5 #include "services/media/framework/conversion_pipeline_builder.h" |
6 #include "services/media/framework/formatting.h" | 6 #include "services/media/framework/formatting.h" |
7 #include "services/media/framework/parts/decoder.h" | 7 #include "services/media/framework/parts/decoder.h" |
8 #include "services/media/framework/parts/lpcm_reformatter.h" | 8 #include "services/media/framework/parts/lpcm_reformatter.h" |
9 | 9 |
10 namespace mojo { | 10 namespace mojo { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 } else { | 68 } else { |
69 return 0; // TODO(dalesat): Remove when we have resamplers. | 69 return 0; // TODO(dalesat): Remove when we have resamplers. |
70 } | 70 } |
71 | 71 |
72 return score; | 72 return score; |
73 } | 73 } |
74 | 74 |
75 // Finds the media type set that best matches in_type. | 75 // Finds the media type set that best matches in_type. |
76 const std::unique_ptr<StreamTypeSet>* FindBestLpcm( | 76 const std::unique_ptr<StreamTypeSet>* FindBestLpcm( |
77 const LpcmStreamType& in_type, | 77 const LpcmStreamType& in_type, |
78 const std::unique_ptr<std::vector<std::unique_ptr<StreamTypeSet>>>& | 78 const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets) { |
79 out_type_sets) { | |
80 const std::unique_ptr<StreamTypeSet>* best = nullptr; | 79 const std::unique_ptr<StreamTypeSet>* best = nullptr; |
81 int best_score = 0; | 80 int best_score = 0; |
82 for (const std::unique_ptr<StreamTypeSet>& out_type_set : *out_type_sets) { | 81 for (const std::unique_ptr<StreamTypeSet>& out_type_set : out_type_sets) { |
83 switch (out_type_set->scheme()) { | 82 switch (out_type_set->scheme()) { |
84 case StreamType::Scheme::kAnyElementary: | 83 case StreamType::Scheme::kAnyElementary: |
85 case StreamType::Scheme::kAnyAudio: | 84 case StreamType::Scheme::kAnyAudio: |
86 case StreamType::Scheme::kAny: | 85 case StreamType::Scheme::kAny: |
87 // Wildcard scheme allows any type without conversion. | 86 // Wildcard scheme allows any type without conversion. |
88 return &out_type_set; | 87 return &out_type_set; |
89 case StreamType::Scheme::kLpcm: { | 88 case StreamType::Scheme::kLpcm: { |
90 int score = Score(in_type, *out_type_set->lpcm()); | 89 int score = Score(in_type, *out_type_set->lpcm()); |
91 if (best_score < score) { | 90 if (best_score < score) { |
92 best_score = score; | 91 best_score = score; |
93 best = &out_type_set; | 92 best = &out_type_set; |
94 } | 93 } |
95 break; | 94 break; |
96 } | 95 } |
97 default: | 96 default: |
98 break; | 97 break; |
99 } | 98 } |
100 } | 99 } |
101 return best; | 100 return best; |
102 } | 101 } |
103 | 102 |
104 // Attempts to add transforms to the pipeline given an input compressed audio | 103 // Attempts to add transforms to the pipeline given an input compressed audio |
105 // stream type with (in_type) and the set of output types we need to convert to | 104 // stream type with (in_type) and the set of output types we need to convert to |
106 // (out_type_sets). If the call succeeds, *out_type is set to the new output | 105 // (out_type_sets). If the call succeeds, *out_type is set to the new output |
107 // type. Otherwise, *out_type is set to nullptr. | 106 // type. Otherwise, *out_type is set to nullptr. |
108 AddResult AddTransformsForCompressedAudio( | 107 AddResult AddTransformsForCompressedAudio( |
109 const CompressedAudioStreamType& in_type, | 108 const CompressedAudioStreamType& in_type, |
110 const std::unique_ptr<StreamType>& in_type_ptr, | 109 const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets, |
111 const std::unique_ptr<std::vector<std::unique_ptr<StreamTypeSet>>>& | |
112 out_type_sets, | |
113 Graph* graph, | 110 Graph* graph, |
114 OutputRef* output, | 111 OutputRef* output, |
115 std::unique_ptr<StreamType>* out_type) { | 112 std::unique_ptr<StreamType>* out_type) { |
116 DCHECK(out_type); | 113 DCHECK(out_type); |
117 DCHECK(graph); | 114 DCHECK(graph); |
118 | 115 |
119 // See if we have a matching COMPRESSED_AUDIO type. | 116 // See if we have a matching COMPRESSED_AUDIO type. |
120 for (const std::unique_ptr<StreamTypeSet>& out_type_set : *out_type_sets) { | 117 for (const std::unique_ptr<StreamTypeSet>& out_type_set : out_type_sets) { |
121 switch (out_type_set->scheme()) { | 118 switch (out_type_set->scheme()) { |
122 case StreamType::Scheme::kAnyElementary: | 119 case StreamType::Scheme::kAnyElementary: |
123 case StreamType::Scheme::kAnyAudio: | 120 case StreamType::Scheme::kAnyAudio: |
124 case StreamType::Scheme::kAny: | 121 case StreamType::Scheme::kAny: |
125 // Wildcard scheme allows any type without conversion. | 122 // Wildcard scheme allows any type without conversion. |
126 *out_type = in_type.Clone(); | 123 *out_type = in_type.Clone(); |
127 return AddResult::kFinished; | 124 return AddResult::kFinished; |
128 case StreamType::Scheme::kCompressedAudio: { | 125 case StreamType::Scheme::kCompressedAudio: { |
129 if (out_type_set->compressed_audio()->contains(in_type)) { | 126 if (out_type_set->compressed_audio()->contains(in_type)) { |
130 // No transform needed. | 127 // No transform needed. |
(...skipping 14 matching lines...) Expand all Loading... |
145 if (best == nullptr) { | 142 if (best == nullptr) { |
146 // No candidates found. | 143 // No candidates found. |
147 *out_type = nullptr; | 144 *out_type = nullptr; |
148 return AddResult::kFailed; | 145 return AddResult::kFailed; |
149 } | 146 } |
150 | 147 |
151 DCHECK_EQ((*best)->scheme(), StreamType::Scheme::kLpcm); | 148 DCHECK_EQ((*best)->scheme(), StreamType::Scheme::kLpcm); |
152 | 149 |
153 // Need to decode. Create a decoder and go from there. | 150 // Need to decode. Create a decoder and go from there. |
154 std::shared_ptr<Decoder> decoder; | 151 std::shared_ptr<Decoder> decoder; |
155 Result result = Decoder::Create(in_type_ptr, &decoder); | 152 Result result = Decoder::Create(in_type, &decoder); |
156 if (result != Result::kOk) { | 153 if (result != Result::kOk) { |
157 // No decoder found. | 154 // No decoder found. |
158 *out_type = nullptr; | 155 *out_type = nullptr; |
159 return AddResult::kFailed; | 156 return AddResult::kFailed; |
160 } | 157 } |
161 | 158 |
162 *output = graph->ConnectOutputToPart(*output, graph->Add(decoder)).output(); | 159 *output = graph->ConnectOutputToPart(*output, graph->Add(decoder)).output(); |
163 *out_type = decoder->output_stream_type(); | 160 *out_type = decoder->output_stream_type(); |
164 | 161 |
165 return AddResult::kProgressed; | 162 return AddResult::kProgressed; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 | 209 |
213 return AddResult::kFinished; | 210 return AddResult::kFinished; |
214 } | 211 } |
215 | 212 |
216 // Attempts to add transforms to the pipeline given an input media type with | 213 // Attempts to add transforms to the pipeline given an input media type with |
217 // scheme LPCM (in_type) and the set of output types we need to convert to | 214 // scheme LPCM (in_type) and the set of output types we need to convert to |
218 // (out_type_sets). If the call succeeds, *out_type is set to the new output | 215 // (out_type_sets). If the call succeeds, *out_type is set to the new output |
219 // type. Otherwise, *out_type is set to nullptr. | 216 // type. Otherwise, *out_type is set to nullptr. |
220 AddResult AddTransformsForLpcm( | 217 AddResult AddTransformsForLpcm( |
221 const LpcmStreamType& in_type, | 218 const LpcmStreamType& in_type, |
222 const std::unique_ptr<std::vector<std::unique_ptr<StreamTypeSet>>>& | 219 const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets, |
223 out_type_sets, | |
224 Graph* graph, | 220 Graph* graph, |
225 OutputRef* output, | 221 OutputRef* output, |
226 std::unique_ptr<StreamType>* out_type) { | 222 std::unique_ptr<StreamType>* out_type) { |
227 DCHECK(graph); | 223 DCHECK(graph); |
228 DCHECK(out_type); | 224 DCHECK(out_type); |
229 | 225 |
230 const std::unique_ptr<StreamTypeSet>* best = | 226 const std::unique_ptr<StreamTypeSet>* best = |
231 FindBestLpcm(in_type, out_type_sets); | 227 FindBestLpcm(in_type, out_type_sets); |
232 if (best == nullptr) { | 228 if (best == nullptr) { |
233 // TODO(dalesat): Support a compressed output type by encoding. | 229 // TODO(dalesat): Support a compressed output type by encoding. |
(...skipping 21 matching lines...) Expand all Loading... |
255 << (*best)->scheme(); | 251 << (*best)->scheme(); |
256 return AddResult::kFailed; | 252 return AddResult::kFailed; |
257 } | 253 } |
258 } | 254 } |
259 | 255 |
260 // Attempts to add transforms to the pipeline given an input media type of any | 256 // Attempts to add transforms to the pipeline given an input media type of any |
261 // scheme (in_type) and the set of output types we need to convert to | 257 // scheme (in_type) and the set of output types we need to convert to |
262 // (out_type_sets). If the call succeeds, *out_type is set to the new output | 258 // (out_type_sets). If the call succeeds, *out_type is set to the new output |
263 // type. Otherwise, *out_type is set to nullptr. | 259 // type. Otherwise, *out_type is set to nullptr. |
264 AddResult AddTransforms( | 260 AddResult AddTransforms( |
265 const std::unique_ptr<StreamType>& in_type, | 261 const StreamType& in_type, |
266 const std::unique_ptr<std::vector<std::unique_ptr<StreamTypeSet>>>& | 262 const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets, |
267 out_type_sets, | |
268 Graph* graph, | 263 Graph* graph, |
269 OutputRef* output, | 264 OutputRef* output, |
270 std::unique_ptr<StreamType>* out_type) { | 265 std::unique_ptr<StreamType>* out_type) { |
271 DCHECK(in_type); | |
272 DCHECK(graph); | 266 DCHECK(graph); |
273 DCHECK(out_type); | 267 DCHECK(out_type); |
274 | 268 |
275 switch (in_type->scheme()) { | 269 switch (in_type.scheme()) { |
276 case StreamType::Scheme::kLpcm: | 270 case StreamType::Scheme::kLpcm: |
277 return AddTransformsForLpcm( | 271 return AddTransformsForLpcm( |
278 *in_type->lpcm(), | 272 *in_type.lpcm(), |
279 out_type_sets, | 273 out_type_sets, |
280 graph, | 274 graph, |
281 output, | 275 output, |
282 out_type); | 276 out_type); |
283 case StreamType::Scheme::kCompressedAudio: | 277 case StreamType::Scheme::kCompressedAudio: |
284 return AddTransformsForCompressedAudio( | 278 return AddTransformsForCompressedAudio( |
285 *in_type->compressed_audio(), | 279 *in_type.compressed_audio(), |
286 in_type, | |
287 out_type_sets, | 280 out_type_sets, |
288 graph, | 281 graph, |
289 output, | 282 output, |
290 out_type); | 283 out_type); |
291 default: | 284 default: |
292 NOTREACHED() << "conversion not supported for scheme" | 285 NOTREACHED() << "conversion not supported for scheme" |
293 << in_type->scheme(); | 286 << in_type.scheme(); |
294 *out_type = nullptr; | 287 *out_type = nullptr; |
295 return AddResult::kFailed; | 288 return AddResult::kFailed; |
296 } | 289 } |
297 } | 290 } |
298 | 291 |
299 } // namespace | 292 } // namespace |
300 | 293 |
301 bool BuildConversionPipeline( | 294 bool BuildConversionPipeline( |
302 const std::unique_ptr<StreamType>& in_type, | 295 const StreamType& in_type, |
303 const std::unique_ptr<std::vector<std::unique_ptr<StreamTypeSet>>>& | 296 const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets, |
304 out_type_sets, | |
305 Graph* graph, | 297 Graph* graph, |
306 OutputRef* output, | 298 OutputRef* output, |
307 std::unique_ptr<StreamType>* out_type) { | 299 std::unique_ptr<StreamType>* out_type) { |
308 DCHECK(in_type); | |
309 DCHECK(out_type_sets); | |
310 DCHECK(graph); | 300 DCHECK(graph); |
311 DCHECK(output); | 301 DCHECK(output); |
312 DCHECK(out_type); | 302 DCHECK(out_type); |
313 | 303 |
314 OutputRef out = *output; | 304 OutputRef out = *output; |
315 | 305 const StreamType* type_to_convert = &in_type; |
316 const std::unique_ptr<StreamType>* type_to_convert = &in_type; | 306 std::unique_ptr<StreamType> converted_type; |
317 std::unique_ptr<StreamType> next_in_type; | |
318 while (true) { | 307 while (true) { |
319 std::unique_ptr<StreamType> converted_type; | |
320 switch (AddTransforms( | 308 switch (AddTransforms( |
321 *type_to_convert, | 309 *type_to_convert, |
322 out_type_sets, | 310 out_type_sets, |
323 graph, | 311 graph, |
324 &out, | 312 &out, |
325 &converted_type)) { | 313 &converted_type)) { |
326 case AddResult::kFailed: | 314 case AddResult::kFailed: |
327 // Failed to find a suitable conversion. Return the pipeline to its | 315 // Failed to find a suitable conversion. Return the pipeline to its |
328 // original state. | 316 // original state. |
329 graph->RemovePartsConnectedToOutput(*output); | 317 graph->RemovePartsConnectedToOutput(*output); |
330 *out_type = nullptr; | 318 *out_type = nullptr; |
331 return false; | 319 return false; |
332 case AddResult::kProgressed: | 320 case AddResult::kProgressed: |
333 // Made progress. Continue. | 321 // Made progress. Continue. |
334 break; | 322 break; |
335 case AddResult::kFinished: | 323 case AddResult::kFinished: |
336 // No further conversion required. | 324 // No further conversion required. |
337 *output = out; | 325 *output = out; |
338 *out_type = std::move(converted_type); | 326 *out_type = std::move(converted_type); |
339 return true; | 327 return true; |
340 } | 328 } |
341 | 329 |
342 next_in_type = std::move(converted_type); | 330 type_to_convert = converted_type.get(); |
343 type_to_convert = &next_in_type; | |
344 } | 331 } |
345 } | 332 } |
346 | 333 |
347 } // namespace media | 334 } // namespace media |
348 } // namespace mojo | 335 } // namespace mojo |
OLD | NEW |