Statistics
| Branch: | Revision:

ffmpeg / libavcodec / flashsvenc.c @ b6607559

History | View | Annotate | Download (9.91 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 "common.h"
62
#include "avcodec.h"
63
#include "bitstream.h"
64
#include "bytestream.h"
65

    
66

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

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

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

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

    
105
    s->avctx = avctx;
106

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

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

    
116
    s->first_frame = 1;
117

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

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

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

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

    
142
    return 0;
143
}
144

    
145

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

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

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

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

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

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

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

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

    
183
            ptr = buf+buf_pos;
184

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

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

    
193

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

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

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

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

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

    
229
    return buf_pos;
230
}
231

    
232

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

    
242
    *p = *pict;
243

    
244
    if (s->first_frame) {
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
        s->first_frame = 0;
252
    }
253

    
254
#if 0
255
    int w, h;
256
    int optim_sizes[16][16];
257
    int smallest_size;
258
    //Try all possible combinations and store the encoded frame sizes
259
    for (w=1 ; w<17 ; w++) {
260
        for (h=1 ; h<17 ; h++) {
261
            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);
262
            //av_log(avctx, AV_LOG_ERROR, "[%d][%d]size = %d\n",w,h,optim_sizes[w-1][h-1]);
263
        }
264
    }
265

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

282
    if (buf_size < res)
283
        av_log(avctx, AV_LOG_ERROR, "buf_size %d < res %d\n", buf_size, res);
284

285
#else
286
    opt_w=1;
287
    opt_h=1;
288

    
289
    if (buf_size < s->image_width*s->image_height*3) {
290
        //Conservative upper bound check for compressed data
291
        av_log(avctx, AV_LOG_ERROR, "buf_size %d <  %d\n", buf_size, s->image_width*s->image_height*3);
292
        return -1;
293
    }
294

    
295
    res = encode_bitstream(s, p, buf, buf_size, opt_w*16, opt_h*16, s->previous_frame, &I_frame);
296
#endif
297
    //save the current frame
298
    memcpy(s->previous_frame, p->data[0], s->image_height*p->linesize[0]);
299

    
300
    //mark the frame type so the muxer can mux it correctly
301
    if (I_frame) {
302
        p->pict_type = FF_I_TYPE;
303
        p->key_frame = 1;
304
    } else {
305
        p->pict_type = FF_P_TYPE;
306
        p->key_frame = 0;
307
    }
308

    
309
    avctx->coded_frame = p;
310

    
311
    return res;
312
}
313

    
314
static int flashsv_encode_end(AVCodecContext *avctx)
315
{
316
    FlashSVContext *s = (FlashSVContext *)avctx->priv_data;
317

    
318
    deflateEnd(&(s->zstream));
319

    
320
    av_free(s->encbuffer);
321
    av_free(s->previous_frame);
322
    av_free(s->tmpblock);
323

    
324
    return 0;
325
}
326

    
327
AVCodec flashsv_encoder = {
328
    "flashsv",
329
    CODEC_TYPE_VIDEO,
330
    CODEC_ID_FLASHSV,
331
    sizeof(FlashSVContext),
332
    flashsv_encode_init,
333
    flashsv_encode_frame,
334
    flashsv_encode_end,
335
    .pix_fmts = (enum PixelFormat[]){PIX_FMT_BGR24, -1},
336
};
337