Home | History | Annotate | Download | only in src
      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