Statistics
| Branch: | Revision:

ffmpeg / libavcodec / qtrleenc.c @ 72415b2a

History | View | Annotate | Download (11 KB)

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

    
25
#include "avcodec.h"
26
#include "bytestream.h"
27

    
28
/** Maximum RLE code for bulk copy */
29
#define MAX_RLE_BULK   127
30
/** Maximum RLE code for repeat */
31
#define MAX_RLE_REPEAT 128
32
/** Maximum RLE code for skip */
33
#define MAX_RLE_SKIP   254
34

    
35
typedef struct QtrleEncContext {
36
    AVCodecContext *avctx;
37
    AVFrame frame;
38
    int pixel_size;
39
    AVPicture previous_frame;
40
    unsigned int max_buf_size;
41
    /**
42
     * This array will contain at ith position the value of the best RLE code
43
     * if the line started at pixel i
44
     * There can be 3 values :
45
     * skip (0)     : skip as much as possible pixels because they are equal to the
46
     *                previous frame ones
47
     * repeat (<-1) : repeat that pixel -rle_code times, still as much as
48
     *                possible
49
     * copy (>0)    : copy the raw next rle_code pixels */
50
    signed char *rlecode_table;
51
    /**
52
     * This array will contain the length of the best rle encoding of the line
53
     * starting at ith pixel */
54
    int *length_table;
55
    /**
56
     * Will contain at ith position the number of consecutive pixels equal to the previous
57
     * frame starting from pixel i */
58
    uint8_t* skip_table;
59
} QtrleEncContext;
60

    
61
static av_cold int qtrle_encode_init(AVCodecContext *avctx)
62
{
63
    QtrleEncContext *s = avctx->priv_data;
64

    
65
    if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
66
        return -1;
67
    }
68
    s->avctx=avctx;
69

    
70
    switch (avctx->pix_fmt) {
71
    case PIX_FMT_RGB555BE:
72
        s->pixel_size = 2;
73
        break;
74
    case PIX_FMT_RGB24:
75
        s->pixel_size = 3;
76
        break;
77
    case PIX_FMT_ARGB:
78
        s->pixel_size = 4;
79
        break;
80
    default:
81
        av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n");
82
        break;
83
    }
84
    avctx->bits_per_coded_sample = s->pixel_size*8;
85

    
86
    s->rlecode_table = av_mallocz(s->avctx->width);
87
    s->skip_table    = av_mallocz(s->avctx->width);
88
    s->length_table  = av_mallocz((s->avctx->width + 1)*sizeof(int));
89
    if (!s->skip_table || !s->length_table || !s->rlecode_table) {
90
        av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n");
91
        return -1;
92
    }
93
    if (avpicture_alloc(&s->previous_frame, avctx->pix_fmt, avctx->width, avctx->height) < 0) {
94
        av_log(avctx, AV_LOG_ERROR, "Error allocating picture\n");
95
        return -1;
96
    }
97

    
98
    s->max_buf_size = s->avctx->width*s->avctx->height*s->pixel_size /* image base material */
99
                      + 15                                           /* header + footer */
100
                      + s->avctx->height*2                           /* skip code+rle end */
101
                      + s->avctx->width/MAX_RLE_BULK + 1             /* rle codes */;
102
    avctx->coded_frame = &s->frame;
103
    return 0;
104
}
105

    
106
/**
107
 * Computes the best RLE sequence for a line
108
 */
109
static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t **buf)
110
{
111
    int width=s->avctx->width;
112
    int i;
113
    signed char rlecode;
114

    
115
    /* We will use it to compute the best bulk copy sequence */
116
    unsigned int bulkcount;
117
    /* This will be the number of pixels equal to the preivous frame one's
118
     * starting from the ith pixel */
119
    unsigned int skipcount;
120
    /* This will be the number of consecutive equal pixels in the current
121
     * frame, starting from the ith one also */
122
    unsigned int av_uninit(repeatcount);
123

    
124
    /* The cost of the three different possibilities */
125
    int total_bulk_cost;
126
    int total_skip_cost;
127
    int total_repeat_cost;
128

    
129
    int temp_cost;
130
    int j;
131

    
132
    uint8_t *this_line = p->               data[0] + line*p->               linesize[0] +
133
        (width - 1)*s->pixel_size;
134
    uint8_t *prev_line = s->previous_frame.data[0] + line*s->previous_frame.linesize[0] +
135
        (width - 1)*s->pixel_size;
136

    
137
    s->length_table[width] = 0;
138
    skipcount = 0;
139

    
140
    for (i = width - 1; i >= 0; i--) {
141

    
142
        if (!s->frame.key_frame && !memcmp(this_line, prev_line, s->pixel_size))
143
            skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP);
144
        else
145
            skipcount = 0;
146

    
147
        total_skip_cost  = s->length_table[i + skipcount] + 2;
148
        s->skip_table[i] = skipcount;
149

    
150

    
151
        if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size))
152
            repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT);
153
        else
154
            repeatcount = 1;
155

    
156
        total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size;
157

    
158
        /* skip code is free for the first pixel, it costs one byte for repeat and bulk copy
159
         * so let's make it aware */
160
        if (i == 0) {
161
            total_skip_cost--;
162
            total_repeat_cost++;
163
        }
164

    
165
        if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) {
166
            /* repeat is the best */
167
            s->length_table[i]  = total_repeat_cost;
168
            s->rlecode_table[i] = -repeatcount;
169
        }
170
        else if (skipcount > 0) {
171
            /* skip is the best choice here */
172
            s->length_table[i]  = total_skip_cost;
173
            s->rlecode_table[i] = 0;
174
        }
175
        else {
176
            /* We cannot do neither skip nor repeat
177
             * thus we search for the best bulk copy to do */
178

    
179
            int limit = FFMIN(width - i, MAX_RLE_BULK);
180

    
181
            temp_cost = 1 + s->pixel_size + !i;
182
            total_bulk_cost = INT_MAX;
183

    
184
            for (j = 1; j <= limit; j++) {
185
                if (s->length_table[i + j] + temp_cost < total_bulk_cost) {
186
                    /* We have found a better bulk copy ... */
187
                    total_bulk_cost = s->length_table[i + j] + temp_cost;
188
                    bulkcount = j;
189
                }
190
                temp_cost += s->pixel_size;
191
            }
192

    
193
            s->length_table[i]  = total_bulk_cost;
194
            s->rlecode_table[i] = bulkcount;
195
        }
196

    
197
        this_line -= s->pixel_size;
198
        prev_line -= s->pixel_size;
199
    }
200

    
201
    /* Good ! Now we have the best sequence for this line, let's ouput it */
202

    
203
    /* We do a special case for the first pixel so that we avoid testing it in
204
     * the whole loop */
205

    
206
    i=0;
207
    this_line = p->               data[0] + line*p->linesize[0];
208

    
209
    if (s->rlecode_table[0] == 0) {
210
        bytestream_put_byte(buf, s->skip_table[0] + 1);
211
        i += s->skip_table[0];
212
    }
213
    else bytestream_put_byte(buf, 1);
214

    
215

    
216
    while (i < width) {
217
        rlecode = s->rlecode_table[i];
218
        bytestream_put_byte(buf, rlecode);
219
        if (rlecode == 0) {
220
            /* Write a skip sequence */
221
            bytestream_put_byte(buf, s->skip_table[i] + 1);
222
            i += s->skip_table[i];
223
        }
224
        else if (rlecode > 0) {
225
            /* bulk copy */
226
            bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size);
227
            i += rlecode;
228
        }
229
        else {
230
            /* repeat the bits */
231
            bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size);
232
            i -= rlecode;
233
        }
234
    }
235
    bytestream_put_byte(buf, -1); // end RLE line
236
}
237

    
238
/** Encodes frame including header */
239
static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf)
240
{
241
    int i;
242
    int start_line = 0;
243
    int end_line = s->avctx->height;
244
    uint8_t *orig_buf = buf;
245

    
246
    if (!s->frame.key_frame) {
247
        unsigned line_size = s->avctx->width * s->pixel_size;
248
        for (start_line = 0; start_line < s->avctx->height; start_line++)
249
            if (memcmp(p->data[0] + start_line*p->linesize[0],
250
                       s->previous_frame.data[0] + start_line*s->previous_frame.linesize[0],
251
                       line_size))
252
                break;
253

    
254
        for (end_line=s->avctx->height; end_line > start_line; end_line--)
255
            if (memcmp(p->data[0] + (end_line - 1)*p->linesize[0],
256
                       s->previous_frame.data[0] + (end_line - 1)*s->previous_frame.linesize[0],
257
                       line_size))
258
                break;
259
    }
260

    
261
    bytestream_put_be32(&buf, 0);                         // CHUNK SIZE, patched later
262

    
263
    if ((start_line == 0 && end_line == s->avctx->height) || start_line == s->avctx->height)
264
        bytestream_put_be16(&buf, 0);                     // header
265
    else {
266
        bytestream_put_be16(&buf, 8);                     // header
267
        bytestream_put_be16(&buf, start_line);            // starting line
268
        bytestream_put_be16(&buf, 0);                     // unknown
269
        bytestream_put_be16(&buf, end_line - start_line); // lines to update
270
        bytestream_put_be16(&buf, 0);                     // unknown
271
    }
272
    for (i = start_line; i < end_line; i++)
273
        qtrle_encode_line(s, p, i, &buf);
274

    
275
    bytestream_put_byte(&buf, 0);                         // zero skip code = frame finished
276
    AV_WB32(orig_buf, buf - orig_buf);                    // patch the chunk size
277
    return buf - orig_buf;
278
}
279

    
280
static int qtrle_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
281
{
282
    QtrleEncContext * const s = avctx->priv_data;
283
    AVFrame *pict = data;
284
    AVFrame * const p = &s->frame;
285
    int chunksize;
286

    
287
    *p = *pict;
288

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

    
295
    if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) {
296
        /* I-Frame */
297
        p->pict_type = FF_I_TYPE;
298
        p->key_frame = 1;
299
    } else {
300
        /* P-Frame */
301
        p->pict_type = FF_P_TYPE;
302
        p->key_frame = 0;
303
    }
304

    
305
    chunksize = encode_frame(s, pict, buf);
306

    
307
    /* save the current frame */
308
    av_picture_copy(&s->previous_frame, (AVPicture *)p, avctx->pix_fmt, avctx->width, avctx->height);
309
    return chunksize;
310
}
311

    
312
static av_cold int qtrle_encode_end(AVCodecContext *avctx)
313
{
314
    QtrleEncContext *s = avctx->priv_data;
315

    
316
    avpicture_free(&s->previous_frame);
317
    av_free(s->rlecode_table);
318
    av_free(s->length_table);
319
    av_free(s->skip_table);
320
    return 0;
321
}
322

    
323
AVCodec qtrle_encoder = {
324
    "qtrle",
325
    AVMEDIA_TYPE_VIDEO,
326
    CODEC_ID_QTRLE,
327
    sizeof(QtrleEncContext),
328
    qtrle_encode_init,
329
    qtrle_encode_frame,
330
    qtrle_encode_end,
331
    .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB555BE, PIX_FMT_ARGB, PIX_FMT_NONE},
332
    .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
333
};