/src/ffmpeg/libavcodec/cinepak.c
Line | Count | Source |
1 | | /* |
2 | | * Cinepak Video Decoder |
3 | | * Copyright (C) 2003 The FFmpeg project |
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 | | * Cinepak video decoder |
25 | | * @author Ewald Snel <ewald@rambo.its.tudelft.nl> |
26 | | * |
27 | | * @see For more information on the Cinepak algorithm, visit: |
28 | | * http://www.csse.monash.edu.au/~timf/ |
29 | | * @see For more information on the quirky data inside Sega FILM/CPK files, visit: |
30 | | * http://wiki.multimedia.cx/index.php?title=Sega_FILM |
31 | | * |
32 | | * Cinepak colorspace support (c) 2013 Rl, Aetey Global Technologies AB |
33 | | * @author Cinepak colorspace, Rl, Aetey Global Technologies AB |
34 | | */ |
35 | | |
36 | | #include <stdio.h> |
37 | | #include <string.h> |
38 | | |
39 | | #include "libavutil/common.h" |
40 | | #include "libavutil/intreadwrite.h" |
41 | | #include "avcodec.h" |
42 | | #include "codec_internal.h" |
43 | | #include "decode.h" |
44 | | |
45 | | |
46 | | typedef uint8_t cvid_codebook[12]; |
47 | | |
48 | | #define MAX_STRIPS 32 |
49 | | |
50 | | typedef struct cvid_strip { |
51 | | uint16_t id; |
52 | | uint16_t x1, y1; |
53 | | uint16_t x2, y2; |
54 | | cvid_codebook v4_codebook[256]; |
55 | | cvid_codebook v1_codebook[256]; |
56 | | } cvid_strip; |
57 | | |
58 | | typedef struct CinepakContext { |
59 | | |
60 | | AVCodecContext *avctx; |
61 | | AVFrame *frame; |
62 | | |
63 | | const unsigned char *data; |
64 | | int size; |
65 | | |
66 | | int width, height; |
67 | | |
68 | | int palette_video; |
69 | | cvid_strip strips[MAX_STRIPS]; |
70 | | |
71 | | int sega_film_skip_bytes; |
72 | | |
73 | | uint32_t pal[256]; |
74 | | } CinepakContext; |
75 | | |
76 | | static void cinepak_decode_codebook (cvid_codebook *codebook, |
77 | | int chunk_id, int size, const uint8_t *data) |
78 | 3.09k | { |
79 | 3.09k | const uint8_t *eod = (data + size); |
80 | 3.09k | uint32_t flag, mask; |
81 | 3.09k | int i, n; |
82 | 3.09k | uint8_t *p; |
83 | | |
84 | | /* check if this chunk contains 4- or 6-element vectors */ |
85 | 3.09k | n = (chunk_id & 0x04) ? 4 : 6; |
86 | 3.09k | flag = 0; |
87 | 3.09k | mask = 0; |
88 | | |
89 | 3.09k | p = codebook[0]; |
90 | 201k | for (i=0; i < 256; i++) { |
91 | 201k | if ((chunk_id & 0x01) && !(mask >>= 1)) { |
92 | 6.97k | if ((data + 4) > eod) |
93 | 870 | break; |
94 | | |
95 | 6.10k | flag = AV_RB32 (data); |
96 | 6.10k | data += 4; |
97 | 6.10k | mask = 0x80000000; |
98 | 6.10k | } |
99 | | |
100 | 200k | if (!(chunk_id & 0x01) || (flag & mask)) { |
101 | 29.4k | int k, kk; |
102 | | |
103 | 29.4k | if ((data + n) > eod) |
104 | 1.77k | break; |
105 | | |
106 | 138k | for (k = 0; k < 4; ++k) { |
107 | 110k | int r = *data++; |
108 | 442k | for (kk = 0; kk < 3; ++kk) |
109 | 331k | *p++ = r; |
110 | 110k | } |
111 | 27.6k | if (n == 6) { |
112 | 14.7k | int r, g, b, u, v; |
113 | 14.7k | u = *(int8_t *)data++; |
114 | 14.7k | v = *(int8_t *)data++; |
115 | 14.7k | p -= 12; |
116 | 73.8k | for(k=0; k<4; ++k) { |
117 | 59.0k | r = *p++ + v*2; |
118 | 59.0k | g = *p++ - (u/2) - v; |
119 | 59.0k | b = *p + u*2; |
120 | 59.0k | p -= 2; |
121 | 59.0k | *p++ = av_clip_uint8(r); |
122 | 59.0k | *p++ = av_clip_uint8(g); |
123 | 59.0k | *p++ = av_clip_uint8(b); |
124 | 59.0k | } |
125 | 14.7k | } |
126 | 170k | } else { |
127 | 170k | p += 12; |
128 | 170k | } |
129 | 200k | } |
130 | 3.09k | } |
131 | | |
132 | | static int cinepak_decode_vectors (CinepakContext *s, cvid_strip *strip, |
133 | | int chunk_id, int size, const uint8_t *data) |
134 | 4.92k | { |
135 | 4.92k | const uint8_t *eod = (data + size); |
136 | 4.92k | uint32_t flag, mask; |
137 | 4.92k | uint8_t *cb0, *cb1, *cb2, *cb3; |
138 | 4.92k | int x, y; |
139 | 4.92k | char *ip0, *ip1, *ip2, *ip3; |
140 | | |
141 | 4.92k | flag = 0; |
142 | 4.92k | mask = 0; |
143 | | |
144 | 12.2k | for (y=strip->y1; y < strip->y2; y+=4) { |
145 | | |
146 | | /* take care of y dimension not being multiple of 4, such streams exist */ |
147 | 10.1k | ip0 = ip1 = ip2 = ip3 = s->frame->data[0] + |
148 | 10.1k | (s->palette_video?strip->x1:strip->x1*3) + (y * s->frame->linesize[0]); |
149 | 10.1k | if(s->avctx->height - y > 1) { |
150 | 8.93k | ip1 = ip0 + s->frame->linesize[0]; |
151 | 8.93k | if(s->avctx->height - y > 2) { |
152 | 8.70k | ip2 = ip1 + s->frame->linesize[0]; |
153 | 8.70k | if(s->avctx->height - y > 3) { |
154 | 7.25k | ip3 = ip2 + s->frame->linesize[0]; |
155 | 7.25k | } |
156 | 8.70k | } |
157 | 8.93k | } |
158 | | /* to get the correct picture for not-multiple-of-4 cases let us fill each |
159 | | * block from the bottom up, thus possibly overwriting the bottommost line |
160 | | * more than once but ending with the correct data in place |
161 | | * (instead of in-loop checking) */ |
162 | | |
163 | 113k | for (x=strip->x1; x < strip->x2; x+=4) { |
164 | 106k | if ((chunk_id & 0x01) && !(mask >>= 1)) { |
165 | 1.74k | if ((data + 4) > eod) |
166 | 776 | return AVERROR_INVALIDDATA; |
167 | | |
168 | 970 | flag = AV_RB32 (data); |
169 | 970 | data += 4; |
170 | 970 | mask = 0x80000000; |
171 | 970 | } |
172 | | |
173 | 105k | if (!(chunk_id & 0x01) || (flag & mask)) { |
174 | 86.5k | if (!(chunk_id & 0x02) && !(mask >>= 1)) { |
175 | 3.86k | if ((data + 4) > eod) |
176 | 498 | return AVERROR_INVALIDDATA; |
177 | | |
178 | 3.36k | flag = AV_RB32 (data); |
179 | 3.36k | data += 4; |
180 | 3.36k | mask = 0x80000000; |
181 | 3.36k | } |
182 | | |
183 | 86.0k | if ((chunk_id & 0x02) || (~flag & mask)) { |
184 | 67.9k | uint8_t *p; |
185 | 67.9k | if (data >= eod) |
186 | 661 | return AVERROR_INVALIDDATA; |
187 | | |
188 | 67.3k | p = strip->v1_codebook[*data++]; |
189 | 67.3k | if (s->palette_video) { |
190 | 8.04k | ip3[0] = ip3[1] = ip2[0] = ip2[1] = p[6]; |
191 | 8.04k | ip3[2] = ip3[3] = ip2[2] = ip2[3] = p[9]; |
192 | 8.04k | ip1[0] = ip1[1] = ip0[0] = ip0[1] = p[0]; |
193 | 8.04k | ip1[2] = ip1[3] = ip0[2] = ip0[3] = p[3]; |
194 | 59.2k | } else { |
195 | 59.2k | p += 6; |
196 | 59.2k | memcpy(ip3 + 0, p, 3); memcpy(ip3 + 3, p, 3); |
197 | 59.2k | memcpy(ip2 + 0, p, 3); memcpy(ip2 + 3, p, 3); |
198 | 59.2k | p += 3; /* ... + 9 */ |
199 | 59.2k | memcpy(ip3 + 6, p, 3); memcpy(ip3 + 9, p, 3); |
200 | 59.2k | memcpy(ip2 + 6, p, 3); memcpy(ip2 + 9, p, 3); |
201 | 59.2k | p -= 9; /* ... + 0 */ |
202 | 59.2k | memcpy(ip1 + 0, p, 3); memcpy(ip1 + 3, p, 3); |
203 | 59.2k | memcpy(ip0 + 0, p, 3); memcpy(ip0 + 3, p, 3); |
204 | 59.2k | p += 3; /* ... + 3 */ |
205 | 59.2k | memcpy(ip1 + 6, p, 3); memcpy(ip1 + 9, p, 3); |
206 | 59.2k | memcpy(ip0 + 6, p, 3); memcpy(ip0 + 9, p, 3); |
207 | 59.2k | } |
208 | | |
209 | 67.3k | } else if (flag & mask) { |
210 | 18.0k | if ((data + 4) > eod) |
211 | 898 | return AVERROR_INVALIDDATA; |
212 | | |
213 | 17.1k | cb0 = strip->v4_codebook[*data++]; |
214 | 17.1k | cb1 = strip->v4_codebook[*data++]; |
215 | 17.1k | cb2 = strip->v4_codebook[*data++]; |
216 | 17.1k | cb3 = strip->v4_codebook[*data++]; |
217 | 17.1k | if (s->palette_video) { |
218 | 3.32k | uint8_t *p; |
219 | 3.32k | p = ip3; |
220 | 3.32k | *p++ = cb2[6]; |
221 | 3.32k | *p++ = cb2[9]; |
222 | 3.32k | *p++ = cb3[6]; |
223 | 3.32k | *p = cb3[9]; |
224 | 3.32k | p = ip2; |
225 | 3.32k | *p++ = cb2[0]; |
226 | 3.32k | *p++ = cb2[3]; |
227 | 3.32k | *p++ = cb3[0]; |
228 | 3.32k | *p = cb3[3]; |
229 | 3.32k | p = ip1; |
230 | 3.32k | *p++ = cb0[6]; |
231 | 3.32k | *p++ = cb0[9]; |
232 | 3.32k | *p++ = cb1[6]; |
233 | 3.32k | *p = cb1[9]; |
234 | 3.32k | p = ip0; |
235 | 3.32k | *p++ = cb0[0]; |
236 | 3.32k | *p++ = cb0[3]; |
237 | 3.32k | *p++ = cb1[0]; |
238 | 3.32k | *p = cb1[3]; |
239 | 13.8k | } else { |
240 | 13.8k | memcpy(ip3 + 0, cb2 + 6, 6); |
241 | 13.8k | memcpy(ip3 + 6, cb3 + 6, 6); |
242 | 13.8k | memcpy(ip2 + 0, cb2 + 0, 6); |
243 | 13.8k | memcpy(ip2 + 6, cb3 + 0, 6); |
244 | 13.8k | memcpy(ip1 + 0, cb0 + 6, 6); |
245 | 13.8k | memcpy(ip1 + 6, cb1 + 6, 6); |
246 | 13.8k | memcpy(ip0 + 0, cb0 + 0, 6); |
247 | 13.8k | memcpy(ip0 + 6, cb1 + 0, 6); |
248 | 13.8k | } |
249 | | |
250 | 17.1k | } |
251 | 86.0k | } |
252 | | |
253 | 103k | if (s->palette_video) { |
254 | 12.1k | ip0 += 4; ip1 += 4; |
255 | 12.1k | ip2 += 4; ip3 += 4; |
256 | 91.2k | } else { |
257 | 91.2k | ip0 += 12; ip1 += 12; |
258 | 91.2k | ip2 += 12; ip3 += 12; |
259 | 91.2k | } |
260 | 103k | } |
261 | 10.1k | } |
262 | | |
263 | 2.09k | return 0; |
264 | 4.92k | } |
265 | | |
266 | | static int cinepak_decode_strip (CinepakContext *s, |
267 | | cvid_strip *strip, const uint8_t *data, int size) |
268 | 16.2k | { |
269 | 16.2k | const uint8_t *eod = (data + size); |
270 | 16.2k | int chunk_id, chunk_size; |
271 | | |
272 | | /* coordinate sanity checks */ |
273 | 16.2k | if (strip->x2 > s->width || |
274 | 14.9k | strip->y2 > s->height || |
275 | 8.91k | strip->x1 >= strip->x2 || strip->y1 >= strip->y2) |
276 | 8.17k | return AVERROR_INVALIDDATA; |
277 | | |
278 | 11.6k | while ((data + 4) <= eod) { |
279 | 8.89k | chunk_id = data[0]; |
280 | 8.89k | chunk_size = AV_RB24 (&data[1]) - 4; |
281 | 8.89k | if(chunk_size < 0) |
282 | 340 | return AVERROR_INVALIDDATA; |
283 | | |
284 | 8.55k | data += 4; |
285 | 8.55k | chunk_size = ((data + chunk_size) > eod) ? (eod - data) : chunk_size; |
286 | | |
287 | 8.55k | switch (chunk_id) { |
288 | | |
289 | 214 | case 0x20: |
290 | 564 | case 0x21: |
291 | 858 | case 0x24: |
292 | 1.13k | case 0x25: |
293 | 1.13k | cinepak_decode_codebook (strip->v4_codebook, chunk_id, |
294 | 1.13k | chunk_size, data); |
295 | 1.13k | break; |
296 | | |
297 | 232 | case 0x22: |
298 | 655 | case 0x23: |
299 | 854 | case 0x26: |
300 | 1.96k | case 0x27: |
301 | 1.96k | cinepak_decode_codebook (strip->v1_codebook, chunk_id, |
302 | 1.96k | chunk_size, data); |
303 | 1.96k | break; |
304 | | |
305 | 2.62k | case 0x30: |
306 | 3.73k | case 0x31: |
307 | 4.92k | case 0x32: |
308 | 4.92k | return cinepak_decode_vectors (s, strip, chunk_id, |
309 | 4.92k | chunk_size, data); |
310 | 8.55k | } |
311 | | |
312 | 3.63k | data += chunk_size; |
313 | 3.63k | } |
314 | | |
315 | 2.78k | return AVERROR_INVALIDDATA; |
316 | 8.04k | } |
317 | | |
318 | | static int cinepak_predecode_check (CinepakContext *s) |
319 | 24.3k | { |
320 | 24.3k | int num_strips; |
321 | 24.3k | int encoded_buf_size; |
322 | | |
323 | 24.3k | num_strips = AV_RB16 (&s->data[8]); |
324 | 24.3k | encoded_buf_size = AV_RB24(&s->data[1]); |
325 | | |
326 | 24.3k | if (s->size < encoded_buf_size * (int64_t)(100 - s->avctx->discard_damaged_percentage) / 100) |
327 | 4.49k | return AVERROR_INVALIDDATA; |
328 | | |
329 | | /* if this is the first frame, check for deviant Sega FILM data */ |
330 | 19.8k | if (s->sega_film_skip_bytes == -1) { |
331 | 1.15k | if (!encoded_buf_size) { |
332 | 347 | avpriv_request_sample(s->avctx, "encoded_buf_size 0"); |
333 | 347 | return AVERROR_PATCHWELCOME; |
334 | 347 | } |
335 | 803 | if (encoded_buf_size != s->size && (s->size % encoded_buf_size) != 0) { |
336 | | /* If the encoded frame size differs from the frame size as indicated |
337 | | * by the container file, this data likely comes from a Sega FILM/CPK file. |
338 | | * If the frame header is followed by the bytes FE 00 00 06 00 00 then |
339 | | * this is probably one of the two known files that have 6 extra bytes |
340 | | * after the frame header. Else, assume 2 extra bytes. The container |
341 | | * size also cannot be a multiple of the encoded size. */ |
342 | 695 | if (s->size >= 16 && |
343 | 652 | (s->data[10] == 0xFE) && |
344 | 76 | (s->data[11] == 0x00) && |
345 | 51 | (s->data[12] == 0x00) && |
346 | 43 | (s->data[13] == 0x06) && |
347 | 21 | (s->data[14] == 0x00) && |
348 | 13 | (s->data[15] == 0x00)) |
349 | 4 | s->sega_film_skip_bytes = 6; |
350 | 691 | else |
351 | 691 | s->sega_film_skip_bytes = 2; |
352 | 695 | } else |
353 | 108 | s->sega_film_skip_bytes = 0; |
354 | 803 | } |
355 | | |
356 | 19.5k | if (s->size < 10 + s->sega_film_skip_bytes + num_strips * 12) |
357 | 1.97k | return AVERROR_INVALIDDATA; |
358 | | |
359 | 17.5k | if (num_strips) { |
360 | 17.5k | const uint8_t *data = s->data + 10 + s->sega_film_skip_bytes; |
361 | 17.5k | int strip_size = AV_RB24 (data + 1); |
362 | 17.5k | if (strip_size < 12 || strip_size > encoded_buf_size) |
363 | 1.28k | return AVERROR_INVALIDDATA; |
364 | 17.5k | } |
365 | | |
366 | 16.2k | return 0; |
367 | 17.5k | } |
368 | | |
369 | | static int cinepak_decode (CinepakContext *s) |
370 | 15.5k | { |
371 | 15.5k | const uint8_t *eod = (s->data + s->size); |
372 | 15.5k | int i, result, strip_size, frame_flags, num_strips; |
373 | 15.5k | int y0 = 0; |
374 | | |
375 | 15.5k | frame_flags = s->data[0]; |
376 | 15.5k | num_strips = AV_RB16 (&s->data[8]); |
377 | | |
378 | 15.5k | s->data += 10 + s->sega_film_skip_bytes; |
379 | | |
380 | 15.5k | num_strips = FFMIN(num_strips, MAX_STRIPS); |
381 | | |
382 | 15.5k | s->frame->flags &= ~AV_FRAME_FLAG_KEY; |
383 | | |
384 | 17.6k | for (i=0; i < num_strips; i++) { |
385 | 16.8k | if ((s->data + 12) > eod) |
386 | 439 | return AVERROR_INVALIDDATA; |
387 | | |
388 | 16.4k | s->strips[i].id = s->data[0]; |
389 | | /* zero y1 means "relative to the previous stripe" */ |
390 | 16.4k | if (!(s->strips[i].y1 = AV_RB16 (&s->data[4]))) |
391 | 6.79k | s->strips[i].y2 = (s->strips[i].y1 = y0) + AV_RB16 (&s->data[8]); |
392 | 9.62k | else |
393 | 9.62k | s->strips[i].y2 = AV_RB16 (&s->data[8]); |
394 | 16.4k | s->strips[i].x1 = AV_RB16 (&s->data[6]); |
395 | 16.4k | s->strips[i].x2 = AV_RB16 (&s->data[10]); |
396 | | |
397 | 16.4k | if (s->strips[i].id == 0x10) |
398 | 203 | s->frame->flags |= AV_FRAME_FLAG_KEY; |
399 | | |
400 | 16.4k | strip_size = AV_RB24 (&s->data[1]) - 12; |
401 | 16.4k | if (strip_size < 0) |
402 | 205 | return AVERROR_INVALIDDATA; |
403 | 16.2k | s->data += 12; |
404 | 16.2k | strip_size = ((s->data + strip_size) > eod) ? (eod - s->data) : strip_size; |
405 | | |
406 | 16.2k | if ((i > 0) && !(frame_flags & 0x01)) { |
407 | 434 | memcpy (s->strips[i].v4_codebook, s->strips[i-1].v4_codebook, |
408 | 434 | sizeof(s->strips[i].v4_codebook)); |
409 | 434 | memcpy (s->strips[i].v1_codebook, s->strips[i-1].v1_codebook, |
410 | 434 | sizeof(s->strips[i].v1_codebook)); |
411 | 434 | } |
412 | | |
413 | 16.2k | result = cinepak_decode_strip (s, &s->strips[i], s->data, strip_size); |
414 | | |
415 | 16.2k | if (result != 0) |
416 | 14.1k | return result; |
417 | | |
418 | 2.09k | s->data += strip_size; |
419 | 2.09k | y0 = s->strips[i].y2; |
420 | 2.09k | } |
421 | 803 | return 0; |
422 | 15.5k | } |
423 | | |
424 | | static av_cold int cinepak_decode_init(AVCodecContext *avctx) |
425 | 1.33k | { |
426 | 1.33k | CinepakContext *s = avctx->priv_data; |
427 | | |
428 | 1.33k | s->avctx = avctx; |
429 | 1.33k | s->width = (avctx->width + 3) & ~3; |
430 | 1.33k | s->height = (avctx->height + 3) & ~3; |
431 | | |
432 | 1.33k | s->sega_film_skip_bytes = -1; /* uninitialized state */ |
433 | | |
434 | | // check for paletted data |
435 | 1.33k | if (avctx->bits_per_coded_sample != 8) { |
436 | 1.28k | s->palette_video = 0; |
437 | 1.28k | avctx->pix_fmt = AV_PIX_FMT_RGB24; |
438 | 1.28k | } else { |
439 | 52 | s->palette_video = 1; |
440 | 52 | avctx->pix_fmt = AV_PIX_FMT_PAL8; |
441 | 52 | } |
442 | | |
443 | 1.33k | s->frame = av_frame_alloc(); |
444 | 1.33k | if (!s->frame) |
445 | 0 | return AVERROR(ENOMEM); |
446 | | |
447 | 1.33k | return 0; |
448 | 1.33k | } |
449 | | |
450 | | static int cinepak_decode_frame(AVCodecContext *avctx, AVFrame *rframe, |
451 | | int *got_frame, AVPacket *avpkt) |
452 | 118k | { |
453 | 118k | const uint8_t *buf = avpkt->data; |
454 | 118k | int ret = 0, buf_size = avpkt->size; |
455 | 118k | CinepakContext *s = avctx->priv_data; |
456 | 118k | int num_strips; |
457 | | |
458 | 118k | s->data = buf; |
459 | 118k | s->size = buf_size; |
460 | | |
461 | 118k | if (s->size < 10) |
462 | 9.47k | return AVERROR_INVALIDDATA; |
463 | | |
464 | 108k | num_strips = AV_RB16 (&s->data[8]); |
465 | | |
466 | | //Empty frame, do not waste time |
467 | 108k | if (!num_strips && (!s->palette_video || !av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL))) |
468 | 84.4k | return buf_size; |
469 | | |
470 | 24.3k | if ((ret = cinepak_predecode_check(s)) < 0) { |
471 | 8.09k | av_log(avctx, AV_LOG_ERROR, "cinepak_predecode_check failed\n"); |
472 | 8.09k | return ret; |
473 | 8.09k | } |
474 | | |
475 | 16.2k | if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) |
476 | 704 | return ret; |
477 | | |
478 | 15.5k | if (s->palette_video) { |
479 | 1.86k | ff_copy_palette(s->pal, avpkt, avctx); |
480 | 1.86k | } |
481 | | |
482 | 15.5k | if ((ret = cinepak_decode(s)) < 0) { |
483 | 14.7k | av_log(avctx, AV_LOG_ERROR, "cinepak_decode failed\n"); |
484 | 14.7k | } |
485 | | |
486 | 15.5k | if (s->palette_video) |
487 | 1.86k | memcpy (s->frame->data[1], s->pal, AVPALETTE_SIZE); |
488 | | |
489 | 15.5k | if ((ret = av_frame_ref(rframe, s->frame)) < 0) |
490 | 0 | return ret; |
491 | | |
492 | 15.5k | *got_frame = 1; |
493 | | |
494 | | /* report that the buffer was completely consumed */ |
495 | 15.5k | return buf_size; |
496 | 15.5k | } |
497 | | |
498 | | static av_cold int cinepak_decode_end(AVCodecContext *avctx) |
499 | 1.33k | { |
500 | 1.33k | CinepakContext *s = avctx->priv_data; |
501 | | |
502 | 1.33k | av_frame_free(&s->frame); |
503 | | |
504 | 1.33k | return 0; |
505 | 1.33k | } |
506 | | |
507 | | const FFCodec ff_cinepak_decoder = { |
508 | | .p.name = "cinepak", |
509 | | CODEC_LONG_NAME("Cinepak"), |
510 | | .p.type = AVMEDIA_TYPE_VIDEO, |
511 | | .p.id = AV_CODEC_ID_CINEPAK, |
512 | | .priv_data_size = sizeof(CinepakContext), |
513 | | .init = cinepak_decode_init, |
514 | | .close = cinepak_decode_end, |
515 | | FF_CODEC_DECODE_CB(cinepak_decode_frame), |
516 | | .p.capabilities = AV_CODEC_CAP_DR1, |
517 | | }; |