📄 auhal.c
字号:
/* Initialize the VLC core channel count */ p_aout->output.output.i_physical_channels = 0; i_original = p_aout->output.output.i_original_channels & AOUT_CHAN_PHYSMASK; if( i_original == AOUT_CHAN_CENTER || layout->mNumberChannelDescriptions < 2 ) { /* We only need Mono or cannot output more than 1 channel */ p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; } else if( i_original == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) || layout->mNumberChannelDescriptions < 3 ) { /* We only need Stereo or cannot output more than 2 channels */ p_aout->output.output.i_physical_channels = AOUT_CHAN_RIGHT | AOUT_CHAN_LEFT; } else { /* We want more than stereo and we can do that */ for( i = 0; i < layout->mNumberChannelDescriptions; i++ ) { msg_Dbg( p_aout, "this is channel: %d", (int)layout->mChannelDescriptions[i].mChannelLabel ); switch( layout->mChannelDescriptions[i].mChannelLabel ) { case kAudioChannelLabel_Left: p_aout->output.output.i_physical_channels |= AOUT_CHAN_LEFT; continue; case kAudioChannelLabel_Right: p_aout->output.output.i_physical_channels |= AOUT_CHAN_RIGHT; continue; case kAudioChannelLabel_Center: p_aout->output.output.i_physical_channels |= AOUT_CHAN_CENTER; continue; case kAudioChannelLabel_LFEScreen: p_aout->output.output.i_physical_channels |= AOUT_CHAN_LFE; continue; case kAudioChannelLabel_LeftSurround: p_aout->output.output.i_physical_channels |= AOUT_CHAN_REARLEFT; continue; case kAudioChannelLabel_RightSurround: p_aout->output.output.i_physical_channels |= AOUT_CHAN_REARRIGHT; continue; case kAudioChannelLabel_RearSurroundLeft: p_aout->output.output.i_physical_channels |= AOUT_CHAN_MIDDLELEFT; continue; case kAudioChannelLabel_RearSurroundRight: p_aout->output.output.i_physical_channels |= AOUT_CHAN_MIDDLERIGHT; continue; case kAudioChannelLabel_CenterSurround: p_aout->output.output.i_physical_channels |= AOUT_CHAN_REARCENTER; continue; default: msg_Warn( p_aout, "unrecognized channel form provided by driver: %d", (int)layout->mChannelDescriptions[i].mChannelLabel ); } } if( p_aout->output.output.i_physical_channels == 0 ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; msg_Err( p_aout, "You should configure your speaker layout with Audio Midi Setup Utility in /Applications/Utilities. Now using Stereo mode." ); } } if( layout ) free( layout ); } else { msg_Warn( p_aout, "this driver does not support kAudioDevicePropertyPreferredChannelLayout. BAD DRIVER AUTHOR !!!" ); p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } msg_Dbg( p_aout, "selected %d physical channels for device output", aout_FormatNbChannels( &p_aout->output.output ) ); msg_Dbg( p_aout, "VLC will output: %s", aout_FormatPrintChannels( &p_aout->output.output )); memset (&new_layout, 0, sizeof(new_layout)); switch( aout_FormatNbChannels( &p_aout->output.output ) ) { case 1: new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; break; case 2: new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; break; case 3: if( p_aout->output.output.i_physical_channels & AOUT_CHAN_CENTER ) { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_7; // L R C } else if( p_aout->output.output.i_physical_channels & AOUT_CHAN_LFE ) { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_4; // L R LFE } break; case 4: if( p_aout->output.output.i_physical_channels & ( AOUT_CHAN_CENTER | AOUT_CHAN_LFE ) ) { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_10; // L R C LFE } else if( p_aout->output.output.i_physical_channels & ( AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT ) ) { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R Ls Rs } else if( p_aout->output.output.i_physical_channels & ( AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER ) ) { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R C Cs } break; case 5: if( p_aout->output.output.i_physical_channels & ( AOUT_CHAN_CENTER ) ) { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_19; // L R Ls Rs C } else if( p_aout->output.output.i_physical_channels & ( AOUT_CHAN_LFE ) ) { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_18; // L R Ls Rs LFE } break; case 6: if( p_aout->output.output.i_physical_channels & ( AOUT_CHAN_LFE ) ) { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_20; // L R Ls Rs C LFE } else { new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_6_0; // L R Ls Rs C Cs } break; case 7: /* FIXME: This is incorrect. VLC uses the internal ordering: L R Lm Rm Lr Rr C LFE but this is wrong */ new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_6_1_A; // L R C LFE Ls Rs Cs break; case 8: /* FIXME: This is incorrect. VLC uses the internal ordering: L R Lm Rm Lr Rr C LFE but this is wrong */ new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_7_1_A; // L R C LFE Ls Rs Lc Rc break; } /* Set up the format to be used */ DeviceFormat.mSampleRate = p_aout->output.output.i_rate; DeviceFormat.mFormatID = kAudioFormatLinearPCM; /* We use float 32. It's the best supported format by both VLC and Coreaudio */ p_aout->output.output.i_format = VLC_FOURCC( 'f','l','3','2'); DeviceFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; DeviceFormat.mBitsPerChannel = 32; DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels( &p_aout->output.output ); /* Calculate framesizes and stuff */ DeviceFormat.mFramesPerPacket = 1; DeviceFormat.mBytesPerFrame = DeviceFormat.mBitsPerChannel * DeviceFormat.mChannelsPerFrame / 8; DeviceFormat.mBytesPerPacket = DeviceFormat.mBytesPerFrame * DeviceFormat.mFramesPerPacket; /* Set the desired format */ i_param_size = sizeof(AudioStreamBasicDescription); verify_noerr( AudioUnitSetProperty( p_sys->au_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &DeviceFormat, i_param_size )); msg_Dbg( p_aout, STREAM_FORMAT_MSG( "we set the AU format: " , DeviceFormat ) ); /* Retrieve actual format */ verify_noerr( AudioUnitGetProperty( p_sys->au_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &DeviceFormat, &i_param_size )); msg_Dbg( p_aout, STREAM_FORMAT_MSG( "the actual set AU format is " , DeviceFormat ) ); /* Do the last VLC aout setups */ aout_FormatPrepare( &p_aout->output.output ); p_aout->output.i_nb_samples = 2048; aout_VolumeSoftInit( p_aout ); /* set the IOproc callback */ input.inputProc = (AURenderCallback) RenderCallbackAnalog; input.inputProcRefCon = p_aout; verify_noerr( AudioUnitSetProperty( p_sys->au_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof( input ) ) ); input.inputProc = (AURenderCallback) RenderCallbackAnalog; input.inputProcRefCon = p_aout; /* Set the new_layout as the layout VLC will use to feed the AU unit */ verify_noerr( AudioUnitSetProperty( p_sys->au_unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &new_layout, sizeof(new_layout) ) ); if( new_layout.mNumberChannelDescriptions > 0 ) free( new_layout.mChannelDescriptions ); /* AU initiliaze */ verify_noerr( AudioUnitInitialize(p_sys->au_unit) ); /* Find the difference between device clock and mdate clock */ p_sys->clock_diff = - (mtime_t) AudioConvertHostTimeToNanos( AudioGetCurrentHostTime() ) / 1000; p_sys->clock_diff += mdate(); /* Start the AU */ verify_noerr( AudioOutputUnitStart(p_sys->au_unit) ); return VLC_TRUE;}/***************************************************************************** * Setup a encoded digital stream (SPDIF) *****************************************************************************/static int OpenSPDIF( aout_instance_t * p_aout ){ struct aout_sys_t *p_sys = p_aout->output.p_sys; OSStatus err = noErr; UInt32 i_param_size = 0, b_mix = 0; Boolean b_writeable = VLC_FALSE; AudioStreamID *p_streams = NULL; int i = 0, i_streams = 0; /* Start doing the SPDIF setup proces */ p_sys->b_digital = VLC_TRUE; /* Hog the device */ i_param_size = sizeof( p_sys->i_hog_pid ); p_sys->i_hog_pid = getpid() ; err = AudioDeviceSetProperty( p_sys->i_selected_dev, 0, 0, FALSE, kAudioDevicePropertyHogMode, i_param_size, &p_sys->i_hog_pid ); if( err != noErr ) { msg_Err( p_aout, "failed to set hogmode: [%4.4s]", (char *)&err ); return VLC_FALSE; } /* Set mixable to false if we are allowed to */ err = AudioDeviceGetPropertyInfo( p_sys->i_selected_dev, 0, FALSE, kAudioDevicePropertySupportsMixing, &i_param_size, &b_writeable ); err = AudioDeviceGetProperty( p_sys->i_selected_dev, 0, FALSE, kAudioDevicePropertySupportsMixing, &i_param_size, &b_mix ); if( !err && b_writeable ) { b_mix = 0; err = AudioDeviceSetProperty( p_sys->i_selected_dev, 0, 0, FALSE, kAudioDevicePropertySupportsMixing, i_param_size, &b_mix ); p_sys->b_changed_mixing = VLC_TRUE; } if( err != noErr ) { msg_Err( p_aout, "failed to set mixmode: [%4.4s]", (char *)&err ); return VLC_FALSE; } /* Get a list of all the streams on this device */ err = AudioDeviceGetPropertyInfo( p_sys->i_selected_dev, 0, FALSE, kAudioDevicePropertyStreams, &i_param_size, NULL ); if( err != noErr ) { msg_Err( p_aout, "could not get number of streams: [%4.4s]", (char *)&err ); return VLC_FALSE; } i_streams = i_param_size / sizeof( AudioStreamID ); p_streams = (AudioStreamID *)malloc( i_param_size ); if( p_streams == NULL ) { msg_Err( p_aout, "out of memory" ); return VLC_FALSE; } err = AudioDeviceGetProperty( p_sys->i_selected_dev, 0, FALSE, kAudioDevicePropertyStreams, &i_param_size, p_streams ); if( err != noErr ) { msg_Err( p_aout, "could not get number of streams: [%4.4s]", (char *)&err ); if( p_streams ) free( p_streams ); return VLC_FALSE; } for( i = 0; i < i_streams && p_sys->i_stream_index < 0 ; i++ ) { /* Find a stream with a cac3 stream */ AudioStreamBasicDescription *p_format_list = NULL; int i_formats = 0, j = 0; vlc_bool_t b_digital = VLC_FALSE; /* Retrieve all the stream formats supported by each output stream */ err = AudioStreamGetPropertyInfo( p_streams[i], 0, kAudioStreamPropertyPhysicalFormats, &i_param_size, NULL ); if( err != noErr ) { msg_Err( p_aout, "could not get number of streamformats: [%4.4s]", (char *)&err ); continue; } 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" ); continue; } err = AudioStreamGetProperty( p_streams[i], 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 ); if( p_format_list) free( p_format_list); continue; } /* Check if one of the supported formats is a digital format */ for( j = 0; j < i_formats; j++ ) { if( p_format_list[j].mFormatID == 'IAC3' || p_format_list[j].mFormatID == kAudioFormat60958AC3 ) { b_digital = VLC_TRUE; break; } } if( b_digital ) { /* if this stream supports a digital (cac3) format, then go set it. */ int i_requested_rate_format = -1; int i_current_rate_format = -1; int i_backup_rate_format = -1; p_sys->i_stream_id = p_streams[i]; p_sys->i_stream_index = i; if( p_sys->b_revert == VLC_FALSE ) { /* Retrieve the original format of this stream first if not done so already */ i_param_size = sizeof( p_sys->sfmt_revert ); err = AudioStreamGetProperty( p_sys->i_stream_id, 0, kAudioStreamPropertyPhysicalFormat, &i_param_size, &p_sys->sfmt_revert ); if( err != noErr ) { msg_Err( p_aout, "could not retrieve the original streamformat: [%4.4s]", (char *)&err ); continue; } p_sys->b_revert = VLC_TRUE; } for( j = 0; j < i_formats; j++ ) { if( p_format_list[j].mFormatID == 'IAC3' || p_format_list[j].mFormatID == kAudioFormat60958AC3 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -