1 /*****************************************************************************/
2 /* The contents of this file are subject to the Mozilla Public License       */
3 /* Version 1.0 (the "License"); you may not use this file except in          */
4 /* compliance with the License.  You may obtain a copy of the License at     */
5 /* http://www.mozilla.org/MPL/                                               */
6 /*                                                                           */
7 /* Software distributed under the License is distributed on an "AS IS"       */
8 /* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the  */
9 /* License for the specific language governing rights and limitations under  */
10 /* the License.                                                              */
11 /*                                                                           */
12 /* The Original Code is the Open H323 Library.                               */
13 /*                                                                           */
14 /* The Initial Developer of the Original Code is Matthias Schneider          */
15 /* Copyright (C) 2007 Matthias Schneider, All Rights Reserved.               */
16 /*                                                                           */
17 /* Contributor(s): Matthias Schneider (ma30002000@yahoo.de)                  */
18 /*                                                                           */
19 /* Alternatively, the contents of this file may be used under the terms of   */
20 /* the GNU General Public License Version 2 or later (the "GPL"), in which   */
21 /* case the provisions of the GPL are applicable instead of those above.  If */
22 /* you wish to allow use of your version of this file only under the terms   */
23 /* of the GPL and not to allow others to use your version of this file under */
24 /* the MPL, indicate your decision by deleting the provisions above and      */
25 /* replace them with the notice and other provisions required by the GPL.    */
26 /* If you do not delete the provisions above, a recipient may use your       */
27 /* version of this file under either the MPL or the GPL.                     */
28 /*                                                                           */
29 /* The Original Code was written by Matthias Schneider <ma30002000@yahoo.de> */
30 /*****************************************************************************/
31 
32 #include "plugin-config.h"
33 
34 #include "h264frame.h"
35 #ifdef _MSC_VER
36  #include "../../common/trace.h"
37 #else
38  #include "trace.h"
39 #endif
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #ifndef LICENCE_MPL
44   #ifndef _WIN32
45     #include "../gpl/enc-ctx.h"
46     #include "../gpl/x264loader_unix.h"
47     extern X264Library X264Lib;
48   #else
49     #include "../gpl/x264loader_win32.h"
50     extern X264Library X264Lib;
51   #endif
52 #endif
53 
54 #define H264_PAYLOAD_SIZE      1400
55 #define MAX_NAL_BUFFER 150  // Max NAL Buffer at H264_PAYLOAD_SIZE byte NAL Units
56 #define MAX_FRAME_SIZE (MAX_NAL_BUFFER * H264_PAYLOAD_SIZE) + 12 // 150 Complete NAL Units plus header
57 
H264Frame()58 H264Frame::H264Frame ()
59 {
60   _timestamp = 0;
61   _maxPayloadSize = H264_PAYLOAD_SIZE;
62   _encodedFrame = (uint8_t*)malloc(MAX_FRAME_SIZE);
63   _NALs = NULL;
64   _numberOfNALsReserved = 0;
65   _nalBuffer = MAX_NAL_BUFFER;
66 
67   BeginNewFrame();
68 }
69 
BeginNewFrame()70 void H264Frame::BeginNewFrame ()
71 {
72   _encodedFrameLen = 0;
73 
74   _numberOfNALsInFrame = 0;
75   _currentNAL = 0;
76 
77   _currentNALFURemainingLen = 0;
78   _currentNALFURemainingDataPtr = NULL;
79   _currentNALFUHeader0 = 0;
80   _currentNALFUHeader1 = 0;
81 
82   _currentFU = 0;
83 
84 }
85 
~H264Frame()86 H264Frame::~H264Frame ()
87 {
88   if (_encodedFrame) free (_encodedFrame);
89   if (_NALs) free(_NALs);
90 }
91 
92 #ifndef LICENCE_MPL
93 
94 #if X264_BUILD > 79
x264_nal_encode(uint8_t * p_data,int * pi_data,int b_annexeb,x264_nal_t * nal)95 int x264_nal_encode(uint8_t *p_data, int *pi_data, int b_annexeb, x264_nal_t *nal )
96 {
97      uint8_t *dst = p_data;
98      uint8_t *src = nal->p_payload;
99      uint8_t *end = &nal->p_payload[nal->i_payload];
100      int i_count = 0;
101 
102      /* FIXME this code doesn't check overflow */
103      if( b_annexeb ) {
104          /* long nal start code (we always use long ones)*/
105          *dst++ = 0x00;
106          *dst++ = 0x00;
107          *dst++ = 0x00;
108          *dst++ = 0x01;
109      }
110 
111      /* nal header */
112      *dst++ = ( 0x00 << 7 ) | ( nal->i_ref_idc << 5 ) | nal->i_type;
113 
114      while( src < end ) {
115          if( i_count == 2 && *src <= 0x03 ) {
116              *dst++ = 0x03;
117              i_count = 0;
118          }
119          if( *src == 0 )
120              i_count++;
121          else
122              i_count = 0;
123          *dst++ = *src++;
124      }
125      *pi_data = dst - (uint8_t*)p_data;
126 
127      return *pi_data;
128  }
129 #endif
130 
SetMaxPayloadSize(uint16_t maxPayloadSize)131 void H264Frame::SetMaxPayloadSize (uint16_t maxPayloadSize) {
132 
133    _maxPayloadSize = maxPayloadSize;
134 
135 }
136 
SetFromFrame(x264_nal_t * NALs,int numberOfNALs)137 void H264Frame::SetFromFrame (x264_nal_t *NALs, int numberOfNALs) {
138   //int vopBufferLen;
139   int currentNAL = 0;
140 
141   int encodedNALS = numberOfNALs;
142   if (numberOfNALs > _nalBuffer) {
143       TRACE(1, "H264\tENC\tNAL Buffer Exceeded (" << numberOfNALs << ") Truncating..");
144       encodedNALS = _nalBuffer;
145   }
146 
147   uint8_t* currentPositionInFrame=(uint8_t*) _encodedFrame;
148   if (_NALs) free(_NALs);
149   _NALs = (h264_nal_t *)malloc(encodedNALS * sizeof(h264_nal_t));
150 
151   _encodedFrameLen = 0;
152   _numberOfNALsInFrame = 0;
153   _currentNAL=0;
154 
155   //TRACE (4, "H264\tEncap\tEncoded " << encodedNALS << " NALs");
156 
157   // read the nals out of the encoder and create meta data about their location and size in the frame
158   for (currentNAL = 0; currentNAL < encodedNALS; currentNAL++) {
159     int currentNALLen;
160 //   currentNALLen = X264_NAL_ENCODE(currentPositionInFrame, &vopBufferLen, 1, &NALs[currentNAL]);
161     currentNALLen = NALs[currentNAL].i_payload;
162     memcpy(currentPositionInFrame,NALs[currentNAL].p_payload,currentNALLen);
163     if (currentNALLen > 0)
164     {
165       _NALs[_numberOfNALsInFrame].length = currentNALLen;
166       _NALs[_numberOfNALsInFrame].offset = _encodedFrameLen;
167       _NALs[_numberOfNALsInFrame].type = NALs[currentNAL].i_type;
168       uint32_t header = 0;
169       if (IsStartCode(currentPositionInFrame))
170       {
171 	header = currentPositionInFrame[2] == 1 ? 3 : 4;
172       }
173       _NALs[_numberOfNALsInFrame].length -= header;
174       _NALs[_numberOfNALsInFrame].offset += header;
175       TRACE_UP(4, "H264\tEncap\tLoaded NAL unit #" << currentNAL << " - type " << NALs[currentNAL].i_type);
176   //    TRACE (4, "H264\tEncap\tLoaded NAL unit #" << currentNAL << " - type " << NALs[currentNAL].i_type << " size " << currentNALLen );
177 
178       uint8_t* NALptr = NALs[currentNAL].p_payload;
179       if ( Trace::CanTraceUserPlane(4) && (NALs[currentNAL].i_type == H264_NAL_TYPE_SEQ_PARAM))
180       {
181       TRACE_UP(4,   "H264\tEncap\tProfile: " << (int)NALptr[0] <<
182                                 " Level: "   << (int)NALptr[2] <<
183 		   	        " Constraints: " << (NALptr[1] & 0x80 ? 1 : 0)
184 			                         << (NALptr[1] & 0x40 ? 1 : 0)
185 					         << (NALptr[1] & 0x20 ? 1 : 0)
186 					         << (NALptr[1] & 0x10 ? 1 : 0));
187       }
188 
189       _numberOfNALsInFrame++;
190       _encodedFrameLen += currentNALLen;
191       currentPositionInFrame += currentNALLen;
192     }
193     else
194     {
195       TRACE_UP(4,"[enc] Need to increase vop buffer size by  " << -currentNALLen);
196     }
197   }
198   TRACE_UP(4, "H264\tEncap\tLoaded an encoded frame of " << _encodedFrameLen << " bytes consisiting of " <<  _numberOfNALsInFrame << " NAL units");
199 }
200 #endif
201 
GetRTPFrame(RTPFrame & frame,unsigned int & flags)202 bool H264Frame::GetRTPFrame(RTPFrame & frame, unsigned int & flags)
203 {
204   flags = 0;
205   flags |= (IsSync()) ? isIFrame : 0;
206   if (_currentNAL < _numberOfNALsInFrame)
207   {
208     uint32_t curNALLen = _NALs[_currentNAL].length;
209     const uint8_t *curNALPtr = _encodedFrame + _NALs[_currentNAL].offset;
210     /*
211      * We have 3 types of packets we can send:
212      * fragmentation units - if the NAL is > max_payload_size
213      * single nal units - if the NAL is < max_payload_size, and can only fit 1 NAL
214      * single time aggregation units - if we can put multiple NALs into one packet
215      *
216      * We don't send multiple time aggregation units
217      */
218 
219     if (curNALLen > _maxPayloadSize)
220     {
221       // fragmentation unit - break up into max_payload_size size chunks
222       return EncapsulateFU(frame, flags);
223     }
224     else
225     {
226       // it is the last NAL of that frame or doesnt fit into an STAP packet with next nal ?
227 #ifdef SEND_STAP_PACKETS
228       if (((_currentNAL + 1) >= _numberOfNALsInFrame)  ||
229 	  ((curNALLen + _NALs[_currentNAL + 1].length + 5) > _maxPayloadSize))
230       {
231 #endif
232         // single nal unit packet
233 
234         frame.SetPayloadSize(curNALLen);
235         memcpy(frame.GetPayloadPtr(), curNALPtr, curNALLen);
236         frame.SetTimestamp(_timestamp);
237         frame.SetMarker((_currentNAL + 1) >= _numberOfNALsInFrame ? 1 : 0);
238         flags |= frame.GetMarker() ? isLastFrame : 0;  // marker bit on last frame of video
239 
240         TRACE_UP(4, "H264\tEncap\tEncapsulating NAL unit #" << _currentNAL << "/" << (_numberOfNALsInFrame-1) << " of " << curNALLen << " bytes as a regular NAL unit");
241         _currentNAL++;
242         return true;
243 #ifdef SEND_STAP_PACKETS
244       }
245       else
246       {
247         return EncapsulateSTAP(frame, flags);
248       }
249 #endif
250     }
251   }
252   else
253   {
254     return false;
255   }
256 }
257 
EncapsulateSTAP(RTPFrame & frame,unsigned int & flags)258 bool H264Frame::EncapsulateSTAP (RTPFrame & frame, unsigned int & flags) {
259   uint32_t STAPLen = 1;
260   uint32_t highestNALNumberInSTAP = _currentNAL;
261 
262   // first check how many nals we want to put into the packet
263   do {
264     STAPLen += 2;
265     STAPLen +=  _NALs[highestNALNumberInSTAP].length;
266     highestNALNumberInSTAP++;
267   } while (highestNALNumberInSTAP < _numberOfNALsInFrame && STAPLen < _maxPayloadSize);
268 
269   if (STAPLen > _maxPayloadSize)
270   {
271     STAPLen -= 2;
272     STAPLen -= _NALs[(highestNALNumberInSTAP-1)].length;
273     highestNALNumberInSTAP--;
274   }
275 
276   TRACE_UP(4, "H264\tEncap\tEncapsulating NAL units " << _currentNAL << "-"<< (highestNALNumberInSTAP-1) << "/" << (_numberOfNALsInFrame-1) << " as a STAP of " << STAPLen);
277 
278   frame.SetPayloadSize(1); // for stap header
279 
280   uint32_t curNALLen;
281   const uint8_t* curNALPtr;
282   uint8_t  maxNRI = 0;
283   while (_currentNAL < highestNALNumberInSTAP) {
284     curNALLen = _NALs[_currentNAL].length;
285     curNALPtr = _encodedFrame + _NALs[_currentNAL].offset;
286 
287     // store the nal length information
288     frame.SetPayloadSize(frame.GetPayloadSize() + 2);
289     *((uint8_t*)frame.GetPayloadPtr() + frame.GetPayloadSize() - 2) = curNALLen >> 8;
290     *((uint8_t*)frame.GetPayloadPtr() + frame.GetPayloadSize() - 1) = curNALLen & 0xff;
291 
292     // store the nal
293     frame.SetPayloadSize(frame.GetPayloadSize() + curNALLen);
294     memcpy ((uint8_t*)frame.GetPayloadPtr() + frame.GetPayloadSize() - curNALLen, (void *)curNALPtr, curNALLen);
295 
296     if ((*curNALPtr & 0x60) > maxNRI) maxNRI = *curNALPtr & 0x60;
297     TRACE_UP(4, "H264\tEncap\tAdding NAL unit " << _currentNAL << "/" << (_numberOfNALsInFrame-1) << " of " << curNALLen << " bytes to STAP");
298     _currentNAL++;
299   }
300 
301   // set the nri value in the stap header
302   //uint8_t stap = 24 | maxNRI;
303   //memcpy (frame.GetPayloadPtr(),&stap,1);
304   memset (frame.GetPayloadPtr(), 24 | maxNRI, 1);
305   frame.SetTimestamp(_timestamp);
306   frame.SetMarker(_currentNAL >= _numberOfNALsInFrame ? 1 : 0);
307   flags |= frame.GetMarker() ? isLastFrame : 0;  // marker bit on last frame of video
308 
309   return true;
310 }
311 
312 
EncapsulateFU(RTPFrame & frame,unsigned int & flags)313 bool H264Frame::EncapsulateFU(RTPFrame & frame, unsigned int & flags) {
314   uint8_t header[2];
315   uint32_t curFULen;
316 
317   if ((_currentNALFURemainingLen==0) || (_currentNALFURemainingDataPtr==NULL))
318   {
319     _currentNALFURemainingLen = _NALs[_currentNAL].length;
320     _currentNALFURemainingDataPtr = _encodedFrame + _NALs[_currentNAL].offset;
321     _currentNALFUHeader0 = (*_currentNALFURemainingDataPtr & 0x60) | 28;
322     _currentNALFUHeader1 = *_currentNALFURemainingDataPtr & 0x1f;
323     header[0] = _currentNALFUHeader0;
324     header[1] = 0x80 | _currentNALFUHeader1; // s indication
325     _currentNALFURemainingDataPtr++; // remove the first byte
326     _currentNALFURemainingLen--;
327   }
328   else
329   {
330     header[0] = _currentNALFUHeader0;
331     header[1] = _currentNALFUHeader1;
332   }
333 
334   if (_currentNALFURemainingLen > 0)
335   {
336     bool last = false;
337     if ((_currentNALFURemainingLen + 2) <= _maxPayloadSize)
338     {
339       header[1] |= 0x40;
340       curFULen = _currentNALFURemainingLen;
341       last = true;
342     }
343     else
344     {
345       curFULen = _maxPayloadSize - 2;
346     }
347 
348     frame.SetPayloadSize(curFULen + 2);
349     memcpy ((uint8_t*)frame.GetPayloadPtr(), header, 2);
350     memcpy ((uint8_t*)frame.GetPayloadPtr()+2, _currentNALFURemainingDataPtr, curFULen);
351     frame.SetTimestamp(_timestamp);
352     frame.SetMarker((last && ((_currentNAL+1) >= _numberOfNALsInFrame)) ? 1 : 0);
353     flags |= frame.GetMarker() ? isLastFrame : 0;  // marker bit on last frame of video
354 
355     _currentNALFURemainingDataPtr += curFULen;
356     _currentNALFURemainingLen -= curFULen;
357     TRACE_UP(4, "H264\tEncap\tEncapsulating "<< curFULen << " bytes of NAL " << _currentNAL<< "/" << (_numberOfNALsInFrame-1) << " as a FU (" << _currentNALFURemainingLen << " bytes remaining)");
358   }
359   if (_currentNALFURemainingLen==0)
360   {
361     _currentNAL++;
362     _currentNALFURemainingDataPtr=NULL;
363   }
364   return true;
365 }
366 
SetFromRTPFrame(RTPFrame & frame,unsigned int & flags)367 bool H264Frame::SetFromRTPFrame(RTPFrame & frame, unsigned int & flags) {
368   uint8_t curNALType = *(frame.GetPayloadPtr()) & 0x1f;
369 
370   if (curNALType >= H264_NAL_TYPE_NON_IDR_SLICE &&
371       curNALType <= H264_NAL_TYPE_FILLER_DATA)
372   {
373     // regular NAL - put in buffer, adding the header.
374     TRACE_UP(4, "H264\tDeencap\tDeencapsulating a regular NAL unit NAL of " << frame.GetPayloadSize() - 1 << " bytes (type " << (int) curNALType << ")");
375     AddDataToEncodedFrame(frame.GetPayloadPtr() + 1, frame.GetPayloadSize() - 1, *(frame.GetPayloadPtr()), 1);
376   }
377   else if (curNALType == 24)
378   {
379     // stap-A (single time aggregation packet )
380     return DeencapsulateSTAP (frame, flags);
381   }
382   else if (curNALType == 28)
383   {
384     // Fragmentation Units
385     return DeencapsulateFU (frame, flags);
386   }
387   else
388   {
389     TRACE_UP(4, "H264\tDeencap\tSkipping unsupported NAL unit type " << curNALType);
390     return false;
391   }
392   return true;
393 }
IsSync()394 bool H264Frame::IsSync () {
395   uint32_t i;
396 
397   for (i=0; i<_numberOfNALsInFrame; i++)
398   {
399     if ((_NALs[i].type == H264_NAL_TYPE_IDR_SLICE) ||
400         (_NALs[i].type == H264_NAL_TYPE_SEQ_PARAM) ||
401         (_NALs[i].type == H264_NAL_TYPE_PIC_PARAM))
402     {
403       return true;
404     }
405   }
406   return false;
407 }
408 
DeencapsulateSTAP(RTPFrame & frame,unsigned int &)409 bool H264Frame::DeencapsulateSTAP (RTPFrame & frame, unsigned int & /*flags*/) {
410   uint8_t* curSTAP = frame.GetPayloadPtr() + 1;
411   uint32_t curSTAPLen = frame.GetPayloadSize() - 1;
412 
413   TRACE_UP(4, "H264\tDeencap\tDeencapsulating a STAP of " << curSTAPLen << " bytes");
414   while (curSTAPLen > 0)
415   {
416     // first, theres a 2 byte length field
417     uint32_t len = (curSTAP[0] << 8) | curSTAP[1];
418     curSTAP += 2;
419     // then the header, followed by the body.  We'll add the header
420     // in the AddDataToEncodedFrame - that's why the nal body is dptr + 1
421     TRACE_UP(4, "H264\tDeencap\tDeencapsulating an NAL unit of " << len << " bytes (type " << (int)(*curSTAP & 0x1f) << ") from STAP");
422     AddDataToEncodedFrame(curSTAP + 1,  len - 1, *curSTAP, 1);
423     curSTAP += len;
424     if ((len + 2) > curSTAPLen)
425     {
426       curSTAPLen = 0;
427       TRACE(1, "H264\tDeencap\tError deencapsulating STAP, STAP header says its " << len + 2 << " bytes long but there are only " << curSTAPLen << " bytes left of the packet");
428       return false;
429     }
430     else
431     {
432       curSTAPLen -= (len + 2);
433     }
434   }
435   return true;
436 }
437 
DeencapsulateFU(RTPFrame & frame,unsigned int &)438 bool H264Frame::DeencapsulateFU (RTPFrame & frame, unsigned int & /*flags*/) {
439   uint8_t* curFUPtr = frame.GetPayloadPtr();
440   uint32_t curFULen = frame.GetPayloadSize();
441   uint8_t header;
442 
443   if ((curFUPtr[1] & 0x80) && !(curFUPtr[1] & 0x40))
444   {
445     TRACE_UP(4, "H264\tDeencap\tDeencapsulating a FU of " << frame.GetPayloadSize() - 1 << " bytes (_Startbit_, !Endbit)");
446     if (_currentFU) {
447       _currentFU=1;
448     }
449     else
450     {
451       _currentFU++;
452       header = (curFUPtr[0] & 0xe0) | (curFUPtr[1] & 0x1f);
453       AddDataToEncodedFrame(curFUPtr + 2, curFULen - 2, header,  1);
454     }
455   }
456   else if (!(curFUPtr[1] & 0x80) && !(curFUPtr[1] & 0x40))
457   {
458     TRACE_UP(4, "H264\tDeencap\tDeencapsulating a FU of " << frame.GetPayloadSize() - 1 << " bytes (!Startbit, !Endbit)");
459     if (_currentFU)
460     {
461       _currentFU++;
462       AddDataToEncodedFrame(curFUPtr + 2, curFULen - 2,  0, 0);
463     }
464     else
465     {
466       _currentFU=0;
467       TRACE(1, "H264\tDeencap\tReceived an intermediate FU without getting the first - dropping!");
468       return false;
469     }
470   }
471   else if (!(curFUPtr[1] & 0x80) && (curFUPtr[1] & 0x40))
472   {
473     TRACE_UP(4, "H264\tDeencap\tDeencapsulating a FU of " << frame.GetPayloadSize() - 1 << " bytes (!Startbit, _Endbit_)");
474     if (_currentFU) {
475       _currentFU=0;
476       AddDataToEncodedFrame( curFUPtr + 2, curFULen - 2, 0, 0);
477     }
478     else
479     {
480       _currentFU=0;
481       TRACE(1, "H264\tDeencap\tReceived a last FU without getting the first - dropping!");
482       return false;
483     }
484   }
485   else if ((curFUPtr[1] & 0x80) && (curFUPtr[1] & 0x40))
486   {
487     TRACE_UP(4, "H264\tDeencap\tDeencapsulating a FU of " << frame.GetPayloadSize() - 1 << " bytes (_Startbit_, _Endbit_)");
488     TRACE(1, "H264\tDeencap\tReceived a FU with both Starbit and Endbit set - This MUST NOT happen!");
489     _currentFU=0;
490     return false;
491   }
492   return true;
493 }
494 
AddDataToEncodedFrame(uint8_t * data,uint32_t dataLen,uint8_t header,bool addHeader)495 void H264Frame::AddDataToEncodedFrame (uint8_t *data, uint32_t dataLen, uint8_t header, bool addHeader) {
496   uint8_t headerLen= addHeader ? 5 : 0;
497   uint8_t* currentPositionInFrame = _encodedFrame + _encodedFrameLen;
498 
499   if (addHeader)
500   {
501     TRACE_UP(4, "H264\tDeencap\tAdding a NAL unit of " << dataLen << " bytes to buffer (type " << (int)(header & 0x1f) << ")");
502     uint8_t* NALptr = data;
503     if ( Trace::CanTraceUserPlane(4) && ((header & 0x1f) == H264_NAL_TYPE_SEQ_PARAM) && (dataLen >= 3))
504     {
505       TRACE_UP(4, "H264\tDeencap\tProfile: " << (int)NALptr[0] <<
506                                 " Level: "   << (int)NALptr[2] <<
507 			        " Constraints: " << (NALptr[1] & 0x80 ? 1 : 0)
508 			                         << (NALptr[1] & 0x40 ? 1 : 0)
509 					         << (NALptr[1] & 0x20 ? 1 : 0)
510 					         << (NALptr[1] & 0x10 ? 1 : 0));
511     }
512   }
513   else TRACE_UP(4, "H264\tDeencap\tAdding a NAL unit of " << dataLen << " bytes to buffer");
514 
515   if (_encodedFrameLen + dataLen + headerLen > MAX_FRAME_SIZE) {
516     TRACE(1, "H264\tDeencap\tFrame too big (" << _encodedFrameLen + dataLen + headerLen << ">" << MAX_FRAME_SIZE << ")");
517     return;
518   }
519 
520   // add 00 00 01 [headerbyte] header
521   if (addHeader)
522   {
523     *currentPositionInFrame++ = 0;
524     *currentPositionInFrame++ = 0;
525     *currentPositionInFrame++ = 0;
526     *currentPositionInFrame++ = 1;
527 
528     if (_numberOfNALsInFrame + 1 >(_numberOfNALsReserved))
529     {
530       _NALs = (h264_nal_t *)realloc(_NALs, (_numberOfNALsReserved + 1) * sizeof(h264_nal_t));
531       _numberOfNALsReserved++;
532     }
533     if (_NALs)
534     {
535       _NALs[_numberOfNALsInFrame].offset = _encodedFrameLen + 4;
536       _NALs[_numberOfNALsInFrame].length = dataLen + 1;
537       _NALs[_numberOfNALsInFrame].type = header & 0x1f;
538 
539 
540       _numberOfNALsInFrame++;
541     }
542 
543     *currentPositionInFrame++ = header;
544   }
545   else
546   {
547     if (_NALs) _NALs[_numberOfNALsInFrame - 1].length += dataLen;
548   }
549 
550   if (_NALs) {
551     TRACE_UP (4, "H264\tDeencap\tReserved memory for  " <<_numberOfNALsReserved <<" NALs, Inframe/current: "<< _numberOfNALsInFrame <<" Offset: "
552       <<_NALs[_numberOfNALsInFrame-1].offset << " Length: "<< _NALs[_numberOfNALsInFrame-1].length << " Type: "<< (int)(_NALs[_numberOfNALsInFrame-1].type));
553   } else {
554     TRACE_UP (4, "H264\tDeencap\t_NALs is NULL");
555   }
556 
557   memcpy(currentPositionInFrame, data, dataLen);
558   _encodedFrameLen += dataLen + headerLen;
559 }
560 
IsStartCode(const uint8_t * positionInFrame)561 bool H264Frame::IsStartCode (const uint8_t *positionInFrame)
562 {
563   if (positionInFrame[0] == 0 &&
564       positionInFrame[1] == 0 &&
565     ((positionInFrame[2] == 1) ||
566     ((positionInFrame[2] == 0) && positionInFrame[3] == 1)))
567   {
568     return true;
569   }
570   return false;
571 }
572 
573 
574 
575 
576