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 "ppapi/shared_impl/ppb_audio_shared.h" | 5 #include "ppapi/shared_impl/ppb_audio_shared.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "ppapi/shared_impl/ppapi_globals.h" | 8 #include "ppapi/shared_impl/ppapi_globals.h" |
9 | 9 |
10 using base::subtle::Atomic32; | 10 using base::subtle::Atomic32; |
11 | 11 |
12 namespace ppapi { | 12 namespace ppapi { |
13 | 13 |
| 14 #if defined(OS_NACL) |
| 15 namespace { |
| 16 // Because this is static, the function pointers will be NULL initially. |
| 17 PP_ThreadFunctions thread_functions; |
| 18 } |
| 19 #endif // defined(OS_NACL) |
| 20 |
14 // FIXME: The following two functions (TotalSharedMemorySizeInBytes, | 21 // FIXME: The following two functions (TotalSharedMemorySizeInBytes, |
15 // SetActualDataSizeInBytes) are copied from audio_util.cc. | 22 // SetActualDataSizeInBytes) are copied from audio_util.cc. |
16 // Remove these functions once a minimal media library is provided for them. | 23 // Remove these functions once a minimal media library is provided for them. |
17 // code.google.com/p/chromium/issues/detail?id=123203 | 24 // code.google.com/p/chromium/issues/detail?id=123203 |
18 | 25 |
19 uint32 TotalSharedMemorySizeInBytes(uint32 packet_size) { | 26 uint32 TotalSharedMemorySizeInBytes(uint32 packet_size) { |
20 // Need to reserve extra 4 bytes for size of data. | 27 // Need to reserve extra 4 bytes for size of data. |
21 return packet_size + sizeof(Atomic32); | 28 return packet_size + sizeof(Atomic32); |
22 } | 29 } |
23 | 30 |
24 void SetActualDataSizeInBytes(base::SharedMemory* shared_memory, | 31 void SetActualDataSizeInBytes(base::SharedMemory* shared_memory, |
25 uint32 shared_memory_size, | 32 uint32 shared_memory_size, |
26 uint32 actual_data_size) { | 33 uint32 actual_data_size) { |
27 char* ptr = static_cast<char*>(shared_memory->memory()) + shared_memory_size; | 34 char* ptr = static_cast<char*>(shared_memory->memory()) + shared_memory_size; |
28 DCHECK_EQ(0u, reinterpret_cast<size_t>(ptr) & 3); | 35 DCHECK_EQ(0u, reinterpret_cast<size_t>(ptr) & 3); |
29 | 36 |
30 // Set actual data size at the end of the buffer. | 37 // Set actual data size at the end of the buffer. |
31 base::subtle::Release_Store(reinterpret_cast<volatile Atomic32*>(ptr), | 38 base::subtle::Release_Store(reinterpret_cast<volatile Atomic32*>(ptr), |
32 actual_data_size); | 39 actual_data_size); |
33 } | 40 } |
34 | 41 |
35 const int PPB_Audio_Shared::kPauseMark = -1; | 42 const int PPB_Audio_Shared::kPauseMark = -1; |
36 | 43 |
37 PPB_Audio_Shared::PPB_Audio_Shared() | 44 PPB_Audio_Shared::PPB_Audio_Shared() |
38 : playing_(false), | 45 : playing_(false), |
39 shared_memory_size_(0), | 46 shared_memory_size_(0), |
| 47 #if defined(OS_NACL) |
| 48 thread_id_(0), |
| 49 thread_active_(false), |
| 50 #endif |
40 callback_(NULL), | 51 callback_(NULL), |
41 user_data_(NULL) { | 52 user_data_(NULL) { |
42 } | 53 } |
43 | 54 |
44 PPB_Audio_Shared::~PPB_Audio_Shared() { | 55 PPB_Audio_Shared::~PPB_Audio_Shared() { |
45 StopThread(); | 56 StopThread(); |
46 } | 57 } |
47 | 58 |
48 void PPB_Audio_Shared::SetCallback(PPB_Audio_Callback callback, | 59 void PPB_Audio_Shared::SetCallback(PPB_Audio_Callback callback, |
49 void* user_data) { | 60 void* user_data) { |
50 callback_ = callback; | 61 callback_ = callback; |
51 user_data_ = user_data; | 62 user_data_ = user_data; |
52 } | 63 } |
53 | 64 |
54 void PPB_Audio_Shared::SetStartPlaybackState() { | 65 void PPB_Audio_Shared::SetStartPlaybackState() { |
55 DCHECK(!playing_); | 66 DCHECK(!playing_); |
| 67 #if !defined(OS_NACL) |
56 DCHECK(!audio_thread_.get()); | 68 DCHECK(!audio_thread_.get()); |
57 | 69 #else |
| 70 DCHECK(!thread_active_); |
| 71 #endif |
58 // If the socket doesn't exist, that means that the plugin has started before | 72 // If the socket doesn't exist, that means that the plugin has started before |
59 // the browser has had a chance to create all the shared memory info and | 73 // the browser has had a chance to create all the shared memory info and |
60 // notify us. This is a common case. In this case, we just set the playing_ | 74 // notify us. This is a common case. In this case, we just set the playing_ |
61 // flag and the playback will automatically start when that data is available | 75 // flag and the playback will automatically start when that data is available |
62 // in SetStreamInfo. | 76 // in SetStreamInfo. |
63 playing_ = true; | 77 playing_ = true; |
64 StartThread(); | 78 StartThread(); |
65 } | 79 } |
66 | 80 |
67 void PPB_Audio_Shared::SetStopPlaybackState() { | 81 void PPB_Audio_Shared::SetStopPlaybackState() { |
(...skipping 16 matching lines...) Expand all Loading... |
84 "Failed to map shared memory for PPB_Audio_Shared."); | 98 "Failed to map shared memory for PPB_Audio_Shared."); |
85 } | 99 } |
86 | 100 |
87 StartThread(); | 101 StartThread(); |
88 } | 102 } |
89 | 103 |
90 void PPB_Audio_Shared::StartThread() { | 104 void PPB_Audio_Shared::StartThread() { |
91 // Don't start the thread unless all our state is set up correctly. | 105 // Don't start the thread unless all our state is set up correctly. |
92 if (!playing_ || !callback_ || !socket_.get() || !shared_memory_->memory()) | 106 if (!playing_ || !callback_ || !socket_.get() || !shared_memory_->memory()) |
93 return; | 107 return; |
| 108 // Clear contents of shm buffer before starting audio thread. This will |
| 109 // prevent a burst of static if for some reason the audio thread doesn't |
| 110 // start up quickly enough. |
| 111 memset(shared_memory_->memory(), 0, shared_memory_size_); |
| 112 #if !defined(OS_NACL) |
94 DCHECK(!audio_thread_.get()); | 113 DCHECK(!audio_thread_.get()); |
95 audio_thread_.reset(new base::DelegateSimpleThread( | 114 audio_thread_.reset(new base::DelegateSimpleThread( |
96 this, "plugin_audio_thread")); | 115 this, "plugin_audio_thread")); |
97 audio_thread_->Start(); | 116 audio_thread_->Start(); |
| 117 #else |
| 118 // Use NaCl's special API for IRT code that creates threads that call back |
| 119 // into user code. |
| 120 if (NULL == thread_functions.thread_create || |
| 121 NULL == thread_functions.thread_join) |
| 122 return; |
| 123 |
| 124 int result = thread_functions.thread_create(&thread_id_, CallRun, this); |
| 125 DCHECK_EQ(result, 0); |
| 126 thread_active_ = true; |
| 127 #endif |
98 } | 128 } |
99 | 129 |
100 void PPB_Audio_Shared::StopThread() { | 130 void PPB_Audio_Shared::StopThread() { |
101 // Shut down the socket to escape any hanging |Receive|s. | 131 // Shut down the socket to escape any hanging |Receive|s. |
102 if (socket_.get()) | 132 if (socket_.get()) |
103 socket_->Shutdown(); | 133 socket_->Shutdown(); |
| 134 #if !defined(OS_NACL) |
104 if (audio_thread_.get()) { | 135 if (audio_thread_.get()) { |
105 audio_thread_->Join(); | 136 audio_thread_->Join(); |
106 audio_thread_.reset(); | 137 audio_thread_.reset(); |
107 } | 138 } |
| 139 #else |
| 140 if (thread_active_) { |
| 141 int result = thread_functions.thread_join(thread_id_); |
| 142 DCHECK_EQ(0, result); |
| 143 thread_active_ = false; |
| 144 } |
| 145 #endif |
108 } | 146 } |
109 | 147 |
| 148 #if defined(OS_NACL) |
| 149 // static |
| 150 void PPB_Audio_Shared::SetThreadFunctions( |
| 151 const struct PP_ThreadFunctions* functions) { |
| 152 DCHECK(thread_functions.thread_create == NULL); |
| 153 DCHECK(thread_functions.thread_join == NULL); |
| 154 thread_functions = *functions; |
| 155 } |
| 156 |
| 157 // static |
| 158 void PPB_Audio_Shared::CallRun(void* self) { |
| 159 PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self); |
| 160 audio->Run(); |
| 161 } |
| 162 #endif |
| 163 |
110 void PPB_Audio_Shared::Run() { | 164 void PPB_Audio_Shared::Run() { |
111 int pending_data; | 165 int pending_data; |
112 void* buffer = shared_memory_->memory(); | 166 void* buffer = shared_memory_->memory(); |
113 | 167 |
114 while (sizeof(pending_data) == | 168 while (sizeof(pending_data) == |
115 socket_->Receive(&pending_data, sizeof(pending_data)) && | 169 socket_->Receive(&pending_data, sizeof(pending_data)) && |
116 pending_data != kPauseMark) { | 170 pending_data != kPauseMark) { |
117 callback_(buffer, shared_memory_size_, user_data_); | 171 callback_(buffer, shared_memory_size_, user_data_); |
118 | 172 |
119 // Let the host know we are done. | 173 // Let the host know we are done. |
120 SetActualDataSizeInBytes(shared_memory_.get(), shared_memory_size_, | 174 SetActualDataSizeInBytes(shared_memory_.get(), shared_memory_size_, |
121 shared_memory_size_); | 175 shared_memory_size_); |
122 } | 176 } |
123 } | 177 } |
124 | 178 |
125 } // namespace ppapi | 179 } // namespace ppapi |
OLD | NEW |