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