OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/filters/opus_audio_decoder.h" | 5 #include "media/filters/opus_audio_decoder.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/message_loop/message_loop_proxy.h" | 12 #include "base/single_thread_task_runner.h" |
13 #include "base/sys_byteorder.h" | 13 #include "base/sys_byteorder.h" |
14 #include "media/base/audio_buffer.h" | 14 #include "media/base/audio_buffer.h" |
15 #include "media/base/audio_decoder_config.h" | 15 #include "media/base/audio_decoder_config.h" |
16 #include "media/base/audio_timestamp_helper.h" | 16 #include "media/base/audio_timestamp_helper.h" |
17 #include "media/base/bind_to_loop.h" | 17 #include "media/base/bind_to_loop.h" |
18 #include "media/base/buffers.h" | 18 #include "media/base/buffers.h" |
19 #include "media/base/decoder_buffer.h" | 19 #include "media/base/decoder_buffer.h" |
20 #include "media/base/demuxer.h" | 20 #include "media/base/demuxer.h" |
21 #include "media/base/pipeline.h" | 21 #include "media/base/pipeline.h" |
22 #include "third_party/opus/src/include/opus.h" | 22 #include "third_party/opus/src/include/opus.h" |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 | 246 |
247 if (extra_data->num_streams + extra_data->num_coupled != extra_data->channels) | 247 if (extra_data->num_streams + extra_data->num_coupled != extra_data->channels) |
248 DVLOG(1) << "Inconsistent channel mapping."; | 248 DVLOG(1) << "Inconsistent channel mapping."; |
249 | 249 |
250 for (int i = 0; i < extra_data->channels; ++i) | 250 for (int i = 0; i < extra_data->channels; ++i) |
251 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); | 251 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); |
252 return true; | 252 return true; |
253 } | 253 } |
254 | 254 |
255 OpusAudioDecoder::OpusAudioDecoder( | 255 OpusAudioDecoder::OpusAudioDecoder( |
256 const scoped_refptr<base::MessageLoopProxy>& message_loop) | 256 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
257 : message_loop_(message_loop), | 257 : task_runner_(task_runner), |
258 weak_factory_(this), | 258 weak_factory_(this), |
259 demuxer_stream_(NULL), | 259 demuxer_stream_(NULL), |
260 opus_decoder_(NULL), | 260 opus_decoder_(NULL), |
261 channel_layout_(CHANNEL_LAYOUT_NONE), | 261 channel_layout_(CHANNEL_LAYOUT_NONE), |
262 samples_per_second_(0), | 262 samples_per_second_(0), |
263 sample_format_(kSampleFormatF32), | 263 sample_format_(kSampleFormatF32), |
264 bits_per_channel_(SampleFormatToBytesPerChannel(sample_format_) * 8), | 264 bits_per_channel_(SampleFormatToBytesPerChannel(sample_format_) * 8), |
265 last_input_timestamp_(kNoTimestamp()), | 265 last_input_timestamp_(kNoTimestamp()), |
266 frames_to_discard_(0), | 266 frames_to_discard_(0), |
267 frame_delay_at_start_(0), | 267 frame_delay_at_start_(0), |
268 start_input_timestamp_(kNoTimestamp()) { | 268 start_input_timestamp_(kNoTimestamp()) { |
269 } | 269 } |
270 | 270 |
271 void OpusAudioDecoder::Initialize( | 271 void OpusAudioDecoder::Initialize( |
272 DemuxerStream* stream, | 272 DemuxerStream* stream, |
273 const PipelineStatusCB& status_cb, | 273 const PipelineStatusCB& status_cb, |
274 const StatisticsCB& statistics_cb) { | 274 const StatisticsCB& statistics_cb) { |
275 DCHECK(message_loop_->BelongsToCurrentThread()); | 275 DCHECK(task_runner_->BelongsToCurrentThread()); |
276 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); | 276 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
277 | 277 |
278 if (demuxer_stream_) { | 278 if (demuxer_stream_) { |
279 // TODO(scherkus): initialization currently happens more than once in | 279 // TODO(scherkus): initialization currently happens more than once in |
280 // PipelineIntegrationTest.BasicPlayback. | 280 // PipelineIntegrationTest.BasicPlayback. |
281 DLOG(ERROR) << "Initialize has already been called."; | 281 DLOG(ERROR) << "Initialize has already been called."; |
282 CHECK(false); | 282 CHECK(false); |
283 } | 283 } |
284 | 284 |
285 weak_this_ = weak_factory_.GetWeakPtr(); | 285 weak_this_ = weak_factory_.GetWeakPtr(); |
286 demuxer_stream_ = stream; | 286 demuxer_stream_ = stream; |
287 | 287 |
288 if (!ConfigureDecoder()) { | 288 if (!ConfigureDecoder()) { |
289 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 289 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
290 return; | 290 return; |
291 } | 291 } |
292 | 292 |
293 statistics_cb_ = statistics_cb; | 293 statistics_cb_ = statistics_cb; |
294 initialize_cb.Run(PIPELINE_OK); | 294 initialize_cb.Run(PIPELINE_OK); |
295 } | 295 } |
296 | 296 |
297 void OpusAudioDecoder::Read(const ReadCB& read_cb) { | 297 void OpusAudioDecoder::Read(const ReadCB& read_cb) { |
298 DCHECK(message_loop_->BelongsToCurrentThread()); | 298 DCHECK(task_runner_->BelongsToCurrentThread()); |
299 DCHECK(!read_cb.is_null()); | 299 DCHECK(!read_cb.is_null()); |
300 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 300 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
301 read_cb_ = BindToCurrentLoop(read_cb); | 301 read_cb_ = BindToCurrentLoop(read_cb); |
302 | 302 |
303 ReadFromDemuxerStream(); | 303 ReadFromDemuxerStream(); |
304 } | 304 } |
305 | 305 |
306 int OpusAudioDecoder::bits_per_channel() { | 306 int OpusAudioDecoder::bits_per_channel() { |
307 DCHECK(message_loop_->BelongsToCurrentThread()); | 307 DCHECK(task_runner_->BelongsToCurrentThread()); |
308 return bits_per_channel_; | 308 return bits_per_channel_; |
309 } | 309 } |
310 | 310 |
311 ChannelLayout OpusAudioDecoder::channel_layout() { | 311 ChannelLayout OpusAudioDecoder::channel_layout() { |
312 DCHECK(message_loop_->BelongsToCurrentThread()); | 312 DCHECK(task_runner_->BelongsToCurrentThread()); |
313 return channel_layout_; | 313 return channel_layout_; |
314 } | 314 } |
315 | 315 |
316 int OpusAudioDecoder::samples_per_second() { | 316 int OpusAudioDecoder::samples_per_second() { |
317 DCHECK(message_loop_->BelongsToCurrentThread()); | 317 DCHECK(task_runner_->BelongsToCurrentThread()); |
318 return samples_per_second_; | 318 return samples_per_second_; |
319 } | 319 } |
320 | 320 |
321 void OpusAudioDecoder::Reset(const base::Closure& closure) { | 321 void OpusAudioDecoder::Reset(const base::Closure& closure) { |
322 DCHECK(message_loop_->BelongsToCurrentThread()); | 322 DCHECK(task_runner_->BelongsToCurrentThread()); |
323 base::Closure reset_cb = BindToCurrentLoop(closure); | 323 base::Closure reset_cb = BindToCurrentLoop(closure); |
324 | 324 |
325 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | 325 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
326 ResetTimestampState(); | 326 ResetTimestampState(); |
327 reset_cb.Run(); | 327 reset_cb.Run(); |
328 } | 328 } |
329 | 329 |
330 OpusAudioDecoder::~OpusAudioDecoder() { | 330 OpusAudioDecoder::~OpusAudioDecoder() { |
331 // TODO(scherkus): should we require Stop() to be called? this might end up | 331 // TODO(scherkus): should we require Stop() to be called? this might end up |
332 // getting called on a random thread due to refcounting. | 332 // getting called on a random thread due to refcounting. |
333 CloseDecoder(); | 333 CloseDecoder(); |
334 } | 334 } |
335 | 335 |
336 void OpusAudioDecoder::ReadFromDemuxerStream() { | 336 void OpusAudioDecoder::ReadFromDemuxerStream() { |
337 DCHECK(!read_cb_.is_null()); | 337 DCHECK(!read_cb_.is_null()); |
338 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); | 338 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); |
339 } | 339 } |
340 | 340 |
341 void OpusAudioDecoder::BufferReady( | 341 void OpusAudioDecoder::BufferReady( |
342 DemuxerStream::Status status, | 342 DemuxerStream::Status status, |
343 const scoped_refptr<DecoderBuffer>& input) { | 343 const scoped_refptr<DecoderBuffer>& input) { |
344 DCHECK(message_loop_->BelongsToCurrentThread()); | 344 DCHECK(task_runner_->BelongsToCurrentThread()); |
345 DCHECK(!read_cb_.is_null()); | 345 DCHECK(!read_cb_.is_null()); |
346 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; | 346 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; |
347 | 347 |
348 if (status == DemuxerStream::kAborted) { | 348 if (status == DemuxerStream::kAborted) { |
349 DCHECK(!input.get()); | 349 DCHECK(!input.get()); |
350 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 350 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
351 return; | 351 return; |
352 } | 352 } |
353 | 353 |
354 if (status == DemuxerStream::kConfigChanged) { | 354 if (status == DemuxerStream::kConfigChanged) { |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 output_timestamp_helper_->AddFrames(frames_decoded); | 619 output_timestamp_helper_->AddFrames(frames_decoded); |
620 | 620 |
621 // Discard the buffer to indicate we need more data. | 621 // Discard the buffer to indicate we need more data. |
622 if (!frames_to_output) | 622 if (!frames_to_output) |
623 *output_buffer = NULL; | 623 *output_buffer = NULL; |
624 | 624 |
625 return true; | 625 return true; |
626 } | 626 } |
627 | 627 |
628 } // namespace media | 628 } // namespace media |
OLD | NEW |