2 * Packed Animation File video decoder
3 * Copyright (c) 2012 Paul B Mahol
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/imgutils.h"
23 #include "libavutil/mem.h"
26 #include "bytestream.h"
27 #include "copy_block.h"
28 #include "codec_internal.h"
32 static const uint8_t block_sequences
[16][8] = {
33 { 0, 0, 0, 0, 0, 0, 0, 0 },
34 { 2, 0, 0, 0, 0, 0, 0, 0 },
35 { 5, 7, 0, 0, 0, 0, 0, 0 },
36 { 5, 0, 0, 0, 0, 0, 0, 0 },
37 { 6, 0, 0, 0, 0, 0, 0, 0 },
38 { 5, 7, 5, 7, 0, 0, 0, 0 },
39 { 5, 7, 5, 0, 0, 0, 0, 0 },
40 { 5, 7, 6, 0, 0, 0, 0, 0 },
41 { 5, 5, 0, 0, 0, 0, 0, 0 },
42 { 3, 0, 0, 0, 0, 0, 0, 0 },
43 { 6, 6, 0, 0, 0, 0, 0, 0 },
44 { 2, 4, 0, 0, 0, 0, 0, 0 },
45 { 2, 4, 5, 7, 0, 0, 0, 0 },
46 { 2, 4, 5, 0, 0, 0, 0, 0 },
47 { 2, 4, 6, 0, 0, 0, 0, 0 },
48 { 2, 4, 5, 7, 5, 7, 0, 0 },
51 typedef struct PAFVideoDecContext
{
67 static av_cold
int paf_video_close(AVCodecContext
*avctx
)
69 PAFVideoDecContext
*c
= avctx
->priv_data
;
72 av_frame_free(&c
->pic
);
74 for (i
= 0; i
< 4; i
++)
75 av_freep(&c
->frame
[i
]);
80 static av_cold
int paf_video_init(AVCodecContext
*avctx
)
82 PAFVideoDecContext
*c
= avctx
->priv_data
;
86 c
->width
= avctx
->width
;
87 c
->height
= avctx
->height
;
89 if (avctx
->height
& 3 || avctx
->width
& 3) {
90 av_log(avctx
, AV_LOG_ERROR
,
91 "width %d and height %d must be multiplie of 4.\n",
92 avctx
->width
, avctx
->height
);
93 return AVERROR_INVALIDDATA
;
96 avctx
->pix_fmt
= AV_PIX_FMT_PAL8
;
97 ret
= av_image_check_size2(avctx
->width
, FFALIGN(avctx
->height
, 256), avctx
->max_pixels
, avctx
->pix_fmt
, 0, avctx
);
101 c
->pic
= av_frame_alloc();
103 return AVERROR(ENOMEM
);
105 c
->frame_size
= avctx
->width
* FFALIGN(avctx
->height
, 256);
106 c
->video_size
= avctx
->width
* avctx
->height
;
107 for (i
= 0; i
< 4; i
++) {
108 c
->frame
[i
] = av_mallocz(c
->frame_size
);
110 return AVERROR(ENOMEM
);
116 static void read4x4block(PAFVideoDecContext
*c
, uint8_t *dst
, int width
)
120 for (i
= 0; i
< 4; i
++) {
121 bytestream2_get_buffer(&c
->gb
, dst
, 4);
126 static void copy_color_mask(uint8_t *dst
, int width
, uint8_t mask
, uint8_t color
)
130 for (i
= 0; i
< 4; i
++) {
131 if (mask
& (1 << 7 - i
))
133 if (mask
& (1 << 3 - i
))
134 dst
[width
+ i
] = color
;
138 static void copy_src_mask(uint8_t *dst
, int width
, uint8_t mask
, const uint8_t *src
)
142 for (i
= 0; i
< 4; i
++) {
143 if (mask
& (1 << 7 - i
))
145 if (mask
& (1 << 3 - i
))
146 dst
[width
+ i
] = src
[width
+ i
];
150 static void set_src_position(PAFVideoDecContext
*c
,
152 const uint8_t **pend
)
154 int val
= bytestream2_get_be16(&c
->gb
);
155 int page
= val
>> 14;
156 int x
= (val
& 0x7F);
157 int y
= ((val
>> 7) & 0x7F);
159 *p
= c
->frame
[page
] + x
* 2 + y
* 2 * c
->width
;
160 *pend
= c
->frame
[page
] + c
->frame_size
;
163 static int decode_0(PAFVideoDecContext
*c
, const uint8_t *pkt
, uint8_t code
)
165 uint32_t opcode_size
, offset
;
166 uint8_t *dst
, *dend
, mask
= 0, color
= 0;
167 const uint8_t *src
, *send
, *opcodes
;
170 i
= bytestream2_get_byte(&c
->gb
);
175 align
= bytestream2_tell(&c
->gb
) & 3;
177 bytestream2_skip(&c
->gb
, 4 - align
);
181 val
= bytestream2_get_be16(&c
->gb
);
183 x
= (val
& 0x7F) * 2;
184 y
= ((val
>> 7) & 0x7F) * 2;
185 dst
= c
->frame
[page
] + x
+ y
* c
->width
;
186 dend
= c
->frame
[page
] + c
->frame_size
;
187 offset
= (x
& 0x7F) * 2;
188 j
= bytestream2_get_le16(&c
->gb
) + offset
;
189 if (bytestream2_get_bytes_left(&c
->gb
) < (j
- offset
) * 16)
190 return AVERROR_INVALIDDATA
;
194 if (dst
+ 3 * c
->width
+ 4 > dend
)
195 return AVERROR_INVALIDDATA
;
196 read4x4block(c
, dst
, c
->width
);
197 if ((offset
& 0x3F) == 0)
200 } while (offset
< j
);
204 dst
= c
->frame
[c
->current_frame
];
205 dend
= c
->frame
[c
->current_frame
] + c
->frame_size
;
207 set_src_position(c
, &src
, &send
);
208 if ((src
+ 3 * c
->width
+ 4 > send
) ||
209 (dst
+ 3 * c
->width
+ 4 > dend
) ||
210 bytestream2_get_bytes_left(&c
->gb
) < 4)
211 return AVERROR_INVALIDDATA
;
212 copy_block4(dst
, src
, c
->width
, c
->width
, 4);
217 } while (i
< c
->video_size
/ 16);
219 opcode_size
= bytestream2_get_le16(&c
->gb
);
220 bytestream2_skip(&c
->gb
, 2);
222 if (bytestream2_get_bytes_left(&c
->gb
) < opcode_size
)
223 return AVERROR_INVALIDDATA
;
225 opcodes
= pkt
+ bytestream2_tell(&c
->gb
);
226 bytestream2_skipu(&c
->gb
, opcode_size
);
228 dst
= c
->frame
[c
->current_frame
];
230 for (i
= 0; i
< c
->height
; i
+= 4, dst
+= c
->width
* 3)
231 for (j
= 0; j
< c
->width
; j
+= 4, dst
+= 4) {
233 if (op
> opcode_size
)
234 return AVERROR_INVALIDDATA
;
236 opcode
= opcodes
[op
] & 15;
239 opcode
= opcodes
[op
] >> 4;
242 while (block_sequences
[opcode
][k
]) {
243 offset
= c
->width
* 2;
244 code
= block_sequences
[opcode
][k
++];
250 color
= bytestream2_get_byte(&c
->gb
);
252 mask
= bytestream2_get_byte(&c
->gb
);
253 copy_color_mask(dst
+ offset
, c
->width
, mask
, color
);
258 set_src_position(c
, &src
, &send
);
260 if (src
+ offset
+ c
->width
+ 4 > send
)
261 return AVERROR_INVALIDDATA
;
262 mask
= bytestream2_get_byte(&c
->gb
);
263 copy_src_mask(dst
+ offset
, c
->width
, mask
, src
+ offset
);
272 static int paf_video_decode(AVCodecContext
*avctx
, AVFrame
*rframe
,
273 int *got_frame
, AVPacket
*pkt
)
275 PAFVideoDecContext
*c
= avctx
->priv_data
;
276 uint8_t code
, *dst
, *end
;
280 return AVERROR_INVALIDDATA
;
282 bytestream2_init(&c
->gb
, pkt
->data
, pkt
->size
);
284 code
= bytestream2_get_byte(&c
->gb
);
285 if ((code
& 0xF) > 4 || (code
& 0xF) == 3) {
286 avpriv_request_sample(avctx
, "unknown/invalid code");
287 return AVERROR_INVALIDDATA
;
290 if ((code
& 0xF) == 0 &&
291 c
->video_size
/ 32 - (int64_t)bytestream2_get_bytes_left(&c
->gb
) > c
->video_size
/ 32 * (int64_t)avctx
->discard_damaged_percentage
/ 100)
292 return AVERROR_INVALIDDATA
;
294 if ((ret
= ff_reget_buffer(avctx
, c
->pic
, 0)) < 0)
297 if (code
& 0x20) { // frame is keyframe
298 memset(c
->pic
->data
[1], 0, AVPALETTE_SIZE
);
299 c
->current_frame
= 0;
300 c
->pic
->flags
|= AV_FRAME_FLAG_KEY
;
301 c
->pic
->pict_type
= AV_PICTURE_TYPE_I
;
303 c
->pic
->flags
&= ~AV_FRAME_FLAG_KEY
;
304 c
->pic
->pict_type
= AV_PICTURE_TYPE_P
;
307 if (code
& 0x40) { // palette update
308 uint32_t *out
= (uint32_t *)c
->pic
->data
[1];
311 index
= bytestream2_get_byte(&c
->gb
);
312 count
= bytestream2_get_byte(&c
->gb
) + 1;
314 if (index
+ count
> 256)
315 return AVERROR_INVALIDDATA
;
316 if (bytestream2_get_bytes_left(&c
->gb
) < 3 * count
)
317 return AVERROR_INVALIDDATA
;
320 for (i
= 0; i
< count
; i
++) {
323 r
= bytestream2_get_byteu(&c
->gb
);
325 g
= bytestream2_get_byteu(&c
->gb
);
327 b
= bytestream2_get_byteu(&c
->gb
);
329 *out
++ = (0xFFU
<< 24) | (r
<< 16) | (g
<< 8) | b
;
331 #if FF_API_PALETTE_HAS_CHANGED
332 FF_DISABLE_DEPRECATION_WARNINGS
333 c
->pic
->palette_has_changed
= 1;
334 FF_ENABLE_DEPRECATION_WARNINGS
338 c
->dirty
[c
->current_frame
] = 1;
340 for (i
= 0; i
< 4; i
++) {
342 memset(c
->frame
[i
], 0, c
->frame_size
);
346 switch (code
& 0x0F) {
348 /* Block-based motion compensation using 4x4 blocks with either
349 * horizontal or vertical vectors; might incorporate VQ as well. */
350 if ((ret
= decode_0(c
, pkt
->data
, code
)) < 0)
354 /* Uncompressed data. This mode specifies that (width * height) bytes
355 * should be copied directly from the encoded buffer into the output. */
356 dst
= c
->frame
[c
->current_frame
];
357 // possibly chunk length data
358 bytestream2_skip(&c
->gb
, 2);
359 if (bytestream2_get_bytes_left(&c
->gb
) < c
->video_size
)
360 return AVERROR_INVALIDDATA
;
361 bytestream2_get_bufferu(&c
->gb
, dst
, c
->video_size
);
364 /* Copy reference frame: Consume the next byte in the stream as the
365 * reference frame (which should be 0, 1, 2, or 3, and should not be
366 * the same as the current frame number). */
367 frame
= bytestream2_get_byte(&c
->gb
);
369 return AVERROR_INVALIDDATA
;
370 if (frame
!= c
->current_frame
)
371 memcpy(c
->frame
[c
->current_frame
], c
->frame
[frame
], c
->frame_size
);
374 /* Run length encoding.*/
375 dst
= c
->frame
[c
->current_frame
];
376 end
= dst
+ c
->video_size
;
378 bytestream2_skip(&c
->gb
, 2);
384 if (bytestream2_get_bytes_left(&c
->gb
) < 2)
385 return AVERROR_INVALIDDATA
;
387 code
= bytestream2_get_byteu(&c
->gb
);
388 count
= FFABS(code
) + 1;
390 if (dst
+ count
> end
)
391 return AVERROR_INVALIDDATA
;
393 memset(dst
, bytestream2_get_byteu(&c
->gb
), count
);
395 bytestream2_get_buffer(&c
->gb
, dst
, count
);
403 av_image_copy_plane(c
->pic
->data
[0], c
->pic
->linesize
[0],
404 c
->frame
[c
->current_frame
], c
->width
,
405 c
->width
, c
->height
);
407 c
->current_frame
= (c
->current_frame
+ 1) & 3;
408 if ((ret
= av_frame_ref(rframe
, c
->pic
)) < 0)
416 const FFCodec ff_paf_video_decoder
= {
417 .p
.name
= "paf_video",
418 CODEC_LONG_NAME("Amazing Studio Packed Animation File Video"),
419 .p
.type
= AVMEDIA_TYPE_VIDEO
,
420 .p
.id
= AV_CODEC_ID_PAF_VIDEO
,
421 .priv_data_size
= sizeof(PAFVideoDecContext
),
422 .init
= paf_video_init
,
423 .close
= paf_video_close
,
424 FF_CODEC_DECODE_CB(paf_video_decode
),
425 .p
.capabilities
= AV_CODEC_CAP_DR1
,
426 .caps_internal
= FF_CODEC_CAP_INIT_CLEANUP
,