home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek 6
/
Geek-006.iso
/
linux
/
video
/
xmovie-1.5.3.tar.gz
/
xmovie-1.5.3.tar
/
xmovie-1.5.3
/
quicktime
/
yuv2.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-11-29
|
9KB
|
334 lines
#include "colormodels.h"
#include "yuv2.h"
/* U V values are signed but Y R G B values are unsigned! */
/*
* R = Y + 1.40200 * V
* G = Y - 0.34414 * U - 0.71414 * V
* B = Y + 1.77200 * U
*/
/*
* Y = 0.2990 * R + 0.5870 * G + 0.1140 * B
* U = -0.1687 * R - 0.3310 * G + 0.5000 * B
* V = 0.5000 * R - 0.4187 * G - 0.0813 * B
*/
static int quicktime_delete_codec_yuv2(quicktime_video_map_t *vtrack)
{
quicktime_yuv2_codec_t *codec;
codec = ((quicktime_codec_t*)vtrack->codec)->priv;
free(codec->work_buffer);
free(codec);
return 0;
}
static int quicktime_reads_colormodel_yuv2(quicktime_t *file,
int colormodel,
int track)
{
return (colormodel == BC_RGB888 ||
colormodel == BC_YUV888 ||
colormodel == BC_YUV422P);
}
static int quicktime_decode_yuv2(quicktime_t *file, unsigned char **row_pointers, int track)
{
long bytes, x, y;
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
int width = vtrack->track->tkhd.track_width;
int height = vtrack->track->tkhd.track_height;
unsigned char *buffer;
char *input_row;
unsigned char *output_row, *y_plane, *u_plane, *v_plane;
int result = 0;
int y1, u, v, y2, r, g, b;
int bytes_per_row = width * cmodel_calculate_pixelsize(file->color_model);
vtrack->track->tkhd.track_width;
quicktime_set_video_position(file, vtrack->current_position, track);
bytes = quicktime_frame_size(file, vtrack->current_position, track);
switch(file->color_model)
{
case BC_RGB888:
buffer = codec->work_buffer;
result = !quicktime_read_data(file, buffer, bytes);
for(y = 0; y < height; y++)
{
input_row = &buffer[y * codec->bytes_per_line];
for(x = 0; x < bytes_per_row; )
{
y1 = (unsigned char)*input_row++;
u = *input_row++;
y2 = (unsigned char)*input_row++;
v = *input_row++;
y1 <<= 16;
y2 <<= 16;
r = ((y1 + codec->vtor[v]) >> 16);
g = ((y1 + codec->utog[u] + codec->vtog[v]) >> 16);
b = ((y1 + codec->utob[u]) >> 16);
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
row_pointers[y][x++] = r;
row_pointers[y][x++] = g;
row_pointers[y][x++] = b;
/* Odd numbers of columns quit here */
if(x < bytes_per_row)
{
r = ((y2 + codec->vtor[v]) >> 16);
g = ((y2 + codec->utog[u] + codec->vtog[v]) >> 16);
b = ((y2 + codec->utob[u]) >> 16);
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
row_pointers[y][x++] = r;
row_pointers[y][x++] = g;
row_pointers[y][x++] = b;
}
}
}
break;
case BC_YUV888:
buffer = codec->work_buffer;
result = !quicktime_read_data(file, buffer, bytes);
for(y = 0; y < height; y++)
{
input_row = &buffer[y * codec->bytes_per_line];
output_row = row_pointers[y];
for(x = 0; x < bytes_per_row; )
{
output_row[x++] = *input_row++;
output_row[x++] = u = *input_row++ + 128;
y2 = *input_row++;
output_row[x++] = v = *input_row++ + 128;
if(x < bytes_per_row)
{
output_row[x++] = y2;
output_row[x++] = u;
output_row[x++] = v;
}
}
}
break;
case BC_YUV422P:
for(y = 0; y < height; y++)
{
input_row = &buffer[y * codec->bytes_per_line];
y_plane = row_pointers[0] + y * bytes_per_row;
u_plane = row_pointers[1] + y * bytes_per_row;
v_plane = row_pointers[2] + y * bytes_per_row;
for(x = 0; x < width; )
{
y_plane[x++] = *input_row++;
*u_plane++ = *input_row++ + 128;
if(x < bytes_per_row) y_plane[x++] = *input_row++;
*v_plane++ = *input_row++ + 128;
}
}
break;
}
return result;
}
static int quicktime_encode_yuv2(quicktime_t *file, unsigned char **row_pointers, int track)
{
long offset = quicktime_position(file);
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
int result = 0;
int width = vtrack->track->tkhd.track_width;
int height = vtrack->track->tkhd.track_height;
long bytes = height * codec->bytes_per_line;
unsigned char *buffer = codec->work_buffer;
int x, y;
int y1, u, y2, v;
int r, g, b;
int bytes_per_row = width * 3;
switch(file->color_model)
{
case BC_RGB888:
for(y = 0; y < height; y++)
{
unsigned char *row_pointer = buffer + y * codec->bytes_per_line;
for(x = 0; x < bytes_per_row; )
{
r = row_pointers[y][x++];
g = row_pointers[y][x++];
b = row_pointers[y][x++];
y1 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
u = (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
v = (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
if(x < bytes_per_row)
{
r = row_pointers[y][x++];
g = row_pointers[y][x++];
b = row_pointers[y][x++];
}
y2 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
u += (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
v += (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
y1 /= 0x10000;
y2 /= 0x10000;
u /= 0x20000;
v /= 0x20000;
if(y1 > 255) y1 = 255;
if(y2 > 255) y2 = 255;
if(u > 127) u = 127;
if(v > 127) v = 127;
if(y1 < 0) y1 = 0;
if(y2 < 0) y2 = 0;
if(u < -128) u = -128;
if(v < -128) v = -128;
*row_pointer++ = y1;
*row_pointer++ = u;
*row_pointer++ = y2;
*row_pointer++ = v;
}
}
result = quicktime_write_data(file, buffer, bytes);
break;
case BC_YUV422:
// Change signs
for(y = 0; y < height; y++)
{
unsigned char *out_row = buffer + y * codec->bytes_per_line;
unsigned char *in_row = row_pointers[y];
for(x = 0; x < bytes_per_row; )
{
*out_row++ = *in_row++;
*out_row++ = (int)(*in_row++) - 128;
*out_row++ = *in_row++;
*out_row++ = (int)(*in_row++) - 128;
x += 4;
}
}
result = quicktime_write_data(file, buffer, bytes);
break;
}
if(result) result = 0; else result = 1;
quicktime_update_tables(file,
file->vtracks[track].track,
offset,
file->vtracks[track].current_chunk,
file->vtracks[track].current_position,
1,
bytes);
file->vtracks[track].current_chunk++;
return result;
}
static int reads_colormodel(quicktime_t *file,
int colormodel,
int track)
{
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
return (colormodel == BC_RGB888 ||
colormodel == BC_YUV888 ||
colormodel == BC_YUV422P ||
colormodel == BC_YUV422);
}
static int writes_colormodel(quicktime_t *file,
int colormodel,
int track)
{
quicktime_video_map_t *vtrack = &(file->vtracks[track]);
quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
return (colormodel == BC_RGB888 ||
colormodel == BC_YUV888 ||
colormodel == BC_YUV422P ||
colormodel == BC_YUV422);
}
void quicktime_init_codec_yuv2(quicktime_video_map_t *vtrack)
{
int i;
quicktime_yuv2_codec_t *codec;
/* Init public items */
((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_yuv2_codec_t));
((quicktime_codec_t*)vtrack->codec)->delete_vcodec = quicktime_delete_codec_yuv2;
((quicktime_codec_t*)vtrack->codec)->decode_video = quicktime_decode_yuv2;
((quicktime_codec_t*)vtrack->codec)->encode_video = quicktime_encode_yuv2;
((quicktime_codec_t*)vtrack->codec)->decode_audio = 0;
((quicktime_codec_t*)vtrack->codec)->encode_audio = 0;
((quicktime_codec_t*)vtrack->codec)->reads_colormodel = reads_colormodel;
((quicktime_codec_t*)vtrack->codec)->writes_colormodel = writes_colormodel;
/* Init private items */
codec = ((quicktime_codec_t*)vtrack->codec)->priv;
for(i = 0; i < 256; i++)
{
/* compression */
codec->rtoy_tab[i] = (long)( 0.2990 * 65536 * i);
codec->rtou_tab[i] = (long)(-0.1687 * 65536 * i);
codec->rtov_tab[i] = (long)( 0.5000 * 65536 * i);
codec->gtoy_tab[i] = (long)( 0.5870 * 65536 * i);
codec->gtou_tab[i] = (long)(-0.3320 * 65536 * i);
codec->gtov_tab[i] = (long)(-0.4187 * 65536 * i);
codec->btoy_tab[i] = (long)( 0.1140 * 65536 * i);
codec->btou_tab[i] = (long)( 0.5000 * 65536 * i);
codec->btov_tab[i] = (long)(-0.0813 * 65536 * i);
}
codec->vtor = &(codec->vtor_tab[128]);
codec->vtog = &(codec->vtog_tab[128]);
codec->utog = &(codec->utog_tab[128]);
codec->utob = &(codec->utob_tab[128]);
for(i = -128; i < 128; i++)
{
/* decompression */
codec->vtor[i] = (long)( 1.4020 * 65536 * i);
codec->vtog[i] = (long)(-0.7141 * 65536 * i);
codec->utog[i] = (long)(-0.3441 * 65536 * i);
codec->utob[i] = (long)( 1.7720 * 65536 * i);
}
codec->bytes_per_line = vtrack->track->tkhd.track_width * 2;
if((float)codec->bytes_per_line / 4 > (int)(codec->bytes_per_line / 4))
codec->bytes_per_line += 2;
codec->work_buffer = malloc(codec->bytes_per_line *
vtrack->track->tkhd.track_height);
}