• 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 #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