FFmpeg
Loading...
Searching...
No Matches
kgv1dec.c
Go to the documentation of this file.
1/*
2 * Kega Game Video (KGV1) decoder
3 * Copyright (c) 2010 Daniel Verkamp
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 * Kega Game Video decoder
25 */
26
27#include "libavutil/common.h"
29#include "libavutil/imgutils.h"
30#include "libavutil/mem.h"
31#include "avcodec.h"
32#include "codec_internal.h"
33#include "decode.h"
34
35typedef struct KgvContext {
36 uint16_t *frame_buffer;
39
40static void decode_flush(AVCodecContext *avctx)
41{
42 KgvContext * const c = avctx->priv_data;
43
44 av_freep(&c->frame_buffer);
45 av_freep(&c->last_frame_buffer);
46}
47
49 int *got_frame, AVPacket *avpkt)
50{
51 const uint8_t *buf = avpkt->data;
52 const uint8_t *buf_end = buf + avpkt->size;
53 KgvContext * const c = avctx->priv_data;
54 int offsets[8];
55 uint8_t *out, *prev;
56 int outcnt = 0, maxcnt;
57 int w, h, i, res;
58
59 if (avpkt->size < 2)
61
62 w = (buf[0] + 1) * 8;
63 h = (buf[1] + 1) * 8;
64 buf += 2;
65
66 if (avpkt->size < 2 + w*h / 513)
68
69 if (w != avctx->width || h != avctx->height) {
70 av_freep(&c->frame_buffer);
71 av_freep(&c->last_frame_buffer);
72 if ((res = ff_set_dimensions(avctx, w, h)) < 0)
73 return res;
74 }
75
76 if (!c->frame_buffer) {
77 c->frame_buffer = av_mallocz(avctx->width * avctx->height * 2);
78 c->last_frame_buffer = av_mallocz(avctx->width * avctx->height * 2);
79 if (!c->frame_buffer || !c->last_frame_buffer) {
80 decode_flush(avctx);
81 return AVERROR(ENOMEM);
82 }
83 }
84
85 maxcnt = w * h;
86
87 if ((res = ff_get_buffer(avctx, frame, 0)) < 0)
88 return res;
89 out = (uint8_t*)c->frame_buffer;
90 prev = (uint8_t*)c->last_frame_buffer;
91
92 for (i = 0; i < 8; i++)
93 offsets[i] = -1;
94
95 while (outcnt < maxcnt && buf_end - 2 >= buf) {
96 int code = AV_RL16(buf);
97 buf += 2;
98
99 if (!(code & 0x8000)) {
100 AV_WN16A(&out[2 * outcnt], code); // rgb555 pixel coded directly
101 outcnt++;
102 } else {
103 int count;
104
105 if ((code & 0x6000) == 0x6000) {
106 // copy from previous frame
107 int oidx = (code >> 10) & 7;
108 int start;
109
110 count = (code & 0x3FF) + 3;
111
112 if (offsets[oidx] < 0) {
113 if (buf_end - 3 < buf)
114 break;
115 offsets[oidx] = AV_RL24(buf);
116 buf += 3;
117 }
118
119 start = (outcnt + offsets[oidx]) % maxcnt;
120
121 if (maxcnt - start < count || maxcnt - outcnt < count)
122 break;
123
124 if (!prev) {
125 av_log(avctx, AV_LOG_ERROR,
126 "Frame reference does not exist\n");
127 break;
128 }
129
130 memcpy(out + 2 * outcnt, prev + 2 * start, 2 * count);
131 } else {
132 // copy from earlier in this frame
133 int offset = (code & 0x1FFF) + 1;
134
135 if (!(code & 0x6000)) {
136 count = 2;
137 } else if ((code & 0x6000) == 0x2000) {
138 count = 3;
139 } else {
140 if (buf_end - 1 < buf)
141 break;
142 count = 4 + *buf++;
143 }
144
145 if (outcnt < offset || maxcnt - outcnt < count)
146 break;
147
148 av_memcpy_backptr(out + 2 * outcnt, 2 * offset, 2 * count);
149 }
150 outcnt += count;
151 }
152 }
153
154 if (outcnt - maxcnt)
155 av_log(avctx, AV_LOG_DEBUG, "frame finished with %d diff\n", outcnt - maxcnt);
156
157 av_image_copy_plane(frame->data[0], frame->linesize[0],
158 (const uint8_t*)c->frame_buffer, avctx->width * 2,
159 avctx->width * 2, avctx->height);
160 FFSWAP(uint16_t *, c->frame_buffer, c->last_frame_buffer);
161
162 *got_frame = 1;
163
164 return avpkt->size;
165}
166
168{
169 avctx->pix_fmt = AV_PIX_FMT_RGB555;
170
171 return 0;
172}
173
175{
176 decode_flush(avctx);
177 return 0;
178}
179
181 .p.name = "kgv1",
182 CODEC_LONG_NAME("Kega Game Video"),
183 .p.type = AVMEDIA_TYPE_VIDEO,
184 .p.id = AV_CODEC_ID_KGV1,
185 .priv_data_size = sizeof(KgvContext),
186 .init = decode_init,
187 .close = decode_end,
189 .flush = decode_flush,
190 .p.capabilities = AV_CODEC_CAP_DR1,
191};
static av_cold void decode_flush(AVCodecContext *avctx)
Definition agm.c:1253
const FFCodec ff_kgv1_decoder
Definition kgv1dec.c:180
static FILE * out
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
Libavcodec external API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
common internal and external API header
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Definition utils.c:91
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_KGV1
Definition codec_id.h:188
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition mem.c:445
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition imgutils.c:374
static const int offsets[]
Definition hevc_pel.c:34
misc image utilities
#define AV_RL24(x)
#define AV_WN16A(p, v)
#define AV_RL16(p)
static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)
Definition kgv1dec.c:48
static av_cold int decode_init(AVCodecContext *avctx)
Definition kgv1dec.c:167
static av_cold int decode_end(AVCodecContext *avctx)
Definition kgv1dec.c:174
static void decode_flush(AVCodecContext *avctx)
Definition kgv1dec.c:40
unsigned offset
Definition libaomenc.c:763
static av_cold int decode_init(AVCodecContext *avctx)
Definition 4xm.c:998
static av_cold int decode_end(AVCodecContext *avctx)
Definition 4xm.c:980
static int decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt)
Definition 4xm.c:837
#define av_cold
Definition attributes.h:117
uint8_t w
Definition llvidencdsp.c:39
#define FFSWAP(type, a, b)
Definition macros.h:52
Memory handling functions.
#define AV_PIX_FMT_RGB555
Definition pixfmt.h:533
const uint8_t * code
Definition spdifenc.c:433
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
uint16_t * last_frame_buffer
Definition kgv1dec.c:37
uint16_t * frame_buffer
Definition kgv1dec.c:36
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static double c[64]