1/* 2 * LOCO codec 3 * Copyright (c) 2005 Konstantin Shishkov 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * LOCO codec. 25 */ 26 27#include "avcodec.h" 28#include "codec_internal.h" 29#include "get_bits.h" 30#include "golomb.h" 31#include "internal.h" 32#include "mathops.h" 33 34enum LOCO_MODE { 35 LOCO_UNKN = 0, 36 LOCO_CYUY2 = -1, 37 LOCO_CRGB = -2, 38 LOCO_CRGBA = -3, 39 LOCO_CYV12 = -4, 40 LOCO_YUY2 = 1, 41 LOCO_UYVY = 2, 42 LOCO_RGB = 3, 43 LOCO_RGBA = 4, 44 LOCO_YV12 = 5, 45}; 46 47typedef struct LOCOContext { 48 AVCodecContext *avctx; 49 int lossy; 50 enum LOCO_MODE mode; 51} LOCOContext; 52 53typedef struct RICEContext { 54 GetBitContext gb; 55 int save, run, run2; /* internal rice decoder state */ 56 int sum, count; /* sum and count for getting rice parameter */ 57 int lossy; 58} RICEContext; 59 60static int loco_get_rice_param(RICEContext *r) 61{ 62 int cnt = 0; 63 int val = r->count; 64 65 while (r->sum > val && cnt < 9) { 66 val <<= 1; 67 cnt++; 68 } 69 70 return cnt; 71} 72 73static inline void loco_update_rice_param(RICEContext *r, int val) 74{ 75 r->sum += val; 76 r->count++; 77 78 if (r->count == 16) { 79 r->sum >>= 1; 80 r->count >>= 1; 81 } 82} 83 84static inline int loco_get_rice(RICEContext *r) 85{ 86 unsigned v; 87 if (r->run > 0) { /* we have zero run */ 88 r->run--; 89 loco_update_rice_param(r, 0); 90 return 0; 91 } 92 if (get_bits_left(&r->gb) < 1) 93 return INT_MIN; 94 v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0); 95 loco_update_rice_param(r, (v + 1) >> 1); 96 if (!v) { 97 if (r->save >= 0) { 98 r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0); 99 if (r->run > 1) 100 r->save += r->run + 1; 101 else 102 r->save -= 3; 103 } else 104 r->run2++; 105 } else { 106 v = ((v >> 1) + r->lossy) ^ -(v & 1); 107 if (r->run2 > 0) { 108 if (r->run2 > 2) 109 r->save += r->run2; 110 else 111 r->save -= 3; 112 r->run2 = 0; 113 } 114 } 115 116 return v; 117} 118 119/* LOCO main predictor - LOCO-I/JPEG-LS predictor */ 120static inline int loco_predict(uint8_t* data, int stride) 121{ 122 int a, b, c; 123 124 a = data[-stride]; 125 b = data[-1]; 126 c = data[-stride - 1]; 127 128 return mid_pred(a, a + b - c, b); 129} 130 131static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, 132 int stride, const uint8_t *buf, int buf_size) 133{ 134 RICEContext rc; 135 unsigned val; 136 int ret; 137 int i, j; 138 139 if(buf_size<=0) 140 return -1; 141 142 if ((ret = init_get_bits8(&rc.gb, buf, buf_size)) < 0) 143 return ret; 144 145 rc.save = 0; 146 rc.run = 0; 147 rc.run2 = 0; 148 rc.lossy = l->lossy; 149 150 rc.sum = 8; 151 rc.count = 1; 152 153 /* restore top left pixel */ 154 val = loco_get_rice(&rc); 155 data[0] = 128 + val; 156 /* restore top line */ 157 for (i = 1; i < width; i++) { 158 val = loco_get_rice(&rc); 159 if (val == INT_MIN) 160 return AVERROR_INVALIDDATA; 161 data[i] = data[i - 1] + val; 162 } 163 data += stride; 164 for (j = 1; j < height; j++) { 165 /* restore left column */ 166 val = loco_get_rice(&rc); 167 if (val == INT_MIN) 168 return AVERROR_INVALIDDATA; 169 data[0] = data[-stride] + val; 170 /* restore all other pixels */ 171 for (i = 1; i < width; i++) { 172 val = loco_get_rice(&rc); 173 if (val == INT_MIN) 174 return -1; 175 data[i] = loco_predict(&data[i], stride) + val; 176 } 177 data += stride; 178 } 179 180 return (get_bits_count(&rc.gb) + 7) >> 3; 181} 182 183static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride) 184{ 185 int y; 186 187 for (y=1; y<height; y++) { 188 if (width>=y) { 189 memmove(data + y*stride, 190 data + y*(stride + 1), 191 (width-y)); 192 if (y+1 < height) 193 memmove(data + y*stride + (width-y), 194 data + (y+1)*stride, y); 195 } 196 } 197} 198 199static int decode_frame(AVCodecContext *avctx, AVFrame *p, 200 int *got_frame, AVPacket *avpkt) 201{ 202 LOCOContext * const l = avctx->priv_data; 203 const uint8_t *buf = avpkt->data; 204 int buf_size = avpkt->size; 205 int decoded, ret; 206 207 if ((ret = ff_get_buffer(avctx, p, 0)) < 0) 208 return ret; 209 p->key_frame = 1; 210 211#define ADVANCE_BY_DECODED do { \ 212 if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \ 213 buf += decoded; buf_size -= decoded; \ 214} while(0) 215 switch(l->mode) { 216 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: 217 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, 218 p->linesize[0], buf, buf_size); 219 ADVANCE_BY_DECODED; 220 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height, 221 p->linesize[1], buf, buf_size); 222 ADVANCE_BY_DECODED; 223 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height, 224 p->linesize[2], buf, buf_size); 225 break; 226 case LOCO_CYV12: case LOCO_YV12: 227 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, 228 p->linesize[0], buf, buf_size); 229 ADVANCE_BY_DECODED; 230 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2, 231 p->linesize[2], buf, buf_size); 232 ADVANCE_BY_DECODED; 233 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2, 234 p->linesize[1], buf, buf_size); 235 break; 236 case LOCO_CRGB: case LOCO_RGB: 237 decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, 238 -p->linesize[1], buf, buf_size); 239 ADVANCE_BY_DECODED; 240 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, 241 -p->linesize[0], buf, buf_size); 242 ADVANCE_BY_DECODED; 243 decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, 244 -p->linesize[2], buf, buf_size); 245 if (avctx->width & 1) { 246 rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0]); 247 rotate_faulty_loco(p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[1]); 248 rotate_faulty_loco(p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[2]); 249 } 250 break; 251 case LOCO_CRGBA: 252 case LOCO_RGBA: 253 decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, 254 -p->linesize[1], buf, buf_size); 255 ADVANCE_BY_DECODED; 256 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, 257 -p->linesize[0], buf, buf_size); 258 ADVANCE_BY_DECODED; 259 decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, 260 -p->linesize[2], buf, buf_size); 261 ADVANCE_BY_DECODED; 262 decoded = loco_decode_plane(l, p->data[3] + p->linesize[3]*(avctx->height-1), avctx->width, avctx->height, 263 -p->linesize[3], buf, buf_size); 264 break; 265 default: 266 av_assert0(0); 267 } 268 269 if (decoded < 0 || decoded > buf_size) 270 goto buf_too_small; 271 buf_size -= decoded; 272 273 *got_frame = 1; 274 275 return avpkt->size - buf_size; 276buf_too_small: 277 av_log(avctx, AV_LOG_ERROR, "Input data too small.\n"); 278 return AVERROR(EINVAL); 279} 280 281static av_cold int decode_init(AVCodecContext *avctx) 282{ 283 LOCOContext * const l = avctx->priv_data; 284 int version; 285 286 l->avctx = avctx; 287 if (avctx->extradata_size < 12) { 288 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n", 289 avctx->extradata_size); 290 return AVERROR_INVALIDDATA; 291 } 292 version = AV_RL32(avctx->extradata); 293 switch (version) { 294 case 1: 295 l->lossy = 0; 296 break; 297 case 2: 298 l->lossy = AV_RL32(avctx->extradata + 8); 299 break; 300 default: 301 l->lossy = AV_RL32(avctx->extradata + 8); 302 avpriv_request_sample(avctx, "LOCO codec version %i", version); 303 } 304 305 if (l->lossy > 65536U) { 306 av_log(avctx, AV_LOG_ERROR, "lossy %i is too large\n", l->lossy); 307 return AVERROR_INVALIDDATA; 308 } 309 310 l->mode = AV_RL32(avctx->extradata + 4); 311 switch (l->mode) { 312 case LOCO_CYUY2: 313 case LOCO_YUY2: 314 case LOCO_UYVY: 315 avctx->pix_fmt = AV_PIX_FMT_YUV422P; 316 break; 317 case LOCO_CRGB: 318 case LOCO_RGB: 319 avctx->pix_fmt = AV_PIX_FMT_GBRP; 320 break; 321 case LOCO_CYV12: 322 case LOCO_YV12: 323 avctx->pix_fmt = AV_PIX_FMT_YUV420P; 324 break; 325 case LOCO_CRGBA: 326 case LOCO_RGBA: 327 avctx->pix_fmt = AV_PIX_FMT_GBRAP; 328 break; 329 default: 330 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode); 331 return AVERROR_INVALIDDATA; 332 } 333 if (avctx->debug & FF_DEBUG_PICT_INFO) 334 av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode); 335 336 return 0; 337} 338 339const FFCodec ff_loco_decoder = { 340 .p.name = "loco", 341 .p.long_name = NULL_IF_CONFIG_SMALL("LOCO"), 342 .p.type = AVMEDIA_TYPE_VIDEO, 343 .p.id = AV_CODEC_ID_LOCO, 344 .priv_data_size = sizeof(LOCOContext), 345 .init = decode_init, 346 FF_CODEC_DECODE_CB(decode_frame), 347 .p.capabilities = AV_CODEC_CAP_DR1, 348 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 349}; 350