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: PVH264PayLoadOutputMediaData()44 PVH264PayLoadOutputMediaData() : don(0), fuType(0) {}; 45 PVH264PayLoadOutputMediaData(const PVH264PayLoadOutputMediaData & x)46 PVH264PayLoadOutputMediaData(const PVH264PayLoadOutputMediaData& x) 47 { 48 data = x.data; 49 don = x.don; 50 fuType = x.fuType; 51 } 52 PVH264PayLoadOutputMediaData(IPayloadParser::Payload adata,uint32 aDon,uint32 aFuType)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 */ compare(PVH264PayLoadOutputMediaData & a,PVH264PayLoadOutputMediaData & b)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 don_diff(uint32 m_don,uint32 n_don)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 fuType_diff(uint32 m_fuType,uint32 n_fuType)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 InterleaveModeProcessing()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 ~InterleaveModeProcessing()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 initialize(uint32 aInterleaveDepth)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 queue(const IPayloadParser::Payload & aMediaData,const uint8 nal_type,const uint32 fragmentedBitMask)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 dequeue(IPayloadParser::Payload & accessUnit)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 isQueueEmpty()221 bool isQueueEmpty() 222 { 223 return iOutputMediaDataQueue.empty(); 224 } 225 226 private: 227 // update variables when the prority queue is queuing data updateWhenQueuingData(const uint32 fuType,const uint8 nal_type,const uint32 fragmentedBitMask)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 updateWhenDequeuingData(const uint32 fuType)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