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