diff options
author | Kurt Korbatits <kurt.korbatits@nokia.com> | 2010-02-23 03:40:03 (GMT) |
---|---|---|
committer | Kurt Korbatits <kurt.korbatits@nokia.com> | 2010-02-23 03:40:03 (GMT) |
commit | 04532ba052559b265b1bc85dc143d8aeeb02149f (patch) | |
tree | 73284772620b9714819141ac815e257da9bf9824 /src/multimedia/audio/qaudioinput_alsa_p.cpp | |
parent | f91f64ee2d0caa86b004bf3653f286116681fa3d (diff) | |
download | Qt-04532ba052559b265b1bc85dc143d8aeeb02149f.zip Qt-04532ba052559b265b1bc85dc143d8aeeb02149f.tar.gz Qt-04532ba052559b265b1bc85dc143d8aeeb02149f.tar.bz2 |
alsa backend for low-level audio doesn't pass new unit tests
New unit tests have identified issues with alsa backend. These issues
need to be resolved before new unit tests are added.
* stateChanged() signal should only be emitted on change of state
currently signals can be emitted multiple times.
* elapsedUSecs() currently uses alsa to provide this value but
this is not reliable enough and this time is reset when
suspend/resuming. This is not correct operation.
* for output data is being lost when input cant be read
from QIODevice but cannot be written to audio sub system.
Task-number:QTBUG-8440
Reviewed-by:Dmytro Poplavskiy
Diffstat (limited to 'src/multimedia/audio/qaudioinput_alsa_p.cpp')
-rw-r--r-- | src/multimedia/audio/qaudioinput_alsa_p.cpp | 121 |
1 files changed, 40 insertions, 81 deletions
diff --git a/src/multimedia/audio/qaudioinput_alsa_p.cpp b/src/multimedia/audio/qaudioinput_alsa_p.cpp index 26e46b3..6010f3c 100644 --- a/src/multimedia/audio/qaudioinput_alsa_p.cpp +++ b/src/multimedia/audio/qaudioinput_alsa_p.cpp @@ -217,9 +217,11 @@ QIODevice* QAudioInputPrivate::start(QIODevice* device) //set to pull mode pullMode = true; audioSource = device; + deviceState = QAudio::ActiveState; } else { //set to push mode pullMode = false; + deviceState = QAudio::IdleState; audioSource = new InputPrivate(this); audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered); } @@ -413,7 +415,6 @@ bool QAudioInputPrivate::open() timer->start(period_time*chunks/2000); errorState = QAudio::NoError; - deviceState = QAudio::ActiveState; totalTimeValue = 0; @@ -439,7 +440,7 @@ int QAudioInputPrivate::bytesReady() const if(resuming) return period_size; - if(deviceState != QAudio::ActiveState) + if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return 0; int frames = snd_pcm_avail_update(handle); if((int)frames > (int)buffer_frames) @@ -450,8 +451,8 @@ int QAudioInputPrivate::bytesReady() const qint64 QAudioInputPrivate::read(char* data, qint64 len) { - Q_UNUSED(data) Q_UNUSED(len) + // Read in some audio data and write it to QIODevice, pull mode if ( !handle ) return 0; @@ -468,7 +469,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) if (readFrames >= 0) { err = snd_pcm_frames_to_bytes(handle, readFrames); #ifdef DEBUG_AUDIO - qDebug()<<QString::fromLatin1("PULL: read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); + qDebug()<<QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); #endif break; } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) { @@ -489,28 +490,46 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) if(err > 0) { // got some send it onward #ifdef DEBUG_AUDIO - qDebug()<<"PULL: frames to write to QIODevice = "<< + qDebug()<<"frames to write to QIODevice = "<< snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes"; #endif - if(deviceState != QAudio::ActiveState) + if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return 0; + if (pullMode) { + qint64 l = audioSource->write(audioBuffer,err); + if(l < 0) { + close(); + errorState = QAudio::IOError; + deviceState = QAudio::StoppedState; + emit stateChanged(deviceState); + } else if(l == 0) { + if (deviceState != QAudio::IdleState) { + errorState = QAudio::NoError; + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } + } else { + totalTimeValue += err; + resuming = false; + if (deviceState != QAudio::ActiveState) { + errorState = QAudio::NoError; + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } + } + return l; - qint64 l = audioSource->write(audioBuffer,err); - if(l < 0) { - close(); - errorState = QAudio::IOError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - } else if(l == 0) { - errorState = QAudio::NoError; - deviceState = QAudio::IdleState; } else { - totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.frequency(); + memcpy(data,audioBuffer,err); + totalTimeValue += err; resuming = false; - errorState = QAudio::NoError; - deviceState = QAudio::ActiveState; + if (deviceState != QAudio::ActiveState) { + errorState = QAudio::NoError; + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } + return err; } - return l; } return 0; } @@ -569,7 +588,7 @@ int QAudioInputPrivate::notifyInterval() const qint64 QAudioInputPrivate::processedUSecs() const { - return totalTimeValue; + return qint64(1000000) * totalTimeValue / settings.frequency(); } void QAudioInputPrivate::suspend() @@ -617,34 +636,10 @@ bool QAudioInputPrivate::deviceReady() qint64 QAudioInputPrivate::elapsedUSecs() const { - if(!handle) - return 0; - if (deviceState == QAudio::StoppedState) return 0; -#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) - snd_pcm_status_t* status; - snd_pcm_status_alloca(&status); - - snd_timestamp_t t1,t2; - if( snd_pcm_status(handle, status) >= 0) { - snd_pcm_status_get_tstamp(status,&t1); - snd_pcm_status_get_trigger_tstamp(status,&t2); - t1.tv_sec-=t2.tv_sec; - - signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec; - if(l < 0) { - t1.tv_sec--; - l = -l; - l %= 1000000; - } - return ((t1.tv_sec * 1000000)+l); - } else - return 0; -#else return clockStamp.elapsed()*1000; -#endif } void QAudioInputPrivate::reset() @@ -670,43 +665,7 @@ InputPrivate::~InputPrivate() qint64 InputPrivate::readData( char* data, qint64 len) { - // push mode, user read() called - if((audioDevice->state() != QAudio::ActiveState) && !audioDevice->resuming) - return 0; - - int readFrames; - int count=0, err = 0; - - while(count < 5) { - int frames = snd_pcm_bytes_to_frames(audioDevice->handle, len); - readFrames = snd_pcm_readi(audioDevice->handle, data, frames); - if (readFrames >= 0) { - err = snd_pcm_frames_to_bytes(audioDevice->handle, readFrames); -#ifdef DEBUG_AUDIO - qDebug()<<QString::fromLatin1("PUSH: read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); -#endif - break; - } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) { - audioDevice->errorState = QAudio::IOError; - err = 0; - break; - } else { - if(readFrames == -EPIPE) { - audioDevice->errorState = QAudio::UnderrunError; - err = snd_pcm_prepare(audioDevice->handle); - } else if(readFrames == -ESTRPIPE) { - err = snd_pcm_prepare(audioDevice->handle); - } - if(err != 0) break; - } - count++; - } - if(err > 0 && readFrames > 0) { - audioDevice->totalTimeValue += readFrames*1000/audioDevice->settings.frequency()*1000; - audioDevice->deviceState = QAudio::ActiveState; - return err; - } - return 0; + return audioDevice->read(data,len); } qint64 InputPrivate::writeData(const char* data, qint64 len) |