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
23 * @file libavcodec/zmbvenc.c
24 * Zip Motion Blocks Video encoder
30 #include "libavutil/intreadwrite.h"
35 #define ZMBV_KEYFRAME 1
36 #define ZMBV_DELTAPAL 2
43 typedef struct ZmbvEncContext
{
44 AVCodecContext
*avctx
;
48 uint8_t *comp_buf
, *work_buf
;
50 uint32_t pal2
[256]; //for quick comparisons
58 static int score_tab
[256];
60 /** Block comparing function
61 * XXX should be optimized and moved to DSPContext
62 * TODO handle out of edge ME
64 static inline int block_cmp(uint8_t *src
, int stride
, uint8_t *src2
, int stride2
, int bw
, int bh
)
68 uint8_t histogram
[256]={0};
70 for(j
= 0; j
< bh
; j
++){
71 for(i
= 0; i
< bw
; i
++)
72 histogram
[src
[i
] ^ src2
[i
]]++;
78 sum
+= score_tab
[histogram
[i
]];
83 /** Motion estimation function
84 * TODO make better ME decisions
86 static int zmbv_me(ZmbvEncContext
*c
, uint8_t *src
, int sstride
, uint8_t *prev
, int pstride
,
87 int x
, int y
, int *mx
, int *my
)
89 int dx
, dy
, tx
, ty
, tv
, bv
, bw
, bh
;
92 bw
= FFMIN(ZMBV_BLOCK
, c
->avctx
->width
- x
);
93 bh
= FFMIN(ZMBV_BLOCK
, c
->avctx
->height
- y
);
94 bv
= block_cmp(src
, sstride
, prev
, pstride
, bw
, bh
);
96 for(ty
= FFMAX(y
- c
->range
, 0); ty
< FFMIN(y
+ c
->range
, c
->avctx
->height
- bh
); ty
++){
97 for(tx
= FFMAX(x
- c
->range
, 0); tx
< FFMIN(x
+ c
->range
, c
->avctx
->width
- bw
); tx
++){
98 if(tx
== x
&& ty
== y
) continue; // we already tested this block
101 tv
= block_cmp(src
, sstride
, prev
+ dx
+ dy
*pstride
, pstride
, bw
, bh
);
113 static int encode_frame(AVCodecContext
*avctx
, uint8_t *buf
, int buf_size
, void *data
)
115 ZmbvEncContext
* const c
= avctx
->priv_data
;
116 AVFrame
*pict
= data
;
117 AVFrame
* const p
= &c
->pic
;
127 keyframe
= !c
->curfrm
;
129 if(c
->curfrm
== c
->keyint
)
132 p
->pict_type
= keyframe
? FF_I_TYPE
: FF_P_TYPE
;
133 p
->key_frame
= keyframe
;
134 chpal
= !keyframe
&& memcmp(p
->data
[1], c
->pal2
, 1024);
136 fl
= (keyframe
? ZMBV_KEYFRAME
: 0) | (chpal
? ZMBV_DELTAPAL
: 0);
139 deflateReset(&c
->zstream
);
140 *buf
++ = 0; len
++; // hi ver
141 *buf
++ = 1; len
++; // lo ver
142 *buf
++ = 1; len
++; // comp
143 *buf
++ = 4; len
++; // format - 8bpp
144 *buf
++ = ZMBV_BLOCK
; len
++; // block width
145 *buf
++ = ZMBV_BLOCK
; len
++; // block height
147 palptr
= (uint32_t*)p
->data
[1];
152 for(i
= 0; i
< 256; i
++){
153 AV_WB24(tpal
, palptr
[i
]);
154 c
->work_buf
[work_size
++] = tpal
[0] ^ c
->pal
[i
* 3 + 0];
155 c
->work_buf
[work_size
++] = tpal
[1] ^ c
->pal
[i
* 3 + 1];
156 c
->work_buf
[work_size
++] = tpal
[2] ^ c
->pal
[i
* 3 + 2];
157 c
->pal
[i
* 3 + 0] = tpal
[0];
158 c
->pal
[i
* 3 + 1] = tpal
[1];
159 c
->pal
[i
* 3 + 2] = tpal
[2];
161 memcpy(c
->pal2
, p
->data
[1], 1024);
164 for(i
= 0; i
< 256; i
++){
165 AV_WB24(c
->pal
+(i
*3), palptr
[i
]);
167 memcpy(c
->work_buf
, c
->pal
, 768);
168 memcpy(c
->pal2
, p
->data
[1], 1024);
170 for(i
= 0; i
< avctx
->height
; i
++){
171 memcpy(c
->work_buf
+ work_size
, src
, avctx
->width
);
172 src
+= p
->linesize
[0];
173 work_size
+= avctx
->width
;
177 uint8_t *tsrc
, *tprev
;
181 bw
= (avctx
->width
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
;
182 bh
= (avctx
->height
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
;
183 mv
= c
->work_buf
+ work_size
;
184 memset(c
->work_buf
+ work_size
, 0, (bw
* bh
* 2 + 3) & ~3);
185 work_size
+= (bw
* bh
* 2 + 3) & ~3;
186 /* for now just XOR'ing */
187 for(y
= 0; y
< avctx
->height
; y
+= ZMBV_BLOCK
) {
188 bh2
= FFMIN(avctx
->height
- y
, ZMBV_BLOCK
);
189 for(x
= 0; x
< avctx
->width
; x
+= ZMBV_BLOCK
, mv
+= 2) {
190 bw2
= FFMIN(avctx
->width
- x
, ZMBV_BLOCK
);
195 bv
= zmbv_me(c
, tsrc
, p
->linesize
[0], tprev
, c
->pstride
, x
, y
, &mx
, &my
);
196 mv
[0] = (mx
<< 1) | !!bv
;
198 tprev
+= mx
+ my
* c
->pstride
;
200 for(j
= 0; j
< bh2
; j
++){
201 for(i
= 0; i
< bw2
; i
++)
202 c
->work_buf
[work_size
++] = tsrc
[i
] ^ tprev
[i
];
203 tsrc
+= p
->linesize
[0];
208 src
+= p
->linesize
[0] * ZMBV_BLOCK
;
209 prev
+= c
->pstride
* ZMBV_BLOCK
;
212 /* save the previous frame */
215 for(i
= 0; i
< avctx
->height
; i
++){
216 memcpy(prev
, src
, avctx
->width
);
218 src
+= p
->linesize
[0];
221 c
->zstream
.next_in
= c
->work_buf
;
222 c
->zstream
.avail_in
= work_size
;
223 c
->zstream
.total_in
= 0;
225 c
->zstream
.next_out
= c
->comp_buf
;
226 c
->zstream
.avail_out
= c
->comp_size
;
227 c
->zstream
.total_out
= 0;
228 if(deflate(&c
->zstream
, Z_SYNC_FLUSH
) != Z_OK
){
229 av_log(avctx
, AV_LOG_ERROR
, "Error compressing data\n");
233 memcpy(buf
, c
->comp_buf
, c
->zstream
.total_out
);
234 return len
+ c
->zstream
.total_out
;
241 static av_cold
int encode_init(AVCodecContext
*avctx
)
243 ZmbvEncContext
* const c
= avctx
->priv_data
;
244 int zret
; // Zlib return code
249 score_tab
[i
]= -i
* log(i
/(double)(ZMBV_BLOCK
*ZMBV_BLOCK
)) * (256/M_LN2
);
254 c
->keyint
= avctx
->keyint_min
;
256 if(avctx
->me_range
> 0)
257 c
->range
= FFMIN(avctx
->me_range
, 127);
259 if(avctx
->compression_level
>= 0)
260 lvl
= avctx
->compression_level
;
261 if(lvl
< 0 || lvl
> 9){
262 av_log(avctx
, AV_LOG_ERROR
, "Compression level should be 0-9, not %i\n", lvl
);
266 // Needed if zlib unused or init aborted before deflateInit
267 memset(&(c
->zstream
), 0, sizeof(z_stream
));
268 c
->comp_size
= avctx
->width
* avctx
->height
+ 1024 +
269 ((avctx
->width
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
) * ((avctx
->height
+ ZMBV_BLOCK
- 1) / ZMBV_BLOCK
) * 2 + 4;
270 if ((c
->work_buf
= av_malloc(c
->comp_size
)) == NULL
) {
271 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate work buffer.\n");
274 /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
275 c
->comp_size
= c
->comp_size
+ ((c
->comp_size
+ 7) >> 3) +
276 ((c
->comp_size
+ 63) >> 6) + 11;
278 /* Allocate compression buffer */
279 if ((c
->comp_buf
= av_malloc(c
->comp_size
)) == NULL
) {
280 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate compression buffer.\n");
283 c
->pstride
= FFALIGN(avctx
->width
, 16);
284 if ((c
->prev
= av_malloc(c
->pstride
* avctx
->height
)) == NULL
) {
285 av_log(avctx
, AV_LOG_ERROR
, "Can't allocate picture.\n");
289 c
->zstream
.zalloc
= Z_NULL
;
290 c
->zstream
.zfree
= Z_NULL
;
291 c
->zstream
.opaque
= Z_NULL
;
292 zret
= deflateInit(&(c
->zstream
), lvl
);
294 av_log(avctx
, AV_LOG_ERROR
, "Inflate init error: %d\n", zret
);
298 avctx
->coded_frame
= (AVFrame
*)&c
->pic
;
306 * Uninit zmbv encoder
308 static av_cold
int encode_end(AVCodecContext
*avctx
)
310 ZmbvEncContext
* const c
= avctx
->priv_data
;
312 av_freep(&c
->comp_buf
);
313 av_freep(&c
->work_buf
);
315 deflateEnd(&(c
->zstream
));
321 AVCodec zmbv_encoder
= {
325 sizeof(ZmbvEncContext
),
329 .pix_fmts
= (const enum PixelFormat
[]){PIX_FMT_PAL8
, PIX_FMT_NONE
},
330 .long_name
= NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),