Libav
|
00001 /* 00002 * Flash Screen Video encoder 00003 * Copyright (C) 2004 Alex Beregszaszi 00004 * Copyright (C) 2006 Benjamin Larsson 00005 * 00006 * This file is part of FFmpeg. 00007 * 00008 * FFmpeg is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * FFmpeg is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with FFmpeg; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 /* Encoding development sponsored by http://fh-campuswien.ac.at */ 00024 00032 /* Bitstream description 00033 * The picture is divided into blocks that are zlib-compressed. 00034 * 00035 * The decoder is fed complete frames, the frameheader contains: 00036 * 4bits of block width 00037 * 12bits of frame width 00038 * 4bits of block height 00039 * 12bits of frame height 00040 * 00041 * Directly after the header are the compressed blocks. The blocks 00042 * have their compressed size represented with 16bits in the beginig. 00043 * If the size = 0 then the block is unchanged from the previous frame. 00044 * All blocks are decompressed until the buffer is consumed. 00045 * 00046 * Encoding ideas, a basic encoder would just use a fixed block size. 00047 * Block sizes can be multipels of 16, from 16 to 256. The blocks don't 00048 * have to be quadratic. A brute force search with a set of different 00049 * block sizes should give a better result than to just use a fixed size. 00050 */ 00051 00052 /* TODO: 00053 * Don't reencode the frame in brute force mode if the frame is a dupe. Speed up. 00054 * Make the difference check faster. 00055 */ 00056 00057 #include <stdio.h> 00058 #include <stdlib.h> 00059 #include <zlib.h> 00060 00061 #include "avcodec.h" 00062 #include "put_bits.h" 00063 #include "bytestream.h" 00064 00065 00066 typedef struct FlashSVContext { 00067 AVCodecContext *avctx; 00068 uint8_t *previous_frame; 00069 AVFrame frame; 00070 int image_width, image_height; 00071 int block_width, block_height; 00072 uint8_t* tmpblock; 00073 uint8_t* encbuffer; 00074 int block_size; 00075 z_stream zstream; 00076 int last_key_frame; 00077 } FlashSVContext; 00078 00079 static int copy_region_enc(uint8_t *sptr, uint8_t *dptr, 00080 int dx, int dy, int h, int w, int stride, uint8_t *pfptr) { 00081 int i,j; 00082 uint8_t *nsptr; 00083 uint8_t *npfptr; 00084 int diff = 0; 00085 00086 for (i = dx+h; i > dx; i--) { 00087 nsptr = sptr+(i*stride)+dy*3; 00088 npfptr = pfptr+(i*stride)+dy*3; 00089 for (j=0 ; j<w*3 ; j++) { 00090 diff |=npfptr[j]^nsptr[j]; 00091 dptr[j] = nsptr[j]; 00092 } 00093 dptr += w*3; 00094 } 00095 if (diff) 00096 return 1; 00097 return 0; 00098 } 00099 00100 static av_cold int flashsv_encode_init(AVCodecContext *avctx) 00101 { 00102 FlashSVContext *s = avctx->priv_data; 00103 00104 s->avctx = avctx; 00105 00106 if ((avctx->width > 4095) || (avctx->height > 4095)) { 00107 av_log(avctx, AV_LOG_ERROR, "Input dimensions too large, input must be max 4096x4096 !\n"); 00108 return -1; 00109 } 00110 00111 // Needed if zlib unused or init aborted before deflateInit 00112 memset(&(s->zstream), 0, sizeof(z_stream)); 00113 00114 s->last_key_frame=0; 00115 00116 s->image_width = avctx->width; 00117 s->image_height = avctx->height; 00118 00119 s->tmpblock = av_mallocz(3*256*256); 00120 s->encbuffer = av_mallocz(s->image_width*s->image_height*3); 00121 00122 if (!s->tmpblock || !s->encbuffer) { 00123 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); 00124 return -1; 00125 } 00126 00127 return 0; 00128 } 00129 00130 00131 static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf, int buf_size, 00132 int block_width, int block_height, uint8_t *previous_frame, int* I_frame) { 00133 00134 PutBitContext pb; 00135 int h_blocks, v_blocks, h_part, v_part, i, j; 00136 int buf_pos, res; 00137 int pred_blocks = 0; 00138 00139 init_put_bits(&pb, buf, buf_size*8); 00140 00141 put_bits(&pb, 4, (block_width/16)-1); 00142 put_bits(&pb, 12, s->image_width); 00143 put_bits(&pb, 4, (block_height/16)-1); 00144 put_bits(&pb, 12, s->image_height); 00145 flush_put_bits(&pb); 00146 buf_pos=4; 00147 00148 h_blocks = s->image_width / block_width; 00149 h_part = s->image_width % block_width; 00150 v_blocks = s->image_height / block_height; 00151 v_part = s->image_height % block_height; 00152 00153 /* loop over all block columns */ 00154 for (j = 0; j < v_blocks + (v_part?1:0); j++) 00155 { 00156 00157 int hp = j*block_height; // horiz position in frame 00158 int hs = (j<v_blocks)?block_height:v_part; // size of block 00159 00160 /* loop over all block rows */ 00161 for (i = 0; i < h_blocks + (h_part?1:0); i++) 00162 { 00163 int wp = i*block_width; // vert position in frame 00164 int ws = (i<h_blocks)?block_width:h_part; // size of block 00165 int ret=Z_OK; 00166 uint8_t *ptr; 00167 00168 ptr = buf+buf_pos; 00169 00170 //copy the block to the temp buffer before compression (if it differs from the previous frame's block) 00171 res = copy_region_enc(p->data[0], s->tmpblock, s->image_height-(hp+hs+1), wp, hs, ws, p->linesize[0], previous_frame); 00172 00173 if (res || *I_frame) { 00174 unsigned long zsize; 00175 zsize = 3*block_width*block_height; 00176 ret = compress2(ptr+2, &zsize, s->tmpblock, 3*ws*hs, 9); 00177 00178 00179 //ret = deflateReset(&(s->zstream)); 00180 if (ret != Z_OK) 00181 av_log(s->avctx, AV_LOG_ERROR, "error while compressing block %dx%d\n", i, j); 00182 00183 bytestream_put_be16(&ptr,(unsigned int)zsize); 00184 buf_pos += zsize+2; 00185 //av_log(avctx, AV_LOG_ERROR, "buf_pos = %d\n", buf_pos); 00186 } else { 00187 pred_blocks++; 00188 bytestream_put_be16(&ptr,0); 00189 buf_pos += 2; 00190 } 00191 } 00192 } 00193 00194 if (pred_blocks) 00195 *I_frame = 0; 00196 else 00197 *I_frame = 1; 00198 00199 return buf_pos; 00200 } 00201 00202 00203 static int flashsv_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data) 00204 { 00205 FlashSVContext * const s = avctx->priv_data; 00206 AVFrame *pict = data; 00207 AVFrame * const p = &s->frame; 00208 uint8_t *pfptr; 00209 int res; 00210 int I_frame = 0; 00211 int opt_w, opt_h; 00212 00213 *p = *pict; 00214 00215 /* First frame needs to be a keyframe */ 00216 if (avctx->frame_number == 0) { 00217 s->previous_frame = av_mallocz(FFABS(p->linesize[0])*s->image_height); 00218 if (!s->previous_frame) { 00219 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); 00220 return -1; 00221 } 00222 I_frame = 1; 00223 } 00224 00225 if (p->linesize[0] < 0) 00226 pfptr = s->previous_frame - ((s->image_height-1) * p->linesize[0]); 00227 else 00228 pfptr = s->previous_frame; 00229 00230 /* Check the placement of keyframes */ 00231 if (avctx->gop_size > 0) { 00232 if (avctx->frame_number >= s->last_key_frame + avctx->gop_size) { 00233 I_frame = 1; 00234 } 00235 } 00236 00237 opt_w=4; 00238 opt_h=4; 00239 00240 if (buf_size < s->image_width*s->image_height*3) { 00241 //Conservative upper bound check for compressed data 00242 av_log(avctx, AV_LOG_ERROR, "buf_size %d < %d\n", buf_size, s->image_width*s->image_height*3); 00243 return -1; 00244 } 00245 00246 res = encode_bitstream(s, p, buf, buf_size, opt_w*16, opt_h*16, pfptr, &I_frame); 00247 00248 //save the current frame 00249 if(p->linesize[0] > 0) 00250 memcpy(s->previous_frame, p->data[0], s->image_height*p->linesize[0]); 00251 else 00252 memcpy(s->previous_frame, p->data[0] + p->linesize[0] * (s->image_height-1), s->image_height*FFABS(p->linesize[0])); 00253 00254 //mark the frame type so the muxer can mux it correctly 00255 if (I_frame) { 00256 p->pict_type = FF_I_TYPE; 00257 p->key_frame = 1; 00258 s->last_key_frame = avctx->frame_number; 00259 av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n",avctx->frame_number); 00260 } else { 00261 p->pict_type = FF_P_TYPE; 00262 p->key_frame = 0; 00263 } 00264 00265 avctx->coded_frame = p; 00266 00267 return res; 00268 } 00269 00270 static av_cold int flashsv_encode_end(AVCodecContext *avctx) 00271 { 00272 FlashSVContext *s = avctx->priv_data; 00273 00274 deflateEnd(&(s->zstream)); 00275 00276 av_free(s->encbuffer); 00277 av_free(s->previous_frame); 00278 av_free(s->tmpblock); 00279 00280 return 0; 00281 } 00282 00283 AVCodec flashsv_encoder = { 00284 "flashsv", 00285 AVMEDIA_TYPE_VIDEO, 00286 CODEC_ID_FLASHSV, 00287 sizeof(FlashSVContext), 00288 flashsv_encode_init, 00289 flashsv_encode_frame, 00290 flashsv_encode_end, 00291 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE}, 00292 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"), 00293 }; 00294