Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 5 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/process_util.h" | 9 #include "base/process_util.h" |
| 10 #include "base/shared_memory.h" | 10 #include "base/shared_memory.h" |
| 11 #include "base/threading/platform_thread.h" | 11 #include "base/threading/platform_thread.h" |
| 12 #include "media/audio/audio_buffers_state.h" | 12 #include "media/audio/audio_buffers_state.h" |
| 13 #include "media/audio/audio_parameters.h" | 13 #include "media/audio/audio_parameters.h" |
| 14 #include "media/audio/shared_memory_util.h" | 14 #include "media/audio/shared_memory_util.h" |
| 15 | 15 |
| 16 #if defined(OS_WIN) | 16 #if defined(OS_WIN) |
| 17 const int kMinIntervalBetweenReadCallsInMs = 10; | 17 const int kMinIntervalBetweenReadCallsInMs = 10; |
| 18 #endif | 18 #endif |
| 19 | 19 |
| 20 using media::AudioBus; | |
| 21 | |
| 20 AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory, | 22 AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory, |
| 21 const media::AudioParameters& params) | 23 const media::AudioParameters& params, |
| 22 : shared_memory_(shared_memory) { | 24 int input_channels) |
| 25 : shared_memory_(shared_memory), | |
| 26 input_channels_(input_channels) { | |
| 23 packet_size_ = media::PacketSizeInBytes(shared_memory_->created_size()); | 27 packet_size_ = media::PacketSizeInBytes(shared_memory_->created_size()); |
| 24 DCHECK_EQ(packet_size_, media::AudioBus::CalculateMemorySize(params)); | 28 DCHECK_EQ(packet_size_, AudioBus::CalculateMemorySize(params)); |
| 25 audio_bus_ = media::AudioBus::WrapMemory(params, shared_memory->memory()); | 29 output_bus_ = AudioBus::WrapMemory(params, shared_memory->memory()); |
| 30 | |
| 31 if (input_channels_ > 0) { | |
| 32 // The input storage is after the output storage. | |
| 33 int output_memory_size = AudioBus::CalculateMemorySize(params); | |
| 34 int frames = params.frames_per_buffer(); | |
| 35 char* input_data = | |
| 36 static_cast<char*>(shared_memory_->memory()) + output_memory_size; | |
| 37 input_bus_ = AudioBus::WrapMemory(input_channels_, frames, input_data); | |
| 38 } | |
| 26 } | 39 } |
| 27 | 40 |
| 28 AudioSyncReader::~AudioSyncReader() { | 41 AudioSyncReader::~AudioSyncReader() { |
| 29 } | 42 } |
| 30 | 43 |
| 31 bool AudioSyncReader::DataReady() { | 44 bool AudioSyncReader::DataReady() { |
| 32 return !media::IsUnknownDataSize(shared_memory_, packet_size_); | 45 return !media::IsUnknownDataSize(shared_memory_, packet_size_); |
| 33 } | 46 } |
| 34 | 47 |
| 35 // media::AudioOutputController::SyncReader implementations. | 48 // media::AudioOutputController::SyncReader implementations. |
| 36 void AudioSyncReader::UpdatePendingBytes(uint32 bytes) { | 49 void AudioSyncReader::UpdatePendingBytes(uint32 bytes) { |
| 37 if (bytes != static_cast<uint32>(media::kPauseMark)) { | 50 if (bytes != static_cast<uint32>(media::kPauseMark)) { |
| 38 // Store unknown length of data into buffer, so we later | 51 // Store unknown length of data into buffer, so we later |
| 39 // can find out if data became available. | 52 // can find out if data became available. |
| 40 media::SetUnknownDataSize(shared_memory_, packet_size_); | 53 media::SetUnknownDataSize(shared_memory_, packet_size_); |
| 41 } | 54 } |
| 42 | 55 |
| 43 if (socket_.get()) { | 56 if (socket_.get()) { |
| 44 socket_->Send(&bytes, sizeof(bytes)); | 57 socket_->Send(&bytes, sizeof(bytes)); |
| 45 } | 58 } |
| 46 } | 59 } |
| 47 | 60 |
| 48 int AudioSyncReader::Read(media::AudioBus* audio_bus) { | 61 int AudioSyncReader::Read(AudioBus* source, AudioBus* dest) { |
| 49 #if defined(OS_WIN) | 62 #if defined(OS_WIN) |
| 50 // HACK: yield if reader is called too often. | 63 // HACK: yield if reader is called too often. |
| 51 // Problem is lack of synchronization between host and renderer. We cannot be | 64 // Problem is lack of synchronization between host and renderer. We cannot be |
| 52 // sure if renderer already filled the buffer, and due to all the plugins we | 65 // sure if renderer already filled the buffer, and due to all the plugins we |
| 53 // cannot change the API, so we yield if previous call was too recent. | 66 // cannot change the API, so we yield if previous call was too recent. |
| 54 // Optimization: if renderer is "new" one that writes length of data we can | 67 // Optimization: if renderer is "new" one that writes length of data we can |
| 55 // stop yielding the moment length is written -- not ideal solution, | 68 // stop yielding the moment length is written -- not ideal solution, |
| 56 // but better than nothing. | 69 // but better than nothing. |
| 57 while (!DataReady() && | 70 while (!DataReady() && |
| 58 ((base::Time::Now() - previous_call_time_).InMilliseconds() < | 71 ((base::Time::Now() - previous_call_time_).InMilliseconds() < |
| 59 kMinIntervalBetweenReadCallsInMs)) { | 72 kMinIntervalBetweenReadCallsInMs)) { |
| 60 base::PlatformThread::YieldCurrentThread(); | 73 base::PlatformThread::YieldCurrentThread(); |
| 61 } | 74 } |
| 62 previous_call_time_ = base::Time::Now(); | 75 previous_call_time_ = base::Time::Now(); |
| 63 #endif | 76 #endif |
| 64 | 77 |
| 78 // Copy optional synchronized live audio input | |
| 79 // for consumption by renderer process. | |
|
scherkus (not reviewing)
2012/09/10 11:46:32
nit: some of this comment can fit on previous line
Chris Rogers
2012/09/10 19:21:38
Done.
| |
| 80 if (source && input_bus_.get()) { | |
| 81 DCHECK_EQ(source->channels(), input_bus_->channels()); | |
| 82 DCHECK_LE(source->frames(), input_bus_->frames()); | |
| 83 source->CopyTo(input_bus_.get()); | |
| 84 } | |
| 85 | |
| 65 // Retrieve the actual number of bytes available from the shared memory. If | 86 // Retrieve the actual number of bytes available from the shared memory. If |
| 66 // the renderer has not completed rendering this value will be invalid (still | 87 // the renderer has not completed rendering this value will be invalid (still |
| 67 // the marker stored in UpdatePendingBytes() above) and must be sanitized. | 88 // the marker stored in UpdatePendingBytes() above) and must be sanitized. |
| 68 // TODO(dalecurtis): Technically this is not the exact size. Due to channel | 89 // TODO(dalecurtis): Technically this is not the exact size. Due to channel |
| 69 // padding for alignment, there may be more data available than this; AudioBus | 90 // padding for alignment, there may be more data available than this; AudioBus |
| 70 // will automatically do the right thing during CopyTo(). Rename this method | 91 // will automatically do the right thing during CopyTo(). Rename this method |
| 71 // to GetActualFrameCount(). | 92 // to GetActualFrameCount(). |
| 72 uint32 size = media::GetActualDataSizeInBytes(shared_memory_, packet_size_); | 93 uint32 size = media::GetActualDataSizeInBytes(shared_memory_, packet_size_); |
| 73 | 94 |
| 74 // Compute the actual number of frames read. It's important to sanitize this | 95 // Compute the actual number of frames read. It's important to sanitize this |
| 75 // value for a couple reasons. One, it might still be the unknown data size | 96 // value for a couple reasons. One, it might still be the unknown data size |
| 76 // marker. Two, shared memory comes from a potentially untrusted source. | 97 // marker. Two, shared memory comes from a potentially untrusted source. |
| 77 int frames = | 98 int frames = |
| 78 size / (sizeof(*audio_bus_->channel(0)) * audio_bus_->channels()); | 99 size / (sizeof(*output_bus_->channel(0)) * output_bus_->channels()); |
| 79 if (frames < 0) | 100 if (frames < 0) |
| 80 frames = 0; | 101 frames = 0; |
| 81 else if (frames > audio_bus_->frames()) | 102 else if (frames > output_bus_->frames()) |
| 82 frames = audio_bus_->frames(); | 103 frames = output_bus_->frames(); |
| 83 | 104 |
| 84 // Copy data from the shared memory into the caller's AudioBus. | 105 // Copy data from the shared memory into the caller's AudioBus. |
| 85 audio_bus_->CopyTo(audio_bus); | 106 output_bus_->CopyTo(dest); |
| 86 | 107 |
| 87 // Zero out any unfilled frames in the destination bus. | 108 // Zero out any unfilled frames in the destination bus. |
| 88 audio_bus->ZeroFramesPartial(frames, audio_bus->frames() - frames); | 109 dest->ZeroFramesPartial(frames, dest->frames() - frames); |
| 89 | 110 |
| 90 // Zero out the entire buffer. | 111 // Zero out the entire output buffer to avoid stuttering/repeating-buffers |
| 91 memset(shared_memory_->memory(), 0, packet_size_); | 112 // in the anomalous case if the renderer is unable to keep up with real-time. |
| 113 output_bus_->Zero(); | |
| 92 | 114 |
| 93 // Store unknown length of data into buffer, in case renderer does not store | 115 // Store unknown length of data into buffer, in case renderer does not store |
| 94 // the length itself. It also helps in decision if we need to yield. | 116 // the length itself. It also helps in decision if we need to yield. |
| 95 media::SetUnknownDataSize(shared_memory_, packet_size_); | 117 media::SetUnknownDataSize(shared_memory_, packet_size_); |
| 96 | 118 |
| 97 // Return the actual number of frames read. | 119 // Return the actual number of frames read. |
| 98 return frames; | 120 return frames; |
| 99 } | 121 } |
| 100 | 122 |
| 101 void AudioSyncReader::Close() { | 123 void AudioSyncReader::Close() { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 126 bool AudioSyncReader::PrepareForeignSocketHandle( | 148 bool AudioSyncReader::PrepareForeignSocketHandle( |
| 127 base::ProcessHandle process_handle, | 149 base::ProcessHandle process_handle, |
| 128 base::FileDescriptor* foreign_handle) { | 150 base::FileDescriptor* foreign_handle) { |
| 129 foreign_handle->fd = foreign_socket_->handle(); | 151 foreign_handle->fd = foreign_socket_->handle(); |
| 130 foreign_handle->auto_close = false; | 152 foreign_handle->auto_close = false; |
| 131 if (foreign_handle->fd != -1) | 153 if (foreign_handle->fd != -1) |
| 132 return true; | 154 return true; |
| 133 return false; | 155 return false; |
| 134 } | 156 } |
| 135 #endif | 157 #endif |
| OLD | NEW |