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 #include  <stdlib.h>
     19 #include <string.h>
     20 #include "cpvh223multiplex.h"
     21 #include "media_packet.h"
     22 #include "media_fragment.h"
     23 #include "lowerlayer.h"
     24 #include "logicalchannel.h"
     25 #include "adaptationlayer.h"
     26 #include "muxtbl.h"
     27 #include "h223.h"
     28 
     29 /* Default sizes for outgoing SDUs */
     30 #define DEF_AL1_SDU_SIZE 1024
     31 #define DEF_AL2_SDU_SIZE 256
     32 #define DEF_AL3_SDU_SIZE 256
     33 
     34 /* Default sizes for incoming SDUs */
     35 #define DEF_AL1_SDU_SIZE_R 1024
     36 #define DEF_AL2_SDU_SIZE_R 256
     37 #define DEF_AL3_SDU_SIZE_R 256
     38 
     39 #define MIN_SEGMENTABLE_SDU_SIZE 256
     40 #define MAX_NONSEGMENTABLE_SDU_SIZE 128  /* Implementers guide notes that not more than 3 frames of audio per pdu*/
     41 #define DEF_CHANNEL_BITRATE 64000
     42 #define DEF_OUTGOING_MEDIA_QUEUE_SIZE_MS 2000
     43 #define DEF_MIN_SAMPLE_INTERVAL 20
     44 
     45 #define GET_SDU_DATA_LIST(segmentable)\
     46  segmentable?iSegmentableSduDataList:iNonSegmentableSduDataList
     47 
     48 #define PV_H223_DEF_SAMPLE_INTERVAL 20
     49 #define H223_LCN_DATA_DETECT_THRESHOLD 1
     50 #define PV_H223_DEF_MULTPLEXING_DELAY_INTERVAL 0
     51 #define PV_H223_INTERLEAVING_FLAG_SEND_FREQUENCY 10
     52 
     53 #define H223_LOWERLAYER_PORT_TAG PV_MULTIPLEXED
     54 
     55 /** Change this to force the queue size for number of outgoing media data.  Otherwise, it is calculated
     56     based on bitrate, sample rate and sdu size */
     57 //#define FORCE_NUM_OUTGOING_MEDIA_DATA 150
     58 
     59 CPVH223Multiplex::CPVH223Multiplex(TPVLoopbackMode aLoopbackMode)
     60         : iLowerLayer(NULL),
     61         iMuxTblMgr(NULL),
     62         iLoopbackMode(aLoopbackMode),
     63         iDummyFragment(NULL),
     64         iMediaDataImplMemAlloc(NULL),
     65         iMuxPduPacketAlloc(NULL),
     66         iClock(NULL),
     67         iInterleavingMultiplexFlagsSize(0),
     68         iInterleavingMultiplexFlags(NULL)
     69 {
     70     iMuxTblMgr = OSCL_NEW(MuxTableMgr, ());
     71 
     72     iState = false;
     73     iLcnsWithData = 0;
     74     iStuffOnlyFirstSend = false;
     75     for (int n = 0; n < MAX_LCNS; n++)
     76     {
     77         iALIndex[n] = 0;
     78     }
     79 
     80     Init();
     81 
     82     ResetStats();
     83 }
     84 
     85 CPVH223Multiplex::~CPVH223Multiplex()
     86 {
     87     OSCL_DELETE(iMuxTblMgr);
     88     iMuxTblMgr = NULL;
     89 }
     90 
     91 void CPVH223Multiplex::Init()
     92 {
     93     iAlSduSize[0] = iMaxAlSduSize[0] = iMaxAlSduSizeR[0] = 0;
     94     iAlSduSizeR[0] = 0;
     95     iAlSduSize[1] = iMaxAlSduSize[1] = DEF_AL1_SDU_SIZE;
     96     iAlSduSize[2] = iMaxAlSduSize[2] = DEF_AL2_SDU_SIZE;
     97     iAlSduSize[3] = iMaxAlSduSize[3] = DEF_AL3_SDU_SIZE;
     98     iAlSduSizeR[1] = iMaxAlSduSizeR[1] = DEF_AL1_SDU_SIZE_R;
     99     iAlSduSizeR[2] = iMaxAlSduSizeR[2] = DEF_AL2_SDU_SIZE_R;
    100     iAlSduSizeR[3] = iMaxAlSduSizeR[3] = DEF_AL3_SDU_SIZE_R;
    101     iLcnEnd = NULL;
    102     iState = false;
    103     iLcnsWithData = 0;
    104     ClearSduDataLists();
    105     for (int n = 0; n < MAX_LCNS; n++)
    106     {
    107         iALIndex[n] = 0;
    108     }
    109     iALIndex[0] = AdaptationLayerAlloc::GetAlIndex(E_EP_LOW);
    110     iBitrate = DEFAULT_BITRATE;
    111     iMinSampleInterval = PV_H223_DEF_SAMPLE_INTERVAL;
    112     iNumMuxIntervalsPerTimerInterval = 0;
    113     iNumBytesPerMinSampleInterval = 0;
    114     iMultiplexingDelayMs = PV_H223_DEF_MULTPLEXING_DELAY_INTERVAL;
    115     TimeValue time_now;
    116     iRand.Seed(time_now.to_msec());
    117     iInLogicalChannelBufferingMs = 0;
    118     iOutLogicalChannelBufferingMs = 0;
    119     iFmStuffingRepeatInterval = 0;
    120     iFmStuffingMode = 0;
    121     iLevelSetupComplete = false;
    122     iEnableStuffing = true;
    123     iInterleavingMultiplexFlagsSize = 0;
    124 }
    125 
    126 int CPVH223Multiplex::GetMinTimerRes()
    127 {
    128     return iLowerLayer->GetMinTimerRes();
    129 }
    130 
    131 void CPVH223Multiplex::SetLoopbackMode(TPVLoopbackMode aLoopbackMode)
    132 {
    133     iLoopbackMode = aLoopbackMode;
    134     iLowerLayer->SetLoopbackMode(iLoopbackMode);
    135 }
    136 
    137 TPVStatusCode CPVH223Multiplex::SetTimerRes(uint32 timer_res)
    138 {
    139     return iLowerLayer->SetTimerRes(timer_res);
    140 }
    141 
    142 TPVStatusCode CPVH223Multiplex::Open()
    143 {
    144     iLogger = PVLogger::GetLoggerObject("3g324m.h223");
    145     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::Open"));
    146 
    147     iLcnEnd = NULL;
    148 
    149     for (unsigned out_lcn = 0; out_lcn < iOutgoingChannels.size(); out_lcn++)
    150     {
    151         iOutgoingChannels[out_lcn].Unbind();
    152     }
    153     for (unsigned in_lcn = 0; in_lcn < iIncomingChannels.size(); in_lcn++)
    154     {
    155         iIncomingChannels[in_lcn].Unbind();
    156     }
    157 
    158     iLowerLayer = OSCL_NEW(H223LowerLayer, (H223_LOWERLAYER_PORT_TAG, iLoopbackMode));
    159     iLowerLayer->SetObserver(this);
    160     iLowerLayer->Open();
    161 
    162     UpdateMuxInterval(DEF_MIN_SAMPLE_INTERVAL);
    163 
    164     uint16 pdu_rate = (uint16)((2000.0 / (float)iMinSampleInterval + .5) + 1); /* For audio and video */
    165     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::Open pdu_rate=%d", pdu_rate));
    166     iMediaDataImplMemAlloc = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (pdu_rate));
    167     if (iMediaDataImplMemAlloc == NULL)
    168     {
    169         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    170                         (0, "CPVH223Multiplex::Open() Failed to allocate iMediaDataImplMemAlloc"));
    171         OSCL_LEAVE(PVMFErrNoMemory);
    172     }
    173     iMediaDataImplMemAlloc->enablenullpointerreturn();
    174 
    175     iMuxPduPacketAlloc = OSCL_NEW(PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>, (pdu_rate, MAX_FRAGMENTS_PER_H223_PDU_PACKET, iMediaDataImplMemAlloc));
    176     if (iMuxPduPacketAlloc == NULL)
    177     {
    178         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    179                         (0, "CPVH223Multiplex::Open() Failed to allocate iMuxPduPacketAlloc"));
    180         OSCL_LEAVE(PVMFErrNoMemory);
    181     }
    182     iMuxPduPacketAlloc->create();
    183 
    184     iLcnsWithData = 0;
    185     return EPVT_Success;
    186 }
    187 
    188 int CPVH223Multiplex::Start(H223PduParcomSharedPtr parcom)
    189 {
    190     int ret = 1;
    191     iState = true;
    192     iPduNum = 0;
    193     iLevelSetupComplete = false;
    194     iEnableStuffing = true;
    195     OSCL_ASSERT(iOutgoingChannels[0].GetRep());
    196     OSCL_ASSERT(iIncomingChannels[0].GetRep());
    197     ret = iLowerLayer->Start(parcom);
    198     //SetStuffingMsgHeader();
    199     return ret;
    200 }
    201 
    202 TPVStatusCode CPVH223Multiplex::Close()
    203 {
    204     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::Close"));
    205     if (iInterleavingMultiplexFlags && iInterleavingPacket)
    206     {
    207         iInterleavingPacket->clearMediaFragments();
    208         iInterleavingPacket.Unbind();
    209         OSCL_DEFAULT_FREE(iInterleavingMultiplexFlags);
    210         iInterleavingMultiplexFlags = NULL;
    211     }
    212 
    213     for (unsigned out_lcn = 0; out_lcn < iOutgoingChannels.size(); out_lcn++)
    214     {
    215         CloseChannel(OUTGOING, iOutgoingChannels[out_lcn]->GetLogicalChannelNumber());
    216     }
    217     for (unsigned in_lcn = 0; in_lcn < iIncomingChannels.size(); in_lcn++)
    218     {
    219         CloseChannel(INCOMING, iIncomingChannels[in_lcn]->GetLogicalChannelNumber());
    220     }
    221     if (iLowerLayer)
    222     {
    223         iLowerLayer->Disconnect();
    224         iLowerLayer->Close();
    225         OSCL_DELETE(iLowerLayer);
    226         iLowerLayer = NULL;
    227     }
    228 
    229     iMuxPduPacketAlloc->removeRef();
    230     OSCL_DELETE(iMediaDataImplMemAlloc);
    231     return EPVT_Success;
    232 }
    233 
    234 int CPVH223Multiplex::Stop()
    235 {
    236     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::Stop"));
    237 
    238     iState = false;
    239     iLcnEnd = NULL;
    240 
    241     iOutgoingChannels[0]->Flush();
    242     iIncomingChannels[0]->Flush();
    243 
    244     iNonSegmentableSduDataList.clear();
    245     iSegmentableSduDataList.clear();
    246     iControlSduDataList.clear();
    247 
    248     iLowerLayer->Stop();
    249 
    250     return 1;
    251 }
    252 
    253 
    254 void CPVH223Multiplex::DataReceptionStart()
    255 {
    256     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::DataReceptionStart()"));
    257     iObserver->DataReceptionStart();
    258 }
    259 void CPVH223Multiplex::LevelSetupComplete(PVMFStatus status, TPVH223Level level)
    260 {
    261     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::LevelSetupComplete - status=%d, level=%d", status, level));
    262     if (iInterleavingMultiplexFlags && iInterleavingPacket)
    263     {
    264         iInterleavingPacket->clearMediaFragments();
    265         iInterleavingPacket.Unbind();
    266         OSCL_DEFAULT_FREE(iInterleavingMultiplexFlags);
    267         iInterleavingMultiplexFlags = NULL;
    268         iInterleavingMultiplexFlagsSize = 0;
    269     }
    270     if (status == PVMFPending)
    271     {
    272         EnableStuffing(true);
    273     }
    274     else
    275     {
    276         iLevelSetupComplete = true;
    277     }
    278     //SetStuffingMsgHeader();
    279     iObserver->MuxSetupComplete(status, level);
    280 }
    281 
    282 uint32 CPVH223Multiplex::MuxPduIndicate(uint8* pPdu, uint32 sz, int32 fClosing, int32 muxCode)
    283 {
    284     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::MuxPduIndicate mux code=%d, closing=%d, size=%d", muxCode, fClosing, sz));
    285     int ret = MuxToALDispatch(pPdu, sz, fClosing, muxCode);
    286     return (uint16)ret;
    287 }
    288 
    289 void CPVH223Multiplex::MuxPduErrIndicate(EMuxPduError err)
    290 {
    291     OSCL_UNUSED_ARG(err);
    292     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::MuxPduErrIndicate - err(%d)", err));
    293     iObserver->MuxErrorOccurred(INCOMING, PV_MUX_COMPONENT_MUX, PVMFErrCorrupt);
    294 }
    295 
    296 void CPVH223Multiplex::MuxSetupComplete(PVMFStatus status, TPVH223Level level)
    297 {
    298     OSCL_UNUSED_ARG(status);
    299     OSCL_UNUSED_ARG(level);
    300 }
    301 
    302 unsigned CPVH223Multiplex::DispatchPduPacket(MuxPduPacketList& packets,
    303         MuxSduData& mux_sdu_data,
    304         PS_MultiplexEntryDescriptor mux_entry,
    305         uint32 max_size)
    306 {
    307     OSCL_ASSERT(mux_entry->size_of_elementList == 1);
    308     OsclSharedPtr<PVMFMediaDataImpl> packet = InitPduPacket();
    309 
    310     if (!packet.GetRep())
    311     {
    312         return 0;
    313     }
    314 
    315     int pm = false;
    316     MakePduData(packet,
    317                 max_size - iLowerLayer->GetHeaderSize(),
    318                 mux_entry->elementList,
    319                 mux_sdu_data,
    320                 &pm);
    321     if (CompletePduPacket(packet, mux_entry->multiplexTableEntryNumber, pm) == PVMFSuccess)
    322     {
    323         packets.push_back(packet);
    324         return packet->getFilledSize();
    325     }
    326     return 0;
    327 }
    328 
    329 /* Called by lower layer to get the next mux pdu to dispatch. */
    330 PVMFStatus CPVH223Multiplex::GetOutgoingMuxPdus(MuxPduPacketList& packets)
    331 {
    332     unsigned cur_pdus_size = 0;
    333     uint16 stuffing_size = (uint16)iLowerLayer->GetStuffingSize();
    334     OsclSharedPtr<PVMFMediaDataImpl> pkt;
    335 
    336     for (unsigned n = 0; n < iNumMuxIntervalsPerTimerInterval; n++)
    337     {
    338         // fill the sdu data lists with lcns that contain data
    339         UpdateSduDataLists();
    340 
    341         int32 max_pdus_size = iNumBytesPerMinSampleInterval;
    342 
    343         if (iInterleavingPacket &&
    344                 iInterleavingPacket.GetRep() &&
    345                 iInterleavingPacket->getFilledSize() &&
    346                 iInterleavingMultiplexFlags &&
    347                 ((iPduNum % PV_H223_INTERLEAVING_FLAG_SEND_FREQUENCY) == 0))
    348         {
    349             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::GetOutgoingMuxPdus Adding interleaving packet."));
    350             iInterleavingPacket->clearMediaFragments();
    351             OsclRefCounterMemFrag frag;
    352             frag.getMemFrag().len = iInterleavingMultiplexFlagsSize;
    353             frag.getMemFrag().ptr = iInterleavingMultiplexFlags;
    354             iInterleavingPacket->appendMediaFragment(frag);
    355             packets.push_back(iInterleavingPacket);
    356             max_pdus_size -= iInterleavingPacket->getFilledSize();
    357         }
    358 
    359         if (iLowerLayer->GetLevel() == H223_LEVEL0)
    360         {
    361             if (n == 0)
    362             {
    363                 pkt = iMuxPduPacketAlloc->allocate(1);
    364                 if (!pkt)
    365                 {
    366                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    367                                     (0, "CPVH223Multiplex::GetOutgoingMuxPdus Unable to allocate packet."));
    368                     return PVMFErrNoMemory;
    369                 }
    370                 iLowerLayer->DoStuffing(iLowerLayer->GetLevel(), pkt, 5);
    371                 packets.push_back(pkt);
    372                 max_pdus_size -= pkt->getFilledSize();
    373             }
    374         }
    375         iPduNum++;
    376 
    377         /* Mux non segmentable data */
    378         cur_pdus_size = MuxLcnData(GET_SDU_DATA_LIST(false),
    379                                    packets,
    380                                    (uint16)OSCL_MIN(max_pdus_size, (int)iLowerLayer->GetPduSize()));
    381         max_pdus_size -= cur_pdus_size;
    382         if (max_pdus_size < (int)iLowerLayer->GetHeaderSize())
    383         {
    384             return PVMFSuccess;
    385         }
    386 
    387         /* Mux control data untill current pdu is filled up */
    388         do
    389         {
    390             cur_pdus_size = MuxLcnData(iControlSduDataList, packets, (uint16)iLowerLayer->GetPduSize());
    391             max_pdus_size -= cur_pdus_size;
    392         }
    393         while (max_pdus_size > (int)iLowerLayer->GetHeaderSize() &&
    394                 cur_pdus_size);
    395 
    396         if (max_pdus_size < (int)iLowerLayer->GetHeaderSize())
    397         {
    398             return PVMFSuccess;
    399         }
    400 
    401         /* Mux segmentable data untill current pdu is filled up */
    402         do
    403         {
    404             cur_pdus_size = MuxLcnData(GET_SDU_DATA_LIST(true),
    405                                        packets,
    406                                        (uint16)OSCL_MIN(max_pdus_size, (int)iLowerLayer->GetPduSize()));
    407             max_pdus_size -= cur_pdus_size;
    408         }
    409         while (max_pdus_size > (int)iLowerLayer->GetHeaderSize() &&
    410                 cur_pdus_size);
    411 
    412         /* Fill stuffing if space remains in pdu.*/
    413         if (iEnableStuffing)
    414         {
    415             if (!iStuffOnlyFirstSend || (iPduNum == 1))
    416             {
    417                 stuffing_size = (uint16)((max_pdus_size > stuffing_size) ? max_pdus_size : stuffing_size);
    418             }
    419         }
    420         pkt = iMuxPduPacketAlloc->allocate(1);
    421         if (!pkt)
    422         {
    423             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    424                             (0, "CPVH223Multiplex::GetOutgoingMuxPdus Unable to allocate packet."));
    425             return PVMFErrNoMemory;
    426         }
    427         iLowerLayer->DoStuffing(iLowerLayer->GetLevel(), pkt, stuffing_size);
    428 
    429         if (pkt->getFilledSize())
    430         {
    431             packets.push_back(pkt);
    432         }
    433         else
    434         {
    435             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::GetOutgoingMuxPdus WARNING Failed to send single stuffing"));
    436             return PVMFErrNoMemory;
    437         }
    438     }
    439     return PVMFSuccess;
    440 }
    441 
    442 
    443 
    444 TPVStatusCode CPVH223Multiplex::SetMaxOutgoingPduSize(uint16 Size)
    445 {
    446     return iLowerLayer->SetMaxOutgoingPduSize(Size);
    447 }
    448 
    449 TPVStatusCode CPVH223Multiplex::SetSduSize(TPVDirection direction, uint16 size, ErrorProtectionLevel_t epl)
    450 {
    451     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux: Set sdu size - direction(%d), size(%d), epl(%d)\n", direction, size, epl));
    452     if (direction == OUTGOING)
    453     {
    454         if (iAlSduSize[epl] > size)
    455         {
    456             iAlSduSize[epl] = size;
    457         }
    458     }
    459     else
    460     {
    461         if (iAlSduSizeR[epl] > size)
    462         {
    463             iAlSduSizeR[epl] = size;
    464         }
    465     }
    466 
    467     return EPVT_Success;
    468 }
    469 
    470 
    471 uint16 CPVH223Multiplex::GetSduSize(TPVDirection direction, ErrorProtectionLevel_t epl)
    472 {
    473     if (direction == OUTGOING)
    474     {
    475         return (uint16)iAlSduSize[epl];
    476     }
    477     return (uint16)iAlSduSizeR[epl];
    478 }
    479 
    480 uint16 CPVH223Multiplex::GetMaxSduSize(TPVDirection direction, ErrorProtectionLevel_t epl)
    481 {
    482     if (direction == OUTGOING)
    483     {
    484         return (uint16)iMaxAlSduSize[epl];
    485     }
    486     return (uint16)iMaxAlSduSizeR[epl];
    487 }
    488 
    489 
    490 TPVStatusCode CPVH223Multiplex::SetMuxLevel(TPVH223Level muxLevel)
    491 {
    492     TPVStatusCode ret = EPVT_Success;
    493 //  iMutex->Lock();
    494     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux: Set Level request (%d)\n", muxLevel));
    495     ret = iLowerLayer->SetLevel(muxLevel);
    496 //  iMutex->Unlock();
    497     return ret;
    498 }
    499 
    500 
    501 TPVH223Level CPVH223Multiplex::GetMuxLevel()
    502 {
    503     return iLowerLayer->GetLevel();
    504 }
    505 
    506 PVMFPortInterface* CPVH223Multiplex::GetLowerLayer()
    507 {
    508     return iLowerLayer;
    509 }
    510 
    511 TPVStatusCode CPVH223Multiplex::SetIncomingMuxTableEntries(CPVMultiplexDescriptor* descriptor)
    512 {
    513 //  iMutex->Lock();
    514     iMuxTblMgr->SetIncomingDescriptors(descriptor->GetDescriptor());
    515 //  iMutex->Unlock();
    516 
    517     return EPVT_Success;
    518 }
    519 
    520 void CPVH223Multiplex::SetIncomingMuxDescriptors(CPVMultiplexEntryDescriptorVector& descriptors, bool replace)
    521 {
    522     iMuxTblMgr->SetIncomingMuxDescriptors(descriptors, replace);
    523 }
    524 
    525 void CPVH223Multiplex::SetOutgoingMuxDescriptors(CPVMultiplexEntryDescriptorVector& descriptors)
    526 {
    527     iMuxTblMgr->SetOutgoingMuxDescriptors(descriptors);
    528 }
    529 
    530 void CPVH223Multiplex::RemoveOutgoingMuxDescriptor(uint8 muxTblNum)
    531 {
    532     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::RemoveOutgoingMuxDescriptor muxTblNum(%d)", muxTblNum));
    533     iMuxTblMgr->RemoveOutgoingMuxDescriptor(muxTblNum);
    534 }
    535 
    536 void CPVH223Multiplex::RemoveIncomingMuxDescriptor(uint8 muxTblNum)
    537 {
    538     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::RemoveIncomingMuxDescriptor muxTblNum(%d)", muxTblNum));
    539     iMuxTblMgr->RemoveIncomingMuxDescriptor(muxTblNum);
    540 }
    541 
    542 PS_MultiplexEntryDescriptor CPVH223Multiplex::GetIncomingMuxDescriptor(uint16 muxTblNum)
    543 {
    544     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::GetIncomingMuxDescriptor muxTblNum(%d)", muxTblNum));
    545     return iMuxTblMgr->GetIncomingDescriptor((uint8)muxTblNum);
    546 }
    547 
    548 PVMFStatus CPVH223Multiplex::GetOutgoingChannel(TPVChannelId id, H223OutgoingChannelPtr& channel)
    549 {
    550     if (id == CHANNEL_ID_UNKNOWN)
    551     {
    552         return PVMFErrArgument;
    553     }
    554     for (TPVChannelId index = 0; index < iOutgoingChannels.size(); index++)
    555     {
    556         if (iOutgoingChannels[index]->GetLogicalChannelNumber() == id)
    557         {
    558             channel = iOutgoingChannels[index];
    559             return PVMFSuccess;
    560         }
    561     }
    562     return PVMFErrArgument;
    563 }
    564 
    565 PVMFStatus CPVH223Multiplex::GetIncomingChannel(TPVChannelId id, H223IncomingChannelPtr& channel)
    566 {
    567     if (id == CHANNEL_ID_UNKNOWN)
    568     {
    569         return PVMFErrArgument;
    570     }
    571     for (TPVChannelId index = 0; index < iIncomingChannels.size(); index++)
    572     {
    573         if (iIncomingChannels[index]->GetLogicalChannelNumber() == id)
    574         {
    575             channel = iIncomingChannels[index];
    576             return PVMFSuccess;
    577         }
    578     }
    579     return PVMFErrArgument;
    580 }
    581 
    582 TPVStatusCode CPVH223Multiplex::GetAdaptationLayer(OsclSharedPtr<AdaptationLayer> &al,
    583         TPVDirection aDirection,
    584         PS_H223LogicalChannelParameters aH223lcnParams,
    585         int32 aSdu_size,
    586         uint32 aNum_media_data)
    587 {
    588     al = AdaptationLayerAlloc::GetAdaptationLayer(aDirection,
    589             aH223lcnParams, (uint16)aSdu_size, aNum_media_data);
    590     if (!al)
    591     {
    592         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    593                         (0, "CPVH223Multiplex::GetAdaptationLayer - Memory allocation failure on StartAlPdu\n"));
    594         return EPVT_Failed;
    595     }
    596     return EPVT_Success;
    597 }
    598 
    599 TPVStatusCode CPVH223Multiplex::OpenChannel(TPVDirection direction,
    600         TPVChannelId channel_id,
    601         H223ChannelParam* h223params)
    602 {
    603     TPVStatusCode ret = EPVT_Success;
    604     OSCL_ASSERT(h223params);
    605 
    606     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    607                     (0, "CPVH223Multiplex::OpenChannel direction(%d), id(%d)\n", direction, channel_id));
    608     PS_H223LogicalChannelParameters h223lcnParams = h223params->GetLcnParams();
    609     H223LogicalChannel* channel = NULL;
    610 
    611     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    612                     (0, "CPVH223Multiplex::OpenChannel -  AL index(%d)", h223lcnParams->adaptationLayerType.index));
    613 
    614     /* Set the port property */
    615     // TODO - Gkl
    616     /*PVMFPortProperty aProps;
    617     aProps.iFormatType = PVCodecTypeToPVMFFormatType(GetCodecType(h223params->GetDataType()));
    618     aProps.iPortType = PORT_TYPE_FOR_DIRECTION(direction);*/
    619     int* sdu_sizes = (direction == OUTGOING) ? iAlSduSize : iAlSduSizeR;
    620     int32 sdu_size = 0;
    621     switch (h223lcnParams->adaptationLayerType.index)
    622     {
    623         case 1:
    624         case 2:
    625             sdu_size = sdu_sizes[1];
    626             break;
    627         case 3:
    628         case 4:
    629             sdu_size = sdu_sizes[2];
    630             break;
    631         case 5:
    632             sdu_size = sdu_sizes[3];
    633             break;
    634         default:
    635             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::OpenChannel ERROR - Invalid AL Index.\n"));
    636             return EPVT_Failed;
    637     }
    638     /* Overwrite audio sdu size, otherwise audio memory allocation can become prohibitive*/
    639     if (!h223lcnParams->segmentableFlag)
    640     {
    641         sdu_size = MAX_NONSEGMENTABLE_SDU_SIZE;
    642     }
    643     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::OpenChannel -  SDU Size=%d", sdu_size));
    644 
    645     int bitrate = (h223params->GetBitrate() > 0) ? h223params->GetBitrate() : DEF_CHANNEL_BITRATE;
    646     uint16 sample_interval = (uint16)h223params->GetSampleInterval();
    647     uint32 min_sdu_size = (direction == INCOMING && h223lcnParams->segmentableFlag) ? sdu_size = MIN_SEGMENTABLE_SDU_SIZE : sdu_size;
    648     uint32 num_media_data = (uint32)((double)(bitrate * DEF_OUTGOING_MEDIA_QUEUE_SIZE_MS) / double(1000.0 * 8.0 * min_sdu_size / 2.0) + .99);
    649     if (h223lcnParams->segmentableFlag && sample_interval)
    650     {
    651         num_media_data += (uint32)((double)DEF_OUTGOING_MEDIA_QUEUE_SIZE_MS / (double)sample_interval + 1);
    652     }
    653     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::OpenChannel bitrate=%d, sample_interval=%d, num_media_data=%d", bitrate, sample_interval, num_media_data));
    654 
    655 #if defined(FORCE_NUM_OUTGOING_MEDIA_DATA)
    656     if (direction == OUTGOING)
    657     {
    658         num_media_data = FORCE_NUM_OUTGOING_MEDIA_DATA;
    659         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::OpenChannel Forcing outgoing num_media_data=%d", num_media_data));
    660     }
    661 #endif
    662 
    663     OsclSharedPtr<AdaptationLayer> al;
    664     if (EPVT_Success != GetAdaptationLayer(al, direction,
    665                                            h223lcnParams, (uint16)sdu_size, num_media_data))
    666     {
    667         return EPVT_Failed;
    668     }
    669 
    670     if (direction == OUTGOING)
    671     {
    672         void* ptr = NULL;
    673         if (channel_id)
    674         {
    675             ptr = OSCL_DEFAULT_MALLOC(sizeof(H223OutgoingChannel));
    676             channel = new(ptr) H223OutgoingChannel((uint16)channel_id,
    677                                                    h223lcnParams->segmentableFlag, al, h223params->GetDataType(), this,
    678                                                    bitrate, sample_interval, num_media_data);
    679         }
    680         else
    681         {
    682             ptr = OSCL_DEFAULT_MALLOC(sizeof(H223OutgoingControlChannel));
    683             channel =  new(ptr) H223OutgoingControlChannel(al,
    684                     h223params->GetDataType(), this, bitrate, sample_interval,
    685                     num_media_data);
    686         }
    687 
    688         OsclRefCounterSA<Oscl_TAlloc<H223OutgoingChannel, BasicAlloc> > *channelRefCounter =
    689             new OsclRefCounterSA<Oscl_TAlloc<H223OutgoingChannel, BasicAlloc> >(ptr);
    690         OsclSharedPtr<H223OutgoingChannel> channel_ptr((H223OutgoingChannel*)channel,
    691                 channelRefCounter);
    692         iOutgoingChannels.push_back(channel_ptr);
    693         UpdateMuxInterval();
    694         if (channel_id)
    695             channel_ptr->BufferMedia(iMultiplexingDelayMs);
    696     }
    697     else
    698     {
    699         void* ptr = OSCL_DEFAULT_MALLOC(sizeof(H223IncomingChannel));
    700         channel = new(ptr)H223IncomingChannel(channel_id,
    701                                               h223lcnParams->segmentableFlag, al,
    702                                               h223params->GetDataType(), this,
    703                                               bitrate, sample_interval, num_media_data);
    704         OsclRefCounterSA<Oscl_TAlloc<H223IncomingChannel, BasicAlloc> > *channelRefCounter =
    705             new OsclRefCounterSA<Oscl_TAlloc<H223IncomingChannel, BasicAlloc> >(ptr);
    706         OsclSharedPtr<H223IncomingChannel> channel_ptr((H223IncomingChannel*)channel, channelRefCounter);
    707         iIncomingChannels.push_back(channel_ptr);
    708     }
    709     channel->Init();
    710     // TODO - Gkl
    711     channel->SetClock(iClock);
    712     //channel->Configure(aProps);
    713 
    714     uint8* fsi = NULL;
    715     unsigned fsi_len = 0;
    716     fsi_len = h223params->GetFormatSpecificInfo(fsi);
    717     if (fsi_len)
    718     {
    719         channel->SetFormatSpecificInfo(fsi, (uint16)fsi_len);
    720     }
    721     return ret;
    722 }
    723 
    724 
    725 TPVStatusCode
    726 CPVH223Multiplex::CloseChannel(TPVDirection direction, TPVChannelId channel_id)
    727 {
    728     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux: Close channel direction(%d), id(%d)\n", direction, channel_id));
    729     OsclSharedPtr<H223OutgoingChannel> outgoing_channel;
    730     bool found_channel = false;
    731 
    732     if (direction == OUTGOING)
    733     {
    734         Oscl_Vector<OsclSharedPtr<H223OutgoingChannel>, OsclMemAllocator>::iterator iter = iOutgoingChannels.begin();
    735         while (iter != iOutgoingChannels.end())
    736         {
    737             outgoing_channel = *iter;
    738             if (outgoing_channel->GetLogicalChannelNumber() == channel_id)
    739             {
    740                 iOutgoingChannels.erase(iter);
    741                 found_channel = true;
    742                 break;
    743             }
    744             iter++;
    745         }
    746         if (!found_channel)
    747         {
    748             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux: Close channel - Failed to lookup channel\n"));
    749             return EPVT_Failed;
    750         }
    751 
    752         /* Release any SDU that the channel has passed to mux */
    753         MuxSduData* sdu_data_ptr = FindMuxSduData(channel_id, outgoing_channel->IsSegmentable());
    754         if (sdu_data_ptr)
    755         {
    756             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::CloseChannel - Releasing pending MUX SDU\n"));
    757             outgoing_channel->ReleasePacket(sdu_data_ptr->sdu);
    758             RemoveMuxSduData(channel_id, outgoing_channel->IsSegmentable());
    759         }
    760 
    761         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::CloseChannel - Successful\n"));
    762         return EPVT_Success;
    763     }
    764     if (iLcnEnd && (iLcnEnd->GetLogicalChannelNumber() == channel_id))
    765     {
    766         iLcnEnd = NULL;
    767     }
    768     OsclSharedPtr<H223IncomingChannel> incoming_channel;
    769     Oscl_Vector<OsclSharedPtr<H223IncomingChannel>, OsclMemAllocator>::iterator iter = iIncomingChannels.begin();
    770 
    771     while (iter != iIncomingChannels.end())
    772     {
    773         incoming_channel = *iter;
    774         if (incoming_channel->GetLogicalChannelNumber() == channel_id)
    775         {
    776             iIncomingChannels.erase(iter);
    777             found_channel = true;
    778             break;
    779         }
    780         iter++;
    781     }
    782     if (!found_channel)
    783     {
    784         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux: Close channel - Failed to lookup channel\n"));
    785         return EPVT_Failed;
    786     }
    787     UpdateMuxInterval();
    788     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::CloseChannel - Successful\n"));
    789     return EPVT_Success;
    790 }
    791 
    792 void CPVH223Multiplex::MakePduData(
    793     OsclSharedPtr<PVMFMediaDataImpl>& outgoingPkt,
    794     int32 max_size,
    795     PS_MultiplexElement pElement,
    796     MuxSduData& mux_sdu_data,
    797     int* pm)
    798 {
    799     *pm = false;
    800 
    801     PVMFSharedMediaDataPtr& sdu_pkt = mux_sdu_data.sdu;
    802     int bytesToMux = mux_sdu_data.size;
    803     //OSCL_ASSERT(bytesToMux);
    804 
    805     OsclRefCounterMemFrag frag;
    806     uint8* pSduFrag = NULL;
    807     int bytesInCurFragment = 0;
    808 
    809     if (pElement->repeatCount.index == 0)   /* finite */
    810     {
    811         bytesToMux = OSCL_MIN(pElement->repeatCount.finite, bytesToMux);
    812     }
    813 
    814     /* dont exceed avail space on PDU */
    815     bytesToMux = OSCL_MIN(max_size, bytesToMux);
    816     if (bytesToMux < 0)
    817     {
    818         OSCL_ASSERT(0);
    819     }
    820     //PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"MakePduData - lcn(%d), bytesToMux(%d)", pElement->muxType.logicalChannelNumber, bytesToMux));
    821     while (bytesToMux > 0)
    822     {
    823         int n = 0;
    824         sdu_pkt->getMediaFragment(mux_sdu_data.cur_frag_num, frag);
    825         bytesInCurFragment = frag.getMemFragSize() - mux_sdu_data.cur_pos;
    826 
    827         pSduFrag = (uint8*)frag.getMemFragPtr() + mux_sdu_data.cur_pos;
    828         n = min2(bytesToMux, bytesInCurFragment);
    829 
    830         /* create a snapshot of size n */
    831         frag.getMemFrag().ptr = pSduFrag;
    832         frag.getMemFrag().len = n;
    833         /* add it to outgoing pkt */
    834         outgoingPkt->appendMediaFragment(frag);
    835         bytesToMux -= n;
    836         mux_sdu_data.cur_pos = (uint16)(mux_sdu_data.cur_pos + n);
    837         bytesInCurFragment -= n;
    838         mux_sdu_data.size = (uint16)(mux_sdu_data.size - n);
    839         // check for end of fragment
    840         if (bytesInCurFragment == 0)
    841         {
    842             mux_sdu_data.cur_frag_num++;
    843             mux_sdu_data.cur_pos = 0;
    844         }
    845     }
    846     /* check for end of packet */
    847     if (mux_sdu_data.size == 0 && mux_sdu_data.lcn->IsSegmentable())
    848     {
    849         *pm = true;
    850     }
    851     return;
    852 }
    853 
    854 int CPVH223Multiplex::MuxToALDispatch(uint8* pdu, int pdu_size, int fClosing, int muxCode)
    855 {
    856     int ret = 0;
    857 
    858     if (fClosing)
    859     {
    860         if (iLcnEnd)
    861         {
    862             H223IncomingChannel* lcn = iLcnEnd;
    863             if (PVMFSuccess != lcn->AlDispatch())
    864             {
    865                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::MuxToALDispatch Memory allocation failure on AlDispatch, channel id=%d", iLcnEnd->GetLogicalChannelNumber()));
    866                 lcn->ResetAlPdu();
    867             }
    868             iLcnEnd = NULL;
    869         }
    870     }
    871 
    872     PS_MultiplexEntryDescriptor mux_entry = iMuxTblMgr->GetIncomingDescriptor((uint8)muxCode);
    873 
    874     if (mux_entry)
    875     {
    876         if (pdu_size)
    877         {
    878             ret = BreakPduData(pdu, pdu_size, mux_entry->elementList, mux_entry->size_of_elementList);
    879         }
    880     }
    881 
    882     return ret;
    883 }
    884 
    885 TPVStatusCode CPVH223Multiplex::AlPduData(H223IncomingChannel* aChannel,
    886         uint8*& pdu,
    887         PS_MultiplexElement pElement,
    888         int n)
    889 {
    890     OSCL_UNUSED_ARG(pElement);
    891     if (PVMFSuccess != aChannel->AlPduData(pdu, (uint16)n))
    892     {
    893         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    894                         (0, "CPVH223Multiplex::BreakPduData Memory allocation failure on AlPduData, channel id=%d",
    895                          pElement->muxType.logicalChannelNumber));
    896         aChannel->ResetAlPdu();
    897         return PVMFFailure;
    898     }
    899     return PVMFSuccess;
    900 }
    901 
    902 TPVStatusCode CPVH223Multiplex::Dispatch(H223IncomingChannel* aChannel,
    903         PS_MultiplexElement pElement)
    904 {
    905     OSCL_UNUSED_ARG(pElement);
    906     if (PVMFSuccess != aChannel->AlDispatch())
    907     {
    908         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    909                         (0, "CPVH223Multiplex::BreakPduData Memory allocation failure on AlDispatch, channel id=%d",
    910                          pElement->muxType.logicalChannelNumber));
    911         aChannel->ResetAlPdu();
    912         return PVMFErrNoMemory;
    913     }
    914     return PVMFSuccess;
    915 }
    916 
    917 int CPVH223Multiplex::BreakPduData(uint8*& pdu, int pdu_size, PS_MultiplexElement pElement, int ListSize)
    918 {
    919     //PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"CPVH223Multiplex::BreakPduData pdu(%x), pdu_size(%d), pElement(%x), ListSize(%d),iObserver(%x)", pdu,pdu_size,pElement,ListSize,iObserver));
    920 
    921     int cnt = 0, cnt2 = 0, LoopCnt = 0, n = 0;
    922     int demuxed_size = 0;
    923     H223IncomingChannel* channel = NULL;
    924 
    925     for (cnt = ListSize ; cnt != 0 ; cnt --)
    926     {
    927         /* sub-element list search */
    928         if (pElement->muxType.index != 0)
    929         {
    930             LoopCnt = (pElement->repeatCount.index) ?
    931                       pdu_size /* untill closing flag */ : pElement->repeatCount.finite;
    932 
    933             for (cnt2 = 0 ; cnt2 < LoopCnt ; cnt2 ++)
    934             {
    935                 demuxed_size += BreakPduData(pdu, pdu_size,
    936                                              pElement->muxType.subElementList,
    937                                              pElement->muxType.size);
    938                 pdu += demuxed_size;
    939                 if (demuxed_size >= pdu_size)
    940                     return demuxed_size; /* Data End */
    941             }
    942         }
    943         /* Element Search */
    944         else
    945         {
    946             for (cnt2 = 0 ; cnt2 < (int)iIncomingChannels.size(); cnt2++)
    947             {
    948                 if (iIncomingChannels[cnt2].GetRep() == NULL)
    949                 {
    950                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::BreakPduData channel(%d) - Does not exist\n", pElement->muxType.logicalChannelNumber));
    951                 }
    952                 if (iIncomingChannels[cnt2].GetRep() &&
    953                         (pElement->muxType.logicalChannelNumber ==
    954                          (0xFFFF&iIncomingChannels[cnt2]->GetLogicalChannelNumber())))
    955                 {
    956                     channel = iIncomingChannels[cnt2];
    957                     if (pElement->repeatCount.index == 0)
    958                     {
    959                         n = min2(pdu_size, pElement->repeatCount.finite);
    960                     }
    961                     else
    962                     {
    963                         n = pdu_size;
    964                     }
    965                     pdu_size -= n;
    966                     demuxed_size += n;
    967 
    968 
    969                     AlPduData(channel, pdu, pElement, n);
    970 
    971                     pdu += n;
    972 
    973                     /* If enough pdus have been received, indicate to observer */
    974                     if (channel->GetNumSdusIn() == H223_LCN_DATA_DETECT_THRESHOLD)
    975                     {
    976                         iObserver->LcnDataDetected(channel->GetLogicalChannelNumber());
    977                     }
    978 
    979                     if (!channel->IsSegmentable())
    980                     {
    981                         Dispatch(channel, pElement);
    982                     }
    983                     else
    984                     {
    985                         if (pdu_size == 0)
    986                         {
    987                             iLcnEnd = channel;
    988                             return demuxed_size;
    989                         }
    990                     }
    991                     if (pdu_size == 0)
    992                         return demuxed_size;
    993                     break;
    994                 }
    995             }
    996         }
    997         pElement++;
    998     }
    999     return false;
   1000 }
   1001 
   1002 
   1003 void CPVH223Multiplex::ResetStats()
   1004 {
   1005     for (unsigned out_lcn = 0; out_lcn < iOutgoingChannels.size(); out_lcn++)
   1006     {
   1007         iOutgoingChannels[out_lcn]->ResetStats();
   1008     }
   1009     for (unsigned in_lcn = 0; in_lcn < iIncomingChannels.size(); in_lcn++)
   1010     {
   1011         iIncomingChannels[in_lcn]->ResetStats();
   1012     }
   1013 
   1014     iMuxTblMgr->ResetStats();
   1015     if (iLowerLayer)
   1016     {
   1017         iLowerLayer->ResetStats();
   1018     }
   1019 }
   1020 
   1021 void CPVH223Multiplex::LogStats(TPVDirection dir)
   1022 {
   1023     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223 Multiplex Statistics:\n"));
   1024 
   1025     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Logical Channel Statistics:\n"));
   1026     if (dir & OUTGOING)
   1027     {
   1028         for (unsigned n = 0; n < iOutgoingChannels.size(); n++)
   1029         {
   1030             iOutgoingChannels[n]->LogStats();
   1031         }
   1032         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Outgoing Multiplex Entry Statistics:\n"));
   1033         iMuxTblMgr->LogStats(OUTGOING);
   1034         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Outgoing Multiplex PDU Statistics:\n"));
   1035         iLowerLayer->LogStats(OUTGOING);
   1036     }
   1037 
   1038     if (dir & INCOMING)
   1039     {
   1040         for (unsigned n = 0; n < iIncomingChannels.size(); n++)
   1041         {
   1042             iIncomingChannels[n]->LogStats();
   1043         }
   1044         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Incoming Multiplex Entry Statistics:\n"));
   1045         iMuxTblMgr->LogStats(INCOMING);
   1046         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Incoming Multiplex PDU Statistics:\n"));
   1047         iLowerLayer->LogStats(INCOMING);
   1048     }
   1049 }
   1050 
   1051 TPVStatusCode CPVH223Multiplex::StopChannel(TPVDirection direction, TPVChannelId channel_id)
   1052 {
   1053     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::StopChannel direction(%d), channel id(%d)\n", direction, channel_id));
   1054     if (iLcnEnd && (iLcnEnd->GetLogicalChannelNumber() == channel_id))
   1055     {
   1056         iLcnEnd = NULL;
   1057     }
   1058     return FlushChannel(direction, channel_id);
   1059 }
   1060 
   1061 TPVStatusCode CPVH223Multiplex::FlushChannel(TPVDirection direction, TPVChannelId channel_id)
   1062 {
   1063     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::FlushChannel direction(%d), channel id(%d)\n", direction, channel_id));
   1064 
   1065     if (direction & OUTGOING)
   1066     {
   1067         OsclSharedPtr<H223OutgoingChannel> channel;
   1068         PVMFStatus status = GetOutgoingChannel(channel_id, channel);
   1069 
   1070         if (status == PVMFSuccess)
   1071         {
   1072             channel->Flush();
   1073             /* flush any partially sent sdu */
   1074             RemoveMuxSduData(channel_id, channel->IsSegmentable());
   1075             return EPVT_Success;
   1076         }
   1077         return EPVT_ErrorInvalidParameter;
   1078     }
   1079     else if (direction & INCOMING)
   1080     {
   1081         OsclSharedPtr<H223IncomingChannel> channel;
   1082         PVMFStatus status = GetIncomingChannel(channel_id, channel);
   1083         if (status == PVMFSuccess)
   1084         {
   1085             channel->Flush();
   1086         }
   1087     }
   1088     return EPVT_Success;
   1089 }
   1090 
   1091 void CPVH223Multiplex::LowerLayerError(TPVDirection direction, PVMFStatus error)
   1092 {
   1093     OSCL_UNUSED_ARG(direction);
   1094     OSCL_UNUSED_ARG(error);
   1095     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::LowerLayerError error(%d)\n", error));
   1096     iObserver->MuxErrorOccurred(direction, PV_MUX_COMPONENT_MUX, error);
   1097 }
   1098 
   1099 inline int32 CPVH223Multiplex::GetTimestamp()
   1100 {
   1101     return iLowerLayer->GetTimestamp();
   1102 }
   1103 
   1104 void CPVH223Multiplex::LogicalChannelError(TPVDirection direction, TPVChannelId id, PVMFStatus error)
   1105 {
   1106     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::LogicalChannelError  error(%d), id(%d)\n", error, id));
   1107     iObserver->MuxErrorOccurred(direction, PV_MUX_COMPONENT_LOGICAL_CHANNEL, error, (uint8*)&id, sizeof(id));
   1108 }
   1109 
   1110 void CPVH223Multiplex::SkewDetected(TPVChannelId lcn1, TPVChannelId lcn2, uint32 skew)
   1111 {
   1112     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::SkewDetected lcn1=%d, lcn2=%d, skew=%d", lcn1, lcn2, skew));
   1113     iObserver->SkewDetected(lcn1, lcn2, skew);
   1114 }
   1115 
   1116 void CPVH223Multiplex::ReceivedFormatSpecificInfo(TPVChannelId lcn, uint8* fsi, uint32 fsi_len)
   1117 {
   1118     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::ReceivedFormatSpecificInfo lcn=%d, len=%d", lcn, fsi_len));
   1119     iObserver->ReceivedFormatSpecificInfo(lcn, fsi, fsi_len);
   1120 }
   1121 
   1122 void CPVH223Multiplex::SetMultiplexLevel(TPVH223Level muxLevel)
   1123 {
   1124     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::SetMultiplexLevel  level(%d)\n", muxLevel));
   1125     if (iLowerLayer == NULL)
   1126     {
   1127         OSCL_LEAVE(PVMFErrInvalidState);
   1128     }
   1129     iLowerLayer->SetLevel(muxLevel);
   1130 }
   1131 
   1132 unsigned CPVH223Multiplex::GetNumChannels(TPVDirection direction)
   1133 {
   1134     if (direction == OUTGOING)
   1135         return iOutgoingChannels.size() - 1;
   1136     return iIncomingChannels.size() - 1;
   1137 }
   1138 
   1139 MuxSduData* CPVH223Multiplex::FindMuxSduData(TPVChannelId lcn,
   1140         bool segmentable,
   1141         uint32* p_index)
   1142 {
   1143     MuxSduDataList& list = GET_SDU_DATA_LIST(segmentable);
   1144     for (unsigned index = 0; index < list.size(); index++)
   1145     {
   1146         if (list[index].lcn->GetLogicalChannelNumber() == lcn)
   1147         {
   1148             if (p_index)
   1149                 *p_index = index;
   1150             return &list[index];
   1151         }
   1152     }
   1153     return NULL;
   1154 }
   1155 
   1156 void CPVH223Multiplex::AppendMuxSduData(MuxSduData& data)
   1157 {
   1158     if (data.lcn->GetLogicalChannelNumber() == 0)
   1159     {
   1160         iControlSduDataList.push_back(data);
   1161         return;
   1162     }
   1163     MuxSduDataList& list = GET_SDU_DATA_LIST(data.lcn->IsSegmentable());
   1164     list.push_back(data);
   1165 }
   1166 
   1167 void CPVH223Multiplex::SetMuxSduData(MuxSduData& data)
   1168 {
   1169     MuxSduData* mux_sdu_data_ptr = FindMuxSduData(data.lcn->GetLogicalChannelNumber(),
   1170                                    data.lcn->IsSegmentable());
   1171     if (mux_sdu_data_ptr)
   1172     {
   1173         *mux_sdu_data_ptr = data;
   1174     }
   1175 }
   1176 
   1177 void CPVH223Multiplex::RemoveMuxSduData(TPVChannelId lcn, bool segmentable)
   1178 {
   1179     if (lcn == 0)
   1180     {
   1181         iControlSduDataList.clear();
   1182         return;
   1183     }
   1184     MuxSduDataList& list = GET_SDU_DATA_LIST(segmentable);
   1185     uint32 index = 0;
   1186     while (list.size())
   1187     {
   1188         if (FindMuxSduData(lcn, segmentable, &index))
   1189         {
   1190             list.erase(list.begin() + index);
   1191         }
   1192     }
   1193 }
   1194 
   1195 void CPVH223Multiplex::ReleaseMuxSdu(MuxSduData& mux_sdu_data,
   1196                                      MuxSduDataList& list,
   1197                                      unsigned index)
   1198 {
   1199     OSCL_UNUSED_ARG(index);
   1200     OSCL_UNUSED_ARG(list);
   1201     mux_sdu_data.lcn->ReleasePacket(mux_sdu_data.sdu);
   1202     if (mux_sdu_data.lcn->GetNextPacket(mux_sdu_data.sdu, PVMFSuccess))
   1203     {
   1204         mux_sdu_data.size = (uint16)mux_sdu_data.sdu->getFilledSize();
   1205         mux_sdu_data.cur_frag_num = 0;
   1206         mux_sdu_data.cur_pos = 0;
   1207     }
   1208     else
   1209     {
   1210         RemoveMuxSduData(mux_sdu_data.lcn->GetLogicalChannelNumber(), mux_sdu_data.lcn->IsSegmentable());
   1211     }
   1212 }
   1213 
   1214 unsigned CPVH223Multiplex::UpdateSduDataLists()
   1215 {
   1216     unsigned num_lcns = 0;
   1217     for (unsigned lcnindex = 0; lcnindex < iOutgoingChannels.size(); lcnindex++)
   1218     {
   1219         MuxSduData* mux_sdu_data_ptr = NULL;
   1220         if (lcnindex == 0)
   1221         {
   1222             if (iControlSduDataList.size())
   1223                 mux_sdu_data_ptr = &iControlSduDataList[0];
   1224         }
   1225         else
   1226         {
   1227             mux_sdu_data_ptr = FindMuxSduData(iOutgoingChannels[lcnindex]->GetLogicalChannelNumber(),
   1228                                               iOutgoingChannels[lcnindex]->IsSegmentable());
   1229         }
   1230         if (mux_sdu_data_ptr)
   1231         {
   1232             num_lcns++;
   1233         }
   1234         else
   1235         {
   1236             // get the next packet and update the sdu size
   1237             PVMFSharedMediaDataPtr sdu;
   1238             if (iOutgoingChannels[lcnindex]->GetNextPacket(sdu, PVMFSuccess))
   1239             {
   1240                 MuxSduData mux_sdu_data;
   1241                 mux_sdu_data.lcn = iOutgoingChannels[lcnindex];
   1242                 mux_sdu_data.sdu = sdu;
   1243                 mux_sdu_data.size = (uint16)sdu->getFilledSize();
   1244                 mux_sdu_data.cur_frag_num = 0;
   1245                 mux_sdu_data.cur_pos = 0;
   1246                 AppendMuxSduData(mux_sdu_data);
   1247                 num_lcns++;
   1248             }
   1249         }
   1250     }
   1251     return num_lcns;
   1252 }
   1253 
   1254 OsclSharedPtr<PVMFMediaDataImpl> CPVH223Multiplex::InitPduPacket()
   1255 {
   1256     OsclSharedPtr<PVMFMediaDataImpl> ret = iMuxPduPacketAlloc->allocate(MAX_FRAGMENTS_PER_H223_PDU_PACKET);
   1257     if (!ret)
   1258     {
   1259         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1260                         (0, "CPVH223Multiplex::InitPduPacket Unable to allocate packet."));
   1261         return ret;
   1262     }
   1263     OsclRefCounterMemFrag hdr;
   1264     iLowerLayer->GetHdrFragment(hdr);
   1265     if (hdr.getMemFragSize())
   1266     {
   1267         ret->appendMediaFragment(hdr);
   1268     }
   1269     else
   1270     {
   1271         ret.Unbind();
   1272     }
   1273     return ret;
   1274 }
   1275 
   1276 PVMFStatus CPVH223Multiplex::CompletePduPacket(OsclSharedPtr<PVMFMediaDataImpl>& packet, int mt, int pm)
   1277 {
   1278     return iLowerLayer->CompletePacket(packet, mt, pm);
   1279 }
   1280 
   1281 void CPVH223Multiplex::UpdateMuxInterval(uint16 aInterval)
   1282 {
   1283     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::UpdateMuxInterval"));
   1284     iMinSampleInterval = aInterval ? aInterval : (uint16)iLowerLayer->GetMinTimerRes();
   1285     unsigned lcnindex;
   1286     for (lcnindex = 0; lcnindex < iOutgoingChannels.size(); lcnindex++)
   1287     {
   1288         uint16 sample_interval = (uint16)iOutgoingChannels[lcnindex]->GetSampleInterval();
   1289         if (sample_interval && (sample_interval < iMinSampleInterval))
   1290             iMinSampleInterval = sample_interval;
   1291     }
   1292 
   1293     iNumMuxIntervalsPerTimerInterval = (uint16)(iLowerLayer->GetMinTimerRes() / iMinSampleInterval);
   1294     iNumBytesPerMinSampleInterval = (uint16)((float)(iMinSampleInterval * iBitrate) / 8000.0 + .5);
   1295     iLowerLayer->SetMaxOutgoingPduSize(iNumBytesPerMinSampleInterval);
   1296     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::UpdateMuxInterval =%d", iMinSampleInterval));
   1297 }
   1298 
   1299 void CPVH223Multiplex::ClearSduDataLists()
   1300 {
   1301     iControlSduDataList.clear();
   1302     iNonSegmentableSduDataList.clear();
   1303     iSegmentableSduDataList.clear();
   1304 }
   1305 
   1306 uint16 CPVH223Multiplex::MuxLcnData(MuxSduDataList& list,
   1307                                     MuxPduPacketList& packets,
   1308                                     uint16 max_size)
   1309 {
   1310     if (list.size() == 0)
   1311         return 0;
   1312 
   1313     int32 pdu_size_left = max_size;
   1314     PS_MultiplexEntryDescriptor mux_entry = NULL;
   1315     for (unsigned n = 0; n < list.size(); n++)
   1316     {
   1317         // get descriptor for this logical channel
   1318         mux_entry = iMuxTblMgr->GetOutgoingDescriptor(list[n].lcn,
   1319                     list[n].sdu);
   1320         if (mux_entry == NULL)
   1321         {
   1322             continue;
   1323         }
   1324         uint32 packet_size = DispatchPduPacket(packets, list[n], mux_entry, pdu_size_left);
   1325         if (packet_size == 0)
   1326             break;
   1327 
   1328         pdu_size_left -= packet_size;
   1329         if (pdu_size_left < 0)
   1330         {
   1331             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::MuxSduData Size exceeded, pdu_size_left=%d", pdu_size_left));
   1332         }
   1333         if (list[n].size == 0)
   1334         {
   1335             ReleaseMuxSdu(list[n], list, n);
   1336         }
   1337         if (pdu_size_left <= (int)iLowerLayer->GetHeaderSize())
   1338             break;
   1339     }
   1340     return (uint16)(max_size - pdu_size_left);
   1341 }
   1342 
   1343 void CPVH223Multiplex::SetMultiplexingDelayMs(uint16 aDelay)
   1344 {
   1345     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::SetMultiplexingDelayMs,aDelay=%d", aDelay));
   1346     iMultiplexingDelayMs = aDelay;
   1347 }
   1348 
   1349 void CPVH223Multiplex::SetLogicalChannelBufferingMs(uint32 aInBufferingMs,
   1350         uint32 aOutBufferingMs)
   1351 {
   1352     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::SetLogicalChannelBufferingMs,aInBufferingMs=%d,aOutBufferingMs=%d", aInBufferingMs, aOutBufferingMs));
   1353     iInLogicalChannelBufferingMs = aInBufferingMs;
   1354     iOutLogicalChannelBufferingMs = aOutBufferingMs;
   1355 }
   1356 
   1357 void CPVH223Multiplex::SetBitrate(uint32 aBitrate)
   1358 {
   1359     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::SetLogicalChannelBufferingMs,aBitrate=%d", aBitrate));
   1360     iBitrate = aBitrate;
   1361 }
   1362 
   1363 void CPVH223Multiplex::SetStuffingMsgHeader()
   1364 {
   1365     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::SetStuffingMsgHeader() mode=%d", iFmStuffingMode));
   1366     const int32 MAX_STUFFING_SEQUENCE_SIZE = 16;
   1367     uint stuffing_size = H223GetMuxStuffingSz(iLowerLayer->GetLevel());
   1368     if (!stuffing_size)
   1369         return;
   1370 
   1371     uint8 buf[MAX_STUFFING_SEQUENCE_SIZE];
   1372     stuffing_size = H223MuxStuffing(iLowerLayer->GetLevel(), buf, stuffing_size);
   1373     iLowerLayer->SendStuffingMsgHeader(buf, (uint16)stuffing_size);
   1374     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::SetStuffingMsgHeader()-done"));
   1375 }
   1376 
   1377 void CPVH223Multiplex::SetInterleavingMultiplexFlags(uint16 size, uint8* flags)
   1378 {
   1379     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::SetInterleavingMultiplexFlags() size=%d, flags=%x", size, flags));
   1380 
   1381     if (iInterleavingMultiplexFlags && iInterleavingPacket)
   1382     {
   1383         iInterleavingPacket->clearMediaFragments();
   1384         iInterleavingPacket.Unbind();
   1385         OSCL_DEFAULT_FREE(iInterleavingMultiplexFlags);
   1386         iInterleavingMultiplexFlags = NULL;
   1387     }
   1388     iInterleavingMultiplexFlagsSize = size;
   1389     iInterleavingMultiplexFlags = (uint8*)OSCL_DEFAULT_MALLOC(size);
   1390     oscl_memcpy(iInterleavingMultiplexFlags, flags, size);
   1391     iInterleavingPacket = iMuxPduPacketAlloc->allocate(1);
   1392     if (!iInterleavingPacket)
   1393     {
   1394         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1395                         (0, "CPVH223Multiplex::SetInterleavingMultiplexFlags Unable to allocate packet."));
   1396     }
   1397 }
   1398 
   1399 void CPVH223Multiplex::EnableStuffing(bool enable)
   1400 {
   1401     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1402                     (0, "CPVH223Multiplex::EnableStuffing enable=%d\n", enable));
   1403     iEnableStuffing = enable;
   1404 }
   1405 
   1406 void CPVH223Multiplex::EnableStuffOnlyFirstSend(bool enable)
   1407 {
   1408     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1409                     (0, "CPVH223Multiplex::EnableStuffOnlyFirstSend enable=%d\n", enable));
   1410     iStuffOnlyFirstSend = enable;
   1411 }
   1412 
   1413 void CPVH223Multiplex::SetMioLatency(int32 aLatency, bool aAudio)
   1414 {
   1415     H223IncomingChannel* channel = NULL;
   1416     if (iIncomingChannels.size() != 0)
   1417     {
   1418         for (int32 ii = 0; ii < (int32)iIncomingChannels.size(); ii++)
   1419         {
   1420             channel = iIncomingChannels[ii];
   1421             if (aAudio)
   1422             {
   1423                 channel->SetAudioLatency(aLatency);
   1424             }
   1425             else
   1426             {
   1427                 channel->SetVideoLatency(aLatency);
   1428             }
   1429         }
   1430     }
   1431 }
   1432 
   1433 
   1434