00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <zlib.h>
00050
00051 #include "avcodec.h"
00052 #include "put_bits.h"
00053 #include "bytestream.h"
00054
00055
00056 typedef struct FlashSVContext {
00057 AVCodecContext *avctx;
00058 uint8_t *previous_frame;
00059 AVFrame frame;
00060 int image_width, image_height;
00061 int block_width, block_height;
00062 uint8_t *tmpblock;
00063 uint8_t *encbuffer;
00064 int block_size;
00065 z_stream zstream;
00066 int last_key_frame;
00067 } FlashSVContext;
00068
00069 static int copy_region_enc(uint8_t *sptr, uint8_t *dptr, int dx, int dy,
00070 int h, int w, int stride, uint8_t *pfptr)
00071 {
00072 int i, j;
00073 uint8_t *nsptr;
00074 uint8_t *npfptr;
00075 int diff = 0;
00076
00077 for (i = dx + h; i > dx; i--) {
00078 nsptr = sptr + i * stride + dy * 3;
00079 npfptr = pfptr + i * stride + dy * 3;
00080 for (j = 0; j < w * 3; j++) {
00081 diff |= npfptr[j] ^ nsptr[j];
00082 dptr[j] = nsptr[j];
00083 }
00084 dptr += w * 3;
00085 }
00086 if (diff)
00087 return 1;
00088 return 0;
00089 }
00090
00091 static av_cold int flashsv_encode_init(AVCodecContext *avctx)
00092 {
00093 FlashSVContext *s = avctx->priv_data;
00094
00095 s->avctx = avctx;
00096
00097 if (avctx->width > 4095 || avctx->height > 4095) {
00098 av_log(avctx, AV_LOG_ERROR,
00099 "Input dimensions too large, input must be max 4096x4096 !\n");
00100 return AVERROR_INVALIDDATA;
00101 }
00102
00103
00104 memset(&s->zstream, 0, sizeof(z_stream));
00105
00106 s->last_key_frame = 0;
00107
00108 s->image_width = avctx->width;
00109 s->image_height = avctx->height;
00110
00111 s->tmpblock = av_mallocz(3 * 256 * 256);
00112 s->encbuffer = av_mallocz(s->image_width * s->image_height * 3);
00113
00114 if (!s->tmpblock || !s->encbuffer) {
00115 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00116 return AVERROR(ENOMEM);
00117 }
00118
00119 return 0;
00120 }
00121
00122
00123 static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf,
00124 int buf_size, int block_width, int block_height,
00125 uint8_t *previous_frame, int *I_frame)
00126 {
00127
00128 PutBitContext pb;
00129 int h_blocks, v_blocks, h_part, v_part, i, j;
00130 int buf_pos, res;
00131 int pred_blocks = 0;
00132
00133 init_put_bits(&pb, buf, buf_size * 8);
00134
00135 put_bits(&pb, 4, block_width / 16 - 1);
00136 put_bits(&pb, 12, s->image_width);
00137 put_bits(&pb, 4, block_height / 16 - 1);
00138 put_bits(&pb, 12, s->image_height);
00139 flush_put_bits(&pb);
00140 buf_pos = 4;
00141
00142 h_blocks = s->image_width / block_width;
00143 h_part = s->image_width % block_width;
00144 v_blocks = s->image_height / block_height;
00145 v_part = s->image_height % block_height;
00146
00147
00148 for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) {
00149
00150 int y_pos = j * block_height;
00151 int cur_blk_height = (j < v_blocks) ? block_height : v_part;
00152
00153
00154 for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) {
00155 int x_pos = i * block_width;
00156 int cur_blk_width = (i < h_blocks) ? block_width : h_part;
00157 int ret = Z_OK;
00158 uint8_t *ptr = buf + buf_pos;
00159
00160
00161
00162 res = copy_region_enc(p->data[0], s->tmpblock,
00163 s->image_height - (y_pos + cur_blk_height + 1),
00164 x_pos, cur_blk_height, cur_blk_width,
00165 p->linesize[0], previous_frame);
00166
00167 if (res || *I_frame) {
00168 unsigned long zsize = 3 * block_width * block_height;
00169 ret = compress2(ptr + 2, &zsize, s->tmpblock,
00170 3 * cur_blk_width * cur_blk_height, 9);
00171
00172
00173 if (ret != Z_OK)
00174 av_log(s->avctx, AV_LOG_ERROR,
00175 "error while compressing block %dx%d\n", i, j);
00176
00177 bytestream_put_be16(&ptr, zsize);
00178 buf_pos += zsize + 2;
00179 av_dlog(s->avctx, "buf_pos = %d\n", buf_pos);
00180 } else {
00181 pred_blocks++;
00182 bytestream_put_be16(&ptr, 0);
00183 buf_pos += 2;
00184 }
00185 }
00186 }
00187
00188 if (pred_blocks)
00189 *I_frame = 0;
00190 else
00191 *I_frame = 1;
00192
00193 return buf_pos;
00194 }
00195
00196
00197 static int flashsv_encode_frame(AVCodecContext *avctx, uint8_t *buf,
00198 int buf_size, void *data)
00199 {
00200 FlashSVContext * const s = avctx->priv_data;
00201 AVFrame *pict = data;
00202 AVFrame * const p = &s->frame;
00203 uint8_t *pfptr;
00204 int res;
00205 int I_frame = 0;
00206 int opt_w = 4, opt_h = 4;
00207
00208 *p = *pict;
00209
00210
00211 if (avctx->frame_number == 0) {
00212 s->previous_frame = av_mallocz(FFABS(p->linesize[0]) * s->image_height);
00213 if (!s->previous_frame) {
00214 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00215 return AVERROR(ENOMEM);
00216 }
00217 I_frame = 1;
00218 }
00219
00220 if (p->linesize[0] < 0)
00221 pfptr = s->previous_frame - (s->image_height - 1) * p->linesize[0];
00222 else
00223 pfptr = s->previous_frame;
00224
00225
00226 if (avctx->gop_size > 0 &&
00227 avctx->frame_number >= s->last_key_frame + avctx->gop_size) {
00228 I_frame = 1;
00229 }
00230
00231 if (buf_size < s->image_width * s->image_height * 3) {
00232
00233 av_log(avctx, AV_LOG_ERROR, "buf_size %d < %d\n",
00234 buf_size, s->image_width * s->image_height * 3);
00235 return -1;
00236 }
00237
00238 res = encode_bitstream(s, p, buf, buf_size, opt_w * 16, opt_h * 16,
00239 pfptr, &I_frame);
00240
00241
00242 if (p->linesize[0] > 0)
00243 memcpy(s->previous_frame, p->data[0], s->image_height * p->linesize[0]);
00244 else
00245 memcpy(s->previous_frame,
00246 p->data[0] + p->linesize[0] * (s->image_height - 1),
00247 s->image_height * FFABS(p->linesize[0]));
00248
00249
00250 if (I_frame) {
00251 p->pict_type = AV_PICTURE_TYPE_I;
00252 p->key_frame = 1;
00253 s->last_key_frame = avctx->frame_number;
00254 av_dlog(avctx, "Inserting keyframe at frame %d\n", avctx->frame_number);
00255 } else {
00256 p->pict_type = AV_PICTURE_TYPE_P;
00257 p->key_frame = 0;
00258 }
00259
00260 avctx->coded_frame = p;
00261
00262 return res;
00263 }
00264
00265 static av_cold int flashsv_encode_end(AVCodecContext *avctx)
00266 {
00267 FlashSVContext *s = avctx->priv_data;
00268
00269 deflateEnd(&s->zstream);
00270
00271 av_free(s->encbuffer);
00272 av_free(s->previous_frame);
00273 av_free(s->tmpblock);
00274
00275 return 0;
00276 }
00277
00278 AVCodec ff_flashsv_encoder = {
00279 .name = "flashsv",
00280 .type = AVMEDIA_TYPE_VIDEO,
00281 .id = CODEC_ID_FLASHSV,
00282 .priv_data_size = sizeof(FlashSVContext),
00283 .init = flashsv_encode_init,
00284 .encode = flashsv_encode_frame,
00285 .close = flashsv_encode_end,
00286 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_NONE},
00287 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"),
00288 };
00289