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 "internal.h"
00053 #include "put_bits.h"
00054 #include "bytestream.h"
00055
00056
00057 typedef struct FlashSVContext {
00058 AVCodecContext *avctx;
00059 uint8_t *previous_frame;
00060 AVFrame frame;
00061 int image_width, image_height;
00062 int block_width, block_height;
00063 uint8_t *tmpblock;
00064 uint8_t *encbuffer;
00065 int block_size;
00066 z_stream zstream;
00067 int last_key_frame;
00068 } FlashSVContext;
00069
00070 static int copy_region_enc(uint8_t *sptr, uint8_t *dptr, int dx, int dy,
00071 int h, int w, int stride, uint8_t *pfptr)
00072 {
00073 int i, j;
00074 uint8_t *nsptr;
00075 uint8_t *npfptr;
00076 int diff = 0;
00077
00078 for (i = dx + h; i > dx; i--) {
00079 nsptr = sptr + i * stride + dy * 3;
00080 npfptr = pfptr + i * stride + dy * 3;
00081 for (j = 0; j < w * 3; j++) {
00082 diff |= npfptr[j] ^ nsptr[j];
00083 dptr[j] = nsptr[j];
00084 }
00085 dptr += w * 3;
00086 }
00087 if (diff)
00088 return 1;
00089 return 0;
00090 }
00091
00092 static av_cold int flashsv_encode_init(AVCodecContext *avctx)
00093 {
00094 FlashSVContext *s = avctx->priv_data;
00095
00096 s->avctx = avctx;
00097
00098 if (avctx->width > 4095 || avctx->height > 4095) {
00099 av_log(avctx, AV_LOG_ERROR,
00100 "Input dimensions too large, input must be max 4096x4096 !\n");
00101 return AVERROR_INVALIDDATA;
00102 }
00103
00104
00105 memset(&s->zstream, 0, sizeof(z_stream));
00106
00107 s->last_key_frame = 0;
00108
00109 s->image_width = avctx->width;
00110 s->image_height = avctx->height;
00111
00112 s->tmpblock = av_mallocz(3 * 256 * 256);
00113 s->encbuffer = av_mallocz(s->image_width * s->image_height * 3);
00114
00115 if (!s->tmpblock || !s->encbuffer) {
00116 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00117 return AVERROR(ENOMEM);
00118 }
00119
00120 return 0;
00121 }
00122
00123
00124 static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf,
00125 int buf_size, int block_width, int block_height,
00126 uint8_t *previous_frame, int *I_frame)
00127 {
00128
00129 PutBitContext pb;
00130 int h_blocks, v_blocks, h_part, v_part, i, j;
00131 int buf_pos, res;
00132 int pred_blocks = 0;
00133
00134 init_put_bits(&pb, buf, buf_size * 8);
00135
00136 put_bits(&pb, 4, block_width / 16 - 1);
00137 put_bits(&pb, 12, s->image_width);
00138 put_bits(&pb, 4, block_height / 16 - 1);
00139 put_bits(&pb, 12, s->image_height);
00140 flush_put_bits(&pb);
00141 buf_pos = 4;
00142
00143 h_blocks = s->image_width / block_width;
00144 h_part = s->image_width % block_width;
00145 v_blocks = s->image_height / block_height;
00146 v_part = s->image_height % block_height;
00147
00148
00149 for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) {
00150
00151 int y_pos = j * block_height;
00152 int cur_blk_height = (j < v_blocks) ? block_height : v_part;
00153
00154
00155 for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) {
00156 int x_pos = i * block_width;
00157 int cur_blk_width = (i < h_blocks) ? block_width : h_part;
00158 int ret = Z_OK;
00159 uint8_t *ptr = buf + buf_pos;
00160
00161
00162
00163 res = copy_region_enc(p->data[0], s->tmpblock,
00164 s->image_height - (y_pos + cur_blk_height + 1),
00165 x_pos, cur_blk_height, cur_blk_width,
00166 p->linesize[0], previous_frame);
00167
00168 if (res || *I_frame) {
00169 unsigned long zsize = 3 * block_width * block_height;
00170 ret = compress2(ptr + 2, &zsize, s->tmpblock,
00171 3 * cur_blk_width * cur_blk_height, 9);
00172
00173
00174 if (ret != Z_OK)
00175 av_log(s->avctx, AV_LOG_ERROR,
00176 "error while compressing block %dx%d\n", i, j);
00177
00178 bytestream_put_be16(&ptr, zsize);
00179 buf_pos += zsize + 2;
00180 av_dlog(s->avctx, "buf_pos = %d\n", buf_pos);
00181 } else {
00182 pred_blocks++;
00183 bytestream_put_be16(&ptr, 0);
00184 buf_pos += 2;
00185 }
00186 }
00187 }
00188
00189 if (pred_blocks)
00190 *I_frame = 0;
00191 else
00192 *I_frame = 1;
00193
00194 return buf_pos;
00195 }
00196
00197
00198 static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
00199 const AVFrame *pict, int *got_packet)
00200 {
00201 FlashSVContext * const s = avctx->priv_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 ((res = ff_alloc_packet2(avctx, pkt, s->image_width * s->image_height * 3)) < 0)
00232 return res;
00233
00234 pkt->size = encode_bitstream(s, p, pkt->data, pkt->size, opt_w * 16, opt_h * 16,
00235 pfptr, &I_frame);
00236
00237
00238 if (p->linesize[0] > 0)
00239 memcpy(s->previous_frame, p->data[0], s->image_height * p->linesize[0]);
00240 else
00241 memcpy(s->previous_frame,
00242 p->data[0] + p->linesize[0] * (s->image_height - 1),
00243 s->image_height * FFABS(p->linesize[0]));
00244
00245
00246 if (I_frame) {
00247 p->pict_type = AV_PICTURE_TYPE_I;
00248 p->key_frame = 1;
00249 s->last_key_frame = avctx->frame_number;
00250 av_dlog(avctx, "Inserting keyframe at frame %d\n", avctx->frame_number);
00251 } else {
00252 p->pict_type = AV_PICTURE_TYPE_P;
00253 p->key_frame = 0;
00254 }
00255
00256 avctx->coded_frame = p;
00257
00258 if (p->key_frame)
00259 pkt->flags |= AV_PKT_FLAG_KEY;
00260 *got_packet = 1;
00261
00262 return 0;
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 = AV_CODEC_ID_FLASHSV,
00282 .priv_data_size = sizeof(FlashSVContext),
00283 .init = flashsv_encode_init,
00284 .encode2 = 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 };