FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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;
58 
59 static int score_tab[256];
60 
61 /** Block comparing function
62  * XXX should be optimized and moved to DSPContext
63  * TODO handle out of edge ME
64  */
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 
89 /** Motion estimation function
90  * TODO make better ME decisions
91  */
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_packet2(avctx, pkt, pkt_size, 0)) < 0)
235  return ret;
236  buf = pkt->data;
237 
238  fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0);
239  *buf++ = fl;
240  if (keyframe) {
241  *buf++ = 0; // hi ver
242  *buf++ = 1; // lo ver
243  *buf++ = 1; // comp
244  *buf++ = 4; // format - 8bpp
245  *buf++ = ZMBV_BLOCK; // block width
246  *buf++ = ZMBV_BLOCK; // block height
247  }
248  memcpy(buf, c->comp_buf, c->zstream.total_out);
249 
250  pkt->flags |= AV_PKT_FLAG_KEY*keyframe;
251  *got_packet = 1;
252 
253  return 0;
254 }
255 
257 {
258  ZmbvEncContext * const c = avctx->priv_data;
259 
260  av_freep(&c->comp_buf);
261  av_freep(&c->work_buf);
262 
263  deflateEnd(&c->zstream);
264  av_freep(&c->prev);
265 
266  return 0;
267 }
268 
269 /**
270  * Init zmbv encoder
271  */
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 * log2(i/(double)(ZMBV_BLOCK*ZMBV_BLOCK)) * 256;
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  return 0;
330 }
331 
333  .name = "zmbv",
334  .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
335  .type = AVMEDIA_TYPE_VIDEO,
336  .id = AV_CODEC_ID_ZMBV,
337  .priv_data_size = sizeof(ZmbvEncContext),
338  .init = encode_init,
339  .encode2 = encode_frame,
340  .close = encode_end,
342 };
uint8_t pal[768]
Definition: zmbvenc.c:50
This structure describes decoded (raw) audio or video data.
Definition: frame.h:184
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
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:256
static AVPacket pkt
AVCodec.
Definition: avcodec.h:3559
#define log2(x)
Definition: libm.h:404
#define ZMBV_KEYFRAME
Definition: zmbvenc.c:37
uint8_t * prev
Definition: zmbvenc.c:52
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:2179
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:1588
#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:1620
AVCodec ff_zmbv_encoder
Definition: zmbvenc.c:332
#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:272
#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:176
const char * name
Name of the codec implementation.
Definition: avcodec.h:3566
#define FFMAX(a, b)
Definition: common.h:94
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1594
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:258
#define FFMIN(a, b)
Definition: common.h:96
int width
picture width / height.
Definition: avcodec.h:1844
#define AV_WB24(p, d)
Definition: intreadwrite.h:450
AVCodecContext * avctx
Definition: zmbvenc.c:46
#define src
Definition: vp9dsp.c:530
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:1744
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:215
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:1657
void * buf
Definition: avisynth_c.h:553
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
Definition: utils.c:1690
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:262
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:198
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:105
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:80
common internal api header.
common internal and external API header
static double c[64]
static int score_tab[256]
Definition: zmbvenc.c:59
attribute_deprecated AVFrame * coded_frame
the picture in the bitstream
Definition: avcodec.h:3078
void * priv_data
Definition: avcodec.h:1699
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:81
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:253
#define av_freep(p)
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
#define stride
uint32_t pal2[256]
Definition: zmbvenc.c:51
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60
This structure stores compressed data.
Definition: avcodec.h:1565
Predicted.
Definition: avutil.h:267
int keyint_min
minimum GOP size
Definition: avcodec.h:2330