@ -57,17 +57,21 @@ typedef struct BitBuf {
# define kmvc_init_getbits(bb, src) bb.bits = 7; bb.bitbuf = *src++;
# define kmvc_getbit(bb, src, res) {\
# define kmvc_getbit(bb, src, src_end, res) {\
res = 0 ; \
if ( bb . bitbuf & ( 1 < < bb . bits ) ) res = 1 ; \
bb . bits - - ; \
if ( bb . bits = = - 1 ) { \
if ( src > = src_end ) { \
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ; \
return AVERROR_INVALIDDATA ; \
} \
bb . bitbuf = * src + + ; \
bb . bits = 7 ; \
} \
}
static void kmvc_decode_intra_8x8 ( KmvcContext * ctx , const uint8_t * src , int w , int h )
static int kmvc_decode_intra_8x8 ( KmvcContext * ctx , const uint8_t * src , int src_size , int w , int h )
{
BitBuf bb ;
int res , val ;
@ -75,13 +79,18 @@ static void kmvc_decode_intra_8x8(KmvcContext * ctx, const uint8_t * src, int w,
int bx , by ;
int l0x , l1x , l0y , l1y ;
int mx , my ;
const uint8_t * src_end = src + src_size ;
kmvc_init_getbits ( bb , src ) ;
for ( by = 0 ; by < h ; by + = 8 )
for ( bx = 0 ; bx < w ; bx + = 8 ) {
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) { // fill whole 8x8 block
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
for ( i = 0 ; i < 64 ; i + + )
BLK ( ctx - > cur , bx + ( i & 0x7 ) , by + ( i > > 3 ) ) = val ;
@ -89,14 +98,22 @@ static void kmvc_decode_intra_8x8(KmvcContext * ctx, const uint8_t * src, int w,
for ( i = 0 ; i < 4 ; i + + ) {
l0x = bx + ( i & 1 ) * 4 ;
l0y = by + ( i & 2 ) * 2 ;
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) {
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) { // fill whole 4x4 block
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
for ( j = 0 ; j < 16 ; j + + )
BLK ( ctx - > cur , l0x + ( j & 3 ) , l0y + ( j > > 2 ) ) = val ;
} else { // copy block from already decoded place
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
mx = val & 0xF ;
my = val > > 4 ;
@ -108,16 +125,24 @@ static void kmvc_decode_intra_8x8(KmvcContext * ctx, const uint8_t * src, int w,
for ( j = 0 ; j < 4 ; j + + ) {
l1x = l0x + ( j & 1 ) * 2 ;
l1y = l0y + ( j & 2 ) ;
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) {
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) { // fill whole 2x2 block
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
BLK ( ctx - > cur , l1x , l1y ) = val ;
BLK ( ctx - > cur , l1x + 1 , l1y ) = val ;
BLK ( ctx - > cur , l1x , l1y + 1 ) = val ;
BLK ( ctx - > cur , l1x + 1 , l1y + 1 ) = val ;
} else { // copy block from already decoded place
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
mx = val & 0xF ;
my = val > > 4 ;
@ -140,9 +165,11 @@ static void kmvc_decode_intra_8x8(KmvcContext * ctx, const uint8_t * src, int w,
}
}
}
return 0 ;
}
static void kmvc_decode_inter_8x8 ( KmvcContext * ctx , const uint8_t * src , int w , int h )
static int kmvc_decode_inter_8x8 ( KmvcContext * ctx , const uint8_t * src , int src_size , int w , int h )
{
BitBuf bb ;
int res , val ;
@ -150,15 +177,20 @@ static void kmvc_decode_inter_8x8(KmvcContext * ctx, const uint8_t * src, int w,
int bx , by ;
int l0x , l1x , l0y , l1y ;
int mx , my ;
const uint8_t * src_end = src + src_size ;
kmvc_init_getbits ( bb , src ) ;
for ( by = 0 ; by < h ; by + = 8 )
for ( bx = 0 ; bx < w ; bx + = 8 ) {
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) {
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) { // fill whole 8x8 block
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
for ( i = 0 ; i < 64 ; i + + )
BLK ( ctx - > cur , bx + ( i & 0x7 ) , by + ( i > > 3 ) ) = val ;
@ -171,14 +203,22 @@ static void kmvc_decode_inter_8x8(KmvcContext * ctx, const uint8_t * src, int w,
for ( i = 0 ; i < 4 ; i + + ) {
l0x = bx + ( i & 1 ) * 4 ;
l0y = by + ( i & 2 ) * 2 ;
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) {
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) { // fill whole 4x4 block
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
for ( j = 0 ; j < 16 ; j + + )
BLK ( ctx - > cur , l0x + ( j & 3 ) , l0y + ( j > > 2 ) ) = val ;
} else { // copy block
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
mx = ( val & 0xF ) - 8 ;
my = ( val > > 4 ) - 8 ;
@ -190,16 +230,24 @@ static void kmvc_decode_inter_8x8(KmvcContext * ctx, const uint8_t * src, int w,
for ( j = 0 ; j < 4 ; j + + ) {
l1x = l0x + ( j & 1 ) * 2 ;
l1y = l0y + ( j & 2 ) ;
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) {
kmvc_getbit ( bb , src , res ) ;
kmvc_getbit ( bb , src , src_end , res ) ;
if ( ! res ) { // fill whole 2x2 block
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
BLK ( ctx - > cur , l1x , l1y ) = val ;
BLK ( ctx - > cur , l1x + 1 , l1y ) = val ;
BLK ( ctx - > cur , l1x , l1y + 1 ) = val ;
BLK ( ctx - > cur , l1x + 1 , l1y + 1 ) = val ;
} else { // copy block
if ( src > = src_end ) {
av_log ( ctx - > avctx , AV_LOG_ERROR , " Data overrun \n " ) ;
return AVERROR_INVALIDDATA ;
}
val = * src + + ;
mx = ( val & 0xF ) - 8 ;
my = ( val > > 4 ) - 8 ;
@ -222,6 +270,8 @@ static void kmvc_decode_inter_8x8(KmvcContext * ctx, const uint8_t * src, int w,
}
}
}
return 0 ;
}
static int decode_frame ( AVCodecContext * avctx , void * data , int * data_size , AVPacket * avpkt )
@ -299,10 +349,10 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *data_size, AVPa
memcpy ( ctx - > cur , ctx - > prev , 320 * 200 ) ;
break ;
case 3 :
kmvc_decode_intra_8x8 ( ctx , buf , avctx - > width , avctx - > height ) ;
kmvc_decode_intra_8x8 ( ctx , buf , buf_size , avctx - > width , avctx - > height ) ;
break ;
case 4 :
kmvc_decode_inter_8x8 ( ctx , buf , avctx - > width , avctx - > height ) ;
kmvc_decode_inter_8x8 ( ctx , buf , buf_size , avctx - > width , avctx - > height ) ;
break ;
default :
av_log ( avctx , AV_LOG_ERROR , " Unknown compression method %i \n " , header & KMVC_METHOD ) ;