• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
WriteResponse(PVMFStatus s,PVMFCommandId id,const OsclAny * ctx,const PVMFTimestamp & ts)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) :
iClock(NULL)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 
~AndroidAudioMIOActiveTimingSupport()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
addRef()118     OSCL_IMPORT_REF void addRef() {}
removeRef()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 
ForceClockUpdate()125     void ForceClockUpdate() { iUpdateClock = true; }
126     void UpdateClock();
127 
clockState()128     PVMFMediaClock::PVMFMediaClockState clockState() { return iClockState; }
setThreadSemaphore(OsclSemaphore * s)129     void setThreadSemaphore(OsclSemaphore* s) { iAudioThreadSem = s; }
130 
131     void setDriverLatency(uint32 latency);
incFrameCount(uint32_t numFrames)132     void incFrameCount(uint32_t numFrames) { iFrameCount += numFrames; }
setFrameRate(float msecsPerFrame)133     void setFrameRate(float msecsPerFrame) { iMsecsPerFrame = msecsPerFrame; }
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 
deleteMediaTransfer(PvmiMIOSession & aSession,PvmiMediaTransfer * media_transfer)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 
cancelCommand(PVMFCommandId aCmdId)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 
writeComplete(PVMFStatus aStatus,PVMFCommandId write_cmd_id,OsclAny * aContext)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 
readComplete(PVMFStatus aStatus,PVMFCommandId read_cmd_id,int32 format_index,const PvmiMediaXferHeader & data_header_info,OsclAny * aContext)224     void readComplete(PVMFStatus aStatus, PVMFCommandId  read_cmd_id, int32 format_index,
225                     const PvmiMediaXferHeader& data_header_info, OsclAny* aContext) {}
226 
statusUpdate(uint32 status_flags)227     void statusUpdate(uint32 status_flags) {}
228 
cancelAllCommands()229     virtual void cancelAllCommands() { returnAllBuffers(); }
230 
231     // Pure virtuals from PvmiCapabilityAndConfig
232 
setObserver(PvmiConfigAndCapabilityCmdObserver * aObserver)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 
createContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)240     void createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext) {
241         OsclError::Leave(OsclErrNotSupported);
242     }
243 
setContextParameters(PvmiMIOSession aSession,PvmiCapabilityContext & aContext,PvmiKvp * aParameters,int num_parameter_elements)244     void setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext,
245         PvmiKvp* aParameters, int num_parameter_elements) {
246         OsclError::Leave(OsclErrNotSupported);
247     }
248 
DeleteContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)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 
getCapabilityMetric(PvmiMIOSession aSession)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 
writeAudioBuffer(uint8 * aData,uint32 aDataLen,PVMFCommandId cmdId,OsclAny * aContext,PVMFTimestamp aTimestamp)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 
returnAllBuffers()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:
CommandResponse(PVMFStatus s,PVMFCommandId id,const OsclAny * ctx)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