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 /*
19 * File: muxpdu.c
20 * Comment: Mux level 1 specific routines
21 */
22 #include "level1.h"
23 #include "h223.h"
24
Level1PduParcom(bool df)25 Level1PduParcom::Level1PduParcom(bool df):
26 iDf(df)
27 {
28 iLogger = PVLogger::GetLoggerObject("3g324m.h223.Level1");
29 iCurrentInt32 = 0;
30 iCurrentOp = ELookForStartFlag;
31 iSkipBytes = 0;
32 iPduPos = NULL;
33 uint8 HecCrc[18] =
34 {
35 0x00, 0x05, 0x07, 0x02, 0x03, 0x06, 0x04, 0x01,
36 0x06, 0x03, 0x01, 0x04, 0x05, 0x00, 0x02, 0x07
37 };
38
39 oscl_memcpy(iHecCrc, HecCrc, 18);
40 }
41
42 void
Construct(uint16 max_outstanding_pdus)43 Level1PduParcom::Construct(uint16 max_outstanding_pdus)
44 {
45 iHdrFragmentAlloc.SetLeaveOnAllocFailure(false);
46 iHdrFragmentAlloc.size(max_outstanding_pdus, (uint16)H223GetMaxStuffingSz(H223_LEVEL1));
47 }
48
GetHdrFragment(OsclRefCounterMemFrag & frag)49 void Level1PduParcom::GetHdrFragment(OsclRefCounterMemFrag& frag)
50 {
51 frag = iHdrFragmentAlloc.get();
52 }
53
54 unsigned
GetStuffing(uint8 * pPdu,uint32 buf_size,uint8 mux_code)55 Level1PduParcom::GetStuffing(uint8* pPdu, uint32 buf_size, uint8 mux_code)
56 {
57 OSCL_UNUSED_ARG(mux_code);
58 OSCL_UNUSED_ARG(buf_size);
59 int32 stuffing_size = iDf ? 4 : 2;
60 int32 size_left = buf_size;
61 while (size_left >= stuffing_size)
62 {
63 *(pPdu) = 0xe1;
64 *(pPdu + 1) = 0x4d;
65 pPdu += 2;
66 size_left -= 2;
67 if (iDf)
68 {
69 *(pPdu) = 0xe1;
70 *(pPdu + 1) = 0x4d;
71 pPdu += 2;
72 size_left -= 2;
73 }
74 }
75 return (buf_size - size_left);
76 }
77
CompletePdu(OsclSharedPtr<PVMFMediaDataImpl> & pdu,int8 MuxTblNum,uint8 pm)78 PVMFStatus Level1PduParcom::CompletePdu(OsclSharedPtr<PVMFMediaDataImpl>& pdu, int8 MuxTblNum, uint8 pm)
79 {
80 iClosingNext = 0;
81 OSCL_UNUSED_ARG(pm);
82 OsclRefCounterMemFrag frag;
83 pdu->getMediaFragment(0, frag);
84 pdu->setMediaFragFilledLen(0, GetHeaderSz());
85
86 // header
87 uint8* pPdu = (uint8*)frag.getMemFrag().ptr;
88
89 *pPdu = 0xe1;
90 *(pPdu + 1) = 0x4d;
91 if (iDf)
92 {
93 *(pPdu + 2) = 0xe1;
94 *(pPdu + 3) = 0x4d;
95 *(pPdu + 4) = (uint8)(iHecCrc[MuxTblNum] << 5 | MuxTblNum << 1);
96 }
97 else
98 {
99 *(pPdu + 2) = (uint8)(iHecCrc[MuxTblNum] << 5 | MuxTblNum << 1);
100 }
101
102 // trailer
103 if (pm)
104 {
105 OsclRefCounterMemFrag frag = iHdrFragmentAlloc.get();
106 if (frag.getMemFragPtr() == NULL)
107 {
108 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Level1PduParcom::CompletePdu Failed to allocate frag"));
109 return PVMFErrNoMemory;
110 }
111
112 frag.getMemFrag().len = GetHeaderSz();
113 pPdu = (uint8*)frag.getMemFragPtr();
114 *pPdu = 0xe1;
115 *(pPdu + 1) = 0x4d;
116 if (iDf) /* L1 Double Flag */
117 {
118 *(pPdu + 2) = 0xe1;
119 *(pPdu + 3) = 0x4d;
120 *(pPdu + 4) = (uint8)(iHecCrc[MuxTblNum] << 5 | MuxTblNum << 1 | 1);
121 }
122 else
123 {
124 *(pPdu + 2) = (uint8)(iHecCrc[MuxTblNum] << 5 | MuxTblNum << 1 | 1);
125 }
126 pdu->appendMediaFragment(frag);
127 }
128 return PVMFSuccess;
129 }
130
IndicatePdu()131 inline void Level1PduParcom::IndicatePdu()
132 {
133 int pdu_size = iPduPos - iPdu;
134 uint8* pdu = iPdu;
135
136 if (pdu_size >= 1)
137 {
138 if (iHecCrc[((*pdu)>>1)&0xf] != (*pdu) >> 5)
139 {
140 iObserver->MuxPduErrIndicate(EHeaderErr);
141 #ifdef PVANALYZER
142 nCrcError++;
143 PVAnalyzer(ANALYZER_MUXHDR, "Mux Header Error #=%d, %%=%f", nCrcError, (double)nCrcError / (double)nPdu);
144 #endif
145 }
146 else
147 {
148 int fClosing = 0;
149 int muxCode = -1;
150 if ((*pdu) & 1)
151 fClosing = 1;
152 muxCode = ((*pdu) >> 1) & 0xf;
153 pdu++;
154 pdu_size--;
155 iObserver->MuxPduIndicate(pdu, (uint16)pdu_size, fClosing, muxCode);
156 }
157 }
158 iPduPos = NULL;
159 }
160
Parse(uint8 * bsbuf,uint32 bsbsz)161 uint32 Level1PduParcom::Parse(uint8* bsbuf, uint32 bsbsz)
162 {
163 const int FLAG = (iDf) ? 0xE14DE14D : 0xE14D;
164 const int FLAG_SZ = (iDf) ? 4 : 2;
165 const int FLAG_MASK = (iDf) ? 0xFFFFFFFF : 0xFFFF;
166 #ifdef PVANALYZER
167 static unsigned int nPdu = 0;
168 static unsigned int nCrcError = 0;
169 nPdu++;
170 #endif
171
172 for (unsigned num = 0; num < bsbsz; num++)
173 {
174 iCurrentInt32 <<= 8;
175 iCurrentInt32 |= bsbuf[num];
176 switch (iCurrentOp)
177 {
178 case ELookForStartFlag:
179 if ((iCurrentInt32 & FLAG_MASK) == FLAG)
180 {
181 iCurrentOp = ESkipFlags;
182 iPduPos = iPdu;
183 }
184 break;
185 case ESkipFlags:
186 iSkipBytes++;
187 if (iSkipBytes == FLAG_SZ)
188 {
189 if ((iCurrentInt32 & FLAG_MASK) != FLAG)
190 {
191 if (!iPduPos)
192 iPduPos = iPdu;
193 // Check if iPduPos+FLAG_SZ-1 overflows
194 int copy_from = iCurrentInt32;
195 for (uint8* write_pos = iPduPos + FLAG_SZ - 1; write_pos >= iPduPos; write_pos--)
196 {
197 *write_pos = (uint8)copy_from;
198 copy_from >>= 8;
199 }
200 iPduPos += FLAG_SZ;
201 iCurrentOp = ELookForEndFlag;
202 }
203 iSkipBytes = 0;
204 }
205 break;
206 case ELookForEndFlag:
207 if ((iCurrentInt32 & FLAG_MASK) == FLAG)
208 {
209 iPduPos -= (FLAG_SZ - 1);
210 // found end flag
211 IndicatePdu();
212 iCurrentOp = ESkipFlags;
213 }
214 else
215 {
216 *iPduPos++ = bsbuf[num];
217 // check for pdu size
218 if ((iPduPos - iPdu) == H223_MAX_MUX_PDU_SIZE)
219 {
220 iObserver->MuxPduErrIndicate(ESizeErr);
221 iPduPos = NULL;
222 iCurrentOp = ELookForStartFlag;
223 }
224 }
225 break;
226 }
227 }
228 return 1;
229 }
230