annotate qtrleenc.c @ 12530:63edd10ad4bc libavcodec tip

Try to fix crashes introduced by r25218 r25218 made assumptions about the existence of past reference frames that weren't necessarily true.
author darkshikari
date Tue, 28 Sep 2010 09:06:22 +0000
parents ffb3668ff7af
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
1 /*
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
2 * Quicktime Animation (RLE) Video Encoder
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
3 * Copyright (C) 2007 Clemens Fruhwirth
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
4 * Copyright (C) 2007 Alexis Ballier
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
5 *
7804
470878c73621 license header consistency cosmetics.
diego
parents: 7040
diff changeset
6 * This file is based on flashsvenc.c.
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
7 *
7804
470878c73621 license header consistency cosmetics.
diego
parents: 7040
diff changeset
8 * This file is part of FFmpeg.
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
9 *
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
10 * FFmpeg is free software; you can redistribute it and/or
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
11 * modify it under the terms of the GNU Lesser General Public
7820
9905b13b3399 Relicense from LGPL 2.1 to LGPL 2.1 or later with the authors' permission.
diego
parents: 7804
diff changeset
12 * License as published by the Free Software Foundation; either
9905b13b3399 Relicense from LGPL 2.1 to LGPL 2.1 or later with the authors' permission.
diego
parents: 7804
diff changeset
13 * version 2.1 of the License, or (at your option) any later version.
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
14 *
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
15 * FFmpeg is distributed in the hope that it will be useful,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
18 * Lesser General Public License for more details.
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
19 *
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
20 * You should have received a copy of the GNU Lesser General Public
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
21 * License along with FFmpeg; if not, write to the Free Software
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
23 */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
24
12372
914f484bb476 Remove use of the deprecated function avcodec_check_dimensions(), use
stefano
parents: 12024
diff changeset
25 #include "libavcore/imgutils.h"
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
26 #include "avcodec.h"
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
27 #include "bytestream.h"
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
28
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
29 /** Maximum RLE code for bulk copy */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
30 #define MAX_RLE_BULK 127
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
31 /** Maximum RLE code for repeat */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
32 #define MAX_RLE_REPEAT 128
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
33 /** Maximum RLE code for skip */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
34 #define MAX_RLE_SKIP 254
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
35
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
36 typedef struct QtrleEncContext {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
37 AVCodecContext *avctx;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
38 AVFrame frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
39 int pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
40 AVPicture previous_frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
41 unsigned int max_buf_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
42 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
43 * This array will contain at ith position the value of the best RLE code
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
44 * if the line started at pixel i
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
45 * There can be 3 values :
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
46 * skip (0) : skip as much as possible pixels because they are equal to the
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
47 * previous frame ones
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
48 * repeat (<-1) : repeat that pixel -rle_code times, still as much as
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
49 * possible
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
50 * copy (>0) : copy the raw next rle_code pixels */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
51 signed char *rlecode_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
52 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
53 * This array will contain the length of the best rle encoding of the line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
54 * starting at ith pixel */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
55 int *length_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
56 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
57 * Will contain at ith position the number of consecutive pixels equal to the previous
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
58 * frame starting from pixel i */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
59 uint8_t* skip_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
60 } QtrleEncContext;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
61
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6204
diff changeset
62 static av_cold int qtrle_encode_init(AVCodecContext *avctx)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
63 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
64 QtrleEncContext *s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
65
12462
ffb3668ff7af Use new imgutils.h API names, fix deprecation warnings.
stefano
parents: 12372
diff changeset
66 if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) {
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
67 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
68 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
69 s->avctx=avctx;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
70
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
71 switch (avctx->pix_fmt) {
11505
61949a920190 qtrleenc: add rgb555 output
benoit
parents: 10146
diff changeset
72 case PIX_FMT_RGB555BE:
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
73 s->pixel_size = 2;
11505
61949a920190 qtrleenc: add rgb555 output
benoit
parents: 10146
diff changeset
74 break;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
75 case PIX_FMT_RGB24:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
76 s->pixel_size = 3;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
77 break;
9932
89f0fd3f1908 Add PIX_FMT_ARGB encoding to qtrle.
cehoyos
parents: 9691
diff changeset
78 case PIX_FMT_ARGB:
89f0fd3f1908 Add PIX_FMT_ARGB encoding to qtrle.
cehoyos
parents: 9691
diff changeset
79 s->pixel_size = 4;
89f0fd3f1908 Add PIX_FMT_ARGB encoding to qtrle.
cehoyos
parents: 9691
diff changeset
80 break;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
81 default:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
82 av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
83 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
84 }
7823
4525dcd81357 Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 7820
diff changeset
85 avctx->bits_per_coded_sample = s->pixel_size*8;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
86
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
87 s->rlecode_table = av_mallocz(s->avctx->width);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
88 s->skip_table = av_mallocz(s->avctx->width);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
89 s->length_table = av_mallocz((s->avctx->width + 1)*sizeof(int));
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
90 if (!s->skip_table || !s->length_table || !s->rlecode_table) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
91 av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
92 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
93 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
94 if (avpicture_alloc(&s->previous_frame, avctx->pix_fmt, avctx->width, avctx->height) < 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
95 av_log(avctx, AV_LOG_ERROR, "Error allocating picture\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
96 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
97 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
98
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
99 s->max_buf_size = s->avctx->width*s->avctx->height*s->pixel_size /* image base material */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
100 + 15 /* header + footer */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
101 + s->avctx->height*2 /* skip code+rle end */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
102 + s->avctx->width/MAX_RLE_BULK + 1 /* rle codes */;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
103 avctx->coded_frame = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
104 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
105 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
106
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
107 /**
12024
fdafbcef52f5 Fix grammar errors in documentation
mru
parents: 11560
diff changeset
108 * Compute the best RLE sequence for a line
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
109 */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
110 static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t **buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
111 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
112 int width=s->avctx->width;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
113 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
114 signed char rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
115
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
116 /* We will use it to compute the best bulk copy sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
117 unsigned int bulkcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
118 /* This will be the number of pixels equal to the preivous frame one's
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
119 * starting from the ith pixel */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
120 unsigned int skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
121 /* This will be the number of consecutive equal pixels in the current
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
122 * frame, starting from the ith one also */
8802
7b81aa80ec46 Add av_uninit macro to variable to avoid false positive warning:
diego
parents: 7823
diff changeset
123 unsigned int av_uninit(repeatcount);
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
124
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
125 /* The cost of the three different possibilities */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
126 int total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
127 int total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
128 int total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
129
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
130 int temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
131 int j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
132
9691
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
133 uint8_t *this_line = p-> data[0] + line*p-> linesize[0] +
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
134 (width - 1)*s->pixel_size;
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
135 uint8_t *prev_line = s->previous_frame.data[0] + line*s->previous_frame.linesize[0] +
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
136 (width - 1)*s->pixel_size;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
137
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
138 s->length_table[width] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
139 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
140
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
141 for (i = width - 1; i >= 0; i--) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
142
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
143 if (!s->frame.key_frame && !memcmp(this_line, prev_line, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
144 skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
145 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
146 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
147
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
148 total_skip_cost = s->length_table[i + skipcount] + 2;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
149 s->skip_table[i] = skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
150
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
151
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
152 if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
153 repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
154 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
155 repeatcount = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
156
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
157 total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
158
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
159 /* skip code is free for the first pixel, it costs one byte for repeat and bulk copy
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
160 * so let's make it aware */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
161 if (i == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
162 total_skip_cost--;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
163 total_repeat_cost++;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
164 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
165
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
166 if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
167 /* repeat is the best */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
168 s->length_table[i] = total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
169 s->rlecode_table[i] = -repeatcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
170 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
171 else if (skipcount > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
172 /* skip is the best choice here */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
173 s->length_table[i] = total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
174 s->rlecode_table[i] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
175 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
176 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
177 /* We cannot do neither skip nor repeat
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
178 * thus we search for the best bulk copy to do */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
179
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
180 int limit = FFMIN(width - i, MAX_RLE_BULK);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
181
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
182 temp_cost = 1 + s->pixel_size + !i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
183 total_bulk_cost = INT_MAX;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
184
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
185 for (j = 1; j <= limit; j++) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
186 if (s->length_table[i + j] + temp_cost < total_bulk_cost) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
187 /* We have found a better bulk copy ... */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
188 total_bulk_cost = s->length_table[i + j] + temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
189 bulkcount = j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
190 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
191 temp_cost += s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
192 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
193
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
194 s->length_table[i] = total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
195 s->rlecode_table[i] = bulkcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
196 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
197
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
198 this_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
199 prev_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
200 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
201
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
202 /* Good ! Now we have the best sequence for this line, let's ouput it */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
203
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
204 /* We do a special case for the first pixel so that we avoid testing it in
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
205 * the whole loop */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
206
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
207 i=0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
208 this_line = p-> data[0] + line*p->linesize[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
209
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
210 if (s->rlecode_table[0] == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
211 bytestream_put_byte(buf, s->skip_table[0] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
212 i += s->skip_table[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
213 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
214 else bytestream_put_byte(buf, 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
215
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
216
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
217 while (i < width) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
218 rlecode = s->rlecode_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
219 bytestream_put_byte(buf, rlecode);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
220 if (rlecode == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
221 /* Write a skip sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
222 bytestream_put_byte(buf, s->skip_table[i] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
223 i += s->skip_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
224 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
225 else if (rlecode > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
226 /* bulk copy */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
227 bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
228 i += rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
229 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
230 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
231 /* repeat the bits */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
232 bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
233 i -= rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
234 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
235 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
236 bytestream_put_byte(buf, -1); // end RLE line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
237 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
238
12024
fdafbcef52f5 Fix grammar errors in documentation
mru
parents: 11560
diff changeset
239 /** Encode frame including header */
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
240 static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
241 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
242 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
243 int start_line = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
244 int end_line = s->avctx->height;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
245 uint8_t *orig_buf = buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
246
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
247 if (!s->frame.key_frame) {
9691
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
248 unsigned line_size = s->avctx->width * s->pixel_size;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
249 for (start_line = 0; start_line < s->avctx->height; start_line++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
250 if (memcmp(p->data[0] + start_line*p->linesize[0],
9691
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
251 s->previous_frame.data[0] + start_line*s->previous_frame.linesize[0],
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
252 line_size))
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
253 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
254
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
255 for (end_line=s->avctx->height; end_line > start_line; end_line--)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
256 if (memcmp(p->data[0] + (end_line - 1)*p->linesize[0],
9691
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
257 s->previous_frame.data[0] + (end_line - 1)*s->previous_frame.linesize[0],
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
258 line_size))
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
259 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
260 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
261
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
262 bytestream_put_be32(&buf, 0); // CHUNK SIZE, patched later
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
263
6204
2265a9c096a4 add parenthesis, fix warning: qtrleenc.c:257: warning: suggest parentheses around && within ||
bcoudurier
parents: 5215
diff changeset
264 if ((start_line == 0 && end_line == s->avctx->height) || start_line == s->avctx->height)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
265 bytestream_put_be16(&buf, 0); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
266 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
267 bytestream_put_be16(&buf, 8); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
268 bytestream_put_be16(&buf, start_line); // starting line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
269 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
270 bytestream_put_be16(&buf, end_line - start_line); // lines to update
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
271 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
272 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
273 for (i = start_line; i < end_line; i++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
274 qtrle_encode_line(s, p, i, &buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
275
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
276 bytestream_put_byte(&buf, 0); // zero skip code = frame finished
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
277 AV_WB32(orig_buf, buf - orig_buf); // patch the chunk size
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
278 return buf - orig_buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
279 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
280
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
281 static int qtrle_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
282 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
283 QtrleEncContext * const s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
284 AVFrame *pict = data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
285 AVFrame * const p = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
286 int chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
287
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
288 *p = *pict;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
289
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
290 if (buf_size < s->max_buf_size) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
291 /* Upper bound check for compressed data */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
292 av_log(avctx, AV_LOG_ERROR, "buf_size %d < %d\n", buf_size, s->max_buf_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
293 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
294 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
295
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
296 if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
297 /* I-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
298 p->pict_type = FF_I_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
299 p->key_frame = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
300 } else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
301 /* P-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
302 p->pict_type = FF_P_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
303 p->key_frame = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
304 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
305
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
306 chunksize = encode_frame(s, pict, buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
307
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
308 /* save the current frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
309 av_picture_copy(&s->previous_frame, (AVPicture *)p, avctx->pix_fmt, avctx->width, avctx->height);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
310 return chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
311 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
312
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6204
diff changeset
313 static av_cold int qtrle_encode_end(AVCodecContext *avctx)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
314 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
315 QtrleEncContext *s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
316
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
317 avpicture_free(&s->previous_frame);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
318 av_free(s->rlecode_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
319 av_free(s->length_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
320 av_free(s->skip_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
321 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
322 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
323
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
324 AVCodec qtrle_encoder = {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
325 "qtrle",
11560
8a4984c5cacc Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents: 11505
diff changeset
326 AVMEDIA_TYPE_VIDEO,
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
327 CODEC_ID_QTRLE,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
328 sizeof(QtrleEncContext),
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
329 qtrle_encode_init,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
330 qtrle_encode_frame,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
331 qtrle_encode_end,
11505
61949a920190 qtrleenc: add rgb555 output
benoit
parents: 10146
diff changeset
332 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB555BE, PIX_FMT_ARGB, PIX_FMT_NONE},
7040
e943e1409077 Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents: 6788
diff changeset
333 .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
334 };