static int ca_thread_func (void *arg) { struct bb10_stream* stream = (struct bb10_stream *) arg; int size = stream->ca_buf_size; unsigned long nframes = stream->ca_frames; void *user_data = stream->user_data; /* Buffer to fill for PJMEDIA */ char *buf = stream->ca_buf; pj_timestamp tstamp; int result; int policy; struct sched_param param; TRACE_((THIS_FILE, "ca_thread_func: size = %d ", size)); if (pthread_getschedparam(pthread_self(), &policy, ¶m) == 0) { param.sched_priority = 18; pthread_setschedparam (pthread_self(), policy, ¶m); } pj_bzero (buf, size); tstamp.u64 = 0; /* Final init now the thread has started */ if ((result = snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE)) < 0) { TRACE_((THIS_FILE, "ca_thread_func failed prepare = %d", result)); return PJ_SUCCESS; } while (!stream->quit) { pjmedia_frame frame; //pj_bzero (buf, size); /* read the input device */ result = snd_pcm_plugin_read(stream->ca_pcm, buf,size); if(result <0 || result != size) { /* We expect result to be size (640) * It's not so we have to read the status error and "prepare" * the channel. This usually happens when output audio routing * has been changed by another thread. * We won't "continue", instead just do what we can and leave * the end of the loop to write what's in the buffer. Not entirely * correct but saves a potential underrun in PJMEDIA */ PJ_LOG (4,(THIS_FILE, "snd_pcm_plugin_read ERROR read = %d required = %d", result,size)); snd_pcm_channel_status_t status; status.channel = SND_PCM_CHANNEL_CAPTURE; if ((result = snd_pcm_plugin_status (stream->ca_pcm, &status)) < 0) { /* Should not fail but all we can do is continue */ PJ_LOG(4,(THIS_FILE, "capture: snd_pcm_plugin_status ret = %d", result)); } else { /* RIM say these are the errors that we should "prepare" * after */ if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN || status.status == SND_PCM_STATUS_ERROR) { if (snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE) < 0) { PJ_LOG (4,(THIS_FILE, "overrun: capture channel prepare error")); } } } } if (stream->quit) break; /* Write the capture audio data to PJMEDIA */ frame.type = PJMEDIA_FRAME_TYPE_AUDIO; frame.buf = (void *) buf; frame.size = size; frame.timestamp.u64 = tstamp.u64; frame.bit_info = 0; result = stream->ca_cb (user_data, &frame); if (result != PJ_SUCCESS || stream->quit) break; tstamp.u64 += nframes; } flush_capture(stream); TRACE_((THIS_FILE, "ca_thread_func: Stopped")); return PJ_SUCCESS; }
static int ca_thread_func (void *arg) { struct bb10_stream* stream = (struct bb10_stream *) arg; int size = stream->ca_buf_size; unsigned long nframes = stream->ca_frames; void *user_data = stream->user_data; /* Buffer to fill for PJMEDIA */ char *buf = stream->ca_buf; pj_timestamp tstamp; int result; struct sched_param param; pthread_t *thid; TRACE_((THIS_FILE, "ca_thread_func: size = %d ", size)); thid = (pthread_t*) pj_thread_get_os_handle (pj_thread_this()); param.sched_priority = sched_get_priority_max (SCHED_RR); result = pthread_setschedparam (*thid, SCHED_RR, ¶m); if (result) { if (result == EPERM) { PJ_LOG (4,(THIS_FILE, "Unable to increase thread priority, " "root access needed.")); } else { PJ_LOG (4,(THIS_FILE, "Unable to increase thread priority, " "error: %d", result)); } } pj_bzero (buf, size); tstamp.u64 = 0; /* Final init now the thread has started */ if ((result = snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE)) < 0) { close_capture_pcm(stream); TRACE_((THIS_FILE, "ca_thread_func failed prepare = %d", result)); return PJ_SUCCESS; } while (!stream->quit) { pjmedia_frame frame; pj_bzero (buf, size); result = snd_pcm_plugin_read(stream->ca_pcm, buf,size); if(result <0 || result != size) { snd_pcm_channel_status_t status; if (snd_pcm_plugin_status (stream->ca_pcm, &status) < 0) { PJ_LOG (4,(THIS_FILE, "overrun: capture channel status " "error")); continue; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN) { if (snd_pcm_plugin_prepare (stream->ca_pcm, SND_PCM_CHANNEL_CAPTURE) < 0) { PJ_LOG (4,(THIS_FILE, "overrun: capture channel prepare " "error")); continue; } } } if (stream->quit) break; frame.type = PJMEDIA_FRAME_TYPE_AUDIO; frame.buf = (void *) buf; frame.size = size; frame.timestamp.u64 = tstamp.u64; frame.bit_info = 0; result = stream->ca_cb (user_data, &frame); if (result != PJ_SUCCESS || stream->quit) break; tstamp.u64 += nframes; } flush_capture(stream); close_capture_pcm(stream); TRACE_((THIS_FILE, "ca_thread_func: Stopped")); return PJ_SUCCESS; }