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
CPVH223Multiplex(TPVLoopbackMode aLoopbackMode)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
~CPVH223Multiplex()85 CPVH223Multiplex::~CPVH223Multiplex()
86 {
87 OSCL_DELETE(iMuxTblMgr);
88 iMuxTblMgr = NULL;
89 }
90
Init()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
GetMinTimerRes()126 int CPVH223Multiplex::GetMinTimerRes()
127 {
128 return iLowerLayer->GetMinTimerRes();
129 }
130
SetLoopbackMode(TPVLoopbackMode aLoopbackMode)131 void CPVH223Multiplex::SetLoopbackMode(TPVLoopbackMode aLoopbackMode)
132 {
133 iLoopbackMode = aLoopbackMode;
134 iLowerLayer->SetLoopbackMode(iLoopbackMode);
135 }
136
SetTimerRes(uint32 timer_res)137 TPVStatusCode CPVH223Multiplex::SetTimerRes(uint32 timer_res)
138 {
139 return iLowerLayer->SetTimerRes(timer_res);
140 }
141
Open()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
Start(H223PduParcomSharedPtr parcom)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
Close()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
Stop()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
DataReceptionStart()254 void CPVH223Multiplex::DataReceptionStart()
255 {
256 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "CPVH223Multiplex::DataReceptionStart()"));
257 iObserver->DataReceptionStart();
258 }
LevelSetupComplete(PVMFStatus status,TPVH223Level level)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
MuxPduIndicate(uint8 * pPdu,uint32 sz,int32 fClosing,int32 muxCode)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
MuxPduErrIndicate(EMuxPduError err)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
MuxSetupComplete(PVMFStatus status,TPVH223Level level)296 void CPVH223Multiplex::MuxSetupComplete(PVMFStatus status, TPVH223Level level)
297 {
298 OSCL_UNUSED_ARG(status);
299 OSCL_UNUSED_ARG(level);
300 }
301
DispatchPduPacket(MuxPduPacketList & packets,MuxSduData & mux_sdu_data,PS_MultiplexEntryDescriptor mux_entry,uint32 max_size)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. */
GetOutgoingMuxPdus(MuxPduPacketList & packets)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
SetMaxOutgoingPduSize(uint16 Size)444 TPVStatusCode CPVH223Multiplex::SetMaxOutgoingPduSize(uint16 Size)
445 {
446 return iLowerLayer->SetMaxOutgoingPduSize(Size);
447 }
448
SetSduSize(TPVDirection direction,uint16 size,ErrorProtectionLevel_t epl)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
GetSduSize(TPVDirection direction,ErrorProtectionLevel_t epl)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
GetMaxSduSize(TPVDirection direction,ErrorProtectionLevel_t epl)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
SetMuxLevel(TPVH223Level muxLevel)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
GetMuxLevel()501 TPVH223Level CPVH223Multiplex::GetMuxLevel()
502 {
503 return iLowerLayer->GetLevel();
504 }
505
GetLowerLayer()506 PVMFPortInterface* CPVH223Multiplex::GetLowerLayer()
507 {
508 return iLowerLayer;
509 }
510
SetIncomingMuxTableEntries(CPVMultiplexDescriptor * descriptor)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
SetIncomingMuxDescriptors(CPVMultiplexEntryDescriptorVector & descriptors,bool replace)520 void CPVH223Multiplex::SetIncomingMuxDescriptors(CPVMultiplexEntryDescriptorVector& descriptors, bool replace)
521 {
522 iMuxTblMgr->SetIncomingMuxDescriptors(descriptors, replace);
523 }
524
SetOutgoingMuxDescriptors(CPVMultiplexEntryDescriptorVector & descriptors)525 void CPVH223Multiplex::SetOutgoingMuxDescriptors(CPVMultiplexEntryDescriptorVector& descriptors)
526 {
527 iMuxTblMgr->SetOutgoingMuxDescriptors(descriptors);
528 }
529
RemoveOutgoingMuxDescriptor(uint8 muxTblNum)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
RemoveIncomingMuxDescriptor(uint8 muxTblNum)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
GetIncomingMuxDescriptor(uint16 muxTblNum)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
GetOutgoingChannel(TPVChannelId id,H223OutgoingChannelPtr & channel)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
GetIncomingChannel(TPVChannelId id,H223IncomingChannelPtr & channel)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
GetAdaptationLayer(OsclSharedPtr<AdaptationLayer> & al,TPVDirection aDirection,PS_H223LogicalChannelParameters aH223lcnParams,int32 aSdu_size,uint32 aNum_media_data)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
OpenChannel(TPVDirection direction,TPVChannelId channel_id,H223ChannelParam * h223params)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
CloseChannel(TPVDirection direction,TPVChannelId channel_id)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
MakePduData(OsclSharedPtr<PVMFMediaDataImpl> & outgoingPkt,int32 max_size,PS_MultiplexElement pElement,MuxSduData & mux_sdu_data,int * pm)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
MuxToALDispatch(uint8 * pdu,int pdu_size,int fClosing,int muxCode)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
AlPduData(H223IncomingChannel * aChannel,uint8 * & pdu,PS_MultiplexElement pElement,int n)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
Dispatch(H223IncomingChannel * aChannel,PS_MultiplexElement pElement)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
BreakPduData(uint8 * & pdu,int pdu_size,PS_MultiplexElement pElement,int ListSize)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
ResetStats()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
LogStats(TPVDirection dir)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
StopChannel(TPVDirection direction,TPVChannelId channel_id)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
FlushChannel(TPVDirection direction,TPVChannelId channel_id)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
LowerLayerError(TPVDirection direction,PVMFStatus error)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
GetTimestamp()1099 inline int32 CPVH223Multiplex::GetTimestamp()
1100 {
1101 return iLowerLayer->GetTimestamp();
1102 }
1103
LogicalChannelError(TPVDirection direction,TPVChannelId id,PVMFStatus error)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
SkewDetected(TPVChannelId lcn1,TPVChannelId lcn2,uint32 skew)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
ReceivedFormatSpecificInfo(TPVChannelId lcn,uint8 * fsi,uint32 fsi_len)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
SetMultiplexLevel(TPVH223Level muxLevel)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
GetNumChannels(TPVDirection direction)1132 unsigned CPVH223Multiplex::GetNumChannels(TPVDirection direction)
1133 {
1134 if (direction == OUTGOING)
1135 return iOutgoingChannels.size() - 1;
1136 return iIncomingChannels.size() - 1;
1137 }
1138
FindMuxSduData(TPVChannelId lcn,bool segmentable,uint32 * p_index)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
AppendMuxSduData(MuxSduData & data)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
SetMuxSduData(MuxSduData & data)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
RemoveMuxSduData(TPVChannelId lcn,bool segmentable)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
ReleaseMuxSdu(MuxSduData & mux_sdu_data,MuxSduDataList & list,unsigned index)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
UpdateSduDataLists()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
InitPduPacket()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
CompletePduPacket(OsclSharedPtr<PVMFMediaDataImpl> & packet,int mt,int pm)1276 PVMFStatus CPVH223Multiplex::CompletePduPacket(OsclSharedPtr<PVMFMediaDataImpl>& packet, int mt, int pm)
1277 {
1278 return iLowerLayer->CompletePacket(packet, mt, pm);
1279 }
1280
UpdateMuxInterval(uint16 aInterval)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
ClearSduDataLists()1299 void CPVH223Multiplex::ClearSduDataLists()
1300 {
1301 iControlSduDataList.clear();
1302 iNonSegmentableSduDataList.clear();
1303 iSegmentableSduDataList.clear();
1304 }
1305
MuxLcnData(MuxSduDataList & list,MuxPduPacketList & packets,uint16 max_size)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
SetMultiplexingDelayMs(uint16 aDelay)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
SetLogicalChannelBufferingMs(uint32 aInBufferingMs,uint32 aOutBufferingMs)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
SetBitrate(uint32 aBitrate)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
SetStuffingMsgHeader()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
SetInterleavingMultiplexFlags(uint16 size,uint8 * flags)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
EnableStuffing(bool enable)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
EnableStuffOnlyFirstSend(bool enable)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
SetMioLatency(int32 aLatency,bool aAudio)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