annotate qtrleenc.c @ 5875:5a61e8e2f65c libavcodec

Remove libvorbis Vorbis decoding support. Our native decoder is complete and has no known bugs, any remaining issues will hopefully be uncovered now.
author diego
date Sun, 04 Nov 2007 12:55:32 +0000
parents 2b72f9bc4f06
children 2265a9c096a4
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 *
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
6 * This file is part of FFmpeg.
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
7 *
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
8 * This file is based on flashsvenc.c
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
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
12 * License, version 2.1, as published by the Free Software Foundation
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
13 *
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
14 * FFmpeg is distributed in the hope that it will be useful,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
17 * Lesser General Public License for more details.
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
18 *
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
19 * You should have received a copy of the GNU Lesser General Public
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
20 * License along with FFmpeg; if not, write to the Free Software
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
22 */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
23
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
24 #include "avcodec.h"
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
25 #include "bytestream.h"
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
26
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
27 /** Maximum RLE code for bulk copy */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
28 #define MAX_RLE_BULK 127
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
29 /** Maximum RLE code for repeat */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
30 #define MAX_RLE_REPEAT 128
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
31 /** Maximum RLE code for skip */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
32 #define MAX_RLE_SKIP 254
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
33
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
34 typedef struct QtrleEncContext {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
35 AVCodecContext *avctx;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
36 AVFrame frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
37 int pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
38 AVPicture previous_frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
39 unsigned int max_buf_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
40 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
41 * This array will contain at ith position the value of the best RLE code
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
42 * if the line started at pixel i
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
43 * There can be 3 values :
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
44 * skip (0) : skip as much as possible pixels because they are equal to the
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
45 * previous frame ones
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
46 * repeat (<-1) : repeat that pixel -rle_code times, still as much as
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
47 * possible
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
48 * copy (>0) : copy the raw next rle_code pixels */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
49 signed char *rlecode_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
50 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
51 * This array will contain the length of the best rle encoding of the line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
52 * starting at ith pixel */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
53 int *length_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
54 /**
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
55 * Will contain at ith position the number of consecutive pixels equal to the previous
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
56 * frame starting from pixel i */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
57 uint8_t* skip_table;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
58 } QtrleEncContext;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
59
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
60 static int qtrle_encode_init(AVCodecContext *avctx)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
61 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
62 QtrleEncContext *s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
63
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
64 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
65 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
66 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
67 s->avctx=avctx;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
68
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
69 switch (avctx->pix_fmt) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
70 /* case PIX_FMT_RGB555:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
71 s->pixel_size = 2;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
72 break;*/
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
73 case PIX_FMT_RGB24:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
74 s->pixel_size = 3;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
75 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
76 default:
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
77 av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
78 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
79 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
80 avctx->bits_per_sample = s->pixel_size*8;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
81
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
82 s->rlecode_table = av_mallocz(s->avctx->width);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
83 s->skip_table = av_mallocz(s->avctx->width);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
84 s->length_table = av_mallocz((s->avctx->width + 1)*sizeof(int));
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
85 if (!s->skip_table || !s->length_table || !s->rlecode_table) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
86 av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n");
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
87 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
88 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
89 if (avpicture_alloc(&s->previous_frame, avctx->pix_fmt, avctx->width, avctx->height) < 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
90 av_log(avctx, AV_LOG_ERROR, "Error allocating picture\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
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
94 s->max_buf_size = s->avctx->width*s->avctx->height*s->pixel_size /* image base material */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
95 + 15 /* header + footer */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
96 + s->avctx->height*2 /* skip code+rle end */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
97 + s->avctx->width/MAX_RLE_BULK + 1 /* rle codes */;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
98 avctx->coded_frame = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
99 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
100 }
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 * Computes the best RLE sequence for a line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
104 */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
105 static void qtrle_encode_line(QtrleEncContext *s, AVFrame *p, int line, uint8_t **buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
106 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
107 int width=s->avctx->width;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
108 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
109 signed char rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
110
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
111 /* We will use it to compute the best bulk copy sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
112 unsigned int bulkcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
113 /* This will be the number of pixels equal to the preivous frame one's
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
114 * starting from the ith pixel */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
115 unsigned int skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
116 /* This will be the number of consecutive equal pixels in the current
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
117 * frame, starting from the ith one also */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
118 unsigned int repeatcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
119
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
120 /* The cost of the three different possibilities */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
121 int total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
122 int total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
123 int total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
124
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
125 int temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
126 int j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
127
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
128 uint8_t *this_line = p-> data[0] + line*p->linesize[0] + (width - 1)*s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
129 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
130
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
131 s->length_table[width] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
132 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
133
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
134 for (i = width - 1; i >= 0; i--) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
135
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
136 if (!s->frame.key_frame && !memcmp(this_line, prev_line, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
137 skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
138 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
139 skipcount = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
140
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
141 total_skip_cost = s->length_table[i + skipcount] + 2;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
142 s->skip_table[i] = skipcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
143
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
144
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
145 if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
146 repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
147 else
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
148 repeatcount = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
149
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
150 total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
151
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
152 /* 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
153 * so let's make it aware */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
154 if (i == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
155 total_skip_cost--;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
156 total_repeat_cost++;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
157 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
158
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
159 if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
160 /* repeat is the best */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
161 s->length_table[i] = total_repeat_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
162 s->rlecode_table[i] = -repeatcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
163 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
164 else if (skipcount > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
165 /* skip is the best choice here */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
166 s->length_table[i] = total_skip_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
167 s->rlecode_table[i] = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
168 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
169 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
170 /* We cannot do neither skip nor repeat
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
171 * thus we search for the best bulk copy to do */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
172
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
173 int limit = FFMIN(width - i, MAX_RLE_BULK);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
174
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
175 temp_cost = 1 + s->pixel_size + !i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
176 total_bulk_cost = INT_MAX;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
177
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
178 for (j = 1; j <= limit; j++) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
179 if (s->length_table[i + j] + temp_cost < total_bulk_cost) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
180 /* We have found a better bulk copy ... */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
181 total_bulk_cost = s->length_table[i + j] + temp_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
182 bulkcount = j;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
183 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
184 temp_cost += s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
185 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
186
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
187 s->length_table[i] = total_bulk_cost;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
188 s->rlecode_table[i] = bulkcount;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
189 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
190
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
191 this_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
192 prev_line -= s->pixel_size;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
193 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
194
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
195 /* Good ! Now we have the best sequence for this line, let's ouput it */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
196
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
197 /* We do a special case for the first pixel so that we avoid testing it in
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
198 * the whole loop */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
199
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
200 i=0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
201 this_line = p-> data[0] + line*p->linesize[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
202 prev_line = s->previous_frame.data[0] + line*p->linesize[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
203
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
204 if (s->rlecode_table[0] == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
205 bytestream_put_byte(buf, s->skip_table[0] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
206 i += s->skip_table[0];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
207 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
208 else bytestream_put_byte(buf, 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
209
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
210
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
211 while (i < width) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
212 rlecode = s->rlecode_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
213 bytestream_put_byte(buf, rlecode);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
214 if (rlecode == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
215 /* Write a skip sequence */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
216 bytestream_put_byte(buf, s->skip_table[i] + 1);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
217 i += s->skip_table[i];
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
218 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
219 else if (rlecode > 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
220 /* bulk copy */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
221 bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
222 i += rlecode;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
223 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
224 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
225 /* repeat the bits */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
226 bytestream_put_buffer(buf, this_line + i*s->pixel_size, 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 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
230 bytestream_put_byte(buf, -1); // end RLE line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
231 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
232
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
233 /** Encodes frame including header */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
234 static int encode_frame(QtrleEncContext *s, AVFrame *p, uint8_t *buf)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
235 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
236 int i;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
237 int start_line = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
238 int end_line = s->avctx->height;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
239 uint8_t *orig_buf = buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
240
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
241 if (!s->frame.key_frame) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
242 for (start_line = 0; start_line < s->avctx->height; start_line++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
243 if (memcmp(p->data[0] + start_line*p->linesize[0],
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
244 s->previous_frame.data[0] + start_line*p->linesize[0],
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
245 p->linesize[0]))
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
246 break;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
247
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
248 for (end_line=s->avctx->height; end_line > start_line; end_line--)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
249 if (memcmp(p->data[0] + (end_line - 1)*p->linesize[0],
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
250 s->previous_frame.data[0] + (end_line - 1)*p->linesize[0],
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
251 p->linesize[0]))
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
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
255 bytestream_put_be32(&buf, 0); // CHUNK SIZE, patched later
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
256
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
257 if (start_line == 0 && end_line == s->avctx->height || start_line == s->avctx->height)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
258 bytestream_put_be16(&buf, 0); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
259 else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
260 bytestream_put_be16(&buf, 8); // header
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
261 bytestream_put_be16(&buf, start_line); // starting line
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
262 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
263 bytestream_put_be16(&buf, end_line - start_line); // lines to update
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
264 bytestream_put_be16(&buf, 0); // unknown
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
265 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
266 for (i = start_line; i < end_line; i++)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
267 qtrle_encode_line(s, p, i, &buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
268
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
269 bytestream_put_byte(&buf, 0); // zero skip code = frame finished
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
270 AV_WB32(orig_buf, buf - orig_buf); // patch the chunk size
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
271 return buf - orig_buf;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
272 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
273
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
274 static int qtrle_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
275 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
276 QtrleEncContext * const s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
277 AVFrame *pict = data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
278 AVFrame * const p = &s->frame;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
279 int chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
280
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
281 *p = *pict;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
282
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
283 if (buf_size < s->max_buf_size) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
284 /* Upper bound check for compressed data */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
285 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
286 return -1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
287 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
288
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
289 if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
290 /* I-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
291 p->pict_type = FF_I_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
292 p->key_frame = 1;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
293 } else {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
294 /* P-Frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
295 p->pict_type = FF_P_TYPE;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
296 p->key_frame = 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
297 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
298
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
299 chunksize = encode_frame(s, pict, buf);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
300
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
301 /* save the current frame */
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
302 av_picture_copy(&s->previous_frame, (AVPicture *)p, avctx->pix_fmt, avctx->width, avctx->height);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
303 return chunksize;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
304 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
305
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
306 static int qtrle_encode_end(AVCodecContext *avctx)
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
307 {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
308 QtrleEncContext *s = avctx->priv_data;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
309
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
310 avpicture_free(&s->previous_frame);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
311 av_free(s->rlecode_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
312 av_free(s->length_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
313 av_free(s->skip_table);
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
314 return 0;
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
315 }
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
316
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
317 AVCodec qtrle_encoder = {
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
318 "qtrle",
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
319 CODEC_TYPE_VIDEO,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
320 CODEC_ID_QTRLE,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
321 sizeof(QtrleEncContext),
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
322 qtrle_encode_init,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
323 qtrle_encode_frame,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
324 qtrle_encode_end,
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
325 .pix_fmts = (enum PixelFormat[]){PIX_FMT_RGB24, -1},
71db186c51b7 QT RLE encoder
benoit
parents:
diff changeset
326 };