r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / quicktime / yuv4.c
blobfe61948cd0f8f5bc9be174d6e818786609a5304a
1 #include "colormodels.h"
2 #include "funcprotos.h"
3 #include "quicktime.h"
4 #include "yuv4.h"
6 /* U V values are signed but Y R G B values are unsigned! */
7 /*
8 * R = Y + 1.40200 * V
9 * G = Y - 0.34414 * U - 0.71414 * V
10 * B = Y + 1.77200 * U
14 * Y = 0.2990 * R + 0.5870 * G + 0.1140 * B
15 * U = -0.1687 * R - 0.3310 * G + 0.5000 * B
16 * V = 0.5000 * R - 0.4187 * G - 0.0813 * B
20 /* Now storing data as rows of UVYYYYUVYYYY */
21 typedef struct
23 int use_float;
24 long rtoy_tab[256], gtoy_tab[256], btoy_tab[256];
25 long rtou_tab[256], gtou_tab[256], btou_tab[256];
26 long rtov_tab[256], gtov_tab[256], btov_tab[256];
28 long vtor_tab[256], vtog_tab[256];
29 long utog_tab[256], utob_tab[256];
30 long *vtor, *vtog, *utog, *utob;
32 unsigned char *work_buffer;
34 /* The YUV4 codec requires a bytes per line that is a multiple of 4 */
35 int bytes_per_line;
36 /* Actual rows encoded in the yuv4 format */
37 int rows;
38 int initialized;
39 } quicktime_yuv4_codec_t;
41 static int quicktime_delete_codec_yuv4(quicktime_video_map_t *vtrack)
43 quicktime_yuv4_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
44 free(codec->work_buffer);
45 free(codec);
46 return 0;
49 static int reads_colormodel(quicktime_t *file,
50 int colormodel,
51 int track)
53 return colormodel == BC_RGB888;
56 static void initialize(quicktime_video_map_t *vtrack, quicktime_yuv4_codec_t *codec)
58 int i;
59 if(!codec->initialized)
61 /* Init private items */
62 for(i = 0; i < 256; i++)
64 /* compression */
65 codec->rtoy_tab[i] = (long)( 0.2990 * 65536 * i);
66 codec->rtou_tab[i] = (long)(-0.1687 * 65536 * i);
67 codec->rtov_tab[i] = (long)( 0.5000 * 65536 * i);
69 codec->gtoy_tab[i] = (long)( 0.5870 * 65536 * i);
70 codec->gtou_tab[i] = (long)(-0.3320 * 65536 * i);
71 codec->gtov_tab[i] = (long)(-0.4187 * 65536 * i);
73 codec->btoy_tab[i] = (long)( 0.1140 * 65536 * i);
74 codec->btou_tab[i] = (long)( 0.5000 * 65536 * i);
75 codec->btov_tab[i] = (long)(-0.0813 * 65536 * i);
78 codec->vtor = &(codec->vtor_tab[128]);
79 codec->vtog = &(codec->vtog_tab[128]);
80 codec->utog = &(codec->utog_tab[128]);
81 codec->utob = &(codec->utob_tab[128]);
82 for(i = -128; i < 128; i++)
84 /* decompression */
85 codec->vtor[i] = (long)( 1.4020 * 65536 * i);
86 codec->vtog[i] = (long)(-0.7141 * 65536 * i);
88 codec->utog[i] = (long)(-0.3441 * 65536 * i);
89 codec->utob[i] = (long)( 1.7720 * 65536 * i);
91 codec->bytes_per_line = vtrack->track->tkhd.track_width * 3;
92 if((float)codec->bytes_per_line / 6 > (int)(codec->bytes_per_line / 6))
93 codec->bytes_per_line += 3;
95 codec->rows = vtrack->track->tkhd.track_height / 2;
96 if((float)vtrack->track->tkhd.track_height / 2 > (int)(vtrack->track->tkhd.track_height / 2))
97 codec->rows++;
99 codec->work_buffer = malloc(codec->bytes_per_line * codec->rows);
100 codec->initialized = 1;
105 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
107 int64_t bytes, in_y, out_y;
108 register int x1, x2;
109 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
110 quicktime_yuv4_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
111 int width = vtrack->track->tkhd.track_width;
112 int height = vtrack->track->tkhd.track_height;
113 unsigned char *buffer;
114 char *input_row;
115 unsigned char *row_pointer1, *row_pointer2;
116 int result = 0;
117 int u, v;
118 register int y1, y2, y3, y4;
119 int r, g, b;
120 int bytes_per_row = width * cmodel_calculate_pixelsize(file->color_model);
121 initialize(vtrack, codec);
123 vtrack->track->tkhd.track_width;
124 quicktime_set_video_position(file, vtrack->current_position, track);
125 bytes = quicktime_frame_size(file, vtrack->current_position, track);
126 switch(file->color_model)
128 case BC_RGB888:
129 buffer = codec->work_buffer;
130 result = quicktime_read_data(file, buffer, bytes);
131 if(result) result = 0; else result = 1;
133 for(out_y = 0, in_y = 0; out_y < height; in_y++)
135 input_row = &buffer[in_y * codec->bytes_per_line];
136 row_pointer1 = row_pointers[out_y++];
138 if(out_y < height)
139 row_pointer2 = row_pointers[out_y];
140 else
141 row_pointer2 = row_pointer1;
143 out_y++;
144 for(x1 = 0, x2 = 0; x1 < bytes_per_row; )
146 u = *input_row++;
147 v = *input_row++;
148 y1 = (unsigned char)*input_row++;
149 y2 = (unsigned char)*input_row++;
150 y3 = (unsigned char)*input_row++;
151 y4 = (unsigned char)*input_row++;
152 y1 <<= 16;
153 y2 <<= 16;
154 y3 <<= 16;
155 y4 <<= 16;
157 /* Top left pixel */
158 r = ((y1 + codec->vtor[v]) >> 16);
159 g = ((y1 + codec->utog[u] + codec->vtog[v]) >> 16);
160 b = ((y1 + codec->utob[u]) >> 16);
161 if(r < 0) r = 0;
162 if(g < 0) g = 0;
163 if(b < 0) b = 0;
164 if(r > 255) r = 255;
165 if(g > 255) g = 255;
166 if(b > 255) b = 255;
168 row_pointer1[x1++] = r;
169 row_pointer1[x1++] = g;
170 row_pointer1[x1++] = b;
172 /* Top right pixel */
173 if(x1 < bytes_per_row)
175 r = ((y2 + codec->vtor[v]) >> 16);
176 g = ((y2 + codec->utog[u] + codec->vtog[v]) >> 16);
177 b = ((y2 + codec->utob[u]) >> 16);
178 if(r < 0) r = 0;
179 if(g < 0) g = 0;
180 if(b < 0) b = 0;
181 if(r > 255) r = 255;
182 if(g > 255) g = 255;
183 if(b > 255) b = 255;
185 row_pointer1[x1++] = r;
186 row_pointer1[x1++] = g;
187 row_pointer1[x1++] = b;
190 /* Bottom left pixel */
191 r = ((y3 + codec->vtor[v]) >> 16);
192 g = ((y3 + codec->utog[u] + codec->vtog[v]) >> 16);
193 b = ((y3 + codec->utob[u]) >> 16);
194 if(r < 0) r = 0;
195 if(g < 0) g = 0;
196 if(b < 0) b = 0;
197 if(r > 255) r = 255;
198 if(g > 255) g = 255;
199 if(b > 255) b = 255;
201 row_pointer2[x2++] = r;
202 row_pointer2[x2++] = g;
203 row_pointer2[x2++] = b;
205 /* Bottom right pixel */
206 if(x2 < bytes_per_row)
208 r = ((y4 + codec->vtor[v]) >> 16);
209 g = ((y4 + codec->utog[u] + codec->vtog[v]) >> 16);
210 b = ((y4 + codec->utob[u]) >> 16);
211 if(r < 0) r = 0;
212 if(g < 0) g = 0;
213 if(b < 0) b = 0;
214 if(r > 255) r = 255;
215 if(g > 255) g = 255;
216 if(b > 255) b = 255;
218 row_pointer2[x2++] = r;
219 row_pointer2[x2++] = g;
220 row_pointer2[x2++] = b;
224 break;
227 return result;
230 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
232 int64_t offset = quicktime_position(file);
233 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
234 quicktime_yuv4_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
235 quicktime_trak_t *trak = vtrack->track;
236 int result = 0;
237 int width = vtrack->track->tkhd.track_width;
238 int height = vtrack->track->tkhd.track_height;
239 int64_t bytes = codec->rows * codec->bytes_per_line;
240 unsigned char *buffer = codec->work_buffer;
241 unsigned char *output_row; /* Pointer to output row */
242 unsigned char *row_pointer1, *row_pointer2; /* Pointers to input rows */
243 register int x1, x2;
244 int in_y, out_y;
245 register int y1, y2, y3, y4;
246 int u, v;
247 int r, g, b;
248 int bytes_per_row = width * 3;
249 int denominator;
250 quicktime_atom_t chunk_atom;
251 initialize(vtrack, codec);
259 for(in_y = 0, out_y = 0; in_y < height; out_y++)
261 output_row = buffer + out_y * codec->bytes_per_line;
262 row_pointer1 = row_pointers[in_y];
263 in_y++;
265 if(in_y < height)
266 row_pointer2 = row_pointers[in_y];
267 else
268 row_pointer2 = row_pointer1;
270 in_y++;
272 for(x1 = 0, x2 = 0; x1 < bytes_per_row; )
274 /* Top left pixel */
275 r = row_pointer1[x1++];
276 g = row_pointer1[x1++];
277 b = row_pointer1[x1++];
279 y1 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
280 u = (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
281 v = (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
283 /* Top right pixel */
284 if(x1 < bytes_per_row)
286 r = row_pointer1[x1++];
287 g = row_pointer1[x1++];
288 b = row_pointer1[x1++];
291 y2 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
292 u += (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
293 v += (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
295 /* Bottom left pixel */
296 r = row_pointer2[x2++];
297 g = row_pointer2[x2++];
298 b = row_pointer2[x2++];
300 y3 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
301 u += (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
302 v += (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
304 /* Bottom right pixel */
305 if(x2 < bytes_per_row)
307 r = row_pointer2[x2++];
308 g = row_pointer2[x2++];
309 b = row_pointer2[x2++];
312 y4 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
313 u += (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
314 v += (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
316 y1 /= 0x10000;
317 y2 /= 0x10000;
318 y3 /= 0x10000;
319 y4 /= 0x10000;
320 u /= 0x40000;
321 v /= 0x40000;
322 if(y1 > 255) y1 = 255;
323 if(y2 > 255) y2 = 255;
324 if(y3 > 255) y3 = 255;
325 if(y4 > 255) y4 = 255;
326 if(u > 127) u = 127;
327 if(v > 127) v = 127;
328 if(y1 < 0) y1 = 0;
329 if(y2 < 0) y2 = 0;
330 if(y3 < 0) y3 = 0;
331 if(y4 < 0) y4 = 0;
332 if(u < -128) u = -128;
333 if(v < -128) v = -128;
335 *output_row++ = u;
336 *output_row++ = v;
337 *output_row++ = y1;
338 *output_row++ = y2;
339 *output_row++ = y3;
340 *output_row++ = y4;
344 quicktime_write_chunk_header(file, trak, &chunk_atom);
345 result = quicktime_write_data(file, buffer, bytes);
346 if(result)
347 result = 0;
348 else
349 result = 1;
350 quicktime_write_chunk_footer(file,
351 trak,
352 vtrack->current_chunk,
353 &chunk_atom,
357 vtrack->current_chunk++;
358 return result;
362 void quicktime_init_codec_yuv4(quicktime_video_map_t *vtrack)
364 int i;
365 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
367 /* Init public items */
368 codec_base->priv = calloc(1, sizeof(quicktime_yuv4_codec_t));
369 codec_base->delete_vcodec = quicktime_delete_codec_yuv4;
370 codec_base->decode_video = decode;
371 codec_base->encode_video = encode;
372 codec_base->decode_audio = 0;
373 codec_base->encode_audio = 0;
374 codec_base->reads_colormodel = reads_colormodel;
375 codec_base->fourcc = QUICKTIME_YUV4;
376 codec_base->title = "YUV 4:2:0 packed";
377 codec_base->desc = "YUV 4:2:0 packed (Not standardized)";