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/shared_memory_util.h" | 14 #include "media/audio/shared_memory_util.h" |
14 | 15 |
15 #if defined(OS_WIN) | 16 #if defined(OS_WIN) |
16 const int kMinIntervalBetweenReadCallsInMs = 10; | 17 const int kMinIntervalBetweenReadCallsInMs = 10; |
17 #endif | 18 #endif |
18 | 19 |
19 AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory) | 20 AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory, |
| 21 const media::AudioParameters& params) |
20 : shared_memory_(shared_memory) { | 22 : shared_memory_(shared_memory) { |
| 23 packet_size_ = media::PacketSizeInBytes(shared_memory_->created_size()); |
| 24 DCHECK_EQ(packet_size_, media::AudioBus::CalculateMemorySize(params)); |
| 25 audio_bus_ = media::AudioBus::WrapMemory(params, shared_memory->memory()); |
21 } | 26 } |
22 | 27 |
23 AudioSyncReader::~AudioSyncReader() { | 28 AudioSyncReader::~AudioSyncReader() { |
24 } | 29 } |
25 | 30 |
26 bool AudioSyncReader::DataReady() { | 31 bool AudioSyncReader::DataReady() { |
27 return !media::IsUnknownDataSize( | 32 return !media::IsUnknownDataSize(shared_memory_, packet_size_); |
28 shared_memory_, | |
29 media::PacketSizeInBytes(shared_memory_->created_size())); | |
30 } | 33 } |
31 | 34 |
32 // media::AudioOutputController::SyncReader implementations. | 35 // media::AudioOutputController::SyncReader implementations. |
33 void AudioSyncReader::UpdatePendingBytes(uint32 bytes) { | 36 void AudioSyncReader::UpdatePendingBytes(uint32 bytes) { |
34 if (bytes != static_cast<uint32>(media::kPauseMark)) { | 37 if (bytes != static_cast<uint32>(media::kPauseMark)) { |
35 // Store unknown length of data into buffer, so we later | 38 // Store unknown length of data into buffer, so we later |
36 // can find out if data became available. | 39 // can find out if data became available. |
37 media::SetUnknownDataSize( | 40 media::SetUnknownDataSize(shared_memory_, packet_size_); |
38 shared_memory_, | |
39 media::PacketSizeInBytes(shared_memory_->created_size())); | |
40 } | 41 } |
41 | 42 |
42 if (socket_.get()) { | 43 if (socket_.get()) { |
43 socket_->Send(&bytes, sizeof(bytes)); | 44 socket_->Send(&bytes, sizeof(bytes)); |
44 } | 45 } |
45 } | 46 } |
46 | 47 |
47 uint32 AudioSyncReader::Read(void* data, uint32 size) { | 48 int AudioSyncReader::Read(media::AudioBus* audio_bus) { |
48 uint32 max_size = media::PacketSizeInBytes( | |
49 shared_memory_->created_size()); | |
50 | |
51 #if defined(OS_WIN) | 49 #if defined(OS_WIN) |
52 // HACK: yield if reader is called too often. | 50 // HACK: yield if reader is called too often. |
53 // Problem is lack of synchronization between host and renderer. We cannot be | 51 // Problem is lack of synchronization between host and renderer. We cannot be |
54 // sure if renderer already filled the buffer, and due to all the plugins we | 52 // sure if renderer already filled the buffer, and due to all the plugins we |
55 // cannot change the API, so we yield if previous call was too recent. | 53 // cannot change the API, so we yield if previous call was too recent. |
56 // Optimization: if renderer is "new" one that writes length of data we can | 54 // Optimization: if renderer is "new" one that writes length of data we can |
57 // stop yielding the moment length is written -- not ideal solution, | 55 // stop yielding the moment length is written -- not ideal solution, |
58 // but better than nothing. | 56 // but better than nothing. |
59 while (!DataReady() && | 57 while (!DataReady() && |
60 ((base::Time::Now() - previous_call_time_).InMilliseconds() < | 58 ((base::Time::Now() - previous_call_time_).InMilliseconds() < |
61 kMinIntervalBetweenReadCallsInMs)) { | 59 kMinIntervalBetweenReadCallsInMs)) { |
62 base::PlatformThread::YieldCurrentThread(); | 60 base::PlatformThread::YieldCurrentThread(); |
63 } | 61 } |
64 previous_call_time_ = base::Time::Now(); | 62 previous_call_time_ = base::Time::Now(); |
65 #endif | 63 #endif |
66 | 64 |
67 uint32 read_size = std::min(media::GetActualDataSizeInBytes(shared_memory_, | 65 // Retrieve the actual number of bytes available from the shared memory. If |
68 max_size), | 66 // the renderer has not completed rendering this value will be invalid (still |
69 size); | 67 // the marker stored in UpdatePendingBytes() above) and must be sanitized. |
| 68 // 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 |
| 70 // will automatically do the right thing during CopyTo(). Rename this method |
| 71 // to GetActualFrameCount(). |
| 72 uint32 size = media::GetActualDataSizeInBytes(shared_memory_, packet_size_); |
70 | 73 |
71 // Get the data from the buffer. | 74 // Compute the actual number of frames read. It's important to sanitize this |
72 memcpy(data, shared_memory_->memory(), read_size); | 75 // 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. |
| 77 int frames = |
| 78 size / (sizeof(*audio_bus_->channel(0)) * audio_bus_->channels()); |
| 79 if (frames < 0) |
| 80 frames = 0; |
| 81 else if (frames > audio_bus_->frames()) |
| 82 frames = audio_bus_->frames(); |
73 | 83 |
74 // If amount read was less than requested, then zero out the remainder. | 84 // Copy data from the shared memory into the caller's AudioBus. |
75 if (read_size < size) | 85 audio_bus_->CopyTo(audio_bus); |
76 memset(static_cast<char*>(data) + read_size, 0, size - read_size); | 86 |
| 87 // Zero out any unfilled frames in the destination bus. |
| 88 audio_bus->ZeroFramesPartial(frames, audio_bus->frames() - frames); |
77 | 89 |
78 // Zero out the entire buffer. | 90 // Zero out the entire buffer. |
79 memset(shared_memory_->memory(), 0, max_size); | 91 memset(shared_memory_->memory(), 0, packet_size_); |
80 | 92 |
81 // Store unknown length of data into buffer, in case renderer does not store | 93 // Store unknown length of data into buffer, in case renderer does not store |
82 // the length itself. It also helps in decision if we need to yield. | 94 // the length itself. It also helps in decision if we need to yield. |
83 media::SetUnknownDataSize(shared_memory_, max_size); | 95 media::SetUnknownDataSize(shared_memory_, packet_size_); |
84 | 96 |
85 return read_size; | 97 // Return the actual number of frames read. |
| 98 return frames; |
86 } | 99 } |
87 | 100 |
88 void AudioSyncReader::Close() { | 101 void AudioSyncReader::Close() { |
89 if (socket_.get()) { | 102 if (socket_.get()) { |
90 socket_->Close(); | 103 socket_->Close(); |
91 } | 104 } |
92 } | 105 } |
93 | 106 |
94 bool AudioSyncReader::Init() { | 107 bool AudioSyncReader::Init() { |
95 socket_.reset(new base::CancelableSyncSocket()); | 108 socket_.reset(new base::CancelableSyncSocket()); |
(...skipping 17 matching lines...) Expand all Loading... |
113 bool AudioSyncReader::PrepareForeignSocketHandle( | 126 bool AudioSyncReader::PrepareForeignSocketHandle( |
114 base::ProcessHandle process_handle, | 127 base::ProcessHandle process_handle, |
115 base::FileDescriptor* foreign_handle) { | 128 base::FileDescriptor* foreign_handle) { |
116 foreign_handle->fd = foreign_socket_->handle(); | 129 foreign_handle->fd = foreign_socket_->handle(); |
117 foreign_handle->auto_close = false; | 130 foreign_handle->auto_close = false; |
118 if (foreign_handle->fd != -1) | 131 if (foreign_handle->fd != -1) |
119 return true; | 132 return true; |
120 return false; | 133 return false; |
121 } | 134 } |
122 #endif | 135 #endif |
OLD | NEW |