| Index: content/browser/renderer_host/media/audio_sync_reader.cc
|
| ===================================================================
|
| --- content/browser/renderer_host/media/audio_sync_reader.cc (revision 156123)
|
| +++ content/browser/renderer_host/media/audio_sync_reader.cc (working copy)
|
| @@ -17,12 +17,25 @@
|
| const int kMinIntervalBetweenReadCallsInMs = 10;
|
| #endif
|
|
|
| +using media::AudioBus;
|
| +
|
| AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
|
| - const media::AudioParameters& params)
|
| - : shared_memory_(shared_memory) {
|
| + const media::AudioParameters& params,
|
| + int input_channels)
|
| + : shared_memory_(shared_memory),
|
| + input_channels_(input_channels) {
|
| packet_size_ = media::PacketSizeInBytes(shared_memory_->created_size());
|
| - DCHECK_EQ(packet_size_, media::AudioBus::CalculateMemorySize(params));
|
| - audio_bus_ = media::AudioBus::WrapMemory(params, shared_memory->memory());
|
| + DCHECK_EQ(packet_size_, AudioBus::CalculateMemorySize(params));
|
| + output_bus_ = AudioBus::WrapMemory(params, shared_memory->memory());
|
| +
|
| + if (input_channels_ > 0) {
|
| + // The input storage is after the output storage.
|
| + int output_memory_size = AudioBus::CalculateMemorySize(params);
|
| + int frames = params.frames_per_buffer();
|
| + char* input_data =
|
| + static_cast<char*>(shared_memory_->memory()) + output_memory_size;
|
| + input_bus_ = AudioBus::WrapMemory(input_channels_, frames, input_data);
|
| + }
|
| }
|
|
|
| AudioSyncReader::~AudioSyncReader() {
|
| @@ -45,7 +58,7 @@
|
| }
|
| }
|
|
|
| -int AudioSyncReader::Read(media::AudioBus* audio_bus) {
|
| +int AudioSyncReader::Read(AudioBus* source, AudioBus* dest) {
|
| #if defined(OS_WIN)
|
| // HACK: yield if reader is called too often.
|
| // Problem is lack of synchronization between host and renderer. We cannot be
|
| @@ -62,6 +75,14 @@
|
| previous_call_time_ = base::Time::Now();
|
| #endif
|
|
|
| + // Copy optional synchronized live audio input for consumption by renderer
|
| + // process.
|
| + if (source && input_bus_.get()) {
|
| + DCHECK_EQ(source->channels(), input_bus_->channels());
|
| + DCHECK_LE(source->frames(), input_bus_->frames());
|
| + source->CopyTo(input_bus_.get());
|
| + }
|
| +
|
| // Retrieve the actual number of bytes available from the shared memory. If
|
| // the renderer has not completed rendering this value will be invalid (still
|
| // the marker stored in UpdatePendingBytes() above) and must be sanitized.
|
| @@ -75,20 +96,21 @@
|
| // value for a couple reasons. One, it might still be the unknown data size
|
| // marker. Two, shared memory comes from a potentially untrusted source.
|
| int frames =
|
| - size / (sizeof(*audio_bus_->channel(0)) * audio_bus_->channels());
|
| + size / (sizeof(*output_bus_->channel(0)) * output_bus_->channels());
|
| if (frames < 0)
|
| frames = 0;
|
| - else if (frames > audio_bus_->frames())
|
| - frames = audio_bus_->frames();
|
| + else if (frames > output_bus_->frames())
|
| + frames = output_bus_->frames();
|
|
|
| // Copy data from the shared memory into the caller's AudioBus.
|
| - audio_bus_->CopyTo(audio_bus);
|
| + output_bus_->CopyTo(dest);
|
|
|
| // Zero out any unfilled frames in the destination bus.
|
| - audio_bus->ZeroFramesPartial(frames, audio_bus->frames() - frames);
|
| + dest->ZeroFramesPartial(frames, dest->frames() - frames);
|
|
|
| - // Zero out the entire buffer.
|
| - memset(shared_memory_->memory(), 0, packet_size_);
|
| + // Zero out the entire output buffer to avoid stuttering/repeating-buffers
|
| + // in the anomalous case if the renderer is unable to keep up with real-time.
|
| + output_bus_->Zero();
|
|
|
| // Store unknown length of data into buffer, in case renderer does not store
|
| // the length itself. It also helps in decision if we need to yield.
|
|
|