| 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 |