Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: media/filters/android/media_codec_audio_decoder.cc

Issue 2466463005: Support (E)AC3 passthrough
Patch Set: Improve CastMediaClient::IsSupportedPassthroughAudio() Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "media/filters/android/media_codec_audio_decoder.h" 5 #include "media/filters/android/media_codec_audio_decoder.h"
6 6
7 #include <cmath>
8
7 #include "base/android/build_info.h" 9 #include "base/android/build_info.h"
8 #include "base/bind.h" 10 #include "base/bind.h"
9 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
10 #include "base/logging.h" 12 #include "base/logging.h"
11 #include "base/threading/thread_task_runner_handle.h" 13 #include "base/threading/thread_task_runner_handle.h"
12 #include "media/base/android/sdk_media_codec_bridge.h" 14 #include "media/base/android/sdk_media_codec_bridge.h"
13 #include "media/base/audio_buffer.h" 15 #include "media/base/audio_buffer.h"
14 #include "media/base/audio_timestamp_helper.h" 16 #include "media/base/audio_timestamp_helper.h"
15 #include "media/base/bind_to_current_loop.h" 17 #include "media/base/bind_to_current_loop.h"
16 #include "media/base/timestamp_constants.h" 18 #include "media/base/timestamp_constants.h"
17 19
18 namespace media { 20 namespace media {
19 21
20 MediaCodecAudioDecoder::MediaCodecAudioDecoder( 22 MediaCodecAudioDecoder::MediaCodecAudioDecoder(
21 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 23 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
22 : task_runner_(task_runner), 24 : task_runner_(task_runner),
23 state_(STATE_UNINITIALIZED), 25 state_(STATE_UNINITIALIZED),
26 is_passthrough_(false),
24 channel_count_(0), 27 channel_count_(0),
25 channel_layout_(CHANNEL_LAYOUT_NONE), 28 channel_layout_(CHANNEL_LAYOUT_NONE),
26 sample_rate_(0), 29 sample_rate_(0),
27 media_drm_bridge_cdm_context_(nullptr), 30 media_drm_bridge_cdm_context_(nullptr),
28 cdm_registration_id_(0), 31 cdm_registration_id_(0),
29 weak_factory_(this) { 32 weak_factory_(this) {
30 DVLOG(1) << __FUNCTION__; 33 DVLOG(1) << __FUNCTION__;
31 } 34 }
32 35
33 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() { 36 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() {
(...skipping 19 matching lines...) Expand all
53 } 56 }
54 57
55 void MediaCodecAudioDecoder::Initialize(const AudioDecoderConfig& config, 58 void MediaCodecAudioDecoder::Initialize(const AudioDecoderConfig& config,
56 CdmContext* cdm_context, 59 CdmContext* cdm_context,
57 const InitCB& init_cb, 60 const InitCB& init_cb,
58 const OutputCB& output_cb) { 61 const OutputCB& output_cb) {
59 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); 62 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString();
60 DCHECK_EQ(state_, STATE_UNINITIALIZED); 63 DCHECK_EQ(state_, STATE_UNINITIALIZED);
61 64
62 InitCB bound_init_cb = BindToCurrentLoop(init_cb); 65 InitCB bound_init_cb = BindToCurrentLoop(init_cb);
66 is_passthrough_ = (config.codec() == kCodecRaw);
63 67
64 // We can support only the codecs that AudioCodecBridge can decode. 68 // We can support only the codecs that AudioCodecBridge can decode.
65 const bool is_codec_supported = config.codec() == kCodecVorbis || 69 const bool is_codec_supported =
66 config.codec() == kCodecAAC || 70 config.codec() == kCodecVorbis || config.codec() == kCodecAAC ||
67 config.codec() == kCodecOpus; 71 config.codec() == kCodecOpus || is_passthrough_;
68 if (!is_codec_supported) { 72 if (!is_codec_supported) {
69 DVLOG(1) << "Unsuported codec " << GetCodecName(config.codec()); 73 DVLOG(1) << "Unsuported codec " << GetCodecName(config.codec());
70 bound_init_cb.Run(false); 74 bound_init_cb.Run(false);
71 return; 75 return;
72 } 76 }
73 77
74 if (config.is_encrypted() && !cdm_context) { 78 if (config.is_encrypted() && !cdm_context) {
75 NOTREACHED() << "The stream is encrypted but there is no CDM context"; 79 NOTREACHED() << "The stream is encrypted but there is no CDM context";
76 bound_init_cb.Run(false); 80 bound_init_cb.Run(false);
77 return; 81 return;
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 } 294 }
291 295
292 void MediaCodecAudioDecoder::OnInputDataQueued(bool success) { 296 void MediaCodecAudioDecoder::OnInputDataQueued(bool success) {
293 // If this is an EOS buffer, then wait to call back until we are notified that 297 // If this is an EOS buffer, then wait to call back until we are notified that
294 // it has been processed via OnDecodedEos(). If the EOS was not queued 298 // it has been processed via OnDecodedEos(). If the EOS was not queued
295 // successfully, then we do want to signal error now since there is no queued 299 // successfully, then we do want to signal error now since there is no queued
296 // EOS to process later. 300 // EOS to process later.
297 if (input_queue_.front().first->end_of_stream() && success) 301 if (input_queue_.front().first->end_of_stream() && success)
298 return; 302 return;
299 303
304 if (is_passthrough_ && success) {
305 scoped_refptr<DecoderBuffer> decoder_buffer = input_queue_.front().first;
306
307 if (!decoder_buffer->end_of_stream()) {
308 duration_queue_.push_back(std::make_pair(decoder_buffer->timestamp(),
309 decoder_buffer->duration()));
310 }
311 }
312
300 input_queue_.front().second.Run(success ? DecodeStatus::OK 313 input_queue_.front().second.Run(success ? DecodeStatus::OK
301 : DecodeStatus::DECODE_ERROR); 314 : DecodeStatus::DECODE_ERROR);
302 input_queue_.pop_front(); 315 input_queue_.pop_front();
303 } 316 }
304 317
305 void MediaCodecAudioDecoder::ClearInputQueue(DecodeStatus decode_status) { 318 void MediaCodecAudioDecoder::ClearInputQueue(DecodeStatus decode_status) {
306 DVLOG(2) << __FUNCTION__; 319 DVLOG(2) << __FUNCTION__;
307 320
308 for (const auto& entry : input_queue_) 321 for (const auto& entry : input_queue_)
309 entry.second.Run(decode_status); 322 entry.second.Run(decode_status);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 DCHECK(codec_loop_); 361 DCHECK(codec_loop_);
349 MediaCodecBridge* media_codec = codec_loop_->GetCodec(); 362 MediaCodecBridge* media_codec = codec_loop_->GetCodec();
350 DCHECK(media_codec); 363 DCHECK(media_codec);
351 364
352 // For proper |frame_count| calculation we need to use the actual number 365 // For proper |frame_count| calculation we need to use the actual number
353 // of channels which can be different from |config_| value. 366 // of channels which can be different from |config_| value.
354 DCHECK_GT(channel_count_, 0); 367 DCHECK_GT(channel_count_, 0);
355 368
356 // Android MediaCodec can only output 16bit PCM audio. 369 // Android MediaCodec can only output 16bit PCM audio.
357 const int bytes_per_frame = sizeof(uint16_t) * channel_count_; 370 const int bytes_per_frame = sizeof(uint16_t) * channel_count_;
358 const size_t frame_count = out.size / bytes_per_frame; 371 size_t frame_count = out.size / bytes_per_frame;
372
373 if (is_passthrough_) {
DaleCurtis 2016/11/01 23:05:13 Didn't we determine that this is all CBR? So we kn
AndyWu 2016/11/04 18:04:24 Could you please advise how to get audio bit rate?
374 // Retrieve duratioin information from PTS-duration pair queue.
375 base::TimeDelta duration;
376 while (!duration_queue_.empty()) {
377 PtsDurationPair pts_duration = duration_queue_.front();
378 duration_queue_.pop_front();
379
380 base::TimeDelta diff = pts_duration.first - out.pts;
381 if (diff.magnitude() < base::TimeDelta::FromMicroseconds(1)) {
382 duration = pts_duration.second;
383 break;
384 }
385 }
386
387 // Calculate the frame count of this compressed audio buffer.
388 frame_count =
389 std::round(config_.samples_per_second() * duration.InSecondsF());
390 }
391
392 const SampleFormat sample_format =
393 is_passthrough_ ? kSampleFormatRaw : kSampleFormatS16;
394 const size_t size = is_passthrough_ ? out.size : 0;
359 395
360 // Create AudioOutput buffer based on current parameters. 396 // Create AudioOutput buffer based on current parameters.
361 scoped_refptr<AudioBuffer> audio_buffer = 397 scoped_refptr<AudioBuffer> audio_buffer =
362 AudioBuffer::CreateBuffer(kSampleFormatS16, channel_layout_, 398 AudioBuffer::CreateBuffer(sample_format, channel_layout_, channel_count_,
363 channel_count_, sample_rate_, frame_count); 399 sample_rate_, frame_count, size);
364 400
365 // Copy data into AudioBuffer. 401 // Copy data into AudioBuffer.
366 CHECK_LE(out.size, audio_buffer->data_size()); 402 CHECK_LE(out.size, audio_buffer->data_size());
367 403
368 MediaCodecStatus status = media_codec->CopyFromOutputBuffer( 404 MediaCodecStatus status = media_codec->CopyFromOutputBuffer(
369 out.index, out.offset, audio_buffer->channel_data()[0], out.size); 405 out.index, out.offset, audio_buffer->channel_data()[0], out.size);
370 406
371 // Release MediaCodec output buffer. 407 // Release MediaCodec output buffer.
372 media_codec->ReleaseOutputBuffer(out.index, false); 408 media_codec->ReleaseOutputBuffer(out.index, false);
373 409
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 RETURN_STRING(STATE_READY); 499 RETURN_STRING(STATE_READY);
464 RETURN_STRING(STATE_ERROR); 500 RETURN_STRING(STATE_ERROR);
465 } 501 }
466 NOTREACHED() << "Unknown state " << state; 502 NOTREACHED() << "Unknown state " << state;
467 return nullptr; 503 return nullptr;
468 } 504 }
469 505
470 #undef RETURN_STRING 506 #undef RETURN_STRING
471 507
472 } // namespace media 508 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698