Home | History | Annotate | Download | only in src
      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