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

📄 oss.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 2 页
字号:
        p_aout->output.output.i_format = AOUT_FMT_S16_NE;        p_aout->output.output.i_physical_channels            = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;    }    else if ( val.i_int == AOUT_VAR_MONO )    {        p_aout->output.output.i_format = AOUT_FMT_S16_NE;        p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;    }    else    {        /* This should not happen ! */        msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int );        free( p_sys );        return VLC_EGENERIC;    }    val.b_bool = VLC_TRUE;    var_Set( p_aout, "intf-change", val );    /* Reset the DSP device */    if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )    {        msg_Err( p_aout, "cannot reset OSS audio device" );        close( p_sys->i_fd );        free( p_sys );        return VLC_EGENERIC;    }    /* Set the output format */    if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )    {        int i_format = AFMT_AC3;        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0             || i_format != AFMT_AC3 )        {            msg_Err( p_aout, "cannot reset OSS audio device" );            close( p_sys->i_fd );            free( p_sys );            return VLC_EGENERIC;        }        p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');        p_aout->output.i_nb_samples = A52_FRAME_NB;        p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;        p_aout->output.output.i_frame_length = A52_FRAME_NB;        aout_VolumeNoneInit( p_aout );    }    if ( !AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )    {        unsigned int i_format = AFMT_S16_NE;        unsigned int i_frame_size, i_fragments;        unsigned int i_rate;        unsigned int i_nb_channels;        audio_buf_info audio_buf;        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )        {            msg_Err( p_aout, "cannot set audio output format" );            close( p_sys->i_fd );            free( p_sys );            return VLC_EGENERIC;        }        switch ( i_format )        {        case AFMT_U8:            p_aout->output.output.i_format = VLC_FOURCC('u','8',' ',' ');            break;        case AFMT_S8:            p_aout->output.output.i_format = VLC_FOURCC('s','8',' ',' ');            break;        case AFMT_U16_LE:            p_aout->output.output.i_format = VLC_FOURCC('u','1','6','l');            break;        case AFMT_S16_LE:            p_aout->output.output.i_format = VLC_FOURCC('s','1','6','l');            break;        case AFMT_U16_BE:            p_aout->output.output.i_format = VLC_FOURCC('u','1','6','b');            break;        case AFMT_S16_BE:            p_aout->output.output.i_format = VLC_FOURCC('s','1','6','b');            break;        default:            msg_Err( p_aout, "OSS fell back to an unknown format (%d)",                     i_format );            close( p_sys->i_fd );            free( p_sys );            return VLC_EGENERIC;        }        i_nb_channels = aout_FormatNbChannels( &p_aout->output.output );        /* Set the number of channels */        if( ioctl( p_sys->i_fd, SNDCTL_DSP_CHANNELS, &i_nb_channels ) < 0 ||            i_nb_channels != aout_FormatNbChannels( &p_aout->output.output ) )        {            msg_Err( p_aout, "cannot set number of audio channels (%s)",                     aout_FormatPrintChannels( &p_aout->output.output) );            close( p_sys->i_fd );            free( p_sys );            return VLC_EGENERIC;        }        /* Set the output rate */        i_rate = p_aout->output.output.i_rate;        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SPEED, &i_rate ) < 0 )        {            msg_Err( p_aout, "cannot set audio output rate (%i)",                             p_aout->output.output.i_rate );            close( p_sys->i_fd );            free( p_sys );            return VLC_EGENERIC;        }        if( i_rate != p_aout->output.output.i_rate )        {            p_aout->output.output.i_rate = i_rate;        }        /* Set the fragment size */        aout_FormatPrepare( &p_aout->output.output );        /* i_fragment = xxxxyyyy where: xxxx        is fragtotal         *                              1 << yyyy   is fragsize */        i_fragments = 0;        i_frame_size = FRAME_SIZE * p_aout->output.output.i_bytes_per_frame;        while( i_frame_size >>= 1 )        {            ++i_fragments;        }        i_fragments |= FRAME_COUNT << 16;        if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFRAGMENT, &i_fragments ) < 0 )        {            msg_Warn( p_aout, "cannot set fragment size (%.8x)", i_fragments );        }        if( ioctl( p_sys->i_fd, SNDCTL_DSP_GETOSPACE, &audio_buf ) < 0 )        {            msg_Err( p_aout, "cannot get fragment size" );            close( p_sys->i_fd );            free( p_sys );            return VLC_EGENERIC;        }        else        {            /* Number of fragments actually allocated */            p_aout->output.p_sys->i_fragstotal = audio_buf.fragstotal;            /* Maximum duration the soundcard's buffer can hold */            p_aout->output.p_sys->max_buffer_duration =                (mtime_t)audio_buf.fragstotal * audio_buf.fragsize * 1000000                / p_aout->output.output.i_bytes_per_frame                / p_aout->output.output.i_rate                * p_aout->output.output.i_frame_length;            p_aout->output.i_nb_samples = audio_buf.fragsize /                p_aout->output.output.i_bytes_per_frame;        }        aout_VolumeSoftInit( p_aout );    }    p_aout->output.p_sys->b_workaround_buggy_driver =        config_GetInt( p_aout, "oss-buggy" );    /* Create OSS thread and wait for its readiness. */    if( vlc_thread_create( p_aout, "aout", OSSThread,                           VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )    {        msg_Err( p_aout, "cannot create OSS thread (%s)", strerror(errno) );        close( p_sys->i_fd );        free( p_sys );        return VLC_ETHREAD;    }    return VLC_SUCCESS;}/***************************************************************************** * Play: nothing to do *****************************************************************************/static void Play( aout_instance_t *p_aout ){}/***************************************************************************** * Close: close the DSP audio device *****************************************************************************/static void Close( vlc_object_t * p_this ){    aout_instance_t *p_aout = (aout_instance_t *)p_this;    struct aout_sys_t * p_sys = p_aout->output.p_sys;    p_aout->b_die = VLC_TRUE;    vlc_thread_join( p_aout );    p_aout->b_die = VLC_FALSE;    ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL );    close( p_sys->i_fd );    free( p_sys );}/***************************************************************************** * BufferDuration: buffer status query ***************************************************************************** * This function returns the duration in microseconds of the current buffer. *****************************************************************************/static mtime_t BufferDuration( aout_instance_t * p_aout ){    struct aout_sys_t * p_sys = p_aout->output.p_sys;    audio_buf_info audio_buf;    int i_bytes;    /* Fill the audio_buf_info structure:     * - fragstotal: total number of fragments allocated     * - fragsize: size of a fragment in bytes     * - bytes: available space in bytes (includes partially used fragments)     * Note! 'bytes' could be more than fragments*fragsize */    ioctl( p_sys->i_fd, SNDCTL_DSP_GETOSPACE, &audio_buf );    /* calculate number of available fragments (not partially used ones) */    i_bytes = (audio_buf.fragstotal * audio_buf.fragsize) - audio_buf.bytes;    /* Return the fragment duration */    return (mtime_t)i_bytes * 1000000            / p_aout->output.output.i_bytes_per_frame            / p_aout->output.output.i_rate            * p_aout->output.output.i_frame_length;}/***************************************************************************** * OSSThread: asynchronous thread used to DMA the data to the device *****************************************************************************/static int OSSThread( aout_instance_t * p_aout ){    struct aout_sys_t * p_sys = p_aout->output.p_sys;    mtime_t next_date = 0;    while ( !p_aout->b_die )    {        aout_buffer_t * p_buffer = NULL;        int i_tmp, i_size;        byte_t * p_bytes;        if ( p_aout->output.output.i_format != VLC_FOURCC('s','p','d','i') )        {            mtime_t buffered = BufferDuration( p_aout );            if( p_aout->output.p_sys->b_workaround_buggy_driver )            {#define i_fragstotal p_aout->output.p_sys->i_fragstotal                /* Wait a bit - we don't want our buffer to be full */                if( buffered > (p_aout->output.p_sys->max_buffer_duration                                / i_fragstotal * (i_fragstotal - 1)) )                {                    msleep((p_aout->output.p_sys->max_buffer_duration                                / i_fragstotal ));                    buffered = BufferDuration( p_aout );                }#undef i_fragstotal            }            /* Next buffer will be played at mdate() + buffered */            p_buffer = aout_OutputNextBuffer( p_aout, mdate() + buffered,                                              VLC_FALSE );            if( p_buffer == NULL &&                buffered > ( p_aout->output.p_sys->max_buffer_duration                             / p_aout->output.p_sys->i_fragstotal ) )            {                /* If we have at least a fragment full, then we can wait a                 * little and retry to get a new audio buffer instead of                 * playing a blank sample */                msleep( ( p_aout->output.p_sys->max_buffer_duration                          / p_aout->output.p_sys->i_fragstotal / 2 ) );                continue;            }        }        else        {            /* emu10k1 driver does not report Buffer Duration correctly in             * passthrough mode so we have to cheat */            if( !next_date )            {                next_date = mdate();            }            else            {                mtime_t delay = next_date - mdate();                if( delay > AOUT_PTS_TOLERANCE )                {                    msleep( delay / 2 );                }            }            while( !p_aout->b_die && ! ( p_buffer =                aout_OutputNextBuffer( p_aout, next_date, VLC_TRUE ) ) )            {                msleep( 1000 );                next_date = mdate();            }        }        if ( p_buffer != NULL )        {            p_bytes = p_buffer->p_buffer;            i_size = p_buffer->i_nb_bytes;            /* This is theoretical ... we'll see next iteration whether             * we're drifting */            next_date += p_buffer->end_date - p_buffer->start_date;        }        else        {            i_size = FRAME_SIZE / p_aout->output.output.i_frame_length                      * p_aout->output.output.i_bytes_per_frame;            p_bytes = malloc( i_size );            memset( p_bytes, 0, i_size );            next_date = 0;        }        i_tmp = write( p_sys->i_fd, p_bytes, i_size );        if( i_tmp < 0 )        {            msg_Err( p_aout, "write failed (%s)", strerror(errno) );        }        if ( p_buffer != NULL )        {            aout_BufferFree( p_buffer );        }        else        {            free( p_bytes );        }    }    return VLC_SUCCESS;}

⌨️ 快捷键说明

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