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

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

Issue 1302423006: Ensure that data is not overwritten in the audio input shared memory ring buffer that sits on the b… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
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_input_sync_writer.h" 5 #include "content/browser/renderer_host/media/audio_input_sync_writer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/memory/shared_memory.h" 9 #include "base/memory/shared_memory.h"
10 #include "base/metrics/histogram.h"
10 #include "content/browser/renderer_host/media/media_stream_manager.h" 11 #include "content/browser/renderer_host/media/media_stream_manager.h"
11 12
12 using media::AudioBus; 13 using media::AudioBus;
13 14
14 namespace content { 15 namespace content {
15 16
17 namespace {
18 // TODO BEFORE COMMIT: Which value makes sense? I.e. how long can we accept
19 // blocking the soundcard thread and wait before dropping data.
20 const base::TimeDelta kReadCheckTimeout =
henrika (OOO until Aug 14) 2015/08/28 07:56:25 Have you experimented with high load to see the ef
Henrik Grunell 2015/08/28 12:21:57 I've stress tested on my machine, couldn't provoke
21 base::TimeDelta::FromMilliseconds(10);
22 }
23
16 AudioInputSyncWriter::AudioInputSyncWriter(base::SharedMemory* shared_memory, 24 AudioInputSyncWriter::AudioInputSyncWriter(base::SharedMemory* shared_memory,
17 int shared_memory_segment_count, 25 int shared_memory_segment_count,
18 const media::AudioParameters& params) 26 const media::AudioParameters& params)
19 : shared_memory_(shared_memory), 27 : shared_memory_(shared_memory),
20 shared_memory_segment_count_(shared_memory_segment_count), 28 shared_memory_segment_count_(shared_memory_segment_count),
21 current_segment_id_(0), 29 current_segment_id_(0),
22 creation_time_(base::Time::Now()), 30 creation_time_(base::Time::Now()),
23 audio_bus_memory_size_(AudioBus::CalculateMemorySize(params)), 31 audio_bus_memory_size_(AudioBus::CalculateMemorySize(params)),
24 next_buffer_id_(0) { 32 next_buffer_id_(0),
33 expected_buffer_reads_(0),
34 read_verification_timeouts_(0) {
25 DCHECK_GT(shared_memory_segment_count, 0); 35 DCHECK_GT(shared_memory_segment_count, 0);
26 DCHECK_EQ(shared_memory->requested_size() % shared_memory_segment_count, 0u); 36 DCHECK_EQ(shared_memory->requested_size() % shared_memory_segment_count, 0u);
27 shared_memory_segment_size_ = 37 shared_memory_segment_size_ =
28 shared_memory->requested_size() / shared_memory_segment_count; 38 shared_memory->requested_size() / shared_memory_segment_count;
29 DVLOG(1) << "SharedMemory::requested_size: " 39 DVLOG(1) << "SharedMemory::requested_size: "
30 << shared_memory->requested_size(); 40 << shared_memory->requested_size();
31 DVLOG(1) << "shared_memory_segment_count: " << shared_memory_segment_count; 41 DVLOG(1) << "shared_memory_segment_count: " << shared_memory_segment_count;
32 DVLOG(1) << "audio_bus_memory_size: " << audio_bus_memory_size_; 42 DVLOG(1) << "audio_bus_memory_size: " << audio_bus_memory_size_;
33 43
34 // Create vector of audio buses by wrapping existing blocks of memory. 44 // Create vector of audio buses by wrapping existing blocks of memory.
35 uint8* ptr = static_cast<uint8*>(shared_memory_->memory()); 45 uint8* ptr = static_cast<uint8*>(shared_memory_->memory());
36 for (int i = 0; i < shared_memory_segment_count; ++i) { 46 for (int i = 0; i < shared_memory_segment_count; ++i) {
37 CHECK((reinterpret_cast<uintptr_t>(ptr) & 47 CHECK((reinterpret_cast<uintptr_t>(ptr) &
38 (media::AudioBus::kChannelAlignment - 1)) == 0U); 48 (media::AudioBus::kChannelAlignment - 1)) == 0U);
39 media::AudioInputBuffer* buffer = 49 media::AudioInputBuffer* buffer =
40 reinterpret_cast<media::AudioInputBuffer*>(ptr); 50 reinterpret_cast<media::AudioInputBuffer*>(ptr);
41 scoped_ptr<media::AudioBus> audio_bus = 51 scoped_ptr<media::AudioBus> audio_bus =
42 media::AudioBus::WrapMemory(params, buffer->audio); 52 media::AudioBus::WrapMemory(params, buffer->audio);
43 audio_buses_.push_back(audio_bus.release()); 53 audio_buses_.push_back(audio_bus.release());
44 ptr += shared_memory_segment_size_; 54 ptr += shared_memory_segment_size_;
45 } 55 }
46 } 56 }
47 57
48 AudioInputSyncWriter::~AudioInputSyncWriter() {} 58 AudioInputSyncWriter::~AudioInputSyncWriter() {
59 // TODO BEFORE COMMIT: Maybe percentage makes more sense here?
DaleCurtis 2015/08/27 16:43:39 For consistency please use the same pattern as we
Henrik Grunell 2015/08/28 12:21:57 Done.
60 UMA_HISTOGRAM_COUNTS_1000("Media.AudioCapturerMissedReadDeadline",
61 read_verification_timeouts_);
62 }
49 63
50 void AudioInputSyncWriter::Write(const media::AudioBus* data, 64 void AudioInputSyncWriter::Write(const media::AudioBus* data,
51 double volume, 65 double volume,
52 bool key_pressed, 66 bool key_pressed,
53 uint32 hardware_delay_bytes) { 67 uint32 hardware_delay_bytes) {
54 #if !defined(OS_ANDROID) 68 #if !defined(OS_ANDROID)
55 static const base::TimeDelta kLogDelayThreadhold = 69 static const base::TimeDelta kLogDelayThreadhold =
56 base::TimeDelta::FromMilliseconds(500); 70 base::TimeDelta::FromMilliseconds(500);
57 71
58 std::ostringstream oss; 72 std::ostringstream oss;
(...skipping 11 matching lines...) Expand all
70 } 84 }
71 } 85 }
72 if (!oss.str().empty()) { 86 if (!oss.str().empty()) {
73 MediaStreamManager::SendMessageToNativeLog(oss.str()); 87 MediaStreamManager::SendMessageToNativeLog(oss.str());
74 DVLOG(1) << oss.str(); 88 DVLOG(1) << oss.str();
75 } 89 }
76 90
77 last_write_time_ = base::Time::Now(); 91 last_write_time_ = base::Time::Now();
78 #endif 92 #endif
79 93
94 // Check that the renderer side has read data so that we don't overwrite.
95 // The renderer side sends a signal over the socket each time it has read
96 // data. Here, we count the number of reads we expect to have been done. When
97 // we reach |shared_memory_segment_count_|, we do
98 // (|shared_memory_segment_count_| / 2) socket receives, which normally is
99 // in queue. If we timeout, there's a problem with being able to read at the
100 // high enough pace, and we throw away the audio buffer.
101 if (expected_buffer_reads_ ==
henrika (OOO until Aug 14) 2015/08/28 07:56:25 Did you check this scheme for a segment count equa
Henrik Grunell 2015/08/28 12:21:57 Good point. I changed the for loop condition to sh
102 static_cast<int>(shared_memory_segment_count_)) {
103 size_t bytes_received = 0;
104 uint32 dummy = 0;
105 for (uint32 i = 0; i < shared_memory_segment_count_ / 2; ++i) {
106 bytes_received =
107 socket_->ReceiveWithTimeout(&dummy, sizeof(dummy), kReadCheckTimeout);
108 if (bytes_received != sizeof(dummy)) {
109 const std::string error_message =
110 "Verifying shared memory read timed out. Dropping audio data.";
111 LOG(ERROR) << error_message;
112 MediaStreamManager::SendMessageToNativeLog(error_message);
113 ++read_verification_timeouts_;
114 return;
115 }
116 --expected_buffer_reads_;
117 DCHECK_GE(expected_buffer_reads_, 0);
118 }
119 }
120
80 // Write audio parameters to shared memory. 121 // Write audio parameters to shared memory.
81 uint8* ptr = static_cast<uint8*>(shared_memory_->memory()); 122 uint8* ptr = static_cast<uint8*>(shared_memory_->memory());
82 ptr += current_segment_id_ * shared_memory_segment_size_; 123 ptr += current_segment_id_ * shared_memory_segment_size_;
83 media::AudioInputBuffer* buffer = 124 media::AudioInputBuffer* buffer =
84 reinterpret_cast<media::AudioInputBuffer*>(ptr); 125 reinterpret_cast<media::AudioInputBuffer*>(ptr);
85 buffer->params.volume = volume; 126 buffer->params.volume = volume;
86 buffer->params.size = audio_bus_memory_size_; 127 buffer->params.size = audio_bus_memory_size_;
87 buffer->params.key_pressed = key_pressed; 128 buffer->params.key_pressed = key_pressed;
88 buffer->params.hardware_delay_bytes = hardware_delay_bytes; 129 buffer->params.hardware_delay_bytes = hardware_delay_bytes;
89 buffer->params.id = next_buffer_id_++; 130 buffer->params.id = next_buffer_id_++;
90 131
91 // Copy data from the native audio layer into shared memory using pre- 132 // Copy data from the native audio layer into shared memory using pre-
92 // allocated audio buses. 133 // allocated audio buses.
93 media::AudioBus* audio_bus = audio_buses_[current_segment_id_]; 134 media::AudioBus* audio_bus = audio_buses_[current_segment_id_];
94 data->CopyTo(audio_bus); 135 data->CopyTo(audio_bus);
95 136
96 socket_->Send(&current_segment_id_, sizeof(current_segment_id_)); 137 socket_->Send(&current_segment_id_, sizeof(current_segment_id_));
97 138
98 if (++current_segment_id_ >= shared_memory_segment_count_) 139 if (++current_segment_id_ >= shared_memory_segment_count_)
99 current_segment_id_ = 0; 140 current_segment_id_ = 0;
141
142 ++expected_buffer_reads_;
143 DCHECK_LE(expected_buffer_reads_,
144 static_cast<int>(shared_memory_segment_count_));
100 } 145 }
101 146
102 void AudioInputSyncWriter::Close() { 147 void AudioInputSyncWriter::Close() {
103 socket_->Close(); 148 socket_->Close();
104 } 149 }
105 150
106 bool AudioInputSyncWriter::Init() { 151 bool AudioInputSyncWriter::Init() {
107 socket_.reset(new base::CancelableSyncSocket()); 152 socket_.reset(new base::CancelableSyncSocket());
108 foreign_socket_.reset(new base::CancelableSyncSocket()); 153 foreign_socket_.reset(new base::CancelableSyncSocket());
109 return base::CancelableSyncSocket::CreatePair(socket_.get(), 154 return base::CancelableSyncSocket::CreatePair(socket_.get(),
110 foreign_socket_.get()); 155 foreign_socket_.get());
111 } 156 }
112 157
113 bool AudioInputSyncWriter::PrepareForeignSocket( 158 bool AudioInputSyncWriter::PrepareForeignSocket(
114 base::ProcessHandle process_handle, 159 base::ProcessHandle process_handle,
115 base::SyncSocket::TransitDescriptor* descriptor) { 160 base::SyncSocket::TransitDescriptor* descriptor) {
116 return foreign_socket_->PrepareTransitDescriptor(process_handle, descriptor); 161 return foreign_socket_->PrepareTransitDescriptor(process_handle, descriptor);
117 } 162 }
118 163
119 164
120 } // namespace content 165 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698