Chromium Code Reviews| Index: content/browser/renderer_host/media/audio_sync_reader.cc |
| =================================================================== |
| --- content/browser/renderer_host/media/audio_sync_reader.cc (revision 155897) |
| +++ 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(); |
|
DaleCurtis
2012/09/11 09:44:39
This doesn't Zero everything when frames are padde
|
| // 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. |