1 #include "viddec_pm_parse.h"
2 #include "viddec_fw_debug.h"
3
4 #define FIRST_STARTCODE_BYTE 0x00
5 #define SECOND_STARTCODE_BYTE 0x00
6 #define THIRD_STARTCODE_BYTE 0x01
7
8 /* BIG ENDIAN: Must be the second and fourth byte of the bytestream for this to work */
9 /* LITTLE ENDIAN: Must be the second and fourth byte of the bytestream for this to work */
10 /* these are little-endian defines */
11 #define SC_BYTE_MASK0 0x00ff0000 /* little-endian */
12 #define SC_BYTE_MASK1 0x000000ff /* little-endian */
13
14 /* Parse for Sc code of pattern 0x00 0x00 0xXX in the current buffer. Returns either sc found or success.
15 The conext is updated with current phase and sc_code position in the buffer.
16 */
viddec_parse_sc(void * in,void * pcxt,void * sc_state)17 uint32_t viddec_parse_sc(void *in, void *pcxt, void *sc_state)
18 {
19 uint8_t *ptr;
20 uint32_t size;
21 uint32_t data_left=0, phase = 0, ret = 0;
22 viddec_sc_parse_cubby_cxt_t *cxt;
23 /* What is phase?: phase is a value between [0-4], we keep track of consecutive '0's with this.
24 Any time a '0' is found its incremented by 1(uptp 2) and reset to '0' if a zero not found.
25 if 0xXX code is found and current phase is 2, its changed to 3 which means we found the pattern
26 we are looking for. Its incremented to 4 once we see a byte after this pattern */
27 cxt = ( viddec_sc_parse_cubby_cxt_t *)in;
28 size = 0;
29 data_left = cxt->size;
30 ptr = cxt->buf;
31 phase = cxt->phase;
32 cxt->sc_end_pos = -1;
33 pcxt=pcxt;
34
35 /* parse until there is more data and start code not found */
36 while((data_left > 0) &&(phase < 3))
37 {
38 /* Check if we are byte aligned & phase=0, if thats the case we can check
39 work at a time instead of byte*/
40 if(((((uint32_t)ptr) & 0x3) == 0) && (phase == 0))
41 {
42 while(data_left > 3)
43 {
44 uint32_t data;
45 char mask1 = 0, mask2=0;
46
47 data = *((uint32_t *)ptr);
48 #ifndef MFDBIGENDIAN
49 data = SWAP_WORD(data);
50 #endif
51 mask1 = (FIRST_STARTCODE_BYTE != (data & SC_BYTE_MASK0));
52 mask2 = (FIRST_STARTCODE_BYTE != (data & SC_BYTE_MASK1));
53 /* If second byte and fourth byte are not zero's then we cannot have a start code here as we need
54 two consecutive zero bytes for a start code pattern */
55 if(mask1 && mask2)
56 {/* Success so skip 4 bytes and start over */
57 ptr+=4;size+=4;data_left-=4;
58 continue;
59 }
60 else
61 {
62 break;
63 }
64 }
65 }
66
67 /* At this point either data is not on a word boundary or phase > 0 or On a word boundary but we detected
68 two zero bytes in the word so we look one byte at a time*/
69 if(data_left > 0)
70 {
71 if(*ptr == FIRST_STARTCODE_BYTE)
72 {/* Phase can be 3 only if third start code byte is found */
73 phase++;
74 ptr++;size++;data_left--;
75 if(phase > 2)
76 {
77 phase = 2;
78
79 if ( (((uint32_t)ptr) & 0x3) == 0 )
80 {
81 while( data_left > 3 )
82 {
83 if(*((uint32_t *)ptr) != 0)
84 {
85 break;
86 }
87 ptr+=4;size+=4;data_left-=4;
88 }
89 }
90 }
91 }
92 else
93 {
94 if((*ptr == THIRD_STARTCODE_BYTE) && (phase == 2))
95 {/* Match for start code so update context with byte position */
96 phase = 3;
97 cxt->sc_end_pos = size;
98 }
99 else
100 {
101 phase = 0;
102 }
103 ptr++;size++;data_left--;
104 }
105 }
106 }
107 if((data_left > 0) && (phase == 3))
108 {
109 viddec_sc_prefix_state_t *state = (viddec_sc_prefix_state_t *)sc_state;
110 cxt->sc_end_pos++;
111 state->next_sc = cxt->buf[cxt->sc_end_pos];
112 state->second_scprfx_length = 3;
113 phase++;
114 ret = 1;
115 }
116 cxt->phase = phase;
117 /* Return SC found only if phase is 4, else always success */
118 return ret;
119 }
120