annotate qtrleenc.c @ 9830:bd0879f752e6 libavcodec

Express the H.264 parser dependency on the golomb code in configure instead of in the Makefile as it is done for all other parts that depend on golomb.
author diego
date Tue, 09 Jun 2009 20:29:52 +0000
parents 9447a746f2cb
children 89f0fd3f1908
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
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
25 #include "avcodec.h"
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
26 #include "bytestream.h"
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
27
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
28 /** Maximum RLE code for bulk copy */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
29 #define MAX_RLE_BULK 127
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
30 /** Maximum RLE code for repeat */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
31 #define MAX_RLE_REPEAT 128
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
32 /** Maximum RLE code for skip */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
33 #define MAX_RLE_SKIP 254
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
34
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
35 typedef struct QtrleEncContext {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
36 AVCodecContext *avctx;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
37 AVFrame frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
38 int pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
39 AVPicture previous_frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
40 unsigned int max_buf_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
41 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
42 * This array will contain at ith position the value of the best RLE code
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
43 * if the line started at pixel i
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
44 * There can be 3 values :
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
45 * skip (0) : skip as much as possible pixels because they are equal to the
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
46 * previous frame ones
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
47 * repeat (<-1) : repeat that pixel -rle_code times, still as much as
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
48 * possible
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
49 * copy (>0) : copy the raw next rle_code pixels */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
50 signed char *rlecode_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
51 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
52 * This array will contain the length of the best rle encoding of the line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
53 * starting at ith pixel */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
54 int *length_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
55 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
56 * Will contain at ith position the number of consecutive pixels equal to the previous
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
57 * frame starting from pixel i */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
58 uint8_t* skip_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
59 } QtrleEncContext;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
60
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6204
diff changeset
61 static av_cold int qtrle_encode_init(AVCodecContext *avctx)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
62 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
63 QtrleEncContext *s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
64
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
65 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
66 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
67 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
68 s->avctx=avctx;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
69
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
70 switch (avctx->pix_fmt) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
71 /* case PIX_FMT_RGB555:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
72 s->pixel_size = 2;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
73 break;*/
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
74 case PIX_FMT_RGB24:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
75 s->pixel_size = 3;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
76 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
77 default:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
78 av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
79 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
80 }
7823
4525dcd81357 Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 7820
diff changeset
81 avctx->bits_per_coded_sample = s->pixel_size*8;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
82
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
83 s->rlecode_table = av_mallocz(s->avctx->width);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
84 s->skip_table = av_mallocz(s->avctx->width);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
85 s->length_table = av_mallocz((s->avctx->width + 1)*sizeof(int));
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
86 if (!s->skip_table || !s->length_table || !s->rlecode_table) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
87 av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
88 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
89 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
90 if (avpicture_alloc(&s->previous_frame, avctx->pix_fmt, avctx->width, avctx->height) < 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
91 av_log(avctx, AV_LOG_ERROR, "Error allocating picture\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
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
95 s->max_buf_size = s->avctx->width*s->avctx->height*s->pixel_size /* image base material */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
96 + 15 /* header + footer */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
97 + s->avctx->height*2 /* skip code+rle end */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
98 + s->avctx->width/MAX_RLE_BULK + 1 /* rle codes */;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
99 avctx->coded_frame = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
100 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
101 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
102
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
103 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
104 * Computes the best RLE sequence for a line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
105 */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
106 static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t **buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
107 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
108 int width=s->avctx->width;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
109 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
110 signed char rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
111
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
112 /* We will use it to compute the best bulk copy sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
113 unsigned int bulkcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
114 /* This will be the number of pixels equal to the preivous frame one's
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
115 * starting from the ith pixel */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
116 unsigned int skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
117 /* This will be the number of consecutive equal pixels in the current
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
118 * 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
119 unsigned int av_uninit(repeatcount);
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
120
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
121 /* The cost of the three different possibilities */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
122 int total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
123 int total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
124 int total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
125
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
126 int temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
127 int j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
128
9691
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
129 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
130 (width - 1)*s->pixel_size;
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
131 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
132 (width - 1)*s->pixel_size;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
133
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
134 s->length_table[width] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
135 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
136
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
137 for (i = width - 1; i >= 0; i--) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
138
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
139 if (!s->frame.key_frame && !memcmp(this_line, prev_line, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
140 skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
141 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
142 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
143
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
144 total_skip_cost = s->length_table[i + skipcount] + 2;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
145 s->skip_table[i] = skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
146
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
147
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
148 if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
149 repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
150 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
151 repeatcount = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
152
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
153 total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
154
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
155 /* 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
156 * so let's make it aware */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
157 if (i == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
158 total_skip_cost--;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
159 total_repeat_cost++;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
160 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
161
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
162 if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
163 /* repeat is the best */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
164 s->length_table[i] = total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
165 s->rlecode_table[i] = -repeatcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
166 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
167 else if (skipcount > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
168 /* skip is the best choice here */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
169 s->length_table[i] = total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
170 s->rlecode_table[i] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
171 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
172 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
173 /* We cannot do neither skip nor repeat
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
174 * thus we search for the best bulk copy to do */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
175
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
176 int limit = FFMIN(width - i, MAX_RLE_BULK);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
177
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
178 temp_cost = 1 + s->pixel_size + !i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
179 total_bulk_cost = INT_MAX;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
180
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
181 for (j = 1; j <= limit; j++) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
182 if (s->length_table[i + j] + temp_cost < total_bulk_cost) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
183 /* We have found a better bulk copy ... */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
184 total_bulk_cost = s->length_table[i + j] + temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
185 bulkcount = j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
186 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
187 temp_cost += s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
188 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
189
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
190 s->length_table[i] = total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
191 s->rlecode_table[i] = bulkcount;
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 this_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
195 prev_line -= s->pixel_size;
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 /* Good ! Now we have the best sequence for this line, let's ouput it */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
199
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
200 /* We do a special case for the first pixel so that we avoid testing it in
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
201 * the whole loop */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
202
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
203 i=0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
204 this_line = p-> data[0] + line*p->linesize[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
205
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
206 if (s->rlecode_table[0] == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
207 bytestream_put_byte(buf, s->skip_table[0] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
208 i += s->skip_table[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
209 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
210 else bytestream_put_byte(buf, 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
211
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
212
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
213 while (i < width) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
214 rlecode = s->rlecode_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
215 bytestream_put_byte(buf, rlecode);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
216 if (rlecode == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
217 /* Write a skip sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
218 bytestream_put_byte(buf, s->skip_table[i] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
219 i += s->skip_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
220 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
221 else if (rlecode > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
222 /* bulk copy */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
223 bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
224 i += rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
225 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
226 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
227 /* repeat the bits */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
228 bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
229 i -= rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
230 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
231 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
232 bytestream_put_byte(buf, -1); // end RLE line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
233 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
234
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
235 /** Encodes frame including header */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
236 static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
237 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
238 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
239 int start_line = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
240 int end_line = s->avctx->height;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
241 uint8_t *orig_buf = buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
242
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
243 if (!s->frame.key_frame) {
9691
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
244 unsigned line_size = s->avctx->width * s->pixel_size;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
245 for (start_line = 0; start_line < s->avctx->height; start_line++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
246 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
247 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
248 line_size))
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
249 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
250
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
251 for (end_line=s->avctx->height; end_line > start_line; end_line--)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
252 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
253 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
254 line_size))
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
255 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
256 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
257
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
258 bytestream_put_be32(&buf, 0); // CHUNK SIZE, patched later
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
259
6204
2265a9c096a4 add parenthesis, fix warning: qtrleenc.c:257: warning: suggest parentheses around && within ||
bcoudurier
parents: 5215
diff changeset
260 if ((start_line == 0 && end_line == s->avctx->height) || start_line == s->avctx->height)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
261 bytestream_put_be16(&buf, 0); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
262 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
263 bytestream_put_be16(&buf, 8); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
264 bytestream_put_be16(&buf, start_line); // starting line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
265 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
266 bytestream_put_be16(&buf, end_line - start_line); // lines to update
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
267 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
268 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
269 for (i = start_line; i < end_line; i++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
270 qtrle_encode_line(s, p, i, &buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
271
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
272 bytestream_put_byte(&buf, 0); // zero skip code = frame finished
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
273 AV_WB32(orig_buf, buf - orig_buf); // patch the chunk size
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
274 return buf - orig_buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
275 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
276
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
277 static int qtrle_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
278 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
279 QtrleEncContext * const s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
280 AVFrame *pict = data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
281 AVFrame * const p = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
282 int chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
283
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
284 *p = *pict;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
285
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
286 if (buf_size < s->max_buf_size) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
287 /* Upper bound check for compressed data */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
288 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
289 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
290 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
291
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
292 if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
293 /* I-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
294 p->pict_type = FF_I_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
295 p->key_frame = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
296 } else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
297 /* P-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
298 p->pict_type = FF_P_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
299 p->key_frame = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
300 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
301
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
302 chunksize = encode_frame(s, pict, buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
303
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
304 /* save the current frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
305 av_picture_copy(&s->previous_frame, (AVPicture *)p, avctx->pix_fmt, avctx->width, avctx->height);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
306 return chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
307 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
308
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6204
diff changeset
309 static av_cold int qtrle_encode_end(AVCodecContext *avctx)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
310 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
311 QtrleEncContext *s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
312
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
313 avpicture_free(&s->previous_frame);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
314 av_free(s->rlecode_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
315 av_free(s->length_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
316 av_free(s->skip_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
317 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
318 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
319
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
320 AVCodec qtrle_encoder = {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
321 "qtrle",
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
322 CODEC_TYPE_VIDEO,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
323 CODEC_ID_QTRLE,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
324 sizeof(QtrleEncContext),
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
325 qtrle_encode_init,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
326 qtrle_encode_frame,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
327 qtrle_encode_end,
6788
e1302edb0f69 Replace some occurrences of -1 with PIX_FMT_NONE.
cehoyos
parents: 6712
diff changeset
328 .pix_fmts = (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_NONE},
7040
e943e1409077 Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents: 6788
diff changeset
329 .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
330 };