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

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

Issue 2572573007: Use passthrough decoder for (E)AC3 formats (Closed)
Patch Set: Sanity checks Created 3 years, 7 months 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
« no previous file with comments | « media/filters/android/media_codec_audio_decoder.h ('k') | media/formats/ac3/ac3_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/media_codec_bridge_impl.h" 14 #include "media/base/android/media_codec_bridge_impl.h"
15 #include "media/base/android/media_codec_util.h"
13 #include "media/base/audio_timestamp_helper.h" 16 #include "media/base/audio_timestamp_helper.h"
14 #include "media/base/bind_to_current_loop.h" 17 #include "media/base/bind_to_current_loop.h"
15 #include "media/base/timestamp_constants.h" 18 #include "media/base/timestamp_constants.h"
19 #include "media/formats/ac3/ac3_util.h"
16 20
17 namespace media { 21 namespace media {
18 22
19 MediaCodecAudioDecoder::MediaCodecAudioDecoder( 23 MediaCodecAudioDecoder::MediaCodecAudioDecoder(
20 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 24 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
21 : task_runner_(task_runner), 25 : task_runner_(task_runner),
22 state_(STATE_UNINITIALIZED), 26 state_(STATE_UNINITIALIZED),
27 is_passthrough_(false),
28 sample_format_(kSampleFormatS16),
23 channel_count_(0), 29 channel_count_(0),
24 channel_layout_(CHANNEL_LAYOUT_NONE), 30 channel_layout_(CHANNEL_LAYOUT_NONE),
25 sample_rate_(0), 31 sample_rate_(0),
26 media_drm_bridge_cdm_context_(nullptr), 32 media_drm_bridge_cdm_context_(nullptr),
27 cdm_registration_id_(0), 33 cdm_registration_id_(0),
28 pool_(new AudioBufferMemoryPool()), 34 pool_(new AudioBufferMemoryPool()),
29 weak_factory_(this) { 35 weak_factory_(this) {
30 DVLOG(1) << __func__; 36 DVLOG(1) << __func__;
31 } 37 }
32 38
(...skipping 25 matching lines...) Expand all
58 const OutputCB& output_cb) { 64 const OutputCB& output_cb) {
59 DVLOG(1) << __func__ << ": " << config.AsHumanReadableString(); 65 DVLOG(1) << __func__ << ": " << config.AsHumanReadableString();
60 DCHECK_NE(state_, STATE_WAITING_FOR_MEDIA_CRYPTO); 66 DCHECK_NE(state_, STATE_WAITING_FOR_MEDIA_CRYPTO);
61 67
62 // Initialization and reinitialization should not be called during pending 68 // Initialization and reinitialization should not be called during pending
63 // decode. 69 // decode.
64 DCHECK(input_queue_.empty()); 70 DCHECK(input_queue_.empty());
65 ClearInputQueue(DecodeStatus::ABORTED); 71 ClearInputQueue(DecodeStatus::ABORTED);
66 72
67 InitCB bound_init_cb = BindToCurrentLoop(init_cb); 73 InitCB bound_init_cb = BindToCurrentLoop(init_cb);
74 is_passthrough_ = MediaCodecUtil::IsPassthroughAudioFormat(config.codec());
75 sample_format_ = kSampleFormatS16;
76
77 if (config.codec() == kCodecAC3)
78 sample_format_ = kSampleFormatAc3;
79 else if (config.codec() == kCodecEAC3)
80 sample_format_ = kSampleFormatEac3;
68 81
69 if (state_ == STATE_ERROR) { 82 if (state_ == STATE_ERROR) {
70 DVLOG(1) << "Decoder is in error state."; 83 DVLOG(1) << "Decoder is in error state.";
71 bound_init_cb.Run(false); 84 bound_init_cb.Run(false);
72 return; 85 return;
73 } 86 }
74 87
75 // We can support only the codecs that MediaCodecBridge can decode. 88 // We can support only the codecs that MediaCodecBridge can decode.
76 // TODO(xhwang): Get this list from MediaCodecBridge or just rely on 89 // TODO(xhwang): Get this list from MediaCodecBridge or just rely on
77 // attempting to create one to determine whether the codec is supported. 90 // attempting to create one to determine whether the codec is supported.
78 const bool is_codec_supported = config.codec() == kCodecVorbis || 91 const bool is_codec_supported =
79 config.codec() == kCodecAAC || 92 config.codec() == kCodecVorbis || config.codec() == kCodecAAC ||
80 config.codec() == kCodecOpus; 93 config.codec() == kCodecOpus || is_passthrough_;
81 if (!is_codec_supported) { 94 if (!is_codec_supported) {
82 DVLOG(1) << "Unsuported codec " << GetCodecName(config.codec()); 95 DVLOG(1) << "Unsuported codec " << GetCodecName(config.codec());
83 bound_init_cb.Run(false); 96 bound_init_cb.Run(false);
84 return; 97 return;
85 } 98 }
86 99
87 if (config.is_encrypted() && !cdm_context) { 100 if (config.is_encrypted() && !cdm_context) {
88 NOTREACHED() << "The stream is encrypted but there is no CDM context"; 101 NOTREACHED() << "The stream is encrypted but there is no CDM context";
89 bound_init_cb.Run(false); 102 bound_init_cb.Run(false);
90 return; 103 return;
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 DCHECK_NE(out.size, 0U); 364 DCHECK_NE(out.size, 0U);
352 DCHECK_NE(out.index, MediaCodecLoop::kInvalidBufferIndex); 365 DCHECK_NE(out.index, MediaCodecLoop::kInvalidBufferIndex);
353 DCHECK(codec_loop_); 366 DCHECK(codec_loop_);
354 MediaCodecBridge* media_codec = codec_loop_->GetCodec(); 367 MediaCodecBridge* media_codec = codec_loop_->GetCodec();
355 DCHECK(media_codec); 368 DCHECK(media_codec);
356 369
357 // For proper |frame_count| calculation we need to use the actual number 370 // For proper |frame_count| calculation we need to use the actual number
358 // of channels which can be different from |config_| value. 371 // of channels which can be different from |config_| value.
359 DCHECK_GT(channel_count_, 0); 372 DCHECK_GT(channel_count_, 0);
360 373
361 // Android MediaCodec can only output 16bit PCM audio. 374 size_t frame_count = 1;
362 const int bytes_per_frame = sizeof(uint16_t) * channel_count_; 375 scoped_refptr<AudioBuffer> audio_buffer;
363 const size_t frame_count = out.size / bytes_per_frame;
364 376
365 // Create AudioOutput buffer based on current parameters. 377 if (is_passthrough_) {
366 scoped_refptr<AudioBuffer> audio_buffer = AudioBuffer::CreateBuffer( 378 audio_buffer = AudioBuffer::CreateBitstreamBuffer(
367 kSampleFormatS16, channel_layout_, channel_count_, sample_rate_, 379 sample_format_, channel_layout_, channel_count_, sample_rate_,
368 frame_count, pool_); 380 frame_count, out.size, pool_);
381
382 MediaCodecStatus status = media_codec->CopyFromOutputBuffer(
383 out.index, out.offset, audio_buffer->channel_data()[0], out.size);
384
385 if (status != MEDIA_CODEC_OK) {
386 media_codec->ReleaseOutputBuffer(out.index, false);
387 return false;
388 }
389
390 if (config_.codec() == kCodecAC3) {
391 frame_count = Ac3Util::ParseTotalAc3SampleCount(
392 audio_buffer->channel_data()[0], out.size);
393 } else if (config_.codec() == kCodecEAC3) {
394 frame_count = Ac3Util::ParseTotalEac3SampleCount(
395 audio_buffer->channel_data()[0], out.size);
396 } else {
397 NOTREACHED() << "Unsupported passthrough format.";
398 }
399
400 // Create AudioOutput buffer based on current parameters.
401 audio_buffer = AudioBuffer::CreateBitstreamBuffer(
402 sample_format_, channel_layout_, channel_count_, sample_rate_,
403 frame_count, out.size, pool_);
404 } else {
405 // Android MediaCodec can only output 16bit PCM audio.
406 const int bytes_per_frame = sizeof(uint16_t) * channel_count_;
407 frame_count = out.size / bytes_per_frame;
408
409 // Create AudioOutput buffer based on current parameters.
410 audio_buffer = AudioBuffer::CreateBuffer(sample_format_, channel_layout_,
411 channel_count_, sample_rate_,
412 frame_count, pool_);
413 }
369 414
370 // Copy data into AudioBuffer. 415 // Copy data into AudioBuffer.
371 CHECK_LE(out.size, audio_buffer->data_size()); 416 CHECK_LE(out.size, audio_buffer->data_size());
372 417
373 MediaCodecStatus status = media_codec->CopyFromOutputBuffer( 418 MediaCodecStatus status = media_codec->CopyFromOutputBuffer(
374 out.index, out.offset, audio_buffer->channel_data()[0], out.size); 419 out.index, out.offset, audio_buffer->channel_data()[0], out.size);
375 420
376 // Release MediaCodec output buffer. 421 // Release MediaCodec output buffer.
377 media_codec->ReleaseOutputBuffer(out.index, false); 422 media_codec->ReleaseOutputBuffer(out.index, false);
378 423
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 RETURN_STRING(STATE_READY); 512 RETURN_STRING(STATE_READY);
468 RETURN_STRING(STATE_ERROR); 513 RETURN_STRING(STATE_ERROR);
469 } 514 }
470 NOTREACHED() << "Unknown state " << state; 515 NOTREACHED() << "Unknown state " << state;
471 return nullptr; 516 return nullptr;
472 } 517 }
473 518
474 #undef RETURN_STRING 519 #undef RETURN_STRING
475 520
476 } // namespace media 521 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/android/media_codec_audio_decoder.h ('k') | media/formats/ac3/ac3_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698