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