Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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