Line |
Branch |
Exec |
Source |
1 |
|
|
/* |
2 |
|
|
* Zip Motion Blocks Video (ZMBV) encoder |
3 |
|
|
* Copyright (c) 2006 Konstantin Shishkov |
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 |
|
|
* Zip Motion Blocks Video encoder |
25 |
|
|
*/ |
26 |
|
|
|
27 |
|
|
#include <stddef.h> |
28 |
|
|
|
29 |
|
|
#include "libavutil/intreadwrite.h" |
30 |
|
|
#include "libavutil/mem.h" |
31 |
|
|
#include "avcodec.h" |
32 |
|
|
#include "codec_internal.h" |
33 |
|
|
#include "encode.h" |
34 |
|
|
#include "zlib_wrapper.h" |
35 |
|
|
|
36 |
|
|
#include <zlib.h> |
37 |
|
|
|
38 |
|
|
/* Frame header flags */ |
39 |
|
|
#define ZMBV_KEYFRAME 1 |
40 |
|
|
#define ZMBV_DELTAPAL 2 |
41 |
|
|
|
42 |
|
|
/* Motion block width/height (maximum allowed value is 255) |
43 |
|
|
* Note: histogram datatype in block_cmp() must be big enough to hold values |
44 |
|
|
* up to (4 * ZMBV_BLOCK * ZMBV_BLOCK) |
45 |
|
|
*/ |
46 |
|
|
#define ZMBV_BLOCK 16 |
47 |
|
|
|
48 |
|
|
/* Keyframe header format values */ |
49 |
|
|
enum ZmbvFormat { |
50 |
|
|
ZMBV_FMT_NONE = 0, |
51 |
|
|
ZMBV_FMT_1BPP = 1, |
52 |
|
|
ZMBV_FMT_2BPP = 2, |
53 |
|
|
ZMBV_FMT_4BPP = 3, |
54 |
|
|
ZMBV_FMT_8BPP = 4, |
55 |
|
|
ZMBV_FMT_15BPP = 5, |
56 |
|
|
ZMBV_FMT_16BPP = 6, |
57 |
|
|
ZMBV_FMT_24BPP = 7, |
58 |
|
|
ZMBV_FMT_32BPP = 8 |
59 |
|
|
}; |
60 |
|
|
|
61 |
|
|
/** |
62 |
|
|
* Encoder context |
63 |
|
|
*/ |
64 |
|
|
typedef struct ZmbvEncContext { |
65 |
|
|
AVCodecContext *avctx; |
66 |
|
|
|
67 |
|
|
int lrange, urange; |
68 |
|
|
uint8_t *comp_buf, *work_buf; |
69 |
|
|
uint8_t pal[768]; |
70 |
|
|
uint32_t pal2[256]; //for quick comparisons |
71 |
|
|
uint8_t *prev, *prev_buf; |
72 |
|
|
int pstride; |
73 |
|
|
int comp_size; |
74 |
|
|
int keyint, curfrm; |
75 |
|
|
int bypp; |
76 |
|
|
enum ZmbvFormat fmt; |
77 |
|
|
FFZStream zstream; |
78 |
|
|
|
79 |
|
|
int score_tab[ZMBV_BLOCK * ZMBV_BLOCK * 4 + 1]; |
80 |
|
|
} ZmbvEncContext; |
81 |
|
|
|
82 |
|
|
|
83 |
|
|
/** Block comparing function |
84 |
|
|
* XXX should be optimized and moved to DSPContext |
85 |
|
|
*/ |
86 |
|
✗ |
static inline int block_cmp(ZmbvEncContext *c, const uint8_t *src, int stride, |
87 |
|
|
const uint8_t *src2, int stride2, int bw, int bh, |
88 |
|
|
int *xored) |
89 |
|
|
{ |
90 |
|
✗ |
int sum = 0; |
91 |
|
|
int i, j; |
92 |
|
✗ |
uint16_t histogram[256] = {0}; |
93 |
|
✗ |
int bw_bytes = bw * c->bypp; |
94 |
|
|
|
95 |
|
|
/* Build frequency histogram of byte values for src[] ^ src2[] */ |
96 |
|
✗ |
for(j = 0; j < bh; j++){ |
97 |
|
✗ |
for(i = 0; i < bw_bytes; i++){ |
98 |
|
✗ |
int t = src[i] ^ src2[i]; |
99 |
|
✗ |
histogram[t]++; |
100 |
|
|
} |
101 |
|
✗ |
src += stride; |
102 |
|
✗ |
src2 += stride2; |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
/* If not all the xored values were 0, then the blocks are different */ |
106 |
|
✗ |
*xored = (histogram[0] < bw_bytes * bh); |
107 |
|
|
|
108 |
|
|
/* Exit early if blocks are equal */ |
109 |
|
✗ |
if (!*xored) return 0; |
110 |
|
|
|
111 |
|
|
/* Sum the entropy of all values */ |
112 |
|
✗ |
for(i = 0; i < 256; i++) |
113 |
|
✗ |
sum += c->score_tab[histogram[i]]; |
114 |
|
|
|
115 |
|
✗ |
return sum; |
116 |
|
|
} |
117 |
|
|
|
118 |
|
|
/** Motion estimation function |
119 |
|
|
* TODO make better ME decisions |
120 |
|
|
*/ |
121 |
|
✗ |
static int zmbv_me(ZmbvEncContext *c, const uint8_t *src, int sstride, const uint8_t *prev, |
122 |
|
|
int pstride, int x, int y, int *mx, int *my, int *xored) |
123 |
|
|
{ |
124 |
|
|
int dx, dy, txored, tv, bv, bw, bh; |
125 |
|
|
int mx0, my0; |
126 |
|
|
|
127 |
|
✗ |
mx0 = *mx; |
128 |
|
✗ |
my0 = *my; |
129 |
|
✗ |
bw = FFMIN(ZMBV_BLOCK, c->avctx->width - x); |
130 |
|
✗ |
bh = FFMIN(ZMBV_BLOCK, c->avctx->height - y); |
131 |
|
|
|
132 |
|
|
/* Try (0,0) */ |
133 |
|
✗ |
bv = block_cmp(c, src, sstride, prev, pstride, bw, bh, xored); |
134 |
|
✗ |
*mx = *my = 0; |
135 |
|
✗ |
if(!bv) return 0; |
136 |
|
|
|
137 |
|
|
/* Try previous block's MV (if not 0,0) */ |
138 |
|
✗ |
if (mx0 || my0){ |
139 |
|
✗ |
tv = block_cmp(c, src, sstride, prev + mx0 * c->bypp + my0 * pstride, pstride, bw, bh, &txored); |
140 |
|
✗ |
if(tv < bv){ |
141 |
|
✗ |
bv = tv; |
142 |
|
✗ |
*mx = mx0; |
143 |
|
✗ |
*my = my0; |
144 |
|
✗ |
*xored = txored; |
145 |
|
✗ |
if(!bv) return 0; |
146 |
|
|
} |
147 |
|
|
} |
148 |
|
|
|
149 |
|
|
/* Try other MVs from top-to-bottom, left-to-right */ |
150 |
|
✗ |
for(dy = -c->lrange; dy <= c->urange; dy++){ |
151 |
|
✗ |
for(dx = -c->lrange; dx <= c->urange; dx++){ |
152 |
|
✗ |
if(!dx && !dy) continue; // we already tested this block |
153 |
|
✗ |
if(dx == mx0 && dy == my0) continue; // this one too |
154 |
|
✗ |
tv = block_cmp(c, src, sstride, prev + dx * c->bypp + dy * pstride, pstride, bw, bh, &txored); |
155 |
|
✗ |
if(tv < bv){ |
156 |
|
✗ |
bv = tv; |
157 |
|
✗ |
*mx = dx; |
158 |
|
✗ |
*my = dy; |
159 |
|
✗ |
*xored = txored; |
160 |
|
✗ |
if(!bv) return 0; |
161 |
|
|
} |
162 |
|
|
} |
163 |
|
|
} |
164 |
|
✗ |
return bv; |
165 |
|
|
} |
166 |
|
|
|
167 |
|
✗ |
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
168 |
|
|
const AVFrame *pict, int *got_packet) |
169 |
|
|
{ |
170 |
|
✗ |
ZmbvEncContext * const c = avctx->priv_data; |
171 |
|
✗ |
z_stream *const zstream = &c->zstream.zstream; |
172 |
|
✗ |
const AVFrame * const p = pict; |
173 |
|
|
const uint8_t *src; |
174 |
|
|
uint8_t *prev, *buf; |
175 |
|
|
uint32_t *palptr; |
176 |
|
|
int keyframe, chpal; |
177 |
|
|
int fl; |
178 |
|
✗ |
int work_size = 0, pkt_size; |
179 |
|
|
int bw, bh; |
180 |
|
|
int i, j, ret; |
181 |
|
|
|
182 |
|
✗ |
keyframe = !c->curfrm; |
183 |
|
✗ |
c->curfrm++; |
184 |
|
✗ |
if(c->curfrm == c->keyint) |
185 |
|
✗ |
c->curfrm = 0; |
186 |
|
|
|
187 |
|
✗ |
palptr = (avctx->pix_fmt == AV_PIX_FMT_PAL8) ? (uint32_t *)p->data[1] : NULL; |
188 |
|
✗ |
chpal = !keyframe && palptr && memcmp(palptr, c->pal2, 1024); |
189 |
|
|
|
190 |
|
✗ |
src = p->data[0]; |
191 |
|
✗ |
prev = c->prev; |
192 |
|
✗ |
if(chpal){ |
193 |
|
|
uint8_t tpal[3]; |
194 |
|
✗ |
for(i = 0; i < 256; i++){ |
195 |
|
✗ |
AV_WB24(tpal, palptr[i]); |
196 |
|
✗ |
c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0]; |
197 |
|
✗ |
c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1]; |
198 |
|
✗ |
c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2]; |
199 |
|
✗ |
c->pal[i * 3 + 0] = tpal[0]; |
200 |
|
✗ |
c->pal[i * 3 + 1] = tpal[1]; |
201 |
|
✗ |
c->pal[i * 3 + 2] = tpal[2]; |
202 |
|
|
} |
203 |
|
✗ |
memcpy(c->pal2, palptr, 1024); |
204 |
|
|
} |
205 |
|
✗ |
if(keyframe){ |
206 |
|
✗ |
if (palptr){ |
207 |
|
✗ |
for(i = 0; i < 256; i++){ |
208 |
|
✗ |
AV_WB24(c->pal+(i*3), palptr[i]); |
209 |
|
|
} |
210 |
|
✗ |
memcpy(c->work_buf, c->pal, 768); |
211 |
|
✗ |
memcpy(c->pal2, palptr, 1024); |
212 |
|
✗ |
work_size = 768; |
213 |
|
|
} |
214 |
|
✗ |
for(i = 0; i < avctx->height; i++){ |
215 |
|
✗ |
memcpy(c->work_buf + work_size, src, avctx->width * c->bypp); |
216 |
|
✗ |
src += p->linesize[0]; |
217 |
|
✗ |
work_size += avctx->width * c->bypp; |
218 |
|
|
} |
219 |
|
|
}else{ |
220 |
|
|
int x, y, bh2, bw2, xored; |
221 |
|
|
const uint8_t *tsrc, *tprev; |
222 |
|
|
uint8_t *mv; |
223 |
|
✗ |
int mx = 0, my = 0; |
224 |
|
|
|
225 |
|
✗ |
bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK; |
226 |
|
✗ |
bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK; |
227 |
|
✗ |
mv = c->work_buf + work_size; |
228 |
|
✗ |
memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3); |
229 |
|
✗ |
work_size += (bw * bh * 2 + 3) & ~3; |
230 |
|
|
/* for now just XOR'ing */ |
231 |
|
✗ |
for(y = 0; y < avctx->height; y += ZMBV_BLOCK) { |
232 |
|
✗ |
bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK); |
233 |
|
✗ |
for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) { |
234 |
|
✗ |
bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK); |
235 |
|
|
|
236 |
|
✗ |
tsrc = src + x * c->bypp; |
237 |
|
✗ |
tprev = prev + x * c->bypp; |
238 |
|
|
|
239 |
|
✗ |
zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored); |
240 |
|
✗ |
mv[0] = (mx * 2) | !!xored; |
241 |
|
✗ |
mv[1] = my * 2; |
242 |
|
✗ |
tprev += mx * c->bypp + my * c->pstride; |
243 |
|
✗ |
if(xored){ |
244 |
|
✗ |
for(j = 0; j < bh2; j++){ |
245 |
|
✗ |
for(i = 0; i < bw2 * c->bypp; i++) |
246 |
|
✗ |
c->work_buf[work_size++] = tsrc[i] ^ tprev[i]; |
247 |
|
✗ |
tsrc += p->linesize[0]; |
248 |
|
✗ |
tprev += c->pstride; |
249 |
|
|
} |
250 |
|
|
} |
251 |
|
|
} |
252 |
|
✗ |
src += p->linesize[0] * ZMBV_BLOCK; |
253 |
|
✗ |
prev += c->pstride * ZMBV_BLOCK; |
254 |
|
|
} |
255 |
|
|
} |
256 |
|
|
/* save the previous frame */ |
257 |
|
✗ |
src = p->data[0]; |
258 |
|
✗ |
prev = c->prev; |
259 |
|
✗ |
for(i = 0; i < avctx->height; i++){ |
260 |
|
✗ |
memcpy(prev, src, avctx->width * c->bypp); |
261 |
|
✗ |
prev += c->pstride; |
262 |
|
✗ |
src += p->linesize[0]; |
263 |
|
|
} |
264 |
|
|
|
265 |
|
✗ |
if (keyframe) |
266 |
|
✗ |
deflateReset(zstream); |
267 |
|
|
|
268 |
|
✗ |
zstream->next_in = c->work_buf; |
269 |
|
✗ |
zstream->avail_in = work_size; |
270 |
|
✗ |
zstream->total_in = 0; |
271 |
|
|
|
272 |
|
✗ |
zstream->next_out = c->comp_buf; |
273 |
|
✗ |
zstream->avail_out = c->comp_size; |
274 |
|
✗ |
zstream->total_out = 0; |
275 |
|
✗ |
if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) { |
276 |
|
✗ |
av_log(avctx, AV_LOG_ERROR, "Error compressing data\n"); |
277 |
|
✗ |
return -1; |
278 |
|
|
} |
279 |
|
|
|
280 |
|
✗ |
pkt_size = zstream->total_out + 1 + 6 * keyframe; |
281 |
|
✗ |
if ((ret = ff_get_encode_buffer(avctx, pkt, pkt_size, 0)) < 0) |
282 |
|
✗ |
return ret; |
283 |
|
✗ |
buf = pkt->data; |
284 |
|
|
|
285 |
|
✗ |
fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0); |
286 |
|
✗ |
*buf++ = fl; |
287 |
|
✗ |
if (keyframe) { |
288 |
|
✗ |
*buf++ = 0; // hi ver |
289 |
|
✗ |
*buf++ = 1; // lo ver |
290 |
|
✗ |
*buf++ = 1; // comp |
291 |
|
✗ |
*buf++ = c->fmt; // format |
292 |
|
✗ |
*buf++ = ZMBV_BLOCK; // block width |
293 |
|
✗ |
*buf++ = ZMBV_BLOCK; // block height |
294 |
|
✗ |
pkt->flags |= AV_PKT_FLAG_KEY; |
295 |
|
|
} |
296 |
|
✗ |
memcpy(buf, c->comp_buf, zstream->total_out); |
297 |
|
|
|
298 |
|
✗ |
*got_packet = 1; |
299 |
|
|
|
300 |
|
✗ |
return 0; |
301 |
|
|
} |
302 |
|
|
|
303 |
|
✗ |
static av_cold int encode_end(AVCodecContext *avctx) |
304 |
|
|
{ |
305 |
|
✗ |
ZmbvEncContext * const c = avctx->priv_data; |
306 |
|
|
|
307 |
|
✗ |
av_freep(&c->comp_buf); |
308 |
|
✗ |
av_freep(&c->work_buf); |
309 |
|
|
|
310 |
|
✗ |
av_freep(&c->prev_buf); |
311 |
|
✗ |
ff_deflate_end(&c->zstream); |
312 |
|
|
|
313 |
|
✗ |
return 0; |
314 |
|
|
} |
315 |
|
|
|
316 |
|
|
/** |
317 |
|
|
* Init zmbv encoder |
318 |
|
|
*/ |
319 |
|
✗ |
static av_cold int encode_init(AVCodecContext *avctx) |
320 |
|
|
{ |
321 |
|
✗ |
ZmbvEncContext * const c = avctx->priv_data; |
322 |
|
|
int i; |
323 |
|
✗ |
int lvl = 9; |
324 |
|
|
int prev_size, prev_offset; |
325 |
|
|
|
326 |
|
✗ |
switch (avctx->pix_fmt) { |
327 |
|
✗ |
case AV_PIX_FMT_PAL8: |
328 |
|
✗ |
c->fmt = ZMBV_FMT_8BPP; |
329 |
|
✗ |
c->bypp = 1; |
330 |
|
✗ |
break; |
331 |
|
✗ |
case AV_PIX_FMT_RGB555LE: |
332 |
|
✗ |
c->fmt = ZMBV_FMT_15BPP; |
333 |
|
✗ |
c->bypp = 2; |
334 |
|
✗ |
break; |
335 |
|
✗ |
case AV_PIX_FMT_RGB565LE: |
336 |
|
✗ |
c->fmt = ZMBV_FMT_16BPP; |
337 |
|
✗ |
c->bypp = 2; |
338 |
|
✗ |
break; |
339 |
|
|
#ifdef ZMBV_ENABLE_24BPP |
340 |
|
|
case AV_PIX_FMT_BGR24: |
341 |
|
|
c->fmt = ZMBV_FMT_24BPP; |
342 |
|
|
c->bypp = 3; |
343 |
|
|
break; |
344 |
|
|
#endif //ZMBV_ENABLE_24BPP |
345 |
|
✗ |
case AV_PIX_FMT_BGR0: |
346 |
|
✗ |
c->fmt = ZMBV_FMT_32BPP; |
347 |
|
✗ |
c->bypp = 4; |
348 |
|
✗ |
break; |
349 |
|
|
} |
350 |
|
|
|
351 |
|
|
/* Entropy-based score tables for comparing blocks. |
352 |
|
|
* Suitable for blocks up to (ZMBV_BLOCK * ZMBV_BLOCK) bytes. |
353 |
|
|
* Scores are nonnegative, lower is better. |
354 |
|
|
*/ |
355 |
|
✗ |
for(i = 1; i <= ZMBV_BLOCK * ZMBV_BLOCK * c->bypp; i++) |
356 |
|
✗ |
c->score_tab[i] = -i * log2(i / (double)(ZMBV_BLOCK * ZMBV_BLOCK * c->bypp)) * 256; |
357 |
|
|
|
358 |
|
✗ |
c->avctx = avctx; |
359 |
|
|
|
360 |
|
✗ |
c->curfrm = 0; |
361 |
|
✗ |
c->keyint = avctx->keyint_min; |
362 |
|
|
|
363 |
|
|
/* Motion estimation range: maximum distance is -64..63 */ |
364 |
|
✗ |
c->lrange = c->urange = 8; |
365 |
|
✗ |
if(avctx->me_range > 0){ |
366 |
|
✗ |
c->lrange = FFMIN(avctx->me_range, 64); |
367 |
|
✗ |
c->urange = FFMIN(avctx->me_range, 63); |
368 |
|
|
} |
369 |
|
|
|
370 |
|
✗ |
if(avctx->compression_level >= 0) |
371 |
|
✗ |
lvl = avctx->compression_level; |
372 |
|
✗ |
if(lvl < 0 || lvl > 9){ |
373 |
|
✗ |
av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl); |
374 |
|
✗ |
return AVERROR(EINVAL); |
375 |
|
|
} |
376 |
|
|
|
377 |
|
✗ |
c->comp_size = avctx->width * c->bypp * avctx->height + 1024 + |
378 |
|
✗ |
((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4; |
379 |
|
✗ |
if (!(c->work_buf = av_malloc(c->comp_size))) { |
380 |
|
✗ |
av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n"); |
381 |
|
✗ |
return AVERROR(ENOMEM); |
382 |
|
|
} |
383 |
|
|
/* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */ |
384 |
|
✗ |
c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) + |
385 |
|
✗ |
((c->comp_size + 63) >> 6) + 11; |
386 |
|
|
|
387 |
|
|
/* Allocate compression buffer */ |
388 |
|
✗ |
if (!(c->comp_buf = av_malloc(c->comp_size))) { |
389 |
|
✗ |
av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n"); |
390 |
|
✗ |
return AVERROR(ENOMEM); |
391 |
|
|
} |
392 |
|
|
|
393 |
|
|
/* Allocate prev buffer - pad around the image to allow out-of-edge ME: |
394 |
|
|
* - The image should be padded with `lrange` rows before and `urange` rows |
395 |
|
|
* after. |
396 |
|
|
* - The stride should be padded with `lrange` pixels, then rounded up to a |
397 |
|
|
* multiple of 16 bytes. |
398 |
|
|
* - The first row should also be padded with `lrange` pixels before, then |
399 |
|
|
* aligned up to a multiple of 16 bytes. |
400 |
|
|
*/ |
401 |
|
✗ |
c->pstride = FFALIGN((avctx->width + c->lrange) * c->bypp, 16); |
402 |
|
✗ |
prev_size = FFALIGN(c->lrange * c->bypp, 16) + c->pstride * (c->lrange + avctx->height + c->urange); |
403 |
|
✗ |
prev_offset = FFALIGN(c->lrange * c->bypp, 16) + c->pstride * c->lrange; |
404 |
|
✗ |
if (!(c->prev_buf = av_mallocz(prev_size))) { |
405 |
|
✗ |
av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n"); |
406 |
|
✗ |
return AVERROR(ENOMEM); |
407 |
|
|
} |
408 |
|
✗ |
c->prev = c->prev_buf + prev_offset; |
409 |
|
|
|
410 |
|
✗ |
return ff_deflate_init(&c->zstream, lvl, avctx); |
411 |
|
|
} |
412 |
|
|
|
413 |
|
|
const FFCodec ff_zmbv_encoder = { |
414 |
|
|
.p.name = "zmbv", |
415 |
|
|
CODEC_LONG_NAME("Zip Motion Blocks Video"), |
416 |
|
|
.p.type = AVMEDIA_TYPE_VIDEO, |
417 |
|
|
.p.id = AV_CODEC_ID_ZMBV, |
418 |
|
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, |
419 |
|
|
.priv_data_size = sizeof(ZmbvEncContext), |
420 |
|
|
.init = encode_init, |
421 |
|
|
FF_CODEC_ENCODE_CB(encode_frame), |
422 |
|
|
.close = encode_end, |
423 |
|
|
.p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8, |
424 |
|
|
AV_PIX_FMT_RGB555LE, |
425 |
|
|
AV_PIX_FMT_RGB565LE, |
426 |
|
|
#ifdef ZMBV_ENABLE_24BPP |
427 |
|
|
AV_PIX_FMT_BGR24, |
428 |
|
|
#endif //ZMBV_ENABLE_24BPP |
429 |
|
|
AV_PIX_FMT_BGR0, |
430 |
|
|
AV_PIX_FMT_NONE }, |
431 |
|
|
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP, |
432 |
|
|
}; |
433 |
|
|
|