yading@10
|
1 /*
|
yading@10
|
2 * a64 video encoder - multicolor modes
|
yading@10
|
3 * Copyright (c) 2009 Tobias Bindhammer
|
yading@10
|
4 *
|
yading@10
|
5 * This file is part of FFmpeg.
|
yading@10
|
6 *
|
yading@10
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
9 * License as published by the Free Software Foundation; either
|
yading@10
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
11 *
|
yading@10
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
15 * Lesser General Public License for more details.
|
yading@10
|
16 *
|
yading@10
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
20 */
|
yading@10
|
21
|
yading@10
|
22 /**
|
yading@10
|
23 * @file
|
yading@10
|
24 * a64 video encoder - multicolor modes
|
yading@10
|
25 */
|
yading@10
|
26
|
yading@10
|
27 #include "a64colors.h"
|
yading@10
|
28 #include "a64tables.h"
|
yading@10
|
29 #include "elbg.h"
|
yading@10
|
30 #include "internal.h"
|
yading@10
|
31 #include "libavutil/common.h"
|
yading@10
|
32 #include "libavutil/intreadwrite.h"
|
yading@10
|
33
|
yading@10
|
34 #define DITHERSTEPS 8
|
yading@10
|
35 #define CHARSET_CHARS 256
|
yading@10
|
36 #define INTERLACED 1
|
yading@10
|
37 #define CROP_SCREENS 1
|
yading@10
|
38
|
yading@10
|
39 #define C64XRES 320
|
yading@10
|
40 #define C64YRES 200
|
yading@10
|
41
|
yading@10
|
42 typedef struct A64Context {
|
yading@10
|
43 /* general variables */
|
yading@10
|
44 AVFrame picture;
|
yading@10
|
45
|
yading@10
|
46 /* variables for multicolor modes */
|
yading@10
|
47 AVLFG randctx;
|
yading@10
|
48 int mc_lifetime;
|
yading@10
|
49 int mc_use_5col;
|
yading@10
|
50 unsigned mc_frame_counter;
|
yading@10
|
51 int *mc_meta_charset;
|
yading@10
|
52 int *mc_charmap;
|
yading@10
|
53 int *mc_best_cb;
|
yading@10
|
54 int mc_luma_vals[5];
|
yading@10
|
55 uint8_t *mc_charset;
|
yading@10
|
56 uint8_t *mc_colram;
|
yading@10
|
57 uint8_t *mc_palette;
|
yading@10
|
58 int mc_pal_size;
|
yading@10
|
59
|
yading@10
|
60 /* pts of the next packet that will be output */
|
yading@10
|
61 int64_t next_pts;
|
yading@10
|
62 } A64Context;
|
yading@10
|
63
|
yading@10
|
64 /* gray gradient */
|
yading@10
|
65 static const int mc_colors[5]={0x0,0xb,0xc,0xf,0x1};
|
yading@10
|
66
|
yading@10
|
67 /* other possible gradients - to be tested */
|
yading@10
|
68 //static const int mc_colors[5]={0x0,0x8,0xa,0xf,0x7};
|
yading@10
|
69 //static const int mc_colors[5]={0x0,0x9,0x8,0xa,0x3};
|
yading@10
|
70
|
yading@10
|
71 static void to_meta_with_crop(AVCodecContext *avctx, AVFrame *p, int *dest)
|
yading@10
|
72 {
|
yading@10
|
73 int blockx, blocky, x, y;
|
yading@10
|
74 int luma = 0;
|
yading@10
|
75 int height = FFMIN(avctx->height, C64YRES);
|
yading@10
|
76 int width = FFMIN(avctx->width , C64XRES);
|
yading@10
|
77 uint8_t *src = p->data[0];
|
yading@10
|
78
|
yading@10
|
79 for (blocky = 0; blocky < C64YRES; blocky += 8) {
|
yading@10
|
80 for (blockx = 0; blockx < C64XRES; blockx += 8) {
|
yading@10
|
81 for (y = blocky; y < blocky + 8 && y < C64YRES; y++) {
|
yading@10
|
82 for (x = blockx; x < blockx + 8 && x < C64XRES; x += 2) {
|
yading@10
|
83 if(x < width && y < height) {
|
yading@10
|
84 /* build average over 2 pixels */
|
yading@10
|
85 luma = (src[(x + 0 + y * p->linesize[0])] +
|
yading@10
|
86 src[(x + 1 + y * p->linesize[0])]) / 2;
|
yading@10
|
87 /* write blocks as linear data now so they are suitable for elbg */
|
yading@10
|
88 dest[0] = luma;
|
yading@10
|
89 }
|
yading@10
|
90 dest++;
|
yading@10
|
91 }
|
yading@10
|
92 }
|
yading@10
|
93 }
|
yading@10
|
94 }
|
yading@10
|
95 }
|
yading@10
|
96
|
yading@10
|
97 static void render_charset(AVCodecContext *avctx, uint8_t *charset,
|
yading@10
|
98 uint8_t *colrammap)
|
yading@10
|
99 {
|
yading@10
|
100 A64Context *c = avctx->priv_data;
|
yading@10
|
101 uint8_t row1, row2;
|
yading@10
|
102 int charpos, x, y;
|
yading@10
|
103 int a, b;
|
yading@10
|
104 uint8_t pix;
|
yading@10
|
105 int lowdiff, highdiff;
|
yading@10
|
106 int *best_cb = c->mc_best_cb;
|
yading@10
|
107 static uint8_t index1[256];
|
yading@10
|
108 static uint8_t index2[256];
|
yading@10
|
109 static uint8_t dither[256];
|
yading@10
|
110 int i;
|
yading@10
|
111 int distance;
|
yading@10
|
112
|
yading@10
|
113 /* generate lookup-tables for dither and index before looping */
|
yading@10
|
114 i = 0;
|
yading@10
|
115 for (a=0; a < 256; a++) {
|
yading@10
|
116 if(i < c->mc_pal_size -1 && a == c->mc_luma_vals[i + 1]) {
|
yading@10
|
117 distance = c->mc_luma_vals[i + 1] - c->mc_luma_vals[i];
|
yading@10
|
118 for(b = 0; b <= distance; b++) {
|
yading@10
|
119 dither[c->mc_luma_vals[i] + b] = b * (DITHERSTEPS - 1) / distance;
|
yading@10
|
120 }
|
yading@10
|
121 i++;
|
yading@10
|
122 }
|
yading@10
|
123 if(i >= c->mc_pal_size - 1) dither[a] = 0;
|
yading@10
|
124 index1[a] = i;
|
yading@10
|
125 index2[a] = FFMIN(i + 1, c->mc_pal_size - 1);
|
yading@10
|
126 }
|
yading@10
|
127
|
yading@10
|
128 /* and render charset */
|
yading@10
|
129 for (charpos = 0; charpos < CHARSET_CHARS; charpos++) {
|
yading@10
|
130 lowdiff = 0;
|
yading@10
|
131 highdiff = 0;
|
yading@10
|
132 for (y = 0; y < 8; y++) {
|
yading@10
|
133 row1 = 0; row2 = 0;
|
yading@10
|
134 for (x = 0; x < 4; x++) {
|
yading@10
|
135 pix = best_cb[y * 4 + x];
|
yading@10
|
136
|
yading@10
|
137 /* accumulate error for brightest/darkest color */
|
yading@10
|
138 if (index1[pix] >= 3)
|
yading@10
|
139 highdiff += pix - c->mc_luma_vals[3];
|
yading@10
|
140 if (index1[pix] < 1)
|
yading@10
|
141 lowdiff += c->mc_luma_vals[1] - pix;
|
yading@10
|
142
|
yading@10
|
143 row1 <<= 2;
|
yading@10
|
144
|
yading@10
|
145 if (INTERLACED) {
|
yading@10
|
146 row2 <<= 2;
|
yading@10
|
147 if (interlaced_dither_patterns[dither[pix]][(y & 3) * 2 + 0][x & 3])
|
yading@10
|
148 row1 |= 3-(index2[pix] & 3);
|
yading@10
|
149 else
|
yading@10
|
150 row1 |= 3-(index1[pix] & 3);
|
yading@10
|
151
|
yading@10
|
152 if (interlaced_dither_patterns[dither[pix]][(y & 3) * 2 + 1][x & 3])
|
yading@10
|
153 row2 |= 3-(index2[pix] & 3);
|
yading@10
|
154 else
|
yading@10
|
155 row2 |= 3-(index1[pix] & 3);
|
yading@10
|
156 }
|
yading@10
|
157 else {
|
yading@10
|
158 if (multi_dither_patterns[dither[pix]][(y & 3)][x & 3])
|
yading@10
|
159 row1 |= 3-(index2[pix] & 3);
|
yading@10
|
160 else
|
yading@10
|
161 row1 |= 3-(index1[pix] & 3);
|
yading@10
|
162 }
|
yading@10
|
163 }
|
yading@10
|
164 charset[y+0x000] = row1;
|
yading@10
|
165 if (INTERLACED) charset[y+0x800] = row2;
|
yading@10
|
166 }
|
yading@10
|
167 /* do we need to adjust pixels? */
|
yading@10
|
168 if (highdiff > 0 && lowdiff > 0 && c->mc_use_5col) {
|
yading@10
|
169 if (lowdiff > highdiff) {
|
yading@10
|
170 for (x = 0; x < 32; x++)
|
yading@10
|
171 best_cb[x] = FFMIN(c->mc_luma_vals[3], best_cb[x]);
|
yading@10
|
172 } else {
|
yading@10
|
173 for (x = 0; x < 32; x++)
|
yading@10
|
174 best_cb[x] = FFMAX(c->mc_luma_vals[1], best_cb[x]);
|
yading@10
|
175 }
|
yading@10
|
176 charpos--; /* redo now adjusted char */
|
yading@10
|
177 /* no adjustment needed, all fine */
|
yading@10
|
178 } else {
|
yading@10
|
179 /* advance pointers */
|
yading@10
|
180 best_cb += 32;
|
yading@10
|
181 charset += 8;
|
yading@10
|
182
|
yading@10
|
183 /* remember colorram value */
|
yading@10
|
184 colrammap[charpos] = (highdiff > 0);
|
yading@10
|
185 }
|
yading@10
|
186 }
|
yading@10
|
187 }
|
yading@10
|
188
|
yading@10
|
189 static av_cold int a64multi_close_encoder(AVCodecContext *avctx)
|
yading@10
|
190 {
|
yading@10
|
191 A64Context *c = avctx->priv_data;
|
yading@10
|
192 av_free(c->mc_meta_charset);
|
yading@10
|
193 av_free(c->mc_best_cb);
|
yading@10
|
194 av_free(c->mc_charset);
|
yading@10
|
195 av_free(c->mc_charmap);
|
yading@10
|
196 av_free(c->mc_colram);
|
yading@10
|
197 return 0;
|
yading@10
|
198 }
|
yading@10
|
199
|
yading@10
|
200 static av_cold int a64multi_init_encoder(AVCodecContext *avctx)
|
yading@10
|
201 {
|
yading@10
|
202 A64Context *c = avctx->priv_data;
|
yading@10
|
203 int a;
|
yading@10
|
204 av_lfg_init(&c->randctx, 1);
|
yading@10
|
205
|
yading@10
|
206 if (avctx->global_quality < 1) {
|
yading@10
|
207 c->mc_lifetime = 4;
|
yading@10
|
208 } else {
|
yading@10
|
209 c->mc_lifetime = avctx->global_quality /= FF_QP2LAMBDA;
|
yading@10
|
210 }
|
yading@10
|
211
|
yading@10
|
212 av_log(avctx, AV_LOG_INFO, "charset lifetime set to %d frame(s)\n", c->mc_lifetime);
|
yading@10
|
213
|
yading@10
|
214 c->mc_frame_counter = 0;
|
yading@10
|
215 c->mc_use_5col = avctx->codec->id == AV_CODEC_ID_A64_MULTI5;
|
yading@10
|
216 c->mc_pal_size = 4 + c->mc_use_5col;
|
yading@10
|
217
|
yading@10
|
218 /* precalc luma values for later use */
|
yading@10
|
219 for (a = 0; a < c->mc_pal_size; a++) {
|
yading@10
|
220 c->mc_luma_vals[a]=a64_palette[mc_colors[a]][0] * 0.30 +
|
yading@10
|
221 a64_palette[mc_colors[a]][1] * 0.59 +
|
yading@10
|
222 a64_palette[mc_colors[a]][2] * 0.11;
|
yading@10
|
223 }
|
yading@10
|
224
|
yading@10
|
225 if (!(c->mc_meta_charset = av_malloc(32000 * c->mc_lifetime * sizeof(int))) ||
|
yading@10
|
226 !(c->mc_best_cb = av_malloc(CHARSET_CHARS * 32 * sizeof(int))) ||
|
yading@10
|
227 !(c->mc_charmap = av_mallocz(1000 * c->mc_lifetime * sizeof(int))) ||
|
yading@10
|
228 !(c->mc_colram = av_mallocz(CHARSET_CHARS * sizeof(uint8_t))) ||
|
yading@10
|
229 !(c->mc_charset = av_malloc(0x800 * (INTERLACED+1) * sizeof(uint8_t)))) {
|
yading@10
|
230 av_log(avctx, AV_LOG_ERROR, "Failed to allocate buffer memory.\n");
|
yading@10
|
231 return AVERROR(ENOMEM);
|
yading@10
|
232 }
|
yading@10
|
233
|
yading@10
|
234 /* set up extradata */
|
yading@10
|
235 if (!(avctx->extradata = av_mallocz(8 * 4 + FF_INPUT_BUFFER_PADDING_SIZE))) {
|
yading@10
|
236 av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for extradata.\n");
|
yading@10
|
237 return AVERROR(ENOMEM);
|
yading@10
|
238 }
|
yading@10
|
239 avctx->extradata_size = 8 * 4;
|
yading@10
|
240 AV_WB32(avctx->extradata, c->mc_lifetime);
|
yading@10
|
241 AV_WB32(avctx->extradata + 16, INTERLACED);
|
yading@10
|
242
|
yading@10
|
243 avcodec_get_frame_defaults(&c->picture);
|
yading@10
|
244 avctx->coded_frame = &c->picture;
|
yading@10
|
245 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
|
yading@10
|
246 avctx->coded_frame->key_frame = 1;
|
yading@10
|
247 if (!avctx->codec_tag)
|
yading@10
|
248 avctx->codec_tag = AV_RL32("a64m");
|
yading@10
|
249
|
yading@10
|
250 c->next_pts = AV_NOPTS_VALUE;
|
yading@10
|
251
|
yading@10
|
252 return 0;
|
yading@10
|
253 }
|
yading@10
|
254
|
yading@10
|
255 static void a64_compress_colram(unsigned char *buf, int *charmap, uint8_t *colram)
|
yading@10
|
256 {
|
yading@10
|
257 int a;
|
yading@10
|
258 uint8_t temp;
|
yading@10
|
259 /* only needs to be done in 5col mode */
|
yading@10
|
260 /* XXX could be squeezed to 0x80 bytes */
|
yading@10
|
261 for (a = 0; a < 256; a++) {
|
yading@10
|
262 temp = colram[charmap[a + 0x000]] << 0;
|
yading@10
|
263 temp |= colram[charmap[a + 0x100]] << 1;
|
yading@10
|
264 temp |= colram[charmap[a + 0x200]] << 2;
|
yading@10
|
265 if (a < 0xe8) temp |= colram[charmap[a + 0x300]] << 3;
|
yading@10
|
266 buf[a] = temp << 2;
|
yading@10
|
267 }
|
yading@10
|
268 }
|
yading@10
|
269
|
yading@10
|
270 static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
yading@10
|
271 const AVFrame *pict, int *got_packet)
|
yading@10
|
272 {
|
yading@10
|
273 A64Context *c = avctx->priv_data;
|
yading@10
|
274 AVFrame *const p = &c->picture;
|
yading@10
|
275
|
yading@10
|
276 int frame;
|
yading@10
|
277 int x, y;
|
yading@10
|
278 int b_height;
|
yading@10
|
279 int b_width;
|
yading@10
|
280
|
yading@10
|
281 int req_size, ret;
|
yading@10
|
282 uint8_t *buf = NULL;
|
yading@10
|
283
|
yading@10
|
284 int *charmap = c->mc_charmap;
|
yading@10
|
285 uint8_t *colram = c->mc_colram;
|
yading@10
|
286 uint8_t *charset = c->mc_charset;
|
yading@10
|
287 int *meta = c->mc_meta_charset;
|
yading@10
|
288 int *best_cb = c->mc_best_cb;
|
yading@10
|
289
|
yading@10
|
290 int charset_size = 0x800 * (INTERLACED + 1);
|
yading@10
|
291 int colram_size = 0x100 * c->mc_use_5col;
|
yading@10
|
292 int screen_size;
|
yading@10
|
293
|
yading@10
|
294 if(CROP_SCREENS) {
|
yading@10
|
295 b_height = FFMIN(avctx->height,C64YRES) >> 3;
|
yading@10
|
296 b_width = FFMIN(avctx->width ,C64XRES) >> 3;
|
yading@10
|
297 screen_size = b_width * b_height;
|
yading@10
|
298 } else {
|
yading@10
|
299 b_height = C64YRES >> 3;
|
yading@10
|
300 b_width = C64XRES >> 3;
|
yading@10
|
301 screen_size = 0x400;
|
yading@10
|
302 }
|
yading@10
|
303
|
yading@10
|
304 /* no data, means end encoding asap */
|
yading@10
|
305 if (!pict) {
|
yading@10
|
306 /* all done, end encoding */
|
yading@10
|
307 if (!c->mc_lifetime) return 0;
|
yading@10
|
308 /* no more frames in queue, prepare to flush remaining frames */
|
yading@10
|
309 if (!c->mc_frame_counter) {
|
yading@10
|
310 c->mc_lifetime = 0;
|
yading@10
|
311 }
|
yading@10
|
312 /* still frames in queue so limit lifetime to remaining frames */
|
yading@10
|
313 else c->mc_lifetime = c->mc_frame_counter;
|
yading@10
|
314 /* still new data available */
|
yading@10
|
315 } else {
|
yading@10
|
316 /* fill up mc_meta_charset with data until lifetime exceeds */
|
yading@10
|
317 if (c->mc_frame_counter < c->mc_lifetime) {
|
yading@10
|
318 *p = *pict;
|
yading@10
|
319 p->pict_type = AV_PICTURE_TYPE_I;
|
yading@10
|
320 p->key_frame = 1;
|
yading@10
|
321 to_meta_with_crop(avctx, p, meta + 32000 * c->mc_frame_counter);
|
yading@10
|
322 c->mc_frame_counter++;
|
yading@10
|
323 if (c->next_pts == AV_NOPTS_VALUE)
|
yading@10
|
324 c->next_pts = pict->pts;
|
yading@10
|
325 /* lifetime is not reached so wait for next frame first */
|
yading@10
|
326 return 0;
|
yading@10
|
327 }
|
yading@10
|
328 }
|
yading@10
|
329
|
yading@10
|
330 /* lifetime reached so now convert X frames at once */
|
yading@10
|
331 if (c->mc_frame_counter == c->mc_lifetime) {
|
yading@10
|
332 req_size = 0;
|
yading@10
|
333 /* any frames to encode? */
|
yading@10
|
334 if (c->mc_lifetime) {
|
yading@10
|
335 req_size = charset_size + c->mc_lifetime*(screen_size + colram_size);
|
yading@10
|
336 if ((ret = ff_alloc_packet2(avctx, pkt, req_size)) < 0)
|
yading@10
|
337 return ret;
|
yading@10
|
338 buf = pkt->data;
|
yading@10
|
339
|
yading@10
|
340 /* calc optimal new charset + charmaps */
|
yading@10
|
341 ff_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx);
|
yading@10
|
342 ff_do_elbg (meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx);
|
yading@10
|
343
|
yading@10
|
344 /* create colorram map and a c64 readable charset */
|
yading@10
|
345 render_charset(avctx, charset, colram);
|
yading@10
|
346
|
yading@10
|
347 /* copy charset to buf */
|
yading@10
|
348 memcpy(buf, charset, charset_size);
|
yading@10
|
349
|
yading@10
|
350 /* advance pointers */
|
yading@10
|
351 buf += charset_size;
|
yading@10
|
352 charset += charset_size;
|
yading@10
|
353 }
|
yading@10
|
354
|
yading@10
|
355 /* write x frames to buf */
|
yading@10
|
356 for (frame = 0; frame < c->mc_lifetime; frame++) {
|
yading@10
|
357 /* copy charmap to buf. buf is uchar*, charmap is int*, so no memcpy here, sorry */
|
yading@10
|
358 for (y = 0; y < b_height; y++) {
|
yading@10
|
359 for (x = 0; x < b_width; x++) {
|
yading@10
|
360 buf[y * b_width + x] = charmap[y * b_width + x];
|
yading@10
|
361 }
|
yading@10
|
362 }
|
yading@10
|
363 /* advance pointers */
|
yading@10
|
364 buf += screen_size;
|
yading@10
|
365 req_size += screen_size;
|
yading@10
|
366
|
yading@10
|
367 /* compress and copy colram to buf */
|
yading@10
|
368 if (c->mc_use_5col) {
|
yading@10
|
369 a64_compress_colram(buf, charmap, colram);
|
yading@10
|
370 /* advance pointers */
|
yading@10
|
371 buf += colram_size;
|
yading@10
|
372 req_size += colram_size;
|
yading@10
|
373 }
|
yading@10
|
374
|
yading@10
|
375 /* advance to next charmap */
|
yading@10
|
376 charmap += 1000;
|
yading@10
|
377 }
|
yading@10
|
378
|
yading@10
|
379 AV_WB32(avctx->extradata + 4, c->mc_frame_counter);
|
yading@10
|
380 AV_WB32(avctx->extradata + 8, charset_size);
|
yading@10
|
381 AV_WB32(avctx->extradata + 12, screen_size + colram_size);
|
yading@10
|
382
|
yading@10
|
383 /* reset counter */
|
yading@10
|
384 c->mc_frame_counter = 0;
|
yading@10
|
385
|
yading@10
|
386 pkt->pts = pkt->dts = c->next_pts;
|
yading@10
|
387 c->next_pts = AV_NOPTS_VALUE;
|
yading@10
|
388
|
yading@10
|
389 pkt->size = req_size;
|
yading@10
|
390 pkt->flags |= AV_PKT_FLAG_KEY;
|
yading@10
|
391 *got_packet = !!req_size;
|
yading@10
|
392 }
|
yading@10
|
393 return 0;
|
yading@10
|
394 }
|
yading@10
|
395
|
yading@10
|
396 #if CONFIG_A64MULTI_ENCODER
|
yading@10
|
397 AVCodec ff_a64multi_encoder = {
|
yading@10
|
398 .name = "a64multi",
|
yading@10
|
399 .type = AVMEDIA_TYPE_VIDEO,
|
yading@10
|
400 .id = AV_CODEC_ID_A64_MULTI,
|
yading@10
|
401 .priv_data_size = sizeof(A64Context),
|
yading@10
|
402 .init = a64multi_init_encoder,
|
yading@10
|
403 .encode2 = a64multi_encode_frame,
|
yading@10
|
404 .close = a64multi_close_encoder,
|
yading@10
|
405 .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE},
|
yading@10
|
406 .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64"),
|
yading@10
|
407 .capabilities = CODEC_CAP_DELAY,
|
yading@10
|
408 };
|
yading@10
|
409 #endif
|
yading@10
|
410 #if CONFIG_A64MULTI5_ENCODER
|
yading@10
|
411 AVCodec ff_a64multi5_encoder = {
|
yading@10
|
412 .name = "a64multi5",
|
yading@10
|
413 .type = AVMEDIA_TYPE_VIDEO,
|
yading@10
|
414 .id = AV_CODEC_ID_A64_MULTI5,
|
yading@10
|
415 .priv_data_size = sizeof(A64Context),
|
yading@10
|
416 .init = a64multi_init_encoder,
|
yading@10
|
417 .encode2 = a64multi_encode_frame,
|
yading@10
|
418 .close = a64multi_close_encoder,
|
yading@10
|
419 .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE},
|
yading@10
|
420 .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64, extended with 5th color (colram)"),
|
yading@10
|
421 .capabilities = CODEC_CAP_DELAY,
|
yading@10
|
422 };
|
yading@10
|
423 #endif
|