FFmpeg
Loading...
Searching...
No Matches
loco.c
Go to the documentation of this file.
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 "decode.h"
30#include "get_bits.h"
31#include "golomb.h"
32#include "mathops.h"
33
46
52
53typedef struct RICEContext {
55 int save, run, run2; /* internal rice decoder state */
56 int sum, count; /* sum and count for getting rice parameter */
57 int lossy;
59
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--;
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 if (v == -1)
96 return INT_MIN;
97 loco_update_rice_param(r, (v + 1) >> 1);
98 if (!v) {
99 if (r->save >= 0) {
100 int run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0);
101 if (run == -1)
102 return INT_MIN;
103 r->run = run;
104 if (r->run > 1)
105 r->save += r->run + 1;
106 else
107 r->save -= 3;
108 } else
109 r->run2++;
110 } else {
111 v = ((v >> 1) + r->lossy) ^ -(v & 1);
112 if (r->run2 > 0) {
113 if (r->run2 > 2)
114 r->save += r->run2;
115 else
116 r->save -= 3;
117 r->run2 = 0;
118 }
119 }
120
121 return v;
122}
123
124/* LOCO main predictor - LOCO-I/JPEG-LS predictor */
125static inline int loco_predict(uint8_t* data, int stride)
126{
127 int a, b, c;
128
129 a = data[-stride];
130 b = data[-1];
131 c = data[-stride - 1];
132
133 return mid_pred(a, a + b - c, b);
134}
135
136static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height,
137 int stride, const uint8_t *buf, int buf_size)
138{
139 RICEContext rc;
140 unsigned val;
141 int ret;
142 int i, j;
143
144 if(buf_size<=0)
145 return -1;
146
147 if ((ret = init_get_bits8(&rc.gb, buf, buf_size)) < 0)
148 return ret;
149
150 rc.save = 0;
151 rc.run = 0;
152 rc.run2 = 0;
153 rc.lossy = l->lossy;
154
155 rc.sum = 8;
156 rc.count = 1;
157
158 /* restore top left pixel */
159 val = loco_get_rice(&rc);
160 if (val == INT_MIN)
161 return AVERROR_INVALIDDATA;
162 data[0] = 128 + val;
163 /* restore top line */
164 for (i = 1; i < width; i++) {
165 val = loco_get_rice(&rc);
166 if (val == INT_MIN)
167 return AVERROR_INVALIDDATA;
168 data[i] = data[i - 1] + val;
169 }
170 data += stride;
171 for (j = 1; j < height; j++) {
172 /* restore left column */
173 val = loco_get_rice(&rc);
174 if (val == INT_MIN)
175 return AVERROR_INVALIDDATA;
176 data[0] = data[-stride] + val;
177 /* restore all other pixels */
178 for (i = 1; i < width; i++) {
179 val = loco_get_rice(&rc);
180 if (val == INT_MIN)
181 return -1;
182 data[i] = loco_predict(&data[i], stride) + val;
183 }
184 data += stride;
185 }
186
187 return (get_bits_count(&rc.gb) + 7) >> 3;
188}
189
190static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride)
191{
192 int y;
193
194 for (y=1; y<height; y++) {
195 if (width>=y) {
196 memmove(data + y*stride,
197 data + y*(stride + 1),
198 (width-y));
199 if (y+1 < height)
200 memmove(data + y*stride + (width-y),
201 data + (y+1)*stride, y);
202 }
203 }
204}
205
206static int decode_frame(AVCodecContext *avctx, AVFrame *p,
207 int *got_frame, AVPacket *avpkt)
208{
209 LOCOContext * const l = avctx->priv_data;
210 const uint8_t *buf = avpkt->data;
211 int buf_size = avpkt->size;
212 int decoded, ret;
213
214 if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
215 return ret;
216
217#define ADVANCE_BY_DECODED do { \
218 if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \
219 buf += decoded; buf_size -= decoded; \
220} while(0)
221 switch(l->mode) {
222 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
223 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
224 p->linesize[0], buf, buf_size);
226 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
227 p->linesize[1], buf, buf_size);
229 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
230 p->linesize[2], buf, buf_size);
231 break;
232 case LOCO_CYV12: case LOCO_YV12:
233 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
234 p->linesize[0], buf, buf_size);
236 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
237 p->linesize[2], buf, buf_size);
239 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
240 p->linesize[1], buf, buf_size);
241 break;
242 case LOCO_CRGB: case LOCO_RGB:
243 decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
244 -p->linesize[1], buf, buf_size);
246 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
247 -p->linesize[0], buf, buf_size);
249 decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
250 -p->linesize[2], buf, buf_size);
251 if (avctx->width & 1) {
252 rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0]);
253 rotate_faulty_loco(p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[1]);
254 rotate_faulty_loco(p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[2]);
255 }
256 break;
257 case LOCO_CRGBA:
258 case LOCO_RGBA:
259 decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
260 -p->linesize[1], buf, buf_size);
262 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
263 -p->linesize[0], buf, buf_size);
265 decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
266 -p->linesize[2], buf, buf_size);
268 decoded = loco_decode_plane(l, p->data[3] + p->linesize[3]*(avctx->height-1), avctx->width, avctx->height,
269 -p->linesize[3], buf, buf_size);
270 break;
271 default:
272 av_assert0(0);
273 }
274
275 if (decoded < 0 || decoded > buf_size)
276 goto buf_too_small;
277 buf_size -= decoded;
278
279 *got_frame = 1;
280
281 return avpkt->size - buf_size;
282buf_too_small:
283 av_log(avctx, AV_LOG_ERROR, "Input data too small.\n");
284 return AVERROR(EINVAL);
285}
286
288{
289 LOCOContext * const l = avctx->priv_data;
290 int version;
291
292 l->avctx = avctx;
293 if (avctx->extradata_size < 12) {
294 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
295 avctx->extradata_size);
296 return AVERROR_INVALIDDATA;
297 }
298 version = AV_RL32(avctx->extradata);
299 switch (version) {
300 case 1:
301 l->lossy = 0;
302 break;
303 case 2:
304 l->lossy = AV_RL32(avctx->extradata + 8);
305 break;
306 default:
307 l->lossy = AV_RL32(avctx->extradata + 8);
308 avpriv_request_sample(avctx, "LOCO codec version %i", version);
309 }
310
311 if (l->lossy > 65536U) {
312 av_log(avctx, AV_LOG_ERROR, "lossy %i is too large\n", l->lossy);
313 return AVERROR_INVALIDDATA;
314 }
315
316 l->mode = AV_RL32(avctx->extradata + 4);
317 switch (l->mode) {
318 case LOCO_CYUY2:
319 case LOCO_YUY2:
320 case LOCO_UYVY:
322 break;
323 case LOCO_CRGB:
324 case LOCO_RGB:
325 avctx->pix_fmt = AV_PIX_FMT_GBRP;
326 break;
327 case LOCO_CYV12:
328 case LOCO_YV12:
330 break;
331 case LOCO_CRGBA:
332 case LOCO_RGBA:
333 avctx->pix_fmt = AV_PIX_FMT_GBRAP;
334 break;
335 default:
336 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
337 return AVERROR_INVALIDDATA;
338 }
339 if (avctx->debug & FF_DEBUG_PICT_INFO)
340 av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode);
341
342 return 0;
343}
344
346 .p.name = "loco",
347 CODEC_LONG_NAME("LOCO"),
348 .p.type = AVMEDIA_TYPE_VIDEO,
349 .p.id = AV_CODEC_ID_LOCO,
350 .priv_data_size = sizeof(LOCOContext),
351 .init = decode_init,
353 .p.capabilities = AV_CODEC_CAP_DR1,
354};
static double val(void *priv, double ch)
Definition aeval.c:77
const FFCodec ff_loco_decoder
Definition loco.c:345
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
#define FF_DEBUG_PICT_INFO
Definition avcodec.h:1393
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
bitstream reader API header.
static int get_bits_left(GetBitContext *gb)
Definition get_bits.h:688
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition get_bits.h:544
static int get_bits_count(const GetBitContext *s)
Definition get_bits.h:254
exp golomb vlc stuff
static int get_ur_golomb_jpegls(GetBitContext *gb, int k, int limit, int esc_len)
read unsigned golomb rice code (jpegls).
Definition golomb.h:431
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_LOCO
Definition codec_id.h:122
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int a
#define r
Definition input.c:42
#define b
Definition input.c:43
#define AV_RL32(p)
static av_cold int decode_init(AVCodecContext *avctx)
Definition 4xm.c:998
static int decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt)
Definition 4xm.c:837
#define av_cold
Definition attributes.h:117
version
Definition libkvazaar.c:313
static int loco_predict(uint8_t *data, int stride)
Definition loco.c:125
static int loco_get_rice(RICEContext *r)
Definition loco.c:84
LOCO_MODE
Definition loco.c:34
@ LOCO_CYV12
Definition loco.c:39
@ LOCO_CRGB
Definition loco.c:37
@ LOCO_RGBA
Definition loco.c:43
@ LOCO_UNKN
Definition loco.c:35
@ LOCO_UYVY
Definition loco.c:41
@ LOCO_RGB
Definition loco.c:42
@ LOCO_YV12
Definition loco.c:44
@ LOCO_YUY2
Definition loco.c:40
@ LOCO_CYUY2
Definition loco.c:36
@ LOCO_CRGBA
Definition loco.c:38
static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride)
Definition loco.c:190
#define ADVANCE_BY_DECODED
static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, int stride, const uint8_t *buf, int buf_size)
Definition loco.c:136
static av_cold int decode_init(AVCodecContext *avctx)
Definition loco.c:287
static int loco_get_rice_param(RICEContext *r)
Definition loco.c:60
static int decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt)
Definition loco.c:206
static void loco_update_rice_param(RICEContext *r, int val)
Definition loco.c:73
#define mid_pred
Definition mathops.h:115
const char data[16]
Definition mxf.c:149
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition pixfmt.h:212
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition pixfmt.h:165
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
int debug
debug
Definition avcodec.h:1392
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition avcodec.h:526
int extradata_size
Definition avcodec.h:527
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
enum LOCO_MODE mode
Definition loco.c:50
AVCodecContext * avctx
Definition loco.c:48
int lossy
Definition loco.c:49
int count
Definition loco.c:56
GetBitContext gb
Definition loco.c:54
int run2
Definition loco.c:55
int run
Definition loco.c:55
int lossy
Definition loco.c:57
int save
Definition loco.c:55
int sum
Definition loco.c:56
uint8_t run
Definition svq3.c:207
#define stride
#define avpriv_request_sample(...)
#define av_log(a,...)
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
static double c[64]