• 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 /*
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