annotate qtrleenc.c @ 8204:507854688c43 libavcodec

Some BMP files have file size declared in the header equal to headers size without image data, so try to correct that value before conducting checks on declared file size.
author kostya
date Mon, 24 Nov 2008 11:24:02 +0000
parents 4525dcd81357
children 7b81aa80ec46
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 */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
119 unsigned int repeatcount;
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
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
129 uint8_t *this_line = p-> data[0] + line*p->linesize[0] + (width - 1)*s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
130 uint8_t *prev_line = s->previous_frame.data[0] + line*p->linesize[0] + (width - 1)*s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
131
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
132 s->length_table[width] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
133 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
134
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
135 for (i = width - 1; i >= 0; i--) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
136
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
137 if (!s->frame.key_frame && !memcmp(this_line, prev_line, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
138 skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
139 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
140 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
141
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
142 total_skip_cost = s->length_table[i + skipcount] + 2;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
143 s->skip_table[i] = skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
144
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
145
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
146 if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
147 repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
148 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
149 repeatcount = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
150
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
151 total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
152
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
153 /* 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
154 * so let's make it aware */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
155 if (i == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
156 total_skip_cost--;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
157 total_repeat_cost++;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
158 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
159
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
160 if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
161 /* repeat is the best */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
162 s->length_table[i] = total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
163 s->rlecode_table[i] = -repeatcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
164 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
165 else if (skipcount > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
166 /* skip is the best choice here */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
167 s->length_table[i] = total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
168 s->rlecode_table[i] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
169 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
170 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
171 /* We cannot do neither skip nor repeat
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
172 * thus we search for the best bulk copy to do */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
173
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
174 int limit = FFMIN(width - i, MAX_RLE_BULK);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
175
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
176 temp_cost = 1 + s->pixel_size + !i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
177 total_bulk_cost = INT_MAX;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
178
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
179 for (j = 1; j <= limit; j++) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
180 if (s->length_table[i + j] + temp_cost < total_bulk_cost) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
181 /* We have found a better bulk copy ... */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
182 total_bulk_cost = s->length_table[i + j] + temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
183 bulkcount = j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
184 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
185 temp_cost += s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
186 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
187
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
188 s->length_table[i] = total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
189 s->rlecode_table[i] = bulkcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
190 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
191
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
192 this_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
193 prev_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
194 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
196 /* Good ! Now we have the best sequence for this line, let's ouput it */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
197
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
198 /* We do a special case for the first pixel so that we avoid testing it in
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
199 * the whole loop */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
200
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
201 i=0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
202 this_line = p-> data[0] + line*p->linesize[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
203 prev_line = s->previous_frame.data[0] + line*p->linesize[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
204
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
205 if (s->rlecode_table[0] == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
206 bytestream_put_byte(buf, s->skip_table[0] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
207 i += s->skip_table[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
208 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
209 else bytestream_put_byte(buf, 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
210
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
211
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
212 while (i < width) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
213 rlecode = s->rlecode_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
214 bytestream_put_byte(buf, rlecode);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
215 if (rlecode == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
216 /* Write a skip sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
217 bytestream_put_byte(buf, s->skip_table[i] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
218 i += s->skip_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
219 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
220 else if (rlecode > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
221 /* bulk copy */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
222 bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
223 i += rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
224 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
225 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
226 /* repeat the bits */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
227 bytestream_put_buffer(buf, this_line + i*s->pixel_size, 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 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
231 bytestream_put_byte(buf, -1); // end RLE line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
232 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
233
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
234 /** Encodes frame including header */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
235 static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
236 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
237 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
238 int start_line = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
239 int end_line = s->avctx->height;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
240 uint8_t *orig_buf = buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
241
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
242 if (!s->frame.key_frame) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
243 for (start_line = 0; start_line < s->avctx->height; start_line++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
244 if (memcmp(p->data[0] + start_line*p->linesize[0],
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
245 s->previous_frame.data[0] + start_line*p->linesize[0],
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
246 p->linesize[0]))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
247 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
248
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
249 for (end_line=s->avctx->height; end_line > start_line; end_line--)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
250 if (memcmp(p->data[0] + (end_line - 1)*p->linesize[0],
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
251 s->previous_frame.data[0] + (end_line - 1)*p->linesize[0],
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
252 p->linesize[0]))
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
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
256 bytestream_put_be32(&buf, 0); // CHUNK SIZE, patched later
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
257
6204
2265a9c096a4 add parenthesis, fix warning: qtrleenc.c:257: warning: suggest parentheses around && within ||
bcoudurier
parents: 5215
diff changeset
258 if ((start_line == 0 && end_line == s->avctx->height) || start_line == s->avctx->height)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
259 bytestream_put_be16(&buf, 0); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
260 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
261 bytestream_put_be16(&buf, 8); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
262 bytestream_put_be16(&buf, start_line); // starting line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
263 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
264 bytestream_put_be16(&buf, end_line - start_line); // lines to update
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
265 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
266 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
267 for (i = start_line; i < end_line; i++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
268 qtrle_encode_line(s, p, i, &buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
269
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
270 bytestream_put_byte(&buf, 0); // zero skip code = frame finished
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
271 AV_WB32(orig_buf, buf - orig_buf); // patch the chunk size
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
272 return buf - orig_buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
273 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
274
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
275 static int qtrle_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
276 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
277 QtrleEncContext * const s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
278 AVFrame *pict = data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
279 AVFrame * const p = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
280 int chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
281
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
282 *p = *pict;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
283
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
284 if (buf_size < s->max_buf_size) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
285 /* Upper bound check for compressed data */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
286 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
287 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
288 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
289
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
290 if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
291 /* I-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
292 p->pict_type = FF_I_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
293 p->key_frame = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
294 } else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
295 /* P-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
296 p->pict_type = FF_P_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
297 p->key_frame = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
298 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
299
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
300 chunksize = encode_frame(s, pict, buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
301
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
302 /* save the current frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
303 av_picture_copy(&s->previous_frame, (AVPicture *)p, avctx->pix_fmt, avctx->width, avctx->height);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
304 return chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
305 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
306
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6204
diff changeset
307 static av_cold int qtrle_encode_end(AVCodecContext *avctx)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
308 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
309 QtrleEncContext *s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
310
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
311 avpicture_free(&s->previous_frame);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
312 av_free(s->rlecode_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
313 av_free(s->length_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
314 av_free(s->skip_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
315 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
316 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
317
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
318 AVCodec qtrle_encoder = {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
319 "qtrle",
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
320 CODEC_TYPE_VIDEO,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
321 CODEC_ID_QTRLE,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
322 sizeof(QtrleEncContext),
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
323 qtrle_encode_init,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
324 qtrle_encode_frame,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
325 qtrle_encode_end,
6788
e1302edb0f69 Replace some occurrences of -1 with PIX_FMT_NONE.
cehoyos
parents: 6712
diff changeset
326 .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
327 .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
328 };