Home | History | Annotate | Download | only in parser
      1 #include "viddec_pm_parse.h"
      2 #include "viddec_fw_debug.h"
      3 #include "viddec_mp4_parse.h"
      4 
      5 /* Parse for Sc code of pattern 0x00 0x00 0xXX in the current buffer. Returns either sc found or success.
      6    The conext is updated with current phase and sc_code position in the buffer.
      7 
      8    What is phase?: phase is a value between [0-4], we keep track of consecutive '0's with this.
      9    Any time a '0' is found its incremented by 1(uptp 2) and reset to '0' if a zero not found.
     10    if 0xXX code is found and current phase is 2, its changed to 3 which means we found the pattern
     11    we are looking for. Its incremented to 4 once we see a byte after this pattern.
     12 
     13    For MP4 there are two startcode patterns LVH & SVH. LVH is same as other codecs (00 00 01), SVH
     14    A.K.A H263 is (00 00 8X). So we have to look for both kind of start codes. The spec doesn't
     15    explicitly say if both of them can exist in a stream? So current implemenation will assume
     16    that only one of them is present in a given stream to simplify implementation. The reason it can
     17    get complicated is resync marker in LVH can potentially be (00 00 8) which will cause false detect
     18    of SVH start code.
     19 */
     20 
     21 uint32_t viddec_parse_sc_mp4(void *in, void *pcxt, void *sc_state)
     22 {
     23     uint8_t *ptr;
     24     uint32_t size;
     25     uint32_t data_left=0, phase = 0, ret = 0;
     26     viddec_sc_parse_cubby_cxt_t *cxt;
     27     viddec_mp4_parser_t *p_info;
     28 
     29     cxt = ( viddec_sc_parse_cubby_cxt_t *)in;
     30     viddec_sc_prefix_state_t *state = (viddec_sc_prefix_state_t *)sc_state;
     31     size = 0;
     32     data_left = cxt->size;
     33     ptr = cxt->buf;
     34     phase = cxt->phase;
     35     cxt->sc_end_pos = -1;
     36     p_info = (viddec_mp4_parser_t *)pcxt;
     37 
     38     /* parse until there is more data and start code not found */
     39     while((data_left > 0) &&(phase < 3))
     40     {
     41         /* Check if we are byte aligned & phase=0, if thats the case we can check
     42            work at a time instead of byte*/
     43         if(((((uint32_t)ptr) & 0x3) == 0) && (phase == 0))
     44         {
     45             while(data_left > 3)
     46             {
     47                 uint32_t data;
     48                 char mask1 = 0, mask2=0;
     49 
     50                 data = *((uint32_t *)ptr);
     51 #ifndef MFDBIGENDIAN
     52                 data = SWAP_WORD(data);
     53 #endif
     54                 mask1 = (FIRST_STARTCODE_BYTE != (data & SC_BYTE_MASK0));
     55                 mask2 = (FIRST_STARTCODE_BYTE != (data & SC_BYTE_MASK1));
     56                 /* If second byte and fourth byte are not zero's then we cannot have a start code here as we need
     57                    two consecutive zero bytes for a start code pattern */
     58                 if(mask1 && mask2)
     59                 {/* Success so skip 4 bytes and start over */
     60                     ptr+=4;size+=4;data_left-=4;
     61                     continue;
     62                 }
     63                 else
     64                 {
     65                     break;
     66                 }
     67             }
     68         }
     69 
     70         /* At this point either data is not on a word boundary or phase > 0 or On a word boundary but we detected
     71            two zero bytes in the word so we look one byte at a time*/
     72         if(data_left > 0)
     73         {
     74             if(*ptr == FIRST_STARTCODE_BYTE)
     75             {/* Phase can be 3 only if third start code byte is found */
     76                 phase++;
     77                 ptr++;size++;data_left--;
     78                 if(phase > 2)
     79                 {
     80                     phase = 2;
     81 
     82                     if ( (((uint32_t)ptr) & 0x3) == 0 )
     83                     {
     84                         while( data_left > 3 )
     85                         {
     86                             if(*((uint32_t *)ptr) != 0)
     87                             {
     88                                 break;
     89                             }
     90                             ptr+=4;size+=4;data_left-=4;
     91                         }
     92                     }
     93                 }
     94             }
     95             else
     96             {
     97                 uint8_t normal_sc=0, short_sc=0;
     98                 if(phase == 2)
     99                 {
    100                     normal_sc = (*ptr == THIRD_STARTCODE_BYTE);
    101                     short_sc  = (p_info->ignore_scs == 0) && (SHORT_THIRD_STARTCODE_BYTE == ( *ptr & 0xFC));
    102                 }
    103 
    104                 if(!(normal_sc | short_sc))
    105                 {
    106                     phase = 0;
    107                 }
    108                 else
    109                 {/* Match for start code so update context with byte position */
    110                     cxt->sc_end_pos = size;
    111                     phase = 3;
    112                     p_info->cur_sc_prefix = p_info->next_sc_prefix;
    113                     p_info->next_sc_prefix = (normal_sc) ? 1: 0;
    114                     if(normal_sc)
    115                     {
    116                         p_info->ignore_scs=1;
    117                     }
    118                     else
    119                     {
    120                         /* For short start code since start code is in one nibble just return at this point */
    121                         phase += 1;
    122                         state->next_sc = *ptr;
    123                         state->second_scprfx_length = 2;
    124                         ret=1;
    125                         break;
    126                     }
    127                 }
    128                 ptr++;size++;data_left--;
    129             }
    130         }
    131     }
    132     if((data_left > 0) && (phase == 3))
    133     {
    134         cxt->sc_end_pos++;
    135         state->next_sc = cxt->buf[cxt->sc_end_pos];
    136         state->second_scprfx_length = 3;
    137         phase++;
    138         ret = 1;
    139     }
    140     cxt->phase = phase;
    141     /* Return SC found only if phase is 4, else always success */
    142     return ret;
    143 }
    144