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

Side by Side Diff: media/audio/audio_device_thread.cc

Issue 1487983002: Forward the number of skipped frames by the OS in audio playout. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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 "media/audio/audio_device_thread.h" 5 #include "media/audio/audio_device_thread.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 12 matching lines...) Expand all
23 // simpler than SimpleThread (no synchronization in Start, etc) and supports 23 // simpler than SimpleThread (no synchronization in Start, etc) and supports
24 // joining the thread handle asynchronously via a provided message loop even 24 // joining the thread handle asynchronously via a provided message loop even
25 // after the Thread object itself has been deleted. 25 // after the Thread object itself has been deleted.
26 class AudioDeviceThread::Thread 26 class AudioDeviceThread::Thread
27 : public PlatformThread::Delegate, 27 : public PlatformThread::Delegate,
28 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> { 28 public base::RefCountedThreadSafe<AudioDeviceThread::Thread> {
29 public: 29 public:
30 Thread(AudioDeviceThread::Callback* callback, 30 Thread(AudioDeviceThread::Callback* callback,
31 base::SyncSocket::Handle socket, 31 base::SyncSocket::Handle socket,
32 const char* thread_name, 32 const char* thread_name,
33 bool synchronized_buffers); 33 bool synchronized_buffers,
34 bool input);
34 35
35 void Start(); 36 void Start();
36 37
37 // Stops the thread. If |loop_for_join| is non-NULL, the function posts 38 // Stops the thread. If |loop_for_join| is non-NULL, the function posts
38 // a task to join (close) the thread handle later instead of waiting for 39 // a task to join (close) the thread handle later instead of waiting for
39 // the thread. If loop_for_join is NULL, then the function waits 40 // the thread. If loop_for_join is NULL, then the function waits
40 // synchronously for the thread to terminate. 41 // synchronously for the thread to terminate.
41 void Stop(base::MessageLoop* loop_for_join); 42 void Stop(base::MessageLoop* loop_for_join);
42 43
43 private: 44 private:
44 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>; 45 friend class base::RefCountedThreadSafe<AudioDeviceThread::Thread>;
45 ~Thread() override; 46 ~Thread() override;
46 47
47 // Overrides from PlatformThread::Delegate. 48 // Overrides from PlatformThread::Delegate.
48 void ThreadMain() override; 49 void ThreadMain() override;
49 50
50 // Runs the loop that reads from the socket. 51 // Runs the loop that reads from the socket.
51 void Run(); 52 void Run();
52 53
53 private: 54 private:
54 base::PlatformThreadHandle thread_; 55 base::PlatformThreadHandle thread_;
55 AudioDeviceThread::Callback* callback_; 56 AudioDeviceThread::Callback* callback_;
56 base::CancelableSyncSocket socket_; 57 base::CancelableSyncSocket socket_;
57 base::Lock callback_lock_; 58 base::Lock callback_lock_;
58 const char* thread_name_; 59 const char* thread_name_;
59 const bool synchronized_buffers_; 60 const bool synchronized_buffers_;
61 const bool input_;
60 62
61 DISALLOW_COPY_AND_ASSIGN(Thread); 63 DISALLOW_COPY_AND_ASSIGN(Thread);
62 }; 64 };
63 65
64 // AudioDeviceThread implementation 66 // AudioDeviceThread implementation
65 67
66 AudioDeviceThread::AudioDeviceThread() { 68 AudioDeviceThread::AudioDeviceThread() {
67 } 69 }
68 70
69 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_.get()); } 71 AudioDeviceThread::~AudioDeviceThread() { DCHECK(!thread_.get()); }
70 72
71 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback, 73 void AudioDeviceThread::Start(AudioDeviceThread::Callback* callback,
72 base::SyncSocket::Handle socket, 74 base::SyncSocket::Handle socket,
73 const char* thread_name, 75 const char* thread_name,
74 bool synchronized_buffers) { 76 bool synchronized_buffers,
77 bool input) {
75 base::AutoLock auto_lock(thread_lock_); 78 base::AutoLock auto_lock(thread_lock_);
76 CHECK(!thread_.get()); 79 CHECK(!thread_.get());
77 thread_ = new AudioDeviceThread::Thread( 80 thread_ = new AudioDeviceThread::Thread(callback, socket, thread_name,
78 callback, socket, thread_name, synchronized_buffers); 81 synchronized_buffers, input);
79 thread_->Start(); 82 thread_->Start();
80 } 83 }
81 84
82 void AudioDeviceThread::Stop(base::MessageLoop* loop_for_join) { 85 void AudioDeviceThread::Stop(base::MessageLoop* loop_for_join) {
83 base::AutoLock auto_lock(thread_lock_); 86 base::AutoLock auto_lock(thread_lock_);
84 if (thread_.get()) { 87 if (thread_.get()) {
85 thread_->Stop(loop_for_join); 88 thread_->Stop(loop_for_join);
86 thread_ = NULL; 89 thread_ = NULL;
87 } 90 }
88 } 91 }
89 92
90 bool AudioDeviceThread::IsStopped() { 93 bool AudioDeviceThread::IsStopped() {
91 base::AutoLock auto_lock(thread_lock_); 94 base::AutoLock auto_lock(thread_lock_);
92 return !thread_.get(); 95 return !thread_.get();
93 } 96 }
94 97
95 // AudioDeviceThread::Thread implementation 98 // AudioDeviceThread::Thread implementation
96 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback, 99 AudioDeviceThread::Thread::Thread(AudioDeviceThread::Callback* callback,
97 base::SyncSocket::Handle socket, 100 base::SyncSocket::Handle socket,
98 const char* thread_name, 101 const char* thread_name,
99 bool synchronized_buffers) 102 bool synchronized_buffers,
103 bool input)
100 : thread_(), 104 : thread_(),
101 callback_(callback), 105 callback_(callback),
102 socket_(socket), 106 socket_(socket),
103 thread_name_(thread_name), 107 thread_name_(thread_name),
104 synchronized_buffers_(synchronized_buffers) { 108 synchronized_buffers_(synchronized_buffers),
105 } 109 input_(input) {}
106 110
107 AudioDeviceThread::Thread::~Thread() { 111 AudioDeviceThread::Thread::~Thread() {
108 DCHECK(thread_.is_null()); 112 DCHECK(thread_.is_null());
109 } 113 }
110 114
111 void AudioDeviceThread::Thread::Start() { 115 void AudioDeviceThread::Thread::Start() {
112 base::AutoLock auto_lock(callback_lock_); 116 base::AutoLock auto_lock(callback_lock_);
113 DCHECK(thread_.is_null()); 117 DCHECK(thread_.is_null());
114 // This reference will be released when the thread exists. 118 // This reference will be released when the thread exists.
115 AddRef(); 119 AddRef();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 Run(); 162 Run();
159 163
160 // Release the reference for the thread. Note that after this, the Thread 164 // Release the reference for the thread. Note that after this, the Thread
161 // instance will most likely be deleted. 165 // instance will most likely be deleted.
162 Release(); 166 Release();
163 } 167 }
164 168
165 void AudioDeviceThread::Thread::Run() { 169 void AudioDeviceThread::Thread::Run() {
166 uint32 buffer_index = 0; 170 uint32 buffer_index = 0;
167 while (true) { 171 while (true) {
168 uint32 pending_data = 0; 172 if (input_) {
169 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data)); 173 uint32_t pending_data = 0;
170 if (bytes_read != sizeof(pending_data)) 174 size_t bytes_read = socket_.Receive(&pending_data, sizeof(pending_data));
171 break; 175 if (bytes_read != sizeof(pending_data))
176 break;
172 177
173 // kuint32max is a special signal which is returned after the browser
174 // stops the output device in response to a renderer side request.
175 //
176 // Avoid running Process() for the paused signal, we still need to update
177 // the buffer index if |synchronized_buffers_| is true though.
178 //
179 // See comments in AudioOutputController::DoPause() for details on why.
180 if (pending_data != kuint32max) {
181 base::AutoLock auto_lock(callback_lock_); 178 base::AutoLock auto_lock(callback_lock_);
182 if (callback_) 179 if (callback_)
183 callback_->Process(pending_data); 180 callback_->Process(pending_data);
181 } else {
182 uint64_t data = 0;
tommi (sloooow) - chröme 2015/12/01 13:34:25 if you don't want to use a struct, you can also us
DaleCurtis 2015/12/01 18:12:46 Long ago we were worried anything more than 4 byte
tommi (sloooow) - chröme 2015/12/01 19:03:31 Would it work to use the shared memory buffer inst
DaleCurtis 2015/12/01 20:06:48 That's what we do for input I believe.
Henrik Grunell 2015/12/03 17:01:06 Good to know. We can use the shared memory. Yes we
183 size_t bytes_read = socket_.Receive(&data, sizeof(data));
184 if (bytes_read != sizeof(data))
185 break;
186
187 uint32_t pending_data = static_cast<uint32_t>((data >> 32) & 0xffffffff);
188 uint32_t frames_skipped = static_cast<uint32_t>(data & 0xffffffff);
189
190 base::AutoLock auto_lock(callback_lock_);
191 if (callback_) {
192 if (frames_skipped > 0)
193 callback_->FramesSkipped(frames_skipped);
194
195 // kuint32max is a special signal which is returned after the browser
196 // stops the output device in response to a renderer side request.
197 //
198 // Avoid running Process() for the paused signal, we still need to
199 // update the buffer index if |synchronized_buffers_| is true though.
200 //
201 // See comments in AudioOutputController::DoPause() for details on why.
202 if (pending_data != kuint32max)
203 callback_->Process(pending_data);
204 }
184 } 205 }
185 206
186 // The usage of |synchronized_buffers_| differs between input and output 207 // The usage of |synchronized_buffers_| differs between input and output
187 // cases. 208 // cases.
188 // Input: 209 // Input:
189 // Let the other end know that we have read data, so that it can verify 210 // Let the other end know that we have read data, so that it can verify
190 // it doesn't overwrite any data before read. The |buffer_index| value is 211 // it doesn't overwrite any data before read. The |buffer_index| value is
191 // not used. For more details, see AudioInputSyncWriter::Write(). 212 // not used. For more details, see AudioInputSyncWriter::Write().
192 // Output: 213 // Output:
193 // Let the other end know which buffer we just filled. The |buffer_index| is 214 // Let the other end know which buffer we just filled. The |buffer_index| is
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 } 246 }
226 247
227 AudioDeviceThread::Callback::~Callback() {} 248 AudioDeviceThread::Callback::~Callback() {}
228 249
229 void AudioDeviceThread::Callback::InitializeOnAudioThread() { 250 void AudioDeviceThread::Callback::InitializeOnAudioThread() {
230 MapSharedMemory(); 251 MapSharedMemory();
231 CHECK(shared_memory_.memory()); 252 CHECK(shared_memory_.memory());
232 } 253 }
233 254
234 } // namespace media. 255 } // namespace media.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698