Statistics
| Branch: | Revision:

ffmpeg / libavcodec / qtrleenc.c @ 2912e87a

History | View | Annotate | Download (11.1 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 Libav.
9
 *
10
 * Libav 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
 * Libav 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 Libav; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
 */
24

    
25
#include "libavutil/imgutils.h"
26
#include "avcodec.h"
27
#include "bytestream.h"
28

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

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

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

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

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

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

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

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

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

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

    
130
    int temp_cost;
131
    int j;
132

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

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

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

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

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

    
151

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

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

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

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

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

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

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

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

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

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

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

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

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

    
216

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

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

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

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

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

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

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

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

    
288
    *p = *pict;
289

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

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

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

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

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

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

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