Libav
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/common.h"
31 #include "libavutil/intreadwrite.h"
32 #include "avcodec.h"
33 #include "internal.h"
34 
35 #include <zlib.h>
36 
37 #define ZMBV_KEYFRAME 1
38 #define ZMBV_DELTAPAL 2
39 
40 #define ZMBV_BLOCK 16
41 
45 typedef struct ZmbvEncContext {
47 
48  int range;
50  uint8_t pal[768];
51  uint32_t pal2[256]; //for quick comparisons
53  int pstride;
54  int comp_size;
55  int keyint, curfrm;
56  z_stream zstream;
58 
59 static int score_tab[256];
60 
65 static inline int block_cmp(uint8_t *src, int stride, uint8_t *src2, int stride2,
66  int bw, int bh, int *xored)
67 {
68  int sum = 0;
69  int i, j;
70  uint8_t histogram[256] = {0};
71 
72  *xored = 0;
73  for(j = 0; j < bh; j++){
74  for(i = 0; i < bw; i++){
75  int t = src[i] ^ src2[i];
76  histogram[t]++;
77  *xored |= t;
78  }
79  src += stride;
80  src2 += stride2;
81  }
82 
83  for(i = 1; i < 256; i++)
84  sum += score_tab[histogram[i]];
85 
86  return sum;
87 }
88 
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)
94 {
95  int dx, dy, tx, ty, tv, bv, bw, bh;
96 
97  *mx = *my = 0;
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);
101  if(!bv) return 0;
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
105  dx = tx - x;
106  dy = ty - y;
107  tv = block_cmp(src, sstride, prev + dx + dy*pstride, pstride, bw, bh, xored);
108  if(tv < bv){
109  bv = tv;
110  *mx = dx;
111  *my = dy;
112  if(!bv) return 0;
113  }
114  }
115  }
116  return bv;
117 }
118 
120  const AVFrame *pict, int *got_packet)
121 {
122  ZmbvEncContext * const c = avctx->priv_data;
123  const AVFrame * const p = pict;
124  uint8_t *src, *prev, *buf;
125  uint32_t *palptr;
126  int keyframe, chpal;
127  int fl;
128  int work_size = 0, pkt_size;
129  int bw, bh;
130  int i, j, ret;
131 
132  keyframe = !c->curfrm;
133  c->curfrm++;
134  if(c->curfrm == c->keyint)
135  c->curfrm = 0;
136 #if FF_API_CODED_FRAME
139  avctx->coded_frame->key_frame = keyframe;
141 #endif
142  chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024);
143 
144  palptr = (uint32_t*)p->data[1];
145  src = p->data[0];
146  prev = c->prev;
147  if(chpal){
148  uint8_t tpal[3];
149  for(i = 0; i < 256; i++){
150  AV_WB24(tpal, palptr[i]);
151  c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0];
152  c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1];
153  c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2];
154  c->pal[i * 3 + 0] = tpal[0];
155  c->pal[i * 3 + 1] = tpal[1];
156  c->pal[i * 3 + 2] = tpal[2];
157  }
158  memcpy(c->pal2, p->data[1], 1024);
159  }
160  if(keyframe){
161  for(i = 0; i < 256; i++){
162  AV_WB24(c->pal+(i*3), palptr[i]);
163  }
164  memcpy(c->work_buf, c->pal, 768);
165  memcpy(c->pal2, p->data[1], 1024);
166  work_size = 768;
167  for(i = 0; i < avctx->height; i++){
168  memcpy(c->work_buf + work_size, src, avctx->width);
169  src += p->linesize[0];
170  work_size += avctx->width;
171  }
172  }else{
173  int x, y, bh2, bw2, xored;
174  uint8_t *tsrc, *tprev;
175  uint8_t *mv;
176  int mx, my;
177 
178  bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
179  bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
180  mv = c->work_buf + work_size;
181  memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3);
182  work_size += (bw * bh * 2 + 3) & ~3;
183  /* for now just XOR'ing */
184  for(y = 0; y < avctx->height; y += ZMBV_BLOCK) {
185  bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK);
186  for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) {
187  bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK);
188 
189  tsrc = src + x;
190  tprev = prev + x;
191 
192  zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored);
193  mv[0] = (mx << 1) | !!xored;
194  mv[1] = my << 1;
195  tprev += mx + my * c->pstride;
196  if(xored){
197  for(j = 0; j < bh2; j++){
198  for(i = 0; i < bw2; i++)
199  c->work_buf[work_size++] = tsrc[i] ^ tprev[i];
200  tsrc += p->linesize[0];
201  tprev += c->pstride;
202  }
203  }
204  }
205  src += p->linesize[0] * ZMBV_BLOCK;
206  prev += c->pstride * ZMBV_BLOCK;
207  }
208  }
209  /* save the previous frame */
210  src = p->data[0];
211  prev = c->prev;
212  for(i = 0; i < avctx->height; i++){
213  memcpy(prev, src, avctx->width);
214  prev += c->pstride;
215  src += p->linesize[0];
216  }
217 
218  if (keyframe)
219  deflateReset(&c->zstream);
220 
221  c->zstream.next_in = c->work_buf;
222  c->zstream.avail_in = work_size;
223  c->zstream.total_in = 0;
224 
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");
230  return -1;
231  }
232 
233  pkt_size = c->zstream.total_out + 1 + 6*keyframe;
234  if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) {
235  av_log(avctx, AV_LOG_ERROR, "Error getting packet of size %d.\n", pkt_size);
236  return ret;
237  }
238  buf = pkt->data;
239 
240  fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0);
241  *buf++ = fl;
242  if (keyframe) {
243  *buf++ = 0; // hi ver
244  *buf++ = 1; // lo ver
245  *buf++ = 1; // comp
246  *buf++ = 4; // format - 8bpp
247  *buf++ = ZMBV_BLOCK; // block width
248  *buf++ = ZMBV_BLOCK; // block height
249  }
250  memcpy(buf, c->comp_buf, c->zstream.total_out);
251 
252  pkt->flags |= AV_PKT_FLAG_KEY*keyframe;
253  *got_packet = 1;
254 
255  return 0;
256 }
257 
259 {
260  ZmbvEncContext * const c = avctx->priv_data;
261 
262  av_freep(&c->comp_buf);
263  av_freep(&c->work_buf);
264 
265  deflateEnd(&c->zstream);
266  av_freep(&c->prev);
267 
268  return 0;
269 }
270 
275 {
276  ZmbvEncContext * const c = avctx->priv_data;
277  int zret; // Zlib return code
278  int i;
279  int lvl = 9;
280 
281  for(i=1; i<256; i++)
282  score_tab[i]= -i * log(i/(double)(ZMBV_BLOCK*ZMBV_BLOCK)) * (256/M_LN2);
283 
284  c->avctx = avctx;
285 
286  c->curfrm = 0;
287  c->keyint = avctx->keyint_min;
288  c->range = 8;
289  if(avctx->me_range > 0)
290  c->range = FFMIN(avctx->me_range, 127);
291 
292  if(avctx->compression_level >= 0)
293  lvl = avctx->compression_level;
294  if(lvl < 0 || lvl > 9){
295  av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl);
296  return AVERROR(EINVAL);
297  }
298 
299  // Needed if zlib unused or init aborted before deflateInit
300  memset(&c->zstream, 0, sizeof(z_stream));
301  c->comp_size = avctx->width * avctx->height + 1024 +
302  ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4;
303  if (!(c->work_buf = av_malloc(c->comp_size))) {
304  av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n");
305  return AVERROR(ENOMEM);
306  }
307  /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
308  c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) +
309  ((c->comp_size + 63) >> 6) + 11;
310 
311  /* Allocate compression buffer */
312  if (!(c->comp_buf = av_malloc(c->comp_size))) {
313  av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n");
314  return AVERROR(ENOMEM);
315  }
316  c->pstride = FFALIGN(avctx->width, 16);
317  if (!(c->prev = av_malloc(c->pstride * avctx->height))) {
318  av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n");
319  return AVERROR(ENOMEM);
320  }
321 
322  c->zstream.zalloc = Z_NULL;
323  c->zstream.zfree = Z_NULL;
324  c->zstream.opaque = Z_NULL;
325  zret = deflateInit(&c->zstream, lvl);
326  if (zret != Z_OK) {
327  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
328  return -1;
329  }
330 
331  return 0;
332 }
333 
335  .name = "zmbv",
336  .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
337  .type = AVMEDIA_TYPE_VIDEO,
338  .id = AV_CODEC_ID_ZMBV,
339  .priv_data_size = sizeof(ZmbvEncContext),
340  .init = encode_init,
341  .encode2 = encode_frame,
342  .close = encode_end,
344 };
uint8_t pal[768]
Definition: zmbvenc.c:50
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:62
This structure describes decoded (raw) audio or video data.
Definition: frame.h:140
int comp_size
Definition: zmbvenc.c:54
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
uint8_t * comp_buf
Definition: zmbvenc.c:49
static av_cold int encode_end(AVCodecContext *avctx)
Definition: zmbvenc.c:258
int stride
Definition: mace.c:144
AVCodec.
Definition: avcodec.h:3120
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:202
#define ZMBV_KEYFRAME
Definition: zmbvenc.c:37
uint8_t * prev
Definition: zmbvenc.c:52
uint8_t
#define av_cold
Definition: attributes.h:66
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:70
int me_range
maximum motion estimation search range in subpel units If 0 then no limit.
Definition: avcodec.h:1913
Encoder context.
Definition: zmbvenc.c:45
uint8_t * data
Definition: avcodec.h:1346
#define FFALIGN(x, a)
Definition: macros.h:48
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1378
AVCodec ff_zmbv_encoder
Definition: zmbvenc.c:334
#define src
Definition: vp8dsp.c:254
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:124
uint8_t * work_buf
Definition: zmbvenc.c:49
static av_cold int encode_init(AVCodecContext *avctx)
Init zmbv encoder.
Definition: zmbvenc.c:274
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:148
const char * name
Name of the codec implementation.
Definition: avcodec.h:3127
#define FFMAX(a, b)
Definition: common.h:64
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1352
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:201
#define FFMIN(a, b)
Definition: common.h:66
int width
picture width / height.
Definition: avcodec.h:1580
#define AV_WB24(p, d)
Definition: intreadwrite.h:423
AVCodecContext * avctx
Definition: zmbvenc.c:46
int ff_alloc_packet(AVPacket *avpkt, int size)
Check AVPacket size and/or allocate data.
Definition: utils.c:1211
static const int8_t mv[256][2]
Definition: 4xm.c:75
#define ZMBV_BLOCK
Definition: zmbvenc.c:40
#define ZMBV_DELTAPAL
Definition: zmbvenc.c:38
Libavcodec external API header.
int compression_level
Definition: avcodec.h:1495
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:158
static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev, int pstride, int x, int y, int *mx, int *my, int *xored)
Motion estimation function TODO make better ME decisions.
Definition: zmbvenc.c:92
main external API structure.
Definition: avcodec.h:1409
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: zmbvenc.c:119
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:257
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:146
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:77
common internal api header.
common internal and external API header
static int score_tab[256]
Definition: zmbvenc.c:59
attribute_deprecated AVFrame * coded_frame
the picture in the bitstream
Definition: avcodec.h:2797
static av_cold int init(AVCodecParserContext *s)
Definition: h264_parser.c:582
void * priv_data
Definition: avcodec.h:1451
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:78
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:196
static int block_cmp(uint8_t *src, int stride, uint8_t *src2, int stride2, int bw, int bh, int *xored)
Block comparing function XXX should be optimized and moved to DSPContext TODO handle out of edge ME...
Definition: zmbvenc.c:65
z_stream zstream
Definition: zmbvenc.c:56
uint32_t pal2[256]
Definition: zmbvenc.c:51
AVPixelFormat
Pixel format.
Definition: pixfmt.h:57
This structure stores compressed data.
Definition: avcodec.h:1323
Predicted.
Definition: avutil.h:261
int keyint_min
minimum GOP size
Definition: avcodec.h:2064