00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <stdio.h>
00058 #include <stdlib.h>
00059 #include <zlib.h>
00060
00061 #include "avcodec.h"
00062 #include "bitstream.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 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
00112 return -1;
00113 }
00114
00115
00116 memset(&(s->zstream), 0, sizeof(z_stream));
00117
00118 s->last_key_frame=0;
00119
00120 s->image_width = avctx->width;
00121 s->image_height = avctx->height;
00122
00123 s->tmpblock = av_mallocz(3*256*256);
00124 s->encbuffer = av_mallocz(s->image_width*s->image_height*3);
00125
00126 if (!s->tmpblock || !s->encbuffer) {
00127 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00128 return -1;
00129 }
00130
00131 return 0;
00132 }
00133
00134
00135 static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf, int buf_size,
00136 int block_width, int block_height, uint8_t *previous_frame, int* I_frame) {
00137
00138 PutBitContext pb;
00139 int h_blocks, v_blocks, h_part, v_part, i, j;
00140 int buf_pos, res;
00141 int pred_blocks = 0;
00142
00143 init_put_bits(&pb, buf, buf_size*8);
00144
00145 put_bits(&pb, 4, (block_width/16)-1);
00146 put_bits(&pb, 12, s->image_width);
00147 put_bits(&pb, 4, (block_height/16)-1);
00148 put_bits(&pb, 12, s->image_height);
00149 flush_put_bits(&pb);
00150 buf_pos=4;
00151
00152 h_blocks = s->image_width / block_width;
00153 h_part = s->image_width % block_width;
00154 v_blocks = s->image_height / block_height;
00155 v_part = s->image_height % block_height;
00156
00157
00158 for (j = 0; j < v_blocks + (v_part?1:0); j++)
00159 {
00160
00161 int hp = j*block_height;
00162 int hs = (j<v_blocks)?block_height:v_part;
00163
00164
00165 for (i = 0; i < h_blocks + (h_part?1:0); i++)
00166 {
00167 int wp = i*block_width;
00168 int ws = (i<h_blocks)?block_width:h_part;
00169 int ret=Z_OK;
00170 uint8_t *ptr;
00171
00172 ptr = buf+buf_pos;
00173
00174
00175 res = copy_region_enc(p->data[0], s->tmpblock, s->image_height-(hp+hs+1), wp, hs, ws, p->linesize[0], previous_frame);
00176
00177 if (res || *I_frame) {
00178 unsigned long zsize;
00179 zsize = 3*block_width*block_height;
00180 ret = compress2(ptr+2, &zsize, s->tmpblock, 3*ws*hs, 9);
00181
00182
00183
00184 if (ret != Z_OK)
00185 av_log(s->avctx, AV_LOG_ERROR, "error while compressing block %dx%d\n", i, j);
00186
00187 bytestream_put_be16(&ptr,(unsigned int)zsize);
00188 buf_pos += zsize+2;
00189
00190 } else {
00191 pred_blocks++;
00192 bytestream_put_be16(&ptr,0);
00193 buf_pos += 2;
00194 }
00195 }
00196 }
00197
00198 if (pred_blocks)
00199 *I_frame = 0;
00200 else
00201 *I_frame = 1;
00202
00203 return buf_pos;
00204 }
00205
00206
00207 static int flashsv_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
00208 {
00209 FlashSVContext * const s = avctx->priv_data;
00210 AVFrame *pict = data;
00211 AVFrame * const p = &s->frame;
00212 uint8_t *pfptr;
00213 int res;
00214 int I_frame = 0;
00215 int opt_w, opt_h;
00216
00217 *p = *pict;
00218
00219
00220 if (avctx->frame_number == 0) {
00221 s->previous_frame = av_mallocz(FFABS(p->linesize[0])*s->image_height);
00222 if (!s->previous_frame) {
00223 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00224 return -1;
00225 }
00226 I_frame = 1;
00227 }
00228
00229 if (p->linesize[0] < 0)
00230 pfptr = s->previous_frame - ((s->image_height-1) * p->linesize[0]);
00231 else
00232 pfptr = s->previous_frame;
00233
00234
00235 if (avctx->gop_size > 0) {
00236 if (avctx->frame_number >= s->last_key_frame + avctx->gop_size) {
00237 I_frame = 1;
00238 }
00239 }
00240
00241 opt_w=4;
00242 opt_h=4;
00243
00244 if (buf_size < s->image_width*s->image_height*3) {
00245
00246 av_log(avctx, AV_LOG_ERROR, "buf_size %d < %d\n", buf_size, s->image_width*s->image_height*3);
00247 return -1;
00248 }
00249
00250 res = encode_bitstream(s, p, buf, buf_size, opt_w*16, opt_h*16, pfptr, &I_frame);
00251
00252
00253 if(p->linesize[0] > 0)
00254 memcpy(s->previous_frame, p->data[0], s->image_height*p->linesize[0]);
00255 else
00256 memcpy(s->previous_frame, p->data[0] + p->linesize[0] * (s->image_height-1), s->image_height*FFABS(p->linesize[0]));
00257
00258
00259 if (I_frame) {
00260 p->pict_type = FF_I_TYPE;
00261 p->key_frame = 1;
00262 s->last_key_frame = avctx->frame_number;
00263 av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n",avctx->frame_number);
00264 } else {
00265 p->pict_type = FF_P_TYPE;
00266 p->key_frame = 0;
00267 }
00268
00269 avctx->coded_frame = p;
00270
00271 return res;
00272 }
00273
00274 static av_cold int flashsv_encode_end(AVCodecContext *avctx)
00275 {
00276 FlashSVContext *s = avctx->priv_data;
00277
00278 deflateEnd(&(s->zstream));
00279
00280 av_free(s->encbuffer);
00281 av_free(s->previous_frame);
00282 av_free(s->tmpblock);
00283
00284 return 0;
00285 }
00286
00287 AVCodec flashsv_encoder = {
00288 "flashsv",
00289 CODEC_TYPE_VIDEO,
00290 CODEC_ID_FLASHSV,
00291 sizeof(FlashSVContext),
00292 flashsv_encode_init,
00293 flashsv_encode_frame,
00294 flashsv_encode_end,
00295 .pix_fmts = (enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE},
00296 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"),
00297 };
00298