[vlc-commits] audiounit_ios: add AC3/DTS passthrough support
Thomas Guillem
git at videolan.org
Fri Mar 3 16:56:36 CET 2017
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Fri Mar 3 10:50:29 2017 +0100| [8f1ae66aee9c6b45a0e75ec579d3d4bb333cc289] | committer: Thomas Guillem
audiounit_ios: add AC3/DTS passthrough support
As there is no way to know if an audio device support a codec via passthrough.
The encoded output should be enabled by the user via the following libvlc call:
libvlc_audio_output_device_set(mp, NULL, "ENCODED");
Even if the ENCODED output is selected, passthrough will be selected only if
the current port is USB or HDMI.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8f1ae66aee9c6b45a0e75ec579d3d4bb333cc289
---
modules/audio_output/audiounit_ios.m | 75 ++++++++++++++++++++++++++++++---
modules/audio_output/coreaudio_common.c | 39 +++++++++++------
2 files changed, 97 insertions(+), 17 deletions(-)
diff --git a/modules/audio_output/audiounit_ios.m b/modules/audio_output/audiounit_ios.m
index d636c4d..5884e1a 100644
--- a/modules/audio_output/audiounit_ios.m
+++ b/modules/audio_output/audiounit_ios.m
@@ -56,6 +56,22 @@ vlc_module_end ()
@property (readonly, assign) audio_output_t* aout;
@end
+enum au_dev
+{
+ AU_DEV_PCM,
+ AU_DEV_ENCODED,
+};
+
+static const struct {
+ const char *psz_id;
+ const char *psz_name;
+ enum au_dev au_dev;
+} au_devs[] = {
+ { "PCM", "Up to 9 channels PCM output", AU_DEV_PCM },
+ { "ENCODED", "Encoded output if available (via HDMI/SPDIF) or PCM output",
+ AU_DEV_ENCODED },
+};
+
/*****************************************************************************
* aout_sys_t: private audio output method descriptor
*****************************************************************************
@@ -72,6 +88,7 @@ struct aout_sys_t
AudioUnit au_unit;
bool b_muted;
bool b_preferred_channels_set;
+ enum au_dev au_dev;
};
enum port_type
@@ -115,6 +132,10 @@ avas_setPreferredNumberOfChannels(audio_output_t *p_aout,
const audio_sample_format_t *fmt)
{
struct aout_sys_t *p_sys = p_aout->sys;
+
+ if (aout_BitsPerSample(fmt->i_format) == 0)
+ return; /* Don't touch the number of channels for passthrough */
+
AVAudioSession *instance = p_sys->avInstance;
NSInteger max_channel_count = [instance maximumOutputNumberOfChannels];
unsigned channel_count = aout_FormatNbChannels(fmt);
@@ -356,8 +377,7 @@ Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
OSStatus status;
AudioChannelLayout *layout = NULL;
- if (aout_FormatNbChannels(fmt) == 0
- || aout_BitsPerSample(fmt->i_format) == 0 /* No Passthrough support */)
+ if (aout_FormatNbChannels(fmt) == 0 || AOUT_FMT_HDMI(fmt))
return VLC_EGENERIC;
aout_FormatPrint(p_aout, "VLC is looking for:", fmt);
@@ -377,8 +397,20 @@ Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
if (ret != VLC_SUCCESS)
goto error;
- /* TODO: Do passthrough if dev_type allows it */
- fmt->i_format = VLC_CODEC_FL32;
+ if (AOUT_FMT_SPDIF(fmt))
+ {
+ if (p_sys->au_dev != AU_DEV_ENCODED
+ || (port_type != PORT_TYPE_USB && port_type != PORT_TYPE_HDMI))
+ goto error;
+
+ fmt->i_format = VLC_CODEC_SPDIFL;
+ fmt->i_bytes_per_frame = 4;
+ fmt->i_frame_length = 1;
+ free(layout);
+ layout = NULL;
+ }
+ else
+ fmt->i_format = VLC_CODEC_FL32;
p_sys->au_unit = au_NewOutputInstance(p_aout, kAudioUnitSubType_RemoteIO);
if (p_sys->au_unit == NULL)
@@ -416,7 +448,8 @@ Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
free(layout);
p_aout->mute_set = MuteSet;
p_aout->pause = Pause;
- msg_Dbg(p_aout, "analog AudioUnit output successfully opened");
+ msg_Dbg(p_aout, "analog AudioUnit output successfully opened for %4.4s %s",
+ (const char *)&fmt->i_format, aout_FormatPrintChannels(fmt));
return VLC_SUCCESS;
error:
@@ -430,6 +463,33 @@ error:
return VLC_EGENERIC;
}
+static int DeviceSelect(audio_output_t *p_aout, const char *psz_id)
+{
+ aout_sys_t *p_sys = p_aout->sys;
+ enum au_dev au_dev = AU_DEV_PCM;
+
+ if (psz_id)
+ {
+ for (unsigned int i = 0; i < sizeof(au_devs) / sizeof(au_devs[0]); ++i)
+ {
+ if (!strcmp(psz_id, au_devs[i].psz_id))
+ {
+ au_dev = au_devs[i].au_dev;
+ break;
+ }
+ }
+ }
+
+ if (au_dev != p_sys->au_dev)
+ {
+ p_sys->au_dev = au_dev;
+ aout_RestartRequest(p_aout, AOUT_RESTART_OUTPUT);
+ msg_Dbg(p_aout, "selected audiounit device: %s", psz_id);
+ }
+ aout_DeviceReport(p_aout, psz_id);
+ return VLC_SUCCESS;
+}
+
static void
Close(vlc_object_t *obj)
{
@@ -462,9 +522,14 @@ Open(vlc_object_t *obj)
sys->b_muted = false;
sys->b_preferred_channels_set = false;
+ sys->au_dev = AU_DEV_PCM;
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
+ aout->device_select = DeviceSelect;
+
+ for (unsigned int i = 0; i< sizeof(au_devs) / sizeof(au_devs[0]); ++i)
+ aout_HotplugReport(aout, au_devs[i].psz_id, au_devs[i].psz_name);
return VLC_SUCCESS;
}
diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c
index 985b770..e3e205a 100644
--- a/modules/audio_output/coreaudio_common.c
+++ b/modules/audio_output/coreaudio_common.c
@@ -626,25 +626,40 @@ int
au_Initialize(audio_output_t *p_aout, AudioUnit au, audio_sample_format_t *fmt,
const AudioChannelLayout *outlayout, mtime_t i_dev_latency_us)
{
- assert(fmt->i_format == VLC_CODEC_FL32);
-
- int ret = MapOutputLayout(p_aout, fmt, outlayout);
- if (ret != VLC_SUCCESS)
- return ret;
-
+ int ret;
AudioChannelLayoutTag inlayout_tag;
- ret = SetupInputLayout(p_aout, fmt, &inlayout_tag);
- if (ret != VLC_SUCCESS)
- return ret;
/* Set the desired format */
AudioStreamBasicDescription desc;
+ if (fmt->i_format == VLC_CODEC_FL32)
+ {
+ ret = MapOutputLayout(p_aout, fmt, outlayout);
+ if (ret != VLC_SUCCESS)
+ return ret;
+
+ ret = SetupInputLayout(p_aout, fmt, &inlayout_tag);
+ if (ret != VLC_SUCCESS)
+ return ret;
+
+ desc.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
+ desc.mChannelsPerFrame = aout_FormatNbChannels(fmt);
+ desc.mBitsPerChannel = 32;
+ }
+ else
+ {
+ /* Passthrough */
+ assert(fmt->i_format == VLC_CODEC_SPDIFL);
+
+ inlayout_tag = kAudioChannelLayoutTag_Stereo;
+
+ desc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
+ kLinearPCMFormatFlagIsPacked; /* S16LE */
+ desc.mChannelsPerFrame = 2;
+ desc.mBitsPerChannel = 16;
+ }
desc.mSampleRate = fmt->i_rate;
desc.mFormatID = kAudioFormatLinearPCM;
- desc.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
- desc.mChannelsPerFrame = aout_FormatNbChannels(fmt);
desc.mFramesPerPacket = 1;
- desc.mBitsPerChannel = 32;
desc.mBytesPerFrame = desc.mBitsPerChannel * desc.mChannelsPerFrame / 8;
desc.mBytesPerPacket = desc.mBytesPerFrame * desc.mFramesPerPacket;
More information about the vlc-commits
mailing list