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