zmbv.c
Go to the documentation of this file.
1 /*
2  * Zip Motion Blocks Video (ZMBV) decoder
3  * Copyright (c) 2006 Konstantin Shishkov
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
27 #include <stdio.h>
28 #include <stdlib.h>
29 
30 #include "libavutil/intreadwrite.h"
31 #include "avcodec.h"
32 
33 #include <zlib.h>
34 
35 #define ZMBV_KEYFRAME 1
36 #define ZMBV_DELTAPAL 2
37 
38 enum ZmbvFormat {
48 };
49 
50 /*
51  * Decoder context
52  */
53 typedef struct ZmbvContext {
56 
57  int bpp;
58  unsigned int decomp_size;
59  uint8_t* decomp_buf;
60  uint8_t pal[768];
61  uint8_t *prev, *cur;
62  int width, height;
63  int fmt;
64  int comp;
65  int flags;
66  int bw, bh, bx, by;
68  z_stream zstream;
69  int (*decode_intra)(struct ZmbvContext *c);
70  int (*decode_xor)(struct ZmbvContext *c);
71 } ZmbvContext;
72 
78 {
79  uint8_t *src = c->decomp_buf;
80  uint8_t *output, *prev;
81  int8_t *mvec;
82  int x, y;
83  int d, dx, dy, bw2, bh2;
84  int block;
85  int i, j;
86  int mx, my;
87 
88  output = c->cur;
89  prev = c->prev;
90 
91  if (c->flags & ZMBV_DELTAPAL) {
92  for (i = 0; i < 768; i++)
93  c->pal[i] ^= *src++;
94  }
95 
96  mvec = (int8_t*)src;
97  src += ((c->bx * c->by * 2 + 3) & ~3);
98 
99  block = 0;
100  for (y = 0; y < c->height; y += c->bh) {
101  bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y);
102  for (x = 0; x < c->width; x += c->bw) {
103  uint8_t *out, *tprev;
104 
105  d = mvec[block] & 1;
106  dx = mvec[block] >> 1;
107  dy = mvec[block + 1] >> 1;
108  block += 2;
109 
110  bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x);
111 
112  /* copy block - motion vectors out of bounds are used to zero blocks */
113  out = output + x;
114  tprev = prev + x + dx + dy * c->width;
115  mx = x + dx;
116  my = y + dy;
117  for (j = 0; j < bh2; j++) {
118  if (my + j < 0 || my + j >= c->height) {
119  memset(out, 0, bw2);
120  } else {
121  for (i = 0; i < bw2; i++) {
122  if (mx + i < 0 || mx + i >= c->width)
123  out[i] = 0;
124  else
125  out[i] = tprev[i];
126  }
127  }
128  out += c->width;
129  tprev += c->width;
130  }
131 
132  if (d) { /* apply XOR'ed difference */
133  out = output + x;
134  for (j = 0; j < bh2; j++) {
135  for (i = 0; i < bw2; i++)
136  out[i] ^= *src++;
137  out += c->width;
138  }
139  }
140  }
141  output += c->width * c->bh;
142  prev += c->width * c->bh;
143  }
144  if (src - c->decomp_buf != c->decomp_len)
145  av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n",
146  src-c->decomp_buf, c->decomp_len);
147  return 0;
148 }
149 
155 {
156  uint8_t *src = c->decomp_buf;
157  uint16_t *output, *prev;
158  int8_t *mvec;
159  int x, y;
160  int d, dx, dy, bw2, bh2;
161  int block;
162  int i, j;
163  int mx, my;
164 
165  output = (uint16_t*)c->cur;
166  prev = (uint16_t*)c->prev;
167 
168  mvec = (int8_t*)src;
169  src += ((c->bx * c->by * 2 + 3) & ~3);
170 
171  block = 0;
172  for (y = 0; y < c->height; y += c->bh) {
173  bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y);
174  for (x = 0; x < c->width; x += c->bw) {
175  uint16_t *out, *tprev;
176 
177  d = mvec[block] & 1;
178  dx = mvec[block] >> 1;
179  dy = mvec[block + 1] >> 1;
180  block += 2;
181 
182  bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x);
183 
184  /* copy block - motion vectors out of bounds are used to zero blocks */
185  out = output + x;
186  tprev = prev + x + dx + dy * c->width;
187  mx = x + dx;
188  my = y + dy;
189  for (j = 0; j < bh2; j++) {
190  if (my + j < 0 || my + j >= c->height) {
191  memset(out, 0, bw2 * 2);
192  } else {
193  for (i = 0; i < bw2; i++) {
194  if (mx + i < 0 || mx + i >= c->width)
195  out[i] = 0;
196  else
197  out[i] = tprev[i];
198  }
199  }
200  out += c->width;
201  tprev += c->width;
202  }
203 
204  if (d) { /* apply XOR'ed difference */
205  out = output + x;
206  for (j = 0; j < bh2; j++){
207  for (i = 0; i < bw2; i++) {
208  out[i] ^= *((uint16_t*)src);
209  src += 2;
210  }
211  out += c->width;
212  }
213  }
214  }
215  output += c->width * c->bh;
216  prev += c->width * c->bh;
217  }
218  if (src - c->decomp_buf != c->decomp_len)
219  av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n",
220  src-c->decomp_buf, c->decomp_len);
221  return 0;
222 }
223 
224 #ifdef ZMBV_ENABLE_24BPP
225 
229 static int zmbv_decode_xor_24(ZmbvContext *c)
230 {
231  uint8_t *src = c->decomp_buf;
232  uint8_t *output, *prev;
233  int8_t *mvec;
234  int x, y;
235  int d, dx, dy, bw2, bh2;
236  int block;
237  int i, j;
238  int mx, my;
239  int stride;
240 
241  output = c->cur;
242  prev = c->prev;
243 
244  stride = c->width * 3;
245  mvec = (int8_t*)src;
246  src += ((c->bx * c->by * 2 + 3) & ~3);
247 
248  block = 0;
249  for (y = 0; y < c->height; y += c->bh) {
250  bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y);
251  for (x = 0; x < c->width; x += c->bw) {
252  uint8_t *out, *tprev;
253 
254  d = mvec[block] & 1;
255  dx = mvec[block] >> 1;
256  dy = mvec[block + 1] >> 1;
257  block += 2;
258 
259  bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x);
260 
261  /* copy block - motion vectors out of bounds are used to zero blocks */
262  out = output + x * 3;
263  tprev = prev + (x + dx) * 3 + dy * stride;
264  mx = x + dx;
265  my = y + dy;
266  for (j = 0; j < bh2; j++) {
267  if (my + j < 0 || my + j >= c->height) {
268  memset(out, 0, bw2 * 3);
269  } else {
270  for (i = 0; i < bw2; i++){
271  if (mx + i < 0 || mx + i >= c->width) {
272  out[i * 3 + 0] = 0;
273  out[i * 3 + 1] = 0;
274  out[i * 3 + 2] = 0;
275  } else {
276  out[i * 3 + 0] = tprev[i * 3 + 0];
277  out[i * 3 + 1] = tprev[i * 3 + 1];
278  out[i * 3 + 2] = tprev[i * 3 + 2];
279  }
280  }
281  }
282  out += stride;
283  tprev += stride;
284  }
285 
286  if (d) { /* apply XOR'ed difference */
287  out = output + x * 3;
288  for (j = 0; j < bh2; j++) {
289  for (i = 0; i < bw2; i++) {
290  out[i * 3 + 0] ^= *src++;
291  out[i * 3 + 1] ^= *src++;
292  out[i * 3 + 2] ^= *src++;
293  }
294  out += stride;
295  }
296  }
297  }
298  output += stride * c->bh;
299  prev += stride * c->bh;
300  }
301  if (src - c->decomp_buf != c->decomp_len)
302  av_log(c->avctx, AV_LOG_ERROR, "Used %i of %i bytes\n",
303  src-c->decomp_buf, c->decomp_len);
304  return 0;
305 }
306 #endif //ZMBV_ENABLE_24BPP
307 
313 {
314  uint8_t *src = c->decomp_buf;
315  uint32_t *output, *prev;
316  int8_t *mvec;
317  int x, y;
318  int d, dx, dy, bw2, bh2;
319  int block;
320  int i, j;
321  int mx, my;
322 
323  output = (uint32_t*)c->cur;
324  prev = (uint32_t*)c->prev;
325 
326  mvec = (int8_t*)src;
327  src += ((c->bx * c->by * 2 + 3) & ~3);
328 
329  block = 0;
330  for (y = 0; y < c->height; y += c->bh) {
331  bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y);
332  for (x = 0; x < c->width; x += c->bw) {
333  uint32_t *out, *tprev;
334 
335  d = mvec[block] & 1;
336  dx = mvec[block] >> 1;
337  dy = mvec[block + 1] >> 1;
338  block += 2;
339 
340  bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x);
341 
342  /* copy block - motion vectors out of bounds are used to zero blocks */
343  out = output + x;
344  tprev = prev + x + dx + dy * c->width;
345  mx = x + dx;
346  my = y + dy;
347  for (j = 0; j < bh2; j++) {
348  if (my + j < 0 || my + j >= c->height) {
349  memset(out, 0, bw2 * 4);
350  } else {
351  for (i = 0; i < bw2; i++){
352  if (mx + i < 0 || mx + i >= c->width)
353  out[i] = 0;
354  else
355  out[i] = tprev[i];
356  }
357  }
358  out += c->width;
359  tprev += c->width;
360  }
361 
362  if (d) { /* apply XOR'ed difference */
363  out = output + x;
364  for (j = 0; j < bh2; j++){
365  for (i = 0; i < bw2; i++) {
366  out[i] ^= *((uint32_t *) src);
367  src += 4;
368  }
369  out += c->width;
370  }
371  }
372  }
373  output += c->width * c->bh;
374  prev += c->width * c->bh;
375  }
376  if (src - c->decomp_buf != c->decomp_len)
377  av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n",
378  src-c->decomp_buf, c->decomp_len);
379  return 0;
380 }
381 
386 {
387  uint8_t *src = c->decomp_buf;
388 
389  /* make the palette available on the way out */
390  if (c->fmt == ZMBV_FMT_8BPP) {
391  memcpy(c->pal, src, 768);
392  src += 768;
393  }
394 
395  memcpy(c->cur, src, c->width * c->height * (c->bpp / 8));
396  return 0;
397 }
398 
399 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
400 {
401  const uint8_t *buf = avpkt->data;
402  int buf_size = avpkt->size;
403  ZmbvContext * const c = avctx->priv_data;
404  int zret = Z_OK; // Zlib return code
405  int len = buf_size;
406  int hi_ver, lo_ver;
407 
408  if (c->pic.data[0])
409  avctx->release_buffer(avctx, &c->pic);
410 
411  c->pic.reference = 1;
413  if (avctx->get_buffer(avctx, &c->pic) < 0) {
414  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
415  return -1;
416  }
417 
418  /* parse header */
419  c->flags = buf[0];
420  buf++; len--;
421  if (c->flags & ZMBV_KEYFRAME) {
422  hi_ver = buf[0];
423  lo_ver = buf[1];
424  c->comp = buf[2];
425  c->fmt = buf[3];
426  c->bw = buf[4];
427  c->bh = buf[5];
428 
429  buf += 6;
430  len -= 6;
431  av_log(avctx, AV_LOG_DEBUG,
432  "Flags=%X ver=%i.%i comp=%i fmt=%i blk=%ix%i\n",
433  c->flags,hi_ver,lo_ver,c->comp,c->fmt,c->bw,c->bh);
434  if (hi_ver != 0 || lo_ver != 1) {
435  av_log(avctx, AV_LOG_ERROR, "Unsupported version %i.%i\n",
436  hi_ver, lo_ver);
437  return -1;
438  }
439  if (c->bw == 0 || c->bh == 0) {
440  av_log(avctx, AV_LOG_ERROR, "Unsupported block size %ix%i\n",
441  c->bw, c->bh);
442  return -1;
443  }
444  if (c->comp != 0 && c->comp != 1) {
445  av_log(avctx, AV_LOG_ERROR, "Unsupported compression type %i\n",
446  c->comp);
447  return -1;
448  }
449 
450  switch (c->fmt) {
451  case ZMBV_FMT_8BPP:
452  c->bpp = 8;
455  break;
456  case ZMBV_FMT_15BPP:
457  case ZMBV_FMT_16BPP:
458  c->bpp = 16;
461  break;
462 #ifdef ZMBV_ENABLE_24BPP
463  case ZMBV_FMT_24BPP:
464  c->bpp = 24;
466  c->decode_xor = zmbv_decode_xor_24;
467  break;
468 #endif //ZMBV_ENABLE_24BPP
469  case ZMBV_FMT_32BPP:
470  c->bpp = 32;
473  break;
474  default:
475  c->decode_intra = NULL;
476  c->decode_xor = NULL;
477  av_log(avctx, AV_LOG_ERROR,
478  "Unsupported (for now) format %i\n", c->fmt);
479  return -1;
480  }
481 
482  zret = inflateReset(&c->zstream);
483  if (zret != Z_OK) {
484  av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
485  return -1;
486  }
487 
488  c->cur = av_realloc(c->cur, avctx->width * avctx->height * (c->bpp / 8));
489  c->prev = av_realloc(c->prev, avctx->width * avctx->height * (c->bpp / 8));
490  c->bx = (c->width + c->bw - 1) / c->bw;
491  c->by = (c->height+ c->bh - 1) / c->bh;
492  }
493 
494  if (c->decode_intra == NULL) {
495  av_log(avctx, AV_LOG_ERROR, "Error! Got no format or no keyframe!\n");
496  return -1;
497  }
498 
499  if (c->comp == 0) { //Uncompressed data
500  if (c->decomp_size < len) {
501  av_log(avctx, AV_LOG_ERROR, "Buffer too small\n");
502  return AVERROR_INVALIDDATA;
503  }
504  memcpy(c->decomp_buf, buf, len);
505  } else { // ZLIB-compressed data
506  c->zstream.total_in = c->zstream.total_out = 0;
507  c->zstream.next_in = buf;
508  c->zstream.avail_in = len;
509  c->zstream.next_out = c->decomp_buf;
510  c->zstream.avail_out = c->decomp_size;
511  inflate(&c->zstream, Z_FINISH);
512  c->decomp_len = c->zstream.total_out;
513  }
514  if (c->flags & ZMBV_KEYFRAME) {
515  c->pic.key_frame = 1;
517  c->decode_intra(c);
518  } else {
519  c->pic.key_frame = 0;
521  if (c->decomp_len)
522  c->decode_xor(c);
523  }
524 
525  /* update frames */
526  {
527  uint8_t *out, *src;
528  int i, j;
529 
530  out = c->pic.data[0];
531  src = c->cur;
532  switch (c->fmt) {
533  case ZMBV_FMT_8BPP:
534  for (j = 0; j < c->height; j++) {
535  for (i = 0; i < c->width; i++) {
536  out[i * 3 + 0] = c->pal[(*src) * 3 + 0];
537  out[i * 3 + 1] = c->pal[(*src) * 3 + 1];
538  out[i * 3 + 2] = c->pal[(*src) * 3 + 2];
539  src++;
540  }
541  out += c->pic.linesize[0];
542  }
543  break;
544  case ZMBV_FMT_15BPP:
545  for (j = 0; j < c->height; j++) {
546  for (i = 0; i < c->width; i++) {
547  uint16_t tmp = AV_RL16(src);
548  src += 2;
549  out[i * 3 + 0] = (tmp & 0x7C00) >> 7;
550  out[i * 3 + 1] = (tmp & 0x03E0) >> 2;
551  out[i * 3 + 2] = (tmp & 0x001F) << 3;
552  }
553  out += c->pic.linesize[0];
554  }
555  break;
556  case ZMBV_FMT_16BPP:
557  for (j = 0; j < c->height; j++) {
558  for (i = 0; i < c->width; i++) {
559  uint16_t tmp = AV_RL16(src);
560  src += 2;
561  out[i * 3 + 0] = (tmp & 0xF800) >> 8;
562  out[i * 3 + 1] = (tmp & 0x07E0) >> 3;
563  out[i * 3 + 2] = (tmp & 0x001F) << 3;
564  }
565  out += c->pic.linesize[0];
566  }
567  break;
568 #ifdef ZMBV_ENABLE_24BPP
569  case ZMBV_FMT_24BPP:
570  for (j = 0; j < c->height; j++) {
571  memcpy(out, src, c->width * 3);
572  src += c->width * 3;
573  out += c->pic.linesize[0];
574  }
575  break;
576 #endif //ZMBV_ENABLE_24BPP
577  case ZMBV_FMT_32BPP:
578  for (j = 0; j < c->height; j++) {
579  for (i = 0; i < c->width; i++) {
580  uint32_t tmp = AV_RL32(src);
581  src += 4;
582  AV_WB24(out+(i*3), tmp);
583  }
584  out += c->pic.linesize[0];
585  }
586  break;
587  default:
588  av_log(avctx, AV_LOG_ERROR, "Cannot handle format %i\n", c->fmt);
589  }
590  FFSWAP(uint8_t *, c->cur, c->prev);
591  }
592  *data_size = sizeof(AVFrame);
593  *(AVFrame*)data = c->pic;
594 
595  /* always report that the buffer was completely consumed */
596  return buf_size;
597 }
598 
599 
600 
601 /*
602  *
603  * Init zmbv decoder
604  *
605  */
607 {
608  ZmbvContext * const c = avctx->priv_data;
609  int zret; // Zlib return code
610 
611  c->avctx = avctx;
612 
613  c->width = avctx->width;
614  c->height = avctx->height;
615 
616  c->bpp = avctx->bits_per_coded_sample;
617 
618  // Needed if zlib unused or init aborted before inflateInit
619  memset(&c->zstream, 0, sizeof(z_stream));
620 
621  avctx->pix_fmt = PIX_FMT_RGB24;
622  c->decomp_size = (avctx->width + 255) * 4 * (avctx->height + 64);
623 
624  /* Allocate decompression buffer */
625  if (c->decomp_size) {
626  if ((c->decomp_buf = av_malloc(c->decomp_size)) == NULL) {
627  av_log(avctx, AV_LOG_ERROR,
628  "Can't allocate decompression buffer.\n");
629  return 1;
630  }
631  }
632 
633  c->zstream.zalloc = Z_NULL;
634  c->zstream.zfree = Z_NULL;
635  c->zstream.opaque = Z_NULL;
636  zret = inflateInit(&c->zstream);
637  if (zret != Z_OK) {
638  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
639  return 1;
640  }
641 
642  return 0;
643 }
644 
645 
646 
647 /*
648  *
649  * Uninit zmbv decoder
650  *
651  */
653 {
654  ZmbvContext * const c = avctx->priv_data;
655 
656  av_freep(&c->decomp_buf);
657 
658  if (c->pic.data[0])
659  avctx->release_buffer(avctx, &c->pic);
660  inflateEnd(&c->zstream);
661  av_freep(&c->cur);
662  av_freep(&c->prev);
663 
664  return 0;
665 }
666 
668  .name = "zmbv",
669  .type = AVMEDIA_TYPE_VIDEO,
670  .id = CODEC_ID_ZMBV,
671  .priv_data_size = sizeof(ZmbvContext),
672  .init = decode_init,
673  .close = decode_end,
674  .decode = decode_frame,
675  .capabilities = CODEC_CAP_DR1,
676  .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
677 };
678