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 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 43 Level1PduParcom::Construct(uint16 max_outstanding_pdus) 44 { 45 iHdrFragmentAlloc.SetLeaveOnAllocFailure(false); 46 iHdrFragmentAlloc.size(max_outstanding_pdus, (uint16)H223GetMaxStuffingSz(H223_LEVEL1)); 47 } 48 49 void Level1PduParcom::GetHdrFragment(OsclRefCounterMemFrag& frag) 50 { 51 frag = iHdrFragmentAlloc.get(); 52 } 53 54 unsigned 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 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 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 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