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 "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, int dx, int dy,
00080 int h, int w, int stride, uint8_t *pfptr)
00081 {
00082 int i, j;
00083 uint8_t *nsptr;
00084 uint8_t *npfptr;
00085 int diff = 0;
00086
00087 for (i = dx + h; i > dx; i--) {
00088 nsptr = sptr + (i * stride) + dy * 3;
00089 npfptr = pfptr + (i * stride) + dy * 3;
00090 for (j = 0; j < w * 3; j++) {
00091 diff |= npfptr[j] ^ nsptr[j];
00092 dptr[j] = nsptr[j];
00093 }
00094 dptr += w * 3;
00095 }
00096 if (diff)
00097 return 1;
00098 return 0;
00099 }
00100
00101 static av_cold int flashsv_encode_init(AVCodecContext *avctx)
00102 {
00103 FlashSVContext *s = avctx->priv_data;
00104
00105 s->avctx = avctx;
00106
00107 if ((avctx->width > 4095) || (avctx->height > 4095)) {
00108 av_log(avctx, AV_LOG_ERROR, "Input dimensions too large, input must be max 4096x4096 !\n");
00109 return AVERROR_INVALIDDATA;
00110 }
00111
00112
00113 memset(&(s->zstream), 0, sizeof(z_stream));
00114
00115 s->last_key_frame = 0;
00116
00117 s->image_width = avctx->width;
00118 s->image_height = avctx->height;
00119
00120 s->tmpblock = av_mallocz(3 * 256 * 256);
00121 s->encbuffer = av_mallocz(s->image_width * s->image_height * 3);
00122
00123 if (!s->tmpblock || !s->encbuffer) {
00124 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00125 return AVERROR(ENOMEM);
00126 }
00127
00128 return 0;
00129 }
00130
00131
00132 static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf,
00133 int buf_size, int block_width, int block_height,
00134 uint8_t *previous_frame, int *I_frame)
00135 {
00136
00137 PutBitContext pb;
00138 int h_blocks, v_blocks, h_part, v_part, i, j;
00139 int buf_pos, res;
00140 int pred_blocks = 0;
00141
00142 init_put_bits(&pb, buf, buf_size * 8);
00143
00144 put_bits(&pb, 4, (block_width / 16) - 1);
00145 put_bits(&pb, 12, s->image_width);
00146 put_bits(&pb, 4, (block_height / 16) - 1);
00147 put_bits(&pb, 12, s->image_height);
00148 flush_put_bits(&pb);
00149 buf_pos = 4;
00150
00151 h_blocks = s->image_width / block_width;
00152 h_part = s->image_width % block_width;
00153 v_blocks = s->image_height / block_height;
00154 v_part = s->image_height % block_height;
00155
00156
00157 for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) {
00158
00159 int hp = j * block_height;
00160 int hs = (j < v_blocks) ? block_height : v_part;
00161
00162
00163 for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) {
00164 int wp = i * block_width;
00165 int ws = (i < h_blocks) ? block_width : h_part;
00166 int ret = Z_OK;
00167 uint8_t *ptr;
00168
00169 ptr = buf + buf_pos;
00170
00171
00172
00173 res = copy_region_enc(p->data[0], s->tmpblock,
00174 s->image_height - (hp + hs + 1),
00175 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,
00208 int buf_size, void *data)
00209 {
00210 FlashSVContext * const s = avctx->priv_data;
00211 AVFrame *pict = data;
00212 AVFrame * const p = &s->frame;
00213 uint8_t *pfptr;
00214 int res;
00215 int I_frame = 0;
00216 int opt_w, opt_h;
00217
00218 *p = *pict;
00219
00220
00221 if (avctx->frame_number == 0) {
00222 s->previous_frame = av_mallocz(FFABS(p->linesize[0]) * s->image_height);
00223 if (!s->previous_frame) {
00224 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00225 return AVERROR(ENOMEM);
00226 }
00227 I_frame = 1;
00228 }
00229
00230 if (p->linesize[0] < 0)
00231 pfptr = s->previous_frame - ((s->image_height - 1) * p->linesize[0]);
00232 else
00233 pfptr = s->previous_frame;
00234
00235
00236 if (avctx->gop_size > 0) {
00237 if (avctx->frame_number >= s->last_key_frame + avctx->gop_size) {
00238 I_frame = 1;
00239 }
00240 }
00241
00242 opt_w = 4;
00243 opt_h = 4;
00244
00245 if (buf_size < s->image_width*s->image_height*3) {
00246
00247 av_log(avctx, AV_LOG_ERROR, "buf_size %d < %d\n",
00248 buf_size, s->image_width * s->image_height * 3);
00249 return -1;
00250 }
00251
00252 res = encode_bitstream(s, p, buf, buf_size, opt_w * 16, opt_h * 16, pfptr, &I_frame);
00253
00254
00255 if (p->linesize[0] > 0)
00256 memcpy(s->previous_frame, p->data[0], s->image_height * p->linesize[0]);
00257 else
00258 memcpy(s->previous_frame, p->data[0] + p->linesize[0] * (s->image_height - 1),
00259 s->image_height * FFABS(p->linesize[0]));
00260
00261
00262 if (I_frame) {
00263 p->pict_type = AV_PICTURE_TYPE_I;
00264 p->key_frame = 1;
00265 s->last_key_frame = avctx->frame_number;
00266 av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n", avctx->frame_number);
00267 } else {
00268 p->pict_type = AV_PICTURE_TYPE_P;
00269 p->key_frame = 0;
00270 }
00271
00272 avctx->coded_frame = p;
00273
00274 return res;
00275 }
00276
00277 static av_cold int flashsv_encode_end(AVCodecContext *avctx)
00278 {
00279 FlashSVContext *s = avctx->priv_data;
00280
00281 deflateEnd(&(s->zstream));
00282
00283 av_free(s->encbuffer);
00284 av_free(s->previous_frame);
00285 av_free(s->tmpblock);
00286
00287 return 0;
00288 }
00289
00290 AVCodec ff_flashsv_encoder = {
00291 .name = "flashsv",
00292 .type = AVMEDIA_TYPE_VIDEO,
00293 .id = CODEC_ID_FLASHSV,
00294 .priv_data_size = sizeof(FlashSVContext),
00295 .init = flashsv_encode_init,
00296 .encode = flashsv_encode_frame,
00297 .close = flashsv_encode_end,
00298 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE},
00299 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"),
00300 };
00301