motionpixels.c
Go to the documentation of this file.
1 /*
2  * Motion Pixels Video Decoder
3  * Copyright (c) 2008 Gregory Montoir (cyx@users.sourceforge.net)
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 #include "avcodec.h"
23 #include "get_bits.h"
24 #include "dsputil.h"
25 #include "internal.h"
26 
27 #define MAX_HUFF_CODES 16
28 
29 #include "motionpixels_tablegen.h"
30 
31 typedef struct HuffCode {
32  int code;
35 } HuffCode;
36 
37 typedef struct MotionPixelsContext {
43  int codes_count, current_codes_count;
47  YuvPixel *vpt, *hpt;
48  uint8_t gradient_scale[3];
52 
54 {
55  MotionPixelsContext *mp = avctx->priv_data;
56  int w4 = (avctx->width + 3) & ~3;
57  int h4 = (avctx->height + 3) & ~3;
58 
59  if(avctx->extradata_size < 2){
60  av_log(avctx, AV_LOG_ERROR, "extradata too small\n");
61  return AVERROR_INVALIDDATA;
62  }
63 
65  mp->avctx = avctx;
66  ff_dsputil_init(&mp->dsp, avctx);
67  mp->changes_map = av_mallocz(avctx->width * h4);
68  mp->offset_bits_len = av_log2(avctx->width * avctx->height) + 1;
69  mp->vpt = av_mallocz(avctx->height * sizeof(YuvPixel));
70  mp->hpt = av_mallocz(h4 * w4 / 16 * sizeof(YuvPixel));
71  avctx->pix_fmt = AV_PIX_FMT_RGB555;
73  return 0;
74 }
75 
76 static void mp_read_changes_map(MotionPixelsContext *mp, GetBitContext *gb, int count, int bits_len, int read_color)
77 {
78  uint16_t *pixels;
79  int offset, w, h, color = 0, x, y, i;
80 
81  while (count--) {
82  offset = get_bits_long(gb, mp->offset_bits_len);
83  w = get_bits(gb, bits_len) + 1;
84  h = get_bits(gb, bits_len) + 1;
85  if (read_color)
86  color = get_bits(gb, 15);
87  x = offset % mp->avctx->width;
88  y = offset / mp->avctx->width;
89  if (y >= mp->avctx->height)
90  continue;
91  w = FFMIN(w, mp->avctx->width - x);
92  h = FFMIN(h, mp->avctx->height - y);
93  pixels = (uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
94  while (h--) {
95  mp->changes_map[offset] = w;
96  if (read_color)
97  for (i = 0; i < w; ++i)
98  pixels[i] = color;
99  offset += mp->avctx->width;
100  pixels += mp->frame.linesize[0] / 2;
101  }
102  }
103 }
104 
105 static int mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size, int code)
106 {
107  while (get_bits1(gb)) {
108  ++size;
109  if (size > mp->max_codes_bits) {
110  av_log(mp->avctx, AV_LOG_ERROR, "invalid code size %d/%d\n", size, mp->max_codes_bits);
111  return AVERROR_INVALIDDATA;
112  }
113  code <<= 1;
114  if (mp_get_code(mp, gb, size, code + 1) < 0)
115  return AVERROR_INVALIDDATA;
116  }
117  if (mp->current_codes_count >= MAX_HUFF_CODES) {
118  av_log(mp->avctx, AV_LOG_ERROR, "too many codes\n");
119  return AVERROR_INVALIDDATA;
120  }
121 
122  mp->codes[mp->current_codes_count ].code = code;
123  mp->codes[mp->current_codes_count++].size = size;
124  return 0;
125 }
126 
128 {
129  if (mp->codes_count == 1) {
130  mp->codes[0].delta = get_bits(gb, 4);
131  } else {
132  int i;
133  int ret;
134 
135  mp->max_codes_bits = get_bits(gb, 4);
136  for (i = 0; i < mp->codes_count; ++i)
137  mp->codes[i].delta = get_bits(gb, 4);
138  mp->current_codes_count = 0;
139  if ((ret = mp_get_code(mp, gb, 0, 0)) < 0)
140  return ret;
141  if (mp->current_codes_count < mp->codes_count) {
142  av_log(mp->avctx, AV_LOG_ERROR, "too few codes\n");
143  return AVERROR_INVALIDDATA;
144  }
145  }
146  return 0;
147 }
148 
149 static int mp_gradient(MotionPixelsContext *mp, int component, int v)
150 {
151  int delta;
152 
153  delta = (v - 7) * mp->gradient_scale[component];
154  mp->gradient_scale[component] = (v == 0 || v == 14) ? 2 : 1;
155  return delta;
156 }
157 
159 {
160  int color;
161 
162  color = *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
163  return mp_rgb_yuv_table[color];
164 }
165 
166 static void mp_set_rgb_from_yuv(MotionPixelsContext *mp, int x, int y, const YuvPixel *p)
167 {
168  int color;
169 
170  color = mp_yuv_to_rgb(p->y, p->v, p->u, 1);
171  *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2] = color;
172 }
173 
175 {
176  int i;
177 
178  i = (mp->codes_count == 1) ? 0 : get_vlc2(gb, mp->vlc.table, mp->max_codes_bits, 1);
179  return mp->codes[i].delta;
180 }
181 
183 {
184  YuvPixel p;
185  const int y0 = y * mp->avctx->width;
186  int w, i, x = 0;
187 
188  p = mp->vpt[y];
189  if (mp->changes_map[y0 + x] == 0) {
190  memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
191  ++x;
192  }
193  while (x < mp->avctx->width) {
194  w = mp->changes_map[y0 + x];
195  if (w != 0) {
196  if ((y & 3) == 0) {
197  if (mp->changes_map[y0 + x + mp->avctx->width] < w ||
198  mp->changes_map[y0 + x + mp->avctx->width * 2] < w ||
199  mp->changes_map[y0 + x + mp->avctx->width * 3] < w) {
200  for (i = (x + 3) & ~3; i < x + w; i += 4) {
201  mp->hpt[((y / 4) * mp->avctx->width + i) / 4] = mp_get_yuv_from_rgb(mp, i, y);
202  }
203  }
204  }
205  x += w;
206  memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
207  p = mp_get_yuv_from_rgb(mp, x - 1, y);
208  } else {
209  p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
210  p.y = av_clip(p.y, 0, 31);
211  if ((x & 3) == 0) {
212  if ((y & 3) == 0) {
213  p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
214  p.v = av_clip(p.v, -32, 31);
215  p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
216  p.u = av_clip(p.u, -32, 31);
217  mp->hpt[((y / 4) * mp->avctx->width + x) / 4] = p;
218  } else {
219  p.v = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].v;
220  p.u = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].u;
221  }
222  }
223  mp_set_rgb_from_yuv(mp, x, y, &p);
224  ++x;
225  }
226  }
227 }
228 
230 {
231  YuvPixel p;
232  int y, y0;
233 
234  av_assert1(mp->changes_map[0]);
235 
236  for (y = 0; y < mp->avctx->height; ++y) {
237  if (mp->changes_map[y * mp->avctx->width] != 0) {
238  memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
239  p = mp_get_yuv_from_rgb(mp, 0, y);
240  } else {
241  p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
242  p.y = av_clip(p.y, 0, 31);
243  if ((y & 3) == 0) {
244  p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
245  p.v = av_clip(p.v, -32, 31);
246  p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
247  p.u = av_clip(p.u, -32, 31);
248  }
249  mp->vpt[y] = p;
250  mp_set_rgb_from_yuv(mp, 0, y, &p);
251  }
252  }
253  for (y0 = 0; y0 < 2; ++y0)
254  for (y = y0; y < mp->avctx->height; y += 2)
255  mp_decode_line(mp, gb, y);
256 }
257 
258 static int mp_decode_frame(AVCodecContext *avctx,
259  void *data, int *got_frame,
260  AVPacket *avpkt)
261 {
262  const uint8_t *buf = avpkt->data;
263  int buf_size = avpkt->size;
264  MotionPixelsContext *mp = avctx->priv_data;
265  GetBitContext gb;
266  int i, count1, count2, sz, ret;
267 
268  if ((ret = ff_reget_buffer(avctx, &mp->frame)) < 0)
269  return ret;
270 
271  /* le32 bitstream msb first */
273  if (!mp->bswapbuf)
274  return AVERROR(ENOMEM);
275  mp->dsp.bswap_buf((uint32_t *)mp->bswapbuf, (const uint32_t *)buf, buf_size / 4);
276  if (buf_size & 3)
277  memcpy(mp->bswapbuf + (buf_size & ~3), buf + (buf_size & ~3), buf_size & 3);
278  memset(mp->bswapbuf + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
279  init_get_bits(&gb, mp->bswapbuf, buf_size * 8);
280 
281  memset(mp->changes_map, 0, avctx->width * avctx->height);
282  for (i = !(avctx->extradata[1] & 2); i < 2; ++i) {
283  count1 = get_bits(&gb, 12);
284  count2 = get_bits(&gb, 12);
285  mp_read_changes_map(mp, &gb, count1, 8, i);
286  mp_read_changes_map(mp, &gb, count2, 4, i);
287  }
288 
289  mp->codes_count = get_bits(&gb, 4);
290  if (mp->codes_count == 0)
291  goto end;
292 
293  if (mp->changes_map[0] == 0) {
294  *(uint16_t *)mp->frame.data[0] = get_bits(&gb, 15);
295  mp->changes_map[0] = 1;
296  }
297  if (mp_read_codes_table(mp, &gb) < 0)
298  goto end;
299 
300  sz = get_bits(&gb, 18);
301  if (avctx->extradata[0] != 5)
302  sz += get_bits(&gb, 18);
303  if (sz == 0)
304  goto end;
305 
306  if (mp->max_codes_bits <= 0)
307  goto end;
308  if (init_vlc(&mp->vlc, mp->max_codes_bits, mp->codes_count, &mp->codes[0].size, sizeof(HuffCode), 1, &mp->codes[0].code, sizeof(HuffCode), 4, 0))
309  goto end;
310  mp_decode_frame_helper(mp, &gb);
311  ff_free_vlc(&mp->vlc);
312 
313 end:
314  if ((ret = av_frame_ref(data, &mp->frame)) < 0)
315  return ret;
316  *got_frame = 1;
317  return buf_size;
318 }
319 
321 {
322  MotionPixelsContext *mp = avctx->priv_data;
323 
324  av_freep(&mp->changes_map);
325  av_freep(&mp->vpt);
326  av_freep(&mp->hpt);
327  av_freep(&mp->bswapbuf);
328  av_frame_unref(&mp->frame);
329 
330  return 0;
331 }
332 
334  .name = "motionpixels",
335  .type = AVMEDIA_TYPE_VIDEO,
337  .priv_data_size = sizeof(MotionPixelsContext),
338  .init = mp_decode_init,
339  .close = mp_decode_end,
341  .capabilities = CODEC_CAP_DR1,
342  .long_name = NULL_IF_CONFIG_SMALL("Motion Pixels video"),
343 };
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
float v
av_cold void ff_dsputil_init(DSPContext *c, AVCodecContext *avctx)
Definition: dsputil.c:2675
#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
uint8_t size
Definition: motionpixels.c:33
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:240
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
AVCodec ff_motionpixels_decoder
Definition: motionpixels.c:333
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
output residual component w
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
uint8_t delta
Definition: motionpixels.c:34
uint8_t
#define av_cold
Definition: attributes.h:78
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:77
end end
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.
static YuvPixel mp_get_yuv_from_rgb(MotionPixelsContext *mp, int x, int y)
Definition: motionpixels.c:158
uint8_t * data
bitstream reader API header.
Discrete Time axis x
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
static const uint8_t offset[127][2]
Definition: vf_spp.c:70
external API header
Definition: get_bits.h:63
struct MotionPixelsContext MotionPixelsContext
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
Identical in function to av_frame_make_writable(), except it uses ff_get_buffer() to allocate the buf...
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
#define FFMIN(a, b)
Definition: common.h:58
static int mp_yuv_to_rgb(int y, int v, int u, int clip_rgb)
ret
Definition: avfilter.c:821
int width
picture width / height.
AVCodecContext * avctx
Definition: motionpixels.c:38
static int mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size, int code)
Definition: motionpixels.c:105
static int mp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: motionpixels.c:258
static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE(*table)[2], int bits, int max_depth)
Parse a vlc code.
Definition: get_bits.h:524
uint8_t * changes_map
Definition: motionpixels.c:41
static void mp_decode_frame_helper(MotionPixelsContext *mp, GetBitContext *gb)
Definition: motionpixels.c:229
static av_cold int mp_decode_init(AVCodecContext *avctx)
Definition: motionpixels.c:53
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
HuffCode codes[MAX_HUFF_CODES]
Definition: motionpixels.c:45
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
#define init_vlc(vlc, nb_bits, nb_codes,bits, bits_wrap, bits_size,codes, codes_wrap, codes_size,flags)
Definition: get_bits.h:426
void * buf
Definition: avisynth_c.h:594
struct HuffCode HuffCode
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:273
void avcodec_get_frame_defaults(AVFrame *frame)
Set the fields of the given AVFrame to default values.
synthesis window for stochastic i
void(* bswap_buf)(uint32_t *dst, const uint32_t *src, int w)
Definition: dsputil.h:208
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:379
static int mp_gradient(MotionPixelsContext *mp, int component, int v)
Definition: motionpixels.c:149
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:330
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition: get_bits.h:306
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
static int mp_get_vlc(MotionPixelsContext *mp, GetBitContext *gb)
Definition: motionpixels.c:174
uint8_t gradient_scale[3]
Definition: motionpixels.c:48
int av_frame_ref(AVFrame *dst, AVFrame *src)
Setup a new reference to the data described by an given frame.
Definition: frame.c:228
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
Synth Windw Norm while(pin< pend)%Until the end...%---Analysis x_w
static void mp_decode_line(MotionPixelsContext *mp, GetBitContext *gb, int y)
Definition: motionpixels.c:182
common internal api header.
static void mp_read_changes_map(MotionPixelsContext *mp, GetBitContext *gb, int count, int bits_len, int read_color)
Definition: motionpixels.c:76
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:269
function y
Definition: D.m:1
#define MAX_HUFF_CODES
Definition: motionpixels.c:27
DSP utils.
static void mp_set_rgb_from_yuv(MotionPixelsContext *mp, int x, int y, const YuvPixel *p)
Definition: motionpixels.c:166
static av_cold int mp_decode_end(AVCodecContext *avctx)
Definition: motionpixels.c:320
#define av_log2
Definition: intmath.h:89
VLC_TYPE(* table)[2]
code, bits
Definition: get_bits.h:65
static int mp_read_codes_table(MotionPixelsContext *mp, GetBitContext *gb)
Definition: motionpixels.c:127
static YuvPixel mp_rgb_yuv_table[1<< 15]
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
static void motionpixels_tableinit(void)
This structure stores compressed data.
void ff_free_vlc(VLC *vlc)
Definition: bitstream.c:344
DSPContext.
Definition: dsputil.h:127