Home | History | Annotate | Download | only in android
      1 /*
      2 **
      3 ** Copyright 2008, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #ifndef ANDROID_AUDIO_MIO_H
     19 #define ANDROID_AUDIO_MIO_H
     20 
     21 #ifndef PVMI_MIO_CONTROL_H_INCLUDED
     22 #include "pvmi_mio_control.h"
     23 #endif
     24 #ifndef PVMI_MEDIA_TRANSFER_H_INCLUDED
     25 #include "pvmi_media_transfer.h"
     26 #endif
     27 #ifndef OSCL_SCHEDULER_AO_H_INCLUDED
     28 #include "oscl_scheduler_ao.h"
     29 #endif
     30 #ifndef PVMI_MEDIA_IO_OBSERVER_H_INCLUDED
     31 #include "pvmi_media_io_observer.h"
     32 #endif
     33 #ifndef OSCL_FILE_IO_H_INCLUDED
     34 #include "oscl_file_io.h"
     35 #endif
     36 #ifndef PVMI_CONFIG_AND_CAPABILITY_H_INCLUDED
     37 #include "pvmi_config_and_capability.h"
     38 #endif
     39 #ifndef OSCL_STRING_CONTAINERS_H_INCLUDED
     40 #include "oscl_string_containers.h"
     41 #endif
     42 #ifndef PVMI_MEDIA_IO_CLOCK_EXTENSION_H_INCLUDED
     43 #include "pvmi_media_io_clock_extension.h"
     44 #endif
     45 
     46 #ifndef ANDROID_AUDIO_OUTPUT_THREADSAFE_CALLBACK_AO_H_INCLUDED
     47 #include "android_audio_output_threadsafe_callbacks.h"
     48 #endif
     49 #ifndef PVMF_MEDIA_CLOCK_H_INCLUDED
     50 #include "pvmf_media_clock.h"
     51 #endif
     52 #ifdef PERFORMANCE_MEASUREMENTS_ENABLED
     53 #ifndef _PVPROFILE_H
     54 #include "pvprofile.h"
     55 #endif
     56 #endif
     57 
     58 #include <media/MediaPlayerInterface.h>
     59 
     60 class PVLogger;
     61 class PVMFMediaClock;
     62 
     63 using namespace android;
     64 
     65 // Write command handling
     66 // the audio output thread queues the responses, this mio dequeues and processes them
     67 class WriteResponse
     68 {
     69 public:
     70     WriteResponse(PVMFStatus s, PVMFCommandId id, const OsclAny* ctx, const PVMFTimestamp& ts) :
     71         iStatus(s), iCmdId(id), iContext(ctx), iTimestamp(ts)
     72     {}
     73 
     74         PVMFStatus iStatus;
     75         PVMFCommandId iCmdId;
     76         const OsclAny* iContext;
     77         PVMFTimestamp iTimestamp;
     78 };
     79 
     80 // Active timing support
     81 class AndroidAudioMIOActiveTimingSupport :
     82     public PvmiClockExtensionInterface, public PVMFMediaClockStateObserver
     83 {
     84 public:
     85 
     86     AndroidAudioMIOActiveTimingSupport(int32 minCorrection=0, int32 maxCorrection=0) :
     87         iClock(NULL),
     88         iClockNotificationsInf(NULL),
     89         iClockState(PVMFMediaClock::STOPPED),
     90         iAudioThreadSem(0),
     91         iStartTime(0),
     92         iFrameCount(0),
     93         iMsecsPerFrame(25),
     94         iDriverLatency(0),
     95         iUpdateClock(true),
     96         iMinCorrection(minCorrection),
     97         iMaxCorrection(maxCorrection)
     98    {
     99    }
    100 
    101     ~AndroidAudioMIOActiveTimingSupport()
    102     {
    103         if (iClock && iClockNotificationsInf)
    104         {
    105             iClockNotificationsInf->RemoveClockStateObserver(*this);
    106             iClock->DestroyMediaClockNotificationsInterface(iClockNotificationsInf);
    107             iClockNotificationsInf = NULL;
    108         }
    109     }
    110 
    111     //from PvmiClockExtensionInterface
    112     OSCL_IMPORT_REF PVMFStatus SetClock(PVMFMediaClock* clockVal);
    113 
    114     // from PVMFMediaClockStateObserver
    115     void ClockStateUpdated();
    116 
    117     //from PVInterface
    118     OSCL_IMPORT_REF void addRef() {}
    119     OSCL_IMPORT_REF void removeRef() {}
    120     OSCL_IMPORT_REF bool queryInterface(const PVUuid& uuid, PVInterface*& iface);
    121     void NotificationsInterfaceDestroyed();
    122 
    123     void queryUuid(PVUuid& uuid);
    124 
    125     void ForceClockUpdate() { iUpdateClock = true; }
    126     void UpdateClock();
    127 
    128     PVMFMediaClock::PVMFMediaClockState clockState() { return iClockState; }
    129     void setThreadSemaphore(OsclSemaphore* s) { iAudioThreadSem = s; }
    130 
    131     void setDriverLatency(uint32 latency);
    132     void incFrameCount(uint32_t numFrames) { iFrameCount += numFrames; }
    133     void setFrameRate(float msecsPerFrame) { iMsecsPerFrame = msecsPerFrame; }
    134     float msecsPerFrame() { return iMsecsPerFrame; }
    135 
    136 private:
    137     PVMFMediaClock* iClock;
    138     PVMFMediaClockNotificationsInterface *iClockNotificationsInf;
    139     PVMFMediaClock::PVMFMediaClockState iClockState;
    140     OsclSemaphore* iAudioThreadSem;
    141 
    142     uint32 iStartTime;
    143     uint32 iFrameCount;
    144     float iMsecsPerFrame;
    145     uint32 iDriverLatency;
    146     bool iUpdateClock;
    147     int32 iMinCorrection;
    148     int32 iMaxCorrection;
    149 };
    150 
    151 // Audio MIO component
    152 class AndroidAudioMIO : public OsclTimerObject,
    153                  public PvmiMIOControl,
    154                  public PvmiMediaTransfer,
    155                  public PvmiCapabilityAndConfig
    156 {
    157 public:
    158     OSCL_IMPORT_REF AndroidAudioMIO(const char* name);
    159 
    160     OSCL_IMPORT_REF ~AndroidAudioMIO();
    161 
    162     // APIs from PvmiMIOControl
    163 
    164     PVMFStatus connect(PvmiMIOSession& aSession, PvmiMIOObserver* aObserver);
    165 
    166     PVMFStatus disconnect(PvmiMIOSession aSession);
    167 
    168     virtual PVMFCommandId QueryUUID(const PvmfMimeString& aMimeType,
    169             Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    170             bool aExactUuidsOnly=false, const OsclAny* aContext=NULL);
    171 
    172     virtual PVMFCommandId QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext=NULL);
    173 
    174     PvmiMediaTransfer* createMediaTransfer(PvmiMIOSession& aSession, PvmiKvp* read_formats=NULL, int32 read_flags=0,
    175                         PvmiKvp* write_formats=NULL, int32 write_flags=0);
    176 
    177     void deleteMediaTransfer(PvmiMIOSession& aSession, PvmiMediaTransfer* media_transfer) {}
    178 
    179     PVMFCommandId Init(const OsclAny* aContext=NULL);
    180 
    181     PVMFCommandId Reset(const OsclAny* aContext=NULL);
    182 
    183     PVMFCommandId Start(const OsclAny* aContext=NULL);
    184 
    185     PVMFCommandId Pause(const OsclAny* aContext=NULL);
    186 
    187     PVMFCommandId Flush(const OsclAny* aContext=NULL);
    188 
    189     virtual PVMFCommandId DiscardData(const OsclAny* aContext=NULL);
    190 
    191     virtual PVMFCommandId DiscardData(PVMFTimestamp aTimestamp=0, const OsclAny* aContext=NULL);
    192 
    193     virtual PVMFCommandId Stop(const OsclAny* aContext=NULL);
    194 
    195     virtual PVMFCommandId CancelAllCommands(const OsclAny* aContext=NULL);
    196 
    197     virtual PVMFCommandId CancelCommand(PVMFCommandId aCmdId, const OsclAny* aContext=NULL);
    198 
    199     virtual void cancelCommand(PVMFCommandId aCmdId) {}
    200 
    201     void ThreadLogon();
    202 
    203     void ThreadLogoff();
    204 
    205     // APIs from PvmiMediaTransfer
    206 
    207     void setPeer(PvmiMediaTransfer* aPeer);
    208 
    209     void useMemoryAllocators(OsclMemAllocator* write_alloc=NULL) {}
    210 
    211     PVMFCommandId writeAsync(uint8 format_type, int32 format_index,
    212                             uint8* data, uint32 data_len,
    213                             const PvmiMediaXferHeader& data_header_info,
    214                             OsclAny* aContext=NULL);
    215 
    216     void writeComplete(PVMFStatus aStatus, PVMFCommandId  write_cmd_id, OsclAny* aContext) {}
    217 
    218     PVMFCommandId readAsync(uint8* data, uint32 max_data_len, OsclAny* aContext=NULL,
    219             int32* formats=NULL, uint16 num_formats=0) {
    220         OsclError::Leave(OsclErrNotSupported);
    221         return -1;
    222     }
    223 
    224     void readComplete(PVMFStatus aStatus, PVMFCommandId  read_cmd_id, int32 format_index,
    225                     const PvmiMediaXferHeader& data_header_info, OsclAny* aContext) {}
    226 
    227     void statusUpdate(uint32 status_flags) {}
    228 
    229     virtual void cancelAllCommands() { returnAllBuffers(); }
    230 
    231     // Pure virtuals from PvmiCapabilityAndConfig
    232 
    233     void setObserver (PvmiConfigAndCapabilityCmdObserver* aObserver) { OSCL_UNUSED_ARG(aObserver); }
    234 
    235     PVMFStatus getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier,
    236         PvmiKvp*& aParameters, int& num_parameter_elements, PvmiCapabilityContext aContext);
    237 
    238     PVMFStatus releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements);
    239 
    240     void createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) {
    241         OsclError::Leave(OsclErrNotSupported);
    242     }
    243 
    244     void setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext,
    245         PvmiKvp* aParameters, int num_parameter_elements) {
    246         OsclError::Leave(OsclErrNotSupported);
    247     }
    248 
    249     void DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) {
    250         OsclError::Leave(OsclErrNotSupported);
    251     }
    252 
    253     virtual void setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters,
    254         int num_elements, PvmiKvp * & aRet_kvp);
    255 
    256     PVMFCommandId setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters,
    257         int num_elements, PvmiKvp*& aRet_kvp, OsclAny* context=NULL) {
    258         OsclError::Leave(OsclErrNotSupported);
    259         return -1;
    260     }
    261 
    262     uint32 getCapabilityMetric (PvmiMIOSession aSession) { return 0; }
    263 
    264     PVMFStatus verifyParametersSync (PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements);
    265 
    266     // Functions specific to this MIO
    267     void setAudioSink(const sp<MediaPlayerInterface::AudioSink>& audioSink);
    268 
    269     virtual void writeAudioBuffer(uint8* aData, uint32 aDataLen, PVMFCommandId cmdId,
    270             OsclAny* aContext, PVMFTimestamp aTimestamp) {}
    271 
    272 protected:
    273     // From OsclTimerObject
    274     void Run();
    275     void sendResponse(PVMFCommandId cmdid, const OsclAny* context, PVMFTimestamp timestamp);
    276 
    277     // Specific to this MIO
    278     void initData();
    279 
    280     void Cleanup();
    281 
    282     virtual void returnAllBuffers() {}
    283 
    284     void ResetData();
    285 
    286     // request active object which the audio output thread uses to schedule this timer object to run
    287     AndroidAudioOutputThreadSafeCallbackAO *iWriteCompleteAO;
    288 
    289     // write response queue, needs to use lock mechanism to access
    290     Oscl_Vector<WriteResponse,OsclMemAllocator> iWriteResponseQueue;
    291 
    292     // lock used to access the write response queue
    293     OsclMutex iWriteResponseQueueLock;
    294 
    295     // From setPeer
    296     PvmiMediaTransfer* iPeer;
    297 
    298     // The PvmiMIOControl class observer.
    299     PvmiMIOObserver* iObserver;
    300 
    301     // for generating command IDs
    302     uint32 iCommandCounter;
    303 
    304     //State
    305     enum PVAudioMIOState
    306     {
    307         STATE_MIO_IDLE
    308         ,STATE_MIO_LOGGED_ON
    309         ,STATE_MIO_INITIALIZED
    310         ,STATE_MIO_STARTED
    311         ,STATE_MIO_PAUSED
    312     };
    313     PVAudioMIOState iState;
    314 
    315     // Control command handling.
    316     class CommandResponse
    317     {
    318     public:
    319         CommandResponse(PVMFStatus s,PVMFCommandId id,const OsclAny* ctx)
    320             :iStatus(s),iCmdId(id),iContext(ctx)
    321         {}
    322 
    323         PVMFStatus iStatus;
    324         PVMFCommandId iCmdId;
    325         const OsclAny* iContext;
    326     };
    327     Oscl_Vector<CommandResponse,OsclMemAllocator> iCommandResponseQueue;
    328     PVMFCommandId QueueCmdResponse(PVMFStatus status, const OsclAny* aContext);
    329     void ProcessWriteResponseQueue();
    330 
    331     // Audio parameters.
    332     PVMFFormatType iAudioFormat;
    333     int32 iAudioNumChannels;
    334     bool iAudioNumChannelsValid;
    335     int32 iAudioSamplingRate;
    336     bool iAudioSamplingRateValid;
    337 
    338     bool iAudioThreadCreatedAndMIOConfigured;
    339 
    340     // For logging
    341     PVLogger* iLogger;
    342 
    343     // For implementing the write flow control
    344     bool iWriteBusy;
    345     bool CheckWriteBusy(uint32);
    346 
    347     bool iFlushPending;
    348     uint32 iDataQueued;
    349 
    350     sp<MediaPlayerInterface::AudioSink>   mAudioSink;
    351 };
    352 
    353 #endif // ANDROID_AUDIO_MIO_H
    354 
    355