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  p->flags |= AV_FRAME_FLAG_KEY;
217 
218 #define ADVANCE_BY_DECODED do { \
219  if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \
220  buf += decoded; buf_size -= decoded; \
221 } while(0)
222  switch(l->mode) {
223  case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
224  decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
225  p->linesize[0], buf, buf_size);
227  decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
228  p->linesize[1], buf, buf_size);
230  decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
231  p->linesize[2], buf, buf_size);
232  break;
233  case LOCO_CYV12: case LOCO_YV12:
234  decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
235  p->linesize[0], buf, buf_size);
237  decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
238  p->linesize[2], buf, buf_size);
240  decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
241  p->linesize[1], buf, buf_size);
242  break;
243  case LOCO_CRGB: case LOCO_RGB:
244  decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
245  -p->linesize[1], buf, buf_size);
247  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
248  -p->linesize[0], buf, buf_size);
250  decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
251  -p->linesize[2], buf, buf_size);
252  if (avctx->width & 1) {
253  rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0]);
254  rotate_faulty_loco(p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[1]);
255  rotate_faulty_loco(p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[2]);
256  }
257  break;
258  case LOCO_CRGBA:
259  case LOCO_RGBA:
260  decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
261  -p->linesize[1], buf, buf_size);
263  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
264  -p->linesize[0], buf, buf_size);
266  decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
267  -p->linesize[2], buf, buf_size);
269  decoded = loco_decode_plane(l, p->data[3] + p->linesize[3]*(avctx->height-1), avctx->width, avctx->height,
270  -p->linesize[3], buf, buf_size);
271  break;
272  default:
273  av_assert0(0);
274  }
275 
276  if (decoded < 0 || decoded > buf_size)
277  goto buf_too_small;
278  buf_size -= decoded;
279 
280  *got_frame = 1;
281 
282  return avpkt->size - buf_size;
283 buf_too_small:
284  av_log(avctx, AV_LOG_ERROR, "Input data too small.\n");
285  return AVERROR(EINVAL);
286 }
287 
289 {
290  LOCOContext * const l = avctx->priv_data;
291  int version;
292 
293  l->avctx = avctx;
294  if (avctx->extradata_size < 12) {
295  av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
296  avctx->extradata_size);
297  return AVERROR_INVALIDDATA;
298  }
299  version = AV_RL32(avctx->extradata);
300  switch (version) {
301  case 1:
302  l->lossy = 0;
303  break;
304  case 2:
305  l->lossy = AV_RL32(avctx->extradata + 8);
306  break;
307  default:
308  l->lossy = AV_RL32(avctx->extradata + 8);
309  avpriv_request_sample(avctx, "LOCO codec version %i", version);
310  }
311 
312  if (l->lossy > 65536U) {
313  av_log(avctx, AV_LOG_ERROR, "lossy %i is too large\n", l->lossy);
314  return AVERROR_INVALIDDATA;
315  }
316 
317  l->mode = AV_RL32(avctx->extradata + 4);
318  switch (l->mode) {
319  case LOCO_CYUY2:
320  case LOCO_YUY2:
321  case LOCO_UYVY:
322  avctx->pix_fmt = AV_PIX_FMT_YUV422P;
323  break;
324  case LOCO_CRGB:
325  case LOCO_RGB:
326  avctx->pix_fmt = AV_PIX_FMT_GBRP;
327  break;
328  case LOCO_CYV12:
329  case LOCO_YV12:
330  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
331  break;
332  case LOCO_CRGBA:
333  case LOCO_RGBA:
334  avctx->pix_fmt = AV_PIX_FMT_GBRAP;
335  break;
336  default:
337  av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
338  return AVERROR_INVALIDDATA;
339  }
340  if (avctx->debug & FF_DEBUG_PICT_INFO)
341  av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode);
342 
343  return 0;
344 }
345 
347  .p.name = "loco",
348  CODEC_LONG_NAME("LOCO"),
349  .p.type = AVMEDIA_TYPE_VIDEO,
350  .p.id = AV_CODEC_ID_LOCO,
351  .priv_data_size = sizeof(LOCOContext),
352  .init = decode_init,
354  .p.capabilities = AV_CODEC_CAP_DR1,
355 };
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:126
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:344
AVPacket::data
uint8_t * data
Definition: packet.h:522
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:148
FFCodec
Definition: codec_internal.h:127
AVFrame::flags
int flags
Frame flags, a combination of AV_FRAME_FLAGS.
Definition: frame.h:616
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:1397
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:365
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:78
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:180
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
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:595
ADVANCE_BY_DECODED
#define ADVANCE_BY_DECODED
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:524
width
#define width
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:287
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:346
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:272
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:203
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:1569
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:365
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:523
codec_internal.h
RICEContext::run2
int run2
Definition: loco.c:55
height
#define height
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:191
RICEContext::count
int count
Definition: loco.c:56
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:523
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:618
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:657
avcodec.h
stride
#define stride
Definition: h264pred_template.c:537
mid_pred
#define mid_pred
Definition: mathops.h:98
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:445
LOCO_RGB
@ LOCO_RGB
Definition: loco.c:42
RICEContext::gb
GetBitContext gb
Definition: loco.c:54
AVCodecContext::debug
int debug
debug
Definition: avcodec.h:1396
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:472
AVPacket
This structure stores compressed data.
Definition: packet.h:499
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: loco.c:288
LOCO_CRGBA
@ LOCO_CRGBA
Definition: loco.c:38
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
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:389
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
LOCO_RGBA
@ LOCO_RGBA
Definition: loco.c:43