00001 #include "quicktime.h"
00002 #include "jpeglib.h"
00003
00004 #define ABS(x) ((x) < 0 ? -(x) : (x))
00005
00006 int quicktime_init_codec_wmx1(quicktime_video_map_t *vtrack)
00007 {
00008 int i;
00009 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
00010
00011 quicktime_init_yuv(&(codec->yuv_tables));
00012 codec->bytes_per_line = vtrack->track->tkhd.track_width * 3;
00013 if((float)codec->bytes_per_line / 6 > (int)(codec->bytes_per_line / 6))
00014 codec->bytes_per_line += 3;
00015
00016 codec->rows = vtrack->track->tkhd.track_height / 2;
00017 if((float)vtrack->track->tkhd.track_height / 2 > (int)(vtrack->track->tkhd.track_height / 2))
00018 codec->rows++;
00019
00020 for(i = 0; i < WMX_CHUNK_FRAMES; i++)
00021 codec->frame_cache[i] = 0;
00022
00023 codec->key_frame = 0;
00024 codec->keyframe_position = 0;
00025 codec->quality = 100;
00026 codec->use_float = 0;
00027 codec->frames_per_chunk = 0;
00028 codec->threshold = 5;
00029 return 0;
00030 }
00031
00032 int quicktime_delete_codec_wmx1(quicktime_video_map_t *vtrack)
00033 {
00034 int i;
00035 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
00036
00037 quicktime_delete_yuv(&(codec->yuv_tables));
00038 for(i = 0; i < WMX_CHUNK_FRAMES; i++)
00039 if(codec->frame_cache[i]) free(codec->frame_cache[i]);
00040
00041 if(codec->key_frame) free(codec->key_frame);
00042 return 0;
00043 }
00044
00045 int wmx1_write_cache(quicktime_t *file, int track)
00046 {
00047 long offset = quicktime_position(file);
00048 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00049 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
00050 int width = codec->bytes_per_line;
00051 int height = codec->rows;
00052 int result = 0;
00053 int frame, channel, i, j, k;
00054 long bytes_per_row = codec->bytes_per_line;
00055 int step = codec->frames_per_chunk * bytes_per_row;
00056 long bytes = height * bytes_per_row * codec->frames_per_chunk;
00057 long output_bytes;
00058 unsigned char *input_row, *input_end, *output_row, *input_frame, *output_frame;
00059
00060
00061 if(!codec->key_frame)
00062 {
00063 codec->key_frame = malloc(bytes);
00064 if(!codec->key_frame) result = 1;
00065 }
00066
00067
00068
00069 for(frame = 0; frame < codec->frames_per_chunk; frame++)
00070 {
00071 input_frame = codec->frame_cache[frame];
00072 output_frame = codec->key_frame + frame * bytes_per_row;
00073 input_row = input_frame;
00074 output_row = output_frame;
00075
00076 for(i = 0; i < height; i++)
00077 {
00078 for(j = 0; j < width; j++)
00079 {
00080 output_row[j] = input_row[j];
00081 }
00082 output_row += step;
00083 input_row += bytes_per_row;
00084 }
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 result = quicktime_write_data(file, codec->key_frame, bytes);
00114 result = !result;
00115
00116
00117 output_bytes = quicktime_position(file) - offset;
00118 quicktime_update_tables(file,
00119 vtrack->track,
00120 offset,
00121 vtrack->current_chunk,
00122 vtrack->current_position,
00123 codec->frames_per_chunk,
00124 output_bytes);
00125
00126
00127 codec->frames_per_chunk = 0;
00128 vtrack->current_chunk++;
00129 return result;
00130 }
00131
00132
00133 int wmx1_store_in_cache(quicktime_t *file, unsigned char *cache, unsigned char **row_pointers, int track)
00134 {
00135 long offset = quicktime_position(file);
00136 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00137 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
00138 quicktime_yuv_t *yuv_tables = &(codec->yuv_tables);
00139 int result = 0;
00140 int width = vtrack->track->tkhd.track_width;
00141 int height = vtrack->track->tkhd.track_height;
00142 long bytes = codec->rows * codec->bytes_per_line;
00143 unsigned char *buffer = cache;
00144 unsigned char *output_row;
00145 unsigned char *row_pointer1, *row_pointer2;
00146 int x1, x2, in_y, out_y;
00147 int y1, y2, y3, y4, u, v;
00148 int r, g, b;
00149 int endpoint = width * 3;
00150 int denominator;
00151
00152 for(in_y = 0, out_y = 0; in_y < height; out_y++)
00153 {
00154 output_row = buffer + out_y * codec->bytes_per_line;
00155 row_pointer1 = row_pointers[in_y];
00156 in_y++;
00157
00158 if(in_y < height)
00159 row_pointer2 = row_pointers[in_y];
00160 else
00161 row_pointer2 = row_pointer1;
00162
00163 in_y++;
00164
00165 for(x1 = 0, x2 = 0; x1 < endpoint; )
00166 {
00167
00168 r = row_pointer1[x1++];
00169 g = row_pointer1[x1++];
00170 b = row_pointer1[x1++];
00171
00172 y1 = (yuv_tables->rtoy_tab[r] + yuv_tables->gtoy_tab[g] + yuv_tables->btoy_tab[b]);
00173 u = (yuv_tables->rtou_tab[r] + yuv_tables->gtou_tab[g] + yuv_tables->btou_tab[b]);
00174 v = (yuv_tables->rtov_tab[r] + yuv_tables->gtov_tab[g] + yuv_tables->btov_tab[b]);
00175
00176
00177 if(x1 < endpoint)
00178 {
00179 r = row_pointer1[x1++];
00180 g = row_pointer1[x1++];
00181 b = row_pointer1[x1++];
00182 }
00183
00184 y2 = (yuv_tables->rtoy_tab[r] + yuv_tables->gtoy_tab[g] + yuv_tables->btoy_tab[b]);
00185 u += (yuv_tables->rtou_tab[r] + yuv_tables->gtou_tab[g] + yuv_tables->btou_tab[b]);
00186 v += (yuv_tables->rtov_tab[r] + yuv_tables->gtov_tab[g] + yuv_tables->btov_tab[b]);
00187
00188
00189 r = row_pointer2[x2++];
00190 g = row_pointer2[x2++];
00191 b = row_pointer2[x2++];
00192
00193 y3 = (yuv_tables->rtoy_tab[r] + yuv_tables->gtoy_tab[g] + yuv_tables->btoy_tab[b]);
00194 u += (yuv_tables->rtou_tab[r] + yuv_tables->gtou_tab[g] + yuv_tables->btou_tab[b]);
00195 v += (yuv_tables->rtov_tab[r] + yuv_tables->gtov_tab[g] + yuv_tables->btov_tab[b]);
00196
00197
00198 if(x2 < endpoint)
00199 {
00200 r = row_pointer2[x2++];
00201 g = row_pointer2[x2++];
00202 b = row_pointer2[x2++];
00203 }
00204
00205 y4 = (yuv_tables->rtoy_tab[r] + yuv_tables->gtoy_tab[g] + yuv_tables->btoy_tab[b]);
00206 u += (yuv_tables->rtou_tab[r] + yuv_tables->gtou_tab[g] + yuv_tables->btou_tab[b]);
00207 v += (yuv_tables->rtov_tab[r] + yuv_tables->gtov_tab[g] + yuv_tables->btov_tab[b]);
00208
00209 y1 /= 0x10000;
00210 y2 /= 0x10000;
00211 y3 /= 0x10000;
00212 y4 /= 0x10000;
00213 u /= 0x40000;
00214 v /= 0x40000;
00215 if(y1 > 255) y1 = 255;
00216 if(y2 > 255) y2 = 255;
00217 if(y3 > 255) y3 = 255;
00218 if(y4 > 255) y4 = 255;
00219 if(u > 127) u = 127;
00220 if(v > 127) v = 127;
00221 if(y1 < 0) y1 = 0;
00222 if(y2 < 0) y2 = 0;
00223 if(y3 < 0) y3 = 0;
00224 if(y4 < 0) y4 = 0;
00225 if(u < -128) u = -128;
00226 if(v < -128) v = -128;
00227
00228 *output_row++ = u;
00229 *output_row++ = v;
00230 *output_row++ = y1;
00231 *output_row++ = y2;
00232 *output_row++ = y3;
00233 *output_row++ = y4;
00234 }
00235 }
00236 return 0;
00237 }
00238
00239 int quicktime_encode_wmx1(quicktime_t *file, unsigned char **row_pointers, int track)
00240 {
00241 int result = 0;
00242 int written_cache = 0;
00243 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00244 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
00245 int width = vtrack->track->tkhd.track_width;
00246 int height = vtrack->track->tkhd.track_height;
00247 int bytes = codec->rows * codec->bytes_per_line;
00248 long frame_difference = 0;
00249 int i;
00250
00251
00252 if(codec->frames_per_chunk < WMX_CHUNK_FRAMES)
00253 {
00254 unsigned char *frame_cache;
00255 unsigned char *row_pointer1, *row_pointer2, *endpoint;
00256 if(!codec->frame_cache[codec->frames_per_chunk])
00257 codec->frame_cache[codec->frames_per_chunk] = malloc(bytes);
00258 frame_cache = codec->frame_cache[codec->frames_per_chunk];
00259
00260
00261 wmx1_store_in_cache(file, frame_cache, row_pointers, track);
00262 codec->frames_per_chunk++;
00263 }
00264 else
00265 {
00266
00267 unsigned char *frame_cache;
00268
00269 result = wmx1_write_cache(file, track);
00270 written_cache = 1;
00271
00272
00273 if(!codec->frame_cache[codec->frames_per_chunk])
00274 codec->frame_cache[codec->frames_per_chunk] = malloc(bytes);
00275 frame_cache = codec->frame_cache[codec->frames_per_chunk];
00276 wmx1_store_in_cache(file, codec->frame_cache[codec->frames_per_chunk], row_pointers, track);
00277 codec->frames_per_chunk++;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 return result;
00291 }
00292
00293 int quicktime_decode_wmx1(quicktime_t *file, unsigned char **row_pointers, int track)
00294 {
00295 int result = 0;
00296 return result;
00297 }