improve ffmpeg format selection popup menu, more ffmpeg audio fixes
[goodguy/history.git] / cinelerra-5.0 / quicktime / rle.c
1 /* RLE codec */
2
3 #include "colormodels.h"
4 #include "funcprotos.h"
5 #include "quicktime.h"
6
7
8 typedef struct
9 {
10         unsigned char *work_buffer;
11         int buffer_size;
12         unsigned char *output_temp;
13 } quicktime_rle_codec_t;
14
15
16 static void delete_codec(quicktime_video_map_t *vtrack)
17 {
18         quicktime_rle_codec_t *codec;
19         codec = ((quicktime_codec_t*)vtrack->codec)->priv;
20         if(codec->work_buffer) free(codec->work_buffer);
21         if(codec->output_temp) free(codec->output_temp);
22         free(codec);
23 }
24
25 static int reads_colormodel(quicktime_t *file, 
26                 int colormodel, 
27                 int track)
28 {
29         return (colormodel == BC_RGB888);
30 }
31
32 static int source_cmodel(quicktime_t *file, int track)
33 {
34         int depth = quicktime_video_depth(file, track);
35         if(depth == 24) 
36                 return BC_RGB888;
37         else
38                 return BC_ARGB8888;
39 }
40
41
42
43 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
44 {
45         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
46         quicktime_trak_t *trak = vtrack->track;
47         quicktime_rle_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
48         int depth = quicktime_video_depth(file, track);
49         int width = trak->tkhd.track_width;
50         int height = trak->tkhd.track_height;
51         int size;
52         unsigned char *ptr;
53         int start_line;
54         int total_lines;
55         int header;
56         int row_bytes;
57         int pixel_size;
58         unsigned char *row_ptr;
59         unsigned char *pixel;
60         unsigned char *buffer_end;
61         int code;
62         int r, g, b, i;
63         int need_temp;
64         unsigned char **temp_rows = malloc(sizeof(unsigned char*) * height);
65         int cmodel = source_cmodel(file, track);
66         int skip;
67
68         quicktime_set_video_position(file, vtrack->current_position, track);
69         size = quicktime_frame_size(file, vtrack->current_position, track);
70         row_bytes = depth / 8 * width;
71         pixel_size = depth / 8;
72
73         if(size <= 8) return 0;
74         if(codec->buffer_size < size && codec->work_buffer)
75         {
76                 free(codec->work_buffer);
77                 codec->work_buffer = 0;
78         }
79         if(!codec->work_buffer)
80         {
81                 codec->work_buffer = malloc(size);
82                 codec->buffer_size = size;
83         }
84
85         quicktime_read_data(file, (char*)codec->work_buffer, size);
86         ptr = codec->work_buffer;
87         buffer_end = ptr + size;
88
89 // Chunk size
90         ptr += 4;
91
92 // Header
93         header = (ptr[0] << 8) | ptr[1];
94         ptr += 2;
95
96 // Incremental change
97         if(header & 0x0008)
98         {
99                 start_line = (ptr[0] << 8) | ptr[1];
100                 ptr += 4;
101                 total_lines = (ptr[0] << 8) | ptr[1];
102                 ptr += 4;
103         }
104         else
105 // Keyframe
106         {
107                 start_line = 0;
108                 total_lines = height;
109         }
110
111
112         if(cmodel != file->color_model ||
113                 file->in_x != 0 ||
114                 file->in_y != 0 ||
115                 file->in_w != width ||
116                 file->in_h != height ||
117                 file->out_w != width ||
118                 file->out_h != height)
119                 need_temp = 1;
120
121         if(need_temp)
122         {
123                 if(!codec->output_temp)
124                         codec->output_temp = calloc(1, height * row_bytes);
125                 row_ptr = codec->output_temp + start_line * row_bytes;
126                 for(i = 0; i < height; i++)
127                         temp_rows[i] = codec->output_temp + i * row_bytes;
128         }
129         else
130         {
131                 row_ptr = row_pointers[start_line];
132                 for(i = 0; i < height; i++)
133                         temp_rows[i] = row_pointers[i];
134         }
135
136         switch(depth)
137         {
138                 case 24:
139                         while(total_lines--)
140                         {
141                                 skip = *ptr++;
142                                 pixel = row_ptr + (skip - 1) * pixel_size;
143
144                                 while(ptr < buffer_end && 
145                                         (code = (char)*ptr++) != -1)
146                                 {
147                                         if(code == 0)
148                                         {
149 // Skip code
150                                                 pixel += (*ptr++ - 1) * pixel_size;
151                                         }
152                                         else
153 // Run length encoded
154                                         if(code < 0)
155                                         {
156                                                 code *= -1;
157                                                 r = *ptr++;
158                                                 g = *ptr++;
159                                                 b = *ptr++;
160                                                 while(code--)
161                                                 {
162                                                         *pixel++ = r;
163                                                         *pixel++ = g;
164                                                         *pixel++ = b;
165                                                 }
166                                         }
167                                         else
168 // Uncompressed
169                                         {
170                                                 while(code--)
171                                                 {
172                                                         *pixel++ = *ptr++;
173                                                         *pixel++ = *ptr++;
174                                                         *pixel++ = *ptr++;
175                                                 }
176                                         }               
177                                 }
178
179
180                                 row_ptr += row_bytes;
181                         }
182                         break;
183         }
184
185
186         if(need_temp)
187         {
188                 cmodel_transfer(row_pointers, 
189                         temp_rows,
190                         row_pointers[0],
191                         row_pointers[1],
192                         row_pointers[2],
193                         0,
194                         0,
195                         0,
196                         file->in_x, 
197                         file->in_y, 
198                         file->in_w, 
199                         file->in_h,
200                         0, 
201                         0, 
202                         file->out_w, 
203                         file->out_h,
204                         cmodel, 
205                         file->color_model,
206                         0,
207                         width,
208                         file->out_w);
209         }
210
211         free(temp_rows);
212
213         return 0;
214 }
215
216
217
218 void quicktime_init_codec_rle(quicktime_video_map_t *vtrack)
219 {
220         quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
221 //      quicktime_rle_codec_t *codec = (quicktime_rle_codec_t*)codec_base->priv;
222         codec_base->priv = calloc(1, sizeof(quicktime_rle_codec_t));
223         codec_base->delete_vcodec = delete_codec;
224         codec_base->decode_video = decode;
225         codec_base->reads_colormodel = reads_colormodel;
226         codec_base->fourcc = QUICKTIME_RLE;
227         codec_base->title = "RLE";
228         codec_base->desc = "Run length encoding";
229
230 }
231