FFmpeg
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 
34 enum 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 
47 typedef struct LOCOContext {
49  int lossy;
51 } LOCOContext;
52 
53 typedef 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;
58 } RICEContext;
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 
73 static 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 
84 static 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 */
125 static 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 
136 static 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 
190 static 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 
206 static 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;
282 buf_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:
321  avctx->pix_fmt = AV_PIX_FMT_YUV422P;
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:
329  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
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 };
LOCOContext
Definition: loco.c:47
get_bits_left
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:695
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
LOCO_YUY2
@ LOCO_YUY2
Definition: loco.c:40
LOCO_UNKN
@ LOCO_UNKN
Definition: loco.c:35
AV_CODEC_ID_LOCO
@ AV_CODEC_ID_LOCO
Definition: codec_id.h:124
get_bits_count
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:266
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
AVPacket::data
uint8_t * data
Definition: packet.h:539
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:149
FFCodec
Definition: codec_internal.h:127
LOCOContext::avctx
AVCodecContext * avctx
Definition: loco.c:48
loco_get_rice
static int loco_get_rice(RICEContext *r)
Definition: loco.c:84
FF_DEBUG_PICT_INFO
#define FF_DEBUG_PICT_INFO
Definition: avcodec.h:1407
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
golomb.h
exp golomb vlc stuff
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:131
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:212
LOCO_CYV12
@ LOCO_CYV12
Definition: loco.c:39
LOCO_MODE
LOCO_MODE
Definition: loco.c:34
GetBitContext
Definition: get_bits.h:108
val
static double val(void *priv, double ch)
Definition: aeval.c:77
RICEContext::sum
int sum
Definition: loco.c:56
RICEContext
Definition: loco.c:53
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
get_ur_golomb_jpegls
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
av_cold
#define av_cold
Definition: attributes.h:90
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:545
LOCO_YV12
@ LOCO_YV12
Definition: loco.c:44
ADVANCE_BY_DECODED
#define ADVANCE_BY_DECODED
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:530
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:311
LOCO_CRGB
@ LOCO_CRGB
Definition: loco.c:37
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
ff_loco_decoder
const FFCodec ff_loco_decoder
Definition: loco.c:345
decode.h
get_bits.h
RICEContext::lossy
int lossy
Definition: loco.c:57
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:296
decode_frame
static int decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt)
Definition: loco.c:206
loco_predict
static int loco_predict(uint8_t *data, int stride)
Definition: loco.c:125
run
uint8_t run
Definition: svq3.c:204
LOCOContext::mode
enum LOCO_MODE mode
Definition: loco.c:50
mathops.h
LOCO_CYUY2
@ LOCO_CYUY2
Definition: loco.c:36
rotate_faulty_loco
static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride)
Definition: loco.c:190
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
ff_get_buffer
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1697
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:368
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:540
height
#define height
Definition: dsp.h:85
codec_internal.h
RICEContext::run2
int run2
Definition: loco.c:55
loco_get_rice_param
static int loco_get_rice_param(RICEContext *r)
Definition: loco.c:60
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
loco_decode_plane
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
version
version
Definition: libkvazaar.c:321
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:220
RICEContext::count
int count
Definition: loco.c:56
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:529
LOCOContext::lossy
int lossy
Definition: loco.c:49
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
AVCodecContext::height
int height
Definition: avcodec.h:624
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:663
avcodec.h
stride
#define stride
Definition: h264pred_template.c:537
mid_pred
#define mid_pred
Definition: mathops.h:96
ret
ret
Definition: filter_design.txt:187
loco_update_rice_param
static void loco_update_rice_param(RICEContext *r, int val)
Definition: loco.c:73
RICEContext::run
int run
Definition: loco.c:55
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
U
#define U(x)
Definition: vpx_arith.h:37
LOCO_UYVY
@ LOCO_UYVY
Definition: loco.c:41
AVCodecContext
main external API structure.
Definition: avcodec.h:451
LOCO_RGB
@ LOCO_RGB
Definition: loco.c:42
RICEContext::gb
GetBitContext gb
Definition: loco.c:54
AVCodecContext::debug
int debug
debug
Definition: avcodec.h:1406
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:165
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:36
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:478
AVPacket
This structure stores compressed data.
Definition: packet.h:516
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: loco.c:287
LOCO_CRGBA
@ LOCO_CRGBA
Definition: loco.c:38
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:624
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:434
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
RICEContext::save
int save
Definition: loco.c:55
width
#define width
Definition: dsp.h:85
LOCO_RGBA
@ LOCO_RGBA
Definition: loco.c:43