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 "oscl_time.h"
     19 #include "lowerlayer.h"
     20 #include "media_fragment.h"
     21 #include "h223.h"
     22 #include "pvlogger.h"
     23 #include "level0.h"
     24 #include "level1.h"
     25 #include "level2.h"
     26 
     27 #define PV_H223_MAIN_TIMER_ID 0
     28 #define H223_MIN_SAMPLE_INTERVAL 20
     29 #if defined(__WINS__) || defined(WIN32)
     30 #define TIMER_RES 100
     31 #else
     32 #define TIMER_RES 40
     33 #endif
     34 #define H223_MIN_TIMER_RESOLUTION 20
     35 #define H223_LEVEL_DEFAULT H223_LEVEL2
     36 
     37 #define H223_INITIAL_STUFFING_SEND_CNT 3
     38 #define H223_INITIAL_STUFFING_SEND_CNT_LEVEL0 25
     39 #define H223_SEND_PDU_SIZE_EXTRA 128
     40 
     41 #define CHECKSIZE 21
     42 
     43 #define H223_DEMUX_BUFFER_SIZE 2048
     44 
     45 H223LowerLayer::H223LowerLayer(int32 aPortTag, TPVLoopbackMode aLoopbackMode)
     46         :   PvmfPortBaseImpl(aPortTag, this),
     47         OsclTimerObject(OsclActiveObject::EPriorityHigh, "H223AO"),
     48         iTimerIntervalNum(0),
     49         iMinTimerResolution(TIMER_RES),
     50         iObserver(NULL),
     51         iMemFragmentAlloc(NULL),
     52         iDispatchPacketAlloc(NULL),
     53         iMediaDataImplMemAlloc(NULL),
     54         iMediaMsgPoolAlloc(NULL),
     55         iSendPduSz(0),
     56         iPduSize(H223_DEFAULT_PDU_SIZE),
     57         iStuffingSize(0),
     58         iTimer("H223LL"),
     59         iLoopbackMode(aLoopbackMode),
     60         iTimerCnt(0),
     61         iBytesSent(0),
     62         iMediaDataAlloc(&iMemAlloc),
     63         iLogger(NULL),
     64         iDemuxBuffer(NULL),
     65         iDemuxBufferPos(NULL),
     66         iIdleSyncCheckBuffer(NULL)
     67 {
     68     iLogger = PVLogger::GetLoggerObject("3g324m.h223.lowerlayer");
     69     AddToScheduler();
     70     InitParams();
     71     ResetStats();
     72 }
     73 
     74 H223LowerLayer::~H223LowerLayer()
     75 {
     76     Cancel();
     77     RemoveFromScheduler();
     78 }
     79 
     80 void H223LowerLayer::InitParams()
     81 {
     82     iMinTimerResolution = TIMER_RES;
     83     iState = 0;
     84     iStateVal = 0;
     85 
     86     iBitrate = DEFAULT_BITRATE;
     87 
     88     iUseAnnexA = true;
     89     iUseAnnexADoubleFlag = true;
     90     iUseAnnexB = true;
     91     iUseAnnexBwithHeader = true;
     92 
     93     for (uint16 level = H223_LEVEL0; level < H223_LEVEL_UNKNOWN; level++)
     94     {
     95         iStuffingSz[level] = (uint16)H223GetMuxStuffingSz((TPVH223Level)level);
     96     }
     97 
     98     UpdatePduSize();
     99 
    100     InitRuntimeParams();
    101     SetLevel(H223_LEVEL_DEFAULT);
    102 
    103     iDemuxBufferSize = 0;
    104     iSyncCheckCount = CHECKSIZE;
    105     SetLoopbackMode(iLoopbackMode);
    106     iSkipLevelCheck = false;
    107 }
    108 
    109 void H223LowerLayer::InitRuntimeParams()
    110 {
    111     iState = iStateVal = 0;
    112     iTimerCnt = 0;
    113     iBytesSent = 0;
    114     iLevelSetupComplete = false;
    115     iSyncDetected = false;
    116     iDataReceptionStart = false;
    117 }
    118 
    119 TPVStatusCode H223LowerLayer::Open()
    120 {
    121     unsigned pdu_rate = (unsigned)(1000.0 / (float)H223_MIN_SAMPLE_INTERVAL + .5) + 1;
    122     iMemFragmentAlloc = OSCL_NEW(PVMFBufferPoolAllocator, ());
    123     iMemFragmentAlloc->SetLeaveOnAllocFailure(false);
    124     iMemFragmentAlloc->size((uint16)(pdu_rate*2), (uint16)(iSendPduSz + H223_SEND_PDU_SIZE_EXTRA));
    125 
    126     iMediaMsgPoolAlloc = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (pdu_rate));
    127     iMediaMsgPoolAlloc->enablenullpointerreturn();
    128 
    129     uint media_data_imp_size = oscl_mem_aligned_size(sizeof(PVMFMediaFragGroup<OsclMemAllocator>)) +
    130                                oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
    131     iMediaDataImplMemAlloc = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (pdu_rate, media_data_imp_size));
    132     iMediaDataImplMemAlloc->enablenullpointerreturn();
    133     iDispatchPacketAlloc = OSCL_NEW(PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>, (pdu_rate, 30, iMediaDataImplMemAlloc));
    134     iDispatchPacketAlloc->create();
    135 
    136     iDemuxBufferSize = (uint32)((float)(H223_DEMUX_BUFFER_INTERVAL_MS * iBitrate) / 8000.0);
    137     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Open iBitrate=%d, iDemuxBufferSize=%d", iBitrate, iDemuxBufferSize));
    138     iDemuxBufferPos = iDemuxBuffer = (uint8*)OSCL_DEFAULT_MALLOC(H223_DEMUX_BUFFER_SIZE);
    139     iIdleSyncCheckBuffer = (uint8*)OSCL_DEFAULT_MALLOC(H223_DEMUX_BUFFER_SIZE);
    140     return EPVT_Success;
    141 }
    142 
    143 TPVStatusCode H223LowerLayer::Close()
    144 {
    145     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Close\n"));
    146 
    147     OSCL_DEFAULT_FREE(iIdleSyncCheckBuffer);
    148     iIdleSyncCheckBuffer = NULL;
    149 
    150     OSCL_DEFAULT_FREE(iDemuxBuffer);
    151     iDemuxBuffer = iDemuxBufferPos = NULL;
    152 
    153     iDispatchPacketAlloc->removeRef();
    154     iDispatchPacketAlloc = NULL;
    155 
    156     OSCL_DELETE(iMediaMsgPoolAlloc);
    157     iMediaMsgPoolAlloc = NULL;
    158 
    159     OSCL_DELETE(iMediaDataImplMemAlloc);
    160     iMediaDataImplMemAlloc = NULL;
    161 
    162     iMemFragmentAlloc->clear();
    163     OSCL_DELETE(iMemFragmentAlloc);
    164     return EPVT_Success;
    165 }
    166 
    167 TPVStatusCode H223LowerLayer::Start(H223PduParcomSharedPtr aParcom)
    168 {
    169     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Start(), parcom=%x", aParcom.GetRep()));
    170     InitRuntimeParams();
    171 
    172     if (aParcom.GetRep())
    173     {
    174         iParcom = aParcom;
    175         iParcom->SetObserver(this);
    176     }
    177 
    178     /* Start timer */
    179     iTimer.SetFrequency(1000 / iMinTimerResolution);
    180     iTimer.SetObserver(this);
    181     iTimer.Request(PV_H223_MAIN_TIMER_ID, PV_H223_MAIN_TIMER_ID , 1, this, 1);
    182 
    183     iState = 1;
    184     iSkipLevelCheck = false;
    185     Mux();
    186     return 1;
    187 }
    188 
    189 TPVStatusCode H223LowerLayer::Stop()
    190 {
    191     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Stop"));
    192 
    193     iTimer.Clear();
    194 
    195     iState = 0;
    196 
    197     iParcom.Unbind();
    198 
    199     iDemuxBufferPos = iDemuxBuffer;
    200 
    201     InitParams();
    202     iState = 0;
    203 
    204     return EPVT_Success;
    205 }
    206 
    207 int H223LowerLayer::Abort()
    208 {
    209     iState = 0;
    210 
    211     Disconnect();
    212 
    213     //Flush remaining data.
    214     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "LL:Abort Complete\n"));
    215 
    216     return 1;
    217 }
    218 
    219 TPVStatusCode H223LowerLayer::SetLevel(TPVH223Level muxLevel)
    220 {
    221     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::SetLevel muxLevel=%d", muxLevel));
    222 
    223     if (muxLevel == H223_LEVEL_UNKNOWN || muxLevel > H223_LEVEL2_OH)
    224     {
    225         OSCL_LEAVE(PVMFErrNotSupported);
    226     }
    227 
    228     CreateParcom(muxLevel);
    229 
    230     SetStuffingSize(muxLevel);
    231     return EPVT_Success;
    232 }
    233 
    234 TPVStatusCode H223LowerLayer::SetBitrate(uint32 bitRate)
    235 {
    236     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux[LL]: SetBitrate Request(%d)\n", bitRate));
    237     iBitrate = bitRate;
    238     UpdatePduSize();
    239     return EPVT_Success;
    240 }
    241 
    242 TPVStatusCode H223LowerLayer::SetMaxOutgoingPduSize(uint16 Size)
    243 {
    244     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::SetMaxOutgoingPduSize(%d)\n", Size));
    245 
    246     if (Size < H223_MIN_PDU_SIZE)
    247     {
    248         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::SetMaxOutgoingPduSize -  size < min(%d)!\n", H223_MIN_PDU_SIZE));
    249         Size = H223_MIN_PDU_SIZE;
    250     }
    251     uint16 max_pdu_size = H223_MAX_MUX_PDU_SIZE;
    252     if (iParcom->GetLevel() == H223_LEVEL2)
    253     {
    254         max_pdu_size = H223_MAX_MUX_PDU_SIZE_LEVEL2;
    255     }
    256     if (Size >= max_pdu_size)
    257     {
    258         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::SetMaxOutgoingPduSize - Size >= max_pdu_size(%d)\n", max_pdu_size));
    259         return EPVT_Success;
    260     }
    261 
    262     SetPduSize(Size);
    263     return EPVT_Success;
    264 }
    265 
    266 unsigned H223LowerLayer::SetPduSize(unsigned pdu_size)
    267 {
    268     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "SetPduSize - current(%d), new(%d)!\n", iPduSize, pdu_size));
    269     if (pdu_size < iPduSize)
    270     {
    271         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "SetPduSize - setting pdu size to (%d)", pdu_size));
    272         iPduSize = pdu_size;
    273     }
    274     else
    275     {
    276         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "SetPduSize - not setting pdu size "));
    277     }
    278     return iPduSize;
    279 }
    280 
    281 void H223LowerLayer::GetHdrFragment(OsclRefCounterMemFrag& hdr_frag)
    282 {
    283     iParcom->GetHdrFragment(hdr_frag);
    284 }
    285 
    286 PVMFStatus H223LowerLayer::CompletePacket(OsclSharedPtr<PVMFMediaDataImpl>& packet, int mt_entry, int pm)
    287 {
    288     PV_STAT_INCR(iNumPdusTx, 1)
    289     PV_STAT_INCR(iNumMuxSduBytesTx, packet->getFilledSize() - iParcom->GetHeaderSz())
    290     PV_STAT_INCR_COND(iNumPmTx, 1, pm)
    291     return iParcom->CompletePdu(packet, (int8)mt_entry, (uint8)pm);
    292 }
    293 
    294 void H223LowerLayer::TimeoutOccurred(int32 timerID, int32 timeoutInfo)
    295 {
    296     OSCL_UNUSED_ARG(timerID);
    297     OSCL_UNUSED_ARG(timeoutInfo);
    298     if (PVMFSuccess != Mux())
    299     {
    300         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::TimeoutOccurred - Memory allocation failed on Mux()\n"));
    301     }
    302 }
    303 
    304 /* H223PduParcomObserver virtuals */
    305 uint32 H223LowerLayer::MuxPduIndicate(uint8* pPdu, uint32 pduSz, int32 fClosing, int32 muxCode)
    306 {
    307     return iObserver->GetParcomObserver()->MuxPduIndicate(pPdu, pduSz, fClosing, muxCode);
    308 }
    309 
    310 void H223LowerLayer::MuxPduErrIndicate(EMuxPduError err)
    311 {
    312     iObserver->GetParcomObserver()->MuxPduErrIndicate(err);
    313 }
    314 
    315 void H223LowerLayer::MuxSetupComplete(PVMFStatus status, TPVH223Level level)
    316 {
    317     OSCL_UNUSED_ARG(level);
    318     if (status == PVMFPending)
    319     {
    320         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::MuxSetupComplete Pending level setup for level=%d", level));
    321         iSkipLevelCheck = true;
    322         return;
    323     }
    324     if (status == PVMFSuccess)
    325     {
    326         iLevelSetupComplete = true;
    327     }
    328     SignalLevelSetupComplete(status);
    329 }
    330 
    331 void H223LowerLayer::Run()
    332 {
    333 }
    334 
    335 void H223LowerLayer::DoCancel()
    336 {
    337     iTimer.Clear();
    338     Cancel();
    339 }
    340 
    341 void H223LowerLayer::SendStuffingMsgHeader(uint8* stuffing, uint16 stuffing_len)
    342 {
    343     OSCL_UNUSED_ARG(stuffing);
    344     OSCL_UNUSED_ARG(stuffing_len);
    345     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::SendStuffingMsgHeader stuffing(%x), len(%d)\n", stuffing, stuffing_len));
    346 }
    347 
    348 PVMFStatus H223LowerLayer::Mux()
    349 {
    350 
    351     if (!IsConnected())
    352     {
    353         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    354                         (0, "H223LowerLayer::Mux - Error Port not connected"));
    355         return PVMFFailure;
    356     }
    357     TimeValue timenow;
    358     OsclSharedPtr<PVMFMediaDataImpl> dispatchPacket = iDispatchPacketAlloc->allocate(30);
    359     if (!dispatchPacket)
    360     {
    361         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    362                         (0, "H223LowerLayer::Mux - Unable to allocate dispatchPacket"));
    363         return PVMFFailure;
    364     }
    365 
    366     dispatchPacket->clearMediaFragments();
    367 
    368     if (iSendTimes == 0)
    369     {
    370         iStartMuxTime = timenow;
    371     }
    372     iLastMuxTime = timenow;
    373     PV_STAT_SET_TIME(iStartTimeTx, iNumBytesTx)
    374     uint32 max_cnt = (iParcom->GetLevel() == H223_LEVEL0) ? H223_INITIAL_STUFFING_SEND_CNT_LEVEL0 : H223_INITIAL_STUFFING_SEND_CNT;
    375 
    376     if (iSendTimes < max_cnt)
    377     {
    378         DoStuffing(iParcom->GetLevel(),
    379                    dispatchPacket,
    380                    iPduSize,
    381                    0);
    382         if (dispatchPacket->getFilledSize() == 0)
    383         {
    384             return PVMFFailure;
    385         }
    386         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Mux sendtimes %d, sending %d bytes of stuffing", iSendTimes, dispatchPacket->getFilledSize()));
    387     }
    388     else
    389     {
    390         if (iObserver)
    391         {
    392             PVMFStatus status = iObserver->GetOutgoingMuxPdus(iSendPacketList);
    393             if (status != PVMFSuccess)
    394             {
    395                 iSendPacketList.clear();
    396                 return status;
    397             }
    398         }
    399 
    400         OsclRefCounterMemFrag dispatch_frag = iMemFragmentAlloc->get();
    401         if (dispatch_frag.getMemFragPtr() == NULL)
    402         {
    403             iSendPacketList.clear();
    404             return PVMFFailure;
    405         }
    406 
    407         uint8 *start_pos = (uint8*)dispatch_frag.getMemFragPtr();
    408         uint8 *pos = start_pos;
    409         uint16 max_size = (uint16)(iSendPduSz + H223_SEND_PDU_SIZE_EXTRA);
    410         for (unsigned pktnum = 0; pktnum < iSendPacketList.size(); pktnum++)
    411         {
    412             for (unsigned frag_num = 0; frag_num < iSendPacketList[pktnum]->getNumFragments(); frag_num++)
    413             {
    414                 OsclRefCounterMemFrag frag;
    415                 iSendPacketList[pktnum]->getMediaFragment(frag_num, frag);
    416                 if (pos - start_pos + frag.getMemFragSize() > max_size)
    417                     break;
    418                 oscl_memcpy(pos, frag.getMemFragPtr(), frag.getMemFragSize());
    419                 pos += frag.getMemFragSize();
    420             }
    421             iSendPacketList[pktnum]->clearMediaFragments();
    422         }
    423         iSendPacketList.clear();
    424         dispatch_frag.getMemFrag().len = (uint16)(pos - start_pos);
    425         if (dispatch_frag.getMemFrag().len)
    426             dispatchPacket->appendMediaFragment(dispatch_frag);
    427     }
    428 
    429     DispatchPacket(dispatchPacket);
    430     return PVMFSuccess;
    431 }
    432 
    433 void H223LowerLayer::MuxException()
    434 {
    435     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::MuxException"));
    436 }
    437 
    438 void H223LowerLayer::Parse(uint8* buf, uint16 size)
    439 {
    440     uint16 used_bytes = 0;
    441     if (!size)
    442         return;
    443 
    444 
    445     if (!iSkipLevelCheck && !iLevelSetupComplete)
    446     {
    447         if (buf[0] != 0x7e && buf[0] != 0xe1)
    448         {
    449             oscl_memset(iIdleSyncCheckBuffer, buf[0], size);
    450             if (oscl_memcmp(iIdleSyncCheckBuffer, buf, size) == 0)
    451             {
    452                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Parse Detected idle sync=%x, dropping %d bytes", buf[0], size));
    453                 return;
    454             }
    455         }
    456 
    457         // check for start of data reception
    458         if (!iDataReceptionStart)
    459         {
    460             for (uint16 i = 0; i < size; i++)
    461             {
    462                 if (buf[i] == 0xE1  || buf[i] == 0xA3 || buf[i] == 0x7E)
    463                 {
    464                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Parse Data reception started, byte=%x", buf[i]));
    465                     iDataReceptionStart = true;
    466                     iObserver->DataReceptionStart();
    467                     break;
    468                 }
    469             }
    470             if (!iDataReceptionStart)
    471             {
    472                 return;
    473             }
    474         }
    475         if (CheckLevelWithSync(buf, size, &used_bytes))
    476         {
    477             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux[LL]: Level Setup Complete - %d\n", iParcom->GetLevel()));
    478             SignalLevelSetupComplete(PVMFSuccess);
    479         }
    480     }
    481     if (iDataReceptionStart)
    482     {
    483         iParcom->Parse(buf, size);
    484     }
    485 }
    486 
    487 void H223LowerLayer::DispatchPacket(OsclSharedPtr<PVMFMediaDataImpl>& pack)
    488 {
    489     unsigned pkt_size = pack->getFilledSize();
    490     PVMFStatus status = PVMFSuccess;
    491 
    492     PV_STAT_INCR(iNumBytesTx, pkt_size)
    493 
    494     OSCL_ASSERT(pkt_size > 0);
    495 
    496     OsclSharedPtr<PVMFMediaData> aMediaData = PVMFMediaData::createMediaData(pack, iMediaMsgPoolAlloc);
    497     if (aMediaData.GetRep() == NULL)
    498     {
    499         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::DispatchPacket Failed to allocate media data"));
    500         return;
    501     }
    502 
    503     if (iLoopbackMode == PV_LOOPBACK_MUX)
    504     {
    505         PacketIn(aMediaData);
    506         iSendTimes++;
    507     }
    508     else
    509     {
    510         PVMFSharedMediaMsgPtr aMediaMsg;
    511         convertToPVMFMediaMsg(aMediaMsg, aMediaData);
    512         aMediaMsg->setSeqNum(iSendTimes++);
    513         status = QueueOutgoingMsg(aMediaMsg);
    514         if (status != PVMFSuccess && status != PVMFErrInvalidState)
    515         {
    516             // happens when we start sending data too soon
    517             iObserver->LowerLayerError(OUTGOING, PV2WayDispatchError);
    518         }
    519     }
    520 
    521     if ((iSendTimes % 100) == 0)
    522     {
    523         PVLOGGER_LOG_USE_ONLY(TimeValue timenow);
    524         PVLOGGER_LOG_USE_ONLY(TimeValue delta_t = timenow - iStartTimeTx);
    525         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux::DispatchPacket - Sent %d bytes in time(%d ms)\n", iNumBytesTx, delta_t.to_msec()));
    526         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux::DispatchPacket - Received %d bytes in time(%d ms)\n", iNumBytesRx, delta_t.to_msec()));
    527         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux::DispatchPacket - Delta = %d\n", iNumBytesTx - iNumBytesRx));
    528     }
    529 }
    530 
    531 /* Incoming packet from TSAP to be demuxed */
    532 void H223LowerLayer::PacketIn(PVMFSharedMediaDataPtr aMediaData)
    533 {
    534     PV_STAT_SET_TIME(iStartTimeRx, iNumBytesRx)
    535     OsclRefCounterMemFrag refCtrMemFrag;
    536     unsigned cur_size = iDemuxBufferPos - iDemuxBuffer;
    537     for (uint16 frag_num = 0; frag_num < aMediaData->getNumFragments(); frag_num++)
    538     {
    539         aMediaData->getMediaFragment(frag_num, refCtrMemFrag);
    540         PV_STAT_INCR(iNumBytesRx, (refCtrMemFrag.getMemFragSize()))
    541         if (refCtrMemFrag.getMemFragSize() > iDemuxBufferSize)
    542         {
    543             if (cur_size)
    544             {
    545                 Parse(iDemuxBuffer, (uint16)cur_size);
    546                 iDemuxBufferPos = iDemuxBuffer;
    547                 cur_size = 0;
    548             }
    549             Parse((uint8*)refCtrMemFrag.getMemFragPtr(), (uint16)refCtrMemFrag.getMemFragSize());
    550             iDemuxBufferSize = 0;
    551             continue;
    552         }
    553         else
    554         {
    555             oscl_memcpy(iDemuxBufferPos, refCtrMemFrag.getMemFragPtr(), refCtrMemFrag.getMemFragSize());
    556             iDemuxBufferPos += refCtrMemFrag.getMemFragSize();
    557             cur_size += refCtrMemFrag.getMemFragSize();
    558             iDemuxBufferSize -= refCtrMemFrag.getMemFragSize();
    559         }
    560     }
    561 }
    562 
    563 
    564 void H223LowerLayer::SignalLevelSetupComplete(PVMFStatus status)
    565 {
    566     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::SignalLevelSetupComplete"));
    567     TimeValue timenow;
    568     iLevelSetupTime = timenow - iStartTimeTx;
    569     iObserver->LevelSetupComplete(status, iParcom->GetLevel());
    570 }
    571 
    572 void H223LowerLayer::DoStuffing(TPVH223Level level,
    573                                 OsclSharedPtr<PVMFMediaDataImpl>& pkt,
    574                                 uint32 stuffing_sz,
    575                                 uint8 mux_code)
    576 {
    577     OSCL_UNUSED_ARG(level);
    578     if (!iParcom.GetRep())
    579         return;
    580 
    581     OsclRefCounterMemFrag stuffing_frag = iMemFragmentAlloc->get();
    582     if (stuffing_frag.getMemFragPtr() == NULL)
    583     {
    584         return;
    585     }
    586 
    587     int bytes_to_stuff = stuffing_sz > stuffing_frag.getCapacity() ? stuffing_frag.getCapacity() : stuffing_sz;
    588 
    589     uint32 sz = iParcom->GetStuffing((uint8*)stuffing_frag.getMemFragPtr(), bytes_to_stuff, mux_code);
    590     if (sz)
    591     {
    592         stuffing_frag.getMemFrag().len = sz;
    593         pkt->appendMediaFragment(stuffing_frag);
    594         PV_STAT_INCR(iNumStuffingBytesTx, sz)
    595     }
    596 
    597     return;
    598 }
    599 
    600 /***********************************************************************
    601   function name        :CheckLevel
    602   function outline     :
    603   function discription :CheckLevel( pData, size )
    604   input data           :pData Pointer to data to use
    605   output data          :size  Size of data
    606   draw time            :'96.07.09
    607 *************************************************************************/
    608 #define STUFFING_BUF_SZ 8
    609 #define SYNC_DETECT_TOLERANCE_BITS 2
    610 bool H223LowerLayer::CheckLevelWithSync(uint8* pData, uint16 size, uint16* used_bytes)
    611 {
    612     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "level check with sync, size(%d)", size));
    613     uint8* pos = pData;
    614 
    615     int sync_detected = false;
    616     if (CheckLevel(pos, size, used_bytes, &sync_detected))
    617     {
    618         return true;
    619     }
    620     if (sync_detected)
    621     {
    622         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevelWithSync - Sync detected, but level mismatch"));
    623         // Reset iSendTimes to force the mux to send out stuffing H223_INITIAL_STUFFING_SEND_CNT times
    624         iSendTimes = 0;
    625         return false;
    626     }
    627     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "level check with sync - done"));
    628     return false;
    629 }
    630 
    631 bool H223LowerLayer::CheckLevel(uint8* pData, uint16 size, uint16* used_bytes, int* sync_detected)
    632 {
    633     int j = 0;
    634     int level = H223_LEVEL_UNKNOWN;
    635     uint stuffing_sz =  0;
    636     uint check_sz = 0;
    637     uint8 stuffing_buf[STUFFING_BUF_SZ];
    638     uint8* pos = pData;
    639     uint32 check_cnt = 0;
    640     *sync_detected  = false;
    641     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevel size=%d, current level=%d, iSyncCheckCount=%d", size, iParcom->GetLevel(), iSyncCheckCount));
    642 
    643     if (size < iSyncCheckCount*H223GetMuxStuffingSz(H223_LEVEL_DEFAULT))
    644     {
    645         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevel Size inadequate to complete sync check reqd=%d", H223GetMuxStuffingSz(H223_LEVEL_DEFAULT)));
    646         return false;
    647     }
    648     level = (iParcom->GetLevel() == H223_LEVEL_UNKNOWN) ? H223_LEVEL_DEFAULT : iParcom->GetLevel();
    649     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevel starting level=%d", level));
    650 
    651     for (; level >= H223_LEVEL0; level--)
    652     {
    653         stuffing_sz =  H223GetMuxStuffingSz((TPVH223Level)level);
    654         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevel checking level=%d, stuffing sz=%d", level, stuffing_sz));
    655         H223MuxStuffing((TPVH223Level)level, stuffing_buf, STUFFING_BUF_SZ);
    656         uint tolerance = (level == H223_LEVEL0) ? 0 : SYNC_DETECT_TOLERANCE_BITS;
    657         if (level == H223_LEVEL1_DF)
    658         {
    659             continue;
    660         }
    661         check_sz = stuffing_sz * iSyncCheckCount;
    662         for (j = 0; j < (int)(size - check_sz + 1); j++)
    663         {
    664             pos = pData + j;
    665             check_cnt = 0;
    666             for (unsigned checknum = 0; checknum < iSyncCheckCount; checknum++)
    667             {
    668                 if (H223CheckSync((TPVH223Level)level, pos, stuffing_sz, tolerance))
    669                 {
    670                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevel Found a match, check_cnt=%d", check_cnt));
    671                     /* found a match */
    672                     pos += stuffing_sz;
    673                     *used_bytes = (uint16)(pos - pData);
    674                     check_cnt++;
    675                 }
    676                 else
    677                 {
    678                     check_cnt = 0;
    679                     break;
    680                 }
    681             }
    682             if (check_cnt == iSyncCheckCount)
    683             {
    684                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevel Sync Detected for level=%d", level));
    685                 *sync_detected = true;
    686                 if (iParcom->GetLevel() == level)
    687                 {
    688                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevel Level setup complete"));
    689                     iLevelSetupComplete = true;
    690                     return true;
    691                 }
    692                 if (!iSyncDetected)
    693                 {
    694                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::CheckLevel sync detected for level for first time(%d)", level));
    695                     iSyncDetected = true;
    696                     int32 err;
    697                     OSCL_TRY(err, CreateParcom((TPVH223Level)level))
    698                     OSCL_FIRST_CATCH_ANY(err, SignalLevelSetupComplete(PVMFErrNoMemory));
    699                     iObserver->LevelSetupComplete(PVMFPending, (TPVH223Level)level);
    700                     return false;
    701                 }
    702             }
    703         }
    704     }
    705 
    706     *used_bytes = (uint16)(pos - pData);
    707     return false;
    708 }
    709 
    710 void H223LowerLayer::ResetStats()
    711 {
    712     // Outgoing
    713     iSendTimes = 0;
    714     iNumBytesTx = 0;
    715     iNumMuxSduBytesTx = 0;
    716     iNumStuffingBytesTx = 0;
    717     iNumPdusTx = 0;
    718     iNumPmTx = 0;
    719 
    720     // Incoming
    721     iNumBytesRx = 0;
    722 
    723     if (iParcom)
    724     {
    725         iParcom->ResetStats();
    726     }
    727 }
    728 
    729 void H223LowerLayer::LogStats(TPVDirection dir)
    730 {
    731     if (dir & OUTGOING)
    732     {
    733         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux-pdu(O) Statistics:\n"));
    734         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num bytes tx - %d\n", iNumBytesTx));
    735 
    736         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num mux-sdu bytes tx - %d\n", iNumMuxSduBytesTx));
    737         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num stuffing bytes tx during level setup - %d\n", iNumStuffingBytesTx));
    738         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num pdus tx - %d\n", iNumPdusTx));
    739         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num pm tx - %d\n", iNumPmTx));
    740         if (iParcom)
    741         {
    742             iParcom->LogStats(OUTGOING);
    743         }
    744     }
    745 
    746     if (dir & INCOMING)
    747     {
    748         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Mux-pdu(I) Statistics:\n"));
    749         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num bytes rx - %d\n", iNumBytesRx));
    750         if (iParcom)
    751         {
    752             iParcom->LogStats(INCOMING);
    753         }
    754     }
    755 
    756 }
    757 
    758 unsigned H223LowerLayer::SetStuffingSize(TPVH223Level level)
    759 {
    760     iStuffingSize = iStuffingSz[level];
    761     return iStuffingSize;
    762 }
    763 
    764 
    765 /* PVMFPortInterface virtuals */
    766 // All requests are synchronous
    767 
    768 
    769 /* Incoming data from the network interface */
    770 PVMFStatus H223LowerLayer::PutData(PVMFSharedMediaMsgPtr aMsg)
    771 {
    772     /* In mux loopback mode, discard data from connected port */
    773     if (iLoopbackMode == PV_LOOPBACK_MUX)
    774         return PVMFSuccess;
    775     /* Dont processs data in invalid state */
    776     if (iState <= 0)
    777     {
    778         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::PutData Error - Invalid state(%d)", iState));
    779         return PVMFErrInvalidState;
    780     }
    781 
    782     PVMFStatus pvmfStatus = PVMFSuccess;
    783     /* Convert to media data */
    784     PVMFSharedMediaDataPtr mediaData;
    785     convertToPVMFMediaData(mediaData, aMsg);
    786 
    787     PacketIn(mediaData);
    788 
    789     return pvmfStatus;
    790 }
    791 
    792 int32 H223LowerLayer::GetTimestamp()
    793 {
    794     return (iLastMuxTime - iStartMuxTime).to_msec();
    795 }
    796 
    797 void H223LowerLayer::UpdatePduSize()
    798 {
    799     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::UpdatePduSize"));
    800     iSendPduSz = (uint16)(iMinTimerResolution * iBitrate / (1000 * 8));
    801     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer: Send pdu size(%d), pdu size(%d)\n", iSendPduSz, iPduSize));
    802 }
    803 
    804 unsigned H223LowerLayer::GetSendSize()
    805 {
    806     return iSendPduSz;
    807 }
    808 
    809 PVMFStatus H223LowerLayer::Connect(PVMFPortInterface* aPort)
    810 {
    811     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Connect"));
    812     if (IsConnected())
    813     {
    814         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::Connect - Already Connected !!"));
    815         return PVMFErrAlreadyExists;
    816     }
    817 
    818     PvmfPortBaseImpl::Connect(aPort);
    819     return PVMFSuccess;
    820 }
    821 
    822 
    823 void H223LowerLayer::HandlePortActivity(const PVMFPortActivity &aActivity)
    824 {
    825     PVMFStatus aStatus;
    826     if (aActivity.iType == PVMF_PORT_ACTIVITY_INCOMING_MSG)
    827     {
    828         PVMFSharedMediaMsgPtr aMsg;
    829         while (IncomingMsgQueueSize())
    830         {
    831             aStatus = DequeueIncomingMsg(aMsg);
    832             if (aStatus == PVMFSuccess)
    833             {
    834                 PutData(aMsg);
    835             }
    836             else
    837             {
    838                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223LowerLayer::HandlePortActivity Failed to DeQueue incoming message: %d", aStatus));
    839                 break;
    840             }
    841         }
    842     }
    843     else if (aActivity.iType == PVMF_PORT_ACTIVITY_OUTGOING_MSG)
    844     {
    845         while (OutgoingMsgQueueSize())
    846         {
    847             aStatus = Send();
    848             if (aStatus != PVMFSuccess)
    849             {
    850                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223LowerLayer::HandlePortActivity Failed to Send outgoing message: %d", aStatus));
    851                 break;
    852             }
    853         }
    854     }
    855     else
    856     {
    857         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LowerLayer::HandlePortActivity Unhandled port activity: %d", aActivity.iType));
    858     }
    859 }
    860 void H223LowerLayer::SetLoopbackMode(TPVLoopbackMode aLoopbackMode)
    861 {
    862     iLoopbackMode = aLoopbackMode;
    863 }
    864 
    865 
    866 void H223LowerLayer::CreateParcom(TPVH223Level level)
    867 {
    868     iParcom.Unbind();
    869 
    870 
    871     H223PduParcom* parcom = NULL;
    872 
    873     switch (level)
    874     {
    875         case H223_LEVEL0:
    876             parcom = OSCL_NEW(Level0PduParcom, ());
    877             break;
    878         case H223_LEVEL1:
    879         case H223_LEVEL1_DF:
    880             parcom = OSCL_NEW(Level1PduParcom, ());
    881             if (level == H223_LEVEL1)
    882                 break;
    883             ((Level1PduParcom*)parcom)->UseDf(true);
    884             break;
    885         case H223_LEVEL2:
    886         case H223_LEVEL2_OH:
    887             parcom = OSCL_NEW(Level2PduParcom, ());
    888 
    889             if (level == H223_LEVEL2)
    890                 break;
    891             ((Level2PduParcom*)parcom)->UseOh(true);
    892             break;
    893         default:
    894             OSCL_LEAVE(PVMFErrArgument);
    895             ;
    896     }
    897     PduParcomRefCounter *refCounter = OSCL_NEW(PduParcomRefCounter, (parcom));
    898     H223PduParcomSharedPtr sharedPtr(parcom, refCounter);
    899     iParcom = sharedPtr;
    900 
    901     uint16 pdu_rate = (uint16)((1000.0 / (float)H223_MIN_TIMER_RESOLUTION + .5) + 1);
    902     pdu_rate <<= 1; /* Double it since it will be used for video and control data also */
    903     iParcom->Construct(pdu_rate);
    904     iParcom->SetObserver(this);
    905     SetStuffingSize(level);
    906 }
    907