47#define VMD_HEADER_SIZE 0x330
48#define PALETTE_COUNT 256
55 const unsigned char *
buf;
65#define QUEUE_SIZE 0x1000
66#define QUEUE_MASK 0x0FFF
69 unsigned char *dest,
int dest_len)
75 unsigned int dataleft;
76 unsigned int chainofs;
77 unsigned int chainlen;
86 dataleft = bytestream2_get_le32(&gb);
90 if (bytestream2_peek_le32(&gb) == 0x56781234) {
100 tag = bytestream2_get_byteu(&gb);
101 if ((
tag == 0xFF) && (dataleft > 8)) {
104 for (
i = 0;
i < 8;
i++) {
105 queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
110 for (
i = 0;
i < 8;
i++) {
116 queue[qpos++] = *d++ = bytestream2_get_byteu(&gb);
120 chainofs = bytestream2_get_byte(&gb);
121 chainofs |= ((bytestream2_peek_byte(&gb) & 0xF0) << 4);
122 chainlen = (bytestream2_get_byte(&gb) & 0x0F) + 3;
123 if (chainlen == speclen) {
124 chainlen = bytestream2_get_byte(&gb) + 0xF + 3;
126 if (d_end - d < chainlen)
128 for (j = 0; j < chainlen; j++) {
130 queue[qpos++] = *d++;
133 dataleft -= chainlen;
142 int src_count,
int src_size,
int dest_len)
146 unsigned char *dest_end = dest + dest_len;
155 *pd++ = bytestream2_get_byteu(&gb);
162 l = bytestream2_get_byteu(&gb);
173 for (
i = 0;
i < l;
i++) {
180 }
while (used < src_count);
188 unsigned int *palette32;
189 unsigned char r,
g,
b;
199 int frame_x, frame_y, prev_linesize;
200 int frame_width, frame_height;
204 frame_width =
AV_RL16(&
s->buf[10]) - frame_x + 1;
205 frame_height =
AV_RL16(&
s->buf[12]) - frame_y + 1;
207 if ((frame_width ==
s->avctx->width && frame_height ==
s->avctx->height) &&
208 (frame_x || frame_y)) {
216 if (frame_x < 0 || frame_width < 0 ||
217 frame_x >=
s->avctx->width ||
218 frame_width >
s->avctx->width ||
219 frame_x + frame_width >
s->avctx->width) {
221 "Invalid horizontal range %d-%d\n",
222 frame_x, frame_width);
225 if (frame_y < 0 || frame_height < 0 ||
226 frame_y >=
s->avctx->height ||
227 frame_height >
s->avctx->height ||
228 frame_y + frame_height >
s->avctx->height) {
230 "Invalid vertical range %d-%d\n",
231 frame_y, frame_height);
237 if (
s->prev_frame->data[0] &&
238 (frame_x || frame_y || (frame_width !=
s->avctx->width) ||
239 (frame_height !=
s->avctx->height))) {
241 memcpy(
frame->data[0],
s->prev_frame->data[0],
242 s->avctx->height *
frame->linesize[0]);
247 if (
s->buf[15] & 0x02) {
249 palette32 = (
unsigned int *)
s->palette;
252 r = bytestream2_get_byteu(&gb) * 4;
253 g = bytestream2_get_byteu(&gb) * 4;
254 b = bytestream2_get_byteu(&gb) * 4;
255 palette32[
i] = 0xFFU << 24 | (
r << 16) | (
g << 8) | (
b);
256 palette32[
i] |= palette32[
i] >> 6 & 0x30303;
270 meth = bytestream2_get_byteu(&gb);
273 if (!
s->unpack_buffer_size) {
275 "Trying to unpack LZ-compressed frame with no LZ buffer\n");
279 s->unpack_buffer,
s->unpack_buffer_size);
286 dp = &
frame->data[0][frame_y *
frame->linesize[0] + frame_x];
287 if (
s->prev_frame->data[0]) {
288 prev_linesize =
s->prev_frame->linesize[0];
289 pp =
s->prev_frame->data[0] + frame_y * prev_linesize + frame_x;
296 for (
i = 0;
i < frame_height;
i++) {
299 len = bytestream2_get_byte(&gb);
302 if (ofs +
len > frame_width ||
309 if (ofs +
len + 1 > frame_width || !pp)
311 memcpy(&dp[ofs], &pp[ofs],
len + 1);
314 }
while (ofs < frame_width);
315 if (ofs > frame_width) {
317 "offset > width (%d > %d)\n",
321 dp +=
frame->linesize[0];
327 for (
i = 0;
i < frame_height;
i++) {
329 dp +=
frame->linesize[0];
334 for (
i = 0;
i < frame_height;
i++) {
337 len = bytestream2_get_byte(&gb);
340 if (bytestream2_peek_byte(&gb) == 0xFF) {
342 bytestream2_get_byte(&gb);
349 if (ofs +
len > frame_width ||
357 if (ofs +
len + 1 > frame_width || !pp)
359 memcpy(&dp[ofs], &pp[ofs],
len + 1);
362 }
while (ofs < frame_width);
363 if (ofs > frame_width) {
365 "offset > width (%d > %d)\n",
369 dp +=
frame->linesize[0];
383 s->unpack_buffer_size = 0;
392 unsigned int *palette32;
393 int palette_index = 0;
394 unsigned char r,
g,
b;
395 unsigned char *vmd_header;
396 unsigned char *raw_palette;
407 vmd_header = (
unsigned char *)avctx->
extradata;
409 s->unpack_buffer_size =
AV_RL32(&vmd_header[800]);
410 if (
s->unpack_buffer_size) {
411 s->unpack_buffer =
av_malloc(
s->unpack_buffer_size);
412 if (!
s->unpack_buffer)
417 raw_palette = &vmd_header[28];
418 palette32 = (
unsigned int *)
s->palette;
420 r = raw_palette[palette_index++] * 4;
421 g = raw_palette[palette_index++] * 4;
422 b = raw_palette[palette_index++] * 4;
423 palette32[
i] = 0xFFU << 24 | (
r << 16) | (
g << 8) | (
b);
424 palette32[
i] |= palette32[
i] >> 6 & 0x30303;
437 const uint8_t *buf = avpkt->
data;
438 int buf_size = avpkt->
size;
468 .p.name =
"vmdvideo",
const FFCodec ff_vmdvideo_decoder
static av_cold void close(AVCodecParserContext *s)
Libavcodec external API header.
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
static av_always_inline void bytestream2_skipu(GetByteContext *g, unsigned int size)
static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, uint8_t *dst, unsigned int size)
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
static av_always_inline int bytestream2_tell(const GetByteContext *g)
#define bytestream2_get_ne16
#define i(width, name, range_min, range_max)
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
common internal and external API header
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
int(* init)(AVBSFContext *ctx)
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
#define AV_GET_BUFFER_FLAG_REF
The decoder will keep a reference to the frame and may reuse it later.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
int av_frame_replace(AVFrame *dst, const AVFrame *src)
Ensure the destination frame refers to the same data described by the source frame,...
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define FF_PTR_ADD(ptr, off)
Memory handling functions.
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
main external API structure.
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
This structure describes decoded (raw) audio or video data.
This structure stores compressed data.
unsigned char * unpack_buffer
unsigned char palette[PALETTE_COUNT *4]
const unsigned char * buf
static int lz_unpack(const unsigned char *src, int src_len, unsigned char *dest, int dest_len)
static av_cold int vmdvideo_decode_end(AVCodecContext *avctx)
static int rle_unpack(const unsigned char *src, unsigned char *dest, int src_count, int src_size, int dest_len)
static int vmdvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
static av_cold int vmdvideo_decode_init(AVCodecContext *avctx)