1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 #include "pvmf_omx_audiodec_node.h" 19 #include "pvlogger.h" 20 #include "oscl_error_codes.h" 21 #include "pvmf_omx_basedec_port.h" 22 #include "pv_mime_string_utils.h" 23 #include "oscl_snprintf.h" 24 #include "pvmf_media_cmd.h" 25 #include "pvmf_media_msg_format_ids.h" 26 #include "pvmi_kvp_util.h" 27 #include "latmpayloadparser.h" 28 29 30 #include "OMX_Core.h" 31 #include "pvmf_omx_basedec_callbacks.h" //used for thin AO in Decoder's callbacks 32 #include "pv_omxcore.h" 33 34 // needed for capability and config 35 #include "pv_omx_config_parser.h" 36 37 #include "utils/Log.h" 38 #undef LOG_TAG 39 #define LOG_TAG "PVOMXAudDecNode" 40 41 #define CONFIG_SIZE_AND_VERSION(param) \ 42 param.nSize=sizeof(param); \ 43 param.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; \ 44 param.nVersion.s.nVersionMinor = SPECVERSIONMINOR; \ 45 param.nVersion.s.nRevision = SPECREVISION; \ 46 param.nVersion.s.nStep = SPECSTEP; 47 48 49 50 #define PVOMXAUDIODEC_MEDIADATA_POOLNUM 2*NUMBER_OUTPUT_BUFFER 51 #define PVOMXAUDIODEC_MEDIADATA_CHUNKSIZE 128 52 53 54 // Node default settings 55 56 #define PVOMXAUDIODECNODE_CONFIG_MIMETYPE_DEF 0 57 58 #define PVMF_OMXAUDIODEC_NUM_METADATA_VALUES 6 59 60 // Constant character strings for metadata keys 61 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY[] = "codec-info/audio/format"; 62 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY[] = "codec-info/audio/channels"; 63 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY[] = "codec-info/audio/sample-rate"; 64 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_AVGBITRATE_KEY[] = "codec-info/audio/avgbitrate"; 65 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_AACOBJECTTYPE_KEY[] = "codec-info/audio/aac-objecttype"; 66 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_AACSTREAMTYPE_KEY[] = "codec-info/audio/aac-streamtype"; 67 68 69 static const char PVOMXAUDIODECMETADATA_SEMICOLON[] = ";"; 70 71 ///////////////////////////////////////////////////////////////////////////// 72 // Class Destructor 73 ///////////////////////////////////////////////////////////////////////////// 74 PVMFOMXAudioDecNode::~PVMFOMXAudioDecNode() 75 { 76 DeleteLATMParser(); 77 ReleaseAllPorts(); 78 } 79 80 ///////////////////////////////////////////////////////////////////////////// 81 // Add AO to the scheduler 82 ///////////////////////////////////////////////////////////////////////////// 83 PVMFStatus PVMFOMXAudioDecNode::ThreadLogon() 84 { 85 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode:ThreadLogon")); 86 87 switch (iInterfaceState) 88 { 89 case EPVMFNodeCreated: 90 if (!IsAdded()) 91 { 92 AddToScheduler(); 93 iIsAdded = true; 94 } 95 iLogger = PVLogger::GetLoggerObject("PVMFOMXAudioDecNode"); 96 iRunlLogger = PVLogger::GetLoggerObject("Run.PVMFOMXAudioDecNode"); 97 iDataPathLogger = PVLogger::GetLoggerObject("datapath"); 98 iClockLogger = PVLogger::GetLoggerObject("clock"); 99 iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.decnode.OMXAudioDecnode"); 100 101 SetState(EPVMFNodeIdle); 102 return PVMFSuccess; 103 104 default: 105 return PVMFErrInvalidState; 106 } 107 } 108 109 ///////////////////// 110 // Private Section // 111 ///////////////////// 112 113 ///////////////////////////////////////////////////////////////////////////// 114 // Class Constructor 115 ///////////////////////////////////////////////////////////////////////////// 116 PVMFOMXAudioDecNode::PVMFOMXAudioDecNode(int32 aPriority) : 117 PVMFOMXBaseDecNode(aPriority, "PVMFOMXAudioDecNode") 118 { 119 iInterfaceState = EPVMFNodeCreated; 120 121 iNodeConfig.iMimeType = PVOMXAUDIODECNODE_CONFIG_MIMETYPE_DEF; 122 123 124 int32 err; 125 OSCL_TRY(err, 126 127 //Create the input command queue. Use a reserve to avoid lots of 128 //dynamic memory allocation. 129 iInputCommands.Construct(PVMF_OMXBASEDEC_NODE_COMMAND_ID_START, PVMF_OMXBASEDEC_NODE_COMMAND_VECTOR_RESERVE); 130 131 //Create the "current command" queue. It will only contain one 132 //command at a time, so use a reserve of 1. 133 iCurrentCommand.Construct(0, 1); 134 135 //Set the node capability data. 136 //This node can support an unlimited number of ports. 137 iCapability.iCanSupportMultipleInputPorts = false; 138 iCapability.iCanSupportMultipleOutputPorts = false; 139 iCapability.iHasMaxNumberOfPorts = true; 140 iCapability.iMaxNumberOfPorts = 2; 141 iCapability.iInputFormatCapability.push_back(PVMF_MIME_MPEG4_AUDIO); 142 iCapability.iInputFormatCapability.push_back(PVMF_MIME_3640); 143 iCapability.iInputFormatCapability.push_back(PVMF_MIME_ADIF); 144 iCapability.iInputFormatCapability.push_back(PVMF_MIME_LATM); 145 iCapability.iInputFormatCapability.push_back(PVMF_MIME_ASF_MPEG4_AUDIO); 146 iCapability.iInputFormatCapability.push_back(PVMF_MIME_AAC_SIZEHDR); 147 148 iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR_IF2); 149 iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR_IETF); 150 iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR); 151 iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMRWB_IETF); 152 iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMRWB); 153 154 iCapability.iInputFormatCapability.push_back(PVMF_MIME_MP3); 155 156 iCapability.iInputFormatCapability.push_back(PVMF_MIME_WMA); 157 158 iCapability.iOutputFormatCapability.push_back(PVMF_MIME_PCM16); 159 160 iAvailableMetadataKeys.reserve(PVMF_OMXAUDIODEC_NUM_METADATA_VALUES); 161 iAvailableMetadataKeys.clear(); 162 ); 163 // LATM init 164 iLATMParser = NULL; 165 iLATMConfigBuffer = NULL; 166 iLATMConfigBufferSize = 0; 167 168 //Try Allocate FSI buffer 169 170 // Do This first in case of Query 171 OSCL_TRY(err, iFsiFragmentAlloc.size(PVOMXAUDIODEC_MEDIADATA_POOLNUM, sizeof(channelSampleInfo))); 172 173 174 OSCL_TRY(err, iPrivateDataFsiFragmentAlloc.size(PVOMXAUDIODEC_MEDIADATA_POOLNUM, sizeof(OsclAny *))); 175 } 176 177 ///////////////////////////////////////////////////////////////////////////// 178 // This routine will process incomming message from the port 179 ///////////////////////////////////////////////////////////////////////////// 180 bool PVMFOMXAudioDecNode::ProcessIncomingMsg(PVMFPortInterface* aPort) 181 { 182 //Called by the AO to process one buffer off the port's 183 //incoming data queue. This routine will dequeue and 184 //dispatch the data. 185 186 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 187 (0, "0x%x PVMFOMXAudioDecNode::ProcessIncomingMsg: aPort=0x%x", this, aPort)); 188 189 PVMFStatus status = PVMFFailure; 190 #ifdef SIMULATE_DROP_MSGS 191 if ((((PVMFOMXDecPort*)aPort)->iNumFramesConsumed % 300 == 299)) // && (((PVMFOMXDecPort*)aPort)->iNumFramesConsumed < 30) ) 192 { 193 194 // just dequeue 195 PVMFSharedMediaMsgPtr msg; 196 197 status = aPort->DequeueIncomingMsg(msg); 198 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 199 status = aPort->DequeueIncomingMsg(msg); 200 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 201 status = aPort->DequeueIncomingMsg(msg); 202 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 203 204 #ifdef _DEBUG 205 printf("PVMFOMXAudioDecNode::ProcessIncomingMsg() SIMULATED DROP 3 MSGS\n"); 206 #endif 207 208 209 } 210 #endif 211 212 #ifdef SIMULATE_BOS 213 214 if ((((PVMFOMXDecPort*)aPort)->iNumFramesConsumed == 6)) 215 { 216 217 PVMFSharedMediaCmdPtr BOSCmdPtr = PVMFMediaCmd::createMediaCmd(); 218 219 // Set the format ID to BOS 220 BOSCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID); 221 222 // Set the timestamp 223 BOSCmdPtr->setTimestamp(201); 224 BOSCmdPtr->setStreamID(0); 225 226 // Convert to media message and send it out 227 PVMFSharedMediaMsgPtr mediaMsgOut; 228 convertToPVMFMediaCmdMsg(mediaMsgOut, BOSCmdPtr); 229 230 //store the stream id and time stamp of bos message 231 iStreamID = mediaMsgOut->getStreamID(); 232 iBOSTimestamp = mediaMsgOut->getTimestamp(); 233 234 235 iInputTimestampClock.set_clock(iBOSTimestamp, 0); 236 iOMXTicksTimestamp = ConvertTimestampIntoOMXTicks(iInputTimestampClock); 237 238 iSendBOS = true; 239 240 #ifdef _DEBUG 241 printf("PVMFOMXAudioDecNode::ProcessIncomingMsg() SIMULATED BOS\n"); 242 #endif 243 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 244 return true; 245 246 } 247 #endif 248 249 #ifdef SIMULATE_PREMATURE_EOS 250 if (((PVMFOMXDecPort*)aPort)->iNumFramesConsumed == 5) 251 { 252 PVMFSharedMediaCmdPtr EOSCmdPtr = PVMFMediaCmd::createMediaCmd(); 253 254 // Set the format ID to EOS 255 EOSCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID); 256 257 // Set the timestamp 258 EOSCmdPtr->setTimestamp(200); 259 260 // Convert to media message and send it out 261 PVMFSharedMediaMsgPtr mediaMsgOut; 262 convertToPVMFMediaCmdMsg(mediaMsgOut, EOSCmdPtr); 263 264 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 265 266 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 267 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: SIMULATED EOS")); 268 #ifdef _DEBUG 269 printf("PVMFOMXAudioDecNode::ProcessIncomingMsg() SIMULATED EOS\n"); 270 #endif 271 // Set EOS flag 272 iEndOfDataReached = true; 273 // Save the timestamp for the EOS cmd 274 iEndOfDataTimestamp = mediaMsgOut->getTimestamp(); 275 276 return true; 277 } 278 279 #endif 280 281 282 283 PVMFSharedMediaMsgPtr msg; 284 285 status = aPort->DequeueIncomingMsg(msg); 286 if (status != PVMFSuccess) 287 { 288 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 289 (0, "0x%x PVMFOMXAudioDecNode::ProcessIncomingMsg: Error - DequeueIncomingMsg failed", this)); 290 return false; 291 } 292 293 if (msg->getFormatID() == PVMF_MEDIA_CMD_BOS_FORMAT_ID) 294 { 295 //store the stream id and time stamp of bos message 296 iStreamID = msg->getStreamID(); 297 iBOSTimestamp = msg->getTimestamp(); 298 299 300 iInputTimestampClock.set_clock(iBOSTimestamp, 0); 301 iOMXTicksTimestamp = ConvertTimestampIntoOMXTicks(iInputTimestampClock); 302 303 iSendBOS = true; 304 305 // if new BOS arrives, and 306 //if we're in the middle of a partial frame assembly 307 // abandon it and start fresh 308 if (iObtainNewInputBuffer == false) 309 { 310 if (iInputBufferUnderConstruction != NULL) 311 { 312 if (iInBufMemoryPool != NULL) 313 { 314 iInBufMemoryPool->deallocate((OsclAny *)iInputBufferUnderConstruction); 315 } 316 iInputBufferUnderConstruction = NULL; 317 } 318 iObtainNewInputBuffer = true; 319 320 } 321 322 // needed to init the sequence numbers and timestamp for partial frame assembly 323 iFirstDataMsgAfterBOS = true; 324 iKeepDroppingMsgsUntilMarkerBit = false; 325 326 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 327 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received BOS stream %d, timestamp %d", iStreamID, iBOSTimestamp)); 328 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 329 return true; 330 } 331 else if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID) 332 { 333 // Set EOS flag 334 iEndOfDataReached = true; 335 // Save the timestamp for the EOS cmd 336 iEndOfDataTimestamp = msg->getTimestamp(); 337 338 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 339 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received EOS")); 340 341 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 342 return true; // do not do conversion into media data, just set the flag and leave 343 } 344 345 346 /////////////////////////////////////////////////////////////////////////////////////// 347 /////////////////////////////////////////////////////////////////////// 348 // For LATM data, need to convert to raw bitstream 349 if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM) 350 { 351 // Keep looping and parsing LATM data until frame complete or data queue runs out 352 uint8 retval; //=FRAME_INCOMPLETE; 353 // if LATM parser does not exist (very first frame), create it: 354 if (iLATMParser == NULL) 355 { 356 // Create and configure the LATM parser based on the stream MUX config 357 // which should be sent as the format specific config in the first media data 358 if (CreateLATMParser() != PVMFSuccess) 359 { 360 361 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 362 (0, "PVMFOMXAudioDecNode::Process Incoming Msg - LATM parser cannot be created")); 363 OSCL_ASSERT(false); 364 ReportErrorEvent(PVMFErrResourceConfiguration); 365 ChangeNodeState(EPVMFNodeError); 366 return true; 367 } 368 369 // get FSI 370 OsclRefCounterMemFrag DataFrag; 371 msg->getFormatSpecificInfo(DataFrag); 372 373 //get pointer to the data fragment 374 uint8* initbuffer = (uint8 *) DataFrag.getMemFragPtr(); 375 uint32 initbufsize = (int32) DataFrag.getMemFragSize(); 376 377 iLATMConfigBufferSize = initbufsize; 378 iLATMConfigBuffer = iLATMParser->ParseStreamMuxConfig(initbuffer, (int32 *) & iLATMConfigBufferSize); 379 if (iLATMConfigBuffer == NULL) 380 { 381 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 382 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg() LATM Stream MUX config parsing failed")); 383 OSCL_ASSERT(false); 384 ReportErrorEvent(PVMFErrResourceConfiguration); 385 ChangeNodeState(EPVMFNodeError); 386 return true; 387 } 388 389 } 390 391 do 392 { 393 if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID) 394 { 395 // Set EOS flag 396 iEndOfDataReached = true; 397 // Save the timestamp for the EOS cmd 398 iEndOfDataTimestamp = msg->getTimestamp(); 399 400 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 401 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received EOS")); 402 403 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 404 return true; // do not do conversion into media data, just set the flag and leave 405 406 } 407 // Convert the next input media msg to media data 408 PVMFSharedMediaDataPtr mediaData; 409 convertToPVMFMediaData(mediaData, msg); 410 411 412 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 413 414 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iDataPathLogger, PVLOGMSG_INFO, 415 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: TS=%d, SEQNUM= %d", msg->getTimestamp(), msg->getSeqNum())); 416 417 418 // Convert the LATM data to raw bitstream 419 retval = iLATMParser->compose(mediaData); 420 421 // if frame is complete, break out of the loop 422 if (retval != FRAME_INCOMPLETE && retval != FRAME_ERROR) 423 break; 424 425 // frame is not complete, keep looping 426 if (aPort->IncomingMsgQueueSize() == 0) 427 { 428 // no more data in the input port queue, unbind current msg, and return 429 msg.Unbind(); 430 // enable reading more data from port 431 break; 432 } 433 else 434 { 435 msg.Unbind(); 436 aPort->DequeueIncomingMsg(msg); // dequeue the message directly from input port 437 438 } 439 440 // Log parser error 441 if (retval == FRAME_ERROR) 442 { 443 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 444 (0, "PVMFAACDecNode::GetInputMediaData() LATM parser error")); 445 } 446 } 447 while ((retval == FRAME_INCOMPLETE || retval == FRAME_ERROR)); 448 449 if (retval == FRAME_COMPLETE) 450 { 451 // Save the media data containing the parser data as the input media data 452 iDataIn = iLATMParser->GetOutputBuffer(); 453 // set the MARKER bit on the data msg, since this is a complete frame produced by LATM parser 454 iDataIn->setMarkerInfo(PVMF_MEDIA_DATA_MARKER_INFO_M_BIT); 455 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, 456 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: - LATM frame assembled")); 457 458 } 459 else if ((retval == FRAME_INCOMPLETE) || (retval == FRAME_ERROR)) 460 { 461 // Do nothing and wait for more data to come in 462 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, 463 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: - incomplete LATM")); 464 // return immediately (i.e. don't assign anything to iDataIn, which will prevent 465 // processing 466 return true; 467 } 468 else if (retval == FRAME_OUTPUTNOTAVAILABLE) 469 { 470 // This should not happen since this node processes one parsed media data at a time 471 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 472 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: LATM parser OUTPUT NOT AVAILABLE")); 473 474 msg.Unbind(); 475 476 OSCL_ASSERT(false); 477 ReportErrorEvent(PVMFErrResourceConfiguration); 478 ChangeNodeState(EPVMFNodeError); 479 480 return true; 481 } 482 } 483 ///////////////////////////////////////////////////////// 484 ////////////////////////// 485 else 486 { 487 // regular (i.e. Non-LATM case) 488 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iDataPathLogger, PVLOGMSG_INFO, 489 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: TS=%d, SEQNUM= %d", msg->getTimestamp(), msg->getSeqNum())); 490 491 convertToPVMFMediaData(iDataIn, msg); 492 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++; 493 } 494 495 iCurrFragNum = 0; // for new message, reset the fragment counter 496 iIsNewDataFragment = true; 497 498 499 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg() Received %d frames", ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed)); 500 501 //return true if we processed an activity... 502 return true; 503 } 504 505 ///////////////////////////////////////////////////////////////////////////// 506 // This routine will handle the PortReEnable state 507 ///////////////////////////////////////////////////////////////////////////// 508 PVMFStatus PVMFOMXAudioDecNode::HandlePortReEnable() 509 { 510 // set the port index so that we get parameters for the proper port 511 iParamPort.nPortIndex = iPortIndexForDynamicReconfig; 512 513 CONFIG_SIZE_AND_VERSION(iParamPort); 514 515 // get new parameters of the port 516 OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort); 517 518 // send command for port re-enabling (for this to happen, we must first recreate the buffers) 519 OMX_SendCommand(iOMXDecoder, OMX_CommandPortEnable, iPortIndexForDynamicReconfig, NULL); 520 521 522 // get also input info (for frame duration if necessary) 523 OMX_ERRORTYPE Err; 524 OMX_PTR CodecProfilePtr; 525 OMX_INDEXTYPE CodecProfileIndx; 526 OMX_AUDIO_PARAM_AACPROFILETYPE Audio_Aac_Param; 527 528 // determine the proper index and structure (based on codec type) 529 if (iInPort) 530 { 531 // AAC 532 if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO || 533 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640 || 534 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM || 535 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF || 536 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO || 537 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AAC_SIZEHDR) // for testing 538 { 539 CodecProfilePtr = (OMX_PTR) & Audio_Aac_Param; 540 CodecProfileIndx = OMX_IndexParamAudioAac; 541 Audio_Aac_Param.nPortIndex = iInputPortIndex; 542 543 CONFIG_SIZE_AND_VERSION(Audio_Aac_Param); 544 545 546 // get parameters: 547 Err = OMX_GetParameter(iOMXDecoder, CodecProfileIndx, CodecProfilePtr); 548 if (Err != OMX_ErrorNone) 549 { 550 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 551 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Input port parameters problem")); 552 553 SetState(EPVMFNodeError); 554 ReportErrorEvent(PVMFErrResource); 555 return PVMFErrResource; 556 } 557 } 558 // for AMR, frame sizes are known, no need to get the parameters 559 // for MP3, frame sizes cannot be obtained through OMX params 560 // for WMA, frame sizes cannot be obtained through OMX params 561 } 562 563 564 565 PVMFFormatType Format = PVMF_MIME_FORMAT_UNKNOWN; 566 if (iInPort != NULL) 567 { 568 Format = ((PVMFOMXDecPort*)iInPort)->iFormat; 569 } 570 if (Format == PVMF_MIME_MPEG4_AUDIO || 571 Format == PVMF_MIME_3640 || 572 Format == PVMF_MIME_LATM || 573 Format == PVMF_MIME_ADIF || 574 Format == PVMF_MIME_ASF_MPEG4_AUDIO || 575 Format == PVMF_MIME_AAC_SIZEHDR) // for testing 576 { 577 iSamplesPerFrame = Audio_Aac_Param.nFrameLength; 578 } 579 // AMR 580 else if (Format == PVMF_MIME_AMR_IF2 || 581 Format == PVMF_MIME_AMR_IETF || 582 Format == PVMF_MIME_AMR) 583 { 584 // AMR NB has fs=8khz Mono and the frame is 20ms long, i.e. there is 160 samples per frame 585 iSamplesPerFrame = PVOMXAUDIODEC_AMRNB_SAMPLES_PER_FRAME; 586 } 587 else if (Format == PVMF_MIME_AMRWB_IETF || 588 Format == PVMF_MIME_AMRWB) 589 { 590 // AMR WB has fs=16khz Mono and the frame is 20ms long, i.e. there is 320 samples per frame 591 iSamplesPerFrame = PVOMXAUDIODEC_AMRWB_SAMPLES_PER_FRAME; 592 } 593 else if (Format == PVMF_MIME_MP3) 594 { 595 // frame size is either 576 or 1152 samples per frame. However, this information cannot be 596 // obtained through OMX MP3 Params. Assume that it's 1152 597 iSamplesPerFrame = PVOMXAUDIODEC_MP3_DEFAULT_SAMPLES_PER_FRAME; 598 } 599 else if (Format == PVMF_MIME_WMA) 600 { 601 // output frame size is unknown in WMA. However, the PV-WMA decoder can control the number 602 // of samples it places in an output buffer, so we can create an output buffer of arbitrary size 603 // and let the decoder control how it is filled 604 iSamplesPerFrame = 0; // unknown 605 } 606 607 // is this output port? 608 if (iPortIndexForDynamicReconfig == iOutputPortIndex) 609 { 610 611 // GET the output buffer params and sizes 612 OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param; 613 Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params 614 615 CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param); 616 617 618 619 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param); 620 if (Err != OMX_ErrorNone) 621 { 622 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 623 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot get component output parameters")); 624 625 SetState(EPVMFNodeError); 626 ReportErrorEvent(PVMFErrResource); 627 return PVMFErrResource; 628 } 629 630 iPCMSamplingRate = Audio_Pcm_Param.nSamplingRate; // can be set to 0 (if unknown) 631 632 if (iPCMSamplingRate == 0) // use default sampling rate (i.e. 48000) 633 iPCMSamplingRate = PVOMXAUDIODEC_DEFAULT_SAMPLINGRATE; 634 635 iNumberOfAudioChannels = Audio_Pcm_Param.nChannels; // should be 1 or 2 636 if (iNumberOfAudioChannels != 1 && iNumberOfAudioChannels != 2) 637 { 638 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 639 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Output parameters num channels = %d", iNumberOfAudioChannels)); 640 641 SetState(EPVMFNodeError); 642 ReportErrorEvent(PVMFErrResource); 643 return PVMFErrResource; 644 } 645 646 if ((iSamplesPerFrame != 0) && ((iSamplesPerFrame * 1000) > iPCMSamplingRate)) 647 // if this iSamplesPerFrame is known and is large enough to ensure that the iMilliSecPerFrame calculation 648 // below won't be set to 0. 649 { 650 // CALCULATE NumBytes per frame, Msec per frame, etc. 651 iNumBytesPerFrame = 2 * iSamplesPerFrame * iNumberOfAudioChannels; 652 iMilliSecPerFrame = (iSamplesPerFrame * 1000) / iPCMSamplingRate; 653 // Determine the size of each PCM output buffer. Size would be big enough to hold certain time amount of PCM data 654 uint32 numframes = PVOMXAUDIODEC_DEFAULT_OUTPUTPCM_TIME / iMilliSecPerFrame; 655 656 if (PVOMXAUDIODEC_DEFAULT_OUTPUTPCM_TIME % iMilliSecPerFrame) 657 { 658 // If there is a remainder, include one more frame 659 ++numframes; 660 } 661 662 // set the output buffer size accordingly: 663 iOMXComponentOutputBufferSize = numframes * iNumBytesPerFrame; 664 } 665 else 666 iOMXComponentOutputBufferSize = (2 * iNumberOfAudioChannels * PVOMXAUDIODEC_DEFAULT_OUTPUTPCM_TIME * iPCMSamplingRate) / 1000; // assuming 16 bits per sample 667 668 if (iOMXComponentOutputBufferSize < iParamPort.nBufferSize) 669 { 670 // the OMX spec says that nBuffersize is a read only field, but the client is allowed to allocate 671 // a buffer size larger than nBufferSize. 672 iOMXComponentOutputBufferSize = iParamPort.nBufferSize; 673 } 674 675 676 // do we need to increase the number of buffers? 677 if (iNumOutputBuffers < iParamPort.nBufferCountMin) 678 iNumOutputBuffers = iParamPort.nBufferCountMin; 679 680 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 681 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() new output buffers %d, size %d", iNumOutputBuffers, iOMXComponentOutputBufferSize)); 682 683 //Send the FSI information to media output node here, before setting output 684 //port parameters to the omx component 685 // Check if Fsi configuration need to be sent 686 sendFsi = true; 687 iCompactFSISettingSucceeded = false; 688 689 if (sendFsi) 690 { 691 int fsiErrorCode = 0; 692 693 OsclRefCounterMemFrag FsiMemfrag; 694 695 OSCL_TRY(fsiErrorCode, FsiMemfrag = iFsiFragmentAlloc.get();); 696 697 OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 698 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Failed to allocate memory for FSI"))); 699 700 if (fsiErrorCode == 0) 701 { 702 channelSampleInfo* pcminfo = (channelSampleInfo*) FsiMemfrag.getMemFragPtr(); 703 704 if (pcminfo != NULL) 705 { 706 OSCL_ASSERT(pcminfo != NULL); 707 708 pcminfo->samplingRate = iPCMSamplingRate; 709 pcminfo->desiredChannels = iNumberOfAudioChannels; 710 pcminfo->bitsPerSample = 16; 711 pcminfo->num_buffers = iNumOutputBuffers; 712 pcminfo->buffer_size = iOMXComponentOutputBufferSize; 713 714 OsclMemAllocator alloc; 715 int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM) + 1; 716 PvmiKeyType KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength); 717 718 if (NULL == KvpKey) 719 { 720 return false; 721 } 722 723 oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM, KeyLength); 724 int32 err; 725 726 OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(FsiMemfrag, KvpKey);); 727 if (err != OsclErrNone) 728 { 729 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 730 (0, "PVMFOMXAudioDecNode::HandlePortReEnable - Problem to set FSI")); 731 } 732 else 733 { 734 sendFsi = false; 735 iCompactFSISettingSucceeded = true; 736 } 737 738 739 alloc.deallocate((OsclAny*)(KvpKey)); 740 } 741 else 742 { 743 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 744 (0, "PVMFOMXAudioDecNode::HandlePortReEnable - Problem allocating Output FSI")); 745 SetState(EPVMFNodeError); 746 ReportErrorEvent(PVMFErrNoMemory); 747 return false; // this is going to make everything go out of scope 748 } 749 } 750 else 751 { 752 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 753 (0, "PVMFOMXAudioDecNode::HandlePortReEnable - Problem allocating Output FSI")); 754 return false; // this is going to make everything go out of scope 755 } 756 757 758 } 759 760 761 //Buffer allocator kvp query and allocation has to be done again if we landed into handle port reconfiguration 762 763 PvmiKvp* kvp = NULL; 764 int numKvp = 0; 765 PvmiKeyType aIdentifier = (PvmiKeyType)PVMF_BUFFER_ALLOCATOR_KEY; 766 int32 err, err1; 767 ipExternalOutputBufferAllocatorInterface = NULL; 768 769 OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiGetBufferAllocatorSpecificInfoSync(aIdentifier, kvp, numKvp);); 770 771 if ((err == OsclErrNone) && (NULL != kvp)) 772 { 773 ipExternalOutputBufferAllocatorInterface = (PVInterface *)kvp->value.key_specific_value; 774 775 if (ipExternalOutputBufferAllocatorInterface) 776 { 777 PVInterface* pTempPVInterfacePtr = NULL; 778 OSCL_TRY(err, ipExternalOutputBufferAllocatorInterface->queryInterface(PVMFFixedSizeBufferAllocUUID, pTempPVInterfacePtr);); 779 780 OSCL_TRY(err1, ((PVMFOMXDecPort*)iOutPort)->releaseParametersSync(kvp, numKvp);); 781 782 if (err1 != OsclErrNone) 783 { 784 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 785 (0, "PVMFOMXAudioDecNode::HandlePortReEnable - Unable to Release Parameters")); 786 } 787 788 if ((err == OsclErrNone) && (NULL != pTempPVInterfacePtr)) 789 { 790 ipFixedSizeBufferAlloc = OSCL_STATIC_CAST(PVMFFixedSizeBufferAlloc*, pTempPVInterfacePtr); 791 792 uint32 iNumBuffers, iBufferSize; 793 794 iNumBuffers = ipFixedSizeBufferAlloc->getNumBuffers(); 795 iBufferSize = ipFixedSizeBufferAlloc->getBufferSize(); 796 797 if ((iNumBuffers < iParamPort.nBufferCountMin) || (iBufferSize < iOMXComponentOutputBufferSize)) 798 { 799 ipExternalOutputBufferAllocatorInterface->removeRef(); 800 ipExternalOutputBufferAllocatorInterface = NULL; 801 } 802 else 803 { 804 iNumOutputBuffers = iNumBuffers; 805 iOMXComponentOutputBufferSize = iBufferSize; 806 } 807 808 } 809 else 810 { 811 ipExternalOutputBufferAllocatorInterface->removeRef(); 812 ipExternalOutputBufferAllocatorInterface = NULL; 813 } 814 } 815 } 816 817 818 /* Allocate output buffers */ 819 if (!CreateOutMemPool(iNumOutputBuffers)) 820 { 821 822 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 823 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot allocate output buffers ")); 824 825 SetState(EPVMFNodeError); 826 ReportErrorEvent(PVMFErrNoMemory); 827 return PVMFErrNoMemory; 828 } 829 830 if (out_ctrl_struct_ptr == NULL) 831 { 832 833 out_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *)); 834 835 if (out_ctrl_struct_ptr == NULL) 836 { 837 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 838 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() out_ctrl_struct_ptr == NULL")); 839 840 SetState(EPVMFNodeError); 841 ReportErrorEvent(PVMFErrNoMemory); 842 return PVMFErrNoMemory; 843 } 844 } 845 846 if (out_buff_hdr_ptr == NULL) 847 { 848 849 out_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumOutputBuffers * sizeof(OsclAny *)); 850 851 if (out_buff_hdr_ptr == NULL) 852 { 853 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 854 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() out_buff_hdr_ptr == NULL")); 855 856 SetState(EPVMFNodeError); 857 ReportErrorEvent(PVMFErrNoMemory); 858 return PVMFErrNoMemory; 859 } 860 } 861 862 863 if (!ProvideBuffersToComponent(iOutBufMemoryPool, // allocator 864 iOutputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 865 iNumOutputBuffers, // number of buffers 866 iOMXComponentOutputBufferSize, // actual buffer size 867 iOutputPortIndex, // port idx 868 iOMXComponentSupportsExternalOutputBufferAlloc, // can component use OMX_UseBuffer 869 false // this is not input 870 )) 871 { 872 873 874 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 875 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot provide output buffers to component")); 876 877 SetState(EPVMFNodeError); 878 ReportErrorEvent(PVMFErrNoMemory); 879 return PVMFErrNoMemory; 880 881 } 882 883 // do not drop output any more, i.e. enable output to be sent downstream 884 iDoNotSendOutputBuffersDownstreamFlag = false; 885 886 887 } 888 else 889 { 890 // this is input port 891 892 iOMXComponentInputBufferSize = iParamPort.nBufferSize; 893 // do we need to increase the number of buffers? 894 if (iNumInputBuffers < iParamPort.nBufferCountMin) 895 iNumInputBuffers = iParamPort.nBufferCountMin; 896 897 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 898 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() new buffers %d, size %d", iNumInputBuffers, iOMXComponentInputBufferSize)); 899 900 /* Allocate input buffers */ 901 if (!CreateInputMemPool(iNumInputBuffers)) 902 { 903 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 904 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot allocate new input buffers to component")); 905 906 SetState(EPVMFNodeError); 907 ReportErrorEvent(PVMFErrNoMemory); 908 return PVMFErrNoMemory; 909 } 910 911 if (in_ctrl_struct_ptr == NULL) 912 { 913 914 in_ctrl_struct_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *)); 915 916 if (in_ctrl_struct_ptr == NULL) 917 { 918 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 919 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() in_ctrl_struct_ptr == NULL")); 920 921 SetState(EPVMFNodeError); 922 ReportErrorEvent(PVMFErrNoMemory); 923 return PVMFErrNoMemory; 924 } 925 } 926 927 if (in_buff_hdr_ptr == NULL) 928 { 929 930 in_buff_hdr_ptr = (OsclAny **) oscl_malloc(iNumInputBuffers * sizeof(OsclAny *)); 931 932 if (in_buff_hdr_ptr == NULL) 933 { 934 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 935 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() in_buff_hdr_ptr == NULL")); 936 937 SetState(EPVMFNodeError); 938 ReportErrorEvent(PVMFErrNoMemory); 939 return PVMFErrNoMemory; 940 } 941 } 942 943 944 if (!ProvideBuffersToComponent(iInBufMemoryPool, // allocator 945 iInputAllocSize, // size to allocate from pool (hdr only or hdr+ buffer) 946 iNumInputBuffers, // number of buffers 947 iOMXComponentInputBufferSize, // actual buffer size 948 iInputPortIndex, // port idx 949 iOMXComponentSupportsExternalInputBufferAlloc, // can component use OMX_UseBuffer 950 true // this is input 951 )) 952 { 953 954 955 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 956 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot provide new input buffers to component")); 957 958 SetState(EPVMFNodeError); 959 ReportErrorEvent(PVMFErrNoMemory); 960 return PVMFErrNoMemory; 961 962 } 963 // do not drop partially consumed input 964 iDoNotSaveInputBuffersFlag = false; 965 966 } 967 968 // if the callback that the port was re-enabled has not arrived yet, wait for it 969 // if it has arrived, it will set the state to either PortReconfig or to ReadyToDecode 970 if (iProcessingState != EPVMFOMXBaseDecNodeProcessingState_PortReconfig && 971 iProcessingState != EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode) 972 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForPortEnable; 973 974 return PVMFSuccess; // allow rescheduling of the node 975 } 976 //////////////////////////////////////////////////////////////////////////////// 977 bool PVMFOMXAudioDecNode::NegotiateComponentParameters(OMX_PTR aOutputParameters) 978 { 979 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 980 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() In")); 981 982 OMX_ERRORTYPE Err; 983 // first get the number of ports and port indices 984 OMX_PORT_PARAM_TYPE AudioPortParameters; 985 uint32 NumPorts; 986 uint32 ii; 987 988 989 pvAudioConfigParserInputs aInputs; 990 AudioOMXConfigParserOutputs *pOutputParameters; 991 992 aInputs.inPtr = (uint8*)((PVMFOMXDecPort*)iInPort)->iTrackConfig; 993 aInputs.inBytes = (int32)((PVMFOMXDecPort*)iInPort)->iTrackConfigSize; 994 aInputs.iMimeType = ((PVMFOMXDecPort*)iInPort)->iFormat; 995 pOutputParameters = (AudioOMXConfigParserOutputs *)aOutputParameters; 996 997 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 998 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Calling audio config parser - TrackConfig = %p, TrackConfigSize = %d, mimetype = %s", aInputs.inPtr, aInputs.inBytes, aInputs.iMimeType.getMIMEStrPtr())); 999 1000 1001 1002 if (aInputs.iMimeType == PVMF_MIME_WMA) 1003 { 1004 iNumberOfAudioChannels = pOutputParameters->Channels; 1005 iPCMSamplingRate = pOutputParameters->SamplesPerSec; 1006 } 1007 else if (aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO || 1008 aInputs.iMimeType == PVMF_MIME_3640 || 1009 aInputs.iMimeType == PVMF_MIME_LATM || 1010 aInputs.iMimeType == PVMF_MIME_ADIF || 1011 aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO || 1012 aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR) 1013 1014 { 1015 iNumberOfAudioChannels = pOutputParameters->Channels; 1016 } 1017 1018 CONFIG_SIZE_AND_VERSION(AudioPortParameters); 1019 // get starting number 1020 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioInit, &AudioPortParameters); 1021 NumPorts = AudioPortParameters.nPorts; // must be at least 2 of them (in&out) 1022 1023 if (Err != OMX_ErrorNone || NumPorts < 2) 1024 { 1025 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1026 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() There is insuffucient (%d) ports", NumPorts)); 1027 return false; 1028 } 1029 1030 1031 // loop through ports starting from the starting index to find index of the first input port 1032 for (ii = AudioPortParameters.nStartPortNumber ; ii < AudioPortParameters.nStartPortNumber + NumPorts; ii++) 1033 { 1034 // get port parameters, and determine if it is input or output 1035 // if there are more than 2 ports, the first one we encounter that has input direction is picked 1036 1037 iParamPort.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 1038 1039 //port 1040 iParamPort.nPortIndex = ii; 1041 1042 CONFIG_SIZE_AND_VERSION(iParamPort); 1043 1044 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort); 1045 1046 if (Err != OMX_ErrorNone) 1047 { 1048 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1049 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with port %d ", ii)); 1050 1051 return false; 1052 } 1053 1054 if (iParamPort.eDir == OMX_DirInput) 1055 { 1056 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1057 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Found Input port index %d ", ii)); 1058 1059 iInputPortIndex = ii; 1060 break; 1061 } 1062 } 1063 if (ii == AudioPortParameters.nStartPortNumber + NumPorts) 1064 { 1065 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1066 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Cannot find any input port ")); 1067 return false; 1068 } 1069 1070 1071 // loop through ports starting from the starting index to find index of the first output port 1072 for (ii = AudioPortParameters.nStartPortNumber ; ii < AudioPortParameters.nStartPortNumber + NumPorts; ii++) 1073 { 1074 // get port parameters, and determine if it is input or output 1075 // if there are more than 2 ports, the first one we encounter that has output direction is picked 1076 1077 1078 //port 1079 iParamPort.nPortIndex = ii; 1080 1081 CONFIG_SIZE_AND_VERSION(iParamPort); 1082 1083 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort); 1084 1085 if (Err != OMX_ErrorNone) 1086 { 1087 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1088 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with port %d ", ii)); 1089 1090 return false; 1091 } 1092 1093 if (iParamPort.eDir == OMX_DirOutput) 1094 { 1095 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1096 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Found Output port index %d ", ii)); 1097 1098 iOutputPortIndex = ii; 1099 break; 1100 } 1101 } 1102 if (ii == AudioPortParameters.nStartPortNumber + NumPorts) 1103 { 1104 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1105 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Cannot find any output port ")); 1106 return false; 1107 } 1108 1109 1110 1111 // now get input parameters 1112 1113 CONFIG_SIZE_AND_VERSION(iParamPort); 1114 1115 //Input port 1116 iParamPort.nPortIndex = iInputPortIndex; 1117 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort); 1118 if (Err != OMX_ErrorNone) 1119 { 1120 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1121 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with input port %d ", iInputPortIndex)); 1122 return false; 1123 } 1124 1125 // preset the number of input buffers 1126 //iNumInputBuffers = NUMBER_INPUT_BUFFER; 1127 iNumInputBuffers = iParamPort.nBufferCountActual; // use the value provided by component 1128 1129 // do we need to increase the number of buffers? 1130 if (iNumInputBuffers < iParamPort.nBufferCountMin) 1131 iNumInputBuffers = iParamPort.nBufferCountMin; 1132 1133 iOMXComponentInputBufferSize = iParamPort.nBufferSize; 1134 1135 iParamPort.nBufferCountActual = iNumInputBuffers; 1136 1137 // set the number of actual input buffers 1138 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1139 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Inport buffers %d,size %d", iNumInputBuffers, iOMXComponentInputBufferSize)); 1140 1141 1142 1143 1144 CONFIG_SIZE_AND_VERSION(iParamPort); 1145 iParamPort.nPortIndex = iInputPortIndex; 1146 // finalize setting input port parameters 1147 Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort); 1148 if (Err != OMX_ErrorNone) 1149 { 1150 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1151 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting parameters in input port %d ", iInputPortIndex)); 1152 return false; 1153 } 1154 1155 1156 // in case of WMA - config parser decodes config info and produces reliable numchannels and sampling rate 1157 // set these values now to prevent unnecessary port reconfig 1158 if (aInputs.iMimeType == PVMF_MIME_WMA) 1159 { 1160 // First get the structure 1161 OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param; 1162 Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params 1163 CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param); 1164 1165 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param); 1166 if (Err != OMX_ErrorNone) 1167 { 1168 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1169 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating PCM parameters with output port %d ", iOutputPortIndex)); 1170 return false; 1171 } 1172 1173 // set the sampling rate obtained from config parser 1174 Audio_Pcm_Param.nSamplingRate = iPCMSamplingRate; // can be set to 0 (if unknown) 1175 1176 // set number of channels obtained from config parser 1177 Audio_Pcm_Param.nChannels = iNumberOfAudioChannels; // should be 1 or 2 1178 1179 // Now, set the parameters 1180 Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params 1181 CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param); 1182 1183 Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param); 1184 if (Err != OMX_ErrorNone) 1185 { 1186 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1187 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem Setting PCM parameters with output port %d ", iOutputPortIndex)); 1188 return false; 1189 } 1190 1191 } 1192 1193 1194 // Codec specific info set/get: SamplingRate, formats etc. 1195 // NOTE: iParamPort is modified in the routine below - it is loaded from the component output port values 1196 // Based on sampling rate - we also determine the desired output buffer size 1197 if (!GetSetCodecSpecificInfo()) 1198 return false; 1199 1200 1201 1202 //Port 1 for output port 1203 iParamPort.nPortIndex = iOutputPortIndex; 1204 1205 CONFIG_SIZE_AND_VERSION(iParamPort); 1206 1207 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort); 1208 if (Err != OMX_ErrorNone) 1209 { 1210 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1211 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with output port %d ", iOutputPortIndex)); 1212 return false; 1213 } 1214 1215 // set number of output buffers and the size 1216 iNumOutputBuffers = iParamPort.nBufferCountActual; 1217 1218 if (iNumOutputBuffers > NUMBER_OUTPUT_BUFFER) 1219 iNumOutputBuffers = NUMBER_OUTPUT_BUFFER; // make sure to limit this number to what the port can hold 1220 1221 1222 if (iNumOutputBuffers < iParamPort.nBufferCountMin) 1223 iNumOutputBuffers = iParamPort.nBufferCountMin; 1224 1225 1226 //Send the FSI information to media output node here, before setting output 1227 //port parameters to the omx component 1228 1229 // Check if Fsi configuration need to be sent 1230 sendFsi = true; 1231 iCompactFSISettingSucceeded = false; 1232 if (sendFsi) 1233 { 1234 int fsiErrorCode = 0; 1235 1236 OsclRefCounterMemFrag FsiMemfrag; 1237 1238 OSCL_TRY(fsiErrorCode, FsiMemfrag = iFsiFragmentAlloc.get();); 1239 1240 OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1241 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Failed to allocate memory for FSI"))); 1242 1243 if (fsiErrorCode == 0) 1244 { 1245 channelSampleInfo* pcminfo = (channelSampleInfo*) FsiMemfrag.getMemFragPtr(); 1246 if (pcminfo != NULL) 1247 { 1248 OSCL_ASSERT(pcminfo != NULL); 1249 1250 pcminfo->samplingRate = iPCMSamplingRate; 1251 pcminfo->desiredChannels = iNumberOfAudioChannels; 1252 pcminfo->bitsPerSample = 16; 1253 pcminfo->num_buffers = iNumOutputBuffers; 1254 pcminfo->buffer_size = iOMXComponentOutputBufferSize; 1255 1256 OsclMemAllocator alloc; 1257 int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM) + 1; 1258 PvmiKeyType KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength); 1259 1260 if (NULL == KvpKey) 1261 { 1262 return false; 1263 } 1264 1265 oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM, KeyLength); 1266 int32 err; 1267 1268 OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(FsiMemfrag, KvpKey);); 1269 if (err != OsclErrNone) 1270 { 1271 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1272 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Problem to set FSI")); 1273 } 1274 else 1275 { 1276 sendFsi = false; 1277 iCompactFSISettingSucceeded = true; 1278 } 1279 1280 alloc.deallocate((OsclAny*)(KvpKey)); 1281 1282 1283 } 1284 else 1285 { 1286 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1287 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Problem allocating Output FSI")); 1288 SetState(EPVMFNodeError); 1289 ReportErrorEvent(PVMFErrNoMemory); 1290 return false; // this is going to make everything go out of scope 1291 } 1292 } 1293 else 1294 { 1295 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1296 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Problem allocating Output FSI")); 1297 return false; // this is going to make everything go out of scope 1298 } 1299 1300 1301 } 1302 1303 //Try querying the buffer allocator KVP for output buffer allocation outside of the node 1304 PvmiKvp* kvp = NULL; 1305 int numKvp = 0; 1306 PvmiKeyType aIdentifier = (PvmiKeyType)PVMF_BUFFER_ALLOCATOR_KEY; 1307 int32 err, err1; 1308 ipExternalOutputBufferAllocatorInterface = NULL; 1309 1310 OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiGetBufferAllocatorSpecificInfoSync(aIdentifier, kvp, numKvp);); 1311 1312 if ((err == OsclErrNone) && (NULL != kvp)) 1313 { 1314 ipExternalOutputBufferAllocatorInterface = (PVInterface*) kvp->value.key_specific_value; 1315 1316 if (ipExternalOutputBufferAllocatorInterface) 1317 { 1318 PVInterface* pTempPVInterfacePtr = NULL; 1319 1320 OSCL_TRY(err, ipExternalOutputBufferAllocatorInterface->queryInterface(PVMFFixedSizeBufferAllocUUID, pTempPVInterfacePtr);); 1321 1322 OSCL_TRY(err1, ((PVMFOMXDecPort*)iOutPort)->releaseParametersSync(kvp, numKvp);); 1323 if (err1 != OsclErrNone) 1324 { 1325 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1326 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Unable to Release Parameters")); 1327 } 1328 1329 if ((err == OsclErrNone) && (NULL != pTempPVInterfacePtr)) 1330 { 1331 ipFixedSizeBufferAlloc = OSCL_STATIC_CAST(PVMFFixedSizeBufferAlloc*, pTempPVInterfacePtr); 1332 1333 uint32 iNumBuffers, iBufferSize; 1334 1335 iNumBuffers = ipFixedSizeBufferAlloc->getNumBuffers(); 1336 iBufferSize = ipFixedSizeBufferAlloc->getBufferSize(); 1337 1338 if ((iNumBuffers < iParamPort.nBufferCountMin) || (iBufferSize < iOMXComponentOutputBufferSize)) 1339 { 1340 ipExternalOutputBufferAllocatorInterface->removeRef(); 1341 ipExternalOutputBufferAllocatorInterface = NULL; 1342 } 1343 else 1344 { 1345 iNumOutputBuffers = iNumBuffers; 1346 iOMXComponentOutputBufferSize = iBufferSize; 1347 1348 } 1349 1350 } 1351 else 1352 { 1353 ipExternalOutputBufferAllocatorInterface->removeRef(); 1354 ipExternalOutputBufferAllocatorInterface = NULL; 1355 1356 } 1357 } 1358 } 1359 1360 1361 iParamPort.nBufferCountActual = iNumOutputBuffers; 1362 1363 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1364 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Outport buffers %d,size %d", iNumOutputBuffers, iOMXComponentOutputBufferSize)); 1365 1366 CONFIG_SIZE_AND_VERSION(iParamPort); 1367 iParamPort.nPortIndex = iOutputPortIndex; 1368 // finalize setting output port parameters 1369 Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort); 1370 if (Err != OMX_ErrorNone) 1371 { 1372 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1373 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting parameters in output port %d ", iOutputPortIndex)); 1374 return false; 1375 } 1376 1377 //Set input audio format 1378 //This is need it since a single component could handle differents roles 1379 1380 // Init to desire format 1381 PVMFFormatType Format = PVMF_MIME_FORMAT_UNKNOWN; 1382 if (iInPort != NULL) 1383 { 1384 Format = ((PVMFOMXDecPort*)iInPort)->iFormat; 1385 } 1386 if (Format == PVMF_MIME_MPEG4_AUDIO || 1387 Format == PVMF_MIME_3640 || 1388 Format == PVMF_MIME_LATM || 1389 Format == PVMF_MIME_ADIF || 1390 Format == PVMF_MIME_ASF_MPEG4_AUDIO || 1391 Format == PVMF_MIME_AAC_SIZEHDR) 1392 { 1393 iOMXAudioCompressionFormat = OMX_AUDIO_CodingAAC; 1394 } 1395 else if (Format == PVMF_MIME_AMR_IF2 || 1396 Format == PVMF_MIME_AMR_IETF || 1397 Format == PVMF_MIME_AMR || 1398 Format == PVMF_MIME_AMRWB_IETF || 1399 Format == PVMF_MIME_AMRWB) 1400 { 1401 iOMXAudioCompressionFormat = OMX_AUDIO_CodingAMR; 1402 } 1403 else if (Format == PVMF_MIME_MP3) 1404 { 1405 iOMXAudioCompressionFormat = OMX_AUDIO_CodingMP3; 1406 } 1407 else if (Format == PVMF_MIME_WMA) 1408 { 1409 iOMXAudioCompressionFormat = OMX_AUDIO_CodingWMA; 1410 } 1411 else 1412 { 1413 // Illegal codec specified. 1414 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1415 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting audio compression format")); 1416 return false; 1417 } 1418 1419 1420 OMX_AUDIO_PARAM_PORTFORMATTYPE AudioPortFormat; 1421 CONFIG_SIZE_AND_VERSION(AudioPortFormat); 1422 AudioPortFormat.nPortIndex = iInputPortIndex; 1423 1424 // Search the proper format index and set it. 1425 // Since we already know that the component has the role we need, search until finding the proper nIndex 1426 // if component does not find the format will return OMX_ErrorNoMore 1427 1428 for (ii = 0;; ii++) 1429 { 1430 AudioPortFormat.nIndex = ii; 1431 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPortFormat, &AudioPortFormat); 1432 if (Err != OMX_ErrorNone) 1433 { 1434 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1435 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting audio compression format")); 1436 return false; 1437 } 1438 if (iOMXAudioCompressionFormat == AudioPortFormat.eEncoding) 1439 { 1440 break; 1441 } 1442 } 1443 // Now set the format to confirm parameters 1444 Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamAudioPortFormat, &AudioPortFormat); 1445 if (Err != OMX_ErrorNone) 1446 { 1447 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1448 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting audio compression format")); 1449 return false; 1450 } 1451 1452 1453 return true; 1454 } 1455 1456 bool PVMFOMXAudioDecNode::GetSetCodecSpecificInfo() 1457 { 1458 1459 // for AAC, need to let the decoder know about the type of AAC format. Need to get the frame length 1460 // need to get the parameters 1461 OMX_PTR CodecProfilePtr = NULL; 1462 OMX_INDEXTYPE CodecProfileIndx = OMX_IndexAudioStartUnused; 1463 OMX_AUDIO_PARAM_AACPROFILETYPE Audio_Aac_Param; 1464 OMX_AUDIO_PARAM_AMRTYPE Audio_Amr_Param; 1465 OMX_AUDIO_PARAM_MP3TYPE Audio_Mp3_Param; 1466 OMX_AUDIO_PARAM_WMATYPE Audio_Wma_Param; 1467 OMX_ERRORTYPE Err = OMX_ErrorNone; 1468 PVMFFormatType Format = PVMF_MIME_FORMAT_UNKNOWN; 1469 1470 // determine the proper index and structure (based on codec type) 1471 1472 if (iInPort != NULL) 1473 { 1474 Format = ((PVMFOMXDecPort*)iInPort)->iFormat; 1475 } 1476 if (Format == PVMF_MIME_MPEG4_AUDIO || 1477 Format == PVMF_MIME_3640 || 1478 Format == PVMF_MIME_LATM || 1479 Format == PVMF_MIME_ADIF || 1480 Format == PVMF_MIME_ASF_MPEG4_AUDIO || 1481 Format == PVMF_MIME_AAC_SIZEHDR) // for testing 1482 { 1483 // AAC 1484 1485 CodecProfilePtr = (OMX_PTR) & Audio_Aac_Param; 1486 CodecProfileIndx = OMX_IndexParamAudioAac; 1487 Audio_Aac_Param.nPortIndex = iInputPortIndex; 1488 1489 CONFIG_SIZE_AND_VERSION(Audio_Aac_Param); 1490 } 1491 // AMR 1492 else if (Format == PVMF_MIME_AMR_IF2 || 1493 Format == PVMF_MIME_AMR_IETF || 1494 Format == PVMF_MIME_AMR || 1495 Format == PVMF_MIME_AMRWB_IETF || 1496 Format == PVMF_MIME_AMRWB) 1497 { 1498 CodecProfilePtr = (OMX_PTR) & Audio_Amr_Param; 1499 CodecProfileIndx = OMX_IndexParamAudioAmr; 1500 Audio_Amr_Param.nPortIndex = iInputPortIndex; 1501 1502 CONFIG_SIZE_AND_VERSION(Audio_Amr_Param); 1503 } 1504 else if (Format == PVMF_MIME_MP3) 1505 { 1506 CodecProfilePtr = (OMX_PTR) & Audio_Mp3_Param; 1507 CodecProfileIndx = OMX_IndexParamAudioMp3; 1508 Audio_Mp3_Param.nPortIndex = iInputPortIndex; 1509 1510 CONFIG_SIZE_AND_VERSION(Audio_Mp3_Param); 1511 } 1512 else if (Format == PVMF_MIME_WMA) 1513 { 1514 CodecProfilePtr = (OMX_PTR) & Audio_Wma_Param; 1515 CodecProfileIndx = OMX_IndexParamAudioWma; 1516 Audio_Wma_Param.nPortIndex = iInputPortIndex; 1517 1518 CONFIG_SIZE_AND_VERSION(Audio_Wma_Param); 1519 } 1520 1521 // first get parameters: 1522 Err = OMX_GetParameter(iOMXDecoder, CodecProfileIndx, CodecProfilePtr); 1523 if (Err != OMX_ErrorNone) 1524 { 1525 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1526 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem getting codec profile parameter on input port %d ", iInputPortIndex)); 1527 return false; 1528 } 1529 // Set the stream format 1530 1531 1532 // AAC FORMATS: 1533 if (Format == PVMF_MIME_MPEG4_AUDIO) 1534 { 1535 Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 1536 } 1537 else if (Format == PVMF_MIME_3640) 1538 { 1539 Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 1540 } 1541 else if (Format == PVMF_MIME_LATM) 1542 { 1543 Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LATM; 1544 } 1545 else if (Format == PVMF_MIME_ADIF) 1546 { 1547 Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF; 1548 } 1549 else if (Format == PVMF_MIME_ASF_MPEG4_AUDIO) 1550 { 1551 Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 1552 } 1553 else if (Format == PVMF_MIME_AAC_SIZEHDR) // for testing 1554 { 1555 Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; 1556 } 1557 // AMR FORMATS 1558 else if (Format == PVMF_MIME_AMR_IF2) 1559 { 1560 Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatIF2; 1561 Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; // we don't know the bitrate yet, but for init 1562 // purposes, we'll set this to any NarrowBand bitrate 1563 // to indicate NB vs WB 1564 } 1565 // File format 1566 // NB 1567 else if (Format == PVMF_MIME_AMR_IETF) 1568 { 1569 Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1570 Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; // we don't know the bitrate yet, but for init 1571 // purposes, we'll set this to any NarrowBand bitrate 1572 // to indicate NB vs WB 1573 } 1574 // WB 1575 else if (Format == PVMF_MIME_AMRWB_IETF) 1576 { 1577 Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; 1578 Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0; // we don't know the bitrate yet, but for init 1579 // purposes, we'll set this to any WideBand bitrate 1580 // to indicate NB vs WB 1581 } 1582 // streaming with Table of Contents 1583 else if (Format == PVMF_MIME_AMR) 1584 { 1585 Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatRTPPayload; 1586 Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; // we don't know the bitrate yet, but for init 1587 // purposes, we'll set this to any WideBand bitrate 1588 // to indicate NB vs WB 1589 } 1590 else if (Format == PVMF_MIME_AMRWB) 1591 { 1592 Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatRTPPayload; 1593 Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0; // we don't know the bitrate yet, but for init 1594 // purposes, we'll set this to any WideBand bitrate 1595 // to indicate NB vs WB 1596 } 1597 else if (Format == PVMF_MIME_MP3) 1598 { 1599 // nothing to do here 1600 } 1601 else if (Format == PVMF_MIME_WMA) 1602 { 1603 Audio_Wma_Param.eFormat = OMX_AUDIO_WMAFormatUnused; // set this initially 1604 } 1605 else 1606 { 1607 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1608 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Unknown format in input port negotiation ")); 1609 return false; 1610 } 1611 1612 // set parameters to inform teh component of the stream type 1613 Err = OMX_SetParameter(iOMXDecoder, CodecProfileIndx, CodecProfilePtr); 1614 if (Err != OMX_ErrorNone) 1615 { 1616 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1617 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting codec profile parameter on input port %d ", iInputPortIndex)); 1618 return false; 1619 } 1620 1621 1622 // read the output frame size 1623 // AAC 1624 if (Format == PVMF_MIME_MPEG4_AUDIO || 1625 Format == PVMF_MIME_3640 || 1626 Format == PVMF_MIME_LATM || 1627 Format == PVMF_MIME_ADIF || 1628 Format == PVMF_MIME_ASF_MPEG4_AUDIO || 1629 Format == PVMF_MIME_AAC_SIZEHDR) // for testing 1630 { 1631 // AAC frame size is 1024 samples or 2048 samples for AAC-HE 1632 iSamplesPerFrame = Audio_Aac_Param.nFrameLength; 1633 } 1634 // AMR 1635 else if (Format == PVMF_MIME_AMR_IF2 || 1636 Format == PVMF_MIME_AMR_IETF || 1637 Format == PVMF_MIME_AMR) 1638 { 1639 // AMR NB has fs=8khz Mono and the frame is 20ms long, i.e. there is 160 samples per frame 1640 iSamplesPerFrame = PVOMXAUDIODEC_AMRNB_SAMPLES_PER_FRAME; 1641 } 1642 else if (Format == PVMF_MIME_AMRWB_IETF || 1643 Format == PVMF_MIME_AMRWB) 1644 { 1645 // AMR WB has fs=16khz Mono and the frame is 20ms long, i.e. there is 320 samples per frame 1646 iSamplesPerFrame = PVOMXAUDIODEC_AMRWB_SAMPLES_PER_FRAME; 1647 } 1648 else if (Format == PVMF_MIME_MP3) 1649 { 1650 // frame size is either 576 or 1152 samples per frame. However, this information cannot be 1651 // obtained through OMX MP3 Params. Assume that it's 1152 1652 iSamplesPerFrame = PVOMXAUDIODEC_MP3_DEFAULT_SAMPLES_PER_FRAME; 1653 } 1654 else if (Format == PVMF_MIME_WMA) 1655 { 1656 // output frame size is unknown in WMA. However, the PV-WMA decoder can control the number 1657 // of samples it places in an output buffer, so we can create an output buffer of arbitrary size 1658 // and let the decoder control how it is filled 1659 iSamplesPerFrame = 0; // unknown 1660 } 1661 1662 // iSamplesPerFrame depends on the codec. 1663 // for AAC: iSamplesPerFrame = 1024 1664 // for AAC+: iSamplesPerFrame = 2048 1665 // for AMRNB: iSamplesPerFrame = 160 1666 // for AMRWB: iSamplesPerFrame = 320 1667 // for MP3: iSamplesPerFrame = unknown, but either 1152 or 576 (we pick 1152 as default) 1668 // for WMA: unknown (iSamplesPerFrame is set to 0) 1669 1670 // GET the output buffer params and sizes 1671 OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param; 1672 Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params 1673 1674 CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param); 1675 1676 1677 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param); 1678 if (Err != OMX_ErrorNone) 1679 { 1680 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1681 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating PCM parameters with output port %d ", iOutputPortIndex)); 1682 return false; 1683 } 1684 1685 1686 // these are some initial default values that may change 1687 iPCMSamplingRate = Audio_Pcm_Param.nSamplingRate; // can be set to 0 (if unknown) 1688 1689 if (iPCMSamplingRate == 0) // use default sampling rate (i.e. 48000) 1690 iPCMSamplingRate = PVOMXAUDIODEC_DEFAULT_SAMPLINGRATE; 1691 1692 iNumberOfAudioChannels = Audio_Pcm_Param.nChannels; // should be 1 or 2 1693 if (iNumberOfAudioChannels != 1 && iNumberOfAudioChannels != 2) 1694 return false; 1695 1696 1697 if ((iSamplesPerFrame != 0) && ((iSamplesPerFrame * 1000) > iPCMSamplingRate)) 1698 // if this iSamplesPerFrame is known and is large enough to ensure that the iMilliSecPerFrame calculation 1699 // below won't be set to 0. 1700 { 1701 // CALCULATE NumBytes per frame, Msec per frame, etc. 1702 1703 iNumBytesPerFrame = 2 * iSamplesPerFrame * iNumberOfAudioChannels; 1704 iMilliSecPerFrame = (iSamplesPerFrame * 1000) / iPCMSamplingRate; 1705 // Determine the size of each PCM output buffer. Size would be big enough to hold certain time amount of PCM data 1706 uint32 numframes = PVOMXAUDIODEC_DEFAULT_OUTPUTPCM_TIME / iMilliSecPerFrame; 1707 1708 if (PVOMXAUDIODEC_DEFAULT_OUTPUTPCM_TIME % iMilliSecPerFrame) 1709 { 1710 // If there is a remainder, include one more frame 1711 ++numframes; 1712 } 1713 // set the output buffer size accordingly: 1714 iOMXComponentOutputBufferSize = numframes * iNumBytesPerFrame; 1715 } 1716 else 1717 iOMXComponentOutputBufferSize = (2 * iNumberOfAudioChannels * PVOMXAUDIODEC_DEFAULT_OUTPUTPCM_TIME * iPCMSamplingRate) / 1000; // assuming 16 bits per sample 1718 1719 //Port 1 for output port 1720 iParamPort.nPortIndex = iOutputPortIndex; 1721 CONFIG_SIZE_AND_VERSION(iParamPort); 1722 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort); 1723 if (Err != OMX_ErrorNone) 1724 { 1725 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1726 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with output port %d ", iOutputPortIndex)); 1727 return false; 1728 } 1729 1730 if (iOMXComponentOutputBufferSize < iParamPort.nBufferSize) 1731 { 1732 // the OMX spec says that nBuffersize is a read only field, but the client is allowed to allocate 1733 // a buffer size larger than nBufferSize. 1734 iOMXComponentOutputBufferSize = iParamPort.nBufferSize; 1735 } 1736 1737 return true; 1738 1739 } 1740 1741 ///////////////////////////////////////////////////////////////////////////// 1742 bool PVMFOMXAudioDecNode::InitDecoder(PVMFSharedMediaDataPtr& DataIn) 1743 { 1744 1745 OsclRefCounterMemFrag DataFrag; 1746 OsclRefCounterMemFrag refCtrMemFragOut; 1747 uint8* initbuffer = NULL; 1748 uint32 initbufsize = 0; 1749 1750 1751 // NOTE: the component may not start decoding without providing the Output buffer to it, 1752 // here, we're sending input/config buffers. 1753 // Then, we'll go to ReadyToDecode state and send output as well 1754 1755 if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM) 1756 { 1757 // must have the LATM config buffer and size already present 1758 if (iLATMConfigBuffer != NULL) 1759 { 1760 initbuffer = iLATMConfigBuffer; 1761 initbufsize = iLATMConfigBufferSize; 1762 } 1763 else 1764 { 1765 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1766 (0, "PVMFOMXAudioDecNode::InitDecoder() Error - LATM config buffer not present")); 1767 return false; 1768 } 1769 } 1770 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO || 1771 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640 || 1772 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF || 1773 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO || 1774 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AAC_SIZEHDR) // for testing 1775 { 1776 // get format specific info and send it as config data: 1777 DataIn->getFormatSpecificInfo(DataFrag); 1778 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1779 (0, "PVMFOMXAudioDecNode::InitDecoder() VOL header (Size=%d)", DataFrag.getMemFragSize())); 1780 1781 //get pointer to the data fragment 1782 initbuffer = (uint8 *) DataFrag.getMemFragPtr(); 1783 initbufsize = (int32) DataFrag.getMemFragSize(); 1784 1785 } // in some cases, initbufsize may be 0, and initbuf= NULL. Config is done after 1st frame of data 1786 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2 || 1787 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF || 1788 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR || 1789 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF || 1790 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB || 1791 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3) 1792 { 1793 initbuffer = NULL; // no special config header. Need to decode 1 frame 1794 initbufsize = 0; 1795 } 1796 1797 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA) 1798 { 1799 // in case of WMA, get config parameters from the port 1800 initbuffer = ((PVMFOMXDecPort*)iInPort)->getTrackConfig(); 1801 initbufsize = (int32)((PVMFOMXDecPort*)iInPort)->getTrackConfigSize(); 1802 1803 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1804 (0, "PVMFOMXAudioDecNode::InitDecoder() for WMA Decoder. Initialization data Size %d.", initbufsize)); 1805 } 1806 1807 1808 if (initbufsize > 0) 1809 { 1810 1811 1812 if (!SendConfigBufferToOMXComponent(initbuffer, initbufsize)) 1813 { 1814 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 1815 (0, "PVMFOMXAudioDecNode::InitDecoder() Error in processing config buffer")); 1816 return false; 1817 } 1818 } 1819 1820 1821 1822 1823 return true; 1824 } 1825 1826 1827 1828 ///////////////////////////////////////////////////////////////////////////// 1829 ////////////////////// CALLBACK PROCESSING FOR EVENT HANDLER 1830 ///////////////////////////////////////////////////////////////////////////// 1831 OMX_ERRORTYPE PVMFOMXAudioDecNode::EventHandlerProcessing(OMX_OUT OMX_HANDLETYPE aComponent, 1832 OMX_OUT OMX_PTR aAppData, 1833 OMX_OUT OMX_EVENTTYPE aEvent, 1834 OMX_OUT OMX_U32 aData1, 1835 OMX_OUT OMX_U32 aData2, 1836 OMX_OUT OMX_PTR aEventData) 1837 { 1838 1839 OSCL_UNUSED_ARG(aComponent); 1840 OSCL_UNUSED_ARG(aAppData); 1841 OSCL_UNUSED_ARG(aEventData); 1842 1843 1844 switch (aEvent) 1845 { 1846 case OMX_EventCmdComplete: 1847 { 1848 1849 switch (aData1) 1850 { 1851 case OMX_CommandStateSet: 1852 { 1853 HandleComponentStateChange(aData2); 1854 break; 1855 } 1856 case OMX_CommandFlush: 1857 { 1858 // flush can be sent as part of repositioning or as part of port reconfig 1859 1860 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1861 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_CommandFlush - completed on port %d", aData2)); 1862 1863 if (iIsRepositioningRequestSentToComponent) 1864 { 1865 if (aData2 == iOutputPortIndex) 1866 { 1867 iIsOutputPortFlushed = true; 1868 } 1869 else if (aData2 == iInputPortIndex) 1870 { 1871 iIsInputPortFlushed = true; 1872 } 1873 1874 if (iIsOutputPortFlushed && iIsInputPortFlushed) 1875 { 1876 iIsRepositionDoneReceivedFromComponent = true; 1877 } 1878 } 1879 1880 if (IsAdded()) 1881 RunIfNotReady(); 1882 1883 } 1884 1885 break; 1886 1887 case OMX_CommandPortDisable: 1888 { 1889 // if port disable command is done, we can re-allocate the buffers and re-enable the port 1890 1891 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_PortReEnable; 1892 iPortIndexForDynamicReconfig = aData2; 1893 1894 RunIfNotReady(); 1895 break; 1896 } 1897 case OMX_CommandPortEnable: 1898 // port enable command is done. Check if the other port also reported change. 1899 // If not, we can start data flow. Otherwise, must start dynamic reconfig procedure for 1900 // the other port as well. 1901 { 1902 if (iSecondPortReportedChange) 1903 { 1904 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1905 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_CommandPortEnable - completed on port %d, dynamic reconfiguration needed on port %d", aData2, iSecondPortToReconfig)); 1906 1907 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_PortReconfig; 1908 iPortIndexForDynamicReconfig = iSecondPortToReconfig; 1909 iSecondPortReportedChange = false; 1910 } 1911 else 1912 { 1913 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1914 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_CommandPortEnable - completed on port %d, resuming normal data flow", aData2)); 1915 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode; 1916 iDynamicReconfigInProgress = false; 1917 // in case pause or stop command was sent to component 1918 // change processing state (because the node might otherwise 1919 // start sending buffers to component before pause/stop is processed) 1920 if (iPauseCommandWasSentToComponent) 1921 { 1922 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Pausing; 1923 } 1924 if (iStopCommandWasSentToComponent) 1925 { 1926 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_Stopping; 1927 } 1928 } 1929 RunIfNotReady(); 1930 break; 1931 } 1932 1933 case OMX_CommandMarkBuffer: 1934 // nothing to do here yet; 1935 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1936 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_CommandMarkBuffer - completed - no action taken")); 1937 1938 break; 1939 1940 default: 1941 { 1942 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1943 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: Unsupported event")); 1944 break; 1945 } 1946 }//end of switch (aData1) 1947 1948 break; 1949 }//end of case OMX_EventCmdComplete 1950 1951 case OMX_EventError: 1952 { 1953 LOGE("Ln %d OMX_EventError nData1 %d nData2 %d", __LINE__, aData1, aData2); 1954 if (aData1 == (OMX_U32) OMX_ErrorStreamCorrupt) 1955 { 1956 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1957 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventError - Bitstream corrupt error")); 1958 // Errors from corrupt bitstream are reported as info events 1959 ReportInfoEvent(PVMFInfoProcessingFailure, NULL); 1960 1961 } 1962 else if (aData1 == (OMX_U32) OMX_ErrorInvalidState) 1963 { 1964 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1965 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventError - OMX_ErrorInvalidState")); 1966 HandleComponentStateChange(OMX_StateInvalid); 1967 } 1968 else 1969 { 1970 1971 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1972 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventError")); 1973 // for now, any error from the component will be reported as error 1974 ReportErrorEvent(PVMFErrProcessing, NULL, NULL); 1975 SetState(EPVMFNodeError); 1976 } 1977 break; 1978 1979 1980 1981 } 1982 1983 case OMX_EventBufferFlag: 1984 { 1985 // the component is reporting it encountered end of stream flag 1986 // we'll send EOS when we receive the last buffer marked with eos 1987 1988 1989 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1990 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventBufferFlag (EOS) flag returned from OMX component")); 1991 1992 RunIfNotReady(); 1993 break; 1994 }//end of case OMX_EventBufferFlag 1995 1996 case OMX_EventMark: 1997 { 1998 1999 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2000 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventMark returned from OMX component - no action taken")); 2001 2002 RunIfNotReady(); 2003 break; 2004 }//end of case OMX_EventMark 2005 2006 case OMX_EventPortSettingsChanged: 2007 { 2008 2009 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2010 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventPortSettingsChanged returned from OMX component")); 2011 2012 // first check if dynamic reconfiguration is already in progress, 2013 // if so, wait until this is completed, and then initiate the 2nd reconfiguration 2014 if (iDynamicReconfigInProgress) 2015 { 2016 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2017 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventPortSettingsChanged returned for port %d, dynamic reconfig already in progress", aData1)); 2018 2019 iSecondPortToReconfig = aData1; 2020 iSecondPortReportedChange = true; 2021 2022 // check the audio sampling rate and fs right away in case of output port 2023 // is this output port? 2024 if (iSecondPortToReconfig == iOutputPortIndex) 2025 { 2026 2027 OMX_ERRORTYPE Err; 2028 // GET the output buffer params and sizes 2029 OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param; 2030 Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params 2031 CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param); 2032 2033 2034 2035 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param); 2036 if (Err != OMX_ErrorNone) 2037 { 2038 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2039 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing() PortSettingsChanged -> Cannot get component output parameters")); 2040 2041 SetState(EPVMFNodeError); 2042 ReportErrorEvent(PVMFErrResource); 2043 } 2044 2045 iPCMSamplingRate = Audio_Pcm_Param.nSamplingRate; // can be set to 0 (if unknown) 2046 2047 if (iPCMSamplingRate == 0) // use default sampling rate (i.e. 48000) 2048 iPCMSamplingRate = PVOMXAUDIODEC_DEFAULT_SAMPLINGRATE; 2049 2050 iNumberOfAudioChannels = Audio_Pcm_Param.nChannels; // should be 1 or 2 2051 if (iNumberOfAudioChannels != 1 && iNumberOfAudioChannels != 2) 2052 { 2053 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2054 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing() PortSettingsChanged -> Output parameters num channels = %d", iNumberOfAudioChannels)); 2055 2056 SetState(EPVMFNodeError); 2057 ReportErrorEvent(PVMFErrResource); 2058 2059 } 2060 } 2061 } 2062 else 2063 { 2064 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2065 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventPortSettingsChanged returned for port %d", aData1)); 2066 2067 iProcessingState = EPVMFOMXBaseDecNodeProcessingState_PortReconfig; 2068 iPortIndexForDynamicReconfig = aData1; 2069 // start "discarding" data right away, don't wait 2070 // check the audio sampling rate and fs right away in case of output port 2071 // is this output port? 2072 if (iPortIndexForDynamicReconfig == iOutputPortIndex) 2073 { 2074 2075 OMX_ERRORTYPE Err; 2076 // GET the output buffer params and sizes 2077 OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param; 2078 Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params 2079 2080 CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param); 2081 2082 2083 Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param); 2084 if (Err != OMX_ErrorNone) 2085 { 2086 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2087 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing() PortSettingsChanged -> Cannot get component output parameters")); 2088 2089 SetState(EPVMFNodeError); 2090 ReportErrorEvent(PVMFErrResource); 2091 2092 } 2093 2094 iPCMSamplingRate = Audio_Pcm_Param.nSamplingRate; // can be set to 0 (if unknown) 2095 2096 if (iPCMSamplingRate == 0) // use default sampling rate (i.e. 48000) 2097 iPCMSamplingRate = PVOMXAUDIODEC_DEFAULT_SAMPLINGRATE; 2098 2099 iNumberOfAudioChannels = Audio_Pcm_Param.nChannels; // should be 1 or 2 2100 if (iNumberOfAudioChannels != 1 && iNumberOfAudioChannels != 2) 2101 { 2102 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2103 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing() PortSettingsChanged -> Output parameters num channels = %d", iNumberOfAudioChannels)); 2104 2105 SetState(EPVMFNodeError); 2106 ReportErrorEvent(PVMFErrResource); 2107 } 2108 } 2109 iDynamicReconfigInProgress = true; 2110 } 2111 2112 RunIfNotReady(); 2113 break; 2114 }//end of case OMX_PortSettingsChanged 2115 2116 case OMX_EventResourcesAcquired: //not supported 2117 { 2118 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2119 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: OMX_EventResourcesAcquired returned from OMX component - no action taken")); 2120 2121 RunIfNotReady(); 2122 2123 break; 2124 } 2125 2126 default: 2127 { 2128 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2129 (0, "PVMFOMXAudioDecNode::EventHandlerProcessing: Unknown Event returned from OMX component - no action taken")); 2130 2131 break; 2132 } 2133 2134 }//end of switch (eEvent) 2135 2136 2137 2138 return OMX_ErrorNone; 2139 } 2140 2141 2142 2143 2144 //////////////////////////////////////////////////////////////////////////////////////////////// 2145 ///////////////////////////// Put output buffer in outgoing queue ////////////////////////////// 2146 //////////////////////////////////////////////////////////////////////////////////////////////// 2147 bool PVMFOMXAudioDecNode::QueueOutputBuffer(OsclSharedPtr<PVMFMediaDataImpl> &mediadataimplout, uint32 aDataLen) 2148 { 2149 2150 bool status = true; 2151 PVMFSharedMediaDataPtr mediaDataOut; 2152 int32 leavecode = OsclErrNone; 2153 2154 // NOTE: ASSUMPTION IS THAT OUTGOING QUEUE IS BIG ENOUGH TO QUEUE ALL THE OUTPUT BUFFERS 2155 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2156 (0, "PVMFOMXAudioDecNode::QueueOutputFrame: In")); 2157 2158 // First check if we can put outgoing msg. into the queue 2159 if (iOutPort->IsOutgoingQueueBusy()) 2160 { 2161 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 2162 (0, "PVMFOMXAudioDecNode::QueueOutputFrame() OutgoingQueue is busy")); 2163 return false; 2164 } 2165 2166 OSCL_TRY(leavecode, 2167 mediaDataOut = PVMFMediaData::createMediaData(mediadataimplout, iMediaDataMemPool);); 2168 if (OsclErrNone == leavecode) 2169 { 2170 2171 // Update the filled length of the fragment 2172 mediaDataOut->setMediaFragFilledLen(0, aDataLen); 2173 2174 // Set timestamp 2175 mediaDataOut->setTimestamp(iOutTimeStamp); 2176 2177 // Set sequence number 2178 mediaDataOut->setSeqNum(iSeqNum++); 2179 // set stream id 2180 mediaDataOut->setStreamID(iStreamID); 2181 2182 2183 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iDataPathLogger, PVLOGMSG_INFO, (0, ":PVMFOMXAudioDecNode::QueueOutputFrame(): - SeqNum=%d, TS=%d", iSeqNum, iOutTimeStamp)); 2184 int fsiErrorCode = 0; 2185 2186 // Check if Fsi configuration need to be sent 2187 if (sendFsi && !iCompactFSISettingSucceeded) 2188 { 2189 2190 OsclRefCounterMemFrag FsiMemfrag; 2191 2192 OSCL_TRY(fsiErrorCode, FsiMemfrag = iFsiFragmentAlloc.get();); 2193 2194 OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 2195 (0, "PVMFOMXAudioDecNode::RemoveOutputFrame() Failed to allocate memory for FSI"))); 2196 2197 if (fsiErrorCode == 0) 2198 { 2199 2200 channelSampleInfo* pcminfo = (channelSampleInfo*) FsiMemfrag.getMemFragPtr(); 2201 if (pcminfo != NULL) 2202 { 2203 OSCL_ASSERT(pcminfo != NULL); 2204 2205 pcminfo->samplingRate = iPCMSamplingRate; 2206 pcminfo->desiredChannels = iNumberOfAudioChannels; 2207 2208 mediaDataOut->setFormatSpecificInfo(FsiMemfrag); 2209 2210 2211 OsclMemAllocator alloc; 2212 int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY) + 1; 2213 PvmiKeyType KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength); 2214 2215 if (NULL == KvpKey) 2216 { 2217 SetState(EPVMFNodeError); 2218 ReportErrorEvent(PVMFErrNoMemory); 2219 return false; 2220 } 2221 2222 oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY, KeyLength); 2223 int32 err; 2224 2225 OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(FsiMemfrag, KvpKey);); 2226 if (err != OsclErrNone) 2227 { 2228 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 2229 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Problem to set FSI")); 2230 SetState(EPVMFNodeError); 2231 ReportErrorEvent(PVMFErrNoMemory); 2232 return false; // this is going to make everyth go out of scope 2233 } 2234 2235 2236 alloc.deallocate((OsclAny*)(KvpKey)); 2237 2238 2239 2240 } 2241 else 2242 { 2243 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 2244 (0, "PVMFOMXAudioDecNode::QueueOutputFrame - Problem allocating Output FSI")); 2245 SetState(EPVMFNodeError); 2246 ReportErrorEvent(PVMFErrNoMemory); 2247 return false; // this is going to make everything go out of scope 2248 } 2249 } 2250 else 2251 { 2252 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 2253 (0, "PVMFOMXAudioDecNode::QueueOutputFrame - Problem allocating Output FSI")); 2254 return false; // this is going to make everything go out of scope 2255 } 2256 2257 // Reset the flag 2258 sendFsi = false; 2259 } 2260 2261 if (fsiErrorCode == 0) 2262 { 2263 // Send frame to downstream node 2264 PVMFSharedMediaMsgPtr mediaMsgOut; 2265 convertToPVMFMediaMsg(mediaMsgOut, mediaDataOut); 2266 2267 if (iOutPort && (iOutPort->QueueOutgoingMsg(mediaMsgOut) == PVMFSuccess)) 2268 { 2269 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2270 (0, "PVMFOMXAudioDecNode::QueueOutputFrame(): Queued frame OK ")); 2271 2272 } 2273 else 2274 { 2275 // we should not get here because we always check for whether queue is busy or not 2276 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 2277 (0, "PVMFOMXAudioDecNode::QueueOutputFrame(): Send frame failed")); 2278 return false; 2279 } 2280 } 2281 2282 2283 }//end of if (OsclErrNone == leavecode) 2284 else 2285 { 2286 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 2287 (0, "PVMFOMXAudioDecNode::QueueOutputFrame() call PVMFMediaData::createMediaData is failed")); 2288 return false; 2289 } 2290 2291 return status; 2292 2293 } 2294 2295 ///////////////////////////////////////////////////////////////////////////// 2296 void PVMFOMXAudioDecNode::DoRequestPort(PVMFOMXBaseDecNodeCommand& aCmd) 2297 { 2298 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2299 (0, "PVMFOMXAudioDecNode::DoRequestPort() In")); 2300 //This node supports port request from any state 2301 2302 //retrieve port tag. 2303 int32 tag; 2304 OSCL_String* portconfig; 2305 2306 aCmd.PVMFOMXBaseDecNodeCommandBase::Parse(tag, portconfig); 2307 2308 PVMFPortInterface* port = NULL; 2309 int32 leavecode = OsclErrNone; 2310 //validate the tag... 2311 switch (tag) 2312 { 2313 case PVMF_OMX_DEC_NODE_PORT_TYPE_INPUT: 2314 if (iInPort) 2315 { 2316 CommandComplete(iInputCommands, aCmd, PVMFFailure); 2317 break; 2318 } 2319 OSCL_TRY(leavecode, iInPort = OSCL_NEW(PVMFOMXDecPort, ((int32)tag, this, (OMX_STRING)PVMF_OMX_AUDIO_DEC_INPUT_PORT_NAME));); 2320 if (leavecode || iInPort == NULL) 2321 { 2322 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 2323 (0, "PVMFOMXAudioDecNode::DoRequestPort: Error - Input port instantiation failed")); 2324 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 2325 return; 2326 } 2327 port = iInPort; 2328 break; 2329 2330 case PVMF_OMX_DEC_NODE_PORT_TYPE_OUTPUT: 2331 if (iOutPort) 2332 { 2333 CommandComplete(iInputCommands, aCmd, PVMFFailure); 2334 break; 2335 } 2336 OSCL_TRY(leavecode, iOutPort = OSCL_NEW(PVMFOMXDecPort, ((int32)tag, this, (OMX_STRING)PVMF_OMX_AUDIO_DEC_OUTPUT_PORT_NAME))); 2337 if (leavecode || iOutPort == NULL) 2338 { 2339 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 2340 (0, "PVMFOMXAudioDecNode::DoRequestPort: Error - Output port instantiation failed")); 2341 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 2342 return; 2343 } 2344 port = iOutPort; 2345 break; 2346 2347 default: 2348 //bad port tag 2349 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 2350 (0, "PVMFOMXAudioDecNode::DoRequestPort: Error - Invalid port tag")); 2351 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 2352 return; 2353 } 2354 2355 //Return the port pointer to the caller. 2356 CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port); 2357 } 2358 2359 ///////////////////////////////////////////////////////////////////////////// 2360 void PVMFOMXAudioDecNode::DoReleasePort(PVMFOMXBaseDecNodeCommand& aCmd) 2361 { 2362 PVMFPortInterface* temp; 2363 aCmd.PVMFOMXBaseDecNodeCommandBase::Parse(temp); 2364 2365 PVMFOMXDecPort* port = (PVMFOMXDecPort*)temp; 2366 2367 if (port != NULL && (port == iInPort || port == iOutPort)) 2368 { 2369 if (port == iInPort) 2370 { 2371 OSCL_DELETE(((PVMFOMXDecPort*)iInPort)); 2372 iInPort = NULL; 2373 } 2374 else 2375 { 2376 OSCL_DELETE(((PVMFOMXDecPort*)iOutPort)); 2377 iOutPort = NULL; 2378 } 2379 //delete the port. 2380 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 2381 } 2382 else 2383 { 2384 //port not found. 2385 CommandComplete(iInputCommands, aCmd, PVMFFailure); 2386 } 2387 } 2388 2389 ///////////////////////////////////////////////////////////////////////////// 2390 PVMFStatus PVMFOMXAudioDecNode::DoGetNodeMetadataKey(PVMFOMXBaseDecNodeCommand& aCmd) 2391 { 2392 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2393 (0, "PVMFOMXAudioDecNode::DoGetNodeMetadataKey() In")); 2394 2395 PVMFMetadataList* keylistptr = NULL; 2396 uint32 starting_index; 2397 int32 max_entries; 2398 char* query_key; 2399 2400 aCmd.PVMFOMXBaseDecNodeCommand::Parse(keylistptr, starting_index, max_entries, query_key); 2401 2402 // Check parameters 2403 if (keylistptr == NULL) 2404 { 2405 // The list pointer is invalid 2406 return PVMFErrArgument; 2407 } 2408 2409 if ((starting_index > (iAvailableMetadataKeys.size() - 1)) || max_entries == 0) 2410 { 2411 // Invalid starting index and/or max entries 2412 return PVMFErrArgument; 2413 } 2414 2415 // Copy the requested keys 2416 uint32 num_entries = 0; 2417 int32 num_added = 0; 2418 int32 leavecode = OsclErrNone; 2419 for (uint32 lcv = 0; lcv < iAvailableMetadataKeys.size(); lcv++) 2420 { 2421 if (query_key == NULL) 2422 { 2423 // No query key so this key is counted 2424 ++num_entries; 2425 if (num_entries > starting_index) 2426 { 2427 // Past the starting index so copy the key 2428 leavecode = OsclErrNone; 2429 leavecode = PushKVPKey(iAvailableMetadataKeys[lcv], keylistptr); 2430 if (OsclErrNone != leavecode) 2431 { 2432 return PVMFErrNoMemory; 2433 } 2434 2435 num_added++; 2436 } 2437 } 2438 else 2439 { 2440 // Check if the key matche the query key 2441 if (pv_mime_strcmp(iAvailableMetadataKeys[lcv].get_cstr(), query_key) >= 0) 2442 { 2443 // This key is counted 2444 ++num_entries; 2445 if (num_entries > starting_index) 2446 { 2447 // Past the starting index so copy the key 2448 leavecode = OsclErrNone; 2449 leavecode = PushKVPKey(iAvailableMetadataKeys[lcv], keylistptr); 2450 if (OsclErrNone != leavecode) 2451 { 2452 return PVMFErrNoMemory; 2453 } 2454 2455 num_added++; 2456 } 2457 } 2458 } 2459 2460 // Check if max number of entries have been copied 2461 if (max_entries > 0 && num_added >= max_entries) 2462 { 2463 break; 2464 } 2465 } 2466 2467 return PVMFSuccess; 2468 } 2469 2470 ///////////////////////////////////////////////////////////////////////////// 2471 PVMFStatus PVMFOMXAudioDecNode::DoGetNodeMetadataValue(PVMFOMXBaseDecNodeCommand& aCmd) 2472 { 2473 PVMFMetadataList* keylistptr = NULL; 2474 Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL; 2475 uint32 starting_index; 2476 int32 max_entries; 2477 2478 aCmd.PVMFOMXBaseDecNodeCommand::Parse(keylistptr, valuelistptr, starting_index, max_entries); 2479 2480 // Check the parameters 2481 if (keylistptr == NULL || valuelistptr == NULL) 2482 { 2483 return PVMFErrArgument; 2484 } 2485 2486 uint32 numkeys = keylistptr->size(); 2487 2488 if (starting_index > (numkeys - 1) || numkeys <= 0 || max_entries == 0) 2489 { 2490 // Don't do anything 2491 return PVMFErrArgument; 2492 } 2493 2494 uint32 numvalentries = 0; 2495 int32 numentriesadded = 0; 2496 for (uint32 lcv = 0; lcv < numkeys; lcv++) 2497 { 2498 int32 leavecode = OsclErrNone; 2499 int32 leavecode1 = OsclErrNone; 2500 PvmiKvp KeyVal; 2501 KeyVal.key = NULL; 2502 uint32 KeyLen = 0; 2503 2504 if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY) == 0)) 2505 { 2506 // PCM output channels 2507 if (iNumberOfAudioChannels > 0) 2508 { 2509 // Increment the counter for the number of values found so far 2510 ++numvalentries; 2511 2512 // Create a value entry if past the starting index 2513 if (numvalentries > starting_index) 2514 { 2515 KeyLen = oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY) + 1; // for "codec-info/audio/channels;" 2516 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 2517 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator 2518 2519 // Allocate memory for the string 2520 leavecode = OsclErrNone; 2521 KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen); 2522 if (OsclErrNone == leavecode) 2523 { 2524 // Copy the key string 2525 oscl_strncpy(KeyVal.key, PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY, oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY) + 1); 2526 oscl_strncat(KeyVal.key, PVOMXAUDIODECMETADATA_SEMICOLON, oscl_strlen(PVOMXAUDIODECMETADATA_SEMICOLON)); 2527 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 2528 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR)); 2529 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 2530 // Copy the value 2531 KeyVal.value.uint32_value = iNumberOfAudioChannels; 2532 // Set the length and capacity 2533 KeyVal.length = 1; 2534 KeyVal.capacity = 1; 2535 } 2536 else 2537 { 2538 // Memory allocation failed 2539 KeyVal.key = NULL; 2540 break; 2541 } 2542 } 2543 } 2544 } 2545 else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY) == 0) && 2546 (iPCMSamplingRate > 0)) 2547 { 2548 // PCM output sampling rate 2549 // Increment the counter for the number of values found so far 2550 ++numvalentries; 2551 2552 // Create a value entry if past the starting index 2553 if (numvalentries > starting_index) 2554 { 2555 KeyLen = oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY) + 1; // for "codec-info/audio/sample-rate;" 2556 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 2557 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator 2558 2559 // Allocate memory for the string 2560 leavecode = OsclErrNone; 2561 KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen); 2562 if (OsclErrNone == leavecode) 2563 { 2564 // Copy the key string 2565 oscl_strncpy(KeyVal.key, PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY, oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY) + 1); 2566 oscl_strncat(KeyVal.key, PVOMXAUDIODECMETADATA_SEMICOLON, oscl_strlen(PVOMXAUDIODECMETADATA_SEMICOLON)); 2567 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 2568 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR)); 2569 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 2570 // Copy the value 2571 KeyVal.value.uint32_value = iPCMSamplingRate; 2572 // Set the length and capacity 2573 KeyVal.length = 1; 2574 KeyVal.capacity = 1; 2575 } 2576 else 2577 { 2578 // Memory allocation failed 2579 KeyVal.key = NULL; 2580 break; 2581 } 2582 } 2583 } 2584 else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY) == 0) && 2585 iInPort != NULL) 2586 { 2587 // Format 2588 if ((((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM) || 2589 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO) || 2590 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640) || 2591 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF) || 2592 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AAC_SIZEHDR) || 2593 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2) || 2594 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF) || 2595 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR) || 2596 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF) || 2597 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB) || 2598 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3) || 2599 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA) 2600 2601 ) 2602 { 2603 // Increment the counter for the number of values found so far 2604 ++numvalentries; 2605 2606 // Create a value entry if past the starting index 2607 if (numvalentries > starting_index) 2608 { 2609 KeyLen = oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY) + 1; // for "codec-info/audio/format;" 2610 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype=" 2611 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR) + 1; // for "char*" and NULL terminator 2612 2613 uint32 valuelen = 0; 2614 if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM) 2615 { 2616 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_LATM)) + 1; // Value string plus one for NULL terminator 2617 } 2618 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO) 2619 { 2620 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_MPEG4_AUDIO)) + 1; // Value string plus one for NULL terminator 2621 } 2622 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640) 2623 { 2624 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_3640)) + 1; // Value string plus one for NULL terminator 2625 } 2626 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF) 2627 { 2628 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_ADIF)) + 1; 2629 } 2630 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2) 2631 { 2632 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMR_IF2)) + 1; 2633 } 2634 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF) 2635 { 2636 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMR_IETF)) + 1; 2637 } 2638 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR) 2639 { 2640 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMR)) + 1; 2641 } 2642 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF) 2643 { 2644 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMRWB_IETF)) + 1; 2645 } 2646 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB) 2647 { 2648 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMRWB)) + 1; 2649 } 2650 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3) 2651 { 2652 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_MP3)) + 1; 2653 } 2654 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA) 2655 { 2656 valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_WMA)) + 1; 2657 } 2658 else 2659 { 2660 // Should not enter here 2661 OSCL_ASSERT(false); 2662 valuelen = 1; 2663 } 2664 2665 // Allocate memory for the strings 2666 leavecode = OsclErrNone; 2667 KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen); 2668 if (OsclErrNone == leavecode) 2669 { 2670 KeyVal.value.pChar_value = (char*) AllocateKVPKeyArray(leavecode1, PVMI_KVPVALTYPE_CHARPTR, valuelen); 2671 } 2672 2673 if (OsclErrNone == leavecode && OsclErrNone == leavecode1) 2674 { 2675 // Copy the key string 2676 oscl_strncpy(KeyVal.key, PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY, oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY) + 1); 2677 oscl_strncat(KeyVal.key, PVOMXAUDIODECMETADATA_SEMICOLON, oscl_strlen(PVOMXAUDIODECMETADATA_SEMICOLON)); 2678 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR)); 2679 oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR)); 2680 KeyVal.key[KeyLen-1] = NULL_TERM_CHAR; 2681 // Copy the value 2682 if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM) 2683 { 2684 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_LATM), valuelen); 2685 } 2686 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO) 2687 { 2688 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_MPEG4_AUDIO), valuelen); 2689 } 2690 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640) 2691 { 2692 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_3640), valuelen); 2693 } 2694 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF) 2695 { 2696 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_ADIF), valuelen); 2697 } 2698 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2) 2699 { 2700 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMR_IF2), valuelen); 2701 } 2702 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF) 2703 { 2704 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMR_IETF), valuelen); 2705 } 2706 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR) 2707 { 2708 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMR), valuelen); 2709 } 2710 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF) 2711 { 2712 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMRWB_IETF), valuelen); 2713 } 2714 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB) 2715 { 2716 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMRWB), valuelen); 2717 } 2718 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3) 2719 { 2720 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_MP3), valuelen); 2721 } 2722 else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA) 2723 { 2724 oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_WMA), valuelen); 2725 } 2726 else 2727 { 2728 // Should not enter here 2729 OSCL_ASSERT(false); 2730 } 2731 KeyVal.value.pChar_value[valuelen-1] = NULL_TERM_CHAR; 2732 // Set the length and capacity 2733 KeyVal.length = valuelen; 2734 KeyVal.capacity = valuelen; 2735 } 2736 else 2737 { 2738 // Memory allocation failed so clean up 2739 if (KeyVal.key) 2740 { 2741 OSCL_ARRAY_DELETE(KeyVal.key); 2742 KeyVal.key = NULL; 2743 } 2744 if (KeyVal.value.pChar_value) 2745 { 2746 OSCL_ARRAY_DELETE(KeyVal.value.pChar_value); 2747 } 2748 break; 2749 } 2750 } 2751 } 2752 } 2753 2754 if (KeyVal.key != NULL) 2755 { 2756 leavecode = OsclErrNone; 2757 leavecode = PushKVP(KeyVal, *valuelistptr); 2758 if (OsclErrNone != leavecode) 2759 { 2760 switch (GetValTypeFromKeyString(KeyVal.key)) 2761 { 2762 case PVMI_KVPVALTYPE_CHARPTR: 2763 if (KeyVal.value.pChar_value != NULL) 2764 { 2765 OSCL_ARRAY_DELETE(KeyVal.value.pChar_value); 2766 KeyVal.value.pChar_value = NULL; 2767 } 2768 break; 2769 2770 default: 2771 // Add more case statements if other value types are returned 2772 break; 2773 } 2774 2775 OSCL_ARRAY_DELETE(KeyVal.key); 2776 KeyVal.key = NULL; 2777 } 2778 else 2779 { 2780 // Increment the counter for number of value entries added to the list 2781 ++numentriesadded; 2782 } 2783 2784 // Check if the max number of value entries were added 2785 if (max_entries > 0 && numentriesadded >= max_entries) 2786 { 2787 break; 2788 } 2789 2790 } 2791 2792 } 2793 2794 return PVMFSuccess; 2795 2796 } 2797 2798 ///////////////////////////////////////////////////////////////////////////// 2799 bool PVMFOMXAudioDecNode::ReleaseAllPorts() 2800 { 2801 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::ReleaseAllPorts() In")); 2802 2803 if (iInPort) 2804 { 2805 iInPort->ClearMsgQueues(); 2806 iInPort->Disconnect(); 2807 OSCL_DELETE(((PVMFOMXDecPort*)iInPort)); 2808 iInPort = NULL; 2809 } 2810 2811 if (iOutPort) 2812 { 2813 iOutPort->ClearMsgQueues(); 2814 iOutPort->Disconnect(); 2815 OSCL_DELETE(((PVMFOMXDecPort*)iOutPort)); 2816 iOutPort = NULL; 2817 } 2818 2819 return true; 2820 } 2821 2822 ///////////////////////////////////////////////////////////////////////////// 2823 void PVMFOMXAudioDecNode::DoQueryUuid(PVMFOMXBaseDecNodeCommand& aCmd) 2824 { 2825 //This node supports Query UUID from any state 2826 2827 OSCL_String* mimetype; 2828 Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec; 2829 bool exactmatch; 2830 aCmd.PVMFOMXBaseDecNodeCommandBase::Parse(mimetype, uuidvec, exactmatch); 2831 2832 //Try to match the input mimetype against any of 2833 //the custom interfaces for this node 2834 2835 //Match against custom interface1... 2836 if (*mimetype == PVMF_OMX_BASE_DEC_NODE_CUSTOM1_MIMETYPE 2837 //also match against base mimetypes for custom interface1, 2838 //unless exactmatch is set. 2839 || (!exactmatch && *mimetype == PVMF_OMX_AUDIO_DEC_NODE_MIMETYPE) 2840 || (!exactmatch && *mimetype == PVMF_BASEMIMETYPE)) 2841 { 2842 2843 PVUuid uuid(PVMF_OMX_BASE_DEC_NODE_CUSTOM1_UUID); 2844 uuidvec->push_back(uuid); 2845 } 2846 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 2847 } 2848 2849 PVMFStatus PVMFOMXAudioDecNode::CreateLATMParser() 2850 { 2851 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode::CreateLATMParser() In")); 2852 2853 // First clean up if necessary 2854 DeleteLATMParser(); 2855 2856 // Instantiate the LATM parser 2857 iLATMParser = OSCL_NEW(PV_LATM_Parser, ()); 2858 if (!iLATMParser) 2859 { 2860 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::CreateLATMParser() LATM parser instantiation failed")); 2861 return PVMFErrNoMemory; 2862 } 2863 2864 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode::CreateLATMParser() Out")); 2865 return PVMFSuccess; 2866 } 2867 2868 PVMFStatus PVMFOMXAudioDecNode::DeleteLATMParser() 2869 { 2870 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode::DeleteLATMParser() In")); 2871 2872 // Delete LATM parser if there is one 2873 if (iLATMParser) 2874 { 2875 OSCL_DELETE(iLATMParser); 2876 iLATMParser = NULL; 2877 } 2878 2879 if (iLATMConfigBuffer) 2880 { 2881 oscl_free(iLATMConfigBuffer); 2882 iLATMConfigBuffer = NULL; 2883 iLATMConfigBufferSize = 0; 2884 } 2885 2886 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode::DeleteLATMParser() Out")); 2887 return PVMFSuccess; 2888 } 2889 2890 2891 2892 2893 2894 2895 ///////////////////////////////////////////////////////////////////////////// 2896 uint32 PVMFOMXAudioDecNode::GetNumMetadataKeys(char* aQueryKeyString) 2897 { 2898 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::GetNumMetadataKeys() called")); 2899 2900 uint32 num_entries = 0; 2901 2902 if (aQueryKeyString == NULL) 2903 { 2904 num_entries = iAvailableMetadataKeys.size(); 2905 } 2906 else 2907 { 2908 for (uint32 i = 0; i < iAvailableMetadataKeys.size(); i++) 2909 { 2910 if (pv_mime_strcmp(iAvailableMetadataKeys[i].get_cstr(), aQueryKeyString) >= 0) 2911 { 2912 num_entries++; 2913 } 2914 } 2915 } 2916 return num_entries; // Number of elements 2917 2918 } 2919 2920 ///////////////////////////////////////////////////////////////////////////// 2921 uint32 PVMFOMXAudioDecNode::GetNumMetadataValues(PVMFMetadataList& aKeyList) 2922 { 2923 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::GetNumMetadataValues() called")); 2924 2925 uint32 numkeys = aKeyList.size(); 2926 2927 if (numkeys <= 0) 2928 { 2929 // Don't do anything 2930 return 0; 2931 } 2932 2933 // Count the number of value entries for the provided key list 2934 uint32 numvalentries = 0; 2935 for (uint32 lcv = 0; lcv < numkeys; lcv++) 2936 { 2937 if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY) == 0)) 2938 { 2939 // Channels 2940 if (iNumberOfAudioChannels > 0) 2941 { 2942 ++numvalentries; 2943 } 2944 } 2945 else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY) == 0) && (iPCMSamplingRate > 0)) 2946 { 2947 // Sample rate 2948 ++numvalentries; 2949 } 2950 else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY) == 0) && 2951 iInPort != NULL) 2952 { 2953 // Format 2954 if ((((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM) || 2955 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO) || 2956 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640) || 2957 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF) || 2958 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2) || 2959 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF) || 2960 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR) || 2961 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF) || 2962 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB) || 2963 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3) || 2964 (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA) 2965 2966 ) 2967 2968 { 2969 ++numvalentries; 2970 } 2971 } 2972 } 2973 2974 return numvalentries; 2975 } 2976 2977 2978 // needed for WMA parameter verification 2979 bool PVMFOMXAudioDecNode::VerifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements) 2980 { 2981 OSCL_UNUSED_ARG(aSession); 2982 OSCL_UNUSED_ARG(num_elements); 2983 if (pv_mime_strcmp(aParameters->key, PVMF_BITRATE_VALUE_KEY) == 0) 2984 { 2985 if (((PVMFOMXDecPort*)iOutPort)->verifyConnectedPortParametersSync(PVMF_BITRATE_VALUE_KEY, &(aParameters->value.uint32_value)) != PVMFSuccess) 2986 { 2987 return false; 2988 } 2989 return true; 2990 } 2991 else if (pv_mime_strcmp(aParameters->key, PVMF_FORMAT_SPECIFIC_INFO_KEY) < 0) 2992 { 2993 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::VerifyParametersSync() - Unsupported Key")); 2994 OSCL_ASSERT(false); 2995 } 2996 2997 bool cap_exchange_status = false; 2998 2999 pvAudioConfigParserInputs aInputs; 3000 OMXConfigParserInputs aInputParameters; 3001 AudioOMXConfigParserOutputs aOutputParameters; 3002 3003 aInputs.inPtr = (uint8*)(aParameters->value.key_specific_value); 3004 aInputs.inBytes = (int32)aParameters->capacity; 3005 aInputs.iMimeType = PVMF_MIME_WMA; 3006 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.wma"; 3007 aInputParameters.inBytes = aInputs.inBytes; 3008 aInputParameters.inPtr = aInputs.inPtr; 3009 3010 3011 if (aInputs.inBytes == 0 || aInputs.inPtr == NULL) 3012 { 3013 return cap_exchange_status; 3014 } 3015 3016 3017 OMX_BOOL status = OMX_FALSE; 3018 OMX_U32 num_comps = 0, ii; 3019 OMX_STRING *CompOfRole; 3020 // uint32 ii; 3021 // call once to find out the number of components that can fit the role 3022 OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, NULL); 3023 3024 if (num_comps > 0) 3025 { 3026 CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING)); 3027 for (ii = 0; ii < num_comps; ii++) 3028 CompOfRole[ii] = (OMX_STRING) oscl_malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8)); 3029 3030 // call 2nd time to get the component names 3031 OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, (OMX_U8 **)CompOfRole); 3032 3033 for (ii = 0; ii < num_comps; ii++) 3034 { 3035 aInputParameters.cComponentName = CompOfRole[ii]; 3036 status = OMX_MasterConfigParser(&aInputParameters, &aOutputParameters); 3037 if (status == OMX_TRUE) 3038 { 3039 break; 3040 } 3041 else 3042 { 3043 status = OMX_FALSE; 3044 } 3045 } 3046 3047 // whether successful or not, need to free CompOfRoles 3048 for (ii = 0; ii < num_comps; ii++) 3049 { 3050 oscl_free(CompOfRole[ii]); 3051 CompOfRole[ii] = NULL; 3052 } 3053 3054 oscl_free(CompOfRole); 3055 3056 } 3057 else 3058 { 3059 // if no components support the role, nothing else to do 3060 return false; 3061 } 3062 3063 if (OMX_FALSE != status) 3064 { 3065 cap_exchange_status = true; 3066 3067 iPCMSamplingRate = aOutputParameters.SamplesPerSec; 3068 iNumberOfAudioChannels = aOutputParameters.Channels; 3069 3070 if ((iNumberOfAudioChannels != 1 && iNumberOfAudioChannels != 2) || 3071 (iPCMSamplingRate <= 0)) 3072 { 3073 cap_exchange_status = false; 3074 } 3075 } 3076 3077 return cap_exchange_status; 3078 3079 } 3080 3081 3082 PVMFStatus PVMFOMXAudioDecNode::DoCapConfigVerifyParameters(PvmiKvp* aParameters, int aNumElements) 3083 { 3084 OSCL_UNUSED_ARG(aNumElements); 3085 3086 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3087 (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() In\n")); 3088 3089 pvAudioConfigParserInputs aInputs; 3090 OMXConfigParserInputs aInputParameters; 3091 AudioOMXConfigParserOutputs aOutputParameters; 3092 3093 aInputs.inPtr = (uint8*)(aParameters->value.key_specific_value); 3094 aInputs.inBytes = (int32)aParameters->capacity; 3095 aInputs.iMimeType = iNodeConfig.iMimeType; 3096 aInputParameters.inBytes = aInputs.inBytes; 3097 aInputParameters.inPtr = aInputs.inPtr; 3098 3099 if (aInputs.inBytes == 0 || aInputs.inPtr == NULL) 3100 { 3101 // in case of following formats - config codec data is expected to 3102 // be present in the query. If not, config parser cannot be called 3103 if (aInputs.iMimeType == PVMF_MIME_WMA || 3104 aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO || 3105 aInputs.iMimeType == PVMF_MIME_3640 || 3106 aInputs.iMimeType == PVMF_MIME_LATM || 3107 aInputs.iMimeType == PVMF_MIME_ADIF || 3108 aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO || 3109 aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR) 3110 { 3111 if (aInputs.iMimeType == PVMF_MIME_LATM) 3112 { 3113 return PVMFErrNotSupported; 3114 } 3115 else 3116 { 3117 // DV TO_DO: remove this 3118 OSCL_LEAVE(OsclErrNotSupported); 3119 } 3120 } 3121 } 3122 3123 3124 if (aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO || 3125 aInputs.iMimeType == PVMF_MIME_3640 || 3126 aInputs.iMimeType == PVMF_MIME_LATM || 3127 aInputs.iMimeType == PVMF_MIME_ADIF || 3128 aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO || 3129 aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR) 3130 { 3131 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.aac"; 3132 } 3133 // AMR 3134 else if (aInputs.iMimeType == PVMF_MIME_AMR_IF2 || 3135 aInputs.iMimeType == PVMF_MIME_AMR_IETF || 3136 aInputs.iMimeType == PVMF_MIME_AMR) 3137 { 3138 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.amrnb"; 3139 } 3140 else if (aInputs.iMimeType == PVMF_MIME_AMRWB_IETF || 3141 aInputs.iMimeType == PVMF_MIME_AMRWB) 3142 { 3143 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.amrwb"; 3144 } 3145 else if (aInputs.iMimeType == PVMF_MIME_MP3) 3146 { 3147 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.mp3"; 3148 } 3149 else if (aInputs.iMimeType == PVMF_MIME_WMA) 3150 { 3151 aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.wma"; 3152 } 3153 else 3154 { 3155 // Illegal codec specified. 3156 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() Input port format other then codec type", iName.Str())); 3157 } 3158 3159 OMX_BOOL status = OMX_FALSE; 3160 OMX_U32 num_comps = 0, ii; 3161 OMX_STRING *CompOfRole; 3162 // uint32 ii; 3163 // call once to find out the number of components that can fit the role 3164 OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, NULL); 3165 3166 if (num_comps > 0) 3167 { 3168 CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING)); 3169 for (ii = 0; ii < num_comps; ii++) 3170 CompOfRole[ii] = (OMX_STRING) oscl_malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8)); 3171 3172 // call 2nd time to get the component names 3173 OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, (OMX_U8 **)CompOfRole); 3174 3175 for (ii = 0; ii < num_comps; ii++) 3176 { 3177 aInputParameters.cComponentName = CompOfRole[ii]; 3178 status = OMX_MasterConfigParser(&aInputParameters, &aOutputParameters); 3179 if (status == OMX_TRUE) 3180 { 3181 break; 3182 } 3183 else 3184 { 3185 status = OMX_FALSE; 3186 } 3187 } 3188 3189 // whether successful or not, need to free CompOfRoles 3190 for (ii = 0; ii < num_comps; ii++) 3191 { 3192 oscl_free(CompOfRole[ii]); 3193 CompOfRole[ii] = NULL; 3194 } 3195 3196 oscl_free(CompOfRole); 3197 3198 } 3199 else 3200 { 3201 // if no component supports the role, nothing else to do 3202 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3203 (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() No omx component supports this role PVMFErrNotSupported\n")); 3204 return PVMFErrNotSupported; 3205 } 3206 3207 if (status == OMX_FALSE) 3208 { 3209 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3210 (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() ->OMXConfigParser() PVMFErrNotSupported\n")); 3211 return PVMFErrNotSupported; 3212 } 3213 3214 if (aInputs.iMimeType == PVMF_MIME_WMA) 3215 { 3216 iNumberOfAudioChannels = aOutputParameters.Channels; 3217 iPCMSamplingRate = aOutputParameters.SamplesPerSec; 3218 } 3219 else if (aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO || 3220 aInputs.iMimeType == PVMF_MIME_3640 || 3221 aInputs.iMimeType == PVMF_MIME_LATM || 3222 aInputs.iMimeType == PVMF_MIME_ADIF || 3223 aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO || 3224 aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR) 3225 { 3226 iNumberOfAudioChannels = aOutputParameters.Channels; 3227 } 3228 3229 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3230 (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() Out\n")); 3231 return PVMFSuccess; 3232 } 3233 3234 void PVMFOMXAudioDecNode::DoCapConfigSetParameters(PvmiKvp* aParameters, int aNumElements, PvmiKvp* &aRetKVP) 3235 { 3236 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3237 (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() In\n")); 3238 OSCL_UNUSED_ARG(aNumElements); 3239 OSCL_UNUSED_ARG(aRetKVP); 3240 3241 // find out if the audio dec format key is used for the query 3242 if (pv_mime_strcmp(aParameters->key, PVMF_AUDIO_DEC_FORMAT_TYPE_VALUE_KEY) == 0) 3243 { 3244 // set the mime type if audio format is being used 3245 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3246 (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() set audio dec format type to %s\n", aParameters->value.pChar_value)); 3247 3248 iNodeConfig.iMimeType = aParameters->value.pChar_value; 3249 } 3250 3251 else 3252 { 3253 // For now, ignore other queries 3254 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3255 (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() Key not used")); 3256 3257 // indicate "error" by setting return KVP to the original 3258 aRetKVP = aParameters; 3259 } 3260 3261 3262 3263 3264 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 3265 (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() Out\n")); 3266 } 3267 3268 3269 3270