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 /** 19 * @file pvmp4ffcn_port.cpp 20 * @brief Port for PVMp4FFComposerNode 21 */ 22 23 #ifndef PVMP4FFCN_PORT_H_INCLUDED 24 #include "pvmp4ffcn_port.h" 25 #endif 26 #ifndef PVMP4FFCN_NODE_H_INCLUDED 27 #include "pvmp4ffcn_node.h" 28 #endif 29 #ifndef PVMP4FFCN_TYPES_H_INCLUDED 30 #include "pvmp4ffcn_types.h" 31 #endif 32 #ifndef PVLOGGER_H_INCLUDED 33 #include "pvlogger.h" 34 #endif 35 #ifndef OSCL_MIME_STRING_UTILS_H 36 #include "pv_mime_string_utils.h" 37 #endif 38 39 #define LOG_STACK_TRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, m); 40 #define LOG_DEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, m); 41 #define LOG_ERR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m); 42 43 //////////////////////////////////////////////////////////////////////////// 44 PVMp4FFComposerPort::PVMp4FFComposerPort(int32 aTag, PVMp4FFComposerNode* aNode, int32 aPriority, const char* aName) 45 : PvmfPortBaseImpl(aTag, this, 46 PVMF_MP4FFCN_PORT_CAPACITY, PVMF_MP4FFCN_PORT_RESERVE, PVMF_MP4FFCN_PORT_THRESHOLD, 47 PVMF_MP4FFCN_PORT_CAPACITY, PVMF_MP4FFCN_PORT_RESERVE, PVMF_MP4FFCN_PORT_THRESHOLD, aName), 48 OsclActiveObject(aPriority, "PVMp4FFComposerPort"), 49 iNode(aNode), 50 iTrackId(0), 51 iFormat(PVMF_MIME_FORMAT_UNKNOWN), 52 iCodecType(0), 53 iReferencePort(NULL), 54 iLastTS(0), 55 iEndOfDataReached(false) 56 { 57 AddToScheduler(); 58 iLogger = PVLogger::GetLoggerObject("PVMp4FFComposerPort"); 59 oscl_memset((OsclAny*)&iFormatSpecificConfig, 0, sizeof(PVMP4FFCNFormatSpecificConfig)); 60 memfrag_pps = NULL; 61 } 62 63 //////////////////////////////////////////////////////////////////////////// 64 PVMp4FFComposerPort::~PVMp4FFComposerPort() 65 { 66 if (memfrag_sps) 67 { 68 for (uint32 i = 0; i < iNode->memvector_sps.size(); i++) 69 { 70 OSCL_FREE(iNode->memvector_sps[i]->ptr); 71 } 72 73 while (!iNode->memvector_sps.empty()) 74 { 75 if (iNode->memvector_sps.front()) 76 { 77 OSCL_FREE(iNode->memvector_sps.front()); 78 } 79 iNode->memvector_sps.erase(&iNode->memvector_sps.front()); 80 } 81 } 82 83 if (memfrag_pps) 84 { 85 for (uint32 i = 0; i < iNode->memvector_pps.size(); i++) 86 { 87 OSCL_FREE(iNode->memvector_pps[i]->ptr); 88 } 89 90 while (!iNode->memvector_pps.empty()) 91 { 92 if (iNode->memvector_pps.front()) 93 { 94 OSCL_FREE(iNode->memvector_pps.front()); 95 } 96 iNode->memvector_pps.erase(&iNode->memvector_pps.front()); 97 } 98 } 99 100 if (iNode->textdecodervector.size() > 0) 101 { 102 103 while (!iNode->textdecodervector.empty()) 104 { 105 if (iNode->textdecodervector.front()) 106 { 107 OSCL_DELETE(iNode->textdecodervector.front()); 108 } 109 110 iNode->textdecodervector.erase(&iNode->textdecodervector.front()); 111 } 112 } 113 Disconnect(); 114 ClearMsgQueues(); 115 116 // we need to clear the activity handler, since otherwise the PvmfPortBaseImpl destructor 117 // ends up calling back onto our HandlePortActivity method, which no longer exists because 118 // this objects's destructor has already been called. 119 SetActivityHandler(NULL); 120 } 121 122 //////////////////////////////////////////////////////////////////////////// 123 OSCL_EXPORT_REF void PVMp4FFComposerPort::QueryInterface(const PVUuid& aUuid, OsclAny*& aPtr) 124 { 125 if (aUuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID) 126 aPtr = (PvmiCapabilityAndConfig*)this; 127 else 128 aPtr = NULL; 129 } 130 131 //////////////////////////////////////////////////////////////////////////// 132 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerPort::Connect(PVMFPortInterface* aPort) 133 { 134 LOG_STACK_TRACE((0, "PVMp4FFComposerPort::Connect: aPort=0x%x", aPort)); 135 136 if (!aPort) 137 { 138 LOG_ERR((0, "PVMp4FFComposerPort::Connect: Error - Connecting to invalid port")); 139 return PVMFErrArgument; 140 } 141 142 if (iConnectedPort) 143 { 144 LOG_ERR((0, "PVMp4FFComposerPort::Connect: Error - Already connected")); 145 return PVMFFailure; 146 } 147 148 OsclAny* temp = NULL; 149 aPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, temp); 150 PvmiCapabilityAndConfig *config = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, temp); 151 152 if (!config) 153 { 154 LOG_ERR((0, "PVMp4FFComposerPort::Connect: Error - Peer port does not support capability interface")); 155 return PVMFFailure; 156 } 157 158 PVMFStatus status = PVMFSuccess; 159 switch (iTag) 160 { 161 case PVMF_MP4FFCN_PORT_TYPE_SINK: 162 status = NegotiateInputSettings(config); 163 break; 164 default: 165 LOG_ERR((0, "PVMp4FFComposerPort::Connect: Error - Invalid port tag")); 166 status = PVMFFailure; 167 } 168 169 if (status != PVMFSuccess) 170 { 171 LOG_ERR((0, "PVMp4FFComposerPort::Connect: Error - Settings negotiation failed. status=%d", status)); 172 return status; 173 } 174 175 //Automatically connect the peer. 176 if (aPort->PeerConnect(this) != PVMFSuccess) 177 { 178 LOG_ERR((0, "PVMp4FFComposerPort::Connect: Error - Peer Connect failed")); 179 return PVMFFailure; 180 } 181 182 iConnectedPort = aPort; 183 184 #if PVMF_PORT_BASE_IMPL_STATS 185 // Reset statistics 186 oscl_memset((OsclAny*)&(PvmfPortBaseImpl::iStats), 0, sizeof(PvmfPortBaseImplStats)); 187 #endif 188 189 PortActivity(PVMF_PORT_ACTIVITY_CONNECT); 190 return PVMFSuccess; 191 } 192 193 //////////////////////////////////////////////////////////////////////////// 194 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerPort::PeerConnect(PVMFPortInterface* aPort) 195 { 196 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 197 (0, "0x%x PVMp4FFComposerPort::PeerConnect: aPort=0x%x", this, aPort)); 198 199 if (!aPort) 200 { 201 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 202 (0, "0x%x PVMp4FFComposerPort::PeerConnect: Error - Connecting to invalid port", this)); 203 return PVMFErrArgument; 204 } 205 206 if (iConnectedPort) 207 { 208 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 209 (0, "0x%x PVMp4FFComposerPort::PeerConnect: Error - Already connected", this)); 210 return PVMFFailure; 211 } 212 213 // When connection is initiated by peer, this port still needs to query the peer 214 // for input format configuration data 215 OsclAny* temp = NULL; 216 aPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, temp); 217 PvmiCapabilityAndConfig *config = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, temp); 218 219 if (!config) 220 { 221 LOG_ERR((0, "PVMp4FFComposerPort::PeerConnect: Error - Peer port does not support capability interface")); 222 return PVMFFailure; 223 } 224 225 PVMFStatus status = GetInputParametersFromPeer(config); 226 if (status != PVMFSuccess) 227 { 228 LOG_ERR((0, "PVMp4FFComposerPort::PeerConnect: Error - GetVideoInputParametersFromPeer failed. status=%d", 229 status)); 230 return status; 231 } 232 233 iConnectedPort = aPort; 234 235 #if PVMF_PORT_BASE_IMPL_STATS 236 // Reset statistics 237 oscl_memset((OsclAny*)&(PvmfPortBaseImpl::iStats), 0, sizeof(PvmfPortBaseImplStats)); 238 #endif 239 240 PortActivity(PVMF_PORT_ACTIVITY_CONNECT); 241 return PVMFSuccess; 242 } 243 244 //////////////////////////////////////////////////////////////////////////// 245 // PvmiCapabilityAndConfig 246 //////////////////////////////////////////////////////////////////////////// 247 OSCL_EXPORT_REF void PVMp4FFComposerPort::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver) 248 { 249 // Not supported 250 OSCL_UNUSED_ARG(aObserver); 251 } 252 253 //////////////////////////////////////////////////////////////////////////// 254 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerPort::getParametersSync(PvmiMIOSession session, 255 PvmiKeyType identifier, 256 PvmiKvp*& parameters, 257 int& num_parameter_elements, 258 PvmiCapabilityContext context) 259 { 260 LOG_STACK_TRACE((0, "PVMp4FFComposerPort::getParametersSync")); 261 OSCL_UNUSED_ARG(session); 262 OSCL_UNUSED_ARG(context); 263 264 parameters = NULL; 265 num_parameter_elements = 0; 266 PVMFStatus status = PVMFFailure; 267 268 //identifier is a key and is assumed to be null terminated 269 if (oscl_strcmp(identifier, INPUT_FORMATS_CAP_QUERY) == 0) 270 { 271 num_parameter_elements = 8; 272 status = AllocateKvp(parameters, (PvmiKeyType)INPUT_FORMATS_VALTYPE, num_parameter_elements); 273 if (status != PVMFSuccess) 274 { 275 LOG_ERR((0, "PVMp4FFComposerPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status)); 276 } 277 else 278 { 279 parameters[0].value.pChar_value = (char*)PVMF_MIME_AMR_IETF; 280 parameters[1].value.pChar_value = (char*)PVMF_MIME_MPEG4_AUDIO; 281 parameters[2].value.pChar_value = (char*)PVMF_MIME_M4V; 282 parameters[3].value.pChar_value = (char*)PVMF_MIME_H2631998; 283 parameters[4].value.pChar_value = (char*)PVMF_MIME_H2632000; 284 parameters[5].value.pChar_value = (char*)PVMF_MIME_H264_VIDEO_MP4; 285 parameters[6].value.pChar_value = (char*)PVMF_MIME_3GPP_TIMEDTEXT; 286 parameters[7].value.pChar_value = (char*)PVMF_MIME_AMRWB_IETF; 287 } 288 } 289 else if (oscl_strcmp(identifier, INPUT_FORMATS_CUR_QUERY) == 0) 290 { 291 num_parameter_elements = 1; 292 status = AllocateKvp(parameters, (PvmiKeyType)INPUT_FORMATS_VALTYPE, num_parameter_elements); 293 if (status != PVMFSuccess) 294 { 295 LOG_ERR((0, "PVMp4FFComposerPort::GetOutputParametersSync: Error - AllocateKvp failed. status=%d", status)); 296 } 297 else 298 { 299 parameters[0].value.pChar_value = (char*)iFormat.getMIMEStrPtr(); 300 } 301 } 302 303 return status; 304 } 305 306 //////////////////////////////////////////////////////////////////////////// 307 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerPort::releaseParameters(PvmiMIOSession session, 308 PvmiKvp* parameters, 309 int num_elements) 310 { 311 OSCL_UNUSED_ARG(session); 312 OSCL_UNUSED_ARG(num_elements); 313 314 if (parameters) 315 { 316 iAlloc.deallocate((OsclAny*)parameters); 317 return PVMFSuccess; 318 } 319 else 320 { 321 return PVMFFailure; 322 } 323 } 324 325 //////////////////////////////////////////////////////////////////////////// 326 OSCL_EXPORT_REF void PVMp4FFComposerPort::createContext(PvmiMIOSession session, PvmiCapabilityContext& context) 327 { 328 OSCL_UNUSED_ARG(session); 329 OSCL_UNUSED_ARG(context); 330 } 331 332 //////////////////////////////////////////////////////////////////////////// 333 OSCL_EXPORT_REF void PVMp4FFComposerPort::setContextParameters(PvmiMIOSession session, 334 PvmiCapabilityContext& context, 335 PvmiKvp* parameters, int num_parameter_elements) 336 { 337 OSCL_UNUSED_ARG(session); 338 OSCL_UNUSED_ARG(context); 339 OSCL_UNUSED_ARG(parameters); 340 OSCL_UNUSED_ARG(num_parameter_elements); 341 } 342 343 //////////////////////////////////////////////////////////////////////////// 344 OSCL_EXPORT_REF void PVMp4FFComposerPort::DeleteContext(PvmiMIOSession session, PvmiCapabilityContext& context) 345 { 346 OSCL_UNUSED_ARG(session); 347 OSCL_UNUSED_ARG(context); 348 } 349 350 //////////////////////////////////////////////////////////////////////////// 351 OSCL_EXPORT_REF void PVMp4FFComposerPort::setParametersSync(PvmiMIOSession session, PvmiKvp* parameters, 352 int num_elements, PvmiKvp*& ret_kvp) 353 { 354 OSCL_UNUSED_ARG(session); 355 356 ret_kvp = NULL; 357 if (iFormat == PVMF_MIME_H264_VIDEO_MP4) 358 { 359 //this code is specific to H264 file format 360 for (int32 i = 0; i < num_elements; i++)//assuming the memory is allocated for key 361 { 362 if (pv_mime_strcmp(parameters->key, VIDEO_AVC_OUTPUT_SPS_CUR_VALUE) == 0) 363 { 364 memfrag_sps = (OsclMemoryFragment *)(OSCL_MALLOC(sizeof(OsclMemoryFragment))); 365 memfrag_sps->len = parameters->capacity; 366 memfrag_sps->ptr = (uint8*)(OSCL_MALLOC(sizeof(uint8) * memfrag_sps->len)); 367 oscl_memcpy((void*)memfrag_sps->ptr, (const void*)parameters->value.key_specific_value, memfrag_sps->len); 368 iNode->memvector_sps.push_back(memfrag_sps); //storing SPS in the vector 369 iNode->iNum_SPS_Set += 1; 370 } 371 if (pv_mime_strcmp(parameters->key, VIDEO_AVC_OUTPUT_PPS_CUR_VALUE) == 0) 372 { 373 memfrag_pps = (OsclMemoryFragment *)(OSCL_MALLOC(sizeof(OsclMemoryFragment))); 374 memfrag_pps->len = parameters->capacity; 375 memfrag_pps->ptr = (uint8*)(OSCL_MALLOC(sizeof(uint8) * memfrag_pps->len)); 376 oscl_memcpy((void*)memfrag_pps->ptr, (const void*)parameters->value.key_specific_value, memfrag_pps->len); 377 iNode->memvector_pps.push_back(memfrag_pps); //storing PPS in the vector 378 iNode->iNum_PPS_Set += 1; 379 } 380 } 381 } 382 if (iFormat == PVMF_MIME_3GPP_TIMEDTEXT) 383 { 384 for (int32 i = 0; i < num_elements; i++)//assuming the memory is allocated for keys 385 { 386 if (pv_mime_strcmp(parameters->key, TIMED_TEXT_OUTPUT_CONFIG_INFO_CUR_VALUE) == 0) 387 { 388 PVA_FF_TextSampleDescInfo* ptempDecoderinfo = 389 OSCL_STATIC_CAST(PVA_FF_TextSampleDescInfo*, parameters->value.key_specific_value); 390 391 PVA_FF_TextSampleDescInfo* pDecoderinfo = OSCL_NEW(PVA_FF_TextSampleDescInfo, (*ptempDecoderinfo)); 392 iNode->textdecodervector.push_back(pDecoderinfo); 393 } 394 } 395 } 396 397 } 398 399 //////////////////////////////////////////////////////////////////////////// 400 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerPort::setParametersAsync(PvmiMIOSession session, 401 PvmiKvp* parameters, 402 int num_elements, 403 PvmiKvp*& ret_kvp, 404 OsclAny* context) 405 { 406 OSCL_UNUSED_ARG(session); 407 OSCL_UNUSED_ARG(parameters); 408 OSCL_UNUSED_ARG(num_elements); 409 OSCL_UNUSED_ARG(ret_kvp); 410 OSCL_UNUSED_ARG(context); 411 return -1; 412 } 413 414 //////////////////////////////////////////////////////////////////////////// 415 OSCL_EXPORT_REF uint32 PVMp4FFComposerPort::getCapabilityMetric(PvmiMIOSession session) 416 { 417 OSCL_UNUSED_ARG(session); 418 return 0; 419 } 420 421 //////////////////////////////////////////////////////////////////////////// 422 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerPort::verifyParametersSync(PvmiMIOSession session, 423 PvmiKvp* parameters, int num_elements) 424 { 425 OSCL_UNUSED_ARG(session); 426 427 PVMFStatus status = PVMFSuccess; 428 for (int32 i = 0; (i < num_elements) && (status == PVMFSuccess); i++) 429 status = VerifyAndSetParameter(&(parameters[i])); 430 431 return status; 432 } 433 434 //////////////////////////////////////////////////////////////////////////// 435 void PVMp4FFComposerPort::ProcessIncomingMsgReady() 436 { 437 if (IncomingMsgQueueSize() > 0) 438 RunIfNotReady(); 439 } 440 441 //////////////////////////////////////////////////////////////////////////// 442 // Pure virtuals from PVMFPortActivityHandler 443 //////////////////////////////////////////////////////////////////////////// 444 void PVMp4FFComposerPort::HandlePortActivity(const PVMFPortActivity& aActivity) 445 { 446 LOG_STACK_TRACE((0, "PVMp4FFComposerPort::HandlePortActivity: type=%d", aActivity.iType)); 447 448 if (aActivity.iPort != this) 449 { 450 LOG_ERR((0, "PVMp4FFComposerPort::HandlePortActivity: Error - Activity is not on this port")); 451 return; 452 } 453 454 switch (aActivity.iType) 455 { 456 case PVMF_PORT_ACTIVITY_CREATED: 457 //Report port created info event to the node. 458 iNode->ReportInfoEvent(PVMFInfoPortCreated, 459 (OsclAny*)aActivity.iPort); 460 break; 461 462 case PVMF_PORT_ACTIVITY_DELETED: 463 //Report port deleted info event to the node. 464 iNode->ReportInfoEvent(PVMFInfoPortDeleted, 465 (OsclAny*)aActivity.iPort); 466 break; 467 468 case PVMF_PORT_ACTIVITY_OUTGOING_MSG: 469 // Not supported 470 break; 471 472 case PVMF_PORT_ACTIVITY_INCOMING_MSG: 473 //Wakeup the AO on the first message only. After that it re-schedules itself as needed. 474 if (IncomingMsgQueueSize() == 1) 475 { 476 RunIfNotReady(); 477 } 478 break; 479 480 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY: 481 // Not supported 482 break; 483 484 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY: 485 // Not supported 486 break; 487 488 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY: 489 // Not supported 490 break; 491 492 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY: 493 // Not supported 494 break; 495 496 case PVMF_PORT_ACTIVITY_CONNECT: 497 case PVMF_PORT_ACTIVITY_DISCONNECT: 498 default: 499 break; 500 } 501 } 502 503 //////////////////////////////////////////////////////////////////////////// 504 // Pure virtuals from OsclActiveObject 505 //////////////////////////////////////////////////////////////////////////// 506 void PVMp4FFComposerPort::Run() 507 { 508 LOG_STACK_TRACE((0, "PVMp4FFComposerPort::Run")); 509 PVMFStatus status = PVMFSuccess; 510 511 if (!iEndOfDataReached && (IncomingMsgQueueSize() > 0)) 512 { 513 //dispatch the incoming data. 514 #ifdef _TEST_AE_ERROR_HANDLING 515 516 if (1 == iNode->iErrorDataPathStall) 517 { 518 status = PVMFSuccess; 519 } 520 else 521 { 522 status = iNode->ProcessIncomingMsg(this); 523 } 524 #else 525 status = iNode->ProcessIncomingMsg(this); 526 #endif 527 switch (status) 528 { 529 case PVMFSuccess: 530 // Reschedule if there is more data and the node did not become busy 531 // after processing the current msg 532 if (IncomingMsgQueueSize() > 0 && iNode->IsProcessIncomingMsgReady()) 533 { 534 RunIfNotReady(); 535 } 536 break; 537 538 case PVMFErrBusy: 539 // Node busy. Don't schedule next data 540 break; 541 542 default: 543 LOG_ERR((0, "PVMp4FFComposerPort::Run: Error - ProcessIncomingMsg failed. status=%d", status)); 544 break; 545 } 546 } 547 548 if (iNode->IsFlushPending()) 549 { 550 if (IncomingMsgQueueSize() == 0 && OutgoingMsgQueueSize() == 0) 551 iNode->FlushComplete(); 552 } 553 } 554 555 //////////////////////////////////////////////////////////////////////////// 556 PVMFStatus PVMp4FFComposerPort::AllocateKvp(PvmiKvp*& aKvp, PvmiKeyType aKey, int32 aNumParams) 557 { 558 LOG_STACK_TRACE((0, "PVMp4FFComposerPort::AllocateKvp")); 559 uint8* buf = NULL; 560 uint32 keyLen = oscl_strlen(aKey) + 1; 561 int32 err = 0; 562 563 OSCL_TRY(err, 564 buf = (uint8*)iAlloc.allocate(aNumParams * (sizeof(PvmiKvp) + keyLen)); 565 if (!buf) 566 OSCL_LEAVE(OsclErrNoMemory); 567 ); 568 OSCL_FIRST_CATCH_ANY(err, 569 LOG_ERR((0, "PVMp4FFComposerPort::AllocateKvp: Error - kvp allocation failed")); 570 return PVMFErrNoMemory; 571 ); 572 573 int32 i = 0; 574 PvmiKvp* curKvp = aKvp = OSCL_PLACEMENT_NEW(buf, PvmiKvp); 575 buf += sizeof(PvmiKvp); 576 for (i = 1; i < aNumParams; i++) 577 { 578 curKvp += i; 579 curKvp = OSCL_PLACEMENT_NEW(buf, PvmiKvp); 580 buf += sizeof(PvmiKvp); 581 } 582 583 for (i = 0; i < aNumParams; i++) 584 { 585 aKvp[i].key = (char*)buf; 586 oscl_strncpy(aKvp[i].key, aKey, keyLen); 587 buf += keyLen; 588 } 589 590 return PVMFSuccess; 591 } 592 593 //////////////////////////////////////////////////////////////////////////// 594 PVMFStatus PVMp4FFComposerPort::VerifyAndSetParameter(PvmiKvp* aKvp, bool aSetParam) 595 { 596 LOG_STACK_TRACE((0, "PVMp4FFComposerPort::VerifyAndSetParameter: aKvp=0x%x, aSetParam=%d", aKvp, aSetParam)); 597 598 if (!aKvp) 599 { 600 LOG_ERR((0, "PVMp4FFComposerPort::VerifyAndSetParameter: Error - Invalid key-value pair")); 601 return PVMFFailure; 602 } 603 604 if (pv_mime_strcmp(aKvp->key, INPUT_FORMATS_VALTYPE) == 0) 605 { 606 if (pv_mime_strcmp(aKvp->value.pChar_value, PVMF_MIME_3GPP_TIMEDTEXT) == 0 || 607 pv_mime_strcmp(aKvp->value.pChar_value, PVMF_MIME_AMR_IETF) == 0 || 608 pv_mime_strcmp(aKvp->value.pChar_value, PVMF_MIME_AMRWB_IETF) == 0 || 609 pv_mime_strcmp(aKvp->value.pChar_value, PVMF_MIME_H264_VIDEO_MP4) == 0 || 610 pv_mime_strcmp(aKvp->value.pChar_value, PVMF_MIME_M4V) == 0 || 611 pv_mime_strcmp(aKvp->value.pChar_value, PVMF_MIME_H2631998) == 0 || 612 pv_mime_strcmp(aKvp->value.pChar_value, PVMF_MIME_H2632000) == 0 || 613 pv_mime_strcmp(aKvp->value.pChar_value, PVMF_MIME_MPEG4_AUDIO) == 0) 614 { 615 if (aSetParam) 616 iFormat = aKvp->value.pChar_value; 617 return PVMFSuccess; 618 } 619 else 620 { 621 LOG_ERR((0, "PVMp4FFComposerPort::VerifyAndSetParameter: Error - Unsupported format %d", 622 aKvp->value.uint32_value)); 623 return PVMFFailure; 624 } 625 } 626 627 LOG_ERR((0, "PVMp4FFComposerPort::VerifyAndSetParameter: Error - Unsupported parameter")); 628 return PVMFFailure; 629 } 630 631 //////////////////////////////////////////////////////////////////////////// 632 PVMFStatus PVMp4FFComposerPort::NegotiateInputSettings(PvmiCapabilityAndConfig* aConfig) 633 { 634 LOG_STACK_TRACE((0, "PVMp4FFComposerPort::NegotiateInputSettings: aConfig=0x%x", aConfig)); 635 if (!aConfig) 636 { 637 LOG_ERR((0, "PVMp4FFComposerPort::NegotiateInputSettings: Error - Invalid config object")); 638 return PVMFFailure; 639 } 640 641 PvmiKvp* kvp = NULL; 642 PvmiKvp* retKvp = NULL; 643 int numParams = 0; 644 int32 err = 0; 645 646 // Get current output formats from peer 647 PVMFStatus status = aConfig->getParametersSync(NULL, (PvmiKeyType)OUTPUT_FORMATS_CUR_QUERY, kvp, numParams, NULL); 648 if (status != PVMFSuccess || numParams != 1) 649 { 650 LOG_ERR((0, "PVMp4FFComposerPort::NegotiateInputSettings: Error - config->getParametersSync(output_formats) failed")); 651 return status; 652 } 653 654 // Check if data format from peer is supported 655 if (pv_mime_strcmp(kvp->value.pChar_value, PVMF_MIME_3GPP_TIMEDTEXT) == 0 || 656 pv_mime_strcmp(kvp->value.pChar_value, PVMF_MIME_AMR_IETF) == 0 || 657 pv_mime_strcmp(kvp->value.pChar_value, PVMF_MIME_AMRWB_IETF) == 0 || 658 pv_mime_strcmp(kvp->value.pChar_value, PVMF_MIME_H264_VIDEO_MP4) == 0 || 659 pv_mime_strcmp(kvp->value.pChar_value, PVMF_MIME_M4V) == 0 || 660 pv_mime_strcmp(kvp->value.pChar_value, PVMF_MIME_H2631998) == 0 || 661 pv_mime_strcmp(kvp->value.pChar_value, PVMF_MIME_H2632000) == 0 || 662 pv_mime_strcmp(kvp->value.pChar_value, PVMF_MIME_MPEG4_AUDIO) == 0) 663 { 664 // do nothing 665 } 666 else 667 { 668 return PVMFErrNotSupported; 669 } 670 671 // Set format of this port, peer port and container node 672 iFormat = kvp->value.pChar_value; 673 OSCL_TRY(err, aConfig->setParametersSync(NULL, kvp, 1, retKvp);); 674 OSCL_FIRST_CATCH_ANY(err, 675 LOG_ERR((0, "PVMp4FFComposerPort::NegotiateInputSettings: Error - aConfig->setParametersSync failed. err=%d", err)); 676 return PVMFFailure; 677 ); 678 679 // Release parameters back to peer and reset for the next query 680 aConfig->releaseParameters(NULL, kvp, numParams); 681 kvp = NULL; 682 numParams = 0; 683 684 return GetInputParametersFromPeer(aConfig); 685 } 686 687 //////////////////////////////////////////////////////////////////////////// 688 PVMFStatus PVMp4FFComposerPort::GetInputParametersFromPeer(PvmiCapabilityAndConfig* aConfig) 689 { 690 LOG_STACK_TRACE((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: aConfig=0x%x", aConfig)); 691 692 PvmiKvp* kvp = NULL; 693 int numParams = 0; 694 695 // Get data bitrate from peer 696 PVMFStatus status = aConfig->getParametersSync(NULL, (PvmiKeyType)OUTPUT_BITRATE_CUR_QUERY, kvp, numParams, NULL); 697 if (status != PVMFSuccess || !kvp || numParams != 1) 698 { 699 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Bitrate info not available. Use default")); 700 if (iFormat == PVMF_MIME_3GPP_TIMEDTEXT) 701 { 702 iFormatSpecificConfig.iBitrate = PVMF_MP4FFCN_TEXT_BITRATE; 703 } 704 else if (iFormat == PVMF_MIME_AMR_IETF || 705 iFormat == PVMF_MIME_AMRWB_IETF || 706 iFormat == PVMF_MIME_MPEG4_AUDIO) 707 { 708 iFormatSpecificConfig.iBitrate = PVMF_MP4FFCN_AUDIO_BITRATE; 709 } 710 else if (iFormat == PVMF_MIME_H264_VIDEO_MP4 || 711 iFormat == PVMF_MIME_M4V || 712 iFormat == PVMF_MIME_H2631998 || 713 iFormat == PVMF_MIME_H2632000) 714 { 715 iFormatSpecificConfig.iBitrate = PVMF_MP4FFCN_VIDEO_BITRATE; 716 } 717 else 718 { 719 return PVMFErrNotSupported; 720 } 721 } 722 else 723 { 724 iFormatSpecificConfig.iBitrate = kvp[0].value.uint32_value; 725 aConfig->releaseParameters(NULL, kvp, numParams); 726 } 727 kvp = NULL; 728 numParams = 0; 729 730 // Get timescale from peer 731 if (iFormat == PVMF_MIME_AMR_IETF || 732 iFormat == PVMF_MIME_AMRWB_IETF || 733 iFormat == PVMF_MIME_MPEG4_AUDIO) 734 { 735 status = aConfig->getParametersSync(NULL, (PvmiKeyType)OUTPUT_TIMESCALE_CUR_QUERY, kvp, numParams, NULL); 736 if (status != PVMFSuccess || !kvp || numParams != 1) 737 { 738 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Sampling rate info not available. Use default")); 739 iFormatSpecificConfig.iTimescale = PVMF_MP4FFCN_AUDIO_TIMESCALE; 740 } 741 else 742 { 743 iFormatSpecificConfig.iTimescale = kvp[0].value.uint32_value; 744 aConfig->releaseParameters(NULL, kvp, numParams); 745 } 746 kvp = NULL; 747 numParams = 0; 748 749 // Get the sampling rate, number of channels and bits per sample for audio 750 // sampling rate 751 status = aConfig->getParametersSync(NULL, (PvmiKeyType)AUDIO_OUTPUT_SAMPLING_RATE_CUR_QUERY, kvp, numParams, NULL); 752 if (status != PVMFSuccess || !kvp || numParams != 1) 753 { 754 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Sampling rate info not available. Use default")); 755 iFormatSpecificConfig.iSamplingRate = PVMF_MP4FFCN_AUDIO_SAMPLING_RATE; 756 } 757 else 758 { 759 iFormatSpecificConfig.iSamplingRate = kvp[0].value.uint32_value; 760 aConfig->releaseParameters(NULL, kvp, numParams); 761 } 762 kvp = NULL; 763 numParams = 0; 764 765 // number of channels 766 status = aConfig->getParametersSync(NULL, (PvmiKeyType)AUDIO_OUTPUT_NUM_CHANNELS_CUR_QUERY, kvp, numParams, NULL); 767 if (status != PVMFSuccess || !kvp || numParams != 1) 768 { 769 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Number of channels info not available. Use default")); 770 iFormatSpecificConfig.iNumberOfChannels = PVMF_MP4FFCN_AUDIO_NUM_CHANNELS; 771 } 772 else 773 { 774 iFormatSpecificConfig.iNumberOfChannels = kvp[0].value.uint32_value; 775 aConfig->releaseParameters(NULL, kvp, numParams); 776 } 777 kvp = NULL; 778 numParams = 0; 779 780 // bits per sample 781 status = aConfig->getParametersSync(NULL, (PvmiKeyType)AUDIO_OUTPUT_BITS_PER_SAMPLE_CUR_QUERY, kvp, numParams, NULL); 782 if (status != PVMFSuccess || !kvp || numParams != 1) 783 { 784 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Bits per sample info not available. Use default")); 785 iFormatSpecificConfig.iBitsPerSample = PVMF_MP4FFCN_AUDIO_BITS_PER_SAMPLE; 786 } 787 else 788 { 789 iFormatSpecificConfig.iBitsPerSample = kvp[0].value.uint32_value; 790 aConfig->releaseParameters(NULL, kvp, numParams); 791 } 792 kvp = NULL; 793 numParams = 0; 794 } 795 else if (iFormat == PVMF_MIME_H264_VIDEO_MP4 || 796 iFormat == PVMF_MIME_M4V || 797 iFormat == PVMF_MIME_H2631998 || 798 iFormat == PVMF_MIME_H2632000) 799 { 800 if (iFormat == PVMF_MIME_H2631998 || 801 iFormat == PVMF_MIME_H2632000) 802 { 803 iFormatSpecificConfig.iH263Profile = PVMF_MP4FFCN_VIDEO_H263_PROFILE; 804 iFormatSpecificConfig.iH263Level = PVMF_MP4FFCN_VIDEO_H263_LEVEL; 805 // Do not break here. Continue to configure the other video parameters 806 } 807 808 status = aConfig->getParametersSync(NULL, (PvmiKeyType)VIDEO_OUTPUT_WIDTH_CUR_QUERY, kvp, numParams, NULL); 809 if (status != PVMFSuccess || numParams != 1) 810 { 811 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Frame width not available. Use default")); 812 iFormatSpecificConfig.iWidth = PVMF_MP4FFCN_VIDEO_FRAME_WIDTH; 813 } 814 else 815 { 816 iFormatSpecificConfig.iWidth = kvp[0].value.uint32_value; 817 aConfig->releaseParameters(NULL, kvp, numParams); 818 } 819 kvp = NULL; 820 numParams = 0; 821 822 iFormatSpecificConfig.iRateControlType = PVMP4FFCN_RATE_CONTROL_CBR; 823 824 // Get size (in pixels) of video data from peer 825 status = aConfig->getParametersSync(NULL, (PvmiKeyType)VIDEO_OUTPUT_IFRAME_INTERVAL_CUR_QUERY, kvp, numParams, NULL); 826 if (status != PVMFSuccess || numParams != 1) 827 { 828 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Frame width not available. Use default")); 829 iFormatSpecificConfig.iIFrameInterval = PVMF_MP4FFCN_VIDEO_IFRAME_INTERVAL; 830 } 831 else 832 { 833 iFormatSpecificConfig.iIFrameInterval = kvp[0].value.uint32_value; 834 aConfig->releaseParameters(NULL, kvp, numParams); 835 } 836 kvp = NULL; 837 numParams = 0; 838 839 status = aConfig->getParametersSync(NULL, (PvmiKeyType)VIDEO_OUTPUT_HEIGHT_CUR_QUERY, kvp, numParams, NULL); 840 if (status != PVMFSuccess || numParams != 1) 841 { 842 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Frame height info not available. Use default")); 843 iFormatSpecificConfig.iHeight = PVMF_MP4FFCN_VIDEO_FRAME_HEIGHT; 844 } 845 else 846 { 847 iFormatSpecificConfig.iHeight = kvp[0].value.uint32_value; 848 aConfig->releaseParameters(NULL, kvp, numParams); 849 } 850 kvp = NULL; 851 numParams = 0; 852 853 // Get video frame rate from peer 854 status = aConfig->getParametersSync(NULL, (PvmiKeyType)VIDEO_OUTPUT_FRAME_RATE_CUR_QUERY, kvp, numParams, NULL); 855 if (status != PVMFSuccess || numParams != 1) 856 { 857 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Frame rate not available. Use default")); 858 iFormatSpecificConfig.iFrameRate = PVMF_MP4FFCN_VIDEO_FRAME_RATE; 859 } 860 else 861 { 862 // Set input frame rate of container node 863 iFormatSpecificConfig.iFrameRate = kvp[0].value.float_value; 864 aConfig->releaseParameters(NULL, kvp, numParams); 865 } 866 kvp = NULL; 867 numParams = 0; 868 869 status = aConfig->getParametersSync(NULL, (PvmiKeyType)OUTPUT_TIMESCALE_CUR_QUERY, kvp, numParams, NULL); 870 if (status != PVMFSuccess || !kvp || numParams != 1) 871 { 872 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Sampling rate info not available. Use default")); 873 iFormatSpecificConfig.iTimescale = PVMF_MP4FFCN_VIDEO_TIMESCALE; 874 } 875 else 876 { 877 iFormatSpecificConfig.iTimescale = kvp[0].value.uint32_value; 878 aConfig->releaseParameters(NULL, kvp, numParams); 879 } 880 kvp = NULL; 881 numParams = 0; 882 } 883 else if (iFormat == PVMF_MIME_3GPP_TIMEDTEXT) 884 { 885 // Get size (in pixels) of Text data from peer 886 status = aConfig->getParametersSync(NULL, (PvmiKeyType)TEXT_INPUT_WIDTH_CUR_QUERY, kvp, numParams, NULL); 887 if (status != PVMFSuccess || numParams != 1) 888 { 889 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Frame width not available. Use default")); 890 iFormatSpecificConfig.iWidth = PVMF_MP4FFCN_TEXT_FRAME_WIDTH; 891 } 892 else 893 { 894 iFormatSpecificConfig.iWidth = kvp[0].value.uint32_value; 895 aConfig->releaseParameters(NULL, kvp, numParams); 896 } 897 kvp = NULL; 898 numParams = 0; 899 900 status = aConfig->getParametersSync(NULL, (PvmiKeyType)TEXT_INPUT_HEIGHT_CUR_QUERY, kvp, numParams, NULL); 901 if (status != PVMFSuccess || numParams != 1) 902 { 903 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Frame height info not available. Use default")); 904 iFormatSpecificConfig.iHeight = PVMF_MP4FFCN_TEXT_FRAME_HEIGHT; 905 } 906 else 907 { 908 iFormatSpecificConfig.iHeight = kvp[0].value.uint32_value; 909 aConfig->releaseParameters(NULL, kvp, numParams); 910 } 911 kvp = NULL; 912 numParams = 0; 913 914 status = aConfig->getParametersSync(NULL, (PvmiKeyType)OUTPUT_TIMESCALE_CUR_QUERY, kvp, numParams, NULL); 915 if (status != PVMFSuccess || !kvp || numParams != 1) 916 { 917 LOG_DEBUG((0, "PVMp4FFComposerPort::GetInputParametersFromPeer: Sampling rate info not available. Use default")); 918 iFormatSpecificConfig.iTimescale = PVMF_MP4FFCN_TEXT_TIMESCALE; 919 } 920 else 921 { 922 iFormatSpecificConfig.iTimescale = kvp[0].value.uint32_value; 923 aConfig->releaseParameters(NULL, kvp, numParams); 924 } 925 kvp = NULL; 926 numParams = 0; 927 } 928 else 929 { 930 return PVMFErrNotSupported; 931 } 932 933 return PVMFSuccess; 934 } 935 936 937 938 939 940 941 942