00001 #include "colormodels.h"
00002 #include "funcprotos.h"
00003 #include "quicktime.h"
00004 #include "yuv4.h"
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 typedef struct
00022 {
00023 int use_float;
00024 long rtoy_tab[256], gtoy_tab[256], btoy_tab[256];
00025 long rtou_tab[256], gtou_tab[256], btou_tab[256];
00026 long rtov_tab[256], gtov_tab[256], btov_tab[256];
00027
00028 long vtor_tab[256], vtog_tab[256];
00029 long utog_tab[256], utob_tab[256];
00030 long *vtor, *vtog, *utog, *utob;
00031
00032 unsigned char *work_buffer;
00033
00034
00035 int bytes_per_line;
00036
00037 int rows;
00038 int initialized;
00039 } quicktime_yuv4_codec_t;
00040
00041 static int quicktime_delete_codec_yuv4(quicktime_video_map_t *vtrack)
00042 {
00043 quicktime_yuv4_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00044 free(codec->work_buffer);
00045 free(codec);
00046 return 0;
00047 }
00048
00049 static int reads_colormodel(quicktime_t *file,
00050 int colormodel,
00051 int track)
00052 {
00053 return colormodel == BC_RGB888;
00054 }
00055
00056 static void initialize(quicktime_video_map_t *vtrack, quicktime_yuv4_codec_t *codec)
00057 {
00058 int i;
00059 if(!codec->initialized)
00060 {
00061
00062 for(i = 0; i < 256; i++)
00063 {
00064
00065 codec->rtoy_tab[i] = (long)( 0.2990 * 65536 * i);
00066 codec->rtou_tab[i] = (long)(-0.1687 * 65536 * i);
00067 codec->rtov_tab[i] = (long)( 0.5000 * 65536 * i);
00068
00069 codec->gtoy_tab[i] = (long)( 0.5870 * 65536 * i);
00070 codec->gtou_tab[i] = (long)(-0.3320 * 65536 * i);
00071 codec->gtov_tab[i] = (long)(-0.4187 * 65536 * i);
00072
00073 codec->btoy_tab[i] = (long)( 0.1140 * 65536 * i);
00074 codec->btou_tab[i] = (long)( 0.5000 * 65536 * i);
00075 codec->btov_tab[i] = (long)(-0.0813 * 65536 * i);
00076 }
00077
00078 codec->vtor = &(codec->vtor_tab[128]);
00079 codec->vtog = &(codec->vtog_tab[128]);
00080 codec->utog = &(codec->utog_tab[128]);
00081 codec->utob = &(codec->utob_tab[128]);
00082 for(i = -128; i < 128; i++)
00083 {
00084
00085 codec->vtor[i] = (long)( 1.4020 * 65536 * i);
00086 codec->vtog[i] = (long)(-0.7141 * 65536 * i);
00087
00088 codec->utog[i] = (long)(-0.3441 * 65536 * i);
00089 codec->utob[i] = (long)( 1.7720 * 65536 * i);
00090 }
00091 codec->bytes_per_line = vtrack->track->tkhd.track_width * 3;
00092 if((float)codec->bytes_per_line / 6 > (int)(codec->bytes_per_line / 6))
00093 codec->bytes_per_line += 3;
00094
00095 codec->rows = vtrack->track->tkhd.track_height / 2;
00096 if((float)vtrack->track->tkhd.track_height / 2 > (int)(vtrack->track->tkhd.track_height / 2))
00097 codec->rows++;
00098
00099 codec->work_buffer = malloc(codec->bytes_per_line * codec->rows);
00100 codec->initialized = 1;
00101 }
00102 }
00103
00104
00105 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
00106 {
00107 int64_t bytes, in_y, out_y;
00108 register int x1, x2;
00109 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00110 quicktime_yuv4_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00111 int width = vtrack->track->tkhd.track_width;
00112 int height = vtrack->track->tkhd.track_height;
00113 unsigned char *buffer;
00114 char *input_row;
00115 unsigned char *row_pointer1, *row_pointer2;
00116 int result = 0;
00117 int u, v;
00118 register int y1, y2, y3, y4;
00119 int r, g, b;
00120 int bytes_per_row = width * cmodel_calculate_pixelsize(file->color_model);
00121 initialize(vtrack, codec);
00122
00123 vtrack->track->tkhd.track_width;
00124 quicktime_set_video_position(file, vtrack->current_position, track);
00125 bytes = quicktime_frame_size(file, vtrack->current_position, track);
00126 switch(file->color_model)
00127 {
00128 case BC_RGB888:
00129 buffer = codec->work_buffer;
00130 result = quicktime_read_data(file, buffer, bytes);
00131 if(result) result = 0; else result = 1;
00132
00133 for(out_y = 0, in_y = 0; out_y < height; in_y++)
00134 {
00135 input_row = &buffer[in_y * codec->bytes_per_line];
00136 row_pointer1 = row_pointers[out_y++];
00137
00138 if(out_y < height)
00139 row_pointer2 = row_pointers[out_y];
00140 else
00141 row_pointer2 = row_pointer1;
00142
00143 out_y++;
00144 for(x1 = 0, x2 = 0; x1 < bytes_per_row; )
00145 {
00146 u = *input_row++;
00147 v = *input_row++;
00148 y1 = (unsigned char)*input_row++;
00149 y2 = (unsigned char)*input_row++;
00150 y3 = (unsigned char)*input_row++;
00151 y4 = (unsigned char)*input_row++;
00152 y1 <<= 16;
00153 y2 <<= 16;
00154 y3 <<= 16;
00155 y4 <<= 16;
00156
00157
00158 r = ((y1 + codec->vtor[v]) >> 16);
00159 g = ((y1 + codec->utog[u] + codec->vtog[v]) >> 16);
00160 b = ((y1 + codec->utob[u]) >> 16);
00161 if(r < 0) r = 0;
00162 if(g < 0) g = 0;
00163 if(b < 0) b = 0;
00164 if(r > 255) r = 255;
00165 if(g > 255) g = 255;
00166 if(b > 255) b = 255;
00167
00168 row_pointer1[x1++] = r;
00169 row_pointer1[x1++] = g;
00170 row_pointer1[x1++] = b;
00171
00172
00173 if(x1 < bytes_per_row)
00174 {
00175 r = ((y2 + codec->vtor[v]) >> 16);
00176 g = ((y2 + codec->utog[u] + codec->vtog[v]) >> 16);
00177 b = ((y2 + codec->utob[u]) >> 16);
00178 if(r < 0) r = 0;
00179 if(g < 0) g = 0;
00180 if(b < 0) b = 0;
00181 if(r > 255) r = 255;
00182 if(g > 255) g = 255;
00183 if(b > 255) b = 255;
00184
00185 row_pointer1[x1++] = r;
00186 row_pointer1[x1++] = g;
00187 row_pointer1[x1++] = b;
00188 }
00189
00190
00191 r = ((y3 + codec->vtor[v]) >> 16);
00192 g = ((y3 + codec->utog[u] + codec->vtog[v]) >> 16);
00193 b = ((y3 + codec->utob[u]) >> 16);
00194 if(r < 0) r = 0;
00195 if(g < 0) g = 0;
00196 if(b < 0) b = 0;
00197 if(r > 255) r = 255;
00198 if(g > 255) g = 255;
00199 if(b > 255) b = 255;
00200
00201 row_pointer2[x2++] = r;
00202 row_pointer2[x2++] = g;
00203 row_pointer2[x2++] = b;
00204
00205
00206 if(x2 < bytes_per_row)
00207 {
00208 r = ((y4 + codec->vtor[v]) >> 16);
00209 g = ((y4 + codec->utog[u] + codec->vtog[v]) >> 16);
00210 b = ((y4 + codec->utob[u]) >> 16);
00211 if(r < 0) r = 0;
00212 if(g < 0) g = 0;
00213 if(b < 0) b = 0;
00214 if(r > 255) r = 255;
00215 if(g > 255) g = 255;
00216 if(b > 255) b = 255;
00217
00218 row_pointer2[x2++] = r;
00219 row_pointer2[x2++] = g;
00220 row_pointer2[x2++] = b;
00221 }
00222 }
00223 }
00224 break;
00225 }
00226
00227 return result;
00228 }
00229
00230 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
00231 {
00232 int64_t offset = quicktime_position(file);
00233 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00234 quicktime_yuv4_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00235 quicktime_trak_t *trak = vtrack->track;
00236 int result = 0;
00237 int width = vtrack->track->tkhd.track_width;
00238 int height = vtrack->track->tkhd.track_height;
00239 int64_t bytes = codec->rows * codec->bytes_per_line;
00240 unsigned char *buffer = codec->work_buffer;
00241 unsigned char *output_row;
00242 unsigned char *row_pointer1, *row_pointer2;
00243 register int x1, x2;
00244 int in_y, out_y;
00245 register int y1, y2, y3, y4;
00246 int u, v;
00247 int r, g, b;
00248 int bytes_per_row = width * 3;
00249 int denominator;
00250 quicktime_atom_t chunk_atom;
00251 initialize(vtrack, codec);
00252
00253
00254
00255
00256
00257
00258
00259 for(in_y = 0, out_y = 0; in_y < height; out_y++)
00260 {
00261 output_row = buffer + out_y * codec->bytes_per_line;
00262 row_pointer1 = row_pointers[in_y];
00263 in_y++;
00264
00265 if(in_y < height)
00266 row_pointer2 = row_pointers[in_y];
00267 else
00268 row_pointer2 = row_pointer1;
00269
00270 in_y++;
00271
00272 for(x1 = 0, x2 = 0; x1 < bytes_per_row; )
00273 {
00274
00275 r = row_pointer1[x1++];
00276 g = row_pointer1[x1++];
00277 b = row_pointer1[x1++];
00278
00279 y1 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
00280 u = (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
00281 v = (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
00282
00283
00284 if(x1 < bytes_per_row)
00285 {
00286 r = row_pointer1[x1++];
00287 g = row_pointer1[x1++];
00288 b = row_pointer1[x1++];
00289 }
00290
00291 y2 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
00292 u += (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
00293 v += (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
00294
00295
00296 r = row_pointer2[x2++];
00297 g = row_pointer2[x2++];
00298 b = row_pointer2[x2++];
00299
00300 y3 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
00301 u += (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
00302 v += (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
00303
00304
00305 if(x2 < bytes_per_row)
00306 {
00307 r = row_pointer2[x2++];
00308 g = row_pointer2[x2++];
00309 b = row_pointer2[x2++];
00310 }
00311
00312 y4 = (codec->rtoy_tab[r] + codec->gtoy_tab[g] + codec->btoy_tab[b]);
00313 u += (codec->rtou_tab[r] + codec->gtou_tab[g] + codec->btou_tab[b]);
00314 v += (codec->rtov_tab[r] + codec->gtov_tab[g] + codec->btov_tab[b]);
00315
00316 y1 /= 0x10000;
00317 y2 /= 0x10000;
00318 y3 /= 0x10000;
00319 y4 /= 0x10000;
00320 u /= 0x40000;
00321 v /= 0x40000;
00322 if(y1 > 255) y1 = 255;
00323 if(y2 > 255) y2 = 255;
00324 if(y3 > 255) y3 = 255;
00325 if(y4 > 255) y4 = 255;
00326 if(u > 127) u = 127;
00327 if(v > 127) v = 127;
00328 if(y1 < 0) y1 = 0;
00329 if(y2 < 0) y2 = 0;
00330 if(y3 < 0) y3 = 0;
00331 if(y4 < 0) y4 = 0;
00332 if(u < -128) u = -128;
00333 if(v < -128) v = -128;
00334
00335 *output_row++ = u;
00336 *output_row++ = v;
00337 *output_row++ = y1;
00338 *output_row++ = y2;
00339 *output_row++ = y3;
00340 *output_row++ = y4;
00341 }
00342 }
00343
00344 quicktime_write_chunk_header(file, trak, &chunk_atom);
00345 result = quicktime_write_data(file, buffer, bytes);
00346 if(result)
00347 result = 0;
00348 else
00349 result = 1;
00350 quicktime_write_chunk_footer(file,
00351 trak,
00352 vtrack->current_chunk,
00353 &chunk_atom,
00354 1);
00355
00356
00357 vtrack->current_chunk++;
00358 return result;
00359 }
00360
00361
00362 void quicktime_init_codec_yuv4(quicktime_video_map_t *vtrack)
00363 {
00364 int i;
00365 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
00366
00367
00368 codec_base->priv = calloc(1, sizeof(quicktime_yuv4_codec_t));
00369 codec_base->delete_vcodec = quicktime_delete_codec_yuv4;
00370 codec_base->decode_video = decode;
00371 codec_base->encode_video = encode;
00372 codec_base->decode_audio = 0;
00373 codec_base->encode_audio = 0;
00374 codec_base->reads_colormodel = reads_colormodel;
00375 codec_base->fourcc = QUICKTIME_YUV4;
00376 codec_base->title = "YUV 4:2:0 packed";
00377 codec_base->desc = "YUV 4:2:0 packed (Not standardized)";
00378 }
00379
00380