Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / quicktime / yuv2.c
blob7c5a794a201f89443d9a425b6ab4f41b9615b99b
1 #include "colormodels.h"
2 #include "funcprotos.h"
3 #include "quicktime.h"
4 #include "yuv2.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 typedef struct
22 unsigned char *work_buffer;
23 int coded_w, coded_h;
25 /* The YUV2 codec requires a bytes per line that is a multiple of 4 */
26 int bytes_per_line;
27 int initialized;
29 int is_2vuy;
30 uint8_t ** rows;
31 } quicktime_yuv2_codec_t;
33 static int quicktime_delete_codec_yuv2(quicktime_video_map_t *vtrack)
35 quicktime_yuv2_codec_t *codec;
37 codec = ((quicktime_codec_t*)vtrack->codec)->priv;
38 if(codec->work_buffer) free(codec->work_buffer);
39 if(codec->rows) free(codec->rows);
40 free(codec);
41 return 0;
43 #if 0
44 static int quicktime_reads_colormodel_yuv2(quicktime_t *file,
45 int colormodel,
46 int track)
48 return (colormodel == BC_RGB888 ||
49 colormodel == BC_YUV888 ||
50 colormodel == BC_YUV422P);
52 #endif
54 static void convert_encode_yuv2(quicktime_yuv2_codec_t *codec, unsigned char **row_pointers)
56 int y, x;
57 for(y = 0; y < codec->coded_h; y++)
59 unsigned char *out_row = codec->work_buffer + y * codec->bytes_per_line;
60 unsigned char *in_row = row_pointers[y];
61 for(x = 0; x < codec->bytes_per_line; )
63 *out_row++ = *in_row++;
64 *out_row++ = (int)(*in_row++) - 128;
65 *out_row++ = *in_row++;
66 *out_row++ = (int)(*in_row++) - 128;
67 x += 4;
72 static void convert_decode_yuv2(quicktime_yuv2_codec_t *codec, unsigned char **row_pointers)
74 int y, x;
75 for(y = 0; y < codec->coded_h; y++)
77 unsigned char *in_row = row_pointers[y];
78 for(x = 0; x < codec->bytes_per_line; )
80 in_row[1] += 128;
81 in_row[3] += 128;
82 x += 4;
83 in_row += 4;
88 static void convert_encode_2vuy(quicktime_yuv2_codec_t *codec, unsigned char **row_pointers)
90 int y, x;
91 for(y = 0; y < codec->coded_h; y++)
93 unsigned char *out_row = codec->work_buffer + y * codec->bytes_per_line;
94 unsigned char *in_row = row_pointers[y];
95 for(x = 0; x < codec->bytes_per_line; )
97 out_row[0] = in_row[1]; /* Y */
98 out_row[1] = in_row[0]; /* U */
99 out_row[2] = in_row[3]; /* Y */
100 out_row[3] = in_row[2]; /* V */
101 x += 4;
102 out_row += 4;
103 in_row += 4;
108 static void convert_decode_2vuy(quicktime_yuv2_codec_t *codec, unsigned char **row_pointers)
110 uint8_t swap;
111 int y, x;
112 for(y = 0; y < codec->coded_h; y++)
114 unsigned char *in_row = row_pointers[y];
115 for(x = 0; x < codec->bytes_per_line; )
117 swap = in_row[0];
118 in_row[0] = in_row[1];
119 in_row[1] = swap;
121 swap = in_row[2];
122 in_row[2] = in_row[3];
123 in_row[3] = swap;
125 x += 4;
126 in_row += 4;
132 static void initialize(quicktime_video_map_t *vtrack, quicktime_yuv2_codec_t *codec,
133 int width, int height)
135 if(!codec->initialized)
137 /* Init private items */
138 codec->coded_w = (int)((float)width / 4 + 0.5) * 4;
139 // codec->coded_h = (int)((float)vtrack->track->tkhd.track_height / 4 + 0.5) * 4;
140 codec->coded_h = height;
141 codec->bytes_per_line = codec->coded_w * 2;
142 codec->work_buffer = malloc(codec->bytes_per_line *
143 codec->coded_h);
144 codec->initialized = 1;
145 codec->rows = malloc(height * sizeof(*(codec->rows)));
149 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
151 int64_t bytes, y;
152 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
153 quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
154 int width = quicktime_video_width(file, track);
155 int height = quicktime_video_height(file, track);
156 int result = 0;
157 initialize(vtrack, codec, width, height);
158 quicktime_set_video_position(file, vtrack->current_position, track);
159 bytes = quicktime_frame_size(file, vtrack->current_position, track);
160 if(file->color_model == BC_YUV422 &&
161 file->in_x == 0 &&
162 file->in_y == 0 &&
163 file->in_w == width &&
164 file->in_h == height &&
165 file->out_w == width &&
166 file->out_h == height)
168 result = !quicktime_read_data(file, row_pointers[0], bytes);
169 if(codec->is_2vuy)
170 convert_decode_2vuy(codec, row_pointers);
171 else
172 convert_decode_yuv2(codec, row_pointers);
174 else
176 if(!codec->rows)
177 codec->rows = malloc(height * sizeof(*(codec->rows)));
178 result = !quicktime_read_data(file, codec->work_buffer, bytes);
179 for(y = 0; y < height; y++)
180 codec->rows[y] = &codec->work_buffer[y * codec->bytes_per_line];
181 if(codec->is_2vuy)
182 convert_decode_2vuy(codec, codec->rows);
183 else
184 convert_decode_yuv2(codec, codec->rows);
186 cmodel_transfer(row_pointers,
187 codec->rows,
188 row_pointers[0],
189 row_pointers[1],
190 row_pointers[2],
194 file->in_x,
195 file->in_y,
196 file->in_w,
197 file->in_h,
200 file->out_w,
201 file->out_h,
202 BC_YUV422,
203 file->color_model,
205 codec->coded_w,
206 file->out_w);
211 return result;
214 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
216 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
217 quicktime_trak_t *trak = vtrack->track;
218 quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
219 int result = 1;
220 int width = vtrack->track->tkhd.track_width;
221 int height = vtrack->track->tkhd.track_height;
222 int64_t bytes;
223 unsigned char *buffer;
224 int i;
225 quicktime_atom_t chunk_atom;
227 initialize(vtrack, codec, width, height);
229 bytes = height * codec->bytes_per_line;
230 buffer = codec->work_buffer;
231 if(file->color_model == BC_YUV422)
233 if(codec->is_2vuy)
234 convert_encode_2vuy(codec, row_pointers);
235 else
236 convert_encode_yuv2(codec, row_pointers);
237 quicktime_write_chunk_header(file, trak, &chunk_atom);
238 result = !quicktime_write_data(file, buffer, bytes);
240 else
242 for(i = 0; i < height; i++)
243 codec->rows[i] = buffer + i * codec->bytes_per_line;
245 cmodel_transfer(codec->rows,
246 row_pointers,
250 row_pointers[0],
251 row_pointers[1],
252 row_pointers[2],
255 width,
256 height,
259 width,
260 height,
261 file->color_model,
262 BC_YUV422,
264 width,
265 codec->coded_w);
266 if(codec->is_2vuy)
267 convert_encode_2vuy(codec, codec->rows);
268 else
269 convert_encode_yuv2(codec, codec->rows);
271 quicktime_write_chunk_header(file, trak, &chunk_atom);
272 result = !quicktime_write_data(file, buffer, bytes);
275 quicktime_write_chunk_footer(file,
276 trak,
277 vtrack->current_chunk,
278 &chunk_atom,
281 vtrack->current_chunk++;
282 return result;
285 static int reads_colormodel(quicktime_t *file,
286 int colormodel,
287 int track)
290 return (colormodel == BC_RGB888 ||
291 colormodel == BC_YUV888 ||
292 colormodel == BC_YUV422P ||
293 colormodel == BC_YUV422);
296 static int writes_colormodel(quicktime_t *file,
297 int colormodel,
298 int track)
301 return (colormodel == BC_RGB888 ||
302 colormodel == BC_YUV888 ||
303 colormodel == BC_YUV422P ||
304 colormodel == BC_YUV422);
307 void quicktime_init_codec_yuv2(quicktime_video_map_t *vtrack)
309 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
311 /* Init public items */
312 codec_base->priv = calloc(1, sizeof(quicktime_yuv2_codec_t));
313 codec_base->delete_vcodec = quicktime_delete_codec_yuv2;
314 codec_base->decode_video = decode;
315 codec_base->encode_video = encode;
316 codec_base->decode_audio = 0;
317 codec_base->encode_audio = 0;
318 codec_base->reads_colormodel = reads_colormodel;
319 codec_base->writes_colormodel = writes_colormodel;
320 codec_base->fourcc = QUICKTIME_YUV2;
321 codec_base->title = "Component Y'CbCr 8-bit 4:2:2 (yuv2)";
322 codec_base->desc = "YUV 4:2:2";
325 void quicktime_init_codec_2vuy(quicktime_video_map_t *vtrack)
327 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
328 quicktime_yuv2_codec_t * codec;
329 /* Init public items */
330 codec_base->priv = calloc(1, sizeof(quicktime_yuv2_codec_t));
331 codec_base->delete_vcodec = quicktime_delete_codec_yuv2;
332 codec_base->decode_video = decode;
333 codec_base->encode_video = encode;
334 codec_base->decode_audio = 0;
335 codec_base->encode_audio = 0;
336 codec_base->reads_colormodel = reads_colormodel;
337 codec_base->writes_colormodel = writes_colormodel;
338 codec_base->fourcc = "2vuy";
339 codec_base->title = "Component Y'CbCr 8-bit 4:2:2 (2vuy)";
340 codec_base->desc = "YUV 4:2:2";
341 codec = (quicktime_yuv2_codec_t *)(codec_base->priv);
342 codec->is_2vuy = 1;