22 #include "audio_capture_manager.h"
26 #include "rmfAudioCapture.h"
28 using namespace audiocapturemgr;
30 const unsigned int QUEUE_CHECK_LOOP_TIME_US = 1000 * 50;
31 static const size_t DEFAULT_FIFO_SIZE = 64 * 1024;
32 static const size_t DEFAULT_THRESHOLD = 8 * 1024;
33 static const unsigned int DEFAULT_DELAY_COMPENSATION = 0;
34 static const unsigned int MAX_QMGR_BUFFER_DURATION_S = 30;
36 static void * q_mgr_thread_launcher(
void * data)
45 ((
q_mgr *)context)->add_data((
unsigned char*)buf, size);
50 inline void q_mgr::lock(pthread_mutex_t &mutex)
52 REPORT_IF_UNEQUAL(0, pthread_mutex_lock(&mutex));
54 inline void q_mgr::unlock(pthread_mutex_t &mutex)
56 REPORT_IF_UNEQUAL(0, pthread_mutex_unlock(&mutex));
58 inline void q_mgr::notify_data_ready()
63 DEBUG(
"Posting semaphore.\n");
64 REPORT_IF_UNEQUAL(0, sem_post(&m_sem));
65 m_notify_new_data =
false;
68 void q_mgr::swap_queues()
70 if(!m_current_outgoing_q->empty())
72 WARN(
"Outgoing queue wasn't empty. Flushing it now.\n");
73 flush_queue(m_current_outgoing_q);
75 std::vector <audio_buffer *> * temp = m_current_incoming_q;
76 m_current_incoming_q = m_current_outgoing_q;
77 m_current_outgoing_q = temp;
80 void q_mgr::flush_queue(std::vector <audio_buffer *> *q)
82 DEBUG(
"Flushing queue.\n");
83 std::vector <audio_buffer *>::iterator iter;
84 for(iter = q->begin(); iter != q->end(); iter++)
91 namespace audiocapturemgr
93 void get_individual_audio_parameters(
const audio_properties_t &audio_props,
unsigned int &sampling_rate,
unsigned int &bits_per_sample,
unsigned int &num_channels)
99 switch(audio_props.sampling_frequency)
102 sampling_rate = 16000;
105 sampling_rate = 24000;
108 sampling_rate = 32000;
111 sampling_rate = 44100;
114 sampling_rate = 48000;
117 ERROR(
"Bad sampling rate: 0x%x\n", audio_props.sampling_frequency);
121 switch(audio_props.format)
124 bits_per_sample = 16; num_channels = 2;
127 bits_per_sample = 24; num_channels = 2;
130 bits_per_sample = 16; num_channels = 1;
133 bits_per_sample = 16; num_channels = 1;
136 bits_per_sample = 16; num_channels = 1;
139 bits_per_sample = 24; num_channels = 6;
142 ERROR(
"Unknown format 0x%x\n", audio_props.format);
148 unsigned int bits_per_sample = 0;
149 unsigned int sampling_rate= 0;
150 unsigned int num_channels = 0;
151 get_individual_audio_parameters(audio_props, sampling_rate, bits_per_sample, num_channels);
152 unsigned int data_rate = bits_per_sample * sampling_rate * num_channels / 8;
153 INFO(
"Audio properties: %dkHz, %d bit, %d channel, byte rate: %d\n", sampling_rate, bits_per_sample, num_channels, data_rate);
157 std::string get_suffix(
unsigned int ticker)
159 std::ostringstream stream;
161 std::string outstring = stream.str();
166 q_mgr::q_mgr() : m_inflow_byte_counter(0), m_num_clients(0), m_notify_new_data(false), m_started(false), m_device_handle(NULL), m_stop_data_monitor(true)
168 INFO(
"Creating instance 0x%p.\n",
static_cast <void *
>(
this));
169 pthread_mutexattr_t mutex_attribute;
170 REPORT_IF_UNEQUAL(0, pthread_mutexattr_init(&mutex_attribute));
171 REPORT_IF_UNEQUAL(0, pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_ERRORCHECK));
172 REPORT_IF_UNEQUAL(0, pthread_mutex_init(&m_q_mutex, &mutex_attribute));
173 REPORT_IF_UNEQUAL(0, pthread_mutex_init(&m_client_mutex, &mutex_attribute));
174 REPORT_IF_UNEQUAL(0, sem_init(&m_sem, 0, 0));
175 m_current_incoming_q =
new std::vector <audio_buffer *>;
176 m_current_outgoing_q =
new std::vector <audio_buffer *>;
177 m_processing_thread_alive =
false;
179 REPORT_IF_UNEQUAL(0, pthread_create(&m_thread, NULL, q_mgr_thread_launcher, (
void *)
this));
182 INFO(
"open() result is 0x%x\n", ret);
186 m_audio_properties.format = settings.
format;
187 m_audio_properties.sampling_frequency = settings.
samplingFreq;
188 m_audio_properties.fifo_size = DEFAULT_FIFO_SIZE;
189 m_audio_properties.threshold = DEFAULT_THRESHOLD;
190 m_audio_properties.delay_compensation_ms = DEFAULT_DELAY_COMPENSATION;
191 m_bytes_per_second = calculate_data_rate(m_audio_properties);
192 m_max_queue_size = (MAX_QMGR_BUFFER_DURATION_S * m_bytes_per_second) / m_audio_properties.threshold;
193 INFO(
"Max incoming queue size is now %d\n", m_max_queue_size);
197 INFO(
"Deleting instance 0x%p.\n",
static_cast <void *
>(
this));
198 if(
true == m_started)
202 if(NULL != m_device_handle)
205 INFO(
"close() result is 0x%x\n", ret);
206 m_device_handle = NULL;
210 m_processing_thread_alive =
false;
211 REPORT_IF_UNEQUAL(0, sem_post(&m_sem));
212 REPORT_IF_UNEQUAL(0, pthread_join(m_thread, NULL));
213 REPORT_IF_UNEQUAL(0, sem_destroy(&m_sem));
214 REPORT_IF_UNEQUAL(0, pthread_mutex_destroy(&m_q_mutex));
215 REPORT_IF_UNEQUAL(0, pthread_mutex_destroy(&m_client_mutex));
216 flush_queue(m_current_incoming_q);
217 flush_queue(m_current_outgoing_q);
218 delete m_current_incoming_q;
219 delete m_current_outgoing_q;
227 if(0 == memcmp(&m_audio_properties, &in_properties,
sizeof(m_audio_properties)))
234 if((racFormat_eMax <= in_properties.format) || (racFreq_eMax <= in_properties.sampling_frequency))
236 ERROR(
"Bad parameters. Format: 0x%x, sampling freq: 0x%x\n", in_properties.format, in_properties.sampling_frequency);
241 m_audio_properties = in_properties;
244 m_bytes_per_second = calculate_data_rate(m_audio_properties);
245 m_max_queue_size = (MAX_QMGR_BUFFER_DURATION_S * m_bytes_per_second) / m_audio_properties.threshold;
246 INFO(
"Max incoming queue size is now %d\n", m_max_queue_size);
249 lock(m_client_mutex);
250 bool needs_restart = m_started;
255 std::vector<audio_capture_client *>::iterator iter;
256 for(iter = m_clients.begin(); iter != m_clients.end(); iter++)
258 (*iter)->notify_event(AUDIO_SETTINGS_CHANGE_EVENT);
262 INFO(
"Restarting audio after settings change.\n");
266 unlock(m_client_mutex);
272 out_properties = m_audio_properties;
279 out_properties.format = settings.
format;
280 out_properties.sampling_frequency = settings.
samplingFreq;
281 out_properties.fifo_size = settings.
fifoSize;
282 out_properties.threshold = settings.
threshold;
287 return m_bytes_per_second;
292 DEBUG(
"Adding data.\n");
295 if(m_max_queue_size < m_current_incoming_q->size())
297 WARN(
"Incoming queue size over limit. Flushing.\n");
298 flush_queue(m_current_incoming_q);
300 m_current_incoming_q->push_back(temp);
304 m_inflow_byte_counter += size;
308 DEBUG(
"Launching.\n");
309 m_processing_thread_alive =
true;
310 while(m_processing_thread_alive)
317 DEBUG(
"Enter processing loop.\n");
318 while(!m_current_outgoing_q->empty())
322 DEBUG(
"No data in outgoing queue.\n");
325 if(!m_current_incoming_q->empty())
327 DEBUG(
"Incoming queue has buffers. Swapping them.\n");
334 m_notify_new_data =
true;
336 DEBUG(
"Incoming queue is empty as well. Waiting until a buffer arrives.\n");
337 if(0 != sem_wait(&m_sem))
339 ERROR(
"Critical semaphore error. Exiting\n");
343 if(!m_processing_thread_alive)
349 DEBUG(
"New data available in incoming queue. Swapping them.\n");
358 void q_mgr::update_buffer_references()
360 std::vector <audio_buffer *>::iterator buffer_iter;
362 for(buffer_iter = m_current_outgoing_q->begin(); buffer_iter != m_current_outgoing_q->end(); buffer_iter++)
369 void q_mgr::process_data()
371 DEBUG(
"Processing %d buffers of data.\n", m_current_outgoing_q->size());
373 lock(m_client_mutex);
375 update_buffer_references();
377 std::vector <audio_buffer *>::iterator buffer_iter;
378 for(buffer_iter = m_current_outgoing_q->begin(); buffer_iter != m_current_outgoing_q->end(); buffer_iter++)
380 std::vector <audio_capture_client *>::iterator client_iter;
381 for(client_iter = m_clients.begin(); client_iter != m_clients.end(); client_iter++)
383 (*client_iter)->data_callback(*buffer_iter);
386 unlock(m_client_mutex);
387 m_current_outgoing_q->clear();
393 lock(m_client_mutex);
394 if(std::find(m_clients.begin(), m_clients.end(), client) == m_clients.end())
396 m_clients.push_back(client);
397 m_num_clients = m_clients.size();
398 if(1 == m_num_clients)
405 INFO(
"Will not register client as it is already present.\n");
407 unlock(m_client_mutex);
408 INFO(
"Total clients: %d.\n", m_num_clients);
414 lock(m_client_mutex);
415 m_clients.erase(std::remove(m_clients.begin(), m_clients.end(), client), m_clients.end());
416 m_num_clients = m_clients.size();
417 if(0 == m_num_clients)
421 unlock(m_client_mutex);
422 INFO(
"Total clients: %d.\n", m_num_clients);
426 void q_mgr::flush_system()
433 flush_queue(m_current_incoming_q);
434 while(!m_current_outgoing_q->empty())
436 usleep(QUEUE_CHECK_LOOP_TIME_US);
443 INFO(
"Format 0x%x, sampling freq: 0x%x, FIFO size: %d, threshold: %d, delay compensation: %d\n",
447 void q_mgr::data_monitor()
449 INFO(
"data_monitor thread has launched.\n");
450 unsigned int saved_byte_counter = 0;
451 bool is_stalled =
false;
452 std::unique_lock<std::mutex> wlock(m_data_monitor_mutex);
453 while(
false == m_stop_data_monitor)
455 auto ret = m_data_monitor_cv.wait_for(wlock, std::chrono::seconds(5), [
this](){
return m_stop_data_monitor;});
458 if(saved_byte_counter == m_inflow_byte_counter)
460 if(
false == is_stalled)
462 WARN(
"Data inflow has stalled at %u bytes for instance 0x%p.\n", saved_byte_counter,
static_cast <void *
>(
this));
470 saved_byte_counter = m_inflow_byte_counter;
471 if(
true == is_stalled)
473 INFO(
"Data inflow has resumed for instance 0x%p.\n",
static_cast <void *
>(
this));
479 INFO(
"data_monitor thread exiting.\n");
484 if(
true == m_started)
486 WARN(
"Looks like device was already started.\n");
490 m_inflow_byte_counter = 0;
497 settings.
fifoSize = m_audio_properties.fifo_size;
498 settings.
threshold = m_audio_properties.threshold;
500 settings.
format = m_audio_properties.format;
501 settings.
samplingFreq = m_audio_properties.sampling_frequency;
503 log_settings(settings);
506 INFO(
"start() result is 0x%x\n", ret);
509 std::unique_lock<std::mutex> wlock(m_data_monitor_mutex);
510 m_stop_data_monitor =
false;
511 m_data_monitor_thread = std::thread(&q_mgr::data_monitor,
this);
517 if(
false == m_started)
519 WARN(
"Looks like device is already stopped.\n");
524 std::unique_lock<std::mutex> wlock(m_data_monitor_mutex);
525 m_stop_data_monitor =
true;
527 m_data_monitor_cv.notify_all();
528 m_data_monitor_thread.join();
531 INFO(
"stop() result is 0x%x\n", ret);
536 void audio_capture_client::release_buffer(
audio_buffer *ptr)
541 int audio_capture_client::data_callback(
audio_buffer *buf)
546 audio_capture_client::audio_capture_client(
q_mgr * manager): m_priority(0), m_manager(manager)
548 pthread_mutexattr_t mutex_attribute;
549 REPORT_IF_UNEQUAL(0, pthread_mutexattr_init(&mutex_attribute));
550 REPORT_IF_UNEQUAL(0, pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_ERRORCHECK));
551 REPORT_IF_UNEQUAL(0, pthread_mutex_init(&m_mutex, &mutex_attribute));
553 audio_capture_client::~audio_capture_client()
555 REPORT_IF_UNEQUAL(0, pthread_mutex_destroy(&m_mutex));
558 void audio_capture_client::set_manager(
q_mgr *mgr)
573 void audio_capture_client::get_default_audio_properties(
audio_properties_t &properties)
578 int audio_capture_client::start()
583 int audio_capture_client::stop()
588 void audio_capture_client::lock()
590 REPORT_IF_UNEQUAL(0, pthread_mutex_lock(&m_mutex));
593 void audio_capture_client::unlock()
595 REPORT_IF_UNEQUAL(0, pthread_mutex_unlock(&m_mutex));