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 }