@ -52,23 +52,25 @@ typedef struct RpzaContext {
GetByteContext gb ;
} RpzaContext ;
# define ADVANCE_BLOCK() \
{ \
pixel_ptr + = 4 ; \
if ( pixel_ptr > = width ) \
{ \
pixel_ptr = 0 ; \
row_ptr + = stride * 4 ; \
} \
total_blocks - - ; \
if ( total_blocks < 0 ) \
{ \
av_log ( s - > avctx , AV_LOG_ERROR , " warning: block counter just went negative (this should not happen) \n " ) ; \
return ; \
} \
}
# define CHECK_BLOCK() \
if ( total_blocks < 1 ) { \
av_log ( s - > avctx , AV_LOG_ERROR , \
" Block counter just went negative (this should not happen) \n " ) ; \
return AVERROR_INVALIDDATA ; \
} \
# define ADVANCE_BLOCK() \
{ \
pixel_ptr + = 4 ; \
if ( pixel_ptr > = width ) \
{ \
pixel_ptr = 0 ; \
row_ptr + = stride * 4 ; \
} \
total_blocks - - ; \
}
static void rpza_decode_stream ( RpzaContext * s )
static int rpza_decode_stream ( RpzaContext * s )
{
int width = s - > avctx - > width ;
int stride = s - > frame - > linesize [ 0 ] / 2 ;
@ -80,7 +82,7 @@ static void rpza_decode_stream(RpzaContext *s)
uint16_t * pixels = ( uint16_t * ) s - > frame - > data [ 0 ] ;
int row_ptr = 0 ;
int pixel_ptr = - 4 ;
int pixel_ptr = 0 ;
int block_ptr ;
int pixel_x , pixel_y ;
int total_blocks ;
@ -130,7 +132,8 @@ static void rpza_decode_stream(RpzaContext *s)
/* Skip blocks */
case 0x80 :
while ( n_blocks - - ) {
ADVANCE_BLOCK ( ) ;
CHECK_BLOCK ( ) ;
ADVANCE_BLOCK ( ) ;
}
break ;
@ -138,7 +141,7 @@ static void rpza_decode_stream(RpzaContext *s)
case 0xa0 :
colorA = bytestream2_get_be16 ( & s - > gb ) ;
while ( n_blocks - - ) {
ADVAN CE_BLOCK( )
CH ECK _BLOCK ( ) ;
block_ptr = row_ptr + pixel_ptr ;
for ( pixel_y = 0 ; pixel_y < 4 ; pixel_y + + ) {
for ( pixel_x = 0 ; pixel_x < 4 ; pixel_x + + ) {
@ -147,6 +150,7 @@ static void rpza_decode_stream(RpzaContext *s)
}
block_ptr + = row_inc ;
}
ADVANCE_BLOCK ( ) ;
}
break ;
@ -181,9 +185,9 @@ static void rpza_decode_stream(RpzaContext *s)
color4 [ 2 ] | = ( ( 21 * ta + 11 * tb ) > > 5 ) ;
if ( bytestream2_get_bytes_left ( & s - > gb ) < n_blocks * 4 )
return ;
return AVERROR_INVALIDDATA ;
while ( n_blocks - - ) {
ADVAN CE_BLOCK( ) ;
CH ECK _BLOCK ( ) ;
block_ptr = row_ptr + pixel_ptr ;
for ( pixel_y = 0 ; pixel_y < 4 ; pixel_y + + ) {
uint8_t index = bytestream2_get_byteu ( & s - > gb ) ;
@ -194,14 +198,15 @@ static void rpza_decode_stream(RpzaContext *s)
}
block_ptr + = row_inc ;
}
ADVANCE_BLOCK ( ) ;
}
break ;
/* Fill block with 16 colors */
case 0x00 :
if ( bytestream2_get_bytes_left ( & s - > gb ) < 30 )
return ;
ADVAN CE_BLOCK( ) ;
return AVERROR_INVALIDDATA ;
CH ECK _BLOCK ( ) ;
block_ptr = row_ptr + pixel_ptr ;
for ( pixel_y = 0 ; pixel_y < 4 ; pixel_y + + ) {
for ( pixel_x = 0 ; pixel_x < 4 ; pixel_x + + ) {
@ -213,6 +218,7 @@ static void rpza_decode_stream(RpzaContext *s)
}
block_ptr + = row_inc ;
}
ADVANCE_BLOCK ( ) ;
break ;
/* Unknown opcode */
@ -220,9 +226,11 @@ static void rpza_decode_stream(RpzaContext *s)
av_log ( s - > avctx , AV_LOG_ERROR , " Unknown opcode %d in rpza chunk. "
" Skip remaining %d bytes of chunk data. \n " , opcode ,
bytestream2_get_bytes_left ( & s - > gb ) ) ;
return ;
return AVERROR_INVALIDDATA ;
} /* Opcode switch */
}
return 0 ;
}
static av_cold int rpza_decode_init ( AVCodecContext * avctx )
@ -251,7 +259,9 @@ static int rpza_decode_frame(AVCodecContext *avctx,
if ( ( ret = ff_reget_buffer ( avctx , s - > frame ) ) < 0 )
return ret ;
rpza_decode_stream ( s ) ;
ret = rpza_decode_stream ( s ) ;
if ( ret < 0 )
return ret ;
if ( ( ret = av_frame_ref ( data , s - > frame ) ) < 0 )
return ret ;