Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: content/browser/renderer_host/media/audio_sync_reader.cc

Issue 10830268: Allow audio system to handle synchronized low-latency audio I/O (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698