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 FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 /**
23  * @file
24  * Zip Motion Blocks Video encoder
25  */
26 
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 
42 /**
43  * Encoder context
44  */
45 typedef struct ZmbvEncContext {
48 
49  int range;
51  uint8_t pal[768];
52  uint32_t pal2[256]; //for quick comparisons
54  int pstride;
55  int comp_size;
56  int keyint, curfrm;
57  z_stream zstream;
59 
60 static int score_tab[256];
61 
62 /** Block comparing function
63  * XXX should be optimized and moved to DSPContext
64  * TODO handle out of edge ME
65  */
66 static inline int block_cmp(uint8_t *src, int stride, uint8_t *src2, int stride2,
67  int bw, int bh, int *xored)
68 {
69  int sum = 0;
70  int i, j;
71  uint8_t histogram[256] = {0};
72 
73  *xored = 0;
74  for(j = 0; j < bh; j++){
75  for(i = 0; i < bw; i++){
76  int t = src[i] ^ src2[i];
77  histogram[t]++;
78  *xored |= t;
79  }
80  src += stride;
81  src2 += stride2;
82  }
83 
84  for(i = 1; i < 256; i++)
85  sum += score_tab[histogram[i]];
86 
87  return sum;
88 }
89 
90 /** Motion estimation function
91  * TODO make better ME decisions
92  */
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)
95 {
96  int dx, dy, tx, ty, tv, bv, bw, bh;
97 
98  *mx = *my = 0;
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);
102  if(!bv) return 0;
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
106  dx = tx - x;
107  dy = ty - y;
108  tv = block_cmp(src, sstride, prev + dx + dy*pstride, pstride, bw, bh, xored);
109  if(tv < bv){
110  bv = tv;
111  *mx = dx;
112  *my = dy;
113  if(!bv) return 0;
114  }
115  }
116  }
117  return bv;
118 }
119 
121  const AVFrame *pict, int *got_packet)
122 {
123  ZmbvEncContext * const c = avctx->priv_data;
124  AVFrame * const p = &c->pic;
125  uint8_t *src, *prev, *buf;
126  uint32_t *palptr;
127  int keyframe, chpal;
128  int fl;
129  int work_size = 0, pkt_size;
130  int bw, bh;
131  int i, j, ret;
132 
133  keyframe = !c->curfrm;
134  c->curfrm++;
135  if(c->curfrm == c->keyint)
136  c->curfrm = 0;
137  *p = *pict;
139  p->key_frame= keyframe;
140  chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024);
141 
142  palptr = (uint32_t*)p->data[1];
143  src = p->data[0];
144  prev = c->prev;
145  if(chpal){
146  uint8_t tpal[3];
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];
155  }
156  memcpy(c->pal2, p->data[1], 1024);
157  }
158  if(keyframe){
159  for(i = 0; i < 256; i++){
160  AV_WB24(c->pal+(i*3), palptr[i]);
161  }
162  memcpy(c->work_buf, c->pal, 768);
163  memcpy(c->pal2, p->data[1], 1024);
164  work_size = 768;
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;
169  }
170  }else{
171  int x, y, bh2, bw2, xored;
172  uint8_t *tsrc, *tprev;
173  uint8_t *mv;
174  int mx, my;
175 
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);
186 
187  tsrc = src + x;
188  tprev = prev + x;
189 
190  zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored);
191  mv[0] = (mx << 1) | !!xored;
192  mv[1] = my << 1;
193  tprev += mx + my * c->pstride;
194  if(xored){
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];
199  tprev += c->pstride;
200  }
201  }
202  }
203  src += p->linesize[0] * ZMBV_BLOCK;
204  prev += c->pstride * ZMBV_BLOCK;
205  }
206  }
207  /* save the previous frame */
208  src = p->data[0];
209  prev = c->prev;
210  for(i = 0; i < avctx->height; i++){
211  memcpy(prev, src, avctx->width);
212  prev += c->pstride;
213  src += p->linesize[0];
214  }
215 
216  if (keyframe)
217  deflateReset(&c->zstream);
218 
219  c->zstream.next_in = c->work_buf;
220  c->zstream.avail_in = work_size;
221  c->zstream.total_in = 0;
222 
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");
228  return -1;
229  }
230 
231  pkt_size = c->zstream.total_out + 1 + 6*keyframe;
232  if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size)) < 0)
233  return ret;
234  buf = pkt->data;
235 
236  fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0);
237  *buf++ = fl;
238  if (keyframe) {
239  *buf++ = 0; // hi ver
240  *buf++ = 1; // lo ver
241  *buf++ = 1; // comp
242  *buf++ = 4; // format - 8bpp
243  *buf++ = ZMBV_BLOCK; // block width
244  *buf++ = ZMBV_BLOCK; // block height
245  }
246  memcpy(buf, c->comp_buf, c->zstream.total_out);
247 
248  pkt->flags |= AV_PKT_FLAG_KEY*keyframe;
249  *got_packet = 1;
250 
251  return 0;
252 }
253 
254 
255 /**
256  * Init zmbv encoder
257  */
259 {
260  ZmbvEncContext * const c = avctx->priv_data;
261  int zret; // Zlib return code
262  int i;
263  int lvl = 9;
264 
265  for(i=1; i<256; i++)
266  score_tab[i]= -i * log(i/(double)(ZMBV_BLOCK*ZMBV_BLOCK)) * (256/M_LN2);
267 
268  c->avctx = avctx;
269 
270  c->curfrm = 0;
271  c->keyint = avctx->keyint_min;
272  c->range = 8;
273  if(avctx->me_range > 0)
274  c->range = FFMIN(avctx->me_range, 127);
275 
276  if(avctx->compression_level >= 0)
277  lvl = avctx->compression_level;
278  if(lvl < 0 || lvl > 9){
279  av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl);
280  return AVERROR(EINVAL);
281  }
282 
283  // Needed if zlib unused or init aborted before deflateInit
284  memset(&c->zstream, 0, sizeof(z_stream));
285  c->comp_size = avctx->width * avctx->height + 1024 +
286  ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4;
287  if ((c->work_buf = av_malloc(c->comp_size)) == NULL) {
288  av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n");
289  return AVERROR(ENOMEM);
290  }
291  /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
292  c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) +
293  ((c->comp_size + 63) >> 6) + 11;
294 
295  /* Allocate compression buffer */
296  if ((c->comp_buf = av_malloc(c->comp_size)) == NULL) {
297  av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n");
298  return AVERROR(ENOMEM);
299  }
300  c->pstride = FFALIGN(avctx->width, 16);
301  if ((c->prev = av_malloc(c->pstride * avctx->height)) == NULL) {
302  av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n");
303  return AVERROR(ENOMEM);
304  }
305 
306  c->zstream.zalloc = Z_NULL;
307  c->zstream.zfree = Z_NULL;
308  c->zstream.opaque = Z_NULL;
309  zret = deflateInit(&c->zstream, lvl);
310  if (zret != Z_OK) {
311  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
312  return -1;
313  }
314 
315  avctx->coded_frame = &c->pic;
316 
317  return 0;
318 }
319 
320 
321 
322 /**
323  * Uninit zmbv encoder
324  */
326 {
327  ZmbvEncContext * const c = avctx->priv_data;
328 
329  av_freep(&c->comp_buf);
330  av_freep(&c->work_buf);
331 
332  deflateEnd(&c->zstream);
333  av_freep(&c->prev);
334 
335  return 0;
336 }
337 
339  .name = "zmbv",
340  .type = AVMEDIA_TYPE_VIDEO,
341  .id = AV_CODEC_ID_ZMBV,
342  .priv_data_size = sizeof(ZmbvEncContext),
343  .init = encode_init,
344  .encode2 = encode_frame,
345  .close = encode_end,
346  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE },
347  .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
348 };
uint8_t pal[768]
Definition: zmbvenc.c:51
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
AVFrame * coded_frame
the picture in the bitstream
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int comp_size
Definition: zmbvenc.c:55
uint8_t * comp_buf
Definition: zmbvenc.c:50
static av_cold int encode_end(AVCodecContext *avctx)
Uninit zmbv encoder.
Definition: zmbvenc.c:325
int stride
Definition: mace.c:144
#define FFALIGN(x, a)
Definition: common.h:63
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:198
#define ZMBV_KEYFRAME
Definition: zmbvenc.c:37
uint8_t * prev
Definition: zmbvenc.c:53
uint8_t
#define av_cold
Definition: attributes.h:78
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:79
int me_range
maximum motion estimation search range in subpel units If 0 then no limit.
static AVPacket pkt
Definition: demuxing.c:56
Encoder context.
Definition: zmbvenc.c:45
uint8_t * data
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
AVCodec ff_zmbv_encoder
Definition: zmbvenc.c:338
Discrete Time axis x
uint8_t * work_buf
Definition: zmbvenc.c:50
static av_cold int encode_init(AVCodecContext *avctx)
Init zmbv encoder.
Definition: zmbvenc.c:258
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
#define FFMAX(a, b)
Definition: common.h:56
external API header
int flags
A combination of AV_PKT_FLAG values.
struct ZmbvEncContext ZmbvEncContext
Encoder context.
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:144
#define M_LN2
Definition: mathematics.h:34
#define FFMIN(a, b)
Definition: common.h:58
ret
Definition: avfilter.c:821
int width
picture width / height.
t
Definition: genspecsines3.m:6
#define AV_WB24(p, d)
Definition: intreadwrite.h:442
AVCodecContext * avctx
Definition: zmbvenc.c:46
AVFrame pic
Definition: zmbvenc.c:47
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size)
Check AVPacket size and/or allocate data.
static const int8_t mv[256][2]
#define ZMBV_BLOCK
Definition: zmbvenc.c:40
NULL
Definition: eval.c:55
#define ZMBV_DELTAPAL
Definition: zmbvenc.c:38
AVS_Value src
Definition: avisynth_c.h:523
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
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:93
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
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:73
synthesis window for stochastic i
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: zmbvenc.c:120
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
common internal api header.
common internal and external API header
static double c[64]
static int score_tab[256]
Definition: zmbvenc.c:60
function y
Definition: D.m:1
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:139
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:66
z_stream zstream
Definition: zmbvenc.c:57
uint32_t pal2[256]
Definition: zmbvenc.c:52
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
This structure stores compressed data.
Predicted.
Definition: avutil.h:217
int keyint_min
minimum GOP size