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