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 "codec_internal.h" 34#include "encode.h" 35#include "zlib_wrapper.h" 36 37#include <zlib.h> 38 39/* Frame header flags */ 40#define ZMBV_KEYFRAME 1 41#define ZMBV_DELTAPAL 2 42 43/* Motion block width/height (maximum allowed value is 255) 44 * Note: histogram datatype in block_cmp() must be big enough to hold values 45 * up to (4 * ZMBV_BLOCK * ZMBV_BLOCK) 46 */ 47#define ZMBV_BLOCK 16 48 49/* Keyframe header format values */ 50enum ZmbvFormat { 51 ZMBV_FMT_NONE = 0, 52 ZMBV_FMT_1BPP = 1, 53 ZMBV_FMT_2BPP = 2, 54 ZMBV_FMT_4BPP = 3, 55 ZMBV_FMT_8BPP = 4, 56 ZMBV_FMT_15BPP = 5, 57 ZMBV_FMT_16BPP = 6, 58 ZMBV_FMT_24BPP = 7, 59 ZMBV_FMT_32BPP = 8 60}; 61 62/** 63 * Encoder context 64 */ 65typedef struct ZmbvEncContext { 66 AVCodecContext *avctx; 67 68 int lrange, urange; 69 uint8_t *comp_buf, *work_buf; 70 uint8_t pal[768]; 71 uint32_t pal2[256]; //for quick comparisons 72 uint8_t *prev, *prev_buf; 73 int pstride; 74 int comp_size; 75 int keyint, curfrm; 76 int bypp; 77 enum ZmbvFormat fmt; 78 FFZStream zstream; 79 80 int score_tab[ZMBV_BLOCK * ZMBV_BLOCK * 4 + 1]; 81} ZmbvEncContext; 82 83 84/** Block comparing function 85 * XXX should be optimized and moved to DSPContext 86 */ 87static inline int block_cmp(ZmbvEncContext *c, uint8_t *src, int stride, 88 uint8_t *src2, int stride2, int bw, int bh, 89 int *xored) 90{ 91 int sum = 0; 92 int i, j; 93 uint16_t histogram[256] = {0}; 94 int bw_bytes = bw * c->bypp; 95 96 /* Build frequency histogram of byte values for src[] ^ src2[] */ 97 for(j = 0; j < bh; j++){ 98 for(i = 0; i < bw_bytes; i++){ 99 int t = src[i] ^ src2[i]; 100 histogram[t]++; 101 } 102 src += stride; 103 src2 += stride2; 104 } 105 106 /* If not all the xored values were 0, then the blocks are different */ 107 *xored = (histogram[0] < bw_bytes * bh); 108 109 /* Exit early if blocks are equal */ 110 if (!*xored) return 0; 111 112 /* Sum the entropy of all values */ 113 for(i = 0; i < 256; i++) 114 sum += c->score_tab[histogram[i]]; 115 116 return sum; 117} 118 119/** Motion estimation function 120 * TODO make better ME decisions 121 */ 122static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev, 123 int pstride, int x, int y, int *mx, int *my, int *xored) 124{ 125 int dx, dy, txored, tv, bv, bw, bh; 126 int mx0, my0; 127 128 mx0 = *mx; 129 my0 = *my; 130 bw = FFMIN(ZMBV_BLOCK, c->avctx->width - x); 131 bh = FFMIN(ZMBV_BLOCK, c->avctx->height - y); 132 133 /* Try (0,0) */ 134 bv = block_cmp(c, src, sstride, prev, pstride, bw, bh, xored); 135 *mx = *my = 0; 136 if(!bv) return 0; 137 138 /* Try previous block's MV (if not 0,0) */ 139 if (mx0 || my0){ 140 tv = block_cmp(c, src, sstride, prev + mx0 * c->bypp + my0 * pstride, pstride, bw, bh, &txored); 141 if(tv < bv){ 142 bv = tv; 143 *mx = mx0; 144 *my = my0; 145 *xored = txored; 146 if(!bv) return 0; 147 } 148 } 149 150 /* Try other MVs from top-to-bottom, left-to-right */ 151 for(dy = -c->lrange; dy <= c->urange; dy++){ 152 for(dx = -c->lrange; dx <= c->urange; dx++){ 153 if(!dx && !dy) continue; // we already tested this block 154 if(dx == mx0 && dy == my0) continue; // this one too 155 tv = block_cmp(c, src, sstride, prev + dx * c->bypp + dy * pstride, pstride, bw, bh, &txored); 156 if(tv < bv){ 157 bv = tv; 158 *mx = dx; 159 *my = dy; 160 *xored = txored; 161 if(!bv) return 0; 162 } 163 } 164 } 165 return bv; 166} 167 168static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, 169 const AVFrame *pict, int *got_packet) 170{ 171 ZmbvEncContext * const c = avctx->priv_data; 172 z_stream *const zstream = &c->zstream.zstream; 173 const AVFrame * const p = pict; 174 uint8_t *src, *prev, *buf; 175 uint32_t *palptr; 176 int keyframe, chpal; 177 int fl; 178 int work_size = 0, pkt_size; 179 int bw, bh; 180 int i, j, ret; 181 182 keyframe = !c->curfrm; 183 c->curfrm++; 184 if(c->curfrm == c->keyint) 185 c->curfrm = 0; 186 187 palptr = (avctx->pix_fmt == AV_PIX_FMT_PAL8) ? (uint32_t *)p->data[1] : NULL; 188 chpal = !keyframe && palptr && memcmp(palptr, c->pal2, 1024); 189 190 src = p->data[0]; 191 prev = c->prev; 192 if(chpal){ 193 uint8_t tpal[3]; 194 for(i = 0; i < 256; i++){ 195 AV_WB24(tpal, palptr[i]); 196 c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0]; 197 c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1]; 198 c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2]; 199 c->pal[i * 3 + 0] = tpal[0]; 200 c->pal[i * 3 + 1] = tpal[1]; 201 c->pal[i * 3 + 2] = tpal[2]; 202 } 203 memcpy(c->pal2, palptr, 1024); 204 } 205 if(keyframe){ 206 if (palptr){ 207 for(i = 0; i < 256; i++){ 208 AV_WB24(c->pal+(i*3), palptr[i]); 209 } 210 memcpy(c->work_buf, c->pal, 768); 211 memcpy(c->pal2, palptr, 1024); 212 work_size = 768; 213 } 214 for(i = 0; i < avctx->height; i++){ 215 memcpy(c->work_buf + work_size, src, avctx->width * c->bypp); 216 src += p->linesize[0]; 217 work_size += avctx->width * c->bypp; 218 } 219 }else{ 220 int x, y, bh2, bw2, xored; 221 uint8_t *tsrc, *tprev; 222 uint8_t *mv; 223 int mx = 0, my = 0; 224 225 bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK; 226 bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK; 227 mv = c->work_buf + work_size; 228 memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3); 229 work_size += (bw * bh * 2 + 3) & ~3; 230 /* for now just XOR'ing */ 231 for(y = 0; y < avctx->height; y += ZMBV_BLOCK) { 232 bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK); 233 for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) { 234 bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK); 235 236 tsrc = src + x * c->bypp; 237 tprev = prev + x * c->bypp; 238 239 zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored); 240 mv[0] = (mx * 2) | !!xored; 241 mv[1] = my * 2; 242 tprev += mx * c->bypp + my * c->pstride; 243 if(xored){ 244 for(j = 0; j < bh2; j++){ 245 for(i = 0; i < bw2 * c->bypp; i++) 246 c->work_buf[work_size++] = tsrc[i] ^ tprev[i]; 247 tsrc += p->linesize[0]; 248 tprev += c->pstride; 249 } 250 } 251 } 252 src += p->linesize[0] * ZMBV_BLOCK; 253 prev += c->pstride * ZMBV_BLOCK; 254 } 255 } 256 /* save the previous frame */ 257 src = p->data[0]; 258 prev = c->prev; 259 for(i = 0; i < avctx->height; i++){ 260 memcpy(prev, src, avctx->width * c->bypp); 261 prev += c->pstride; 262 src += p->linesize[0]; 263 } 264 265 if (keyframe) 266 deflateReset(zstream); 267 268 zstream->next_in = c->work_buf; 269 zstream->avail_in = work_size; 270 zstream->total_in = 0; 271 272 zstream->next_out = c->comp_buf; 273 zstream->avail_out = c->comp_size; 274 zstream->total_out = 0; 275 if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) { 276 av_log(avctx, AV_LOG_ERROR, "Error compressing data\n"); 277 return -1; 278 } 279 280 pkt_size = zstream->total_out + 1 + 6 * keyframe; 281 if ((ret = ff_get_encode_buffer(avctx, pkt, pkt_size, 0)) < 0) 282 return ret; 283 buf = pkt->data; 284 285 fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0); 286 *buf++ = fl; 287 if (keyframe) { 288 *buf++ = 0; // hi ver 289 *buf++ = 1; // lo ver 290 *buf++ = 1; // comp 291 *buf++ = c->fmt; // format 292 *buf++ = ZMBV_BLOCK; // block width 293 *buf++ = ZMBV_BLOCK; // block height 294 pkt->flags |= AV_PKT_FLAG_KEY; 295 } 296 memcpy(buf, c->comp_buf, zstream->total_out); 297 298 *got_packet = 1; 299 300 return 0; 301} 302 303static av_cold int encode_end(AVCodecContext *avctx) 304{ 305 ZmbvEncContext * const c = avctx->priv_data; 306 307 av_freep(&c->comp_buf); 308 av_freep(&c->work_buf); 309 310 av_freep(&c->prev_buf); 311 ff_deflate_end(&c->zstream); 312 313 return 0; 314} 315 316/** 317 * Init zmbv encoder 318 */ 319static av_cold int encode_init(AVCodecContext *avctx) 320{ 321 ZmbvEncContext * const c = avctx->priv_data; 322 int i; 323 int lvl = 9; 324 int prev_size, prev_offset; 325 326 switch (avctx->pix_fmt) { 327 case AV_PIX_FMT_PAL8: 328 c->fmt = ZMBV_FMT_8BPP; 329 c->bypp = 1; 330 break; 331 case AV_PIX_FMT_RGB555LE: 332 c->fmt = ZMBV_FMT_15BPP; 333 c->bypp = 2; 334 break; 335 case AV_PIX_FMT_RGB565LE: 336 c->fmt = ZMBV_FMT_16BPP; 337 c->bypp = 2; 338 break; 339#ifdef ZMBV_ENABLE_24BPP 340 case AV_PIX_FMT_BGR24: 341 c->fmt = ZMBV_FMT_24BPP; 342 c->bypp = 3; 343 break; 344#endif //ZMBV_ENABLE_24BPP 345 case AV_PIX_FMT_BGR0: 346 c->fmt = ZMBV_FMT_32BPP; 347 c->bypp = 4; 348 break; 349 } 350 351 /* Entropy-based score tables for comparing blocks. 352 * Suitable for blocks up to (ZMBV_BLOCK * ZMBV_BLOCK) bytes. 353 * Scores are nonnegative, lower is better. 354 */ 355 for(i = 1; i <= ZMBV_BLOCK * ZMBV_BLOCK * c->bypp; i++) 356 c->score_tab[i] = -i * log2(i / (double)(ZMBV_BLOCK * ZMBV_BLOCK * c->bypp)) * 256; 357 358 c->avctx = avctx; 359 360 c->curfrm = 0; 361 c->keyint = avctx->keyint_min; 362 363 /* Motion estimation range: maximum distance is -64..63 */ 364 c->lrange = c->urange = 8; 365 if(avctx->me_range > 0){ 366 c->lrange = FFMIN(avctx->me_range, 64); 367 c->urange = FFMIN(avctx->me_range, 63); 368 } 369 370 if(avctx->compression_level >= 0) 371 lvl = avctx->compression_level; 372 if(lvl < 0 || lvl > 9){ 373 av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl); 374 return AVERROR(EINVAL); 375 } 376 377 c->comp_size = avctx->width * c->bypp * avctx->height + 1024 + 378 ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4; 379 if (!(c->work_buf = av_malloc(c->comp_size))) { 380 av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n"); 381 return AVERROR(ENOMEM); 382 } 383 /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */ 384 c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) + 385 ((c->comp_size + 63) >> 6) + 11; 386 387 /* Allocate compression buffer */ 388 if (!(c->comp_buf = av_malloc(c->comp_size))) { 389 av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n"); 390 return AVERROR(ENOMEM); 391 } 392 393 /* Allocate prev buffer - pad around the image to allow out-of-edge ME: 394 * - The image should be padded with `lrange` rows before and `urange` rows 395 * after. 396 * - The stride should be padded with `lrange` pixels, then rounded up to a 397 * multiple of 16 bytes. 398 * - The first row should also be padded with `lrange` pixels before, then 399 * aligned up to a multiple of 16 bytes. 400 */ 401 c->pstride = FFALIGN((avctx->width + c->lrange) * c->bypp, 16); 402 prev_size = FFALIGN(c->lrange * c->bypp, 16) + c->pstride * (c->lrange + avctx->height + c->urange); 403 prev_offset = FFALIGN(c->lrange * c->bypp, 16) + c->pstride * c->lrange; 404 if (!(c->prev_buf = av_mallocz(prev_size))) { 405 av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n"); 406 return AVERROR(ENOMEM); 407 } 408 c->prev = c->prev_buf + prev_offset; 409 410 return ff_deflate_init(&c->zstream, lvl, avctx); 411} 412 413const FFCodec ff_zmbv_encoder = { 414 .p.name = "zmbv", 415 .p.long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), 416 .p.type = AVMEDIA_TYPE_VIDEO, 417 .p.id = AV_CODEC_ID_ZMBV, 418 .p.capabilities = AV_CODEC_CAP_DR1, 419 .priv_data_size = sizeof(ZmbvEncContext), 420 .init = encode_init, 421 FF_CODEC_ENCODE_CB(encode_frame), 422 .close = encode_end, 423 .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8, 424 AV_PIX_FMT_RGB555LE, 425 AV_PIX_FMT_RGB565LE, 426#ifdef ZMBV_ENABLE_24BPP 427 AV_PIX_FMT_BGR24, 428#endif //ZMBV_ENABLE_24BPP 429 AV_PIX_FMT_BGR0, 430 AV_PIX_FMT_NONE }, 431 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, 432}; 433