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
22 unsigned char *work_buffer
;
25 /* The YUV2 codec requires a bytes per line that is a multiple of 4 */
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
);
44 static int quicktime_reads_colormodel_yuv2(quicktime_t
*file
,
48 return (colormodel
== BC_RGB888
||
49 colormodel
== BC_YUV888
||
50 colormodel
== BC_YUV422P
);
54 static void convert_encode_yuv2(quicktime_yuv2_codec_t
*codec
, unsigned char **row_pointers
)
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;
72 static void convert_decode_yuv2(quicktime_yuv2_codec_t
*codec
, unsigned char **row_pointers
)
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
; )
88 static void convert_encode_2vuy(quicktime_yuv2_codec_t
*codec
, unsigned char **row_pointers
)
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 */
108 static void convert_decode_2vuy(quicktime_yuv2_codec_t
*codec
, unsigned char **row_pointers
)
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
; )
118 in_row
[0] = in_row
[1];
122 in_row
[2] = in_row
[3];
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
*
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
)
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
);
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
&&
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
);
170 convert_decode_2vuy(codec
, row_pointers
);
172 convert_decode_yuv2(codec
, row_pointers
);
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
];
182 convert_decode_2vuy(codec
, codec
->rows
);
184 convert_decode_yuv2(codec
, codec
->rows
);
186 cmodel_transfer(row_pointers
,
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
;
220 int width
= vtrack
->track
->tkhd
.track_width
;
221 int height
= vtrack
->track
->tkhd
.track_height
;
223 unsigned char *buffer
;
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
)
234 convert_encode_2vuy(codec
, row_pointers
);
236 convert_encode_yuv2(codec
, row_pointers
);
237 quicktime_write_chunk_header(file
, trak
, &chunk_atom
);
238 result
= !quicktime_write_data(file
, buffer
, bytes
);
242 for(i
= 0; i
< height
; i
++)
243 codec
->rows
[i
] = buffer
+ i
* codec
->bytes_per_line
;
245 cmodel_transfer(codec
->rows
,
267 convert_encode_2vuy(codec
, codec
->rows
);
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
,
277 vtrack
->current_chunk
,
281 vtrack
->current_chunk
++;
285 static int reads_colormodel(quicktime_t
*file
,
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
,
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
);