2 * Zip Motion Blocks Video (ZMBV) encoder
3 * Copyright (c) 2006 Konstantin Shishkov
5 * This file is part of Libav.
7 * Libav 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 * Libav 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 Libav; 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
;
50 uint8_t *comp_buf
, *work_buf
;
52 uint32_t pal2
[256]; //for quick comparisons
60 static int score_tab
[256];
62 /** Block comparing function
63 * XXX should be optimized and moved to DSPContext
64 * TODO handle out of edge ME
66 static inline int block_cmp(uint8_t *src
, int stride
, uint8_t *src2
, int stride2
,
67 int bw
, int bh
, int *xored
)
71 uint8_t histogram
[256] = {0};
74 for(j
= 0; j
< bh
; j
++){
75 for(i
= 0; i
< bw
; i
++){
76 int t
= src
[i
] ^ src2
[i
];
84 for(i
= 1; i
< 256; i
++)
85 sum
+= score_tab
[histogram
[i
]];
90 /** Motion estimation function
91 * TODO make better ME decisions
93 static int zmbv_me(ZmbvEncContext
*c
, uint8_t *src
, int sstride
, uint8_t *prev
,
94 int pstride
, int x
, int y
, int *mx
, int *my
, int *xored
)
96 int dx
, dy
, tx
, ty
, tv
, bv
, bw
, bh
;
99 bw
= FFMIN(ZMBV_BLOCK
, c
->avctx
->width
- x
);
100 bh
= FFMIN(ZMBV_BLOCK
, c
->avctx
->height
- y
);
101 bv
= block_cmp(src
, sstride
, prev
, pstride
, bw
, bh
, xored
);
103 for(ty
= FFMAX(y
- c
->range
, 0); ty
< FFMIN(y
+ c
->range
, c
->avctx
->height
- bh
); ty
++){
104 for(tx
= FFMAX(x
- c
->range
, 0); tx
< FFMIN(x
+ c
->range
, c
->avctx
->width
- bw
); tx
++){
105 if(tx
== x
&& ty
== y
) continue; // we already tested this block
108 tv
= block_cmp(src
, sstride
, prev
+ dx
+ dy
*pstride
, pstride
, bw
, bh
, xored
);
120 static int encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
121 const AVFrame
*pict
, int *got_packet
)
123 ZmbvEncContext
* const c
= avctx
->priv_data
;
124 AVFrame
* const p
= &c
->pic
;
125 uint8_t *src
, *prev
, *buf
;
129 int work_size
= 0, pkt_size
;
133 keyframe
= !c
->curfrm
;
135 if(c
->curfrm
== c
->keyint
)
138 p
->pict_type
= keyframe
? AV_PICTURE_TYPE_I
: AV_PICTURE_TYPE_P
;
139 p
->key_frame
= keyframe
;
140 chpal
= !keyframe
&& memcmp(p
->data
[1], c
->pal2
, 1024);
142 palptr
= (uint32_t*)p
->data
[1];
147 for(i
= 0; i
< 256; i
++){
148 AV_WB24(tpal
, palptr
[i
]);
149 c
->work_buf
[work_size
++] = tpal
[0] ^ c
->pal
[i
* 3 + 0];
150 c
->work_buf
[work_size
++] = tpal
[1] ^ c
->pal
[i
* 3 + 1];
151 c
->work_buf
[work_size
++] = tpal
[2] ^ c
->pal
[i
* 3 + 2];
152 c
->pal
[i
* 3 + 0] = tpal
[0];
153 c
->pal
[i
* 3 + 1] = tpal
[1];
154 c
->pal
[i
* 3 + 2] = tpal
[2];
156 memcpy(c
->pal2
, p
->data
[1], 1024);
159 for(i
= 0; i
< 256; i
++){
160 AV_WB24(c
->pal
+(i
*3), palptr
[i
]);
162 memcpy(c
->work_buf
, c
->pal
, 768);
163 memcpy(c
->pal2
, p
->data
[1], 1024);
165 for(i
= 0; i
< avctx
->height
; i
++){
166 memcpy(c
->work_buf
+ work_size
, src
, avctx
->width
);
167 src
+= p
->linesize
[0];
168 work_size
+= avctx
->width
;
171 int x
, y
, bh2
, bw2
, xored
;
172 uint8_t *tsrc
, *tprev
;
176 bw
= (avctx
->width
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
;
177 bh
= (avctx
->height
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
;
178 mv
= c
->work_buf
+ work_size
;
179 memset(c
->work_buf
+ work_size
, 0, (bw
* bh
* 2 + 3) & ~3);
180 work_size
+= (bw
* bh
* 2 + 3) & ~3;
181 /* for now just XOR'ing */
182 for(y
= 0; y
< avctx
->height
; y
+= ZMBV_BLOCK
) {
183 bh2
= FFMIN(avctx
->height
- y
, ZMBV_BLOCK
);
184 for(x
= 0; x
< avctx
->width
; x
+= ZMBV_BLOCK
, mv
+= 2) {
185 bw2
= FFMIN(avctx
->width
- x
, ZMBV_BLOCK
);
190 zmbv_me(c
, tsrc
, p
->linesize
[0], tprev
, c
->pstride
, x
, y
, &mx
, &my
, &xored
);
191 mv
[0] = (mx
<< 1) | !!xored
;
193 tprev
+= mx
+ my
* c
->pstride
;
195 for(j
= 0; j
< bh2
; j
++){
196 for(i
= 0; i
< bw2
; i
++)
197 c
->work_buf
[work_size
++] = tsrc
[i
] ^ tprev
[i
];
198 tsrc
+= p
->linesize
[0];
203 src
+= p
->linesize
[0] * ZMBV_BLOCK
;
204 prev
+= c
->pstride
* ZMBV_BLOCK
;
207 /* save the previous frame */
210 for(i
= 0; i
< avctx
->height
; i
++){
211 memcpy(prev
, src
, avctx
->width
);
213 src
+= p
->linesize
[0];
217 deflateReset(&c
->zstream
);
219 c
->zstream
.next_in
= c
->work_buf
;
220 c
->zstream
.avail_in
= work_size
;
221 c
->zstream
.total_in
= 0;
223 c
->zstream
.next_out
= c
->comp_buf
;
224 c
->zstream
.avail_out
= c
->comp_size
;
225 c
->zstream
.total_out
= 0;
226 if(deflate(&c
->zstream
, Z_SYNC_FLUSH
) != Z_OK
){
227 av_log(avctx
, AV_LOG_ERROR
, "Error compressing data\n");
231 pkt_size
= c
->zstream
.total_out
+ 1 + 6*keyframe
;
232 if ((ret
= ff_alloc_packet(pkt
, pkt_size
)) < 0) {
233 av_log(avctx
, AV_LOG_ERROR
, "Error getting packet of size %d.\n", pkt_size
);
238 fl
= (keyframe
? ZMBV_KEYFRAME
: 0) | (chpal
? ZMBV_DELTAPAL
: 0);
241 *buf
++ = 0; // hi ver
242 *buf
++ = 1; // lo ver
244 *buf
++ = 4; // format - 8bpp
245 *buf
++ = ZMBV_BLOCK
; // block width
246 *buf
++ = ZMBV_BLOCK
; // block height
248 memcpy(buf
, c
->comp_buf
, c
->zstream
.total_out
);
250 pkt
->flags
|= AV_PKT_FLAG_KEY
*keyframe
;
260 static av_cold
int encode_init(AVCodecContext
*avctx
)
262 ZmbvEncContext
* const c
= avctx
->priv_data
;
263 int zret
; // Zlib return code
268 score_tab
[i
]= -i
* log(i
/(double)(ZMBV_BLOCK
*ZMBV_BLOCK
)) * (256/M_LN2
);
273 c
->keyint
= avctx
->keyint_min
;
275 if(avctx
->me_range
> 0)
276 c
->range
= FFMIN(avctx
->me_range
, 127);
278 if(avctx
->compression_level
>= 0)
279 lvl
= avctx
->compression_level
;
280 if(lvl
< 0 || lvl
> 9){
281 av_log(avctx
, AV_LOG_ERROR
, "Compression level should be 0-9, not %i\n", lvl
);
282 return AVERROR(EINVAL
);
285 // Needed if zlib unused or init aborted before deflateInit
286 memset(&c
->zstream
, 0, sizeof(z_stream
));
287 c
->comp_size
= avctx
->width
* avctx
->height
+ 1024 +
288 ((avctx
->width
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
) * ((avctx
->height
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
) * 2 + 4;
289 if ((c
->work_buf
= av_malloc(c
->comp_size
)) == NULL
) {
290 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate work buffer.\n");
291 return AVERROR(ENOMEM
);
293 /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
294 c
->comp_size
= c
->comp_size
+ ((c
->comp_size
+ 7) >> 3) +
295 ((c
->comp_size
+ 63) >> 6) + 11;
297 /* Allocate compression buffer */
298 if ((c
->comp_buf
= av_malloc(c
->comp_size
)) == NULL
) {
299 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate compression buffer.\n");
300 return AVERROR(ENOMEM
);
302 c
->pstride
= FFALIGN(avctx
->width
, 16);
303 if ((c
->prev
= av_malloc(c
->pstride
* avctx
->height
)) == NULL
) {
304 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate picture.\n");
305 return AVERROR(ENOMEM
);
308 c
->zstream
.zalloc
= Z_NULL
;
309 c
->zstream
.zfree
= Z_NULL
;
310 c
->zstream
.opaque
= Z_NULL
;
311 zret
= deflateInit(&c
->zstream
, lvl
);
313 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
317 avctx
->coded_frame
= &c
->pic
;
325 * Uninit zmbv encoder
327 static av_cold
int encode_end(AVCodecContext
*avctx
)
329 ZmbvEncContext
* const c
= avctx
->priv_data
;
331 av_freep(&c
->comp_buf
);
332 av_freep(&c
->work_buf
);
334 deflateEnd(&c
->zstream
);
340 AVCodec ff_zmbv_encoder
= {
342 .type
= AVMEDIA_TYPE_VIDEO
,
343 .id
= AV_CODEC_ID_ZMBV
,
344 .priv_data_size
= sizeof(ZmbvEncContext
),
346 .encode2
= encode_frame
,
348 .pix_fmts
= (const enum AVPixelFormat
[]){ AV_PIX_FMT_PAL8
, AV_PIX_FMT_NONE
},
349 .long_name
= NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),