]> git.sesse.net Git - ffmpeg/blob - libavcodec/prosumer.c
a2932852c931553c95b468a9150c37d4c286c8b8
[ffmpeg] / libavcodec / prosumer.c
1 /*
2  * Brooktree ProSumer Video decoder
3  * Copyright (c) 2018 Paul B Mahol
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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "libavutil/imgutils.h"
27 #include "libavutil/internal.h"
28 #include "libavutil/intreadwrite.h"
29 #include "libavutil/mem.h"
30
31 #include "avcodec.h"
32 #include "bytestream.h"
33 #include "internal.h"
34
35 typedef struct ProSumerContext {
36     GetByteContext gb;
37     PutByteContext pb;
38
39     unsigned stride;
40     unsigned size;
41     uint32_t lut[0x10000];
42     uint8_t *table_b;
43     uint8_t *decbuffer;
44 } ProSumerContext;
45
46 #define PAIR(high, low) (((uint64_t)(high) << 32) | low)
47
48 static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const uint32_t *lut)
49 {
50     int pos, idx, cnt, fill;
51     uint32_t a, b, c;
52
53     bytestream2_skip(gb, 32);
54     cnt = 4;
55     a = bytestream2_get_le32(gb);
56     idx = a >> 20;
57     b = lut[2 * idx];
58
59     while (1) {
60         if (((b & 0xFF00u) != 0x8000u) || (b & 0xFFu)) {
61             if ((b & 0xFF00u) != 0x8000u) {
62                 bytestream2_put_le16(pb, b);
63             } else if (b & 0xFFu) {
64                 idx = 0;
65                 for (int i = 0; i < (b & 0xFFu); i++)
66                     bytestream2_put_le32(pb, 0);
67             }
68             c = b >> 16;
69             if (c & 0xFF00u) {
70                 c = (((c >> 8) & 0xFFu) | (c & 0xFF00)) & 0xF00F;
71                 fill = lut[2 * idx + 1];
72                 if ((c & 0xFF00u) == 0x1000) {
73                     bytestream2_put_le16(pb, fill);
74                     c &= 0xFFFF00FFu;
75                 } else {
76                     bytestream2_put_le32(pb, fill);
77                     c &= 0xFFFF00FFu;
78                 }
79             }
80             while (c) {
81                 a <<= 4;
82                 cnt--;
83                 if (!cnt) {
84                     if (bytestream2_get_bytes_left(gb) <= 0) {
85                         if (!a)
86                             return 0;
87                         cnt = 4;
88                     } else {
89                         pos = bytestream2_tell(gb) ^ 2;
90                         bytestream2_seek(gb, pos, SEEK_SET);
91                         AV_WN16(&a, bytestream2_peek_le16(gb));
92                         pos = pos ^ 2;
93                         bytestream2_seek(gb, pos, SEEK_SET);
94                         bytestream2_skip(gb, 2);
95                         cnt = 4;
96                     }
97                 }
98                 c--;
99             }
100             idx = a >> 20;
101             b = lut[2 * idx];
102             continue;
103         }
104         idx = 2;
105         while (idx) {
106             a <<= 4;
107             cnt--;
108             if (cnt) {
109                 idx--;
110                 continue;
111             }
112             if (bytestream2_get_bytes_left(gb) <= 0) {
113                 if (a) {
114                     cnt = 4;
115                     idx--;
116                     continue;
117                 }
118                 return 0;
119             }
120             pos = bytestream2_tell(gb) ^ 2;
121             bytestream2_seek(gb, pos, SEEK_SET);
122             AV_WN16(&a, bytestream2_peek_le16(gb));
123             pos = pos ^ 2;
124             bytestream2_seek(gb, pos, SEEK_SET);
125             bytestream2_skip(gb, 2);
126             cnt = 4;
127             idx--;
128         }
129         b = PAIR(4, a) >> 16;
130     }
131
132     return 0;
133 }
134
135 static void do_shift(uint32_t *dst, int offset, uint32_t *src, int stride, int height)
136 {
137     uint32_t x = (0x7F7F7F7F >> 1) & 0x7F7F7F7F;
138
139     dst += offset >> 2;
140
141     for (int i = 0; i < height; i++) {
142         for (int j = 0; j < stride >> 2; j++) {
143             dst[j] = (((src[j] >> 3) + (x & dst[j])) << 3) & 0xFCFCFCFC;
144         }
145
146         dst += stride >> 2;
147         src += stride >> 2;
148     }
149 }
150
151 static int decode_frame(AVCodecContext *avctx, void *data,
152                         int *got_frame, AVPacket *avpkt)
153 {
154     ProSumerContext *s = avctx->priv_data;
155     AVFrame * const frame = data;
156     int ret;
157
158     if (avpkt->size <= 32)
159         return AVERROR_INVALIDDATA;
160
161     memset(s->decbuffer, 0, s->size);
162     bytestream2_init(&s->gb, avpkt->data, avpkt->size);
163     bytestream2_init_writer(&s->pb, s->decbuffer, s->size);
164
165     decompress(&s->gb, AV_RL32(avpkt->data + 28) >> 1, &s->pb, s->lut);
166     do_shift((uint32_t *)s->decbuffer, 0, (uint32_t *)s->table_b, s->stride, 1);
167     do_shift((uint32_t *)s->decbuffer, s->stride, (uint32_t *)s->decbuffer, s->stride, avctx->height - 1);
168
169     ret = ff_get_buffer(avctx, frame, 0);
170     if (ret < 0)
171         return ret;
172
173     for (int i = avctx->height - 1; i >= 0 ; i--) {
174         uint8_t *y = &frame->data[0][i * frame->linesize[0]];
175         uint8_t *u = &frame->data[1][i * frame->linesize[1]];
176         uint8_t *v = &frame->data[2][i * frame->linesize[2]];
177         uint8_t *src = s->decbuffer + (avctx->height - 1 - i) * s->stride;
178
179         for (int j = 0; j < avctx->width; j += 8) {
180             *(u++) = *src++;
181             *(y++) = *src++;
182             *(v++) = *src++;
183             *(y++) = *src++;
184
185             *(u++) = *src++;
186             *(y++) = *src++;
187             *(v++) = *src++;
188             *(y++) = *src++;
189
190             *(y++) = *src++;
191             *(y++) = *src++;
192             *(y++) = *src++;
193             *(y++) = *src++;
194         }
195     }
196
197     frame->pict_type = AV_PICTURE_TYPE_I;
198     frame->key_frame = 1;
199     *got_frame = 1;
200
201     return avpkt->size;
202 }
203
204 static const uint32_t table[] = {
205     0x0000, 0x10000001, 0x0101, 0x20000001, 0x0202, 0x30000001, 0xFFFF, 0x40000001, 0xFEFE, 0x50000001,
206     0x0001, 0x70000001, 0x0100, 0x80000001, 0x00FF, 0x90000001, 0xFF00, 0xA0000001, 0x8001, 0x60000001,
207     0x8002, 0xB0000001, 0xFCFC, 0x01000002, 0x0404, 0x03000002, 0x0002, 0xD3000002, 0xFEFC, 0x02000002,
208     0xFCFE, 0x04000002, 0xFEFF, 0xD2000002, 0x0808, 0x06000002, 0xFFFE, 0x05000002, 0x0402, 0xC0000002,
209     0x0204, 0xC1000002, 0xF8F8, 0xC3000002, 0x0201, 0xC4000002, 0x0102, 0xC6000002, 0x0804, 0xF3000002,
210     0x0408, 0xE0000002, 0xF8FC, 0xE1000002, 0xFCF8, 0xC7000002, 0x00FE, 0xD0000002, 0xFE00, 0xD4000002,
211     0xFF01, 0xD5000002, 0x01FF, 0xD6000002, 0x0200, 0xD7000002, 0xFCFF, 0xE2000002, 0x0104, 0xE3000002,
212     0xF0F0, 0xE5000002, 0x0401, 0xE7000002, 0x02FE, 0xF0000002, 0xFE02, 0xF1000002, 0xFE01, 0xF2000002,
213     0x01FE, 0xF4000002, 0xFF02, 0xF5000002, 0x02FF, 0xF6000002, 0x8003, 0xC2000002, 0x8004, 0x07000002,
214     0x8005, 0xD1000002, 0x8006, 0xC5000002, 0x8007, 0xE6000002, 0x8008, 0xE4000002, 0x8009, 0xF7000002,
215     0xFC02, 0x08000003, 0xFE04, 0x08100003, 0xFC00, 0x08200003, 0x02FC, 0x08300003, 0x1010, 0x08400003,
216     0x00FC, 0x08500003, 0x0004, 0x08600003, 0x0400, 0x08700003, 0xFFFC, 0x08800003, 0x1008, 0x08900003,
217     0x0810, 0x08A00003, 0x0802, 0x08B00003, 0x0208, 0x08C00003, 0xFEF8, 0x08D00003, 0xFC01, 0x08E00003,
218     0x04FF, 0x08F00003, 0xF8FE, 0x09000003, 0xFC04, 0x09100003, 0x04FC, 0x09200003, 0xFF04, 0x09300003,
219     0x01FC, 0x09400003, 0xF0F8, 0x09500003, 0xF8F0, 0x09600003, 0x04FE, 0x09700003, 0xF0FC, 0x09800003,
220     0x0008, 0x09900003, 0x08FE, 0x09A00003, 0x01F8, 0x09B00003, 0x0800, 0x09C00003, 0x08FC, 0x09D00003,
221     0xFE08, 0x09E00003, 0xFC08, 0x09F00003, 0xF800, 0x0A000003, 0x0108, 0x0A100003, 0xF802, 0x0A200003,
222     0x0801, 0x0A300003, 0x00F8, 0x0A400003, 0xF804, 0x0A500003, 0xF8FF, 0x0A600003, 0xFFF8, 0x0A700003,
223     0x04F8, 0x0A800003, 0x02F8, 0x0A900003, 0x1004, 0x0AA00003, 0x08F8, 0x0AB00003, 0xF808, 0x0AC00003,
224     0x0410, 0x0AD00003, 0xFF08, 0x0AE00003, 0x08FF, 0x0AF00003, 0xFCF0, 0x0B000003, 0xF801, 0x0B100003,
225     0xE0F0, 0x0B200003, 0xF3F3, 0x0B300003, 0xF0E0, 0x0B400003, 0xFAFA, 0x0B500003, 0xF7F7, 0x0B600003,
226     0xFEF0, 0x0B700003, 0xF0FE, 0x0B800003, 0xE9E9, 0x0B900003, 0xF9F9, 0x0BA00003, 0x2020, 0x0BB00003,
227     0xE0E0, 0x0BC00003, 0x02F0, 0x0BD00003, 0x04F0, 0x0BE00003, 0x2010, 0x0BF00003, 0xECEC, 0x0C000003,
228     0xEFEF, 0x0C100003, 0x1020, 0x0C200003, 0xF5F5, 0x0C300003, 0xF4F4, 0x0C400003, 0xEDED, 0x0C500003,
229     0xEAEA, 0x0C600003, 0xFBFB, 0x0C700003, 0x1002, 0x0C800003, 0xF2F2, 0x0C900003, 0xF6F6, 0x0CA00003,
230     0xF1F1, 0x0CB00003, 0xFDFD, 0x0CC00003, 0x0210, 0x0CD00003, 0x10FF, 0x0CE00003, 0xFDFE, 0x0CF00003,
231     0x10F8, 0x0D000003, 0x1000, 0x0D100003, 0xF001, 0x0D200003, 0x1001, 0x0D300003, 0x0010, 0x0D400003,
232     0x10FE, 0x0D500003, 0xEBEB, 0x0D600003, 0xFE10, 0x0D700003, 0x0110, 0x0D800003, 0xF000, 0x0D900003,
233     0x08F0, 0x0DA00003, 0x01F0, 0x0DB00003, 0x0303, 0x0DC00003, 0x00F0, 0x0DD00003, 0xF002, 0x0DE00003,
234     0x10FC, 0x0DF00003, 0xFC10, 0x0E000003, 0xF0FF, 0x0E100003, 0xEEEE, 0x0E200003, 0xF004, 0x0E300003,
235     0xFFF0, 0x0E400003, 0xF7F8, 0x0E500003, 0xF3F2, 0x0E600003, 0xF9FA, 0x0E700003, 0x0820, 0x0E800003,
236     0x0302, 0x0E900003, 0xE0F8, 0x0EA00003, 0x0505, 0x0EB00003, 0x2008, 0x0EC00003, 0xE8E8, 0x0ED00003,
237     0x0403, 0x0EE00003, 0xFBFC, 0x0EF00003, 0xFCFD, 0x0F000003, 0xFBFA, 0x0F100003, 0x0203, 0x0F200003,
238     0xFCFB, 0x0F300003, 0x0304, 0x0F400003, 0xF810, 0x0F500003, 0xFF10, 0x0F600003, 0xF008, 0x0F700003,
239     0xFEFD, 0x0F800003, 0xF7F6, 0x0F900003, 0xF2F1, 0x0FA00003, 0xF3F4, 0x0FB00003, 0xEDEC, 0x0FC00003,
240     0xF4F1, 0x0FD00003, 0xF5F6, 0x0FE00003, 0xF0F1, 0x0FF00003, 0xF9F8, 0xC8000003, 0x10F0, 0xC8100003,
241     0xF2F3, 0xC8200003, 0xF7F9, 0xC8300003, 0xF6F5, 0xC8400003, 0xF0EF, 0xC8500003, 0xF4F5, 0xC8600003,
242     0xF6F7, 0xC8700003, 0xFAF9, 0xC8800003, 0x0405, 0xC8900003, 0xF8F9, 0xC8A00003, 0xFAFB, 0xC8B00003,
243     0xF1F0, 0xC8C00003, 0xF4F3, 0xC8D00003, 0xF1F2, 0xC8E00003, 0xF8E0, 0xC8F00003, 0xF8F7, 0xC9000003,
244     0xFDFC, 0xC9100003, 0xF8FA, 0xC9200003, 0xFAF6, 0xC9300003, 0xEEEF, 0xC9400003, 0xF5F7, 0xC9500003,
245     0xFDFB, 0xC9600003, 0xF4F6, 0xC9700003, 0xFCFA, 0xC9800003, 0xECED, 0xC9900003, 0xF0F3, 0xC9A00003,
246     0xF3F1, 0xC9B00003, 0xECEB, 0xC9C00003, 0xEDEE, 0xC9D00003, 0xF9F7, 0xC9E00003, 0x0420, 0xC9F00003,
247     0xEBEA, 0xCA000003, 0xF0F4, 0xCA100003, 0xF3F5, 0xCA200003, 0xFAF7, 0xCA300003, 0x0301, 0xCA400003,
248     0xF3F7, 0xCA500003, 0xF7F3, 0xCA600003, 0xEFF0, 0xCA700003, 0xF9F6, 0xCA800003, 0xEFEE, 0xCA900003,
249     0xF4F7, 0xCAA00003, 0x0504, 0xCAB00003, 0xF5F4, 0xCAC00003, 0xF1F3, 0xCAD00003, 0xEBEE, 0xCAE00003,
250     0xF2F5, 0xCAF00003, 0xF3EF, 0xCB000003, 0xF5F1, 0xCB100003, 0xF9F3, 0xCB200003, 0xEDF0, 0xCB300003,
251     0xEEF1, 0xCB400003, 0xF6F9, 0xCB500003, 0xF8FB, 0xCB600003, 0xF010, 0xCB700003, 0xF2F6, 0xCB800003,
252     0xF4ED, 0xCB900003, 0xF7FB, 0xCBA00003, 0xF8F3, 0xCBB00003, 0xEDEB, 0xCBC00003, 0xF0F2, 0xCBD00003,
253     0xF2F9, 0xCBE00003, 0xF8F1, 0xCBF00003, 0xFAFC, 0xCC000003, 0xFBF8, 0xCC100003, 0xF6F0, 0xCC200003,
254     0xFAF8, 0xCC300003, 0x0103, 0xCC400003, 0xF3F6, 0xCC500003, 0xF4F9, 0xCC600003, 0xF7F2, 0xCC700003,
255     0x2004, 0xCC800003, 0xF2F0, 0xCC900003, 0xF4F2, 0xCCA00003, 0xEEED, 0xCCB00003, 0xFCE0, 0xCCC00003,
256     0xEAE9, 0xCCD00003, 0xEAEB, 0xCCE00003, 0xF6F4, 0xCCF00003, 0xFFFD, 0xCD000003, 0xE9EA, 0xCD100003,
257     0xF1F4, 0xCD200003, 0xF6EF, 0xCD300003, 0xF6F8, 0xCD400003, 0xF8F6, 0xCD500003, 0xEFF2, 0xCD600003,
258     0xEFF1, 0xCD700003, 0xF7F1, 0xCD800003, 0xFBFD, 0xCD900003, 0xFEF6, 0xCDA00003, 0xFFF7, 0xCDB00003,
259     0x0605, 0xCDC00003, 0xF0F5, 0xCDD00003, 0xF0FA, 0xCDE00003, 0xF1F9, 0xCDF00003, 0xF2FC, 0xCE000003,
260     0xF7EE, 0xCE100003, 0xF7F5, 0xCE200003, 0xF9FC, 0xCE300003, 0xFAF5, 0xCE400003, 0xFBF1, 0xCE500003,
261     0xF1EF, 0xCE600003, 0xF1FA, 0xCE700003, 0xF4F8, 0xCE800003, 0xF7F0, 0xCE900003, 0xF7F4, 0xCEA00003,
262     0xF7FC, 0xCEB00003, 0xF9FB, 0xCEC00003, 0xFAF1, 0xCED00003, 0xFBF9, 0xCEE00003, 0xFDFF, 0xCEF00003,
263     0xE0FC, 0xCF000003, 0xEBEC, 0xCF100003, 0xEDEF, 0xCF200003, 0xEFED, 0xCF300003, 0xF1F6, 0xCF400003,
264     0xF2F7, 0xCF500003, 0xF3EE, 0xCF600003, 0xF3F8, 0xCF700003, 0xF5F2, 0xCF800003, 0xF8F2, 0xCF900003,
265     0xF9F1, 0xCFA00003, 0xF9F2, 0xCFB00003, 0xFBEF, 0xCFC00003, 0x00FD, 0xCFD00003, 0xECEE, 0xCFE00003,
266     0xF2EF, 0xCFF00003, 0xF2F8, 0xD8000003, 0xF5F0, 0xD8100003, 0xF6F2, 0xD8200003, 0xFCF7, 0xD8300003,
267     0xFCF9, 0xD8400003, 0x0506, 0xD8500003, 0xEEEC, 0xD8600003, 0xF0F6, 0xD8700003, 0xF2F4, 0xD8800003,
268     0xF6F1, 0xD8900003, 0xF8F5, 0xD8A00003, 0xF9F4, 0xD8B00003, 0xFBF7, 0xD8C00003, 0x0503, 0xD8D00003,
269     0xEFEC, 0xD8E00003, 0xF3F0, 0xD8F00003, 0xF4F0, 0xD9000003, 0xF5F3, 0xD9100003, 0xF6F3, 0xD9200003,
270     0xF7FA, 0xD9300003, 0x800A, 0xD9400003, 0x800B, 0xD9500003, 0x800C, 0xD9600003, 0x800D, 0xD9700003,
271     0x800E, 0xD9800003, 0x800F, 0xD9900003, 0x8010, 0xD9A00003, 0x8011, 0xD9B00003, 0x8012, 0xD9C00003,
272     0x8013, 0xD9D00003, 0x8014, 0xD9E00003, 0x8015, 0xD9F00003, 0x8016, 0xDA000003, 0x8017, 0xDA100003,
273     0x8018, 0xDA200003, 0x8019, 0xDA300003, 0x801A, 0xDA400003, 0x801B, 0xDA500003, 0x801C, 0xDA600003,
274     0x801D, 0xDA700003, 0x801E, 0xDA800003, 0x801F, 0xDA900003, 0x8020, 0xDAA00003, 0x8021, 0xDAB00003,
275     0x8022, 0xDAC00003, 0x8023, 0xDAD00003, 0x8024, 0xDAE00003, 0x8025, 0xDAF00003, 0x8026, 0xDB000003,
276     0x8027, 0xDB100003, 0x8028, 0xDB200003, 0x8029, 0xDB300003, 0x802A, 0xDB400003, 0x802B, 0xDB500003,
277     0x802C, 0xDB600003, 0x802D, 0xDB700003, 0x802E, 0xDB800003, 0x802F, 0xDB900003, 0x80FF, 0xDBA00003,
278     0x0001
279 };
280
281 static void fill_elements(uint32_t idx, uint32_t shift, int size, uint32_t *e0, uint32_t *e1)
282 {
283     uint32_t a = 1, b, g = 1, h = idx << (32 - shift);
284
285     for (int i = 0; i < size; i++) {
286         if (!a || !g)
287             break;
288         b = 4 * (table[2 * i + 1] & 0xF);
289         if (shift >= b && (h & (0xFFF00000u << (12 - b))) == (table[2 * i + 1] & 0xFFFF0000u)) {
290             if (table[2 * i] >> 8 == 0x80u) {
291                 g = 0;
292             } else {
293                 a = 0;
294                 *e1 = table[2 * i];
295                 *e0 = (*e0 & 0xFFFFFFu) | (((12 + b - shift) & 0xFFFFFFFCu | 0x40u) << 22);
296                 shift -= b;
297                 h <<= b;
298             }
299         }
300     }
301     a = 1;
302     for (int i = 0; i < size; i++) {
303         if (!a || !g)
304             break;
305         b = 4 * (table[2 * i + 1] & 0xF);
306         if (shift >= b && (h & (0xFFF00000u << (12 - b))) == (table[2 * i + 1] & 0xFFFF0000u)) {
307             if ((table[2 * i] >> 8) == 0x80u) {
308                 g = 0;
309             } else {
310                 a = 0;
311                 *e1 |= table[2 * i] << 16;
312                 *e0 = (*e0 & 0xFFFFFFu) | (((12 + b - shift) & 0xFFFFFFFCu | 0x80u) << 22);
313             }
314         }
315     }
316 }
317
318 static void fill_lut(uint32_t *lut)
319 {
320     for (int i = 1; i < FF_ARRAY_ELEMS(table); i += 2) {
321         uint32_t a = table[i];
322         uint32_t b = a & 0xFFu;
323         uint32_t c, d, e;
324
325         if (b > 3)
326             continue;
327
328         c = (b << 16) | table[i-1];
329         d = 4 * (3 - b);
330         e = (((0xFFF00000u << d) & a) >> 20) & 0xFFF;
331         if (d <= 0) {
332             lut[2 * e] = c;
333             lut[2 * e + 1] = 0;
334         } else {
335             for (int j = 0; j < 1 << d; j++) {
336                 uint32_t f = 0xFFFFFFFFu;
337                 c &= 0xFFFFFFu;
338                 if ((c & 0xFF00u) != 0x8000u)
339                     fill_elements(j, d, 365, &c, &f);
340                 lut[2 * e + 2 * j] = c;
341                 lut[2 * e + 2 * j + 1] = f;
342             }
343         }
344     }
345
346     for (int i = 0; i < 32; i += 2) {
347         lut[i  ] = 0x68000;
348         lut[i+1] = 0;
349     }
350 }
351
352 static av_cold int decode_init(AVCodecContext *avctx)
353 {
354     ProSumerContext *s = avctx->priv_data;
355
356     s->stride = 3LL * FFALIGN(avctx->width, 8) >> 1;
357     s->size = avctx->height * s->stride;
358
359     avctx->pix_fmt = AV_PIX_FMT_YUV411P;
360
361     s->table_b = av_malloc(s->stride);
362     s->decbuffer = av_malloc(s->size);
363     if (!s->table_b || !s->decbuffer)
364         return AVERROR(ENOMEM);
365     memset(s->table_b, 0x80u, s->stride);
366
367     fill_lut(s->lut);
368
369     return 0;
370 }
371
372 static av_cold int decode_close(AVCodecContext *avctx)
373 {
374     ProSumerContext *s = avctx->priv_data;
375
376     av_freep(&s->table_b);
377     av_freep(&s->decbuffer);
378
379     return 0;
380 }
381
382 AVCodec ff_prosumer_decoder = {
383     .name           = "prosumer",
384     .long_name      = NULL_IF_CONFIG_SMALL("Brooktree ProSumer Video"),
385     .type           = AVMEDIA_TYPE_VIDEO,
386     .id             = AV_CODEC_ID_PROSUMER,
387     .priv_data_size = sizeof(ProSumerContext),
388     .init           = decode_init,
389     .decode         = decode_frame,
390     .close          = decode_close,
391     .capabilities   = AV_CODEC_CAP_DR1,
392     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
393                       FF_CODEC_CAP_INIT_CLEANUP,
394 };