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