static inline int loco_get_rice(RICEContext *r)
{
- int v;
+ unsigned v;
if (r->run > 0) { /* we have zero run */
r->run--;
loco_update_rice_param(r, 0);
return 0;
}
+ if (get_bits_left(&r->gb) < 1)
+ return INT_MIN;
v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0);
loco_update_rice_param(r, (v + 1) >> 1);
if (!v) {
}
/* LOCO main predictor - LOCO-I/JPEG-LS predictor */
-static inline int loco_predict(uint8_t* data, int stride, int step)
+static inline int loco_predict(uint8_t* data, int stride)
{
int a, b, c;
a = data[-stride];
- b = data[-step];
- c = data[-stride - step];
+ b = data[-1];
+ c = data[-stride - 1];
return mid_pred(a, a + b - c, b);
}
static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height,
- int stride, const uint8_t *buf, int buf_size, int step)
+ int stride, const uint8_t *buf, int buf_size)
{
RICEContext rc;
- int val;
+ unsigned val;
int ret;
int i, j;
/* restore top line */
for (i = 1; i < width; i++) {
val = loco_get_rice(&rc);
- data[i * step] = data[i * step - step] + val;
+ if (val == INT_MIN)
+ return AVERROR_INVALIDDATA;
+ data[i] = data[i - 1] + val;
}
data += stride;
for (j = 1; j < height; j++) {
/* restore left column */
val = loco_get_rice(&rc);
+ if (val == INT_MIN)
+ return AVERROR_INVALIDDATA;
data[0] = data[-stride] + val;
/* restore all other pixels */
for (i = 1; i < width; i++) {
val = loco_get_rice(&rc);
- data[i * step] = loco_predict(&data[i * step], stride, step) + val;
+ if (val == INT_MIN)
+ return -1;
+ data[i] = loco_predict(&data[i], stride) + val;
}
data += stride;
}
return (get_bits_count(&rc.gb) + 7) >> 3;
}
-static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride, int step)
+static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride)
{
int y;
for (y=1; y<height; y++) {
if (width>=y) {
memmove(data + y*stride,
- data + y*(stride + step),
- step*(width-y));
+ data + y*(stride + 1),
+ (width-y));
if (y+1 < height)
- memmove(data + y*stride + step*(width-y),
- data + (y+1)*stride,
- step*y);
+ memmove(data + y*stride + (width-y),
+ data + (y+1)*stride, y);
}
}
}
switch(l->mode) {
case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
- p->linesize[0], buf, buf_size, 1);
+ p->linesize[0], buf, buf_size);
ADVANCE_BY_DECODED;
decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
- p->linesize[1], buf, buf_size, 1);
+ p->linesize[1], buf, buf_size);
ADVANCE_BY_DECODED;
decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
- p->linesize[2], buf, buf_size, 1);
+ p->linesize[2], buf, buf_size);
break;
case LOCO_CYV12: case LOCO_YV12:
decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
- p->linesize[0], buf, buf_size, 1);
+ p->linesize[0], buf, buf_size);
ADVANCE_BY_DECODED;
decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
- p->linesize[2], buf, buf_size, 1);
+ p->linesize[2], buf, buf_size);
ADVANCE_BY_DECODED;
decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
- p->linesize[1], buf, buf_size, 1);
+ p->linesize[1], buf, buf_size);
break;
case LOCO_CRGB: case LOCO_RGB:
- decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
- -p->linesize[0], buf, buf_size, 3);
+ decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
+ -p->linesize[1], buf, buf_size);
ADVANCE_BY_DECODED;
- decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
- -p->linesize[0], buf, buf_size, 3);
+ decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
+ -p->linesize[0], buf, buf_size);
ADVANCE_BY_DECODED;
- decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
- -p->linesize[0], buf, buf_size, 3);
- if (avctx->width & 1)
- rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0], 3);
+ decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
+ -p->linesize[2], buf, buf_size);
+ if (avctx->width & 1) {
+ rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0]);
+ rotate_faulty_loco(p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[1]);
+ rotate_faulty_loco(p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[2]);
+ }
break;
case LOCO_CRGBA:
case LOCO_RGBA:
- decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
- -p->linesize[0], buf, buf_size, 4);
+ decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
+ -p->linesize[1], buf, buf_size);
ADVANCE_BY_DECODED;
- decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
- -p->linesize[0], buf, buf_size, 4);
+ decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
+ -p->linesize[0], buf, buf_size);
ADVANCE_BY_DECODED;
- decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
- -p->linesize[0], buf, buf_size, 4);
+ decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
+ -p->linesize[2], buf, buf_size);
ADVANCE_BY_DECODED;
- decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 3, avctx->width, avctx->height,
- -p->linesize[0], buf, buf_size, 4);
+ decoded = loco_decode_plane(l, p->data[3] + p->linesize[3]*(avctx->height-1), avctx->width, avctx->height,
+ -p->linesize[3], buf, buf_size);
break;
default:
av_assert0(0);
avpriv_request_sample(avctx, "LOCO codec version %i", version);
}
+ if (l->lossy > 65536U) {
+ av_log(avctx, AV_LOG_ERROR, "lossy %i is too large\n", l->lossy);
+ return AVERROR_INVALIDDATA;
+ }
+
l->mode = AV_RL32(avctx->extradata + 4);
switch (l->mode) {
case LOCO_CYUY2:
break;
case LOCO_CRGB:
case LOCO_RGB:
- avctx->pix_fmt = AV_PIX_FMT_BGR24;
+ avctx->pix_fmt = AV_PIX_FMT_GBRP;
break;
case LOCO_CYV12:
case LOCO_YV12:
break;
case LOCO_CRGBA:
case LOCO_RGBA:
- avctx->pix_fmt = AV_PIX_FMT_BGRA;
+ avctx->pix_fmt = AV_PIX_FMT_GBRAP;
break;
default:
av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
return 0;
}
-AVCodec ff_loco_decoder = {
+const AVCodec ff_loco_decoder = {
.name = "loco",
.long_name = NULL_IF_CONFIG_SMALL("LOCO"),
.type = AVMEDIA_TYPE_VIDEO,
.init = decode_init,
.decode = decode_frame,
.capabilities = AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
};