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

📄 auhal.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                                    kAudioDevicePropertyStreams,                                    &i_param_size, p_streams );        if( err != noErr )    {        msg_Err( p_aout, "could not get number of streams: [%4.4s]", (char *)&err );        return VLC_FALSE;    }    for( i = 0; i < i_streams; i++ )    {        if( AudioStreamSupportsDigital( p_aout, p_streams[i] ) )            b_return = VLC_TRUE;    }        if( p_streams ) free( p_streams );    return b_return;}/***************************************************************************** * AudioStreamSupportsDigital: Check i_stream_id for digital stream support. *****************************************************************************/static int AudioStreamSupportsDigital( aout_instance_t *p_aout, AudioStreamID i_stream_id ){    OSStatus                    err = noErr;    UInt32                      i_param_size = 0;    AudioStreamBasicDescription *p_format_list = NULL;    int                         i = 0, i_formats = 0;    vlc_bool_t                  b_return = VLC_FALSE;        /* Retrieve all the stream formats supported by each output stream */    err = AudioStreamGetPropertyInfo( i_stream_id, 0,                                      kAudioStreamPropertyPhysicalFormats,                                      &i_param_size, NULL );    if( err != noErr )    {        msg_Err( p_aout, "could not get number of streamformats: [%4.4s]", (char *)&err );        return VLC_FALSE;    }        i_formats = i_param_size / sizeof( AudioStreamBasicDescription );    p_format_list = (AudioStreamBasicDescription *)malloc( i_param_size );    if( p_format_list == NULL )    {        msg_Err( p_aout, "could not malloc the memory" );        return VLC_FALSE;    }        err = AudioStreamGetProperty( i_stream_id, 0,                                      kAudioStreamPropertyPhysicalFormats,                                      &i_param_size, p_format_list );    if( err != noErr )    {        msg_Err( p_aout, "could not get the list of streamformats: [%4.4s]", (char *)&err );        free( p_format_list);        p_format_list = NULL;        return VLC_FALSE;    }    for( i = 0; i < i_formats; i++ )    {        msg_Dbg( p_aout, STREAM_FORMAT_MSG( "supported format: ", p_format_list[i] ) );                if( p_format_list[i].mFormatID == 'IAC3' ||                  p_format_list[i].mFormatID == kAudioFormat60958AC3 )        {            b_return = VLC_TRUE;        }    }        if( p_format_list ) free( p_format_list );    return b_return;}/***************************************************************************** * AudioStreamChangeFormat: Change i_stream_id to change_format *****************************************************************************/static int AudioStreamChangeFormat( aout_instance_t *p_aout, AudioStreamID i_stream_id, AudioStreamBasicDescription change_format ){    OSStatus            err = noErr;    UInt32              i_param_size = 0;    int i;    struct timeval now;    struct timespec timeout;    struct { vlc_mutex_t lock; vlc_cond_t cond; } w;        msg_Dbg( p_aout, STREAM_FORMAT_MSG( "setting stream format: ", change_format ) );    /* Condition because SetProperty is asynchronious */     vlc_cond_init( p_aout, &w.cond );    vlc_mutex_init( p_aout, &w.lock );    vlc_mutex_lock( &w.lock );    /* Install the callback */    err = AudioStreamAddPropertyListener( i_stream_id, 0,                                      kAudioStreamPropertyPhysicalFormat,                                      StreamListener, (void *)&w );    if( err != noErr )    {        msg_Err( p_aout, "AudioStreamAddPropertyListener failed: [%4.4s]", (char *)&err );        return VLC_FALSE;    }    /* change the format */    err = AudioStreamSetProperty( i_stream_id, 0, 0,                                  kAudioStreamPropertyPhysicalFormat,                                  sizeof( AudioStreamBasicDescription ),                                  &change_format );     if( err != noErr )    {        msg_Err( p_aout, "could not set the stream format: [%4.4s]", (char *)&err );        return VLC_FALSE;    }    /* The AudioStreamSetProperty is not only asynchronious (requiring the locks)     * it is also not Atomic, in it's behaviour.     * Therefore we check 5 times before we really give up.     * FIXME: failing isn't actually implemented yet. */    for( i = 0; i < 5; i++ )    {        AudioStreamBasicDescription actual_format;        gettimeofday( &now, NULL );        timeout.tv_sec = now.tv_sec;        timeout.tv_nsec = (now.tv_usec + 500000) * 1000;        if( pthread_cond_timedwait( &w.cond.cond, &w.lock.mutex, &timeout ) )        {            msg_Dbg( p_aout, "reached timeout" );        }        i_param_size = sizeof( AudioStreamBasicDescription );        err = AudioStreamGetProperty( i_stream_id, 0,                                      kAudioStreamPropertyPhysicalFormat,                                      &i_param_size,                                       &actual_format );        msg_Dbg( p_aout, STREAM_FORMAT_MSG( "actual format in use: ", actual_format ) );        if( actual_format.mSampleRate == change_format.mSampleRate &&            actual_format.mFormatID == change_format.mFormatID &&            actual_format.mFramesPerPacket == change_format.mFramesPerPacket )        {            /* The right format is now active */            break;        }        /* We need to check again */    }        /* Removing the property listener */    err = AudioStreamRemovePropertyListener( i_stream_id, 0,                                            kAudioStreamPropertyPhysicalFormat,                                            StreamListener );    if( err != noErr )    {        msg_Err( p_aout, "AudioStreamRemovePropertyListener failed: [%4.4s]", (char *)&err );        return VLC_FALSE;    }        /* Destroy the lock and condition */    vlc_mutex_unlock( &w.lock );    vlc_mutex_destroy( &w.lock );    vlc_cond_destroy( &w.cond );        return VLC_TRUE;}/***************************************************************************** * RenderCallbackAnalog: This function is called everytime the AudioUnit wants * us to provide some more audio data. * Don't print anything during normal playback, calling blocking function from * this callback is not allowed. *****************************************************************************/static OSStatus RenderCallbackAnalog( vlc_object_t *_p_aout,                                      AudioUnitRenderActionFlags *ioActionFlags,                                      const AudioTimeStamp *inTimeStamp,                                      unsigned int inBusNummer,                                      unsigned int inNumberFrames,                                      AudioBufferList *ioData ){    AudioTimeStamp  host_time;    mtime_t         current_date = 0;    uint32_t        i_mData_bytes = 0;        aout_instance_t * p_aout = (aout_instance_t *)_p_aout;    struct aout_sys_t * p_sys = p_aout->output.p_sys;    host_time.mFlags = kAudioTimeStampHostTimeValid;    AudioDeviceTranslateTime( p_sys->i_selected_dev, inTimeStamp, &host_time );    /* Check for the difference between the Device clock and mdate */    p_sys->clock_diff = - (mtime_t)        AudioConvertHostTimeToNanos( AudioGetCurrentHostTime() ) / 1000;     p_sys->clock_diff += mdate();    current_date = p_sys->clock_diff +                   AudioConvertHostTimeToNanos( host_time.mHostTime ) / 1000;                   //- ((mtime_t) 1000000 / p_aout->output.output.i_rate * 31 ); // 31 = Latency in Frames. retrieve somewhere    if( ioData == NULL && ioData->mNumberBuffers < 1 )    {        msg_Err( p_aout, "no iodata or buffers");        return 0;    }    if( ioData->mNumberBuffers > 1 )        msg_Err( p_aout, "well this is weird. seems like there is more than one buffer..." );    if( p_sys->i_total_bytes > 0 )    {        i_mData_bytes = __MIN( p_sys->i_total_bytes - p_sys->i_read_bytes, ioData->mBuffers[0].mDataByteSize );        p_aout->p_vlc->pf_memcpy( ioData->mBuffers[0].mData, &p_sys->p_remainder_buffer[p_sys->i_read_bytes], i_mData_bytes );        p_sys->i_read_bytes += i_mData_bytes;        current_date += (mtime_t) ( (mtime_t) 1000000 / p_aout->output.output.i_rate ) *                        ( i_mData_bytes / 4 / aout_FormatNbChannels( &p_aout->output.output )  ); // 4 is fl32 specific                if( p_sys->i_read_bytes >= p_sys->i_total_bytes )            p_sys->i_read_bytes = p_sys->i_total_bytes = 0;    }        while( i_mData_bytes < ioData->mBuffers[0].mDataByteSize )    {        /* We don't have enough data yet */        aout_buffer_t * p_buffer;        p_buffer = aout_OutputNextBuffer( p_aout, current_date , VLC_FALSE );                if( p_buffer != NULL )        {            uint32_t i_second_mData_bytes = __MIN( p_buffer->i_nb_bytes, ioData->mBuffers[0].mDataByteSize - i_mData_bytes );                        p_aout->p_vlc->pf_memcpy( (uint8_t *)ioData->mBuffers[0].mData + i_mData_bytes, p_buffer->p_buffer, i_second_mData_bytes );            i_mData_bytes += i_second_mData_bytes;            if( i_mData_bytes >= ioData->mBuffers[0].mDataByteSize )            {                p_sys->i_total_bytes = p_buffer->i_nb_bytes - i_second_mData_bytes;                p_aout->p_vlc->pf_memcpy( p_sys->p_remainder_buffer, &p_buffer->p_buffer[i_second_mData_bytes], p_sys->i_total_bytes );            }            else            {                /* update current_date */                current_date += (mtime_t) ( (mtime_t) 1000000 / p_aout->output.output.i_rate ) *                                ( i_second_mData_bytes / 4 / aout_FormatNbChannels( &p_aout->output.output )  ); // 4 is fl32 specific            }            aout_BufferFree( p_buffer );        }        else        {             p_aout->p_vlc->pf_memset( (uint8_t *)ioData->mBuffers[0].mData +i_mData_bytes, 0, ioData->mBuffers[0].mDataByteSize - i_mData_bytes );             i_mData_bytes += ioData->mBuffers[0].mDataByteSize - i_mData_bytes;        }    }    return( noErr );     }/***************************************************************************** * RenderCallbackSPDIF: callback for SPDIF audio output *****************************************************************************/static OSStatus RenderCallbackSPDIF( AudioDeviceID inDevice,                                    const AudioTimeStamp * inNow,                                     const void * inInputData,                                    const AudioTimeStamp * inInputTime,                                     AudioBufferList * outOutputData,                                    const AudioTimeStamp * inOutputTime,                                     void * threadGlobals ){    aout_buffer_t * p_buffer;    mtime_t         current_date;    aout_instance_t * p_aout = (aout_instance_t *)threadGlobals;    struct aout_sys_t * p_sys = p_aout->output.p_sys;    /* Check for the difference between the Device clock and mdate */    p_sys->clock_diff = - (mtime_t)        AudioConvertHostTimeToNanos( inNow->mHostTime ) / 1000;     p_sys->clock_diff += mdate();    current_date = p_sys->clock_diff +                   AudioConvertHostTimeToNanos( inOutputTime->mHostTime ) / 1000;                   //- ((mtime_t) 1000000 / p_aout->output.output.i_rate * 31 ); // 31 = Latency in Frames. retrieve somewhere    p_buffer = aout_OutputNextBuffer( p_aout, current_date, VLC_TRUE );#define BUFFER outOutputData->mBuffers[p_sys->i_stream_index]    if( p_buffer != NULL )    {        if( (int)BUFFER.mDataByteSize != (int)p_buffer->i_nb_bytes)            msg_Warn( p_aout, "bytesize: %d nb_bytes: %d", (int)BUFFER.mDataByteSize, (int)p_buffer->i_nb_bytes );                /* move data into output data buffer */        p_aout->p_vlc->pf_memcpy( BUFFER.mData,                                  p_buffer->p_buffer, p_buffer->i_nb_bytes );        aout_BufferFree( p_buffer );    }    else    {        p_aout->p_vlc->pf_memset( BUFFER.mData, 0, BUFFER.mDataByteSize );    }#undef BUFFER    return( noErr );     }/***************************************************************************** * HardwareListener: Warns us of changes in the list of registered devices *****************************************************************************/static OSStatus HardwareListener( AudioHardwarePropertyID inPropertyID,                                  void * inClientData ){    OSStatus err = noErr;    aout_instance_t     *p_aout = (aout_instance_t *)inClientData;    switch( inPropertyID )    {        case kAudioHardwarePropertyDevices:        {            /* something changed in the list of devices */            /* We trigger the audio-device's aout_ChannelsRestart callback */            var_Change( p_aout, "audio-device", VLC_VAR_TRIGGER_CALLBACKS, NULL, NULL );            var_Destroy( p_aout, "audio-device" );        }        break;    }    return( err );}/***************************************************************************** * StreamListener  *****************************************************************************/static OSStatus StreamListener( AudioStreamID inStream,                                UInt32 inChannel,                                AudioDevicePropertyID inPropertyID,                                void * inClientData ){    OSStatus err = noErr;    struct { vlc_mutex_t lock; vlc_cond_t cond; } * w = inClientData;        switch( inPropertyID )    {        case kAudioStreamPropertyPhysicalFormat:            vlc_mutex_lock( &w->lock );            vlc_cond_signal( &w->cond );            vlc_mutex_unlock( &w->lock );             break;        default:            break;    }    return( err );}/***************************************************************************** * AudioDeviceCallback: Callback triggered when the audio-device variable is changed *****************************************************************************/static int AudioDeviceCallback( vlc_object_t *p_this, const char *psz_variable,                     vlc_value_t old_val, vlc_value_t new_val, void *param ){    aout_instance_t *p_aout = (aout_instance_t *)p_this;    var_Set( p_aout->p_vlc, "macosx-audio-device", new_val );    msg_Dbg( p_aout, "Set Device: %#x", new_val.i_int );    return aout_ChannelsRestart( p_this, psz_variable, old_val, new_val, param );}

⌨️ 快捷键说明

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