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