/** * Set up capture based on the audio sample waverec except we use VoIP parameters */ static int capture(circular_buffer_t* circular_buffer) { // Re-usable buffer for capture char *record_buffer; record_buffer = (char*) malloc(g_frame_size_c); // Some diagnostic variables int failed = 0; int totalRead = 0; snd_pcm_channel_status_t status; status.channel = SND_PCM_CHANNEL_CAPTURE; // Loop until stopAudio() flags us while (g_execute_audio) { // This blocking read appears to take much longer than 20ms on the simulator // but it never fails and always returns 160 bytes int read = snd_pcm_plugin_read(g_pcm_handle_c, record_buffer, g_frame_size_c); if (read < 0 || read != g_frame_size_c) { failed++; fprintf(stderr,"CAPTURE FAILURE: snd_pcm_plugin_read: %d requested = %d\n",read,g_frame_size_c); if (snd_pcm_plugin_status(g_pcm_handle_c, &status) < 0) { fprintf(stderr, "Capture channel status error: %d\n",status.status); } else { if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN || status.status == SND_PCM_STATUS_CHANGE || status.status == SND_PCM_STATUS_ERROR) { fprintf(stderr, "CAPTURE FAILURE:snd_pcm_plugin_status: = %d \n",status.status); if (snd_pcm_plugin_prepare (g_pcm_handle_c, SND_PCM_CHANNEL_CAPTURE) < 0) { fprintf (stderr, "Capture channel prepare error 1 %d\n",status.status); exit (1); } } } } else { totalRead += read; // On simulator always room in the circular buffer if (!writeToCircularBuffer(circular_buffer, record_buffer, g_frame_size_c)) { failed++; } } capture_ready = true; } fprintf(stderr,"CAPTURE EXIT BEGIN\n"); (void) snd_pcm_plugin_flush(g_pcm_handle_c, SND_PCM_CHANNEL_CAPTURE); //(void)snd_mixer_close (mixer_handle); (void) snd_pcm_close(g_pcm_handle_c); audio_manager_free_handle(g_audio_manager_handle_c); // IMPORTANT NB: You only get failed on capture if the play loop has exited hence the circular buffer fills. This is with the simulator fprintf(stderr, "CAPTURE EXIT Total Bytes read = %d failed = %d\n",totalRead,failed); free(record_buffer); return 0; }
qint64 QnxAudioInput::read(char *data, qint64 len) { int errorCode = 0; QByteArray tempBuffer(m_periodSize, 0); const int actualRead = snd_pcm_plugin_read(m_pcmHandle, tempBuffer.data(), m_periodSize); if (actualRead < 1) { snd_pcm_channel_status_t status; memset(&status, 0, sizeof(status)); status.channel = SND_PCM_CHANNEL_CAPTURE; if ((errorCode = snd_pcm_plugin_status(m_pcmHandle, &status)) < 0) { qWarning("QnxAudioInput: read error, couldn't get plugin status (0x%x)", -errorCode); close(); setError(QAudio::FatalError); setState(QAudio::StoppedState); return -1; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_OVERRUN) { if ((errorCode = snd_pcm_plugin_prepare(m_pcmHandle, SND_PCM_CHANNEL_CAPTURE)) < 0) { qWarning("QnxAudioInput: read error, couldn't prepare plugin (0x%x)", -errorCode); close(); setError(QAudio::FatalError); setState(QAudio::StoppedState); return -1; } } } else { setError(QAudio::NoError); setState(QAudio::ActiveState); } if (m_volume < 1.0f) QAudioHelperInternal::qMultiplySamples(m_volume, m_format, tempBuffer.data(), tempBuffer.data(), actualRead); m_bytesRead += actualRead; if (m_pullMode) { m_audioSource->write(tempBuffer.data(), actualRead); } else { memcpy(data, tempBuffer.data(), qMin(static_cast<qint64>(actualRead), len)); } m_bytesAvailable = 0; return actualRead; }
static int process_read(snd_pcm_t* hRecord) { int nread = snd_pcm_plugin_read(hRecord, outputdata, (size_t)fragsize); if (nread != fragsize) { cli_print("snd_pcm_plugin_read: %s", snd_strerror(nread)); return 1; } else { if (fwrite((void*)outputdata, (size_t)1, (size_t)nread, outputfile) != (size_t)nread) { cli_print("fwrite: %s", strerror(errno)); return 1; } else { outputdatasize += nread; } } return 0; }
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 ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) { qsa_data* data=(qsa_data*)device->ExtraData; char* read_ptr; snd_pcm_channel_status_t status; fd_set rfds; int selectret; struct timeval timeout; int bytes_read; ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); ALint len=samples*frame_size; int rstatus; read_ptr=buffer; while (len>0) { FD_ZERO(&rfds); FD_SET(data->audio_fd, &rfds); timeout.tv_sec=2; timeout.tv_usec=0; /* Select also works like time slice to OS */ bytes_read=0; selectret=select(data->audio_fd+1, &rfds, NULL, NULL, &timeout); switch (selectret) { case -1: aluHandleDisconnect(device); return ALC_INVALID_DEVICE; case 0: break; default: if (FD_ISSET(data->audio_fd, &rfds)) { bytes_read=snd_pcm_plugin_read(data->pcmHandle, read_ptr, len); break; } break; } if (bytes_read<=0) { if ((errno==EAGAIN) || (errno==EWOULDBLOCK)) { continue; } memset(&status, 0, sizeof (status)); status.channel=SND_PCM_CHANNEL_CAPTURE; snd_pcm_plugin_status(data->pcmHandle, &status); /* we need to reinitialize the sound channel if we've overrun the buffer */ if ((status.status==SND_PCM_STATUS_OVERRUN) || (status.status==SND_PCM_STATUS_READY)) { if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); aluHandleDisconnect(device); return ALC_INVALID_DEVICE; } snd_pcm_capture_go(data->pcmHandle); } } else { read_ptr+=bytes_read; len-=bytes_read; } } return ALC_NO_ERROR; }
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; }