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 "get_bits.h"
29 #include "golomb.h"
30 #include "internal.h"
31 #include "mathops.h"
32 
33 enum LOCO_MODE {
34  LOCO_UNKN = 0,
35  LOCO_CYUY2 = -1,
36  LOCO_CRGB = -2,
37  LOCO_CRGBA = -3,
38  LOCO_CYV12 = -4,
39  LOCO_YUY2 = 1,
40  LOCO_UYVY = 2,
41  LOCO_RGB = 3,
42  LOCO_RGBA = 4,
43  LOCO_YV12 = 5,
44 };
45 
46 typedef struct LOCOContext {
48  int lossy;
49  int mode;
50 } LOCOContext;
51 
52 typedef struct RICEContext {
54  int save, run, run2; /* internal rice decoder state */
55  int sum, count; /* sum and count for getting rice parameter */
56  int lossy;
57 } RICEContext;
58 
60 {
61  int cnt = 0;
62  int val = r->count;
63 
64  while (r->sum > val && cnt < 9) {
65  val <<= 1;
66  cnt++;
67  }
68 
69  return cnt;
70 }
71 
72 static inline void loco_update_rice_param(RICEContext *r, int val)
73 {
74  r->sum += val;
75  r->count++;
76 
77  if (r->count == 16) {
78  r->sum >>= 1;
79  r->count >>= 1;
80  }
81 }
82 
83 static inline int loco_get_rice(RICEContext *r)
84 {
85  int v;
86  if (r->run > 0) { /* we have zero run */
87  r->run--;
89  return 0;
90  }
91  v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0);
92  loco_update_rice_param(r, (v + 1) >> 1);
93  if (!v) {
94  if (r->save >= 0) {
95  r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0);
96  if (r->run > 1)
97  r->save += r->run + 1;
98  else
99  r->save -= 3;
100  } else
101  r->run2++;
102  } else {
103  v = ((v >> 1) + r->lossy) ^ -(v & 1);
104  if (r->run2 > 0) {
105  if (r->run2 > 2)
106  r->save += r->run2;
107  else
108  r->save -= 3;
109  r->run2 = 0;
110  }
111  }
112 
113  return v;
114 }
115 
116 /* LOCO main predictor - LOCO-I/JPEG-LS predictor */
117 static inline int loco_predict(uint8_t* data, int stride, int step)
118 {
119  int a, b, c;
120 
121  a = data[-stride];
122  b = data[-step];
123  c = data[-stride - step];
124 
125  return mid_pred(a, a + b - c, b);
126 }
127 
129  int stride, const uint8_t *buf, int buf_size, int step)
130 {
131  RICEContext rc;
132  int val;
133  int i, j;
134 
135  if(buf_size<=0)
136  return -1;
137 
138  init_get_bits(&rc.gb, buf, buf_size*8);
139  rc.save = 0;
140  rc.run = 0;
141  rc.run2 = 0;
142  rc.lossy = l->lossy;
143 
144  rc.sum = 8;
145  rc.count = 1;
146 
147  /* restore top left pixel */
148  val = loco_get_rice(&rc);
149  data[0] = 128 + val;
150  /* restore top line */
151  for (i = 1; i < width; i++) {
152  val = loco_get_rice(&rc);
153  data[i * step] = data[i * step - step] + val;
154  }
155  data += stride;
156  for (j = 1; j < height; j++) {
157  /* restore left column */
158  val = loco_get_rice(&rc);
159  data[0] = data[-stride] + val;
160  /* restore all other pixels */
161  for (i = 1; i < width; i++) {
162  val = loco_get_rice(&rc);
163  data[i * step] = loco_predict(&data[i * step], stride, step) + val;
164  }
165  data += stride;
166  }
167 
168  return (get_bits_count(&rc.gb) + 7) >> 3;
169 }
170 
172  void *data, int *got_frame,
173  AVPacket *avpkt)
174 {
175  LOCOContext * const l = avctx->priv_data;
176  const uint8_t *buf = avpkt->data;
177  int buf_size = avpkt->size;
178  AVFrame * const p = data;
179  int decoded, ret;
180 
181  if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
182  return ret;
183  p->key_frame = 1;
184 
185 #define ADVANCE_BY_DECODED do { \
186  if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \
187  buf += decoded; buf_size -= decoded; \
188 } while(0)
189  switch(l->mode) {
190  case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
191  decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
192  p->linesize[0], buf, buf_size, 1);
194  decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
195  p->linesize[1], buf, buf_size, 1);
197  decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
198  p->linesize[2], buf, buf_size, 1);
199  break;
200  case LOCO_CYV12: case LOCO_YV12:
201  decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
202  p->linesize[0], buf, buf_size, 1);
204  decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
205  p->linesize[2], buf, buf_size, 1);
207  decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
208  p->linesize[1], buf, buf_size, 1);
209  break;
210  case LOCO_CRGB: case LOCO_RGB:
211  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
212  -p->linesize[0], buf, buf_size, 3);
214  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
215  -p->linesize[0], buf, buf_size, 3);
217  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
218  -p->linesize[0], buf, buf_size, 3);
219  break;
220  case LOCO_CRGBA:
221  case LOCO_RGBA:
222  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
223  -p->linesize[0], buf, buf_size, 4);
225  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
226  -p->linesize[0], buf, buf_size, 4);
228  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
229  -p->linesize[0], buf, buf_size, 4);
231  decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 3, avctx->width, avctx->height,
232  -p->linesize[0], buf, buf_size, 4);
233  break;
234  default:
235  av_assert0(0);
236  }
237 
238  if (decoded < 0 || decoded > buf_size)
239  goto buf_too_small;
240  buf_size -= decoded;
241 
242  *got_frame = 1;
243 
244  return avpkt->size - buf_size;
245 buf_too_small:
246  av_log(avctx, AV_LOG_ERROR, "Input data too small.\n");
247  return AVERROR(EINVAL);
248 }
249 
251 {
252  LOCOContext * const l = avctx->priv_data;
253  int version;
254 
255  l->avctx = avctx;
256  if (avctx->extradata_size < 12) {
257  av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
258  avctx->extradata_size);
259  return AVERROR_INVALIDDATA;
260  }
261  version = AV_RL32(avctx->extradata);
262  switch (version) {
263  case 1:
264  l->lossy = 0;
265  break;
266  case 2:
267  l->lossy = AV_RL32(avctx->extradata + 8);
268  break;
269  default:
270  l->lossy = AV_RL32(avctx->extradata + 8);
271  avpriv_request_sample(avctx, "LOCO codec version %i", version);
272  }
273 
274  l->mode = AV_RL32(avctx->extradata + 4);
275  switch (l->mode) {
276  case LOCO_CYUY2:
277  case LOCO_YUY2:
278  case LOCO_UYVY:
279  avctx->pix_fmt = AV_PIX_FMT_YUV422P;
280  break;
281  case LOCO_CRGB:
282  case LOCO_RGB:
283  avctx->pix_fmt = AV_PIX_FMT_BGR24;
284  break;
285  case LOCO_CYV12:
286  case LOCO_YV12:
287  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
288  break;
289  case LOCO_CRGBA:
290  case LOCO_RGBA:
291  avctx->pix_fmt = AV_PIX_FMT_BGRA;
292  break;
293  default:
294  av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
295  return AVERROR_INVALIDDATA;
296  }
297  if (avctx->debug & FF_DEBUG_PICT_INFO)
298  av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode);
299 
300  return 0;
301 }
302 
304  .name = "loco",
305  .type = AVMEDIA_TYPE_VIDEO,
306  .id = AV_CODEC_ID_LOCO,
307  .priv_data_size = sizeof(LOCOContext),
308  .init = decode_init,
309  .decode = decode_frame,
310  .capabilities = CODEC_CAP_DR1,
311  .long_name = NULL_IF_CONFIG_SMALL("LOCO"),
312 };
float v
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
Definition: loco.c:41
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
static int loco_predict(uint8_t *data, int stride, int step)
Definition: loco.c:117
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int version
Definition: avisynth_c.h:666
static int get_ur_golomb_jpegls(GetBitContext *gb, int k, int limit, int esc_len)
read unsigned golomb rice code (jpegls).
Definition: golomb.h:294
uint8_t run
Definition: svq3.c:136
int stride
Definition: mace.c:144
Definition: loco.c:43
int run2
Definition: loco.c:54
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
void void avpriv_request_sample(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
static int loco_get_rice_param(RICEContext *r)
Definition: loco.c:59
uint8_t
#define av_cold
Definition: attributes.h:78
#define b
Definition: input.c:42
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
uint8_t * data
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:193
bitstream reader API header.
int run
Definition: loco.c:54
struct RICEContext RICEContext
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:99
Spectrum Plot time data
const char * r
Definition: vf_curves.c:94
int count
Definition: loco.c:55
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
static int loco_get_rice(RICEContext *r)
Definition: loco.c:83
struct LOCOContext LOCOContext
external API header
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:72
int save
Definition: loco.c:54
int lossy
Definition: loco.c:48
static void loco_update_rice_param(RICEContext *r, int val)
Definition: loco.c:72
static av_cold int decode_init(AVCodecContext *avctx)
Definition: loco.c:250
ret
Definition: avfilter.c:821
int width
picture width / height.
LOCO_MODE
Definition: loco.c:33
#define AV_RL32
GetBitContext gb
Definition: loco.c:53
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:71
static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, int stride, const uint8_t *buf, int buf_size, int step)
Definition: loco.c:128
AVCodecContext * avctx
Definition: loco.c:47
int lossy
Definition: loco.c:56
Definition: loco.c:36
int sum
Definition: loco.c:55
static int width
Definition: tests/utils.c:158
Definition: loco.c:40
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
BYTE int const BYTE int int int height
Definition: avisynth_c.h:713
synthesis window for stochastic i
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:379
Definition: loco.c:42
#define mid_pred
Definition: mathops.h:94
#define ADVANCE_BY_DECODED
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
AVCodec ff_loco_decoder
Definition: loco.c:303
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
#define FF_DEBUG_PICT_INFO
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
common internal api header.
static double c[64]
Definition: loco.c:39
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:139
Definition: loco.c:34
#define AV_LOG_INFO
Definition: log.h:156
void INT64 INT64 count
Definition: avisynth_c.h:594
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
int mode
Definition: loco.c:49
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: loco.c:171
exp golomb vlc stuff
This structure stores compressed data.
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step