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