FFmpeg  4.0
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 {
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;
57 
58  int score_tab[256];
60 
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(ZmbvEncContext *c, uint8_t *src, int stride,
67  uint8_t *src2, int stride2, int bw, int bh,
68  int *xored)
69 {
70  int sum = 0;
71  int i, j;
72  uint8_t histogram[256] = {0};
73 
74  *xored = 0;
75  for(j = 0; j < bh; j++){
76  for(i = 0; i < bw; i++){
77  int t = src[i] ^ src2[i];
78  histogram[t]++;
79  *xored |= t;
80  }
81  src += stride;
82  src2 += stride2;
83  }
84 
85  for(i = 1; i < 256; i++)
86  sum += c->score_tab[histogram[i]];
87 
88  return sum;
89 }
90 
91 /** Motion estimation function
92  * TODO make better ME decisions
93  */
94 static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev,
95  int pstride, int x, int y, int *mx, int *my, int *xored)
96 {
97  int dx, dy, tx, ty, tv, bv, bw, bh;
98 
99  *mx = *my = 0;
100  bw = FFMIN(ZMBV_BLOCK, c->avctx->width - x);
101  bh = FFMIN(ZMBV_BLOCK, c->avctx->height - y);
102  bv = block_cmp(c, src, sstride, prev, pstride, bw, bh, xored);
103  if(!bv) return 0;
104  for(ty = FFMAX(y - c->range, 0); ty < FFMIN(y + c->range, c->avctx->height - bh); ty++){
105  for(tx = FFMAX(x - c->range, 0); tx < FFMIN(x + c->range, c->avctx->width - bw); tx++){
106  if(tx == x && ty == y) continue; // we already tested this block
107  dx = tx - x;
108  dy = ty - y;
109  tv = block_cmp(c, src, sstride, prev + dx + dy * pstride, pstride, bw, bh, xored);
110  if(tv < bv){
111  bv = tv;
112  *mx = dx;
113  *my = dy;
114  if(!bv) return 0;
115  }
116  }
117  }
118  return bv;
119 }
120 
122  const AVFrame *pict, int *got_packet)
123 {
124  ZmbvEncContext * const c = avctx->priv_data;
125  const AVFrame * const p = pict;
126  uint8_t *src, *prev, *buf;
127  uint32_t *palptr;
128  int keyframe, chpal;
129  int fl;
130  int work_size = 0, pkt_size;
131  int bw, bh;
132  int i, j, ret;
133 
134  keyframe = !c->curfrm;
135  c->curfrm++;
136  if(c->curfrm == c->keyint)
137  c->curfrm = 0;
138 #if FF_API_CODED_FRAME
141  avctx->coded_frame->key_frame = keyframe;
143 #endif
144  chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024);
145 
146  palptr = (uint32_t*)p->data[1];
147  src = p->data[0];
148  prev = c->prev;
149  if(chpal){
150  uint8_t tpal[3];
151  for(i = 0; i < 256; i++){
152  AV_WB24(tpal, palptr[i]);
153  c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0];
154  c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1];
155  c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2];
156  c->pal[i * 3 + 0] = tpal[0];
157  c->pal[i * 3 + 1] = tpal[1];
158  c->pal[i * 3 + 2] = tpal[2];
159  }
160  memcpy(c->pal2, p->data[1], 1024);
161  }
162  if(keyframe){
163  for(i = 0; i < 256; i++){
164  AV_WB24(c->pal+(i*3), palptr[i]);
165  }
166  memcpy(c->work_buf, c->pal, 768);
167  memcpy(c->pal2, p->data[1], 1024);
168  work_size = 768;
169  for(i = 0; i < avctx->height; i++){
170  memcpy(c->work_buf + work_size, src, avctx->width);
171  src += p->linesize[0];
172  work_size += avctx->width;
173  }
174  }else{
175  int x, y, bh2, bw2, xored;
176  uint8_t *tsrc, *tprev;
177  uint8_t *mv;
178  int mx, my;
179 
180  bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
181  bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK;
182  mv = c->work_buf + work_size;
183  memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3);
184  work_size += (bw * bh * 2 + 3) & ~3;
185  /* for now just XOR'ing */
186  for(y = 0; y < avctx->height; y += ZMBV_BLOCK) {
187  bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK);
188  for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) {
189  bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK);
190 
191  tsrc = src + x;
192  tprev = prev + x;
193 
194  zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored);
195  mv[0] = (mx << 1) | !!xored;
196  mv[1] = my << 1;
197  tprev += mx + my * c->pstride;
198  if(xored){
199  for(j = 0; j < bh2; j++){
200  for(i = 0; i < bw2; i++)
201  c->work_buf[work_size++] = tsrc[i] ^ tprev[i];
202  tsrc += p->linesize[0];
203  tprev += c->pstride;
204  }
205  }
206  }
207  src += p->linesize[0] * ZMBV_BLOCK;
208  prev += c->pstride * ZMBV_BLOCK;
209  }
210  }
211  /* save the previous frame */
212  src = p->data[0];
213  prev = c->prev;
214  for(i = 0; i < avctx->height; i++){
215  memcpy(prev, src, avctx->width);
216  prev += c->pstride;
217  src += p->linesize[0];
218  }
219 
220  if (keyframe)
221  deflateReset(&c->zstream);
222 
223  c->zstream.next_in = c->work_buf;
224  c->zstream.avail_in = work_size;
225  c->zstream.total_in = 0;
226 
227  c->zstream.next_out = c->comp_buf;
228  c->zstream.avail_out = c->comp_size;
229  c->zstream.total_out = 0;
230  if(deflate(&c->zstream, Z_SYNC_FLUSH) != Z_OK){
231  av_log(avctx, AV_LOG_ERROR, "Error compressing data\n");
232  return -1;
233  }
234 
235  pkt_size = c->zstream.total_out + 1 + 6*keyframe;
236  if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size, 0)) < 0)
237  return ret;
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 
271 /**
272  * Init zmbv encoder
273  */
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  c->score_tab[i] = -i * log2(i / (double)(ZMBV_BLOCK * ZMBV_BLOCK)) * 256;
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
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int comp_size
Definition: zmbvenc.c:54
int score_tab[256]
Definition: zmbvenc.c:58
uint8_t * comp_buf
Definition: zmbvenc.c:49
static av_cold int encode_end(AVCodecContext *avctx)
Definition: zmbvenc.c:258
static AVPacket pkt
#define src
Definition: vp8dsp.c:254
int stride
Definition: mace.c:144
AVCodec.
Definition: avcodec.h:3408
#define log2(x)
Definition: libm.h:404
#define ZMBV_KEYFRAME
Definition: zmbvenc.c:37
uint8_t * prev
Definition: zmbvenc.c:52
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
Definition: encode.c:32
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:73
int me_range
maximum motion estimation search range in subpel units If 0 then no limit.
Definition: avcodec.h:1988
static void deflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord)
Definition: vf_neighbor.c:114
Encoder context.
Definition: zmbvenc.c:45
uint8_t * data
Definition: avcodec.h:1430
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1462
AVCodec ff_zmbv_encoder
Definition: zmbvenc.c:334
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
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:186
const char * name
Name of the codec implementation.
Definition: avcodec.h:3415
#define FFMAX(a, b)
Definition: common.h:94
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1436
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:301
#define FFMIN(a, b)
Definition: common.h:96
int width
picture width / height.
Definition: avcodec.h:1690
#define AV_WB24(p, d)
Definition: intreadwrite.h:450
AVCodecContext * avctx
Definition: zmbvenc.c:46
static const int8_t mv[256][2]
Definition: 4xm.c:77
#define ZMBV_BLOCK
Definition: zmbvenc.c:40
#define ZMBV_DELTAPAL
Definition: zmbvenc.c:38
Libavcodec external API header.
int compression_level
Definition: avcodec.h:1590
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:249
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:94
main external API structure.
Definition: avcodec.h:1518
void * buf
Definition: avisynth_c.h:690
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition: zmbvenc.c:121
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:266
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:84
common internal api header.
common internal and external API header
static double c[64]
attribute_deprecated AVFrame * coded_frame
the picture in the bitstream
Definition: avcodec.h:2760
void * priv_data
Definition: avcodec.h:1545
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:85
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:296
static int block_cmp(ZmbvEncContext *c, 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
#define av_freep(p)
z_stream zstream
Definition: zmbvenc.c:56
uint32_t pal2[256]
Definition: zmbvenc.c:51
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60
This structure stores compressed data.
Definition: avcodec.h:1407
Predicted.
Definition: avutil.h:275
int keyint_min
minimum GOP size
Definition: avcodec.h:2094