osxaudio: Avoid making a duplicate structure in caps for mono/stereo case
[platform/upstream/gstreamer.git] / sys / osxaudio / gstosxcoreaudio.c
1 /*
2  * GStreamer
3  * Copyright (C) 2012-2013 Fluendo S.A. <support@fluendo.com>
4  *   Authors: Josep Torra Vallès <josep@fluendo.com>
5  *            Andoni Morales Alastruey <amorales@fluendo.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  */
23
24 #include "gstosxcoreaudio.h"
25 #include "gstosxcoreaudiocommon.h"
26
27 GST_DEBUG_CATEGORY_STATIC (osx_audio_debug);
28 #define GST_CAT_DEFAULT osx_audio_debug
29
30 G_DEFINE_TYPE (GstCoreAudio, gst_core_audio, G_TYPE_OBJECT);
31
32 #ifdef HAVE_IOS
33 #include "gstosxcoreaudioremoteio.c"
34 #else
35 #include "gstosxcoreaudiohal.c"
36 #endif
37
38
39 static void
40 gst_core_audio_class_init (GstCoreAudioClass * klass)
41 {
42 }
43
44 static void
45 gst_core_audio_init (GstCoreAudio * core_audio)
46 {
47   core_audio->is_passthrough = FALSE;
48   core_audio->device_id = kAudioDeviceUnknown;
49   core_audio->is_src = FALSE;
50   core_audio->audiounit = NULL;
51   core_audio->cached_caps = NULL;
52   core_audio->cached_caps_valid = FALSE;
53 #ifndef HAVE_IOS
54   core_audio->hog_pid = -1;
55   core_audio->disabled_mixing = FALSE;
56 #endif
57 }
58
59 static gboolean
60 _is_outer_scope (AudioUnitScope scope, AudioUnitElement element)
61 {
62   return
63       (scope == kAudioUnitScope_Input && element == 1) ||
64       (scope == kAudioUnitScope_Output && element == 0);
65 }
66
67 static void
68 _audio_unit_property_listener (void *inRefCon, AudioUnit inUnit,
69     AudioUnitPropertyID inID, AudioUnitScope inScope,
70     AudioUnitElement inElement)
71 {
72   GstCoreAudio *core_audio;
73
74   core_audio = GST_CORE_AUDIO (inRefCon);
75   g_assert (inUnit == core_audio->audiounit);
76
77   switch (inID) {
78     case kAudioUnitProperty_AudioChannelLayout:
79     case kAudioUnitProperty_StreamFormat:
80       if (_is_outer_scope (inScope, inElement)) {
81         /* We don't push gst_event_new_caps here (for src),
82          * nor gst_event_new_reconfigure (for sink), since Core Audio continues
83          * to happily function with the old format, doing conversion/resampling
84          * as needed.
85          * This merely "refreshes" our PREFERRED caps. */
86
87         /* This function is called either from a Core Audio thread
88          * or as a result of a Core Audio API (e.g. AudioUnitInitialize)
89          * from our own thread. In the latter case, osxbuf can be
90          * already locked (GStreamer's mutex is not recursive).
91          * For this reason we use a boolean flag instead of nullifying
92          * cached_caps. */
93         core_audio->cached_caps_valid = FALSE;
94       }
95       break;
96   }
97 }
98
99 /**************************
100  *       Public API       *
101  *************************/
102
103 GstCoreAudio *
104 gst_core_audio_new (GstObject * osxbuf)
105 {
106   GstCoreAudio *core_audio;
107
108   core_audio = g_object_new (GST_TYPE_CORE_AUDIO, NULL);
109   core_audio->osxbuf = osxbuf;
110   core_audio->cached_caps = NULL;
111   return core_audio;
112 }
113
114 gboolean
115 gst_core_audio_close (GstCoreAudio * core_audio)
116 {
117   OSStatus status;
118
119   /* Uninitialize the AudioUnit */
120   status = AudioUnitUninitialize (core_audio->audiounit);
121   if (status) {
122     GST_ERROR_OBJECT (core_audio, "Failed to uninitialize AudioUnit: %d",
123         (int) status);
124     return FALSE;
125   }
126
127   AudioUnitRemovePropertyListenerWithUserData (core_audio->audiounit,
128       kAudioUnitProperty_AudioChannelLayout, _audio_unit_property_listener,
129       core_audio);
130   AudioUnitRemovePropertyListenerWithUserData (core_audio->audiounit,
131       kAudioUnitProperty_StreamFormat, _audio_unit_property_listener,
132       core_audio);
133
134   /* core_audio->osxbuf is already locked at this point */
135   core_audio->cached_caps_valid = FALSE;
136   gst_caps_replace (&core_audio->cached_caps, NULL);
137
138   AudioComponentInstanceDispose (core_audio->audiounit);
139   core_audio->audiounit = NULL;
140   return TRUE;
141 }
142
143 gboolean
144 gst_core_audio_open (GstCoreAudio * core_audio)
145 {
146   OSStatus status;
147
148   /* core_audio->osxbuf is already locked at this point */
149   core_audio->cached_caps_valid = FALSE;
150   gst_caps_replace (&core_audio->cached_caps, NULL);
151
152   if (!gst_core_audio_open_impl (core_audio))
153     return FALSE;
154
155   /* Add property listener */
156   status = AudioUnitAddPropertyListener (core_audio->audiounit,
157       kAudioUnitProperty_AudioChannelLayout, _audio_unit_property_listener,
158       core_audio);
159   if (status != noErr) {
160     GST_ERROR_OBJECT (core_audio, "Failed to add audio channel layout property "
161         "listener for AudioUnit: %d", (int) status);
162   }
163   status = AudioUnitAddPropertyListener (core_audio->audiounit,
164       kAudioUnitProperty_StreamFormat, _audio_unit_property_listener,
165       core_audio);
166   if (status != noErr) {
167     GST_ERROR_OBJECT (core_audio, "Failed to add stream format property "
168         "listener for AudioUnit: %d", (int) status);
169   }
170
171   /* Initialize the AudioUnit. We keep the audio unit initialized early so that
172    * we can probe the underlying device. */
173   status = AudioUnitInitialize (core_audio->audiounit);
174   if (status) {
175     GST_ERROR_OBJECT (core_audio, "Failed to initialize AudioUnit: %d",
176         (int) status);
177     return FALSE;
178   }
179
180   return TRUE;
181 }
182
183 gboolean
184 gst_core_audio_start_processing (GstCoreAudio * core_audio)
185 {
186   return gst_core_audio_start_processing_impl (core_audio);
187 }
188
189 gboolean
190 gst_core_audio_pause_processing (GstCoreAudio * core_audio)
191 {
192   return gst_core_audio_pause_processing_impl (core_audio);
193 }
194
195 gboolean
196 gst_core_audio_stop_processing (GstCoreAudio * core_audio)
197 {
198   return gst_core_audio_stop_processing_impl (core_audio);
199 }
200
201 gboolean
202 gst_core_audio_get_samples_and_latency (GstCoreAudio * core_audio,
203     gdouble rate, guint * samples, gdouble * latency)
204 {
205   return gst_core_audio_get_samples_and_latency_impl (core_audio, rate,
206       samples, latency);
207 }
208
209 gboolean
210 gst_core_audio_initialize (GstCoreAudio * core_audio,
211     AudioStreamBasicDescription format, GstCaps * caps, gboolean is_passthrough)
212 {
213   guint32 frame_size;
214
215   GST_DEBUG_OBJECT (core_audio,
216       "Initializing: passthrough:%d caps:%" GST_PTR_FORMAT, is_passthrough,
217       caps);
218
219   if (!gst_core_audio_initialize_impl (core_audio, format, caps,
220           is_passthrough, &frame_size)) {
221     return FALSE;
222   }
223
224   if (core_audio->is_src) {
225     /* create AudioBufferList needed for recording */
226     core_audio->recBufferSize = frame_size * format.mBytesPerFrame;
227     core_audio->recBufferList =
228         buffer_list_alloc (format.mChannelsPerFrame, core_audio->recBufferSize,
229         /* Currently always TRUE (i.e. interleaved) */
230         !(format.mFormatFlags & kAudioFormatFlagIsNonInterleaved));
231   }
232
233   return TRUE;
234 }
235
236 void
237 gst_core_audio_uninitialize (GstCoreAudio * core_audio)
238 {
239   buffer_list_free (core_audio->recBufferList);
240   core_audio->recBufferList = NULL;
241 }
242
243 void
244 gst_core_audio_set_volume (GstCoreAudio * core_audio, gfloat volume)
245 {
246   AudioUnitSetParameter (core_audio->audiounit, kHALOutputParam_Volume,
247       kAudioUnitScope_Global, 0, (float) volume, 0);
248 }
249
250 gboolean
251 gst_core_audio_select_device (GstCoreAudio * core_audio)
252 {
253   return gst_core_audio_select_device_impl (core_audio);
254 }
255
256 void
257 gst_core_audio_init_debug (void)
258 {
259   GST_DEBUG_CATEGORY_INIT (osx_audio_debug, "osxaudio", 0,
260       "OSX Audio Elements");
261 }
262
263 gboolean
264 gst_core_audio_audio_device_is_spdif_avail (AudioDeviceID device_id)
265 {
266   return gst_core_audio_audio_device_is_spdif_avail_impl (device_id);
267 }
268
269 /* Does the channel have at least one positioned channel?
270  * (GStreamer is more strict than Core Audio, in that it requires either
271  * all channels to be positioned, or all unpositioned.) */
272 static gboolean
273 _is_core_audio_layout_positioned (AudioChannelLayout * layout)
274 {
275   guint i;
276
277   g_assert (layout->mChannelLayoutTag ==
278       kAudioChannelLayoutTag_UseChannelDescriptions);
279
280   for (i = 0; i < layout->mNumberChannelDescriptions; ++i) {
281     GstAudioChannelPosition p =
282         gst_core_audio_channel_label_to_gst
283         (layout->mChannelDescriptions[i].mChannelLabel, i, FALSE);
284
285     if (p >= 0)                 /* not special positition */
286       return TRUE;
287   }
288
289   return FALSE;
290 }
291
292 static void
293 _core_audio_parse_channel_descriptions (AudioChannelLayout * layout,
294     guint * channels, guint64 * channel_mask, GstAudioChannelPosition * pos)
295 {
296   gboolean positioned;
297   guint i;
298
299   g_assert (layout->mChannelLayoutTag ==
300       kAudioChannelLayoutTag_UseChannelDescriptions);
301
302   positioned = _is_core_audio_layout_positioned (layout);
303   *channel_mask = 0;
304
305   /* Go over all labels, either taking only positioned or only
306    * unpositioned channels, up to GST_OSX_AUDIO_MAX_CHANNEL channels.
307    *
308    * The resulting 'pos' array will contain either:
309    *  - only regular (>= 0) positions
310    *  - only GST_AUDIO_CHANNEL_POSITION_NONE positions
311    * in a compact form, skipping over all unsupported positions.
312    */
313   *channels = 0;
314   for (i = 0; i < layout->mNumberChannelDescriptions; ++i) {
315     GstAudioChannelPosition p =
316         gst_core_audio_channel_label_to_gst
317         (layout->mChannelDescriptions[i].mChannelLabel, i, TRUE);
318
319     /* In positioned layouts, skip all unpositioned channels.
320      * In unpositioned layouts, skip all invalid channels. */
321     if ((positioned && p >= 0) ||
322         (!positioned && p == GST_AUDIO_CHANNEL_POSITION_NONE)) {
323
324       if (pos)
325         pos[*channels] = p;
326       *channel_mask |= G_GUINT64_CONSTANT (1) << p;
327       ++(*channels);
328
329       if (*channels == GST_OSX_AUDIO_MAX_CHANNEL)
330         break;                  /* not to overflow */
331     }
332   }
333 }
334
335 gboolean
336 gst_core_audio_parse_channel_layout (AudioChannelLayout * layout,
337     guint * channels, guint64 * channel_mask, GstAudioChannelPosition * pos)
338 {
339   g_assert (channels != NULL);
340   g_assert (channel_mask != NULL);
341   g_assert (layout != NULL);
342
343   if (layout->mChannelLayoutTag !=
344       kAudioChannelLayoutTag_UseChannelDescriptions) {
345     GST_ERROR
346         ("Only kAudioChannelLayoutTag_UseChannelDescriptions is supported.");
347     *channels = 0;
348     *channel_mask = 0;
349     return FALSE;
350   }
351
352   switch (layout->mNumberChannelDescriptions) {
353     case 0:
354       if (pos)
355         pos[0] = GST_AUDIO_CHANNEL_POSITION_NONE;
356       *channels = 0;
357       *channel_mask = 0;
358       return TRUE;
359     case 1:
360       if (pos)
361         pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
362       *channels = 1;
363       *channel_mask = 0;
364       return TRUE;
365     case 2:
366       if (pos) {
367         pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
368         pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
369       }
370       *channels = 2;
371       *channel_mask =
372           GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
373           GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
374       return TRUE;
375     default:
376       _core_audio_parse_channel_descriptions (layout, channels, channel_mask,
377           pos);
378       return TRUE;
379   }
380 }
381
382 /* Converts an AudioStreamBasicDescription to preferred caps.
383  *
384  * These caps will indicate the AU element's canonical format, which won't
385  * make Core Audio resample nor convert.
386  *
387  * NOTE ON MULTI-CHANNEL AUDIO:
388  *
389  * If layout is not NULL, resulting caps will only include the subset
390  * of channels supported by GStreamer. If the Core Audio layout contained
391  * ANY positioned channels, then ONLY positioned channels will be included
392  * in the resulting caps. Otherwise, resulting caps will be unpositioned,
393  * and include only unpositioned channels.
394  * (Channels with unsupported AudioChannelLabel will be skipped either way.)
395  *
396  * Naturally, the number of channels indicated by 'channels' can be lower
397  * than the AU element's total number of channels.
398  */
399 GstCaps *
400 gst_core_audio_asbd_to_caps (AudioStreamBasicDescription * asbd,
401     AudioChannelLayout * layout)
402 {
403   GstAudioInfo info;
404   GstAudioFormat format = GST_AUDIO_FORMAT_UNKNOWN;
405   guint rate, channels, bps, endianness;
406   guint64 channel_mask;
407   gboolean sign, interleaved;
408
409   if (asbd->mFormatID != kAudioFormatLinearPCM) {
410     GST_WARNING ("Only linear PCM is supported");
411     goto error;
412   }
413
414   if (!(asbd->mFormatFlags & kAudioFormatFlagIsPacked)) {
415     GST_WARNING ("Only packed formats supported");
416     goto error;
417   }
418
419   if (asbd->mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) {
420     GST_WARNING ("Fixed point audio is unsupported");
421     goto error;
422   }
423
424   rate = asbd->mSampleRate;
425   if (rate == kAudioStreamAnyRate) {
426     GST_WARNING ("No sample rate");
427     goto error;
428   }
429
430   bps = asbd->mBitsPerChannel;
431   endianness = asbd->mFormatFlags & kAudioFormatFlagIsBigEndian ?
432       G_BIG_ENDIAN : G_LITTLE_ENDIAN;
433   sign = asbd->mFormatID & kAudioFormatFlagIsSignedInteger ? TRUE : FALSE;
434   interleaved = asbd->mFormatFlags & kAudioFormatFlagIsNonInterleaved ?
435       TRUE : FALSE;
436
437   if (asbd->mFormatFlags & kAudioFormatFlagIsFloat) {
438     if (bps == 32) {
439       if (endianness == G_LITTLE_ENDIAN)
440         format = GST_AUDIO_FORMAT_F32LE;
441       else
442         format = GST_AUDIO_FORMAT_F32BE;
443
444     } else if (bps == 64) {
445       if (endianness == G_LITTLE_ENDIAN)
446         format = GST_AUDIO_FORMAT_F64LE;
447       else
448         format = GST_AUDIO_FORMAT_F64BE;
449     }
450   } else {
451     format = gst_audio_format_build_integer (sign, endianness, bps, bps);
452   }
453
454   if (format == GST_AUDIO_FORMAT_UNKNOWN) {
455     GST_WARNING ("Unsupported sample format");
456     goto error;
457   }
458
459   if (layout) {
460     GstAudioChannelPosition pos[GST_OSX_AUDIO_MAX_CHANNEL];
461
462     if (!gst_core_audio_parse_channel_layout (layout, &channels, &channel_mask,
463             pos)) {
464       GST_WARNING ("Failed to parse channel layout");
465       goto error;
466     }
467
468     /* The AU can have arbitrary channel order, but we're using GstAudioInfo
469      * which supports only the GStreamer channel order.
470      * Also, we're eventually producing caps, which only have channel-mask
471      * (whose implied order is the GStreamer channel order). */
472     gst_audio_channel_positions_to_valid_order (pos, channels);
473
474     gst_audio_info_set_format (&info, format, rate, channels, pos);
475   } else {
476     channels = MIN (asbd->mChannelsPerFrame, GST_OSX_AUDIO_MAX_CHANNEL);
477     gst_audio_info_set_format (&info, format, rate, channels, NULL);
478   }
479
480   return gst_audio_info_to_caps (&info);
481
482 error:
483   return NULL;
484 }
485
486 static gboolean
487 _core_audio_get_property (GstCoreAudio * core_audio, gboolean outer,
488     AudioUnitPropertyID inID, void *inData, UInt32 * inDataSize)
489 {
490   OSStatus status;
491   AudioUnitScope scope;
492   AudioUnitElement element;
493
494   scope = outer ?
495       CORE_AUDIO_OUTER_SCOPE (core_audio) : CORE_AUDIO_INNER_SCOPE (core_audio);
496   element = CORE_AUDIO_ELEMENT (core_audio);
497
498   status =
499       AudioUnitGetProperty (core_audio->audiounit, inID, scope, element, inData,
500       inDataSize);
501
502   return status == noErr;
503 }
504
505 static gboolean
506 _core_audio_get_stream_format (GstCoreAudio * core_audio,
507     AudioStreamBasicDescription * asbd, gboolean outer)
508 {
509   UInt32 size;
510
511   size = sizeof (AudioStreamBasicDescription);
512   return _core_audio_get_property (core_audio, outer,
513       kAudioUnitProperty_StreamFormat, asbd, &size);
514 }
515
516 AudioChannelLayout *
517 gst_core_audio_get_channel_layout (GstCoreAudio * core_audio, gboolean outer)
518 {
519   UInt32 size;
520   AudioChannelLayout *layout;
521
522   if (core_audio->is_src) {
523     GST_WARNING_OBJECT (core_audio,
524         "gst_core_audio_get_channel_layout not supported on source.");
525     return NULL;
526   }
527
528   if (!_core_audio_get_property (core_audio, outer,
529           kAudioUnitProperty_AudioChannelLayout, NULL, &size)) {
530     GST_WARNING_OBJECT (core_audio, "unable to get channel layout");
531     return NULL;
532   }
533
534   layout = g_malloc (size);
535   if (!_core_audio_get_property (core_audio, outer,
536           kAudioUnitProperty_AudioChannelLayout, layout, &size)) {
537     GST_WARNING_OBJECT (core_audio, "unable to get channel layout");
538     g_free (layout);
539     return NULL;
540   }
541
542   return layout;
543 }
544
545 #define STEREO_CHANNEL_MASK \
546   (GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) | \
547    GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT))
548
549 GstCaps *
550 gst_core_audio_probe_caps (GstCoreAudio * core_audio, GstCaps * in_caps)
551 {
552   guint i, channels;
553   gboolean spdif_allowed;
554   AudioChannelLayout *layout;
555   AudioStreamBasicDescription outer_asbd;
556   gboolean got_outer_asbd;
557   GstCaps *caps = NULL;
558   guint64 channel_mask;
559
560   /* Get the ASBD of the outer scope (i.e. input scope of Input,
561    * output scope of Output).
562    * This ASBD indicates the hardware format. */
563   got_outer_asbd =
564       _core_audio_get_stream_format (core_audio, &outer_asbd, TRUE);
565
566   /* Collect info about the HW capabilites and preferences */
567   spdif_allowed =
568       gst_core_audio_audio_device_is_spdif_avail (core_audio->device_id);
569   layout = gst_core_audio_get_channel_layout (core_audio, TRUE);
570
571   GST_DEBUG_OBJECT (core_audio, "Selected device ID: %u SPDIF allowed: %d",
572       (unsigned) core_audio->device_id, spdif_allowed);
573
574   if (layout) {
575     if (!gst_core_audio_parse_channel_layout (layout, &channels, &channel_mask,
576             NULL)) {
577       GST_WARNING_OBJECT (core_audio, "Failed to parse channel layout");
578       channel_mask = 0;
579     }
580
581     /* If available, start with the preferred caps. */
582     if (got_outer_asbd)
583       caps = gst_core_audio_asbd_to_caps (&outer_asbd, layout);
584
585     g_free (layout);
586   } else if (got_outer_asbd) {
587     channels = outer_asbd.mChannelsPerFrame;
588     channel_mask = 0;
589     /* If available, start with the preferred caps */
590     caps = gst_core_audio_asbd_to_caps (&outer_asbd, NULL);
591   } else {
592     GST_ERROR_OBJECT (core_audio,
593         "Unable to get any information about hardware");
594     return NULL;
595   }
596
597   /* Append the allowed subset based on the template caps  */
598   if (!caps)
599     caps = gst_caps_new_empty ();
600   for (i = 0; i < gst_caps_get_size (in_caps); i++) {
601     GstStructure *in_s;
602
603     in_s = gst_caps_get_structure (in_caps, i);
604
605     if (gst_structure_has_name (in_s, "audio/x-ac3") ||
606         gst_structure_has_name (in_s, "audio/x-dts")) {
607       if (spdif_allowed) {
608         gst_caps_append_structure (caps, gst_structure_copy (in_s));
609       }
610     } else {
611       GstStructure *out_s;
612
613       out_s = gst_structure_copy (in_s);
614       gst_structure_set (out_s, "channels", G_TYPE_INT, channels, NULL);
615       if (channel_mask != 0) {
616         /* positioned layout */
617         gst_structure_set (out_s,
618             "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL);
619       } else {
620         /* unpositioned layout */
621         gst_structure_remove_field (out_s, "channel-mask");
622       }
623
624       /* Special cases for upmixing and downmixing.
625        * Other than that, the AUs don't upmix or downmix multi-channel audio,
626        * e.g. if you push 5.1-surround audio to a stereo configuration,
627        * the left and right channels will be played accordingly,
628        * and the rest will be dropped. */
629
630       if (channels == 1 || (channels == 2 &&
631               (channel_mask == 0 || channel_mask == STEREO_CHANNEL_MASK))) {
632
633         /* If have stereo channels, then also offer mono since CoreAudio
634          * upmixes it. If mono, then also offer stereo since CoreAudio
635          * downmixes to it */
636
637         gst_structure_set (out_s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
638
639         if (channels == 1)
640           gst_structure_set (out_s, "channel-mask", GST_TYPE_BITMASK,
641               STEREO_CHANNEL_MASK, NULL);
642       }
643
644       gst_caps_append_structure (caps, out_s);
645     }
646   }
647
648   return caps;
649 }