|
|
|
@@ -38,16 +38,9 @@ typedef struct UltimotionDecodeContext { |
|
|
|
int width, height, blocks; |
|
|
|
AVFrame frame; |
|
|
|
const uint8_t *ulti_codebook; |
|
|
|
GetByteContext gb; |
|
|
|
} UltimotionDecodeContext; |
|
|
|
|
|
|
|
#define CHECK_OVERREAD_SIZE(size) \ |
|
|
|
do { \ |
|
|
|
if (buf_end - buf < (size)) { \ |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); \ |
|
|
|
return AVERROR_INVALIDDATA; \ |
|
|
|
} \ |
|
|
|
} while(0) |
|
|
|
|
|
|
|
static av_cold int ulti_decode_init(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
UltimotionDecodeContext *s = avctx->priv_data; |
|
|
|
@@ -231,7 +224,6 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
int i; |
|
|
|
int skip; |
|
|
|
int tmp; |
|
|
|
const uint8_t *buf_end = buf + buf_size; |
|
|
|
|
|
|
|
s->frame.reference = 1; |
|
|
|
s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; |
|
|
|
@@ -240,18 +232,20 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
bytestream2_init(&s->gb, buf, buf_size); |
|
|
|
|
|
|
|
while(!done) { |
|
|
|
int idx; |
|
|
|
if(blocks >= s->blocks || y >= s->height) |
|
|
|
break;//all blocks decoded |
|
|
|
|
|
|
|
CHECK_OVERREAD_SIZE(1); |
|
|
|
idx = *buf++; |
|
|
|
if (bytestream2_get_bytes_left(&s->gb) < 1) |
|
|
|
goto err; |
|
|
|
idx = bytestream2_get_byteu(&s->gb); |
|
|
|
if((idx & 0xF8) == 0x70) { |
|
|
|
switch(idx) { |
|
|
|
case 0x70: //change modifier |
|
|
|
CHECK_OVERREAD_SIZE(1); |
|
|
|
modifier = *buf++; |
|
|
|
modifier = bytestream2_get_byte(&s->gb); |
|
|
|
if(modifier>1) |
|
|
|
av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier); |
|
|
|
break; |
|
|
|
@@ -265,8 +259,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
done = 1; |
|
|
|
break; |
|
|
|
case 0x74: //skip some blocks |
|
|
|
CHECK_OVERREAD_SIZE(1); |
|
|
|
skip = *buf++; |
|
|
|
skip = bytestream2_get_byte(&s->gb); |
|
|
|
if ((blocks + skip) >= s->blocks) |
|
|
|
break; |
|
|
|
blocks += skip; |
|
|
|
@@ -293,8 +286,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
} else { |
|
|
|
cf = 0; |
|
|
|
if (idx) { |
|
|
|
CHECK_OVERREAD_SIZE(1); |
|
|
|
chroma = *buf++; |
|
|
|
chroma = bytestream2_get_byte(&s->gb); |
|
|
|
} |
|
|
|
} |
|
|
|
for (i = 0; i < 4; i++) { // for every subblock |
|
|
|
@@ -302,15 +294,13 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
if(!code) //skip subblock |
|
|
|
continue; |
|
|
|
if(cf) { |
|
|
|
CHECK_OVERREAD_SIZE(1); |
|
|
|
chroma = *buf++; |
|
|
|
chroma = bytestream2_get_byte(&s->gb); |
|
|
|
} |
|
|
|
tx = x + block_coords[i * 2]; |
|
|
|
ty = y + block_coords[(i * 2) + 1]; |
|
|
|
switch(code) { |
|
|
|
case 1: |
|
|
|
CHECK_OVERREAD_SIZE(1); |
|
|
|
tmp = *buf++; |
|
|
|
tmp = bytestream2_get_byte(&s->gb); |
|
|
|
|
|
|
|
angle = angle_by_index[(tmp >> 6) & 0x3]; |
|
|
|
|
|
|
|
@@ -330,8 +320,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
|
|
|
|
case 2: |
|
|
|
if (modifier) { // unpack four luma samples |
|
|
|
CHECK_OVERREAD_SIZE(3); |
|
|
|
tmp = bytestream_get_be24(&buf); |
|
|
|
tmp = bytestream2_get_be24(&s->gb); |
|
|
|
|
|
|
|
Y[0] = (tmp >> 18) & 0x3F; |
|
|
|
Y[1] = (tmp >> 12) & 0x3F; |
|
|
|
@@ -339,8 +328,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
Y[3] = tmp & 0x3F; |
|
|
|
angle = 16; |
|
|
|
} else { // retrieve luma samples from codebook |
|
|
|
CHECK_OVERREAD_SIZE(2); |
|
|
|
tmp = bytestream_get_be16(&buf); |
|
|
|
tmp = bytestream2_get_be16(&s->gb); |
|
|
|
|
|
|
|
angle = (tmp >> 12) & 0xF; |
|
|
|
tmp &= 0xFFF; |
|
|
|
@@ -356,27 +344,27 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
if (modifier) { // all 16 luma samples |
|
|
|
uint8_t Luma[16]; |
|
|
|
|
|
|
|
CHECK_OVERREAD_SIZE(12); |
|
|
|
|
|
|
|
tmp = bytestream_get_be24(&buf); |
|
|
|
if (bytestream2_get_bytes_left(&s->gb) < 12) |
|
|
|
goto err; |
|
|
|
tmp = bytestream2_get_be24u(&s->gb); |
|
|
|
Luma[0] = (tmp >> 18) & 0x3F; |
|
|
|
Luma[1] = (tmp >> 12) & 0x3F; |
|
|
|
Luma[2] = (tmp >> 6) & 0x3F; |
|
|
|
Luma[3] = tmp & 0x3F; |
|
|
|
|
|
|
|
tmp = bytestream_get_be24(&buf); |
|
|
|
tmp = bytestream2_get_be24u(&s->gb); |
|
|
|
Luma[4] = (tmp >> 18) & 0x3F; |
|
|
|
Luma[5] = (tmp >> 12) & 0x3F; |
|
|
|
Luma[6] = (tmp >> 6) & 0x3F; |
|
|
|
Luma[7] = tmp & 0x3F; |
|
|
|
|
|
|
|
tmp = bytestream_get_be24(&buf); |
|
|
|
tmp = bytestream2_get_be24u(&s->gb); |
|
|
|
Luma[8] = (tmp >> 18) & 0x3F; |
|
|
|
Luma[9] = (tmp >> 12) & 0x3F; |
|
|
|
Luma[10] = (tmp >> 6) & 0x3F; |
|
|
|
Luma[11] = tmp & 0x3F; |
|
|
|
|
|
|
|
tmp = bytestream_get_be24(&buf); |
|
|
|
tmp = bytestream2_get_be24u(&s->gb); |
|
|
|
Luma[12] = (tmp >> 18) & 0x3F; |
|
|
|
Luma[13] = (tmp >> 12) & 0x3F; |
|
|
|
Luma[14] = (tmp >> 6) & 0x3F; |
|
|
|
@@ -384,22 +372,23 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
|
|
|
|
ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma); |
|
|
|
} else { |
|
|
|
CHECK_OVERREAD_SIZE(4); |
|
|
|
tmp = *buf++; |
|
|
|
if (bytestream2_get_bytes_left(&s->gb) < 4) |
|
|
|
goto err; |
|
|
|
tmp = bytestream2_get_byteu(&s->gb); |
|
|
|
if(tmp & 0x80) { |
|
|
|
angle = (tmp >> 4) & 0x7; |
|
|
|
tmp = (tmp << 8) + *buf++; |
|
|
|
tmp = (tmp << 8) + bytestream2_get_byteu(&s->gb); |
|
|
|
Y[0] = (tmp >> 6) & 0x3F; |
|
|
|
Y[1] = tmp & 0x3F; |
|
|
|
Y[2] = (*buf++) & 0x3F; |
|
|
|
Y[3] = (*buf++) & 0x3F; |
|
|
|
Y[2] = bytestream2_get_byteu(&s->gb) & 0x3F; |
|
|
|
Y[3] = bytestream2_get_byteu(&s->gb) & 0x3F; |
|
|
|
ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block |
|
|
|
} else { // some patterns |
|
|
|
int f0, f1; |
|
|
|
f0 = *buf++; |
|
|
|
f0 = bytestream2_get_byteu(&s->gb); |
|
|
|
f1 = tmp; |
|
|
|
Y[0] = (*buf++) & 0x3F; |
|
|
|
Y[1] = (*buf++) & 0x3F; |
|
|
|
Y[0] = bytestream2_get_byteu(&s->gb) & 0x3F; |
|
|
|
Y[1] = bytestream2_get_byteu(&s->gb) & 0x3F; |
|
|
|
ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma); |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -421,6 +410,11 @@ static int ulti_decode_frame(AVCodecContext *avctx, |
|
|
|
*(AVFrame*)data= s->frame; |
|
|
|
|
|
|
|
return buf_size; |
|
|
|
|
|
|
|
err: |
|
|
|
av_log(avctx, AV_LOG_ERROR, |
|
|
|
"Insufficient data\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
AVCodec ff_ulti_decoder = { |
|
|
|
|