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