⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pa_unix_oss.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        PA_DEBUG(( "OnExit: Stoppage\n" ));    /* Eventually notify user all buffers have played */    if( stream->streamRepresentation.streamFinishedCallback )        stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );    stream->callbackAbort = 0;      /* Clear state */    stream->isActive = 0;}static PaError SetUpBuffers( PaOssStream *stream, unsigned long framesAvail ){    PaError result = paNoError;    if( stream->capture )    {        PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, 0, stream->capture->buffer,                stream->capture->hostChannelCount );        PaUtil_SetInputFrameCount( &stream->bufferProcessor, framesAvail );    }    if( stream->playback )    {        PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, 0, stream->playback->buffer,                stream->playback->hostChannelCount );        PaUtil_SetOutputFrameCount( &stream->bufferProcessor, framesAvail );    }    return result;}/** Thread procedure for callback processing. * * Aspect StreamState: StartStream will wait on this to initiate audio processing, useful in case the * callback should be used for buffer priming. When the stream is cancelled a separate function will * take care of the transition to the Callback Finished state (the stream isn't considered Stopped * before StopStream() or AbortStream() are called). */static void *PaOSS_AudioThreadProc( void *userData ){    PaError result = paNoError;    PaOssStream *stream = (PaOssStream*)userData;    unsigned long framesAvail = 0, framesProcessed = 0;    int callbackResult = paContinue;    int triggered = stream->triggered;  /* See if SNDCTL_DSP_TRIGGER has been issued already */    int initiateProcessing = triggered;    /* Already triggered? */    PaStreamCallbackFlags cbFlags = 0;  /* We might want to keep state across iterations */    PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* TODO: IMPLEMENT ME */        /*#if ( SOUND_VERSION > 0x030904 )        audio_errinfo errinfo;#endif*/        assert( stream );    pthread_cleanup_push( &OnExit, stream );	/* Execute OnExit when exiting */    /* The first time the stream is started we use SNDCTL_DSP_TRIGGER to accurately start capture and     * playback in sync, when the stream is restarted after being stopped we simply start by reading/     * writing.     */    PA_ENSURE( PaOssStream_Prepare( stream ) );    /* If we are to initiate processing implicitly by reading/writing data, we start off in blocking mode */    if( initiateProcessing )    {        /* Make sure devices are in blocking mode */        if( stream->capture )            ModifyBlocking( stream->capture->fd, 1 );        if( stream->playback )            ModifyBlocking( stream->playback->fd, 1 );    }    while( 1 )    {        pthread_testcancel();        if( stream->callbackStop && callbackResult == paContinue )        {            PA_DEBUG(( "Setting callbackResult to paComplete\n" ));            callbackResult = paComplete;        }        /* Aspect StreamState: Because of the messy OSS scheme we can't explicitly trigger device start unless         * the stream has been recently started, we will have to go right ahead and read/write in blocking         * fashion to trigger operation. Therefore we begin with processing one host buffer before we switch         * to non-blocking mode.         */        if( !initiateProcessing )        {            PA_ENSURE( PaOssStream_WaitForFrames( stream, &framesAvail ) );  /* Wait on available frames */            assert( framesAvail % stream->framesPerHostBuffer == 0 );        }        else        {            framesAvail = stream->framesPerHostBuffer;        }        while( framesAvail > 0 )        {            unsigned long frames = framesAvail;            pthread_testcancel();            PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );            /* Read data */            if ( stream->capture )            {                PA_ENSURE( PaOssStreamComponent_Read( stream->capture, &frames ) );                if( frames < framesAvail )                {                    PA_DEBUG(( "Read %lu less frames than requested\n", framesAvail - frames ));                    framesAvail = frames;                }            }#if ( SOUND_VERSION >= 0x030904 )            /*               Check with OSS to see if there have been any under/overruns               since last time we checked.               */            /*            if( ioctl( stream->deviceHandle, SNDCTL_DSP_GETERROR, &errinfo ) >= 0 )            {                if( errinfo.play_underruns )                    cbFlags |= paOutputUnderflow ;                if( errinfo.record_underruns )                    cbFlags |= paInputUnderflow ;            }            else                PA_DEBUG(( "SNDCTL_DSP_GETERROR command failed: %s\n", strerror( errno ) ));                */#endif            PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo,                    cbFlags );            cbFlags = 0;            PA_ENSURE( SetUpBuffers( stream, framesAvail ) );            framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor,                    &callbackResult );            assert( framesProcessed == framesAvail );            PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );            if ( stream->playback )            {                frames = framesAvail;                PA_ENSURE( PaOssStreamComponent_Write( stream->playback, &frames ) );                if( frames < framesAvail )                {                    /* TODO: handle bytesWritten != bytesRequested (slippage?) */                    PA_DEBUG(( "Wrote %lu less frames than requested\n", framesAvail - frames ));                }            }            framesAvail -= framesProcessed;            stream->framesProcessed += framesProcessed;            if( callbackResult != paContinue )                break;        }        if( initiateProcessing || !triggered )        {            /* Non-blocking */            if( stream->capture )                PA_ENSURE( ModifyBlocking( stream->capture->fd, 0 ) );            if( stream->playback && !stream->sharedDevice )                PA_ENSURE( ModifyBlocking( stream->playback->fd, 0 ) );            initiateProcessing = 0;            sem_post( &stream->semaphore );        }        if( callbackResult != paContinue )        {            stream->callbackAbort = callbackResult == paAbort;            if( stream->callbackAbort || PaUtil_IsBufferProcessorOutputEmpty( &stream->bufferProcessor ) )                break;        }    }    pthread_cleanup_pop( 1 );error:    pthread_exit( NULL );}/** Close the stream. * */static PaError CloseStream( PaStream* s ){    PaError result = paNoError;    PaOssStream *stream = (PaOssStream*)s;    assert( stream );    PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );    PaOssStream_Terminate( stream );    return result;}/** Start the stream. * * Aspect StreamState: After returning, the stream shall be in the Active state, implying that an eventual * callback will be repeatedly called in a separate thread. If a separate thread is started this function * will block untill it has started processing audio, otherwise audio processing is started directly. */static PaError StartStream( PaStream *s ){    PaError result = paNoError;    PaOssStream *stream = (PaOssStream*)s;    stream->isActive = 1;    stream->isStopped = 0;    stream->lastPosPtr = 0;    stream->lastStreamBytes = 0;    stream->framesProcessed = 0;    /* only use the thread for callback streams */    if( stream->bufferProcessor.streamCallback )    {        PA_ENSURE( PaUtil_StartThreading( &stream->threading, &PaOSS_AudioThreadProc, stream ) );        sem_wait( &stream->semaphore );    }    else        PA_ENSURE( PaOssStream_Prepare( stream ) );error:    return result;}static PaError RealStop( PaOssStream *stream, int abort ){    PaError result = paNoError;    if( stream->callbackMode )    {        if( abort )            stream->callbackAbort = 1;        else            stream->callbackStop = 1;        PA_ENSURE( PaUtil_CancelThreading( &stream->threading, !abort, NULL ) );        stream->callbackStop = stream->callbackAbort = 0;    }    else        PA_ENSURE( PaOssStream_Stop( stream, abort ) );    stream->isStopped = 1;error:    return result;}/** Stop the stream. * * Aspect StreamState: This will cause the stream to transition to the Stopped state, playing all enqueued * buffers. */static PaError StopStream( PaStream *s ){    return RealStop( (PaOssStream *)s, 0 );}/** Abort the stream. * * Aspect StreamState: This will cause the stream to transition to the Stopped state, discarding all enqueued * buffers. Note that the buffers are not currently correctly discarded, this is difficult without closing * the OSS device. */static PaError AbortStream( PaStream *s ){    return RealStop( (PaOssStream *)s, 1 );}/** Is the stream in the Stopped state. * */static PaError IsStreamStopped( PaStream *s ){    PaOssStream *stream = (PaOssStream*)s;    return (stream->isStopped);}/** Is the stream in the Active state. * */static PaError IsStreamActive( PaStream *s ){    PaOssStream *stream = (PaOssStream*)s;    return (stream->isActive);}static PaTime GetStreamTime( PaStream *s ){    PaOssStream *stream = (PaOssStream*)s;    count_info info;    int delta;    if( stream->playback ) {        if( ioctl( stream->playback->fd, SNDCTL_DSP_GETOPTR, &info) == 0 ) {            delta = ( info.bytes - stream->lastPosPtr ) /* & 0x000FFFFF*/;            return (float)(stream->lastStreamBytes + delta) / PaOssStreamComponent_FrameSize( stream->playback ) / stream->sampleRate;        }    }    else {        if (ioctl( stream->capture->fd, SNDCTL_DSP_GETIPTR, &info) == 0) {            delta = (info.bytes - stream->lastPosPtr) /*& 0x000FFFFF*/;            return (float)(stream->lastStreamBytes + delta) / PaOssStreamComponent_FrameSize( stream->capture ) / stream->sampleRate;        }    }    /* the ioctl failed, but we can still give a coarse estimate */    return stream->framesProcessed / stream->sampleRate;}static double GetStreamCpuLoad( PaStream* s ){    PaOssStream *stream = (PaOssStream*)s;    return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );}/*    As separate stream interfaces are used for blocking and callback    streams, the following functions can be guaranteed to only be called    for blocking streams.*/static PaError ReadStream( PaStream* s,                           void *buffer,                           unsigned long frames ){    PaOssStream *stream = (PaOssStream*)s;    int bytesRequested, bytesRead;    unsigned long framesRequested;    void *userBuffer;    /* If user input is non-interleaved, PaUtil_CopyInput will manipulate the channel pointers,     * so we copy the user provided pointers */    if( stream->bufferProcessor.userInputIsInterleaved )        userBuffer = buffer;    else /* Copy channels into local array */    {        userBuffer = stream->capture->userBuffers;        memcpy( (void *)userBuffer, buffer, sizeof (void *) * stream->capture->userChannelCount );    }    while( frames )    {        framesRequested = PA_MIN( frames, stream->capture->hostFrames );	bytesRequested = framesRequested * PaOssStreamComponent_FrameSize( stream->capture );	bytesRead = read( stream->capture->fd, stream->capture->buffer, bytesRequested );	if ( bytesRequested != bytesRead )	    return paUnanticipatedHostError;	PaUtil_SetInputFrameCount( &stream->bufferProcessor, stream->capture->hostFrames );	PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, 0, stream->capture->buffer, stream->capture->hostChannelCount );        PaUtil_CopyInp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -