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 #ifndef H264_PAYLOAD_PARSER_INTERLEAVE_MODE_H
     19 #define H264_PAYLOAD_PARSER_INTERLEAVE_MODE_H
     20 
     21 
     22 #ifndef OSCL_PRIQUEUE_H_INCLUDED
     23 #include "oscl_priqueue.h"
     24 #endif
     25 
     26 #ifndef OSCL_MEM_H_INCLUDED
     27 #include "oscl_mem.h"
     28 #endif
     29 
     30 #ifndef PAYLOAD_PARSER_H_INCLUDED
     31 #include "payload_parser.h"
     32 #endif
     33 
     34 #ifndef H264_PAYLOAD_PARSER_MACROS_H_INCLUDED
     35 #include "h264_payload_parser_macros.h"
     36 #endif
     37 
     38 /////////////////////////////////////////////////////////////////////////////////
     39 ////////////// priority queue related data structures ///////////////////////////
     40 /////////////////////////////////////////////////////////////////////////////////
     41 class PVH264PayLoadOutputMediaData
     42 {
     43     public:
     44         PVH264PayLoadOutputMediaData() : don(0), fuType(0) {};
     45 
     46         PVH264PayLoadOutputMediaData(const PVH264PayLoadOutputMediaData& x)
     47         {
     48             data  = x.data;
     49             don  = x.don;
     50             fuType = x.fuType;
     51         }
     52 
     53         PVH264PayLoadOutputMediaData(IPayloadParser::Payload adata, uint32 aDon, uint32 aFuType)
     54         {
     55             data = adata;
     56             don = aDon;
     57             fuType = aFuType;
     58         }
     59 
     60         //required for compile of OsclPriorityQueue but not currently used & not implemented.
     61         //would be needed if code called "remove".
     62         bool operator==(const PVH264PayLoadOutputMediaData& x)const
     63         {
     64             OSCL_UNUSED_ARG(&x);
     65             OSCL_ASSERT(0);
     66             return false;
     67         }
     68 
     69     public:
     70         IPayloadParser::Payload data;
     71         uint32  don;
     72         uint32  fuType; // First byte: current fuType
     73         // 0 complete NAL
     74         // 1 starting FU
     75         // 2 intermediate FU
     76         // 3 ending FU
     77         // Second byte: previous fuType
     78         // Third-Fourth bytes: counter for intermediate FUs for the following compare function
     79 
     80 };
     81 
     82 // priority comparison class
     83 class PVH264PayLoadOutputMediaDataCompareLess
     84 {
     85     public:
     86         /**
     87         * The algorithm used in OsclPriorityQueue needs a compare function
     88         * that returns true when a's priority is less than b's. In the
     89         * current context, when a's don is larger than b's don, return true
     90         * Basically when a's don is smaller than b's don, then a's priority
     91         * is higher than b's.
     92         * @return true if a's priority is less than b's, else false
     93         */
     94         int compare(PVH264PayLoadOutputMediaData& a, PVH264PayLoadOutputMediaData& b) const
     95         {
     96             int32 diffDon = PVH264PayLoadOutputMediaDataCompareLess::don_diff(a.don, b.don);
     97             if (diffDon == 0)
     98             {
     99                 // use fuType
    100                 diffDon = PVH264PayLoadOutputMediaDataCompareLess::fuType_diff(a.fuType, b.fuType);
    101             }
    102             return (diffDon < 0);
    103         }
    104 
    105     private:
    106 
    107         static int32 don_diff(uint32 m_don, uint32 n_don)
    108         {
    109             if (m_don == n_don) return 0;
    110 
    111             if (m_don < n_don && (n_don - m_don < 32768))
    112                 return ((int32)n_don - (int32)m_don);
    113 
    114             if (m_don < n_don && (n_don - m_don >= 32768))
    115                 return ((int32)n_don - (int32)m_don - 65536);
    116 
    117             if (m_don > n_don && (m_don - n_don < 32768))
    118                 return -((int32)m_don - (int32)n_don);
    119 
    120             if (m_don > n_don && (m_don - n_don >= 32768))
    121                 return (65536 - m_don + n_don);
    122 
    123             return 0;
    124         }
    125 
    126         static int32 fuType_diff(uint32 m_fuType, uint32 n_fuType)
    127         {
    128             int32 diff_fuType = (int32)(n_fuType & 0x03) - (int32)(m_fuType & 0x03);
    129 
    130             // for intermediate FUs
    131             if (diff_fuType == 0)
    132             {
    133                 diff_fuType = (int32)(n_fuType >> 16) - (int32)(m_fuType >> 16);
    134             }
    135 
    136             return diff_fuType;
    137         }
    138 };
    139 
    140 //memory allocator type for this node.
    141 typedef OsclMemAllocator PVH264PayloadParserAllocator;
    142 
    143 
    144 class InterleaveModeProcessing
    145 {
    146 
    147     public:
    148 
    149         // constructor
    150         InterleaveModeProcessing() : iNALUnitsCounter(0),
    151                 iDon(0),
    152                 iDonBase(0),
    153                 iTimestampOffset(0),
    154                 iPrevNALType(0),
    155                 iRtpPayloadPtr(NULL)
    156         {
    157             ;
    158         }
    159 
    160         // destructor
    161         ~InterleaveModeProcessing()
    162         {
    163 
    164             // for iOutputMediaDataQueue, remove all the elements from the output data priority queue
    165             while (!iOutputMediaDataQueue.empty())
    166             {
    167                 iOutputMediaDataQueue.pop();
    168             }
    169 
    170             iNALUnitsCounter = iDon = iDonBase =
    171                                           iTimestampOffset = iPrevNALType = 0;
    172             iRtpPayloadPtr = NULL;
    173         }
    174 
    175         // initialize the iOutputMediaDataQueue when in the interleaved mode
    176         bool initialize(uint32 aInterleaveDepth)
    177         {
    178             if (aInterleaveDepth > 0)
    179             {
    180                 int32 err = 0;
    181                 OSCL_TRY(err, iOutputMediaDataQueue.reserve((aInterleaveDepth + 1) << 2));
    182                 if (err) return false;
    183             }
    184             return true;
    185         }
    186 
    187         // push data to priority queue
    188         bool queue(const IPayloadParser::Payload& aMediaData, const uint8 nal_type, const uint32 fragmentedBitMask)
    189         {
    190             uint32 prev_fuType = iPrevNALType & 0x03;
    191             uint32 fuType = fragmentedBitMask & 0x03;
    192             uint32 fuCounter = 0;
    193             if (fuType == 2)  // for the above fuType_diff() in priority comparsion
    194             {
    195                 fuCounter = (fragmentedBitMask >> BIT_SHIFT_FOR_FU_COUNTER) << 16;
    196             }
    197             PVH264PayLoadOutputMediaData out_data(aMediaData, iDon, (fuCounter | (prev_fuType << 8) | fuType));
    198 
    199             // push into the prority queue
    200             int32 err;
    201             OSCL_TRY(err, iOutputMediaDataQueue.push(out_data));
    202             if (err || iOutputMediaDataQueue.empty()) return false;
    203 
    204             // update internal variables
    205             updateWhenQueuingData(fuType, nal_type, fragmentedBitMask);
    206             return true;
    207         }
    208 
    209         // pop data from priority queue
    210         void dequeue(IPayloadParser::Payload& accessUnit)
    211         {
    212             PVH264PayLoadOutputMediaData out_data(iOutputMediaDataQueue.top());
    213             iOutputMediaDataQueue.pop();
    214             accessUnit = out_data.data;
    215 
    216             // update internal variables
    217             updateWhenDequeuingData(out_data.fuType);
    218         }
    219 
    220         // priority queue is empty
    221         bool isQueueEmpty()
    222         {
    223             return iOutputMediaDataQueue.empty();
    224         }
    225 
    226     private:
    227         // update variables when the prority queue is queuing data
    228         void updateWhenQueuingData(const uint32 fuType, const uint8 nal_type, const uint32 fragmentedBitMask)
    229         {
    230             if (fuType == 0 || fuType == 3)  // complete NAL or ending FU
    231             {
    232                 iNALUnitsCounter++;
    233             }
    234 
    235             // update iPrevNALType, only for complete NALs and FU-B
    236             if (nal_type != H264_RTP_PAYLOAD_FU_A)
    237             {
    238                 iPrevNALType = fragmentedBitMask & 0x07;
    239             }
    240             else   // FU-A
    241             {
    242                 iPrevNALType >>= 2;
    243                 iPrevNALType <<= 2;     // clear bit 1 and bit 0
    244                 iPrevNALType |= fuType; // keep bit 2 unchanged for FU-A, for isCurrRTPPacketIgnored()
    245             }
    246         }
    247 
    248         // update variables when the prority queue is de-queuing data
    249         void updateWhenDequeuingData(const uint32 fuType)
    250         {
    251             uint32 prev_fuType = (fuType >> 8) & 0x03;
    252             uint32 curr_fuType = fuType & 0x03;
    253 
    254             if (curr_fuType == 0)  // complete NAL
    255             {
    256                 iNALUnitsCounter--;
    257                 if (prev_fuType == 1 || prev_fuType == 2)  // current one is complete NAL, but the previous one is fragmented NAL in case that the ending fragmented NAL is lost
    258                 {
    259                     iNALUnitsCounter--;
    260                 }
    261             }
    262             else if (curr_fuType == 3)  // ending fragemented NAL
    263             {
    264                 iNALUnitsCounter--;
    265             }
    266         }
    267 
    268 
    269     public:
    270         // counter of complete NAL units, which could be smaller than the actual number of elements in iOutputMediaDataQueue
    271         uint32 iNALUnitsCounter;
    272 
    273         // hold the current DON, for FU-As following the first FU-B
    274         uint32 iDon;
    275 
    276         // hold the DONB, for MTAPs, or serves as the counter for FUs
    277         uint32 iDonBase;
    278 
    279         // for MTAPs only, save the timestamp offset
    280         uint32 iTimestampOffset;
    281 
    282         // for the NAL type of the previous media message sent out, should be equal to "iIsFragmentedBitMask&0x03" of class H264PayloadParser
    283         uint32 iPrevNALType;
    284 
    285         // save the rtp payload pointer to check if the current input rtp packet is the same as the previous one
    286         uint8 *iRtpPayloadPtr;
    287 
    288         // Priority Queue of output media data
    289         OsclPriorityQueue < PVH264PayLoadOutputMediaData,
    290         PVH264PayloadParserAllocator,
    291         Oscl_Vector<PVH264PayLoadOutputMediaData, PVH264PayloadParserAllocator>,
    292         PVH264PayLoadOutputMediaDataCompareLess > iOutputMediaDataQueue;
    293 
    294 };
    295 
    296 #endif // H264_PAYLOAD_PARSER_INTERLEAVE_MODE_H
    297 
    298