1 #include "colormodels.h"
2 #include "funcprotos.h"
6 /* U V values are signed but Y R G B values are unsigned! */
9 * G = Y - 0.34414 * U - 0.71414 * V
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 */
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 */
36 /* Actual rows encoded in the yuv4 format */
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
);
49 static int reads_colormodel(quicktime_t
*file
,
53 return colormodel
== BC_RGB888
;
56 static void initialize(quicktime_video_map_t
*vtrack
, quicktime_yuv4_codec_t
*codec
)
59 if(!codec
->initialized
)
61 /* Init private items */
62 for(i
= 0; i
< 256; i
++)
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
++)
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))
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
;
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
;
115 unsigned char *row_pointer1
, *row_pointer2
;
118 register int y1
, y2
, y3
, y4
;
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
)
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
++];
139 row_pointer2
= row_pointers
[out_y
];
141 row_pointer2
= row_pointer1
;
144 for(x1
= 0, x2
= 0; x1
< bytes_per_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
++;
158 r
= ((y1
+ codec
->vtor
[v
]) >> 16);
159 g
= ((y1
+ codec
->utog
[u
] + codec
->vtog
[v
]) >> 16);
160 b
= ((y1
+ codec
->utob
[u
]) >> 16);
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);
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);
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);
218 row_pointer2
[x2
++] = r
;
219 row_pointer2
[x2
++] = g
;
220 row_pointer2
[x2
++] = b
;
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
;
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 */
245 register int y1
, y2
, y3
, y4
;
248 int bytes_per_row
= width
* 3;
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
];
266 row_pointer2
= row_pointers
[in_y
];
268 row_pointer2
= row_pointer1
;
272 for(x1
= 0, x2
= 0; x1
< bytes_per_row
; )
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
]);
322 if(y1
> 255) y1
= 255;
323 if(y2
> 255) y2
= 255;
324 if(y3
> 255) y3
= 255;
325 if(y4
> 255) y4
= 255;
332 if(u
< -128) u
= -128;
333 if(v
< -128) v
= -128;
344 quicktime_write_chunk_header(file
, trak
, &chunk_atom
);
345 result
= quicktime_write_data(file
, buffer
, bytes
);
350 quicktime_write_chunk_footer(file
,
352 vtrack
->current_chunk
,
357 vtrack
->current_chunk
++;
362 void quicktime_init_codec_yuv4(quicktime_video_map_t
*vtrack
)
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)";