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 
119 static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
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;
137  avctx->coded_frame->key_frame = keyframe;
138  chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024);
139 
140  palptr = (uint32_t*)p->data[1];
141  src = p->data[0];
142  prev = c->prev;
143  if(chpal){
144  uint8_t tpal[3];
145  for(i = 0; i < 256; i++){
146  AV_WB24(tpal, palptr[i]);
147  c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0];
148  c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1];
149  c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2];
150  c->pal[i * 3 + 0] = tpal[0];
151  c->pal[i * 3 + 1] = tpal[1];
152  c->pal[i * 3 + 2] = tpal[2];
153  }
154  memcpy(c->pal2, p->data[1], 1024);
155  }
156  if(keyframe){
157  for(i = 0; i < 256; i++){
158  AV_WB24(c->pal+(i*3), palptr[i]);
159  }
160  memcpy(c->work_buf, c->pal, 768);
161  memcpy(c->pal2, p->data[1], 1024);
162  work_size = 768;
163  for(i = 0; i < avctx->height; i++){
164  memcpy(c->work_buf + work_size, src, avctx->width);
165  src += p->linesize[0];
166  work_size += avctx->width;
167  }
168  }else{
169  int x, y, bh2, bw2, xored;
170  uint8_t *tsrc, *tprev;
171  uint8_t *mv;
172  int mx, my;
173 
174  bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
175  bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
176  mv = c->work_buf + work_size;
177  memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3);
178  work_size += (bw * bh * 2 + 3) & ~3;
179  /* for now just XOR'ing */
180  for(y = 0; y < avctx->height; y += ZMBV_BLOCK) {
181  bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK);
182  for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) {
183  bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK);
184 
185  tsrc = src + x;
186  tprev = prev + x;
187 
188  zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored);
189  mv[0] = (mx << 1) | !!xored;
190  mv[1] = my << 1;
191  tprev += mx + my * c->pstride;
192  if(xored){
193  for(j = 0; j < bh2; j++){
194  for(i = 0; i < bw2; i++)
195  c->work_buf[work_size++] = tsrc[i] ^ tprev[i];
196  tsrc += p->linesize[0];
197  tprev += c->pstride;
198  }
199  }
200  }
201  src += p->linesize[0] * ZMBV_BLOCK;
202  prev += c->pstride * ZMBV_BLOCK;
203  }
204  }
205  /* save the previous frame */
206  src = p->data[0];
207  prev = c->prev;
208  for(i = 0; i < avctx->height; i++){
209  memcpy(prev, src, avctx->width);
210  prev += c->pstride;
211  src += p->linesize[0];
212  }
213 
214  if (keyframe)
215  deflateReset(&c->zstream);
216 
217  c->zstream.next_in = c->work_buf;
218  c->zstream.avail_in = work_size;
219  c->zstream.total_in = 0;
220 
221  c->zstream.next_out = c->comp_buf;
222  c->zstream.avail_out = c->comp_size;
223  c->zstream.total_out = 0;
224  if(deflate(&c->zstream, Z_SYNC_FLUSH) != Z_OK){
225  av_log(avctx, AV_LOG_ERROR, "Error compressing data\n");
226  return -1;
227  }
228 
229  pkt_size = c->zstream.total_out + 1 + 6*keyframe;
230  if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) {
231  av_log(avctx, AV_LOG_ERROR, "Error getting packet of size %d.\n", pkt_size);
232  return ret;
233  }
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 
255 {
256  ZmbvEncContext * const c = avctx->priv_data;
257 
258  av_freep(&c->comp_buf);
259  av_freep(&c->work_buf);
260 
261  deflateEnd(&c->zstream);
262  av_freep(&c->prev);
263 
264  av_frame_free(&avctx->coded_frame);
265 
266  return 0;
267 }
268 
273 {
274  ZmbvEncContext * const c = avctx->priv_data;
275  int zret; // Zlib return code
276  int i;
277  int lvl = 9;
278 
279  for(i=1; i<256; i++)
280  score_tab[i]= -i * log(i/(double)(ZMBV_BLOCK*ZMBV_BLOCK)) * (256/M_LN2);
281 
282  c->avctx = avctx;
283 
284  c->curfrm = 0;
285  c->keyint = avctx->keyint_min;
286  c->range = 8;
287  if(avctx->me_range > 0)
288  c->range = FFMIN(avctx->me_range, 127);
289 
290  if(avctx->compression_level >= 0)
291  lvl = avctx->compression_level;
292  if(lvl < 0 || lvl > 9){
293  av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl);
294  return AVERROR(EINVAL);
295  }
296 
297  // Needed if zlib unused or init aborted before deflateInit
298  memset(&c->zstream, 0, sizeof(z_stream));
299  c->comp_size = avctx->width * avctx->height + 1024 +
300  ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4;
301  if (!(c->work_buf = av_malloc(c->comp_size))) {
302  av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n");
303  return AVERROR(ENOMEM);
304  }
305  /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
306  c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) +
307  ((c->comp_size + 63) >> 6) + 11;
308 
309  /* Allocate compression buffer */
310  if (!(c->comp_buf = av_malloc(c->comp_size))) {
311  av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n");
312  return AVERROR(ENOMEM);
313  }
314  c->pstride = FFALIGN(avctx->width, 16);
315  if (!(c->prev = av_malloc(c->pstride * avctx->height))) {
316  av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n");
317  return AVERROR(ENOMEM);
318  }
319 
320  c->zstream.zalloc = Z_NULL;
321  c->zstream.zfree = Z_NULL;
322  c->zstream.opaque = Z_NULL;
323  zret = deflateInit(&c->zstream, lvl);
324  if (zret != Z_OK) {
325  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
326  return -1;
327  }
328 
329  avctx->coded_frame = av_frame_alloc();
330  if (!avctx->coded_frame) {
331  encode_end(avctx);
332  return AVERROR(ENOMEM);
333  }
334 
335  return 0;
336 }
337 
339  .name = "zmbv",
340  .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
341  .type = AVMEDIA_TYPE_VIDEO,
342  .id = AV_CODEC_ID_ZMBV,
343  .priv_data_size = sizeof(ZmbvEncContext),
344  .init = encode_init,
345  .encode2 = encode_frame,
346  .close = encode_end,
347  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE },
348 };
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:135
AVFrame * coded_frame
the picture in the bitstream
Definition: avcodec.h:2532
int comp_size
Definition: zmbvenc.c:54
uint8_t * comp_buf
Definition: zmbvenc.c:49
static av_cold int encode_end(AVCodecContext *avctx)
Definition: zmbvenc.c:254
int stride
Definition: mace.c:144
AVCodec.
Definition: avcodec.h:2796
#define FFALIGN(x, a)
Definition: common.h:62
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:52
uint8_t
#define av_cold
Definition: attributes.h:66
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:57
8 bit with PIX_FMT_RGB32 palette
Definition: pixfmt.h:76
int me_range
maximum motion estimation search range in subpel units If 0 then no limit.
Definition: avcodec.h:1539
Encoder context.
Definition: zmbvenc.c:45
uint8_t * data
Definition: avcodec.h:973
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1019
AVCodec ff_zmbv_encoder
Definition: zmbvenc.c:338
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:123
uint8_t * work_buf
Definition: zmbvenc.c:49
static av_cold int encode_init(AVCodecContext *avctx)
Init zmbv encoder.
Definition: zmbvenc.c:272
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:69
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:150
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:168
const char * name
Name of the codec implementation.
Definition: avcodec.h:2803
#define FFMAX(a, b)
Definition: common.h:55
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:979
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:196
#define FFMIN(a, b)
Definition: common.h:57
int width
picture width / height.
Definition: avcodec.h:1224
#define AV_WB24(p, d)
Definition: intreadwrite.h:412
AVCodecContext * avctx
Definition: zmbvenc.c:46
int ff_alloc_packet(AVPacket *avpkt, int size)
Check AVPacket size and/or allocate data.
Definition: utils.c:1245
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:1136
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:153
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:1050
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:490
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: zmbvenc.c:119
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:141
common internal api header.
common internal and external API header
static int score_tab[256]
Definition: zmbvenc.c:59
static av_cold int init(AVCodecParserContext *s)
Definition: h264_parser.c:499
void * priv_data
Definition: avcodec.h:1092
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:191
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:63
This structure stores compressed data.
Definition: avcodec.h:950
Predicted.
Definition: avutil.h:254
int keyint_min
minimum GOP size
Definition: avcodec.h:1700