blob: cdd864bf820953cf22e6b389583ee9d95c0829a7
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 "libavutil/imgutils.h" |
26 | #include "avcodec.h" |
27 | #include "bytestream.h" |
28 | #include "internal.h" |
29 | |
30 | /** Maximum RLE code for bulk copy */ |
31 | #define MAX_RLE_BULK 127 |
32 | /** Maximum RLE code for repeat */ |
33 | #define MAX_RLE_REPEAT 128 |
34 | /** Maximum RLE code for skip */ |
35 | #define MAX_RLE_SKIP 254 |
36 | |
37 | typedef struct QtrleEncContext { |
38 | AVCodecContext *avctx; |
39 | int pixel_size; |
40 | AVFrame *previous_frame; |
41 | unsigned int max_buf_size; |
42 | int logical_width; |
43 | /** |
44 | * This array will contain at ith position the value of the best RLE code |
45 | * if the line started at pixel i |
46 | * There can be 3 values : |
47 | * skip (0) : skip as much as possible pixels because they are equal to the |
48 | * previous frame ones |
49 | * repeat (<-1) : repeat that pixel -rle_code times, still as much as |
50 | * possible |
51 | * copy (>0) : copy the raw next rle_code pixels */ |
52 | signed char *rlecode_table; |
53 | /** |
54 | * This array will contain the length of the best rle encoding of the line |
55 | * starting at ith pixel */ |
56 | int *length_table; |
57 | /** |
58 | * Will contain at ith position the number of consecutive pixels equal to the previous |
59 | * frame starting from pixel i */ |
60 | uint8_t* skip_table; |
61 | |
62 | /** Encoded frame is a key frame */ |
63 | int key_frame; |
64 | } QtrleEncContext; |
65 | |
66 | static av_cold int qtrle_encode_end(AVCodecContext *avctx) |
67 | { |
68 | QtrleEncContext *s = avctx->priv_data; |
69 | |
70 | av_frame_free(&s->previous_frame); |
71 | av_free(s->rlecode_table); |
72 | av_free(s->length_table); |
73 | av_free(s->skip_table); |
74 | return 0; |
75 | } |
76 | |
77 | static av_cold int qtrle_encode_init(AVCodecContext *avctx) |
78 | { |
79 | QtrleEncContext *s = avctx->priv_data; |
80 | |
81 | if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) { |
82 | return AVERROR(EINVAL); |
83 | } |
84 | s->avctx=avctx; |
85 | s->logical_width=avctx->width; |
86 | |
87 | switch (avctx->pix_fmt) { |
88 | case AV_PIX_FMT_GRAY8: |
89 | if (avctx->width % 4) { |
90 | av_log(avctx, AV_LOG_ERROR, "Width not being a multiple of 4 is not supported\n"); |
91 | return AVERROR(EINVAL); |
92 | } |
93 | s->logical_width = avctx->width / 4; |
94 | s->pixel_size = 4; |
95 | break; |
96 | case AV_PIX_FMT_RGB555BE: |
97 | s->pixel_size = 2; |
98 | break; |
99 | case AV_PIX_FMT_RGB24: |
100 | s->pixel_size = 3; |
101 | break; |
102 | case AV_PIX_FMT_ARGB: |
103 | s->pixel_size = 4; |
104 | break; |
105 | default: |
106 | av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n"); |
107 | break; |
108 | } |
109 | avctx->bits_per_coded_sample = avctx->pix_fmt == AV_PIX_FMT_GRAY8 ? 40 : s->pixel_size*8; |
110 | |
111 | s->rlecode_table = av_mallocz(s->logical_width); |
112 | s->skip_table = av_mallocz(s->logical_width); |
113 | s->length_table = av_mallocz_array(s->logical_width + 1, sizeof(int)); |
114 | if (!s->skip_table || !s->length_table || !s->rlecode_table) { |
115 | av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n"); |
116 | return AVERROR(ENOMEM); |
117 | } |
118 | s->previous_frame = av_frame_alloc(); |
119 | if (!s->previous_frame) { |
120 | av_log(avctx, AV_LOG_ERROR, "Error allocating picture\n"); |
121 | return AVERROR(ENOMEM); |
122 | } |
123 | |
124 | s->max_buf_size = s->logical_width*s->avctx->height*s->pixel_size*2 /* image base material */ |
125 | + 15 /* header + footer */ |
126 | + s->avctx->height*2 /* skip code+rle end */ |
127 | + s->logical_width/MAX_RLE_BULK + 1 /* rle codes */; |
128 | |
129 | return 0; |
130 | } |
131 | |
132 | /** |
133 | * Compute the best RLE sequence for a line |
134 | */ |
135 | static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, uint8_t **buf) |
136 | { |
137 | int width=s->logical_width; |
138 | int i; |
139 | signed char rlecode; |
140 | |
141 | /* This will be the number of pixels equal to the previous frame one's |
142 | * starting from the ith pixel */ |
143 | unsigned int skipcount; |
144 | /* This will be the number of consecutive equal pixels in the current |
145 | * frame, starting from the ith one also */ |
146 | unsigned int av_uninit(repeatcount); |
147 | |
148 | /* The cost of the three different possibilities */ |
149 | int total_skip_cost; |
150 | int total_repeat_cost; |
151 | |
152 | int base_bulk_cost; |
153 | int lowest_bulk_cost; |
154 | int lowest_bulk_cost_index; |
155 | int sec_lowest_bulk_cost; |
156 | int sec_lowest_bulk_cost_index; |
157 | |
158 | uint8_t *this_line = p-> data[0] + line*p-> linesize[0] + |
159 | (width - 1)*s->pixel_size; |
160 | uint8_t *prev_line = s->previous_frame->data[0] + line * s->previous_frame->linesize[0] + |
161 | (width - 1)*s->pixel_size; |
162 | |
163 | s->length_table[width] = 0; |
164 | skipcount = 0; |
165 | |
166 | /* Initial values */ |
167 | lowest_bulk_cost = INT_MAX / 2; |
168 | lowest_bulk_cost_index = width; |
169 | sec_lowest_bulk_cost = INT_MAX / 2; |
170 | sec_lowest_bulk_cost_index = width; |
171 | |
172 | base_bulk_cost = 1 + s->pixel_size; |
173 | |
174 | for (i = width - 1; i >= 0; i--) { |
175 | |
176 | int prev_bulk_cost; |
177 | |
178 | /* If our lowest bulk cost index is too far away, replace it |
179 | * with the next lowest bulk cost */ |
180 | if (FFMIN(width, i + MAX_RLE_BULK) < lowest_bulk_cost_index) { |
181 | lowest_bulk_cost = sec_lowest_bulk_cost; |
182 | lowest_bulk_cost_index = sec_lowest_bulk_cost_index; |
183 | |
184 | sec_lowest_bulk_cost = INT_MAX / 2; |
185 | sec_lowest_bulk_cost_index = width; |
186 | } |
187 | |
188 | /* Deal with the first pixel's bulk cost */ |
189 | if (!i) { |
190 | base_bulk_cost++; |
191 | lowest_bulk_cost++; |
192 | sec_lowest_bulk_cost++; |
193 | } |
194 | |
195 | /* Look at the bulk cost of the previous loop and see if it is |
196 | * a new lower bulk cost */ |
197 | prev_bulk_cost = s->length_table[i + 1] + base_bulk_cost; |
198 | if (prev_bulk_cost <= sec_lowest_bulk_cost) { |
199 | /* If it's lower than the 2nd lowest, then it may be lower |
200 | * than the lowest */ |
201 | if (prev_bulk_cost <= lowest_bulk_cost) { |
202 | |
203 | /* If we have found a new lowest bulk cost, |
204 | * then the 2nd lowest bulk cost is now farther than the |
205 | * lowest bulk cost, and will never be used */ |
206 | sec_lowest_bulk_cost = INT_MAX / 2; |
207 | |
208 | lowest_bulk_cost = prev_bulk_cost; |
209 | lowest_bulk_cost_index = i + 1; |
210 | } else { |
211 | /* Then it must be the 2nd lowest bulk cost */ |
212 | sec_lowest_bulk_cost = prev_bulk_cost; |
213 | sec_lowest_bulk_cost_index = i + 1; |
214 | } |
215 | } |
216 | |
217 | if (!s->key_frame && !memcmp(this_line, prev_line, s->pixel_size)) |
218 | skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP); |
219 | else |
220 | skipcount = 0; |
221 | |
222 | total_skip_cost = s->length_table[i + skipcount] + 2; |
223 | s->skip_table[i] = skipcount; |
224 | |
225 | |
226 | if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size)) |
227 | repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT); |
228 | else |
229 | repeatcount = 1; |
230 | |
231 | total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size; |
232 | |
233 | /* skip code is free for the first pixel, it costs one byte for repeat and bulk copy |
234 | * so let's make it aware */ |
235 | if (i == 0) { |
236 | total_skip_cost--; |
237 | total_repeat_cost++; |
238 | } |
239 | |
240 | if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) { |
241 | /* repeat is the best */ |
242 | s->length_table[i] = total_repeat_cost; |
243 | s->rlecode_table[i] = -repeatcount; |
244 | } |
245 | else if (skipcount > 0) { |
246 | /* skip is the best choice here */ |
247 | s->length_table[i] = total_skip_cost; |
248 | s->rlecode_table[i] = 0; |
249 | } |
250 | else { |
251 | /* We cannot do neither skip nor repeat |
252 | * thus we use the best bulk copy */ |
253 | |
254 | s->length_table[i] = lowest_bulk_cost; |
255 | s->rlecode_table[i] = lowest_bulk_cost_index - i; |
256 | |
257 | } |
258 | |
259 | /* These bulk costs increase every iteration */ |
260 | lowest_bulk_cost += s->pixel_size; |
261 | sec_lowest_bulk_cost += s->pixel_size; |
262 | |
263 | this_line -= s->pixel_size; |
264 | prev_line -= s->pixel_size; |
265 | } |
266 | |
267 | /* Good! Now we have the best sequence for this line, let's output it. */ |
268 | |
269 | /* We do a special case for the first pixel so that we avoid testing it in |
270 | * the whole loop */ |
271 | |
272 | i=0; |
273 | this_line = p-> data[0] + line*p->linesize[0]; |
274 | |
275 | if (s->rlecode_table[0] == 0) { |
276 | bytestream_put_byte(buf, s->skip_table[0] + 1); |
277 | i += s->skip_table[0]; |
278 | } |
279 | else bytestream_put_byte(buf, 1); |
280 | |
281 | |
282 | while (i < width) { |
283 | rlecode = s->rlecode_table[i]; |
284 | bytestream_put_byte(buf, rlecode); |
285 | if (rlecode == 0) { |
286 | /* Write a skip sequence */ |
287 | bytestream_put_byte(buf, s->skip_table[i] + 1); |
288 | i += s->skip_table[i]; |
289 | } |
290 | else if (rlecode > 0) { |
291 | /* bulk copy */ |
292 | if (s->avctx->pix_fmt == AV_PIX_FMT_GRAY8) { |
293 | int j; |
294 | // QT grayscale colorspace has 0=white and 255=black, we will |
295 | // ignore the palette that is included in the AVFrame because |
296 | // AV_PIX_FMT_GRAY8 has defined color mapping |
297 | for (j = 0; j < rlecode*s->pixel_size; ++j) |
298 | bytestream_put_byte(buf, *(this_line + i*s->pixel_size + j) ^ 0xff); |
299 | } else { |
300 | bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size); |
301 | } |
302 | i += rlecode; |
303 | } |
304 | else { |
305 | /* repeat the bits */ |
306 | if (s->avctx->pix_fmt == AV_PIX_FMT_GRAY8) { |
307 | int j; |
308 | // QT grayscale colorspace has 0=white and 255=black, ... |
309 | for (j = 0; j < s->pixel_size; ++j) |
310 | bytestream_put_byte(buf, *(this_line + i*s->pixel_size + j) ^ 0xff); |
311 | } else { |
312 | bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size); |
313 | } |
314 | i -= rlecode; |
315 | } |
316 | } |
317 | bytestream_put_byte(buf, -1); // end RLE line |
318 | } |
319 | |
320 | /** Encode frame including header */ |
321 | static int encode_frame(QtrleEncContext *s, const AVFrame *p, uint8_t *buf) |
322 | { |
323 | int i; |
324 | int start_line = 0; |
325 | int end_line = s->avctx->height; |
326 | uint8_t *orig_buf = buf; |
327 | |
328 | if (!s->key_frame) { |
329 | unsigned line_size = s->logical_width * s->pixel_size; |
330 | for (start_line = 0; start_line < s->avctx->height; start_line++) |
331 | if (memcmp(p->data[0] + start_line*p->linesize[0], |
332 | s->previous_frame->data[0] + start_line * s->previous_frame->linesize[0], |
333 | line_size)) |
334 | break; |
335 | |
336 | for (end_line=s->avctx->height; end_line > start_line; end_line--) |
337 | if (memcmp(p->data[0] + (end_line - 1)*p->linesize[0], |
338 | s->previous_frame->data[0] + (end_line - 1) * s->previous_frame->linesize[0], |
339 | line_size)) |
340 | break; |
341 | } |
342 | |
343 | bytestream_put_be32(&buf, 0); // CHUNK SIZE, patched later |
344 | |
345 | if ((start_line == 0 && end_line == s->avctx->height) || start_line == s->avctx->height) |
346 | bytestream_put_be16(&buf, 0); // header |
347 | else { |
348 | bytestream_put_be16(&buf, 8); // header |
349 | bytestream_put_be16(&buf, start_line); // starting line |
350 | bytestream_put_be16(&buf, 0); // unknown |
351 | bytestream_put_be16(&buf, end_line - start_line); // lines to update |
352 | bytestream_put_be16(&buf, 0); // unknown |
353 | } |
354 | for (i = start_line; i < end_line; i++) |
355 | qtrle_encode_line(s, p, i, &buf); |
356 | |
357 | bytestream_put_byte(&buf, 0); // zero skip code = frame finished |
358 | AV_WB32(orig_buf, buf - orig_buf); // patch the chunk size |
359 | return buf - orig_buf; |
360 | } |
361 | |
362 | static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
363 | const AVFrame *pict, int *got_packet) |
364 | { |
365 | QtrleEncContext * const s = avctx->priv_data; |
366 | int ret; |
367 | |
368 | if ((ret = ff_alloc_packet2(avctx, pkt, s->max_buf_size, 0)) < 0) |
369 | return ret; |
370 | |
371 | if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) { |
372 | /* I-Frame */ |
373 | s->key_frame = 1; |
374 | } else { |
375 | /* P-Frame */ |
376 | s->key_frame = 0; |
377 | } |
378 | |
379 | pkt->size = encode_frame(s, pict, pkt->data); |
380 | |
381 | /* save the current frame */ |
382 | av_frame_unref(s->previous_frame); |
383 | ret = av_frame_ref(s->previous_frame, pict); |
384 | if (ret < 0) { |
385 | av_log(avctx, AV_LOG_ERROR, "cannot add reference\n"); |
386 | return ret; |
387 | } |
388 | |
389 | #if FF_API_CODED_FRAME |
390 | FF_DISABLE_DEPRECATION_WARNINGS |
391 | avctx->coded_frame->key_frame = s->key_frame; |
392 | avctx->coded_frame->pict_type = s->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; |
393 | FF_ENABLE_DEPRECATION_WARNINGS |
394 | #endif |
395 | |
396 | if (s->key_frame) |
397 | pkt->flags |= AV_PKT_FLAG_KEY; |
398 | *got_packet = 1; |
399 | |
400 | return 0; |
401 | } |
402 | |
403 | AVCodec ff_qtrle_encoder = { |
404 | .name = "qtrle", |
405 | .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), |
406 | .type = AVMEDIA_TYPE_VIDEO, |
407 | .id = AV_CODEC_ID_QTRLE, |
408 | .priv_data_size = sizeof(QtrleEncContext), |
409 | .init = qtrle_encode_init, |
410 | .encode2 = qtrle_encode_frame, |
411 | .close = qtrle_encode_end, |
412 | .pix_fmts = (const enum AVPixelFormat[]){ |
413 | AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB555BE, AV_PIX_FMT_ARGB, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE |
414 | }, |
415 | }; |
416 |