Libav
|
00001 /* 00002 * Zip Motion Blocks Video (ZMBV) encoder 00003 * Copyright (c) 2006 Konstantin Shishkov 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 00030 #include "libavutil/intreadwrite.h" 00031 #include "avcodec.h" 00032 00033 #include <zlib.h> 00034 00035 #define ZMBV_KEYFRAME 1 00036 #define ZMBV_DELTAPAL 2 00037 00038 #define ZMBV_BLOCK 16 00039 00043 typedef struct ZmbvEncContext { 00044 AVCodecContext *avctx; 00045 AVFrame pic; 00046 00047 int range; 00048 uint8_t *comp_buf, *work_buf; 00049 uint8_t pal[768]; 00050 uint32_t pal2[256]; //for quick comparisons 00051 uint8_t *prev; 00052 int pstride; 00053 int comp_size; 00054 int keyint, curfrm; 00055 z_stream zstream; 00056 } ZmbvEncContext; 00057 00058 static int score_tab[256]; 00059 00064 static inline int block_cmp(uint8_t *src, int stride, uint8_t *src2, int stride2, 00065 int bw, int bh, int *xored) 00066 { 00067 int sum = 0; 00068 int i, j; 00069 uint8_t histogram[256] = {0}; 00070 00071 *xored = 0; 00072 for(j = 0; j < bh; j++){ 00073 for(i = 0; i < bw; i++){ 00074 int t = src[i] ^ src2[i]; 00075 histogram[t]++; 00076 *xored |= t; 00077 } 00078 src += stride; 00079 src2 += stride2; 00080 } 00081 00082 for(i = 1; i < 256; i++) 00083 sum += score_tab[histogram[i]]; 00084 00085 return sum; 00086 } 00087 00091 static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev, 00092 int pstride, int x, int y, int *mx, int *my, int *xored) 00093 { 00094 int dx, dy, tx, ty, tv, bv, bw, bh; 00095 00096 *mx = *my = 0; 00097 bw = FFMIN(ZMBV_BLOCK, c->avctx->width - x); 00098 bh = FFMIN(ZMBV_BLOCK, c->avctx->height - y); 00099 bv = block_cmp(src, sstride, prev, pstride, bw, bh, xored); 00100 if(!bv) return 0; 00101 for(ty = FFMAX(y - c->range, 0); ty < FFMIN(y + c->range, c->avctx->height - bh); ty++){ 00102 for(tx = FFMAX(x - c->range, 0); tx < FFMIN(x + c->range, c->avctx->width - bw); tx++){ 00103 if(tx == x && ty == y) continue; // we already tested this block 00104 dx = tx - x; 00105 dy = ty - y; 00106 tv = block_cmp(src, sstride, prev + dx + dy*pstride, pstride, bw, bh, xored); 00107 if(tv < bv){ 00108 bv = tv; 00109 *mx = dx; 00110 *my = dy; 00111 if(!bv) return 0; 00112 } 00113 } 00114 } 00115 return bv; 00116 } 00117 00118 static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data) 00119 { 00120 ZmbvEncContext * const c = avctx->priv_data; 00121 AVFrame *pict = data; 00122 AVFrame * const p = &c->pic; 00123 uint8_t *src, *prev; 00124 uint32_t *palptr; 00125 int len = 0; 00126 int keyframe, chpal; 00127 int fl; 00128 int work_size = 0; 00129 int bw, bh; 00130 int i, j; 00131 00132 keyframe = !c->curfrm; 00133 c->curfrm++; 00134 if(c->curfrm == c->keyint) 00135 c->curfrm = 0; 00136 *p = *pict; 00137 p->pict_type= keyframe ? FF_I_TYPE : FF_P_TYPE; 00138 p->key_frame= keyframe; 00139 chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024); 00140 00141 fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0); 00142 *buf++ = fl; len++; 00143 if(keyframe){ 00144 deflateReset(&c->zstream); 00145 *buf++ = 0; len++; // hi ver 00146 *buf++ = 1; len++; // lo ver 00147 *buf++ = 1; len++; // comp 00148 *buf++ = 4; len++; // format - 8bpp 00149 *buf++ = ZMBV_BLOCK; len++; // block width 00150 *buf++ = ZMBV_BLOCK; len++; // block height 00151 } 00152 palptr = (uint32_t*)p->data[1]; 00153 src = p->data[0]; 00154 prev = c->prev; 00155 if(chpal){ 00156 uint8_t tpal[3]; 00157 for(i = 0; i < 256; i++){ 00158 AV_WB24(tpal, palptr[i]); 00159 c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0]; 00160 c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1]; 00161 c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2]; 00162 c->pal[i * 3 + 0] = tpal[0]; 00163 c->pal[i * 3 + 1] = tpal[1]; 00164 c->pal[i * 3 + 2] = tpal[2]; 00165 } 00166 memcpy(c->pal2, p->data[1], 1024); 00167 } 00168 if(keyframe){ 00169 for(i = 0; i < 256; i++){ 00170 AV_WB24(c->pal+(i*3), palptr[i]); 00171 } 00172 memcpy(c->work_buf, c->pal, 768); 00173 memcpy(c->pal2, p->data[1], 1024); 00174 work_size = 768; 00175 for(i = 0; i < avctx->height; i++){ 00176 memcpy(c->work_buf + work_size, src, avctx->width); 00177 src += p->linesize[0]; 00178 work_size += avctx->width; 00179 } 00180 }else{ 00181 int x, y, bh2, bw2, xored; 00182 uint8_t *tsrc, *tprev; 00183 uint8_t *mv; 00184 int mx, my, bv; 00185 00186 bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK; 00187 bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK; 00188 mv = c->work_buf + work_size; 00189 memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3); 00190 work_size += (bw * bh * 2 + 3) & ~3; 00191 /* for now just XOR'ing */ 00192 for(y = 0; y < avctx->height; y += ZMBV_BLOCK) { 00193 bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK); 00194 for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) { 00195 bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK); 00196 00197 tsrc = src + x; 00198 tprev = prev + x; 00199 00200 bv = zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored); 00201 mv[0] = (mx << 1) | !!xored; 00202 mv[1] = my << 1; 00203 tprev += mx + my * c->pstride; 00204 if(xored){ 00205 for(j = 0; j < bh2; j++){ 00206 for(i = 0; i < bw2; i++) 00207 c->work_buf[work_size++] = tsrc[i] ^ tprev[i]; 00208 tsrc += p->linesize[0]; 00209 tprev += c->pstride; 00210 } 00211 } 00212 } 00213 src += p->linesize[0] * ZMBV_BLOCK; 00214 prev += c->pstride * ZMBV_BLOCK; 00215 } 00216 } 00217 /* save the previous frame */ 00218 src = p->data[0]; 00219 prev = c->prev; 00220 for(i = 0; i < avctx->height; i++){ 00221 memcpy(prev, src, avctx->width); 00222 prev += c->pstride; 00223 src += p->linesize[0]; 00224 } 00225 00226 c->zstream.next_in = c->work_buf; 00227 c->zstream.avail_in = work_size; 00228 c->zstream.total_in = 0; 00229 00230 c->zstream.next_out = c->comp_buf; 00231 c->zstream.avail_out = c->comp_size; 00232 c->zstream.total_out = 0; 00233 if(deflate(&c->zstream, Z_SYNC_FLUSH) != Z_OK){ 00234 av_log(avctx, AV_LOG_ERROR, "Error compressing data\n"); 00235 return -1; 00236 } 00237 00238 memcpy(buf, c->comp_buf, c->zstream.total_out); 00239 return len + c->zstream.total_out; 00240 } 00241 00242 00246 static av_cold int encode_init(AVCodecContext *avctx) 00247 { 00248 ZmbvEncContext * const c = avctx->priv_data; 00249 int zret; // Zlib return code 00250 int i; 00251 int lvl = 9; 00252 00253 for(i=1; i<256; i++) 00254 score_tab[i]= -i * log(i/(double)(ZMBV_BLOCK*ZMBV_BLOCK)) * (256/M_LN2); 00255 00256 c->avctx = avctx; 00257 00258 c->curfrm = 0; 00259 c->keyint = avctx->keyint_min; 00260 c->range = 8; 00261 if(avctx->me_range > 0) 00262 c->range = FFMIN(avctx->me_range, 127); 00263 00264 if(avctx->compression_level >= 0) 00265 lvl = avctx->compression_level; 00266 if(lvl < 0 || lvl > 9){ 00267 av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl); 00268 return -1; 00269 } 00270 00271 // Needed if zlib unused or init aborted before deflateInit 00272 memset(&(c->zstream), 0, sizeof(z_stream)); 00273 c->comp_size = avctx->width * avctx->height + 1024 + 00274 ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4; 00275 if ((c->work_buf = av_malloc(c->comp_size)) == NULL) { 00276 av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n"); 00277 return -1; 00278 } 00279 /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */ 00280 c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) + 00281 ((c->comp_size + 63) >> 6) + 11; 00282 00283 /* Allocate compression buffer */ 00284 if ((c->comp_buf = av_malloc(c->comp_size)) == NULL) { 00285 av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n"); 00286 return -1; 00287 } 00288 c->pstride = FFALIGN(avctx->width, 16); 00289 if ((c->prev = av_malloc(c->pstride * avctx->height)) == NULL) { 00290 av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n"); 00291 return -1; 00292 } 00293 00294 c->zstream.zalloc = Z_NULL; 00295 c->zstream.zfree = Z_NULL; 00296 c->zstream.opaque = Z_NULL; 00297 zret = deflateInit(&(c->zstream), lvl); 00298 if (zret != Z_OK) { 00299 av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); 00300 return -1; 00301 } 00302 00303 avctx->coded_frame = (AVFrame*)&c->pic; 00304 00305 return 0; 00306 } 00307 00308 00309 00313 static av_cold int encode_end(AVCodecContext *avctx) 00314 { 00315 ZmbvEncContext * const c = avctx->priv_data; 00316 00317 av_freep(&c->comp_buf); 00318 av_freep(&c->work_buf); 00319 00320 deflateEnd(&(c->zstream)); 00321 av_freep(&c->prev); 00322 00323 return 0; 00324 } 00325 00326 AVCodec zmbv_encoder = { 00327 "zmbv", 00328 AVMEDIA_TYPE_VIDEO, 00329 CODEC_ID_ZMBV, 00330 sizeof(ZmbvEncContext), 00331 encode_init, 00332 encode_frame, 00333 encode_end, 00334 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_PAL8, PIX_FMT_NONE}, 00335 .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), 00336 };