1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "AVFKernelProcessor.h" 27 28 #include <pthread.h> 29 30 // Apple reserves 0-1024 for their own properties 31 #define kAVFProperty_KernelProcessor 2099 32 33 class AVFKernelComponent : AUEffectBase { 34 public: 35 AVFKernelComponent(AudioComponentInstance audioUnit, bool inProcessesInPlace = true) 36 : AUEffectBase(audioUnit, inProcessesInPlace), 37 mUsesKernel(false), 38 mProcessor(NULL) 39 {} 40 41 virtual ~AVFKernelComponent() { 42 // Don't do anything with mProcessor as it could have been deleted already 43 } 44 45 virtual AUKernelBase *NewKernel() { 46 if (mProcessor) { 47 AUKernelBase *kernel = mProcessor->NewKernel(); 48 mUsesKernel = (kernel != NULL); 49 return kernel; 50 } 51 mUsesKernel = false; 52 return NULL; 53 } 54 55 virtual OSStatus ChangeStreamFormat(AudioUnitScope inScope, 56 AudioUnitElement inElement, 57 const CAStreamBasicDescription &inPrevFormat, 58 const CAStreamBasicDescription &inNewFormat) { 59 OSStatus status = this->AUEffectBase::ChangeStreamFormat(inScope, 60 inElement, 61 inPrevFormat, 62 inNewFormat); 63 if (inScope == kAudioUnitScope_Input && inElement == 0) { 64 mProcessor->StreamFormatChanged(inNewFormat); 65 } 66 return status; 67 } 68 69 virtual OSStatus ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags, 70 const AudioBufferList& inBuffer, 71 AudioBufferList& outBuffer, 72 UInt32 inFramesToProcess) { 73 // Call our base class if we have kernels 74 if (mUsesKernel) { 75 return this->AUEffectBase::ProcessBufferLists(ioActionFlags, 76 inBuffer, 77 outBuffer, 78 inFramesToProcess); 79 } 80 // Otherwise call ProcessBufferLists 81 if (mProcessor) { 82 return mProcessor->ProcessBufferLists(ioActionFlags, 83 inBuffer, 84 outBuffer, 85 inFramesToProcess); 86 } 87 return noErr; // ??? just in case 88 } 89 90 virtual OSStatus SetProperty(AudioUnitPropertyID inID, 91 AudioUnitScope inScope, 92 AudioUnitElement inElement, 93 const void *inData, 94 UInt32 inDataSize) { 95 if (inID == kAVFProperty_KernelProcessor && 96 inScope == kAudioUnitScope_Global && 97 inElement == 0) { 98 if (inDataSize == sizeof(AVFKernelProcessor*)) { 99 AVFKernelProcessor *processor = *((AVFKernelProcessor **)inData); 100 if (mProcessor != processor) { 101 if (mProcessor) { 102 mProcessor->SetAudioUnit(NULL); 103 mProcessor = NULL; 104 } 105 106 mProcessor = processor; 107 if (mProcessor) { 108 mProcessor->SetAudioUnit(this); 109 const AudioStreamBasicDescription& format = 110 GetStreamFormat(kAudioUnitScope_Input, 0); 111 mProcessor->StreamFormatChanged(format); 112 } 113 } 114 return noErr; 115 } 116 return kAudioUnitErr_InvalidPropertyValue; 117 } 118 return this->AUEffectBase::SetProperty(inID, inScope, inElement, inData, inDataSize); 119 } 120 private: 121 bool mUsesKernel; 122 AVFKernelProcessor *mProcessor; 123 }; 124 125 // Synchronize registration of the component 126 volatile AudioComponent gAVFComponent = NULL; 127 pthread_mutex_t gAVFComponentLock = PTHREAD_MUTEX_INITIALIZER; 128 129 static inline AudioComponent GetAVFComponent() { 130 AudioComponent component = NULL; 131 pthread_mutex_lock(&gAVFComponentLock); 132 133 if (!gAVFComponent) { 134 gAVFComponent = AUBaseFactory<AVFKernelComponent>::Register(kAudioUnitType_Effect, 135 'Krnl', 136 'JAVA', 137 CFSTR("JavaFX Kernel Processor"), 138 0x00010000); 139 } 140 component = gAVFComponent; 141 142 pthread_mutex_unlock(&gAVFComponentLock); 143 return component; 144 } 145 146 147 AudioUnit NewKernelProcessorUnit(AVFKernelProcessor *kernel) { 148 OSStatus status = noErr; 149 AudioUnit unit = NULL; 150 AudioComponent ac = GetAVFComponent(); 151 152 if (!ac) { 153 return NULL; 154 } 155 156 status = AudioComponentInstanceNew(ac, &unit); 157 if (noErr == status) { 158 status = AudioUnitSetProperty(unit, 159 kAVFProperty_KernelProcessor, 160 kAudioUnitScope_Global, 161 0, 162 &kernel, 163 sizeof(AVFKernelProcessor**)); 164 } 165 166 if (noErr != status) { 167 if (unit) { 168 AudioComponentInstanceDispose(unit); 169 } 170 } 171 return unit; 172 }