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 "get_bits.h" 29#include "golomb.h" 30#include "internal.h" 31#include "mathops.h" 32 33enum LOCO_MODE { 34 LOCO_UNKN = 0, 35 LOCO_CYUY2 = -1, 36 LOCO_CRGB = -2, 37 LOCO_CRGBA = -3, 38 LOCO_CYV12 = -4, 39 LOCO_YUY2 = 1, 40 LOCO_UYVY = 2, 41 LOCO_RGB = 3, 42 LOCO_RGBA = 4, 43 LOCO_YV12 = 5, 44}; 45 46typedef struct LOCOContext { 47 AVCodecContext *avctx; 48 int lossy; 49 int mode; 50} LOCOContext; 51 52typedef struct RICEContext { 53 GetBitContext gb; 54 int save, run, run2; /* internal rice decoder state */ 55 int sum, count; /* sum and count for getting rice parameter */ 56 int lossy; 57} RICEContext; 58 59static int loco_get_rice_param(RICEContext *r) 60{ 61 int cnt = 0; 62 int val = r->count; 63 64 while (r->sum > val && cnt < 9) { 65 val <<= 1; 66 cnt++; 67 } 68 69 return cnt; 70} 71 72static inline void loco_update_rice_param(RICEContext *r, int val) 73{ 74 r->sum += val; 75 r->count++; 76 77 if (r->count == 16) { 78 r->sum >>= 1; 79 r->count >>= 1; 80 } 81} 82 83static inline int loco_get_rice(RICEContext *r) 84{ 85 int v; 86 if (r->run > 0) { /* we have zero run */ 87 r->run--; 88 loco_update_rice_param(r, 0); 89 return 0; 90 } 91 v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0); 92 loco_update_rice_param(r, (v + 1) >> 1); 93 if (!v) { 94 if (r->save >= 0) { 95 r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0); 96 if (r->run > 1) 97 r->save += r->run + 1; 98 else 99 r->save -= 3; 100 } else 101 r->run2++; 102 } else { 103 v = ((v >> 1) + r->lossy) ^ -(v & 1); 104 if (r->run2 > 0) { 105 if (r->run2 > 2) 106 r->save += r->run2; 107 else 108 r->save -= 3; 109 r->run2 = 0; 110 } 111 } 112 113 return v; 114} 115 116/* LOCO main predictor - LOCO-I/JPEG-LS predictor */ 117static inline int loco_predict(uint8_t* data, int stride, int step) 118{ 119 int a, b, c; 120 121 a = data[-stride]; 122 b = data[-step]; 123 c = data[-stride - step]; 124 125 return mid_pred(a, a + b - c, b); 126} 127 128static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, 129 int stride, const uint8_t *buf, int buf_size, int step) 130{ 131 RICEContext rc; 132 int val; 133 int i, j; 134 135 if(buf_size<=0) 136 return -1; 137 138 init_get_bits8(&rc.gb, buf, buf_size); 139 rc.save = 0; 140 rc.run = 0; 141 rc.run2 = 0; 142 rc.lossy = l->lossy; 143 144 rc.sum = 8; 145 rc.count = 1; 146 147 /* restore top left pixel */ 148 val = loco_get_rice(&rc); 149 data[0] = 128 + val; 150 /* restore top line */ 151 for (i = 1; i < width; i++) { 152 val = loco_get_rice(&rc); 153 data[i * step] = data[i * step - step] + val; 154 } 155 data += stride; 156 for (j = 1; j < height; j++) { 157 /* restore left column */ 158 val = loco_get_rice(&rc); 159 data[0] = data[-stride] + val; 160 /* restore all other pixels */ 161 for (i = 1; i < width; i++) { 162 val = loco_get_rice(&rc); 163 data[i * step] = loco_predict(&data[i * step], stride, step) + val; 164 } 165 data += stride; 166 } 167 168 return (get_bits_count(&rc.gb) + 7) >> 3; 169} 170 171static int decode_frame(AVCodecContext *avctx, 172 void *data, int *got_frame, 173 AVPacket *avpkt) 174{ 175 LOCOContext * const l = avctx->priv_data; 176 const uint8_t *buf = avpkt->data; 177 int buf_size = avpkt->size; 178 AVFrame * const p = data; 179 int decoded, ret; 180 181 if ((ret = ff_get_buffer(avctx, p, 0)) < 0) 182 return ret; 183 p->key_frame = 1; 184 185#define ADVANCE_BY_DECODED do { \ 186 if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \ 187 buf += decoded; buf_size -= decoded; \ 188} while(0) 189 switch(l->mode) { 190 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: 191 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, 192 p->linesize[0], buf, buf_size, 1); 193 ADVANCE_BY_DECODED; 194 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height, 195 p->linesize[1], buf, buf_size, 1); 196 ADVANCE_BY_DECODED; 197 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height, 198 p->linesize[2], buf, buf_size, 1); 199 break; 200 case LOCO_CYV12: case LOCO_YV12: 201 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, 202 p->linesize[0], buf, buf_size, 1); 203 ADVANCE_BY_DECODED; 204 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2, 205 p->linesize[2], buf, buf_size, 1); 206 ADVANCE_BY_DECODED; 207 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2, 208 p->linesize[1], buf, buf_size, 1); 209 break; 210 case LOCO_CRGB: case LOCO_RGB: 211 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, 212 -p->linesize[0], buf, buf_size, 3); 213 ADVANCE_BY_DECODED; 214 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height, 215 -p->linesize[0], buf, buf_size, 3); 216 ADVANCE_BY_DECODED; 217 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height, 218 -p->linesize[0], buf, buf_size, 3); 219 break; 220 case LOCO_CRGBA: 221 case LOCO_RGBA: 222 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, 223 -p->linesize[0], buf, buf_size, 4); 224 ADVANCE_BY_DECODED; 225 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height, 226 -p->linesize[0], buf, buf_size, 4); 227 ADVANCE_BY_DECODED; 228 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height, 229 -p->linesize[0], buf, buf_size, 4); 230 ADVANCE_BY_DECODED; 231 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 3, avctx->width, avctx->height, 232 -p->linesize[0], buf, buf_size, 4); 233 break; 234 default: 235 av_assert0(0); 236 } 237 238 if (decoded < 0 || decoded > buf_size) 239 goto buf_too_small; 240 buf_size -= decoded; 241 242 *got_frame = 1; 243 244 return avpkt->size - buf_size; 245buf_too_small: 246 av_log(avctx, AV_LOG_ERROR, "Input data too small.\n"); 247 return AVERROR(EINVAL); 248} 249 250static av_cold int decode_init(AVCodecContext *avctx) 251{ 252 LOCOContext * const l = avctx->priv_data; 253 int version; 254 255 l->avctx = avctx; 256 if (avctx->extradata_size < 12) { 257 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n", 258 avctx->extradata_size); 259 return AVERROR_INVALIDDATA; 260 } 261 version = AV_RL32(avctx->extradata); 262 switch (version) { 263 case 1: 264 l->lossy = 0; 265 break; 266 case 2: 267 l->lossy = AV_RL32(avctx->extradata + 8); 268 break; 269 default: 270 l->lossy = AV_RL32(avctx->extradata + 8); 271 avpriv_request_sample(avctx, "LOCO codec version %i", version); 272 } 273 274 l->mode = AV_RL32(avctx->extradata + 4); 275 switch (l->mode) { 276 case LOCO_CYUY2: 277 case LOCO_YUY2: 278 case LOCO_UYVY: 279 avctx->pix_fmt = AV_PIX_FMT_YUV422P; 280 break; 281 case LOCO_CRGB: 282 case LOCO_RGB: 283 avctx->pix_fmt = AV_PIX_FMT_BGR24; 284 break; 285 case LOCO_CYV12: 286 case LOCO_YV12: 287 avctx->pix_fmt = AV_PIX_FMT_YUV420P; 288 break; 289 case LOCO_CRGBA: 290 case LOCO_RGBA: 291 avctx->pix_fmt = AV_PIX_FMT_BGRA; 292 break; 293 default: 294 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode); 295 return AVERROR_INVALIDDATA; 296 } 297 if (avctx->debug & FF_DEBUG_PICT_INFO) 298 av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode); 299 300 return 0; 301} 302 303AVCodec ff_loco_decoder = { 304 .name = "loco", 305 .long_name = NULL_IF_CONFIG_SMALL("LOCO"), 306 .type = AVMEDIA_TYPE_VIDEO, 307 .id = AV_CODEC_ID_LOCO, 308 .priv_data_size = sizeof(LOCOContext), 309 .init = decode_init, 310 .decode = decode_frame, 311 .capabilities = CODEC_CAP_DR1, 312}; 313