• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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