blob: 85b6b8e3fdebe8f85ea613c4e4f9e689118e805b [file] [log] [blame]
#include "viddec_pm_parse.h"
#include "viddec_fw_debug.h"
#define FIRST_STARTCODE_BYTE 0x00
#define SECOND_STARTCODE_BYTE 0x00
#define THIRD_STARTCODE_BYTE 0x01
/* BIG ENDIAN: Must be the second and fourth byte of the bytestream for this to work */
/* LITTLE ENDIAN: Must be the second and fourth byte of the bytestream for this to work */
/* these are little-endian defines */
#define SC_BYTE_MASK0 0x00ff0000 /* little-endian */
#define SC_BYTE_MASK1 0x000000ff /* little-endian */
/* Parse for Sc code of pattern 0x00 0x00 0xXX in the current buffer. Returns either sc found or success.
The conext is updated with current phase and sc_code position in the buffer.
*/
uint32_t viddec_parse_sc(void *in, void *pcxt, void *sc_state)
{
uint8_t *ptr;
uint32_t size;
uint32_t data_left=0, phase = 0, ret = 0;
viddec_sc_parse_cubby_cxt_t *cxt;
/* What is phase?: phase is a value between [0-4], we keep track of consecutive '0's with this.
Any time a '0' is found its incremented by 1(uptp 2) and reset to '0' if a zero not found.
if 0xXX code is found and current phase is 2, its changed to 3 which means we found the pattern
we are looking for. Its incremented to 4 once we see a byte after this pattern */
cxt = ( viddec_sc_parse_cubby_cxt_t *)in;
size = 0;
data_left = cxt->size;
ptr = cxt->buf;
phase = cxt->phase;
cxt->sc_end_pos = -1;
pcxt=pcxt;
/* parse until there is more data and start code not found */
while((data_left > 0) &&(phase < 3))
{
/* Check if we are byte aligned & phase=0, if thats the case we can check
work at a time instead of byte*/
if(((((uint32_t)ptr) & 0x3) == 0) && (phase == 0))
{
while(data_left > 3)
{
uint32_t data;
char mask1 = 0, mask2=0;
data = *((uint32_t *)ptr);
#ifndef MFDBIGENDIAN
data = SWAP_WORD(data);
#endif
mask1 = (FIRST_STARTCODE_BYTE != (data & SC_BYTE_MASK0));
mask2 = (FIRST_STARTCODE_BYTE != (data & SC_BYTE_MASK1));
/* If second byte and fourth byte are not zero's then we cannot have a start code here as we need
two consecutive zero bytes for a start code pattern */
if(mask1 && mask2)
{/* Success so skip 4 bytes and start over */
ptr+=4;size+=4;data_left-=4;
continue;
}
else
{
break;
}
}
}
/* At this point either data is not on a word boundary or phase > 0 or On a word boundary but we detected
two zero bytes in the word so we look one byte at a time*/
if(data_left > 0)
{
if(*ptr == FIRST_STARTCODE_BYTE)
{/* Phase can be 3 only if third start code byte is found */
phase++;
ptr++;size++;data_left--;
if(phase > 2)
{
phase = 2;
if ( (((uint32_t)ptr) & 0x3) == 0 )
{
while( data_left > 3 )
{
if(*((uint32_t *)ptr) != 0)
{
break;
}
ptr+=4;size+=4;data_left-=4;
}
}
}
}
else
{
if((*ptr == THIRD_STARTCODE_BYTE) && (phase == 2))
{/* Match for start code so update context with byte position */
phase = 3;
cxt->sc_end_pos = size;
}
else
{
phase = 0;
}
ptr++;size++;data_left--;
}
}
}
if((data_left > 0) && (phase == 3))
{
viddec_sc_prefix_state_t *state = (viddec_sc_prefix_state_t *)sc_state;
cxt->sc_end_pos++;
state->next_sc = cxt->buf[cxt->sc_end_pos];
state->second_scprfx_length = 3;
phase++;
ret = 1;
}
cxt->phase = phase;
/* Return SC found only if phase is 4, else always success */
return ret;
}