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

Unified Diff: media/renderers/audio_renderer_impl.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 side-by-side diff with in-line comments
Download patch
Index: media/renderers/audio_renderer_impl.cc
diff --git a/media/renderers/audio_renderer_impl.cc b/media/renderers/audio_renderer_impl.cc
index 379c9570b114175ad358f3c31ec1e0f9af0f2759..5445ca8f67ce6dfea46aeb1e9375a55ab8040801 100644
--- a/media/renderers/audio_renderer_impl.cc
+++ b/media/renderers/audio_renderer_impl.cc
@@ -24,6 +24,7 @@
#include "media/base/audio_splicer.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/demuxer_stream.h"
+#include "media/base/media_client.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/renderer_client.h"
@@ -33,6 +34,8 @@
namespace media {
+static const int kMaxFramesPerCompressedAudioBuffer = 4096;
+
AudioRendererImpl::AudioRendererImpl(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
media::AudioRendererSink* sink,
@@ -57,6 +60,7 @@ AudioRendererImpl::AudioRendererImpl(
received_end_of_stream_(false),
rendered_end_of_stream_(false),
is_suspending_(false),
+ is_passthrough_(false),
last_reported_media_time_(kNoTimestamp),
weak_factory_(this) {
audio_buffer_stream_->set_splice_observer(base::Bind(
@@ -364,11 +368,35 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream,
// failed.
init_cb_ = BindToCurrentLoop(init_cb);
+ AudioCodec codec = stream->audio_decoder_config().codec();
+ MediaClient* media_client = GetMediaClient();
+ is_passthrough_ =
+ media_client && media_client->IsSupportedPassthroughAudio(codec);
+
const AudioParameters& hw_params =
sink_->GetOutputDeviceInfo().output_params();
expecting_config_changes_ = stream->SupportsConfigChanges();
- if (!expecting_config_changes_ || !hw_params.IsValid() ||
- hw_params.format() == AudioParameters::AUDIO_FAKE) {
+
+ if (is_passthrough_) {
+ AudioParameters::Format format = AudioParameters::AUDIO_FAKE;
+ if (codec == kCodecAC3) {
+ format = AudioParameters::AUDIO_RAW_AC3;
+ } else if (codec == kCodecEAC3) {
+ format = AudioParameters::AUDIO_RAW_EAC3;
+ } else {
+ NOTREACHED();
+ }
+
+ const int buffer_size = kMaxFramesPerCompressedAudioBuffer *
+ stream->audio_decoder_config().bytes_per_frame();
+
+ audio_parameters_.Reset(
+ format, stream->audio_decoder_config().channel_layout(),
+ stream->audio_decoder_config().samples_per_second(),
+ stream->audio_decoder_config().bits_per_channel(), buffer_size);
+ buffer_converter_.reset();
+ } else if (!expecting_config_changes_ || !hw_params.IsValid() ||
+ hw_params.format() == AudioParameters::AUDIO_FAKE) {
// The actual buffer size is controlled via the size of the AudioBus
// provided to Render(), but we should choose a value here based on hardware
// parameters if possible since it affects the initial buffer size used by
@@ -580,6 +608,20 @@ void AudioRendererImpl::DecodedAudioReady(
return;
}
+ if (buffer->sample_format() == kSampleFormatRaw) {
+ if (last_decoded_sample_rate_ &&
+ buffer->sample_rate() != last_decoded_sample_rate_) {
+ OnConfigChange();
+ }
+ last_decoded_sample_rate_ = buffer->sample_rate();
+
+ if (!HandleSplicerBuffer_Locked(buffer) && !CanRead_Locked())
+ return;
+
+ AttemptRead_Locked();
+ return;
+ }
+
if (expecting_config_changes_) {
if (last_decoded_sample_rate_ &&
buffer->sample_rate() != last_decoded_sample_rate_) {
@@ -647,7 +689,7 @@ bool AudioRendererImpl::HandleSplicerBuffer_Locked(
if (buffer->end_of_stream()) {
received_end_of_stream_ = true;
} else {
- if (state_ == kPlaying) {
+ if (state_ == kPlaying && buffer->sample_format() != kSampleFormatRaw) {
DaleCurtis 2016/11/01 23:05:13 This is incorrect, seeking is going to return the
AndyWu 2016/11/04 18:04:24 Thanks for pointing it out. Mark reporting time as
DaleCurtis 2016/11/04 19:48:29 No, AV sync will never recover for this case since
AndyWu 2016/11/08 00:04:21 I see. I reset start_timestamp_and audio_clock_in
DaleCurtis 2016/11/08 00:11:47 I don't think this will work. There is code in oth
watk 2016/11/08 19:59:30 PipelineImpl::GetMediaTime() tracks the last repor
AndyWu 2016/11/11 17:52:48 Thanks a lot for your information. I guess I can d
if (IsBeforeStartTime(buffer))
return true;
@@ -776,7 +818,7 @@ bool AudioRendererImpl::IsBeforeStartTime(
int AudioRendererImpl::Render(AudioBus* audio_bus,
uint32_t frames_delayed,
uint32_t frames_skipped) {
- const int frames_requested = audio_bus->frames();
+ int frames_requested = audio_bus->frames();
DVLOG(4) << __func__ << " frames_delayed:" << frames_delayed
<< " frames_skipped:" << frames_skipped
<< " frames_requested:" << frames_requested;
@@ -812,9 +854,13 @@ int AudioRendererImpl::Render(AudioBus* audio_bus,
return 0;
}
- // Delay playback by writing silence if we haven't reached the first
- // timestamp yet; this can occur if the video starts before the audio.
- if (algorithm_->frames_buffered() > 0) {
+ if (is_passthrough_ && algorithm_->frames_buffered() > 0) {
+ frames_written += algorithm_->FillBuffer(audio_bus, 0, frames_requested,
+ playback_rate_);
+ frames_requested = frames_written;
+ } else if (algorithm_->frames_buffered() > 0) {
+ // Delay playback by writing silence if we haven't reached the first
+ // timestamp yet; this can occur if the video starts before the audio.
CHECK_NE(first_packet_timestamp_, kNoTimestamp);
CHECK_GE(first_packet_timestamp_, base::TimeDelta());
const base::TimeDelta play_delay =
« media/filters/android/media_codec_audio_decoder.cc ('K') | « media/renderers/audio_renderer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698