zmbvenc.c
Go to the documentation of this file.
1 /*
2  * Zip Motion Blocks Video (ZMBV) encoder
3  * Copyright (c) 2006 Konstantin Shishkov
4  *
5  * This file is part of Libav.
6  *
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.
11  *
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.
16  *
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
20  */
21 
27 #include <stdio.h>
28 #include <stdlib.h>
29 
30 #include "libavutil/intreadwrite.h"
31 #include "avcodec.h"
32 
33 #include <zlib.h>
34 
35 #define ZMBV_KEYFRAME 1
36 #define ZMBV_DELTAPAL 2
37 
38 #define ZMBV_BLOCK 16
39 
43 typedef struct ZmbvEncContext {
46 
47  int range;
48  uint8_t *comp_buf, *work_buf;
49  uint8_t pal[768];
50  uint32_t pal2[256]; //for quick comparisons
51  uint8_t *prev;
52  int pstride;
53  int comp_size;
54  int keyint, curfrm;
55  z_stream zstream;
57 
58 static int score_tab[256];
59 
64 static inline int block_cmp(uint8_t *src, int stride, uint8_t *src2, int stride2,
65  int bw, int bh, int *xored)
66 {
67  int sum = 0;
68  int i, j;
69  uint8_t histogram[256] = {0};
70 
71  *xored = 0;
72  for(j = 0; j < bh; j++){
73  for(i = 0; i < bw; i++){
74  int t = src[i] ^ src2[i];
75  histogram[t]++;
76  *xored |= t;
77  }
78  src += stride;
79  src2 += stride2;
80  }
81 
82  for(i = 1; i < 256; i++)
83  sum += score_tab[histogram[i]];
84 
85  return sum;
86 }
87 
91 static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev,
92  int pstride, int x, int y, int *mx, int *my, int *xored)
93 {
94  int dx, dy, tx, ty, tv, bv, bw, bh;
95 
96  *mx = *my = 0;
97  bw = FFMIN(ZMBV_BLOCK, c->avctx->width - x);
98  bh = FFMIN(ZMBV_BLOCK, c->avctx->height - y);
99  bv = block_cmp(src, sstride, prev, pstride, bw, bh, xored);
100  if(!bv) return 0;
101  for(ty = FFMAX(y - c->range, 0); ty < FFMIN(y + c->range, c->avctx->height - bh); ty++){
102  for(tx = FFMAX(x - c->range, 0); tx < FFMIN(x + c->range, c->avctx->width - bw); tx++){
103  if(tx == x && ty == y) continue; // we already tested this block
104  dx = tx - x;
105  dy = ty - y;
106  tv = block_cmp(src, sstride, prev + dx + dy*pstride, pstride, bw, bh, xored);
107  if(tv < bv){
108  bv = tv;
109  *mx = dx;
110  *my = dy;
111  if(!bv) return 0;
112  }
113  }
114  }
115  return bv;
116 }
117 
118 static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
119 {
120  ZmbvEncContext * const c = avctx->priv_data;
121  AVFrame *pict = data;
122  AVFrame * const p = &c->pic;
123  uint8_t *src, *prev;
124  uint32_t *palptr;
125  int len = 0;
126  int keyframe, chpal;
127  int fl;
128  int work_size = 0;
129  int bw, bh;
130  int i, j;
131 
132  keyframe = !c->curfrm;
133  c->curfrm++;
134  if(c->curfrm == c->keyint)
135  c->curfrm = 0;
136  *p = *pict;
138  p->key_frame= keyframe;
139  chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024);
140 
141  fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0);
142  *buf++ = fl; len++;
143  if(keyframe){
144  deflateReset(&c->zstream);
145  *buf++ = 0; len++; // hi ver
146  *buf++ = 1; len++; // lo ver
147  *buf++ = 1; len++; // comp
148  *buf++ = 4; len++; // format - 8bpp
149  *buf++ = ZMBV_BLOCK; len++; // block width
150  *buf++ = ZMBV_BLOCK; len++; // block height
151  }
152  palptr = (uint32_t*)p->data[1];
153  src = p->data[0];
154  prev = c->prev;
155  if(chpal){
156  uint8_t tpal[3];
157  for(i = 0; i < 256; i++){
158  AV_WB24(tpal, palptr[i]);
159  c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0];
160  c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1];
161  c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2];
162  c->pal[i * 3 + 0] = tpal[0];
163  c->pal[i * 3 + 1] = tpal[1];
164  c->pal[i * 3 + 2] = tpal[2];
165  }
166  memcpy(c->pal2, p->data[1], 1024);
167  }
168  if(keyframe){
169  for(i = 0; i < 256; i++){
170  AV_WB24(c->pal+(i*3), palptr[i]);
171  }
172  memcpy(c->work_buf, c->pal, 768);
173  memcpy(c->pal2, p->data[1], 1024);
174  work_size = 768;
175  for(i = 0; i < avctx->height; i++){
176  memcpy(c->work_buf + work_size, src, avctx->width);
177  src += p->linesize[0];
178  work_size += avctx->width;
179  }
180  }else{
181  int x, y, bh2, bw2, xored;
182  uint8_t *tsrc, *tprev;
183  uint8_t *mv;
184  int mx, my;
185 
186  bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
187  bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
188  mv = c->work_buf + work_size;
189  memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3);
190  work_size += (bw * bh * 2 + 3) & ~3;
191  /* for now just XOR'ing */
192  for(y = 0; y < avctx->height; y += ZMBV_BLOCK) {
193  bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK);
194  for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) {
195  bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK);
196 
197  tsrc = src + x;
198  tprev = prev + x;
199 
200  zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored);
201  mv[0] = (mx << 1) | !!xored;
202  mv[1] = my << 1;
203  tprev += mx + my * c->pstride;
204  if(xored){
205  for(j = 0; j < bh2; j++){
206  for(i = 0; i < bw2; i++)
207  c->work_buf[work_size++] = tsrc[i] ^ tprev[i];
208  tsrc += p->linesize[0];
209  tprev += c->pstride;
210  }
211  }
212  }
213  src += p->linesize[0] * ZMBV_BLOCK;
214  prev += c->pstride * ZMBV_BLOCK;
215  }
216  }
217  /* save the previous frame */
218  src = p->data[0];
219  prev = c->prev;
220  for(i = 0; i < avctx->height; i++){
221  memcpy(prev, src, avctx->width);
222  prev += c->pstride;
223  src += p->linesize[0];
224  }
225 
226  c->zstream.next_in = c->work_buf;
227  c->zstream.avail_in = work_size;
228  c->zstream.total_in = 0;
229 
230  c->zstream.next_out = c->comp_buf;
231  c->zstream.avail_out = c->comp_size;
232  c->zstream.total_out = 0;
233  if(deflate(&c->zstream, Z_SYNC_FLUSH) != Z_OK){
234  av_log(avctx, AV_LOG_ERROR, "Error compressing data\n");
235  return -1;
236  }
237 
238  memcpy(buf, c->comp_buf, c->zstream.total_out);
239  return len + c->zstream.total_out;
240 }
241 
242 
247 {
248  ZmbvEncContext * const c = avctx->priv_data;
249  int zret; // Zlib return code
250  int i;
251  int lvl = 9;
252 
253  for(i=1; i<256; i++)
254  score_tab[i]= -i * log(i/(double)(ZMBV_BLOCK*ZMBV_BLOCK)) * (256/M_LN2);
255 
256  c->avctx = avctx;
257 
258  c->curfrm = 0;
259  c->keyint = avctx->keyint_min;
260  c->range = 8;
261  if(avctx->me_range > 0)
262  c->range = FFMIN(avctx->me_range, 127);
263 
264  if(avctx->compression_level >= 0)
265  lvl = avctx->compression_level;
266  if(lvl < 0 || lvl > 9){
267  av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl);
268  return -1;
269  }
270 
271  // Needed if zlib unused or init aborted before deflateInit
272  memset(&c->zstream, 0, sizeof(z_stream));
273  c->comp_size = avctx->width * avctx->height + 1024 +
274  ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4;
275  if ((c->work_buf = av_malloc(c->comp_size)) == NULL) {
276  av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n");
277  return -1;
278  }
279  /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
280  c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) +
281  ((c->comp_size + 63) >> 6) + 11;
282 
283  /* Allocate compression buffer */
284  if ((c->comp_buf = av_malloc(c->comp_size)) == NULL) {
285  av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n");
286  return -1;
287  }
288  c->pstride = FFALIGN(avctx->width, 16);
289  if ((c->prev = av_malloc(c->pstride * avctx->height)) == NULL) {
290  av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n");
291  return -1;
292  }
293 
294  c->zstream.zalloc = Z_NULL;
295  c->zstream.zfree = Z_NULL;
296  c->zstream.opaque = Z_NULL;
297  zret = deflateInit(&c->zstream, lvl);
298  if (zret != Z_OK) {
299  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
300  return -1;
301  }
302 
303  avctx->coded_frame = (AVFrame*)&c->pic;
304 
305  return 0;
306 }
307 
308 
309 
314 {
315  ZmbvEncContext * const c = avctx->priv_data;
316 
317  av_freep(&c->comp_buf);
318  av_freep(&c->work_buf);
319 
320  deflateEnd(&c->zstream);
321  av_freep(&c->prev);
322 
323  return 0;
324 }
325 
327  .name = "zmbv",
328  .type = AVMEDIA_TYPE_VIDEO,
329  .id = CODEC_ID_ZMBV,
330  .priv_data_size = sizeof(ZmbvEncContext),
331  .init = encode_init,
332  .encode = encode_frame,
333  .close = encode_end,
334  .pix_fmts = (const enum PixelFormat[]){PIX_FMT_PAL8, PIX_FMT_NONE},
335  .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
336 };