1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010 - 2013, 2018, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of The Linux Foundation nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "frameparser.h"
33 #include "qc_omx_msg.h"
34
35 #ifdef _ANDROID_
36 extern "C" {
37 #include<utils/Log.h>
38 }
39 #endif//_ANDROID_
40
41 static unsigned char H264_mask_code[4] = {0xFF,0xFF,0xFF,0xFF};
42 static unsigned char H264_start_code[4] = {0x00,0x00,0x00,0x01};
43
44 static unsigned char MPEG2_start_code[4] = {0x00, 0x00, 0x01, 0x00};
45 static unsigned char MPEG2_mask_code[4] = {0xFF, 0xFF, 0xFF, 0xFF};
46
frame_parse()47 frame_parse::frame_parse():mutils(NULL),
48 parse_state(A0),
49 start_code(NULL),
50 mask_code(NULL),
51 last_byte(0),
52 header_found(false),
53 skip_frame_boundary(false),
54 state_nal(NAL_LENGTH_ACC),
55 nal_length(0),
56 accum_length(0),
57 bytes_tobeparsed(0)
58 {
59 }
60
~frame_parse()61 frame_parse::~frame_parse ()
62 {
63 if (mutils)
64 delete mutils;
65
66 mutils = NULL;
67 }
68
init_start_codes(codec_type codec_type_parse)69 int frame_parse::init_start_codes (codec_type codec_type_parse)
70 {
71 /*Check if Codec Type is proper and we are in proper state*/
72 if (codec_type_parse > CODEC_TYPE_MAX || parse_state != A0) {
73 return -1;
74 }
75
76 switch (codec_type_parse) {
77 case CODEC_TYPE_H264:
78 case CODEC_TYPE_HEVC:
79 start_code = H264_start_code;
80 mask_code = H264_mask_code;
81 break;
82 case CODEC_TYPE_MPEG2:
83 start_code = MPEG2_start_code;
84 mask_code = MPEG2_mask_code;
85 break;
86 default:
87 return -1;
88 }
89
90 return 1;
91 }
92
93
init_nal_length(unsigned int nal_len)94 int frame_parse::init_nal_length (unsigned int nal_len)
95 {
96 if (nal_len == 0 || nal_len > 4 || state_nal != NAL_LENGTH_ACC) {
97 return -1;
98 }
99
100 nal_length = nal_len;
101
102 return 1;
103 }
104
parse_sc_frame(OMX_BUFFERHEADERTYPE * source,OMX_BUFFERHEADERTYPE * dest,OMX_U32 * partialframe)105 int frame_parse::parse_sc_frame ( OMX_BUFFERHEADERTYPE *source,
106 OMX_BUFFERHEADERTYPE *dest ,
107 OMX_U32 *partialframe)
108 {
109 OMX_U8 *pdest = NULL,*psource = NULL, match_found = FALSE, is_byte_match = 0;
110 OMX_U32 dest_len =0, source_len = 0, temp_len = 0;
111 OMX_U32 parsed_length = 0,i=0;
112 int residue_byte = 0;
113
114 if (source == NULL || dest == NULL || partialframe == NULL) {
115 return -1;
116 }
117
118 /*Calculate how many bytes are left in source and destination*/
119 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
120 psource = source->pBuffer + source->nOffset;
121 pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
122 source_len = source->nFilledLen;
123
124 /*Need Minimum Start Code size for destination to copy atleast Start code*/
125 if ((dest_len < 4) || (source_len == 0)) {
126 DEBUG_PRINT("FrameParser: dest_len %u source_len %u",(unsigned int)dest_len, (unsigned int)source_len);
127
128 if (source_len == 0 && (source->nFlags & 0x01)) {
129 DEBUG_PRINT("FrameParser: EOS rxd!! Notify it as a complete frame");
130 *partialframe = 0;
131 return 1;
132 }
133
134 DEBUG_PRINT("FrameParser: Bitstream Parsing error");
135 return -1;
136 }
137
138 /*Check if State of the previous find is a Start code*/
139 if (parse_state == A4 || parse_state == A5) {
140 /*Check for minimun size should be 4*/
141 dest->nFlags = source->nFlags;
142 dest->nTimeStamp = source->nTimeStamp;
143
144 memcpy (pdest,start_code,4);
145
146 if (start_code == MPEG2_start_code) {
147 pdest[3] = last_byte;
148 update_skip_frame();
149 }
150
151 dest->nFilledLen += 4;
152 pdest += 4;
153
154 parse_state = A0;
155 }
156
157 /*Entry State Machine*/
158 while ( source->nFilledLen > 0 && parse_state != A0
159 && parse_state != A4 && parse_state != A5 && dest_len > 0
160 ) {
161 //printf ("In the Entry Loop");
162 switch (parse_state) {
163 case A3:
164 parse_additional_start_code(psource,&parsed_length);
165
166 if (parse_state == A4) {
167 source->nFilledLen--;
168 source->nOffset++;
169 psource++;
170 break;
171 }
172
173 /*If fourth Byte is matching then start code is found*/
174 if ((*psource & mask_code [3]) == start_code [3]) {
175 parse_state = A4;
176 last_byte = *psource;
177 source->nFilledLen--;
178 source->nOffset++;
179 psource++;
180 } else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1])) {
181 parse_state = A2;
182 memcpy (pdest,start_code,1);
183 pdest++;
184 dest->nFilledLen++;
185 dest_len--;
186 } else if (start_code [2] == start_code [0]) {
187 parse_state = A1;
188 memcpy (pdest,start_code,2);
189 pdest += 2;
190 dest->nFilledLen += 2;
191 dest_len -= 2;
192 } else {
193 parse_state = A0;
194 memcpy (pdest,start_code,3);
195 pdest += 3;
196 dest->nFilledLen +=3;
197 dest_len -= 3;
198 }
199
200 break;
201
202 case A2:
203 is_byte_match = ((*psource & mask_code [2]) == start_code [2]);
204 match_found = FALSE;
205
206 if (start_code == H264_start_code &&
207 (*psource & mask_code [3]) == start_code [3]) {
208 parse_state = A5;
209 match_found = TRUE;
210 } else {
211 if (is_byte_match) {
212 parse_state = A3;
213 match_found = TRUE;
214 }
215 }
216
217 if (match_found) {
218 source->nFilledLen--;
219 source->nOffset++;
220 psource++;
221 } else if (start_code [1] == start_code [0]) {
222 parse_state = A1;
223 memcpy (pdest,start_code,1);
224 dest->nFilledLen +=1;
225 dest_len--;
226 pdest++;
227 } else {
228 parse_state = A0;
229 memcpy (pdest,start_code,2);
230 dest->nFilledLen +=2;
231 dest_len -= 2;
232 pdest += 2;
233 }
234
235 break;
236
237 case A1:
238
239 if ((*psource & mask_code [1]) == start_code [1]) {
240 parse_state = A2;
241 source->nFilledLen--;
242 source->nOffset++;
243 psource++;
244 } else {
245 memcpy (pdest,start_code,1);
246 dest->nFilledLen +=1;
247 pdest++;
248 dest_len--;
249 parse_state = A0;
250 }
251
252 break;
253 case A4:
254 case A0:
255 case A5:
256 break;
257 }
258
259 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
260 }
261
262 if (parse_state == A4 || parse_state == A5) {
263 *partialframe = 0;
264 check_skip_frame_boundary(partialframe);
265 DEBUG_PRINT("FrameParser: Parsed Len = %u", (unsigned int)dest->nFilledLen);
266 return 1;
267 }
268
269 /*Partial Frame is true*/
270 *partialframe = 1;
271
272 /*Calculate how many bytes are left in source and destination*/
273 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
274 psource = source->pBuffer + source->nOffset;
275 pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
276 source_len = source->nFilledLen;
277
278 temp_len = (source_len < dest_len)?source_len:dest_len;
279
280 /*Check if entry state machine consumed source or destination*/
281 if (temp_len == 0) {
282 return 1;
283 }
284
285 /*Parsing State Machine*/
286 while (parsed_length < temp_len) {
287 switch (parse_state) {
288 case A0:
289
290 if ((psource [parsed_length] & mask_code [0]) == start_code[0]) {
291 parse_state = A1;
292 }
293
294 parsed_length++;
295 break;
296 case A1:
297
298 if ((psource [parsed_length] & mask_code [1]) == start_code [1]) {
299 parsed_length++;
300 parse_state = A2;
301 } else {
302 parse_state = A0;
303 }
304
305 break;
306 case A2:
307 is_byte_match = ((psource[parsed_length] & mask_code [2]) == start_code [2]);
308 match_found = FALSE;
309
310 if (start_code == H264_start_code &&
311 (psource[parsed_length] & mask_code [3]) == start_code [3]) {
312 parse_state = A5;
313 match_found = TRUE;
314 } else {
315 if (is_byte_match) {
316 parse_state = A3;
317 match_found = TRUE;
318 }
319 }
320
321 if (match_found) {
322 parsed_length++;
323 } else if (start_code [1] == start_code [0]) {
324 parse_state = A1;
325 } else {
326 parse_state = A0;
327 }
328
329 break;
330 case A3:
331 parse_additional_start_code(psource,&parsed_length);
332
333 if (parse_state == A4) break;
334
335 if ((psource [parsed_length] & mask_code [3]) == start_code [3]) {
336 last_byte = psource [parsed_length];
337 parsed_length++;
338 parse_state = A4;
339 } else if ((start_code [1] == start_code [0]) && (start_code [2] == start_code [1])) {
340 parse_state = A2;
341 } else if (start_code [2] == start_code [0]) {
342 parse_state = A1;
343 } else {
344 parse_state = A0;
345 }
346
347 break;
348 case A4:
349 case A5:
350 break;
351 }
352
353 /*Found the code break*/
354 if (parse_state == A4 || parse_state == A5) {
355 break;
356 }
357 }
358
359 /*Exit State Machine*/
360 psource = source->pBuffer + source->nOffset;
361 OMX_U32 bytes_to_skip = 0;
362 switch (parse_state) {
363 case A5:
364 *partialframe = 0;
365 check_skip_frame_boundary(partialframe);
366 bytes_to_skip = 3;
367 break;
368 case A4:
369 *partialframe = 0;
370 check_skip_frame_boundary(partialframe);
371 bytes_to_skip = 4;
372 break;
373 case A3:
374 if (source->nFlags & OMX_BUFFERFLAG_EOS) {
375 bytes_to_skip = 0;
376 } else {
377 bytes_to_skip = 3;
378 }
379 break;
380 case A2:
381 if (source->nFlags & OMX_BUFFERFLAG_EOS) {
382 bytes_to_skip = 0;
383 } else {
384 bytes_to_skip = 2;
385 }
386 break;
387 case A1:
388 if (source->nFlags & OMX_BUFFERFLAG_EOS) {
389 bytes_to_skip = 0;
390 } else {
391 bytes_to_skip = 1;
392 }
393 break;
394 case A0:
395 bytes_to_skip = 0;
396 break;
397 }
398
399 if (source->nFilledLen < parsed_length) {
400 DEBUG_PRINT_ERROR ("FATAL Error");
401 return -1;
402 }
403
404 if (parsed_length > bytes_to_skip) {
405 memcpy (pdest, psource, (parsed_length-bytes_to_skip));
406 dest->nFilledLen += (parsed_length-bytes_to_skip);
407 }
408
409 source->nFilledLen -= parsed_length;
410 source->nOffset += parsed_length;
411
412 return 1;
413 }
414
415
parse_h264_nallength(OMX_BUFFERHEADERTYPE * source,OMX_BUFFERHEADERTYPE * dest,OMX_U32 * partialframe)416 int frame_parse::parse_h264_nallength (OMX_BUFFERHEADERTYPE *source,
417 OMX_BUFFERHEADERTYPE *dest ,
418 OMX_U32 *partialframe)
419 {
420 OMX_U8 *pdest = NULL,*psource = NULL;
421 OMX_U32 dest_len =0, source_len = 0, temp_len = 0,parsed_length = 0;
422
423 if (source == NULL || dest == NULL || partialframe == NULL) {
424 return -1;
425 }
426
427 /*Calculate the length's*/
428 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
429 source_len = source->nFilledLen;
430
431 if (dest_len < 4 || nal_length == 0) {
432 DEBUG_PRINT("FrameParser: NAL Parsing Error! dest_len %u "
433 "nal_length %u", (unsigned int)dest_len, nal_length);
434 return -1;
435 }
436
437 if (source_len == 0 ) {
438 if (source->nFlags & OMX_BUFFERFLAG_EOS) {
439 DEBUG_PRINT("FrameParser: EOS rxd for nallength!!"
440 " Notify it as a complete frame");
441 *partialframe = 0;
442 return 1;
443 } else {
444 DEBUG_PRINT_ERROR("FrameParser: NAL Parsing Error!"
445 "Buffer recieved with source_len = %u and with"
446 "flags %u", (unsigned int)source_len, (unsigned int)source->nFlags);
447 return -1;
448 }
449 }
450
451 *partialframe = 1;
452 temp_len = (source_len < dest_len)?source_len:dest_len;
453 psource = source->pBuffer + source->nOffset;
454 pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
455
456 /* Find the Bytes to Accumalte*/
457 if (state_nal == NAL_LENGTH_ACC) {
458 while (parsed_length < temp_len ) {
459 bytes_tobeparsed |= (((OMX_U32)(*psource))) << (((nal_length-accum_length-1) << 3));
460
461 accum_length++;
462 source->nFilledLen--;
463 source->nOffset++;
464 psource++;
465 //dest->nFilledLen++;
466 //pdest++;
467 parsed_length++;
468
469 if (accum_length == nal_length) {
470 accum_length = 0;
471 state_nal = NAL_PARSING;
472 memcpy (pdest,H264_start_code,4);
473 dest->nFilledLen += 4;
474 break;
475 }
476 }
477 }
478
479 dest_len = dest->nAllocLen - (dest->nFilledLen + dest->nOffset);
480 source_len = source->nFilledLen;
481 temp_len = (source_len < dest_len)?source_len:dest_len;
482
483 psource = source->pBuffer + source->nOffset;
484 pdest = dest->pBuffer + (dest->nFilledLen + dest->nOffset);
485
486 dest->nTimeStamp = source->nTimeStamp;
487 dest->nFlags = source->nFlags;
488
489 /*Already in Parsing state go ahead and copy*/
490 if (state_nal == NAL_PARSING && temp_len > 0) {
491 if (temp_len < bytes_tobeparsed) {
492 memcpy (pdest,psource,temp_len);
493 dest->nFilledLen += temp_len;
494 source->nOffset += temp_len;
495 source->nFilledLen -= temp_len;
496 bytes_tobeparsed -= temp_len;
497 } else {
498 memcpy (pdest,psource,bytes_tobeparsed);
499 temp_len -= bytes_tobeparsed;
500 dest->nFilledLen += bytes_tobeparsed;
501 source->nOffset += bytes_tobeparsed;
502 source->nFilledLen -= bytes_tobeparsed;
503 bytes_tobeparsed = 0;
504 }
505 }
506
507 if (bytes_tobeparsed == 0 && state_nal == NAL_PARSING) {
508 *partialframe = 0;
509 state_nal = NAL_LENGTH_ACC;
510 }
511
512 return 1;
513 }
514
flush()515 void frame_parse::flush ()
516 {
517 parse_state = A0;
518 state_nal = NAL_LENGTH_ACC;
519 accum_length = 0;
520 bytes_tobeparsed = 0;
521 header_found = false;
522 skip_frame_boundary = false;
523 }
524
parse_additional_start_code(OMX_U8 * psource,OMX_U32 * parsed_length)525 void frame_parse::parse_additional_start_code(OMX_U8 *psource,
526 OMX_U32 *parsed_length)
527 {
528
529 if ((start_code == MPEG2_start_code) &&
530 psource &&
531 parsed_length) {
532 OMX_U32 index = *parsed_length;
533
534 if (start_code == MPEG2_start_code &&
535 psource [index] == 0xB3) {
536 if (header_found) {
537 last_byte = psource [index];
538 index++;
539 parse_state = A4;
540 } else
541 header_found = true;
542 }
543
544 *parsed_length = index;
545 }
546 }
547
check_skip_frame_boundary(OMX_U32 * partialframe)548 void frame_parse::check_skip_frame_boundary(OMX_U32 *partialframe)
549 {
550 if ((start_code == MPEG2_start_code) &&
551 partialframe) {
552
553 *partialframe = 1;
554
555 if (!skip_frame_boundary)
556 *partialframe = 0;
557
558 skip_frame_boundary = false;
559 }
560 }
561
update_skip_frame()562 void frame_parse::update_skip_frame()
563 {
564 if ((start_code == MPEG2_start_code) &&
565 (last_byte == 0xB3)) {
566
567 skip_frame_boundary = true;
568 }
569 }
570