]> git.sesse.net Git - vlc/blob - modules/access/qtsound.m
http: correctly strip URI scheme upon redirection (fixes #6872)
[vlc] / modules / access / qtsound.m
1 /*****************************************************************************
2 * qtsound.m: qtkit (Mac OS X) based audio capture module
3 *****************************************************************************
4 * Copyright © 2011 VLC authors and VideoLAN
5 *
6 * Authors: Pierre d'Herbemont <pdherbemont@videolan.org>
7 *          Gustaf Neumann <neumann@wu.ac.at>
8 *          Michael S. Feurstein <michael.feurstein@wu.ac.at>
9 *
10 *****************************************************************************
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
24 *
25 *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_aout.h>
38
39 #include <vlc_demux.h>
40 #include <vlc_dialog.h>
41
42 //#define QTKIT_VERSION_MIN_REQUIRED 70603
43 #define QTKIT_VERSION_MAX_ALLOWED 70700
44
45 #import <QTKit/QTKit.h>
46
47 /*****************************************************************************
48  * Local prototypes.
49  *****************************************************************************/
50 static int Open(vlc_object_t *p_this);
51 static void Close(vlc_object_t *p_this);
52 static int Demux(demux_t *p_demux);
53 static int Control(demux_t *, int, va_list);
54
55 /*****************************************************************************
56  * Module descriptor
57  *****************************************************************************/
58
59 vlc_module_begin()
60 set_shortname(N_("QTSound"))
61 set_description(N_("QuickTime Sound Capture"))
62 set_category(CAT_INPUT)
63 set_subcategory(SUBCAT_INPUT_ACCESS)
64 add_shortcut("qtsound")
65 set_capability("access_demux", 0)
66 set_callbacks(Open, Close)
67 vlc_module_end ()
68
69
70 /*****************************************************************************
71  * QTKit Bridge
72  *****************************************************************************/
73 @interface VLCDecompressedAudioOutput : QTCaptureDecompressedAudioOutput
74 {
75     demux_t *p_qtsound;
76     AudioBuffer *currentAudioBuffer;
77     block_t *rawAudioData;
78     UInt32 numberOfSamples;
79     date_t date;
80     mtime_t currentPts;
81     mtime_t previousPts;
82 }
83 - (id)initWithDemux:(demux_t *)p_demux;
84 - (void)outputAudioSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection;
85 - (BOOL)checkCurrentAudioBuffer;
86 - (void)freeAudioMem;
87 - (mtime_t)getCurrentPts;
88 - (void *)getCurrentAudioBufferData;
89 - (UInt32)getCurrentTotalDataSize;
90 - (UInt32)getNumberOfSamples;
91
92 @end
93
94 @implementation VLCDecompressedAudioOutput : QTCaptureDecompressedAudioOutput
95 - (id)initWithDemux:(demux_t *)p_demux
96 {
97     if (self = [super init]) {
98         p_qtsound = p_demux;
99         currentAudioBuffer = nil;
100         date_Init(&date, 44100, 1);
101         date_Set(&date,0);
102         currentPts = 0;
103         previousPts = 0;
104     }
105     return self;
106 }
107 - (void)dealloc
108 {
109     [super dealloc];
110 }
111
112 - (void)outputAudioSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection
113 {
114     AudioBufferList *tempAudioBufferList;
115     UInt32 totalDataSize = 0;
116     UInt32 count = 0;
117
118     @synchronized (self) {
119         numberOfSamples = [sampleBuffer numberOfSamples];
120         date_Increment(&date,numberOfSamples);
121         currentPts = date_Get(&date);
122
123         tempAudioBufferList = [sampleBuffer audioBufferListWithOptions:0];
124         if (tempAudioBufferList->mNumberBuffers == 2) {
125             /*
126              * Compute totalDataSize as sum of all data blocks in the
127              * audio buffer list:
128              */
129             for (count = 0; count < tempAudioBufferList->mNumberBuffers; count++)
130                 totalDataSize += tempAudioBufferList->mBuffers[count].mDataByteSize;
131
132             /*
133              * Allocate storage for the interleaved audio data
134              */
135             rawAudioData = block_Alloc(totalDataSize * sizeof(float));
136             if (NULL == rawAudioData) {
137                 msg_Err(p_qtsound, "Raw audiodata could not be allocated");
138                 return;
139             }
140         } else {
141             msg_Err(p_qtsound, "Too many or only one channel found.");
142             return;
143         }
144
145         /*
146          * Interleave raw data (provided in two separate channels as
147          * F32L) with 2 samples per frame
148          */
149         if (totalDataSize) {
150             unsigned short i;
151             const float *b1Ptr, *b2Ptr;
152             float *uPtr;
153
154             for (i = 0,
155                  uPtr = (float *)rawAudioData,
156                  b1Ptr = (const float *) tempAudioBufferList->mBuffers[0].mData,
157                  b2Ptr = (const float *) tempAudioBufferList->mBuffers[1].mData;
158                  i < numberOfSamples; i++) {
159                 *uPtr++ = *b1Ptr++;
160                 *uPtr++ = *b2Ptr++;
161             }
162
163             if (currentAudioBuffer == nil) {
164                 currentAudioBuffer = (AudioBuffer *)malloc(sizeof(AudioBuffer));
165                 if (NULL == currentAudioBuffer) {
166                     msg_Err(p_qtsound, "AudioBuffer could not be allocated.");
167                     return;
168                 }
169             }
170             currentAudioBuffer->mNumberChannels = 2;
171             currentAudioBuffer->mDataByteSize = totalDataSize;
172             currentAudioBuffer->mData = rawAudioData;
173         }
174     }
175 }
176
177 - (BOOL)checkCurrentAudioBuffer
178 {
179     return (currentAudioBuffer) ? 1 : 0;
180 }
181
182 - (void)freeAudioMem
183 {
184     @synchronized (self) {
185         if (rawAudioData)
186             free(rawAudioData);
187     }
188 }
189
190 - (mtime_t)getCurrentPts
191 {
192     /* FIXME: can this getter be minimized? */
193     mtime_t pts;
194
195     if(!currentAudioBuffer || currentPts == previousPts)
196         return 0;
197
198     @synchronized (self) {
199         pts = previousPts = currentPts;
200     }
201
202     return (currentAudioBuffer->mData) ? currentPts : 0;
203 }
204
205 - (void *)getCurrentAudioBufferData
206 {
207     return currentAudioBuffer->mData;
208 }
209
210 - (UInt32)getCurrentTotalDataSize
211 {
212     return currentAudioBuffer->mDataByteSize;
213 }
214
215 - (UInt32)getNumberOfSamples
216 {
217     return numberOfSamples;
218 }
219
220 @end
221
222 /*****************************************************************************
223  * Struct
224  *****************************************************************************/
225
226 struct demux_sys_t {
227     QTCaptureSession * session;
228     QTCaptureDevice * audiodevice;
229     VLCDecompressedAudioOutput * audiooutput;
230     es_out_id_t *p_es_audio;
231     int i_audio_max_buffer_size;
232 };
233
234 /*****************************************************************************
235  * Open: initialize interface
236  *****************************************************************************/
237 static int Open(vlc_object_t *p_this)
238 {
239     demux_t *p_demux = (demux_t*)p_this;
240     demux_sys_t *p_sys;
241     es_format_t audiofmt;
242     char *psz_uid = NULL;
243     int audiocodec;
244     bool success;
245     NSString *qtk_curraudiodevice_uid;
246     NSAutoreleasePool *pool;
247     NSArray *myAudioDevices, *audioformat_array;
248     QTFormatDescription *audio_format;
249     QTCaptureDeviceInput *audioInput;
250     NSError *o_returnedAudioError;
251
252     if(p_demux->psz_location && *p_demux->psz_location)
253         psz_uid = p_demux->psz_location;
254
255     msg_Dbg(p_demux, "qtsound uid = %s", psz_uid);
256     qtk_curraudiodevice_uid = [[NSString alloc] initWithFormat:@"%s", psz_uid];
257
258     pool = [[NSAutoreleasePool alloc] init];
259
260     p_demux->p_sys = p_sys = calloc(1, sizeof(demux_sys_t));
261     if(!p_sys)
262         return VLC_ENOMEM;
263
264     msg_Dbg(p_demux, "qtsound : uid = %s", [qtk_curraudiodevice_uid UTF8String]);
265     myAudioDevices = [[[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeSound] arrayByAddingObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeMuxed]] retain];
266     if([myAudioDevices count] == 0) {
267         dialog_FatalWait(p_demux, _("No Audio Input device found"),
268                          _("Your Mac does not seem to be equipped with a suitable audio input device."
269                      "Please check your connectors and drivers."));
270         msg_Err(p_demux, "Can't find any Audio device");
271
272         goto error;
273     }
274     unsigned iaudio;
275     for (iaudio = 0; iaudio < [myAudioDevices count]; iaudio++) {
276         QTCaptureDevice *qtk_audioDevice;
277         qtk_audioDevice = [myAudioDevices objectAtIndex:iaudio];
278         msg_Dbg(p_demux, "qtsound audio %u/%lu localizedDisplayName: %s uniqueID: %s", iaudio, [myAudioDevices count], [[qtk_audioDevice localizedDisplayName] UTF8String], [[qtk_audioDevice uniqueID] UTF8String]);
279         if ([[[qtk_audioDevice uniqueID]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isEqualToString:qtk_curraudiodevice_uid]) {
280             msg_Dbg(p_demux, "Device found");
281             break;
282         }
283     }
284
285     audioInput = nil;
286     if(iaudio < [myAudioDevices count])
287         p_sys->audiodevice = [myAudioDevices objectAtIndex:iaudio];
288     else {
289         /* cannot find designated audio device, fall back to open default audio device */
290         msg_Dbg(p_demux, "Cannot find designated uid audio device as %s. Fall back to open default audio device.", [qtk_curraudiodevice_uid UTF8String]);
291         p_sys->audiodevice = [QTCaptureDevice defaultInputDeviceWithMediaType: QTMediaTypeSound];
292     }
293     if(!p_sys->audiodevice) {
294         dialog_FatalWait(p_demux, _("No audio input device found"),
295                          _("Your Mac does not seem to be equipped with a suitable audio input device."
296                      "Please check your connectors and drivers."));
297         msg_Err(p_demux, "Can't find any Audio device");
298
299         goto error;
300     }
301
302     if(![p_sys->audiodevice open: &o_returnedAudioError]) {
303         msg_Err(p_demux, "Unable to open the audio capture device (%ld)", [o_returnedAudioError code]);
304         goto error;
305     }
306
307     if([p_sys->audiodevice isInUseByAnotherApplication] == YES) {
308         msg_Err(p_demux, "default audio capture device is exclusively in use by another application");
309         goto error;
310     }
311     audioInput = [[QTCaptureDeviceInput alloc] initWithDevice: p_sys->audiodevice];
312     if(!audioInput) {
313         msg_Err(p_demux, "can't create a valid audio capture input facility");
314         goto error;
315     } else
316         msg_Dbg(p_demux, "created valid audio capture input facility");
317
318     p_sys->audiooutput = [[VLCDecompressedAudioOutput alloc] initWithDemux:p_demux];
319     msg_Dbg (p_demux, "initialized audio output");
320
321     /* Get the formats */
322     /*
323      FIXME: the format description gathered here does not seem to be the same
324      in comparison to the format description collected from the actual sampleBuffer.
325      This information needs to be updated some other place. For the time being this shall suffice.
326
327      The following verbose output is an example of what is read from the input device during the below block
328      [0x3042138] qtsound demux debug: Audio localized format summary: Linear PCM, 24 bit little-endian signed integer, 2 channels, 44100 Hz
329      [0x3042138] qtsound demux debug: Sample Rate: 44100; Format ID: lpcm; Format Flags: 00000004; Bytes per Packet: 8; Frames per Packet: 1; Bytes per Frame: 8; Channels per Frame: 2; Bits per Channel: 24
330      [0x3042138] qtsound demux debug: Flag float 0 bigEndian 0 signedInt 1 packed 0 alignedHigh 0 non interleaved 0 non mixable 0
331      canonical 0 nativeFloatPacked 0 nativeEndian 0
332
333      However when reading this information from the sampleBuffer during the delegate call from
334      - (void)outputAudioSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection;
335      the following data shows up
336      2011-09-23 22:06:03.077 VLC[23070:f103] Audio localized format summary: Linear PCM, 32 bit little-endian floating point, 2 channels, 44100 Hz
337      2011-09-23 22:06:03.078 VLC[23070:f103] Sample Rate: 44100; Format ID: lpcm; Format Flags: 00000029; Bytes per Packet: 4; Frames per Packet: 1; Bytes per Frame: 4; Channels per Frame: 2; Bits per Channel: 32
338      2011-09-23 22:06:03.078 VLC[23070:f103] Flag float 1 bigEndian 0 signedInt 0 packed 1 alignedHigh 0 non interleaved 1 non mixable 0
339      canonical 1 nativeFloatPacked 1 nativeEndian 0
340
341      Note the differences
342      24bit vs. 32bit
343      little-endian signed integer vs. little-endian floating point
344      format flag 00000004 vs. 00000029
345      bytes per packet 8 vs. 4
346      packed 0 vs. 1
347      non interleaved 0 vs. 1 -> this makes a major difference when filling our own buffer
348      canonical 0 vs. 1
349      nativeFloatPacked 0 vs. 1
350
351      One would assume we'd need to feed the (es_format_t)audiofmt with the data collected here.
352      This is not the case. Audio will be transmitted in artefacts, due to wrong information.
353
354      At the moment this data is set manually, however one should consider trying to set this data dynamically
355      */
356     audioformat_array = [p_sys->audiodevice formatDescriptions];
357     audio_format = NULL;
358     for(int k = 0; k < [audioformat_array count]; k++) {
359         audio_format = (QTFormatDescription *)[audioformat_array objectAtIndex: k];
360
361         msg_Dbg(p_demux, "Audio localized format summary: %s", [[audio_format localizedFormatSummary] UTF8String]);
362         msg_Dbg(p_demux, "Audio format description attributes: %s",[[[audio_format formatDescriptionAttributes] description] UTF8String]);
363
364         AudioStreamBasicDescription asbd = {0};
365         NSValue *asbdValue =  [audio_format attributeForKey:QTFormatDescriptionAudioStreamBasicDescriptionAttribute];
366         [asbdValue getValue:&asbd];
367
368         char formatIDString[5];
369         UInt32 formatID = CFSwapInt32HostToBig (asbd.mFormatID);
370         bcopy (&formatID, formatIDString, 4);
371         formatIDString[4] = '\0';
372
373         /* kept for development purposes */
374 #if 0
375         msg_Dbg(p_demux, "Sample Rate: %.0lf; Format ID: %s; Format Flags: %.8x; Bytes per Packet: %d; Frames per Packet: %d; Bytes per Frame: %d; Channels per Frame: %d; Bits per Channel: %d",
376                 asbd.mSampleRate,
377                 formatIDString,
378                 asbd.mFormatFlags,
379                 asbd.mBytesPerPacket,
380                 asbd.mFramesPerPacket,
381                 asbd.mBytesPerFrame,
382                 asbd.mChannelsPerFrame,
383                 asbd.mBitsPerChannel);
384
385         msg_Dbg(p_demux, "Flag float %d bigEndian %d signedInt %d packed %d alignedHigh %d non interleaved %d non mixable %d\ncanonical %d nativeFloatPacked %d nativeEndian %d",
386                 (asbd.mFormatFlags & kAudioFormatFlagIsFloat) != 0,
387                 (asbd.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0,
388                 (asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0,
389                 (asbd.mFormatFlags & kAudioFormatFlagIsPacked) != 0,
390                 (asbd.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0,
391                 (asbd.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0,
392                 (asbd.mFormatFlags & kAudioFormatFlagIsNonMixable) != 0,
393
394                 (asbd.mFormatFlags & kAudioFormatFlagsCanonical) != 0,
395                 (asbd.mFormatFlags & kAudioFormatFlagsNativeFloatPacked) != 0,
396                 (asbd.mFormatFlags & kAudioFormatFlagsNativeEndian) != 0
397                );
398 #endif
399     }
400
401     if([audioformat_array count])
402         audio_format = [audioformat_array objectAtIndex: 0];
403     else
404         goto error;
405
406     /* Now we can init */
407     audiocodec = VLC_CODEC_FL32;
408     es_format_Init(&audiofmt, AUDIO_ES, audiocodec);
409
410     audiofmt.audio.i_format = audiocodec;
411     audiofmt.audio.i_rate = 44100;
412     /*
413      * i_physical_channels Describes the channels configuration of the
414      * samples (ie. number of channels which are available in the
415      * buffer, and positions).
416      */
417     audiofmt.audio.i_physical_channels = AOUT_CHAN_RIGHT | AOUT_CHAN_LEFT;
418     /*
419      * i_original_channels Describes from which original channels,
420      * before downmixing, the buffer is derived.
421      */
422     audiofmt.audio.i_original_channels = AOUT_CHAN_RIGHT | AOUT_CHAN_LEFT;
423     /*
424      * Please note that it may be completely arbitrary - buffers are not
425      * obliged to contain a integral number of so-called "frames". It's
426      * just here for the division:
427      * buffer_size = i_nb_samples * i_bytes_per_frame / i_frame_length
428      */
429     audiofmt.audio.i_bitspersample = 32;
430     audiofmt.audio.i_channels = 2;
431     audiofmt.audio.i_blockalign = audiofmt.audio.i_channels * (audiofmt.audio.i_bitspersample / 8);
432     audiofmt.i_bitrate = audiofmt.audio.i_channels * audiofmt.audio.i_rate * audiofmt.audio.i_bitspersample;
433     p_sys->i_audio_max_buffer_size = audiofmt.i_bitrate;
434
435     p_sys->session = [[QTCaptureSession alloc] init];
436
437     success = [p_sys->session addInput:audioInput error: &o_returnedAudioError];
438     if(!success) {
439         msg_Err(p_demux, "the audio capture device could not be added to capture session (%ld)", [o_returnedAudioError code]);
440         goto error;
441     }
442
443     success = [p_sys->session addOutput:p_sys->audiooutput error: &o_returnedAudioError];
444     if(!success) {
445         msg_Err(p_demux, "audio output could not be added to capture session (%ld)", [o_returnedAudioError code]);
446         goto error;
447     }
448
449     [p_sys->session startRunning];
450
451     /* Set up p_demux */
452     p_demux->pf_demux = Demux;
453     p_demux->pf_control = Control;
454     p_demux->info.i_update = 0;
455     p_demux->info.i_title = 0;
456     p_demux->info.i_seekpoint = 0;
457
458     msg_Dbg(p_demux, "New audio es %d channels %dHz",
459             audiofmt.audio.i_channels, audiofmt.audio.i_rate);
460
461     p_sys->p_es_audio = es_out_Add(p_demux->out, &audiofmt);
462
463     [audioInput release];
464     [pool release];
465
466     msg_Dbg(p_demux, "QTSound: We have an audio device ready!");
467
468     return VLC_SUCCESS;
469 error:
470     [audioInput release];
471     [pool release];
472
473     free(p_sys);
474
475     return VLC_EGENERIC;
476 }
477
478 /*****************************************************************************
479  * Close: destroy interface
480  *****************************************************************************/
481 static void Close(vlc_object_t *p_this)
482 {
483     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
484     demux_t *p_demux = (demux_t*)p_this;
485     demux_sys_t *p_sys = p_demux->p_sys;
486
487     [p_sys->session performSelectorOnMainThread:@selector(stopRunning) withObject:nil waitUntilDone:NO];
488     [p_sys->audiooutput performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
489     [p_sys->session performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
490
491     free(p_sys);
492
493     [pool release];
494 }
495
496 /*****************************************************************************
497  * Demux:
498  *****************************************************************************/
499 static int Demux(demux_t *p_demux)
500 {
501     demux_sys_t *p_sys = p_demux->p_sys;
502     block_t *p_blocka;
503     NSAutoreleasePool *pool;
504
505     p_blocka = block_New(p_demux, p_sys->i_audio_max_buffer_size);
506
507     if(!p_blocka) {
508         msg_Err(p_demux, "cannot get audio block");
509         return 0;
510     }
511
512     @synchronized (p_sys->audiooutput) {
513         if ([p_sys->audiooutput checkCurrentAudioBuffer]) {
514             p_blocka->i_buffer = p_blocka->i_size = [p_sys->audiooutput getCurrentTotalDataSize];
515             p_blocka->p_buffer = p_blocka->p_start = [p_sys->audiooutput getCurrentAudioBufferData];
516             p_blocka->i_nb_samples = [p_sys->audiooutput getNumberOfSamples];
517             p_blocka->i_pts = [p_sys->audiooutput getCurrentPts];
518         }
519     }
520
521     if(!p_blocka->i_pts) {
522         // Nothing to transfer yet, just forget
523         block_Release(p_blocka);
524         msleep(10000);
525         return 1;
526     }
527
528     if(p_blocka) {
529         es_out_Control(p_demux->out, ES_OUT_SET_PCR, p_blocka->i_pts);
530         es_out_Send(p_demux->out, p_sys->p_es_audio, p_blocka);
531     }
532
533     @synchronized (p_sys->audiooutput) {
534         [p_sys->audiooutput freeAudioMem];
535     }
536
537     return 1;
538 }
539
540 /*****************************************************************************
541  * Control:
542  *****************************************************************************/
543 static int Control(demux_t *p_demux, int i_query, va_list args)
544 {
545     bool *pb;
546     int64_t *pi64;
547
548     switch(i_query) {
549             /* Special for access_demux */
550         case DEMUX_CAN_PAUSE:
551         case DEMUX_CAN_SEEK:
552         case DEMUX_SET_PAUSE_STATE:
553         case DEMUX_CAN_CONTROL_PACE:
554             pb = (bool*)va_arg(args, bool *);
555             *pb = false;
556             return VLC_SUCCESS;
557
558         case DEMUX_GET_PTS_DELAY:
559             pi64 = (int64_t*)va_arg(args, int64_t *);
560             *pi64 = INT64_C(1000) * var_InheritInteger(p_demux, "live-caching");
561             return VLC_SUCCESS;
562
563         default:
564             return VLC_EGENERIC;
565     }
566     return VLC_EGENERIC;
567 }