2 * Zip Motion Blocks Video (ZMBV) encoder
3 * Copyright (c) 2006 Konstantin Shishkov
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
24 * Zip Motion Blocks Video encoder
30 #include "libavutil/common.h"
31 #include "libavutil/intreadwrite.h"
37 #define ZMBV_KEYFRAME 1
38 #define ZMBV_DELTAPAL 2
45 typedef struct ZmbvEncContext
{
46 AVCodecContext
*avctx
;
49 uint8_t *comp_buf
, *work_buf
;
51 uint32_t pal2
[256]; //for quick comparisons
59 static int score_tab
[256];
61 /** Block comparing function
62 * XXX should be optimized and moved to DSPContext
63 * TODO handle out of edge ME
65 static inline int block_cmp(uint8_t *src
, int stride
, uint8_t *src2
, int stride2
,
66 int bw
, int bh
, int *xored
)
70 uint8_t histogram
[256] = {0};
73 for(j
= 0; j
< bh
; j
++){
74 for(i
= 0; i
< bw
; i
++){
75 int t
= src
[i
] ^ src2
[i
];
83 for(i
= 1; i
< 256; i
++)
84 sum
+= score_tab
[histogram
[i
]];
89 /** Motion estimation function
90 * TODO make better ME decisions
92 static int zmbv_me(ZmbvEncContext
*c
, uint8_t *src
, int sstride
, uint8_t *prev
,
93 int pstride
, int x
, int y
, int *mx
, int *my
, int *xored
)
95 int dx
, dy
, tx
, ty
, tv
, bv
, bw
, bh
;
98 bw
= FFMIN(ZMBV_BLOCK
, c
->avctx
->width
- x
);
99 bh
= FFMIN(ZMBV_BLOCK
, c
->avctx
->height
- y
);
100 bv
= block_cmp(src
, sstride
, prev
, pstride
, bw
, bh
, xored
);
102 for(ty
= FFMAX(y
- c
->range
, 0); ty
< FFMIN(y
+ c
->range
, c
->avctx
->height
- bh
); ty
++){
103 for(tx
= FFMAX(x
- c
->range
, 0); tx
< FFMIN(x
+ c
->range
, c
->avctx
->width
- bw
); tx
++){
104 if(tx
== x
&& ty
== y
) continue; // we already tested this block
107 tv
= block_cmp(src
, sstride
, prev
+ dx
+ dy
*pstride
, pstride
, bw
, bh
, xored
);
119 static int encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
120 const AVFrame
*pict
, int *got_packet
)
122 ZmbvEncContext
* const c
= avctx
->priv_data
;
123 const AVFrame
* const p
= pict
;
124 uint8_t *src
, *prev
, *buf
;
128 int work_size
= 0, pkt_size
;
132 keyframe
= !c
->curfrm
;
134 if(c
->curfrm
== c
->keyint
)
136 avctx
->coded_frame
->pict_type
= keyframe
? AV_PICTURE_TYPE_I
: AV_PICTURE_TYPE_P
;
137 avctx
->coded_frame
->key_frame
= keyframe
;
138 chpal
= !keyframe
&& memcmp(p
->data
[1], c
->pal2
, 1024);
140 palptr
= (uint32_t*)p
->data
[1];
145 for(i
= 0; i
< 256; i
++){
146 AV_WB24(tpal
, palptr
[i
]);
147 c
->work_buf
[work_size
++] = tpal
[0] ^ c
->pal
[i
* 3 + 0];
148 c
->work_buf
[work_size
++] = tpal
[1] ^ c
->pal
[i
* 3 + 1];
149 c
->work_buf
[work_size
++] = tpal
[2] ^ c
->pal
[i
* 3 + 2];
150 c
->pal
[i
* 3 + 0] = tpal
[0];
151 c
->pal
[i
* 3 + 1] = tpal
[1];
152 c
->pal
[i
* 3 + 2] = tpal
[2];
154 memcpy(c
->pal2
, p
->data
[1], 1024);
157 for(i
= 0; i
< 256; i
++){
158 AV_WB24(c
->pal
+(i
*3), palptr
[i
]);
160 memcpy(c
->work_buf
, c
->pal
, 768);
161 memcpy(c
->pal2
, p
->data
[1], 1024);
163 for(i
= 0; i
< avctx
->height
; i
++){
164 memcpy(c
->work_buf
+ work_size
, src
, avctx
->width
);
165 src
+= p
->linesize
[0];
166 work_size
+= avctx
->width
;
169 int x
, y
, bh2
, bw2
, xored
;
170 uint8_t *tsrc
, *tprev
;
174 bw
= (avctx
->width
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
;
175 bh
= (avctx
->height
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
;
176 mv
= c
->work_buf
+ work_size
;
177 memset(c
->work_buf
+ work_size
, 0, (bw
* bh
* 2 + 3) & ~3);
178 work_size
+= (bw
* bh
* 2 + 3) & ~3;
179 /* for now just XOR'ing */
180 for(y
= 0; y
< avctx
->height
; y
+= ZMBV_BLOCK
) {
181 bh2
= FFMIN(avctx
->height
- y
, ZMBV_BLOCK
);
182 for(x
= 0; x
< avctx
->width
; x
+= ZMBV_BLOCK
, mv
+= 2) {
183 bw2
= FFMIN(avctx
->width
- x
, ZMBV_BLOCK
);
188 zmbv_me(c
, tsrc
, p
->linesize
[0], tprev
, c
->pstride
, x
, y
, &mx
, &my
, &xored
);
189 mv
[0] = (mx
<< 1) | !!xored
;
191 tprev
+= mx
+ my
* c
->pstride
;
193 for(j
= 0; j
< bh2
; j
++){
194 for(i
= 0; i
< bw2
; i
++)
195 c
->work_buf
[work_size
++] = tsrc
[i
] ^ tprev
[i
];
196 tsrc
+= p
->linesize
[0];
201 src
+= p
->linesize
[0] * ZMBV_BLOCK
;
202 prev
+= c
->pstride
* ZMBV_BLOCK
;
205 /* save the previous frame */
208 for(i
= 0; i
< avctx
->height
; i
++){
209 memcpy(prev
, src
, avctx
->width
);
211 src
+= p
->linesize
[0];
215 deflateReset(&c
->zstream
);
217 c
->zstream
.next_in
= c
->work_buf
;
218 c
->zstream
.avail_in
= work_size
;
219 c
->zstream
.total_in
= 0;
221 c
->zstream
.next_out
= c
->comp_buf
;
222 c
->zstream
.avail_out
= c
->comp_size
;
223 c
->zstream
.total_out
= 0;
224 if(deflate(&c
->zstream
, Z_SYNC_FLUSH
) != Z_OK
){
225 av_log(avctx
, AV_LOG_ERROR
, "Error compressing data\n");
229 pkt_size
= c
->zstream
.total_out
+ 1 + 6*keyframe
;
230 if ((ret
= ff_alloc_packet2(avctx
, pkt
, pkt_size
)) < 0)
234 fl
= (keyframe
? ZMBV_KEYFRAME
: 0) | (chpal
? ZMBV_DELTAPAL
: 0);
237 *buf
++ = 0; // hi ver
238 *buf
++ = 1; // lo ver
240 *buf
++ = 4; // format - 8bpp
241 *buf
++ = ZMBV_BLOCK
; // block width
242 *buf
++ = ZMBV_BLOCK
; // block height
244 memcpy(buf
, c
->comp_buf
, c
->zstream
.total_out
);
246 pkt
->flags
|= AV_PKT_FLAG_KEY
*keyframe
;
252 static av_cold
int encode_end(AVCodecContext
*avctx
)
254 ZmbvEncContext
* const c
= avctx
->priv_data
;
256 av_freep(&c
->comp_buf
);
257 av_freep(&c
->work_buf
);
259 deflateEnd(&c
->zstream
);
262 av_frame_free(&avctx
->coded_frame
);
270 static av_cold
int encode_init(AVCodecContext
*avctx
)
272 ZmbvEncContext
* const c
= avctx
->priv_data
;
273 int zret
; // Zlib return code
278 score_tab
[i
]= -i
* log(i
/(double)(ZMBV_BLOCK
*ZMBV_BLOCK
)) * (256/M_LN2
);
283 c
->keyint
= avctx
->keyint_min
;
285 if(avctx
->me_range
> 0)
286 c
->range
= FFMIN(avctx
->me_range
, 127);
288 if(avctx
->compression_level
>= 0)
289 lvl
= avctx
->compression_level
;
290 if(lvl
< 0 || lvl
> 9){
291 av_log(avctx
, AV_LOG_ERROR
, "Compression level should be 0-9, not %i\n", lvl
);
292 return AVERROR(EINVAL
);
295 // Needed if zlib unused or init aborted before deflateInit
296 memset(&c
->zstream
, 0, sizeof(z_stream
));
297 c
->comp_size
= avctx
->width
* avctx
->height
+ 1024 +
298 ((avctx
->width
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
) * ((avctx
->height
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
) * 2 + 4;
299 if (!(c
->work_buf
= av_malloc(c
->comp_size
))) {
300 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate work buffer.\n");
301 return AVERROR(ENOMEM
);
303 /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
304 c
->comp_size
= c
->comp_size
+ ((c
->comp_size
+ 7) >> 3) +
305 ((c
->comp_size
+ 63) >> 6) + 11;
307 /* Allocate compression buffer */
308 if (!(c
->comp_buf
= av_malloc(c
->comp_size
))) {
309 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate compression buffer.\n");
310 return AVERROR(ENOMEM
);
312 c
->pstride
= FFALIGN(avctx
->width
, 16);
313 if (!(c
->prev
= av_malloc(c
->pstride
* avctx
->height
))) {
314 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate picture.\n");
315 return AVERROR(ENOMEM
);
318 c
->zstream
.zalloc
= Z_NULL
;
319 c
->zstream
.zfree
= Z_NULL
;
320 c
->zstream
.opaque
= Z_NULL
;
321 zret
= deflateInit(&c
->zstream
, lvl
);
323 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
327 avctx
->coded_frame
= av_frame_alloc();
328 if (!avctx
->coded_frame
) {
330 return AVERROR(ENOMEM
);
336 AVCodec ff_zmbv_encoder
= {
338 .long_name
= NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
339 .type
= AVMEDIA_TYPE_VIDEO
,
340 .id
= AV_CODEC_ID_ZMBV
,
341 .priv_data_size
= sizeof(ZmbvEncContext
),
343 .encode2
= encode_frame
,
345 .pix_fmts
= (const enum AVPixelFormat
[]){ AV_PIX_FMT_PAL8
, AV_PIX_FMT_NONE
},