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