Statistics
| Branch: | Revision:

ffmpeg / libavcodec / flashsvenc.c @ 2029f312

History | View | Annotate | Download (10.2 KB)

1
/*
2
 * Flash Screen Video encoder
3
 * Copyright (C) 2004 Alex Beregszaszi
4
 * Copyright (C) 2006 Benjamin Larsson
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22

    
23
/* Encoding development sponsored by http://fh-campuswien.ac.at */
24

    
25
/**
26
 * @file flashsvenc.c
27
 * Flash Screen Video encoder
28
 * @author Alex Beregszaszi
29
 * @author Benjamin Larsson
30
 */
31

    
32
/* Bitstream description
33
 * The picture is divided into blocks that are zlib-compressed.
34
 *
35
 * The decoder is fed complete frames, the frameheader contains:
36
 * 4bits of block width
37
 * 12bits of frame width
38
 * 4bits of block height
39
 * 12bits of frame height
40
 *
41
 * Directly after the header are the compressed blocks. The blocks
42
 * have their compressed size represented with 16bits in the beginig.
43
 * If the size = 0 then the block is unchanged from the previous frame.
44
 * All blocks are decompressed until the buffer is consumed.
45
 *
46
 * Encoding ideas, a basic encoder would just use a fixed block size.
47
 * Block sizes can be multipels of 16, from 16 to 256. The blocks don't
48
 * have to be quadratic. A brute force search with a set of different
49
 * block sizes should give a better result than to just use a fixed size.
50
 */
51

    
52
/* TODO:
53
 * Don't reencode the frame in brute force mode if the frame is a dupe. Speed up.
54
 * Make the difference check faster.
55
 */
56

    
57
#include <stdio.h>
58
#include <stdlib.h>
59
#include <zlib.h>
60

    
61
#include "avcodec.h"
62
#include "bitstream.h"
63
#include "bytestream.h"
64

    
65

    
66
typedef struct FlashSVContext {
67
    AVCodecContext *avctx;
68
    uint8_t *previous_frame;
69
    AVFrame frame;
70
    int image_width, image_height;
71
    int block_width, block_height;
72
    uint8_t* tmpblock;
73
    uint8_t* encbuffer;
74
    int block_size;
75
    z_stream zstream;
76
    int last_key_frame;
77
} FlashSVContext;
78

    
79
static int copy_region_enc(uint8_t *sptr, uint8_t *dptr,
80
        int dx, int dy, int h, int w, int stride, uint8_t *pfptr) {
81
    int i,j;
82
    uint8_t *nsptr;
83
    uint8_t *npfptr;
84
    int diff = 0;
85

    
86
    for (i = dx+h; i > dx; i--) {
87
        nsptr = sptr+(i*stride)+dy*3;
88
        npfptr = pfptr+(i*stride)+dy*3;
89
        for (j=0 ; j<w*3 ; j++) {
90
            diff |=npfptr[j]^nsptr[j];
91
            dptr[j] = nsptr[j];
92
        }
93
        dptr += w*3;
94
    }
95
    if (diff)
96
        return 1;
97
    return 0;
98
}
99

    
100
static int flashsv_encode_init(AVCodecContext *avctx)
101
{
102
    FlashSVContext *s = avctx->priv_data;
103

    
104
    s->avctx = avctx;
105

    
106
    if ((avctx->width > 4095) || (avctx->height > 4095)) {
107
        av_log(avctx, AV_LOG_ERROR, "Input dimensions too large, input must be max 4096x4096 !\n");
108
        return -1;
109
    }
110

    
111
    if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
112
        return -1;
113
    }
114

    
115
    // Needed if zlib unused or init aborted before deflateInit
116
    memset(&(s->zstream), 0, sizeof(z_stream));
117
/*
118
    s->zstream.zalloc = NULL; //av_malloc;
119
    s->zstream.zfree = NULL; //av_free;
120
    s->zstream.opaque = NULL;
121
    zret = deflateInit(&(s->zstream), 9);
122
    if (zret != Z_OK) {
123
        av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
124
        return -1;
125
    }
126
*/
127

    
128
    s->last_key_frame=0;
129

    
130
    s->image_width = avctx->width;
131
    s->image_height = avctx->height;
132

    
133
    s->tmpblock = av_mallocz(3*256*256);
134
    s->encbuffer = av_mallocz(s->image_width*s->image_height*3);
135

    
136
    if (!s->tmpblock || !s->encbuffer) {
137
        av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
138
        return -1;
139
    }
140

    
141
    return 0;
142
}
143

    
144

    
145
static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf, int buf_size,
146
     int block_width, int block_height, uint8_t *previous_frame, int* I_frame) {
147

    
148
    PutBitContext pb;
149
    int h_blocks, v_blocks, h_part, v_part, i, j;
150
    int buf_pos, res;
151
    int pred_blocks = 0;
152

    
153
    init_put_bits(&pb, buf, buf_size*8);
154

    
155
    put_bits(&pb, 4, (block_width/16)-1);
156
    put_bits(&pb, 12, s->image_width);
157
    put_bits(&pb, 4, (block_height/16)-1);
158
    put_bits(&pb, 12, s->image_height);
159
    flush_put_bits(&pb);
160
    buf_pos=4;
161

    
162
    h_blocks = s->image_width / block_width;
163
    h_part = s->image_width % block_width;
164
    v_blocks = s->image_height / block_height;
165
    v_part = s->image_height % block_height;
166

    
167
    /* loop over all block columns */
168
    for (j = 0; j < v_blocks + (v_part?1:0); j++)
169
    {
170

    
171
        int hp = j*block_height; // horiz position in frame
172
        int hs = (j<v_blocks)?block_height:v_part; // size of block
173

    
174
        /* loop over all block rows */
175
        for (i = 0; i < h_blocks + (h_part?1:0); i++)
176
        {
177
            int wp = i*block_width; // vert position in frame
178
            int ws = (i<h_blocks)?block_width:h_part; // size of block
179
            int ret=Z_OK;
180
            uint8_t *ptr;
181

    
182
            ptr = buf+buf_pos;
183

    
184
            //copy the block to the temp buffer before compression (if it differs from the previous frame's block)
185
            res = copy_region_enc(p->data[0], s->tmpblock, s->image_height-(hp+hs+1), wp, hs, ws, p->linesize[0], previous_frame);
186

    
187
            if (res || *I_frame) {
188
                unsigned long zsize;
189
                zsize = 3*block_width*block_height;
190
                ret = compress2(ptr+2, &zsize, s->tmpblock, 3*ws*hs, 9);
191

    
192

    
193
                //ret = deflateReset(&(s->zstream));
194
                if (ret != Z_OK)
195
                    av_log(s->avctx, AV_LOG_ERROR, "error while compressing block %dx%d\n", i, j);
196
                /*
197
                s->zstream.next_in = s->tmpblock;
198
                s->zstream.avail_in = 3*ws*hs;
199
                s->zstream.total_in = 0;
200

201
                s->zstream.next_out = ptr+2;
202
                s->zstream.avail_out = buf_size-buf_pos-2;
203
                s->zstream.total_out = 0;
204

205
                ret = deflate(&(s->zstream), Z_FINISH);
206
                if ((ret != Z_OK) && (ret != Z_STREAM_END))
207
                    av_log(s->avctx, AV_LOG_ERROR, "error while compressing block %dx%d\n", i, j);
208

209
                size = s->zstream.total_out;
210
                //av_log(avctx, AV_LOG_INFO, "compressed blocks: %d\n", size);
211
                */
212
                bytestream_put_be16(&ptr,(unsigned int)zsize);
213
                buf_pos += zsize+2;
214
                //av_log(avctx, AV_LOG_ERROR, "buf_pos = %d\n", buf_pos);
215
            } else {
216
                pred_blocks++;
217
                bytestream_put_be16(&ptr,0);
218
                buf_pos += 2;
219
            }
220
        }
221
    }
222

    
223
    if (pred_blocks)
224
        *I_frame = 0;
225
    else
226
        *I_frame = 1;
227

    
228
    return buf_pos;
229
}
230

    
231

    
232
static int flashsv_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
233
{
234
    FlashSVContext * const s = avctx->priv_data;
235
    AVFrame *pict = data;
236
    AVFrame * const p = &s->frame;
237
    int res;
238
    int I_frame = 0;
239
    int opt_w, opt_h;
240

    
241
    *p = *pict;
242

    
243
    /* First frame needs to be a keyframe */
244
    if (avctx->frame_number == 0) {
245
        s->previous_frame = av_mallocz(p->linesize[0]*s->image_height);
246
        if (!s->previous_frame) {
247
            av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
248
            return -1;
249
        }
250
        I_frame = 1;
251
    }
252

    
253
    /* Check the placement of keyframes */
254
    if (avctx->gop_size > 0) {
255
        if (avctx->frame_number >= s->last_key_frame + avctx->gop_size) {
256
            I_frame = 1;
257
        }
258
    }
259

    
260
#if 0
261
    int w, h;
262
    int optim_sizes[16][16];
263
    int smallest_size;
264
    //Try all possible combinations and store the encoded frame sizes
265
    for (w=1 ; w<17 ; w++) {
266
        for (h=1 ; h<17 ; h++) {
267
            optim_sizes[w-1][h-1] = encode_bitstream(s, p, s->encbuffer, s->image_width*s->image_height*4, w*16, h*16, s->previous_frame);
268
            //av_log(avctx, AV_LOG_ERROR, "[%d][%d]size = %d\n",w,h,optim_sizes[w-1][h-1]);
269
        }
270
    }
271

272
    //Search for the smallest framesize and encode the frame with those parameters
273
    smallest_size=optim_sizes[0][0];
274
    opt_w = 0;
275
    opt_h = 0;
276
    for (w=0 ; w<16 ; w++) {
277
        for (h=0 ; h<16 ; h++) {
278
            if (optim_sizes[w][h] < smallest_size) {
279
                smallest_size = optim_sizes[w][h];
280
                opt_w = w;
281
                opt_h = h;
282
            }
283
        }
284
    }
285
    res = encode_bitstream(s, p, buf, buf_size, (opt_w+1)*16, (opt_h+1)*16, s->previous_frame);
286
    av_log(avctx, AV_LOG_ERROR, "[%d][%d]optimal size = %d, res = %d|\n", opt_w, opt_h, smallest_size, res);
287

288
    if (buf_size < res)
289
        av_log(avctx, AV_LOG_ERROR, "buf_size %d < res %d\n", buf_size, res);
290

291
#else
292
    opt_w=1;
293
    opt_h=1;
294

    
295
    if (buf_size < s->image_width*s->image_height*3) {
296
        //Conservative upper bound check for compressed data
297
        av_log(avctx, AV_LOG_ERROR, "buf_size %d <  %d\n", buf_size, s->image_width*s->image_height*3);
298
        return -1;
299
    }
300

    
301
    res = encode_bitstream(s, p, buf, buf_size, opt_w*16, opt_h*16, s->previous_frame, &I_frame);
302
#endif
303
    //save the current frame
304
    memcpy(s->previous_frame, p->data[0], s->image_height*p->linesize[0]);
305

    
306
    //mark the frame type so the muxer can mux it correctly
307
    if (I_frame) {
308
        p->pict_type = FF_I_TYPE;
309
        p->key_frame = 1;
310
        s->last_key_frame = avctx->frame_number;
311
        av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n",avctx->frame_number);
312
    } else {
313
        p->pict_type = FF_P_TYPE;
314
        p->key_frame = 0;
315
    }
316

    
317
    avctx->coded_frame = p;
318

    
319
    return res;
320
}
321

    
322
static int flashsv_encode_end(AVCodecContext *avctx)
323
{
324
    FlashSVContext *s = avctx->priv_data;
325

    
326
    deflateEnd(&(s->zstream));
327

    
328
    av_free(s->encbuffer);
329
    av_free(s->previous_frame);
330
    av_free(s->tmpblock);
331

    
332
    return 0;
333
}
334

    
335
AVCodec flashsv_encoder = {
336
    "flashsv",
337
    CODEC_TYPE_VIDEO,
338
    CODEC_ID_FLASHSV,
339
    sizeof(FlashSVContext),
340
    flashsv_encode_init,
341
    flashsv_encode_frame,
342
    flashsv_encode_end,
343
    .pix_fmts = (enum PixelFormat[]){PIX_FMT_BGR24, -1},
344
};
345