annotate qtrleenc.c @ 11211:dfeaae916502 libavcodec

Since WavPack chunk can contain more samples than FFmpeg is guaranteed to hold, decode it in several iterations outputting as many samples as possible.
author kostya
date Fri, 19 Feb 2010 14:05:41 +0000
parents 38cfe222e1a4
children 61949a920190
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;
9932
89f0fd3f1908 Add PIX_FMT_ARGB encoding to qtrle.
cehoyos
parents: 9691
diff changeset
77 case PIX_FMT_ARGB:
89f0fd3f1908 Add PIX_FMT_ARGB encoding to qtrle.
cehoyos
parents: 9691
diff changeset
78 s->pixel_size = 4;
89f0fd3f1908 Add PIX_FMT_ARGB encoding to qtrle.
cehoyos
parents: 9691
diff changeset
79 break;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
80 default:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
81 av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
82 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
83 }
7823
4525dcd81357 Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 7820
diff changeset
84 avctx->bits_per_coded_sample = s->pixel_size*8;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
85
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
86 s->rlecode_table = av_mallocz(s->avctx->width);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
87 s->skip_table = av_mallocz(s->avctx->width);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
88 s->length_table = av_mallocz((s->avctx->width + 1)*sizeof(int));
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
89 if (!s->skip_table || !s->length_table || !s->rlecode_table) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
90 av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
91 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
92 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
93 if (avpicture_alloc(&s->previous_frame, avctx->pix_fmt, avctx->width, avctx->height) < 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
94 av_log(avctx, AV_LOG_ERROR, "Error allocating picture\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
95 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
96 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
97
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
98 s->max_buf_size = s->avctx->width*s->avctx->height*s->pixel_size /* image base material */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
99 + 15 /* header + footer */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
100 + s->avctx->height*2 /* skip code+rle end */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
101 + s->avctx->width/MAX_RLE_BULK + 1 /* rle codes */;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
102 avctx->coded_frame = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
103 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
104 }
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 * Computes the best RLE sequence for a line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
108 */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
109 static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t **buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
110 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
111 int width=s->avctx->width;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
112 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
113 signed char rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
114
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
115 /* We will use it to compute the best bulk copy sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
116 unsigned int bulkcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
117 /* This will be the number of pixels equal to the preivous frame one's
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
118 * starting from the ith pixel */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
119 unsigned int skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
120 /* This will be the number of consecutive equal pixels in the current
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
121 * 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
122 unsigned int av_uninit(repeatcount);
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
123
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
124 /* The cost of the three different possibilities */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
125 int total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
126 int total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
127 int total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
128
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
129 int temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
130 int j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
131
9691
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
132 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
133 (width - 1)*s->pixel_size;
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
134 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
135 (width - 1)*s->pixel_size;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
136
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
137 s->length_table[width] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
138 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
139
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
140 for (i = width - 1; i >= 0; i--) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
141
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
142 if (!s->frame.key_frame && !memcmp(this_line, prev_line, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
143 skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
144 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
145 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
146
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
147 total_skip_cost = s->length_table[i + skipcount] + 2;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
148 s->skip_table[i] = skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
149
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
150
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
151 if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
152 repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
153 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
154 repeatcount = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
155
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
156 total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
157
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
158 /* 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
159 * so let's make it aware */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
160 if (i == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
161 total_skip_cost--;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
162 total_repeat_cost++;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
163 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
164
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
165 if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
166 /* repeat is the best */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
167 s->length_table[i] = total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
168 s->rlecode_table[i] = -repeatcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
169 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
170 else if (skipcount > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
171 /* skip is the best choice here */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
172 s->length_table[i] = total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
173 s->rlecode_table[i] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
174 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
175 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
176 /* We cannot do neither skip nor repeat
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
177 * thus we search for the best bulk copy to do */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
178
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
179 int limit = FFMIN(width - i, MAX_RLE_BULK);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
180
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
181 temp_cost = 1 + s->pixel_size + !i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
182 total_bulk_cost = INT_MAX;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
183
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
184 for (j = 1; j <= limit; j++) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
185 if (s->length_table[i + j] + temp_cost < total_bulk_cost) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
186 /* We have found a better bulk copy ... */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
187 total_bulk_cost = s->length_table[i + j] + temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
188 bulkcount = j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
189 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
190 temp_cost += s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
191 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
192
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
193 s->length_table[i] = total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
194 s->rlecode_table[i] = bulkcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
195 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
196
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
197 this_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
198 prev_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
199 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
200
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
201 /* Good ! Now we have the best sequence for this line, let's ouput it */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
202
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
203 /* We do a special case for the first pixel so that we avoid testing it in
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
204 * the whole loop */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
205
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
206 i=0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
207 this_line = p-> data[0] + line*p->linesize[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
208
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
209 if (s->rlecode_table[0] == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
210 bytestream_put_byte(buf, s->skip_table[0] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
211 i += s->skip_table[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
212 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
213 else bytestream_put_byte(buf, 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
214
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
215
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
216 while (i < width) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
217 rlecode = s->rlecode_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
218 bytestream_put_byte(buf, rlecode);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
219 if (rlecode == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
220 /* Write a skip sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
221 bytestream_put_byte(buf, s->skip_table[i] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
222 i += s->skip_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
223 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
224 else if (rlecode > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
225 /* bulk copy */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
226 bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
227 i += rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
228 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
229 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
230 /* repeat the bits */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
231 bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
232 i -= rlecode;
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 bytestream_put_byte(buf, -1); // end RLE line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
236 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
237
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
238 /** Encodes frame including header */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
239 static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
240 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
241 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
242 int start_line = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
243 int end_line = s->avctx->height;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
244 uint8_t *orig_buf = buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
245
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
246 if (!s->frame.key_frame) {
9691
9447a746f2cb fix qtrle encoding when previous frame linesize differs, fix #998
bcoudurier
parents: 9593
diff changeset
247 unsigned line_size = s->avctx->width * s->pixel_size;
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
248 for (start_line = 0; start_line < s->avctx->height; start_line++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
249 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
250 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
251 line_size))
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
252 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
253
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
254 for (end_line=s->avctx->height; end_line > start_line; end_line--)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
255 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
256 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
257 line_size))
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
258 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
259 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
260
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
261 bytestream_put_be32(&buf, 0); // CHUNK SIZE, patched later
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
262
6204
2265a9c096a4 add parenthesis, fix warning: qtrleenc.c:257: warning: suggest parentheses around && within ||
bcoudurier
parents: 5215
diff changeset
263 if ((start_line == 0 && end_line == s->avctx->height) || start_line == s->avctx->height)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
264 bytestream_put_be16(&buf, 0); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
265 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
266 bytestream_put_be16(&buf, 8); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
267 bytestream_put_be16(&buf, start_line); // starting line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
268 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
269 bytestream_put_be16(&buf, end_line - start_line); // lines to update
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
270 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
271 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
272 for (i = start_line; i < end_line; i++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
273 qtrle_encode_line(s, p, i, &buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
274
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
275 bytestream_put_byte(&buf, 0); // zero skip code = frame finished
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
276 AV_WB32(orig_buf, buf - orig_buf); // patch the chunk size
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
277 return buf - orig_buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
278 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
279
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
280 static int qtrle_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
281 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
282 QtrleEncContext * const s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
283 AVFrame *pict = data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
284 AVFrame * const p = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
285 int chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
286
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
287 *p = *pict;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
288
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
289 if (buf_size < s->max_buf_size) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
290 /* Upper bound check for compressed data */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
291 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
292 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
293 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
294
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
295 if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
296 /* I-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
297 p->pict_type = FF_I_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
298 p->key_frame = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
299 } else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
300 /* P-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
301 p->pict_type = FF_P_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
302 p->key_frame = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
303 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
304
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
305 chunksize = encode_frame(s, pict, buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
306
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
307 /* save the current frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
308 av_picture_copy(&s->previous_frame, (AVPicture *)p, avctx->pix_fmt, avctx->width, avctx->height);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
309 return chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
310 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
311
6517
48759bfbd073 Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents: 6204
diff changeset
312 static av_cold int qtrle_encode_end(AVCodecContext *avctx)
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
313 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
314 QtrleEncContext *s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
315
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
316 avpicture_free(&s->previous_frame);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
317 av_free(s->rlecode_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
318 av_free(s->length_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
319 av_free(s->skip_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
320 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
321 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
322
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
323 AVCodec qtrle_encoder = {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
324 "qtrle",
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
325 CODEC_TYPE_VIDEO,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
326 CODEC_ID_QTRLE,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
327 sizeof(QtrleEncContext),
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
328 qtrle_encode_init,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
329 qtrle_encode_frame,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
330 qtrle_encode_end,
10146
38cfe222e1a4 Mark all pix_fmts and supported_framerates compound literals as const.
reimar
parents: 9932
diff changeset
331 .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_ARGB, PIX_FMT_NONE},
7040
e943e1409077 Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents: 6788
diff changeset
332 .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"),
5195
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
333 };