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;
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_packet2(avctx, pkt, pkt_size)) < 0)
231  return ret;
232  buf = pkt->data;
233 
234  fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0);
235  *buf++ = fl;
236  if (keyframe) {
237  *buf++ = 0; // hi ver
238  *buf++ = 1; // lo ver
239  *buf++ = 1; // comp
240  *buf++ = 4; // format - 8bpp
241  *buf++ = ZMBV_BLOCK; // block width
242  *buf++ = ZMBV_BLOCK; // block height
243  }
244  memcpy(buf, c->comp_buf, c->zstream.total_out);
245 
246  pkt->flags |= AV_PKT_FLAG_KEY*keyframe;
247  *got_packet = 1;
248 
249  return 0;
250 }
251 
253 {
254  ZmbvEncContext * const c = avctx->priv_data;
255 
256  av_freep(&c->comp_buf);
257  av_freep(&c->work_buf);
258 
259  deflateEnd(&c->zstream);
260  av_freep(&c->prev);
261 
262  av_frame_free(&avctx->coded_frame);
263 
264  return 0;
265 }
266 
267 /**
268  * Init zmbv encoder
269  */
271 {
272  ZmbvEncContext * const c = avctx->priv_data;
273  int zret; // Zlib return code
274  int i;
275  int lvl = 9;
276 
277  for(i=1; i<256; i++)
278  score_tab[i]= -i * log(i/(double)(ZMBV_BLOCK*ZMBV_BLOCK)) * (256/M_LN2);
279 
280  c->avctx = avctx;
281 
282  c->curfrm = 0;
283  c->keyint = avctx->keyint_min;
284  c->range = 8;
285  if(avctx->me_range > 0)
286  c->range = FFMIN(avctx->me_range, 127);
287 
288  if(avctx->compression_level >= 0)
289  lvl = avctx->compression_level;
290  if(lvl < 0 || lvl > 9){
291  av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl);
292  return AVERROR(EINVAL);
293  }
294 
295  // Needed if zlib unused or init aborted before deflateInit
296  memset(&c->zstream, 0, sizeof(z_stream));
297  c->comp_size = avctx->width * avctx->height + 1024 +
298  ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4;
299  if (!(c->work_buf = av_malloc(c->comp_size))) {
300  av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n");
301  return AVERROR(ENOMEM);
302  }
303  /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */
304  c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) +
305  ((c->comp_size + 63) >> 6) + 11;
306 
307  /* Allocate compression buffer */
308  if (!(c->comp_buf = av_malloc(c->comp_size))) {
309  av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n");
310  return AVERROR(ENOMEM);
311  }
312  c->pstride = FFALIGN(avctx->width, 16);
313  if (!(c->prev = av_malloc(c->pstride * avctx->height))) {
314  av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n");
315  return AVERROR(ENOMEM);
316  }
317 
318  c->zstream.zalloc = Z_NULL;
319  c->zstream.zfree = Z_NULL;
320  c->zstream.opaque = Z_NULL;
321  zret = deflateInit(&c->zstream, lvl);
322  if (zret != Z_OK) {
323  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
324  return -1;
325  }
326 
327  avctx->coded_frame = av_frame_alloc();
328  if (!avctx->coded_frame) {
329  encode_end(avctx);
330  return AVERROR(ENOMEM);
331  }
332 
333  return 0;
334 }
335 
337  .name = "zmbv",
338  .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"),
339  .type = AVMEDIA_TYPE_VIDEO,
340  .id = AV_CODEC_ID_ZMBV,
341  .priv_data_size = sizeof(ZmbvEncContext),
342  .init = encode_init,
343  .encode2 = encode_frame,
344  .close = encode_end,
345  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE },
346 };
uint8_t pal[768]
Definition: zmbvenc.c:50
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and/or allocate data.
Definition: utils.c:1736
This structure describes decoded (raw) audio or video data.
Definition: frame.h:171
AVFrame * coded_frame
the picture in the bitstream
Definition: avcodec.h:2745
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:252
static AVPacket pkt
AVCodec.
Definition: avcodec.h:3181
#define FFALIGN(x, a)
Definition: common.h:71
#define ZMBV_KEYFRAME
Definition: zmbvenc.c:37
uint8_t * prev
Definition: zmbvenc.c:52
uint8_t
#define av_cold
Definition: attributes.h:74
#define av_malloc(s)
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:135
8 bit with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:74
int me_range
maximum motion estimation search range in subpel units If 0 then no limit.
Definition: avcodec.h:1735
Encoder context.
Definition: zmbvenc.c:45
uint8_t * data
Definition: avcodec.h:1162
#define av_log(a,...)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1208
AVCodec ff_zmbv_encoder
Definition: zmbvenc.c:336
#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:270
#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:148
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:175
const char * name
Name of the codec implementation.
Definition: avcodec.h:3188
#define FFMAX(a, b)
Definition: common.h:64
Libavcodec external API header.
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1168
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:242
#define M_LN2
Definition: mathematics.h:34
#define FFMIN(a, b)
Definition: common.h:66
float y
ret
Definition: avfilter.c:974
int width
picture width / height.
Definition: avcodec.h:1414
#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
AVS_Value src
Definition: avisynth_c.h:482
int compression_level
Definition: avcodec.h:1327
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:199
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:1241
void * buf
Definition: avisynth_c.h:553
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:182
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:105
common internal api header.
common internal and external API header
static double c[64]
static int score_tab[256]
Definition: zmbvenc.c:59
void * priv_data
Definition: avcodec.h:1283
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:237
#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:61
This structure stores compressed data.
Definition: avcodec.h:1139
Predicted.
Definition: avutil.h:268
int keyint_min
minimum GOP size
Definition: avcodec.h:1894