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 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 | 253 |
254 if (extra_data->num_streams + extra_data->num_coupled != extra_data->channels) | 254 if (extra_data->num_streams + extra_data->num_coupled != extra_data->channels) |
255 DVLOG(1) << "Inconsistent channel mapping."; | 255 DVLOG(1) << "Inconsistent channel mapping."; |
256 | 256 |
257 for (int i = 0; i < extra_data->channels; ++i) | 257 for (int i = 0; i < extra_data->channels; ++i) |
258 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); | 258 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); |
259 return true; | 259 return true; |
260 } | 260 } |
261 | 261 |
262 OpusAudioDecoder::OpusAudioDecoder( | 262 OpusAudioDecoder::OpusAudioDecoder( |
263 const scoped_refptr<base::MessageLoopProxy>& message_loop) | 263 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
264 : message_loop_(message_loop), | 264 : task_runner_(task_runner), |
265 weak_factory_(this), | 265 weak_factory_(this), |
266 demuxer_stream_(NULL), | 266 demuxer_stream_(NULL), |
267 opus_decoder_(NULL), | 267 opus_decoder_(NULL), |
268 bits_per_channel_(0), | 268 bits_per_channel_(0), |
269 channel_layout_(CHANNEL_LAYOUT_NONE), | 269 channel_layout_(CHANNEL_LAYOUT_NONE), |
270 samples_per_second_(0), | 270 samples_per_second_(0), |
271 last_input_timestamp_(kNoTimestamp()), | 271 last_input_timestamp_(kNoTimestamp()), |
272 frames_to_discard_(0), | 272 frames_to_discard_(0), |
273 frame_delay_at_start_(0) { | 273 frame_delay_at_start_(0) { |
274 } | 274 } |
275 | 275 |
276 void OpusAudioDecoder::Initialize( | 276 void OpusAudioDecoder::Initialize( |
277 DemuxerStream* stream, | 277 DemuxerStream* stream, |
278 const PipelineStatusCB& status_cb, | 278 const PipelineStatusCB& status_cb, |
279 const StatisticsCB& statistics_cb) { | 279 const StatisticsCB& statistics_cb) { |
280 DCHECK(message_loop_->BelongsToCurrentThread()); | 280 DCHECK(task_runner_->BelongsToCurrentThread()); |
281 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); | 281 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
282 | 282 |
283 if (demuxer_stream_) { | 283 if (demuxer_stream_) { |
284 // TODO(scherkus): initialization currently happens more than once in | 284 // TODO(scherkus): initialization currently happens more than once in |
285 // PipelineIntegrationTest.BasicPlayback. | 285 // PipelineIntegrationTest.BasicPlayback. |
286 DVLOG(0) << "Initialize has already been called."; | 286 DVLOG(0) << "Initialize has already been called."; |
287 CHECK(false); | 287 CHECK(false); |
288 } | 288 } |
289 | 289 |
290 weak_this_ = weak_factory_.GetWeakPtr(); | 290 weak_this_ = weak_factory_.GetWeakPtr(); |
291 demuxer_stream_ = stream; | 291 demuxer_stream_ = stream; |
292 | 292 |
293 if (!ConfigureDecoder()) { | 293 if (!ConfigureDecoder()) { |
294 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 294 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
295 return; | 295 return; |
296 } | 296 } |
297 | 297 |
298 statistics_cb_ = statistics_cb; | 298 statistics_cb_ = statistics_cb; |
299 initialize_cb.Run(PIPELINE_OK); | 299 initialize_cb.Run(PIPELINE_OK); |
300 } | 300 } |
301 | 301 |
302 void OpusAudioDecoder::Read(const ReadCB& read_cb) { | 302 void OpusAudioDecoder::Read(const ReadCB& read_cb) { |
303 DCHECK(message_loop_->BelongsToCurrentThread()); | 303 DCHECK(task_runner_->BelongsToCurrentThread()); |
304 DCHECK(!read_cb.is_null()); | 304 DCHECK(!read_cb.is_null()); |
305 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 305 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
306 read_cb_ = BindToCurrentLoop(read_cb); | 306 read_cb_ = BindToCurrentLoop(read_cb); |
307 | 307 |
308 ReadFromDemuxerStream(); | 308 ReadFromDemuxerStream(); |
309 } | 309 } |
310 | 310 |
311 int OpusAudioDecoder::bits_per_channel() { | 311 int OpusAudioDecoder::bits_per_channel() { |
312 DCHECK(message_loop_->BelongsToCurrentThread()); | 312 DCHECK(task_runner_->BelongsToCurrentThread()); |
313 return bits_per_channel_; | 313 return bits_per_channel_; |
314 } | 314 } |
315 | 315 |
316 ChannelLayout OpusAudioDecoder::channel_layout() { | 316 ChannelLayout OpusAudioDecoder::channel_layout() { |
317 DCHECK(message_loop_->BelongsToCurrentThread()); | 317 DCHECK(task_runner_->BelongsToCurrentThread()); |
318 return channel_layout_; | 318 return channel_layout_; |
319 } | 319 } |
320 | 320 |
321 int OpusAudioDecoder::samples_per_second() { | 321 int OpusAudioDecoder::samples_per_second() { |
322 DCHECK(message_loop_->BelongsToCurrentThread()); | 322 DCHECK(task_runner_->BelongsToCurrentThread()); |
323 return samples_per_second_; | 323 return samples_per_second_; |
324 } | 324 } |
325 | 325 |
326 void OpusAudioDecoder::Reset(const base::Closure& closure) { | 326 void OpusAudioDecoder::Reset(const base::Closure& closure) { |
327 DCHECK(message_loop_->BelongsToCurrentThread()); | 327 DCHECK(task_runner_->BelongsToCurrentThread()); |
328 base::Closure reset_cb = BindToCurrentLoop(closure); | 328 base::Closure reset_cb = BindToCurrentLoop(closure); |
329 | 329 |
330 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | 330 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
331 ResetTimestampState(); | 331 ResetTimestampState(); |
332 reset_cb.Run(); | 332 reset_cb.Run(); |
333 } | 333 } |
334 | 334 |
335 OpusAudioDecoder::~OpusAudioDecoder() { | 335 OpusAudioDecoder::~OpusAudioDecoder() { |
336 // TODO(scherkus): should we require Stop() to be called? this might end up | 336 // TODO(scherkus): should we require Stop() to be called? this might end up |
337 // getting called on a random thread due to refcounting. | 337 // getting called on a random thread due to refcounting. |
338 CloseDecoder(); | 338 CloseDecoder(); |
339 } | 339 } |
340 | 340 |
341 void OpusAudioDecoder::ReadFromDemuxerStream() { | 341 void OpusAudioDecoder::ReadFromDemuxerStream() { |
342 DCHECK(!read_cb_.is_null()); | 342 DCHECK(!read_cb_.is_null()); |
343 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); | 343 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); |
344 } | 344 } |
345 | 345 |
346 void OpusAudioDecoder::BufferReady( | 346 void OpusAudioDecoder::BufferReady( |
347 DemuxerStream::Status status, | 347 DemuxerStream::Status status, |
348 const scoped_refptr<DecoderBuffer>& input) { | 348 const scoped_refptr<DecoderBuffer>& input) { |
349 DCHECK(message_loop_->BelongsToCurrentThread()); | 349 DCHECK(task_runner_->BelongsToCurrentThread()); |
350 DCHECK(!read_cb_.is_null()); | 350 DCHECK(!read_cb_.is_null()); |
351 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; | 351 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; |
352 | 352 |
353 if (status == DemuxerStream::kAborted) { | 353 if (status == DemuxerStream::kAborted) { |
354 DCHECK(!input.get()); | 354 DCHECK(!input.get()); |
355 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 355 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
356 return; | 356 return; |
357 } | 357 } |
358 | 358 |
359 if (status == DemuxerStream::kConfigChanged) { | 359 if (status == DemuxerStream::kConfigChanged) { |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 PipelineStatistics statistics; | 612 PipelineStatistics statistics; |
613 statistics.audio_bytes_decoded = | 613 statistics.audio_bytes_decoded = |
614 frames_decoded * | 614 frames_decoded * |
615 demuxer_stream_->audio_decoder_config().bytes_per_frame(); | 615 demuxer_stream_->audio_decoder_config().bytes_per_frame(); |
616 statistics_cb_.Run(statistics); | 616 statistics_cb_.Run(statistics); |
617 | 617 |
618 return true; | 618 return true; |
619 } | 619 } |
620 | 620 |
621 } // namespace media | 621 } // namespace media |
OLD | NEW |