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 //#define LOG_NDEBUG 0 19 #define LOG_TAG "AudioMIO" 20 #include <utils/Log.h> 21 22 #include "android_audio_mio.h" 23 #include "pvlogger.h" 24 #include "pv_mime_string_utils.h" 25 #include "oscl_snprintf.h" 26 #include "oscl_mem.h" 27 #include "oscl_dll.h" 28 #include "oscl_mem.h" 29 30 #include <sys/prctl.h> 31 32 #include <utils/Timers.h> 33 #include <sys/resource.h> 34 #include <limits.h> 35 36 #include <utils/threads.h> 37 38 #include <media/AudioTrack.h> 39 40 using namespace android; 41 42 // depth of buffer/command queues in MIO 43 static const int kCommandQueueDepth = 10; 44 45 // Define entry point for this DLL 46 OSCL_DLL_ENTRY_POINT_DEFAULT() 47 48 // Audio Media IO component base class implementation 49 OSCL_EXPORT_REF AndroidAudioMIO::AndroidAudioMIO(const char* name) 50 : OsclTimerObject(OsclActiveObject::EPriorityNominal, name), 51 iWriteCompleteAO(NULL) 52 { 53 initData(); 54 } 55 56 OSCL_EXPORT_REF AndroidAudioMIO::~AndroidAudioMIO() 57 { 58 LOGV("destructor"); 59 Cleanup(); 60 } 61 62 void AndroidAudioMIO::initData() 63 { 64 LOGV("initData in"); 65 ResetData(); 66 67 iCommandCounter = 0; 68 iLogger = NULL; 69 iCommandResponseQueue.reserve(kCommandQueueDepth); 70 iWriteResponseQueueLock.Create(); 71 iWriteResponseQueue.reserve(kCommandQueueDepth); 72 iObserver = NULL; 73 iLogger = NULL; 74 iPeer = NULL; 75 iState = STATE_MIO_IDLE; 76 iWriteBusy = false; 77 iFlushPending = false; 78 iDataQueued = 0; 79 LOGV("initData out"); 80 } 81 82 void AndroidAudioMIO::ResetData() 83 //reset all data from this session. 84 { 85 LOGV("ResetData in"); 86 // reset all the received media parameters. 87 iAudioFormat = PVMF_MIME_FORMAT_UNKNOWN; 88 iAudioNumChannelsValid = false; 89 iAudioSamplingRateValid = false; 90 iAudioThreadCreatedAndMIOConfigured = false; 91 LOGV("ResetData out"); 92 } 93 94 //cleanup all allocated memory and release resources. 95 void AndroidAudioMIO::Cleanup() 96 { 97 LOGV("Cleanup in"); 98 while (!iCommandResponseQueue.empty()) { 99 if (iObserver) { 100 iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, 101 iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus)); 102 } 103 iCommandResponseQueue.erase(&iCommandResponseQueue[0]); 104 } 105 106 // return empty buffers 107 returnAllBuffers(); 108 109 // delete the request active object 110 if (iWriteCompleteAO) { 111 OSCL_DELETE(iWriteCompleteAO); 112 iWriteCompleteAO = NULL; 113 } 114 iWriteResponseQueueLock.Close(); 115 LOGV("Cleanup out"); 116 } 117 118 PVMFStatus AndroidAudioMIO::connect(PvmiMIOSession& aSession, PvmiMIOObserver* aObserver) 119 { 120 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::connect() called")); 121 122 // currently supports only one session 123 if (iObserver) return PVMFFailure; 124 iObserver = aObserver; 125 return PVMFSuccess; 126 } 127 128 PVMFStatus AndroidAudioMIO::disconnect(PvmiMIOSession aSession) 129 { 130 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::disconnect() called")); 131 iObserver = NULL; 132 return PVMFSuccess; 133 } 134 135 136 PvmiMediaTransfer* AndroidAudioMIO::createMediaTransfer(PvmiMIOSession& aSession, 137 PvmiKvp* read_formats, int32 read_flags, 138 PvmiKvp* write_formats, int32 write_flags) 139 { 140 // create the request active object 141 // such when audio output thread is done with a buffer 142 // it can put the buffer on the write response queue 143 // and schedule this MIO to run, to return the buffer 144 // to the engine 145 iWriteCompleteAO = OSCL_NEW(AndroidAudioOutputThreadSafeCallbackAO,(this, 5)); 146 147 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::createMediaTransfer() called")); 148 return (PvmiMediaTransfer*)this; 149 } 150 151 PVMFCommandId AndroidAudioMIO::QueueCmdResponse(PVMFStatus status, const OsclAny* aContext) 152 { 153 PVMFCommandId cmdId = iCommandCounter++; 154 CommandResponse resp(status, cmdId, aContext); 155 iCommandResponseQueue.push_back(resp); 156 157 // cancel any timer delay so the command response will happen ASAP. 158 if (IsBusy()) Cancel(); 159 RunIfNotReady(); 160 return cmdId; 161 } 162 163 // return any held buffers to the engine 164 void AndroidAudioMIO::ProcessWriteResponseQueue() 165 { 166 //LOGV("ProcessWriteResponseQueue in [Response Q size %d]",iWriteResponseQueue.size()); 167 PVMFStatus status = 0; 168 PVMFCommandId cmdId = 0; 169 const OsclAny* context = 0; 170 171 iWriteResponseQueueLock.Lock(); 172 while (!iWriteResponseQueue.empty()) { 173 status = iWriteResponseQueue[0].iStatus; 174 cmdId = iWriteResponseQueue[0].iCmdId; 175 context = (OsclAny*)iWriteResponseQueue[0].iContext; 176 iWriteResponseQueue.erase(&iWriteResponseQueue[0]); 177 iWriteResponseQueueLock.Unlock(); 178 if (iPeer) { 179 LOGV("Return buffer(%d) status(%d) context(%p)", cmdId,status,context); 180 iPeer->writeComplete(status, cmdId, (OsclAny*)context); 181 } 182 iWriteResponseQueueLock.Lock(); 183 } 184 iWriteResponseQueueLock.Unlock(); 185 //LOGV("ProcessWriteResponseQueue out"); 186 } 187 188 PVMFCommandId AndroidAudioMIO::QueryUUID(const PvmfMimeString& aMimeType, 189 Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids, 190 bool aExactUuidsOnly, const OsclAny* aContext) 191 { 192 LOGV("QueryUUID"); 193 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::QueryUUID() called")); 194 return QueueCmdResponse(PVMFFailure, aContext); 195 } 196 197 PVMFCommandId AndroidAudioMIO::QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext) 198 { 199 LOGV("QueryInterface"); 200 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::QueryInterface() called")); 201 PVMFStatus status=PVMFFailure; 202 if (aUuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID) { 203 PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this); 204 aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface); 205 status = PVMFSuccess; 206 } 207 return QueueCmdResponse(status, aContext); 208 } 209 210 PVMFCommandId AndroidAudioMIO::Init(const OsclAny* aContext) 211 { 212 LOGV("Init (%p)", aContext); 213 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::Init() called")); 214 iState=STATE_MIO_INITIALIZED; 215 return QueueCmdResponse(PVMFSuccess, aContext); 216 } 217 218 PVMFCommandId AndroidAudioMIO::Reset(const OsclAny* aContext) 219 { 220 LOGV("Reset (%p)", aContext); 221 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::Reset() called")); 222 return QueueCmdResponse(PVMFSuccess, aContext); 223 } 224 225 PVMFCommandId AndroidAudioMIO::Start(const OsclAny* aContext) 226 { 227 // Start is NO-OP 228 LOGV("Start (%p)", aContext); 229 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::Start() called")); 230 iState = STATE_MIO_STARTED; 231 return QueueCmdResponse(PVMFSuccess, aContext); 232 } 233 234 PVMFCommandId AndroidAudioMIO::Pause(const OsclAny* aContext) 235 { 236 LOGV("Pause (%p)", aContext); 237 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::Pause() called")); 238 iState = STATE_MIO_PAUSED; 239 return QueueCmdResponse(PVMFSuccess, aContext); 240 } 241 242 243 PVMFCommandId AndroidAudioMIO::Flush(const OsclAny* aContext) 244 { 245 LOGV("Flush (%p)", aContext); 246 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::Flush() called")); 247 iState = STATE_MIO_INITIALIZED; 248 return QueueCmdResponse(PVMFSuccess, aContext); 249 } 250 251 PVMFCommandId AndroidAudioMIO::DiscardData(const OsclAny* aContext) 252 { 253 LOGV("DiscardData (%p)", aContext); 254 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::DiscardData() called")); 255 return DiscardData(UINT_MAX, aContext); 256 } 257 258 PVMFCommandId AndroidAudioMIO::DiscardData(PVMFTimestamp aTimestamp, const OsclAny* aContext) 259 { 260 LOGV("DiscardData (%u, %p)", aTimestamp, aContext); 261 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::DiscardData() called")); 262 return QueueCmdResponse(PVMFSuccess, aContext); 263 } 264 265 PVMFCommandId AndroidAudioMIO::Stop(const OsclAny* aContext) 266 { 267 LOGV("Stop (%p)", aContext); 268 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::Stop() called")); 269 iState = STATE_MIO_INITIALIZED; 270 return QueueCmdResponse(PVMFSuccess, aContext); 271 } 272 273 PVMFCommandId AndroidAudioMIO::CancelAllCommands(const OsclAny* aContext) 274 { 275 LOGV("CancelAllCommands (%p)", aContext); 276 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::CancelAllCommands() called")); 277 278 //commands are executed immediately upon being received, so 279 //it isn't really possible to cancel them. 280 return QueueCmdResponse(PVMFSuccess, aContext); 281 } 282 283 PVMFCommandId AndroidAudioMIO::CancelCommand(PVMFCommandId aCmdId, const OsclAny* aContext) 284 { 285 LOGV("CancelCommand (%u, %p)", aCmdId, aContext); 286 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::CancelCommand() called")); 287 288 //see if the response is still queued. 289 PVMFStatus status = PVMFFailure; 290 for (uint32 i = 0; i < iCommandResponseQueue.size(); i++) { 291 if (iCommandResponseQueue[i].iCmdId == aCmdId) { 292 status = PVMFSuccess; 293 break; 294 } 295 } 296 return QueueCmdResponse(PVMFSuccess, aContext); 297 } 298 299 void AndroidAudioMIO::ThreadLogon() 300 { 301 LOGV("ThreadLogon() called "); 302 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::ThreadLogon() called")); 303 if (iState == STATE_MIO_IDLE) { 304 iLogger = PVLogger::GetLoggerObject("AndroidAudioMIO\n"); 305 AddToScheduler(); 306 iState=STATE_MIO_LOGGED_ON; 307 } 308 } 309 310 void AndroidAudioMIO::ThreadLogoff() 311 { 312 LOGV("ThreadLogoff() called"); 313 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::ThreadLogoff() called")); 314 if (iState!=STATE_MIO_IDLE) { 315 RemoveFromScheduler(); 316 iLogger = NULL; 317 iState = STATE_MIO_IDLE; 318 ResetData(); 319 } 320 } 321 322 void AndroidAudioMIO::setPeer(PvmiMediaTransfer* aPeer) 323 { 324 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"AndroidAudioMIO::setPeer() called")); 325 // Set the observer 326 iPeer = aPeer; 327 } 328 329 //This routine will determine whether data can be accepted in a writeAsync 330 //call and if not, will return true; 331 bool AndroidAudioMIO::CheckWriteBusy(uint32 aSeqNum) 332 { 333 // FIXME: this line screws up video output - why? 334 // return (iOSSRequestQueue.size() >= 5); 335 return false; 336 } 337 338 PVMFCommandId AndroidAudioMIO::writeAsync(uint8 aFormatType, int32 aFormatIndex, uint8* aData, uint32 aDataLen, 339 const PvmiMediaXferHeader& data_header_info, OsclAny* aContext) 340 { 341 // Do a leave if MIO is not configured except when it is an EOS 342 if (!iAudioThreadCreatedAndMIOConfigured 343 && 344 !((PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION == aFormatType) 345 && (PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM == aFormatIndex))) 346 { 347 LOGE("ERROR :: data is pumped in before mio configured"); 348 OSCL_LEAVE(OsclErrInvalidState); 349 return -1; 350 } 351 352 uint32 aSeqNum = data_header_info.seq_num; 353 PVMFTimestamp aTimestamp = data_header_info.timestamp; 354 uint32 flags = data_header_info.flags; 355 356 bool bWriteComplete = true; 357 358 //LOGV("writeAsync() called seqnum %d ts %d flags %d context %d formattype %d formatindex %d",aSeqNum, aTimestamp, flags,aContext,aFormatType,aFormatIndex); 359 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 360 (0,"AndroidAudioMIO::writeAsync() seqnum %d ts %d flags %d context %d", 361 aSeqNum, aTimestamp, flags,aContext)); 362 363 PVMFStatus status=PVMFFailure; 364 365 switch(aFormatType) { 366 case PVMI_MEDIAXFER_FMT_TYPE_COMMAND : 367 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 368 (0,"AndroidAudioMIO::writeAsync() called with Command info.")); 369 //ignore 370 LOGV("PVMI_MEDIAXFER_FMT_TYPE_COMMAND"); 371 status = PVMFSuccess; 372 break; 373 374 case PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION : 375 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 376 (0,"AndroidAudioMIO::writeAsync() called with Notification info.")); 377 switch(aFormatIndex) { 378 case PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM: 379 LOGV("PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM"); 380 bWriteComplete = false; //force an empty buffer through the audio thread 381 break; 382 default: 383 break; 384 } 385 //ignore 386 status = PVMFSuccess; 387 break; 388 389 case PVMI_MEDIAXFER_FMT_TYPE_DATA : 390 switch(aFormatIndex) { 391 case PVMI_MEDIAXFER_FMT_INDEX_FMT_SPECIFIC_INFO: 392 status = PVMFSuccess; 393 LOGV("PVMI_MEDIAXFER_FMT_INDEX_FMT_SPECIFIC_INFO"); 394 break; 395 396 case PVMI_MEDIAXFER_FMT_INDEX_DATA: 397 LOGV("PVMI_MEDIAXFER_FMT_INDEX_DATA"); 398 //data contains the media bitstream. 399 400 //Check whether we can accept data now and leave if we can't. 401 if (CheckWriteBusy(aSeqNum)) { 402 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 403 (0,"AndroidAudioMIO::writeAsync: Entering busy state")); 404 405 //schedule an event to re-start the data flow. 406 iWriteBusy = true; 407 bWriteComplete = false; 408 409 // Rich:: commenting in this line. 410 // Need some timeout here just in case. 411 // I have no evidence of any problems. 412 RunIfNotReady(10 * 1000); 413 OSCL_LEAVE(OsclErrBusy); 414 } else { 415 if (aDataLen > 0) { 416 // this buffer will be queued by the audio output thread to process 417 // this buffer cannot be write completed until 418 // it has been processed by the audio output thread 419 bWriteComplete = false; 420 } else { 421 LOGE("writeAsync() called with aDataLen==0"); 422 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, 423 (0,"AndroidAudioMIO::writeAsync() called aDataLen==0.")); 424 } 425 status = PVMFSuccess; 426 } 427 break; 428 429 default: 430 LOGE("Error unrecognized format index =%u", aFormatIndex); 431 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 432 (0,"AndroidAudioMIO::writeAsync: Error - unrecognized format index")); 433 status = PVMFFailure; 434 break; 435 } 436 break; 437 438 default: 439 LOGE("Error unrecognized format type =%u", aFormatType); 440 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 441 (0,"AndroidAudioMIO::writeAsync: Error - unrecognized format type")); 442 status = PVMFFailure; 443 break; 444 } 445 446 //Schedule asynchronous response 447 PVMFCommandId cmdid=iCommandCounter++; 448 if (bWriteComplete) { 449 LOGV("write complete (%d)", cmdid); 450 WriteResponse resp(status, cmdid, aContext, aTimestamp); 451 iWriteResponseQueueLock.Lock(); 452 iWriteResponseQueue.push_back(resp); 453 iWriteResponseQueueLock.Unlock(); 454 RunIfNotReady(); 455 } else if (!iWriteBusy) { 456 writeAudioBuffer(aData, aDataLen, cmdid, aContext, aTimestamp); 457 } 458 LOGV("data queued = %u", iDataQueued); 459 460 return cmdid; 461 } 462 463 PVMFStatus AndroidAudioMIO::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier, 464 PvmiKvp*& aParameters, int& num_parameter_elements, 465 PvmiCapabilityContext aContext) 466 { 467 LOGV("getParametersSync in %s",aIdentifier); 468 OSCL_UNUSED_ARG(aSession); 469 OSCL_UNUSED_ARG(aContext); 470 aParameters=NULL; 471 num_parameter_elements=0; 472 PVMFStatus status = PVMFFailure; 473 474 if(pv_mime_strcmp(aIdentifier, INPUT_FORMATS_CAP_QUERY) == 0) { 475 //This is a query for the list of supported formats. 476 aParameters=(PvmiKvp*)oscl_malloc(2 * sizeof(PvmiKvp)); 477 if (aParameters) { 478 aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_PCM16; 479 aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_PCM8; 480 status = PVMFSuccess; 481 } 482 else{ 483 status = PVMFErrNoMemory; 484 } 485 } 486 //other queries are not currently supported. 487 488 //unrecognized key. 489 LOGV("getParametersSync out status %d",status); 490 return status; 491 } 492 493 PVMFStatus AndroidAudioMIO::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements) 494 { 495 LOGV("releaseParameters in"); 496 OSCL_UNUSED_ARG(aSession); 497 OSCL_UNUSED_ARG(num_elements); 498 PVMFStatus status = PVMFFailure; 499 //release parameters that were allocated by this component. 500 if (aParameters) { 501 oscl_free(aParameters); 502 status = PVMFSuccess; 503 } 504 LOGV("releaseParameters out status %d",status); 505 return status; 506 } 507 508 PVMFStatus AndroidAudioMIO::verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements) 509 { 510 OSCL_UNUSED_ARG(aSession); 511 //LOGV("verifyParametersSync in"); 512 513 // Go through each parameter 514 for (int32 i=0; i<num_elements; i++) { 515 char* compstr = NULL; 516 pv_mime_string_extract_type(0, aParameters[i].key, compstr); 517 if (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/media/format-type")) == 0) { 518 if ((pv_mime_strcmp(aParameters[i].value.pChar_value, PVMF_MIME_PCM8) == 0) || 519 (pv_mime_strcmp(aParameters[i].value.pChar_value, PVMF_MIME_PCM16) == 0) 520 ) { 521 return PVMFSuccess; 522 } 523 else { 524 return PVMFErrNotSupported; 525 } 526 } 527 } 528 return PVMFSuccess; 529 //LOGV("verifyParametersSync out"); 530 531 } 532 void AndroidAudioMIO::setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, 533 int num_elements, PvmiKvp * & aRet_kvp) 534 { 535 OSCL_UNUSED_ARG(aSession); 536 //LOGV("setParametersSync in"); 537 aRet_kvp = NULL; 538 539 for (int32 i=0;i<num_elements;i++) { 540 //Check against known audio parameter keys... 541 if (pv_mime_strcmp(aParameters[i].key, MOUT_AUDIO_FORMAT_KEY) == 0) { 542 LOGV("Audio format: %s", aParameters[i].value.pChar_value); 543 iAudioFormat=aParameters[i].value.pChar_value; 544 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 545 (0,"AndroidAudioOutput::setParametersSync() Audio Format Key, Value %s",aParameters[i].value.pChar_value)); 546 } else if (pv_mime_strcmp(aParameters[i].key, MOUT_AUDIO_SAMPLING_RATE_KEY) == 0) { 547 iAudioSamplingRate=(int32)aParameters[i].value.uint32_value; 548 iAudioSamplingRateValid=true; 549 // LOGD("iAudioSamplingRate=%d", iAudioSamplingRate); 550 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 551 (0,"AndroidAudioMIO::setParametersSync() Audio Sampling Rate Key, Value %d",iAudioSamplingRate)); 552 } else if (pv_mime_strcmp(aParameters[i].key, MOUT_AUDIO_NUM_CHANNELS_KEY) == 0) { 553 iAudioNumChannels=(int32)aParameters[i].value.uint32_value; 554 iAudioNumChannelsValid=true; 555 // LOGD("iAudioNumChannels=%d", iAudioNumChannels); 556 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 557 (0,"AndroidAudioMIO::setParametersSync() Audio Num Channels Key, Value %d",iAudioNumChannels)); 558 } else { 559 //if we get here the key is unrecognized. 560 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 561 (0,"AndroidAudioMIO::setParametersSync() Error, unrecognized key %s",aParameters[i].key)); 562 563 //set the return value to indicate the unrecognized key 564 //and return. 565 aRet_kvp = &aParameters[i]; 566 return; 567 } 568 } 569 570 //LOGV("setParametersSync out"); 571 } 572 573 // 574 // Private section 575 // 576 577 void AndroidAudioMIO::Run() 578 { 579 while (!iCommandResponseQueue.empty()) { 580 if (iObserver) { 581 iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, 582 iCommandResponseQueue[0].iContext, 583 iCommandResponseQueue[0].iStatus)); 584 } 585 iCommandResponseQueue.erase(&iCommandResponseQueue[0]); 586 } 587 588 //send async write completion 589 ProcessWriteResponseQueue(); 590 591 //Re-start the data transfer if needed. 592 if (iWriteBusy) { 593 iWriteBusy = false; 594 iPeer->statusUpdate(PVMI_MEDIAXFER_STATUS_WRITE); 595 } 596 } 597 598 // send response to MIO 599 void AndroidAudioMIO::sendResponse(PVMFCommandId cmdid, const OsclAny* context, PVMFTimestamp timestamp) 600 { 601 LOGV("sendResponse :: return buffer (%d) timestamp(%d) context(%p)", cmdid, timestamp, context); 602 WriteResponse resp(PVMFSuccess, cmdid, context, timestamp); 603 iWriteResponseQueueLock.Lock(); 604 if (iWriteResponseQueue.size() < iWriteResponseQueue.capacity()) { 605 iWriteResponseQueue.push_back(resp); 606 } else { 607 LOGE("Exceeded response queue capacity"); 608 } 609 iWriteResponseQueueLock.Unlock(); 610 611 // Create an event for the threadsafe callback AO 612 OsclAny* P = NULL; 613 iWriteCompleteAO->ReceiveEvent(P); 614 } 615 616 void AndroidAudioMIO::setAudioSink(const sp<MediaPlayerInterface::AudioSink>& audioSink) 617 { 618 LOGV("setAudioSink in"); 619 mAudioSink = audioSink; 620 } 621 622 //------------------------------------------------------------------------ 623 // Active timing support 624 // 625 OSCL_EXPORT_REF PVMFStatus AndroidAudioMIOActiveTimingSupport::SetClock(PVMFMediaClock *clockVal) 626 { 627 LOGV("ATS :: SetClock in"); 628 iClock=clockVal; 629 630 return PVMFSuccess; 631 } 632 633 void AndroidAudioMIOActiveTimingSupport::NotificationsInterfaceDestroyed() 634 { 635 LOGV("ATS :: NotificationsInterfaceDestroyed in"); 636 iClockNotificationsInf=NULL; 637 } 638 639 640 OSCL_EXPORT_REF bool AndroidAudioMIOActiveTimingSupport::queryInterface(const PVUuid& aUuid, PVInterface*& aInterface) 641 { 642 aInterface = NULL; 643 PVUuid uuid; 644 queryUuid(uuid); 645 bool status = false; 646 if (uuid == aUuid) { 647 PvmiClockExtensionInterface* myInterface = OSCL_STATIC_CAST(PvmiClockExtensionInterface*, this); 648 aInterface = OSCL_STATIC_CAST(PVInterface*, myInterface); 649 status = true; 650 } 651 LOGV("ATS :: queryInterface out status %d",status); 652 return status; 653 } 654 655 void AndroidAudioMIOActiveTimingSupport::queryUuid(PVUuid& uuid) 656 { 657 LOGV("ATS :: queryUuid in"); 658 uuid = PvmiClockExtensionInterfaceUuid; 659 } 660 661 void AndroidAudioMIOActiveTimingSupport::ClockStateUpdated() 662 { 663 LOGV("ATS :: ClockStateUpdated in"); 664 if (iClock) { 665 666 PVMFMediaClock::PVMFMediaClockState newClockState = iClock->GetState(); 667 if (newClockState != iClockState) { 668 iClockState = newClockState; 669 switch (iClockState) { 670 case PVMFMediaClock::STOPPED: 671 LOGV("A/V clock stopped"); 672 break; 673 case PVMFMediaClock::RUNNING: 674 LOGV("A/V clock running"); 675 // must be seeking, get new clock offset for A/V sync 676 if (iUpdateClock) { 677 bool overflowFlag = false; 678 uint32 currentTimeBase32 = 0; 679 iClock->GetCurrentTime32(iStartTime, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, currentTimeBase32); 680 iFrameCount = 0; 681 iUpdateClock = false; 682 LOGV("update iStartTime: %d", iStartTime); 683 } 684 LOGV("signal thread to start"); 685 if (iAudioThreadSem) iAudioThreadSem->Signal(); 686 break; 687 case PVMFMediaClock::PAUSED: 688 LOGV("A/V clock paused"); 689 break; 690 default: 691 LOGE("Wrong clock state!"); 692 break; 693 } 694 } 695 } 696 LOGV("ATS :: ClockStateUpdated out"); 697 } 698 699 void AndroidAudioMIOActiveTimingSupport::UpdateClock() 700 { 701 LOGV("ATS :: UpdateClock in"); 702 if (iClock && (iClockState == PVMFMediaClock::RUNNING)) { 703 uint32 clockTime32, timeBaseTime32, updateClock32; 704 int32 correction = 0; 705 bool overflowFlag = false; 706 // get current time 707 iClock->GetCurrentTime32(clockTime32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timeBaseTime32); 708 LOGV("PV clock current = %u", clockTime32); 709 710 // calculate sample clock 711 updateClock32 = iFrameCount * iMsecsPerFrame; 712 LOGV("sample clock = %u frameCount(%u) msecsPerFrame(%f)", updateClock32,iFrameCount,iMsecsPerFrame); 713 714 correction = updateClock32 - (clockTime32 - iStartTime); 715 LOGV("ADJ_CLK iDriverLatency %d old clock %d delta %d", iDriverLatency, clockTime32, correction); 716 717 // do clock correction if drift exceeds threshold 718 if (OSCL_ABS(correction) > iMinCorrection) { 719 if (correction > iMaxCorrection) { 720 correction = iMaxCorrection; 721 } else if (correction < -iMaxCorrection) { 722 correction = -iMaxCorrection; 723 } 724 updateClock32 = clockTime32 + correction; 725 LOGV("ADJ_CLK old clock %d correction %d new clock %d", clockTime32, correction, updateClock32); 726 727 PVMFMediaClockAdjustTimeStatus adjustmentstatus = 728 iClock->AdjustClockTime32(clockTime32, timeBaseTime32, updateClock32,PVMF_MEDIA_CLOCK_MSEC,overflowFlag); 729 730 if ((PVMF_MEDIA_CLOCK_ADJUST_SUCCESS != adjustmentstatus)) 731 { 732 LOGE("Error adjusting clock status = %d",adjustmentstatus); 733 } 734 if(overflowFlag) { 735 LOGE("Adjusting clock caused overflow"); 736 } 737 } 738 else{ 739 LOGV("ATS :: sample clock and pv clock are close enough no need to update"); 740 } 741 } 742 LOGV("ATS :: UpdateClock out"); 743 } 744 void AndroidAudioMIOActiveTimingSupport::setDriverLatency(uint32 latency) 745 { 746 LOGV("ATS :: setDriverLatency in"); 747 iDriverLatency = latency; 748 if (iClock){ 749 LOGV("register latency to media clock and set clockobserver"); 750 PVMFStatus ret = iClock->ConstructMediaClockNotificationsInterface(iClockNotificationsInf,*this,latency); 751 if(iClockNotificationsInf && (PVMFSuccess == ret)) 752 { 753 iClockNotificationsInf->SetClockStateObserver(*this); 754 } 755 else 756 { 757 LOGE("latency could NOT be set !! set it later "); 758 } 759 } 760 LOGV("ATS :: setDriverLatency out"); 761 } 762 763