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