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
23 long rtoy_tab
[256], gtoy_tab
[256], btoy_tab
[256];
24 long rtou_tab
[256], gtou_tab
[256], btou_tab
[256];
25 long rtov_tab
[256], gtov_tab
[256], btov_tab
[256];
27 long vtor_tab
[256], vtog_tab
[256];
28 long utog_tab
[256], utob_tab
[256];
29 long *vtor
, *vtog
, *utog
, *utob
;
31 unsigned char *work_buffer
;
34 /* The YUV2 codec requires a bytes per line that is a multiple of 4 */
37 } quicktime_yuv2_codec_t
;
39 static int quicktime_delete_codec_yuv2(quicktime_video_map_t
*vtrack
)
41 quicktime_yuv2_codec_t
*codec
;
43 codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
44 if(codec
->work_buffer
) free(codec
->work_buffer
);
49 static int quicktime_reads_colormodel_yuv2(quicktime_t
*file
,
53 return (colormodel
== BC_RGB888
||
54 colormodel
== BC_YUV888
||
55 colormodel
== BC_YUV422P
);
58 static void encode_sign_change(quicktime_yuv2_codec_t
*codec
, unsigned char **row_pointers
)
61 for(y
= 0; y
< codec
->coded_h
; y
++)
63 unsigned char *out_row
= codec
->work_buffer
+ y
* codec
->bytes_per_line
;
64 unsigned char *in_row
= row_pointers
[y
];
65 for(x
= 0; x
< codec
->bytes_per_line
; )
67 *out_row
++ = *in_row
++;
68 *out_row
++ = (int)(*in_row
++) - 128;
69 *out_row
++ = *in_row
++;
70 *out_row
++ = (int)(*in_row
++) - 128;
76 static void decode_sign_change(quicktime_yuv2_codec_t
*codec
, unsigned char **row_pointers
)
79 for(y
= 0; y
< codec
->coded_h
; y
++)
81 unsigned char *in_row
= row_pointers
[y
];
82 for(x
= 0; x
< codec
->bytes_per_line
; )
92 static void initialize(quicktime_video_map_t
*vtrack
, quicktime_yuv2_codec_t
*codec
)
95 if(!codec
->initialized
)
97 /* Init private items */
98 for(i
= 0; i
< 256; i
++)
101 codec
->rtoy_tab
[i
] = (long)( 0.2990 * 65536 * i
);
102 codec
->rtou_tab
[i
] = (long)(-0.1687 * 65536 * i
);
103 codec
->rtov_tab
[i
] = (long)( 0.5000 * 65536 * i
);
105 codec
->gtoy_tab
[i
] = (long)( 0.5870 * 65536 * i
);
106 codec
->gtou_tab
[i
] = (long)(-0.3320 * 65536 * i
);
107 codec
->gtov_tab
[i
] = (long)(-0.4187 * 65536 * i
);
109 codec
->btoy_tab
[i
] = (long)( 0.1140 * 65536 * i
);
110 codec
->btou_tab
[i
] = (long)( 0.5000 * 65536 * i
);
111 codec
->btov_tab
[i
] = (long)(-0.0813 * 65536 * i
);
114 codec
->vtor
= &(codec
->vtor_tab
[128]);
115 codec
->vtog
= &(codec
->vtog_tab
[128]);
116 codec
->utog
= &(codec
->utog_tab
[128]);
117 codec
->utob
= &(codec
->utob_tab
[128]);
119 for(i
= -128; i
< 128; i
++)
122 codec
->vtor
[i
] = (long)( 1.4020 * 65536 * i
);
123 codec
->vtog
[i
] = (long)(-0.7141 * 65536 * i
);
125 codec
->utog
[i
] = (long)(-0.3441 * 65536 * i
);
126 codec
->utob
[i
] = (long)( 1.7720 * 65536 * i
);
129 codec
->coded_w
= (int)((float)vtrack
->track
->tkhd
.track_width
/ 4 + 0.5) * 4;
130 codec
->coded_h
= (int)((float)vtrack
->track
->tkhd
.track_height
/ 4 + 0.5) * 4;
132 codec
->bytes_per_line
= codec
->coded_w
* 2;
133 codec
->work_buffer
= malloc(codec
->bytes_per_line
*
135 codec
->initialized
= 1;
139 static int decode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
142 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
143 quicktime_yuv2_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
144 int width
= vtrack
->track
->tkhd
.track_width
;
145 int height
= vtrack
->track
->tkhd
.track_height
;
146 unsigned char *buffer
;
148 unsigned char *output_row
, *y_plane
, *u_plane
, *v_plane
;
150 int y1
, u
, v
, y2
, r
, g
, b
;
151 int bytes_per_row
= width
* cmodel_calculate_pixelsize(file
->color_model
);
152 initialize(vtrack
, codec
);
154 vtrack
->track
->tkhd
.track_width
;
155 quicktime_set_video_position(file
, vtrack
->current_position
, track
);
156 bytes
= quicktime_frame_size(file
, vtrack
->current_position
, track
);
158 if(file
->color_model
== BC_YUV422
&&
161 file
->in_w
== width
&&
162 file
->in_h
== height
&&
163 file
->out_w
== width
&&
164 file
->out_h
== height
)
166 result
= !quicktime_read_data(file
, row_pointers
[0], bytes
);
167 decode_sign_change(codec
, row_pointers
);
171 unsigned char *input_rows
[height
];
172 result
= !quicktime_read_data(file
, codec
->work_buffer
, bytes
);
173 for(y
= 0; y
< height
; y
++)
174 input_rows
[y
] = &codec
->work_buffer
[y
* codec
->bytes_per_line
];
175 decode_sign_change(codec
, input_rows
);
177 cmodel_transfer(row_pointers
,
205 static int encode(quicktime_t
*file
, unsigned char **row_pointers
, int track
)
207 int64_t offset
= quicktime_position(file
);
208 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
209 quicktime_trak_t
*trak
= vtrack
->track
;
210 quicktime_yuv2_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
212 int width
= vtrack
->track
->tkhd
.track_width
;
213 int height
= vtrack
->track
->tkhd
.track_height
;
215 unsigned char *buffer
;
219 int bytes_per_row
= width
* 3;
220 quicktime_atom_t chunk_atom
;
222 initialize(vtrack
, codec
);
224 bytes
= height
* codec
->bytes_per_line
;
225 buffer
= codec
->work_buffer
;
226 if(file
->color_model
== BC_YUV422
)
228 encode_sign_change(codec
, row_pointers
);
229 quicktime_write_chunk_header(file
, trak
, &chunk_atom
);
230 result
= !quicktime_write_data(file
, buffer
, bytes
);
234 unsigned char **temp_rows
= malloc(sizeof(unsigned char*) * height
);
235 for(i
= 0; i
< height
; i
++)
236 temp_rows
[i
] = buffer
+ i
* codec
->bytes_per_line
;
238 cmodel_transfer(temp_rows
,
259 encode_sign_change(codec
, temp_rows
);
260 quicktime_write_chunk_header(file
, trak
, &chunk_atom
);
261 result
= !quicktime_write_data(file
, buffer
, bytes
);
265 quicktime_write_chunk_footer(file
,
267 vtrack
->current_chunk
,
271 vtrack
->current_chunk
++;
275 static int reads_colormodel(quicktime_t
*file
,
279 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
280 quicktime_yuv2_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
282 return (colormodel
== BC_RGB888
||
283 colormodel
== BC_YUV888
||
284 colormodel
== BC_YUV422P
||
285 colormodel
== BC_YUV422
);
288 static int writes_colormodel(quicktime_t
*file
,
292 quicktime_video_map_t
*vtrack
= &(file
->vtracks
[track
]);
293 quicktime_yuv2_codec_t
*codec
= ((quicktime_codec_t
*)vtrack
->codec
)->priv
;
295 return (colormodel
== BC_RGB888
||
296 colormodel
== BC_YUV888
||
297 colormodel
== BC_YUV422P
||
298 colormodel
== BC_YUV422
);
301 void quicktime_init_codec_yuv2(quicktime_video_map_t
*vtrack
)
303 quicktime_codec_t
*codec_base
= (quicktime_codec_t
*)vtrack
->codec
;
305 /* Init public items */
306 codec_base
->priv
= calloc(1, sizeof(quicktime_yuv2_codec_t
));
307 codec_base
->delete_vcodec
= quicktime_delete_codec_yuv2
;
308 codec_base
->decode_video
= decode
;
309 codec_base
->encode_video
= encode
;
310 codec_base
->decode_audio
= 0;
311 codec_base
->encode_audio
= 0;
312 codec_base
->reads_colormodel
= reads_colormodel
;
313 codec_base
->writes_colormodel
= writes_colormodel
;
314 codec_base
->fourcc
= QUICKTIME_YUV2
;
315 codec_base
->title
= "Component Video";
316 codec_base
->desc
= "YUV 4:2:2";