1/*
2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#import "config.h"
27
28#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
29
30#import "AVAudioCaptureSource.h"
31
32#import "Logging.h"
33#import "MediaConstraints.h"
34#import "MediaStreamSourceStates.h"
35#import "NotImplemented.h"
36#import "SoftLinking.h"
37#import <AVFoundation/AVFoundation.h>
38#import <objc/runtime.h>
39
40typedef AVCaptureConnection AVCaptureConnectionType;
41typedef AVCaptureDevice AVCaptureDeviceType;
42typedef AVCaptureDeviceInput AVCaptureDeviceInputType;
43typedef AVCaptureOutput AVCaptureOutputType;
44typedef AVCaptureAudioDataOutput AVCaptureAudioDataOutputType;
45
46SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
47
48SOFT_LINK_CLASS(AVFoundation, AVCaptureAudioDataOutput)
49SOFT_LINK_CLASS(AVFoundation, AVCaptureConnection)
50SOFT_LINK_CLASS(AVFoundation, AVCaptureDevice)
51SOFT_LINK_CLASS(AVFoundation, AVCaptureDeviceInput)
52SOFT_LINK_CLASS(AVFoundation, AVCaptureOutput)
53
54#define AVCaptureAudioDataOutput getAVCaptureAudioDataOutputClass()
55#define AVCaptureConnection getAVCaptureConnectionClass()
56#define AVCaptureDevice getAVCaptureDeviceClass()
57#define AVCaptureDeviceInput getAVCaptureDeviceInputClass()
58#define AVCaptureOutput getAVCaptureOutputClass()
59
60SOFT_LINK_POINTER(AVFoundation, AVMediaTypeAudio, NSString *)
61
62#define AVMediaTypeAudio getAVMediaTypeAudio()
63
64namespace WebCore {
65
66RefPtr<AVMediaCaptureSource> AVAudioCaptureSource::create(AVCaptureDeviceType* device, const AtomicString& id, PassRefPtr<MediaConstraints> constraint)
67{
68    return adoptRef(new AVAudioCaptureSource(device, id, constraint));
69}
70
71AVAudioCaptureSource::AVAudioCaptureSource(AVCaptureDeviceType* device, const AtomicString& id, PassRefPtr<MediaConstraints> constraints)
72    : AVMediaCaptureSource(device, id, MediaStreamSource::Audio, constraints)
73{
74    currentStates()->setSourceId(id);
75    currentStates()->setSourceType(MediaStreamSourceStates::Microphone);
76}
77
78AVAudioCaptureSource::~AVAudioCaptureSource()
79{
80}
81
82RefPtr<MediaStreamSourceCapabilities> AVAudioCaptureSource::capabilities() const
83{
84    notImplemented();
85    return 0;
86}
87
88void AVAudioCaptureSource::updateStates()
89{
90    // FIXME: use [AVCaptureAudioPreviewOutput volume] for volume
91}
92
93void AVAudioCaptureSource::setupCaptureSession()
94{
95    RetainPtr<AVCaptureDeviceInputType> audioIn = adoptNS([[AVCaptureDeviceInput alloc] initWithDevice:device() error:nil]);
96    ASSERT([session() canAddInput:audioIn.get()]);
97    if ([session() canAddInput:audioIn.get()])
98        [session() addInput:audioIn.get()];
99
100    RetainPtr<AVCaptureAudioDataOutputType> audioOutput = adoptNS([[AVCaptureAudioDataOutput alloc] init]);
101    setAudioSampleBufferDelegate(audioOutput.get());
102    ASSERT([session() canAddOutput:audioOutput.get()]);
103    if ([session() canAddOutput:audioOutput.get()])
104        [session() addOutput:audioOutput.get()];
105    m_audioConnection = adoptNS([audioOutput.get() connectionWithMediaType:AVMediaTypeAudio]);
106}
107
108void AVAudioCaptureSource::captureOutputDidOutputSampleBufferFromConnection(AVCaptureOutputType*, CMSampleBufferRef sampleBuffer, AVCaptureConnectionType*)
109{
110    CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
111    if (!formatDescription)
112        return;
113
114    CFRetain(formatDescription);
115    m_audioFormatDescription = adoptCF(formatDescription);
116}
117
118} // namespace WebCore
119
120#endif // ENABLE(MEDIA_STREAM)
121