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  loco_update_rice_param(r, (v + 1) >> 1);
96  if (!v) {
97  if (r->save >= 0) {
98  r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0);
99  if (r->run > 1)
100  r->save += r->run + 1;
101  else
102  r->save -= 3;
103  } else
104  r->run2++;
105  } else {
106  v = ((v >> 1) + r->lossy) ^ -(v & 1);
107  if (r->run2 > 0) {
108  if (r->run2 > 2)
109  r->save += r->run2;
110  else
111  r->save -= 3;
112  r->run2 = 0;
113  }
114  }
115 
116  return v;
117 }
118 
119 /* LOCO main predictor - LOCO-I/JPEG-LS predictor */
120 static inline int loco_predict(uint8_t* data, int stride)
121 {
122  int a, b, c;
123 
124  a = data[-stride];
125  b = data[-1];
126  c = data[-stride - 1];
127 
128  return mid_pred(a, a + b - c, b);
129 }
130 
131 static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height,
132  int stride, const uint8_t *buf, int buf_size)
133 {
134  RICEContext rc;
135  unsigned val;
136  int ret;
137  int i, j;
138 
139  if(buf_size<=0)
140  return -1;
141 
142  if ((ret = init_get_bits8(&rc.gb, buf, buf_size)) < 0)
143  return ret;
144 
145  rc.save = 0;
146  rc.run = 0;
147  rc.run2 = 0;
148  rc.lossy = l->lossy;
149 
150  rc.sum = 8;
151  rc.count = 1;
152 
153  /* restore top left pixel */
154  val = loco_get_rice(&rc);
155  data[0] = 128 + val;
156  /* restore top line */
157  for (i = 1; i < width; i++) {
158  val = loco_get_rice(&rc);
159  if (val == INT_MIN)
160  return AVERROR_INVALIDDATA;
161  data[i] = data[i - 1] + val;
162  }
163  data += stride;
164  for (j = 1; j < height; j++) {
165  /* restore left column */
166  val = loco_get_rice(&rc);
167  if (val == INT_MIN)
168  return AVERROR_INVALIDDATA;
169  data[0] = data[-stride] + val;
170  /* restore all other pixels */
171  for (i = 1; i < width; i++) {
172  val = loco_get_rice(&rc);
173  if (val == INT_MIN)
174  return -1;
175  data[i] = loco_predict(&data[i], stride) + val;
176  }
177  data += stride;
178  }
179 
180  return (get_bits_count(&rc.gb) + 7) >> 3;
181 }
182 
183 static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride)
184 {
185  int y;
186 
187  for (y=1; y<height; y++) {
188  if (width>=y) {
189  memmove(data + y*stride,
190  data + y*(stride + 1),
191  (width-y));
192  if (y+1 < height)
193  memmove(data + y*stride + (width-y),
194  data + (y+1)*stride, y);
195  }
196  }
197 }
198 
199 static int decode_frame(AVCodecContext *avctx, AVFrame *p,
200  int *got_frame, AVPacket *avpkt)
201 {
202  LOCOContext * const l = avctx->priv_data;
203  const uint8_t *buf = avpkt->data;
204  int buf_size = avpkt->size;
205  int decoded, ret;
206 
207  if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
208  return ret;
209  p->key_frame = 1;
210 
211 #define ADVANCE_BY_DECODED do { \
212  if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \
213  buf += decoded; buf_size -= decoded; \
214 } while(0)
215  switch(l->mode) {
216  case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
217  decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
218  p->linesize[0], buf, buf_size);
220  decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
221  p->linesize[1], buf, buf_size);
223  decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
224  p->linesize[2], buf, buf_size);
225  break;
226  case LOCO_CYV12: case LOCO_YV12:
227  decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
228  p->linesize[0], buf, buf_size);
230  decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
231  p->linesize[2], buf, buf_size);
233  decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
234  p->linesize[1], buf, buf_size);
235  break;
236  case LOCO_CRGB: case LOCO_RGB:
237  decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
238  -p->linesize[1], buf, buf_size);
240  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
241  -p->linesize[0], buf, buf_size);
243  decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
244  -p->linesize[2], buf, buf_size);
245  if (avctx->width & 1) {
246  rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0]);
247  rotate_faulty_loco(p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[1]);
248  rotate_faulty_loco(p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[2]);
249  }
250  break;
251  case LOCO_CRGBA:
252  case LOCO_RGBA:
253  decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height,
254  -p->linesize[1], buf, buf_size);
256  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
257  -p->linesize[0], buf, buf_size);
259  decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height,
260  -p->linesize[2], buf, buf_size);
262  decoded = loco_decode_plane(l, p->data[3] + p->linesize[3]*(avctx->height-1), avctx->width, avctx->height,
263  -p->linesize[3], buf, buf_size);
264  break;
265  default:
266  av_assert0(0);
267  }
268 
269  if (decoded < 0 || decoded > buf_size)
270  goto buf_too_small;
271  buf_size -= decoded;
272 
273  *got_frame = 1;
274 
275  return avpkt->size - buf_size;
276 buf_too_small:
277  av_log(avctx, AV_LOG_ERROR, "Input data too small.\n");
278  return AVERROR(EINVAL);
279 }
280 
282 {
283  LOCOContext * const l = avctx->priv_data;
284  int version;
285 
286  l->avctx = avctx;
287  if (avctx->extradata_size < 12) {
288  av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
289  avctx->extradata_size);
290  return AVERROR_INVALIDDATA;
291  }
292  version = AV_RL32(avctx->extradata);
293  switch (version) {
294  case 1:
295  l->lossy = 0;
296  break;
297  case 2:
298  l->lossy = AV_RL32(avctx->extradata + 8);
299  break;
300  default:
301  l->lossy = AV_RL32(avctx->extradata + 8);
302  avpriv_request_sample(avctx, "LOCO codec version %i", version);
303  }
304 
305  if (l->lossy > 65536U) {
306  av_log(avctx, AV_LOG_ERROR, "lossy %i is too large\n", l->lossy);
307  return AVERROR_INVALIDDATA;
308  }
309 
310  l->mode = AV_RL32(avctx->extradata + 4);
311  switch (l->mode) {
312  case LOCO_CYUY2:
313  case LOCO_YUY2:
314  case LOCO_UYVY:
315  avctx->pix_fmt = AV_PIX_FMT_YUV422P;
316  break;
317  case LOCO_CRGB:
318  case LOCO_RGB:
319  avctx->pix_fmt = AV_PIX_FMT_GBRP;
320  break;
321  case LOCO_CYV12:
322  case LOCO_YV12:
323  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
324  break;
325  case LOCO_CRGBA:
326  case LOCO_RGBA:
327  avctx->pix_fmt = AV_PIX_FMT_GBRAP;
328  break;
329  default:
330  av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
331  return AVERROR_INVALIDDATA;
332  }
333  if (avctx->debug & FF_DEBUG_PICT_INFO)
334  av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode);
335 
336  return 0;
337 }
338 
340  .p.name = "loco",
341  CODEC_LONG_NAME("LOCO"),
342  .p.type = AVMEDIA_TYPE_VIDEO,
343  .p.id = AV_CODEC_ID_LOCO,
344  .priv_data_size = sizeof(LOCOContext),
345  .init = decode_init,
347  .p.capabilities = AV_CODEC_CAP_DR1,
348 };
LOCOContext
Definition: loco.c:47
get_bits_left
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:839
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:219
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
AVPacket::data
uint8_t * data
Definition: packet.h:374
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:146
FFCodec
Definition: codec_internal.h:119
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:1328
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:346
golomb.h
exp golomb vlc stuff
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:123
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:205
LOCO_CYV12
@ LOCO_CYV12
Definition: loco.c:39
LOCO_MODE
LOCO_MODE
Definition: loco.c:34
GetBitContext
Definition: get_bits.h:61
AVFrame::key_frame
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:417
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: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:428
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:667
LOCO_YV12
@ LOCO_YV12
Definition: loco.c:44
ADVANCE_BY_DECODED
#define ADVANCE_BY_DECODED
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:500
width
#define width
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:298
LOCO_CRGB
@ LOCO_CRGB
Definition: loco.c:37
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts_bsf.c:363
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
ff_loco_decoder
const FFCodec ff_loco_decoder
Definition: loco.c:339
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:66
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:264
decode_frame
static int decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt)
Definition: loco.c:199
loco_predict
static int loco_predict(uint8_t *data, int stride)
Definition: loco.c:120
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:183
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:1450
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:375
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:131
version
version
Definition: libkvazaar.c:313
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:269
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:499
LOCOContext::lossy
int lossy
Definition: loco.c:49
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:211
AVCodecContext::height
int height
Definition: avcodec.h:571
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:608
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:398
LOCO_RGB
@ LOCO_RGB
Definition: loco.c:42
RICEContext::gb
GetBitContext gb
Definition: loco.c:54
AVCodecContext::debug
int debug
debug
Definition: avcodec.h:1327
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:158
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:70
avpriv_request_sample
#define avpriv_request_sample(...)
Definition: tableprint_vlc.h:36
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:425
AVPacket
This structure stores compressed data.
Definition: packet.h:351
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: loco.c:281
LOCO_CRGBA
@ LOCO_CRGBA
Definition: loco.c:38
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:571
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:370
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