r123: Merged HEAD and TEST. New stuff shall be committed to HEAD from now on.
[cinelerra_cv/mob.git] / quicktime / wmx1.c
blob41aa2bb322cc0466229f6c39ccc66fcfc0d206f4
1 #include "quicktime.h"
2 #include "jpeglib.h"
4 #define ABS(x) ((x) < 0 ? -(x) : (x))
6 int quicktime_init_codec_wmx1(quicktime_video_map_t *vtrack)
8 int i;
9 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
11 quicktime_init_yuv(&(codec->yuv_tables));
12 codec->bytes_per_line = vtrack->track->tkhd.track_width * 3;
13 if((float)codec->bytes_per_line / 6 > (int)(codec->bytes_per_line / 6))
14 codec->bytes_per_line += 3;
16 codec->rows = vtrack->track->tkhd.track_height / 2;
17 if((float)vtrack->track->tkhd.track_height / 2 > (int)(vtrack->track->tkhd.track_height / 2))
18 codec->rows++;
20 for(i = 0; i < WMX_CHUNK_FRAMES; i++)
21 codec->frame_cache[i] = 0;
23 codec->key_frame = 0;
24 codec->keyframe_position = 0;
25 codec->quality = 100;
26 codec->use_float = 0;
27 codec->frames_per_chunk = 0;
28 codec->threshold = 5;
29 return 0;
32 int quicktime_delete_codec_wmx1(quicktime_video_map_t *vtrack)
34 int i;
35 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
37 quicktime_delete_yuv(&(codec->yuv_tables));
38 for(i = 0; i < WMX_CHUNK_FRAMES; i++)
39 if(codec->frame_cache[i]) free(codec->frame_cache[i]);
41 if(codec->key_frame) free(codec->key_frame);
42 return 0;
45 int wmx1_write_cache(quicktime_t *file, int track)
47 long offset = quicktime_position(file);
48 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
49 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
50 int width = codec->bytes_per_line;
51 int height = codec->rows;
52 int result = 0;
53 int frame, channel, i, j, k;
54 long bytes_per_row = codec->bytes_per_line;
55 int step = codec->frames_per_chunk * bytes_per_row;
56 long bytes = height * bytes_per_row * codec->frames_per_chunk;
57 long output_bytes;
58 unsigned char *input_row, *input_end, *output_row, *input_frame, *output_frame;
60 /*printf("wmx1_write_cache 1 %d %d %d\n", bytes_per_row, bytes_per_channel, bytes); */
61 if(!codec->key_frame)
63 codec->key_frame = malloc(bytes);
64 if(!codec->key_frame) result = 1;
66 /*printf("wmx1_write_cache 2\n"); */
68 /* Interlace rows */
69 for(frame = 0; frame < codec->frames_per_chunk; frame++)
71 input_frame = codec->frame_cache[frame];
72 output_frame = codec->key_frame + frame * bytes_per_row;
73 input_row = input_frame;
74 output_row = output_frame;
76 for(i = 0; i < height; i++)
78 for(j = 0; j < width; j++)
80 output_row[j] = input_row[j];
82 output_row += step;
83 input_row += bytes_per_row;
87 /* Write as a jpeg */
88 /* { */
89 /* struct jpeg_compress_struct jpeg_compress; */
90 /* struct jpeg_error_mgr jpeg_error; */
91 /* JSAMPROW row_pointer[1]; */
92 /* jpeg_compress.err = jpeg_std_error(&jpeg_error); */
93 /* jpeg_create_compress(&jpeg_compress); */
94 /* jpeg_stdio_dest(&jpeg_compress, quicktime_get_fd(file)); */
95 /* jpeg_compress.image_width = bytes_per_row; */
96 /* jpeg_compress.image_height = height * codec->frames_per_chunk; */
97 /* jpeg_compress.input_components = 1; */
98 /* jpeg_compress.in_color_space = JCS_GRAYSCALE; */
99 /* jpeg_set_defaults(&jpeg_compress); */
100 /* jpeg_set_quality(&jpeg_compress, codec->quality, 0); */
101 /* jpeg_start_compress(&jpeg_compress, TRUE); */
102 /* while(jpeg_compress.next_scanline < jpeg_compress.image_height && !result) */
103 /* { */
104 /* row_pointer[0] = codec->key_frame + jpeg_compress.next_scanline * bytes_per_row; */
105 /* result = jpeg_write_scanlines(&jpeg_compress, row_pointer, 1); */
106 /* result = !result; */
107 /* } */
108 /* jpeg_finish_compress(&jpeg_compress); */
109 /* jpeg_destroy((j_common_ptr)&jpeg_compress); */
110 /* } */
112 /* Write as raw */
113 result = quicktime_write_data(file, codec->key_frame, bytes);
114 result = !result;
115 /*printf("wmx1_write_cache 4\n"); */
117 output_bytes = quicktime_position(file) - offset;
118 quicktime_update_tables(file,
119 vtrack->track,
120 offset,
121 vtrack->current_chunk,
122 vtrack->current_position,
123 codec->frames_per_chunk,
124 output_bytes);
125 /*printf("wmx1_write_cache 5\n"); */
127 codec->frames_per_chunk = 0;
128 vtrack->current_chunk++;
129 return result;
132 /* Perform YUV transform and store in cache */
133 int wmx1_store_in_cache(quicktime_t *file, unsigned char *cache, unsigned char **row_pointers, int track)
135 long offset = quicktime_position(file);
136 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
137 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
138 quicktime_yuv_t *yuv_tables = &(codec->yuv_tables);
139 int result = 0;
140 int width = vtrack->track->tkhd.track_width;
141 int height = vtrack->track->tkhd.track_height;
142 long bytes = codec->rows * codec->bytes_per_line;
143 unsigned char *buffer = cache;
144 unsigned char *output_row; /* Pointer to output row */
145 unsigned char *row_pointer1, *row_pointer2; /* Pointers to input rows */
146 int x1, x2, in_y, out_y;
147 int y1, y2, y3, y4, u, v;
148 int r, g, b;
149 int endpoint = width * 3;
150 int denominator;
152 for(in_y = 0, out_y = 0; in_y < height; out_y++)
154 output_row = buffer + out_y * codec->bytes_per_line;
155 row_pointer1 = row_pointers[in_y];
156 in_y++;
158 if(in_y < height)
159 row_pointer2 = row_pointers[in_y];
160 else
161 row_pointer2 = row_pointer1;
163 in_y++;
165 for(x1 = 0, x2 = 0; x1 < endpoint; )
167 /* Top left pixel */
168 r = row_pointer1[x1++];
169 g = row_pointer1[x1++];
170 b = row_pointer1[x1++];
172 y1 = (yuv_tables->rtoy_tab[r] + yuv_tables->gtoy_tab[g] + yuv_tables->btoy_tab[b]);
173 u = (yuv_tables->rtou_tab[r] + yuv_tables->gtou_tab[g] + yuv_tables->btou_tab[b]);
174 v = (yuv_tables->rtov_tab[r] + yuv_tables->gtov_tab[g] + yuv_tables->btov_tab[b]);
176 /* Top right pixel */
177 if(x1 < endpoint)
179 r = row_pointer1[x1++];
180 g = row_pointer1[x1++];
181 b = row_pointer1[x1++];
184 y2 = (yuv_tables->rtoy_tab[r] + yuv_tables->gtoy_tab[g] + yuv_tables->btoy_tab[b]);
185 u += (yuv_tables->rtou_tab[r] + yuv_tables->gtou_tab[g] + yuv_tables->btou_tab[b]);
186 v += (yuv_tables->rtov_tab[r] + yuv_tables->gtov_tab[g] + yuv_tables->btov_tab[b]);
188 /* Bottom left pixel */
189 r = row_pointer2[x2++];
190 g = row_pointer2[x2++];
191 b = row_pointer2[x2++];
193 y3 = (yuv_tables->rtoy_tab[r] + yuv_tables->gtoy_tab[g] + yuv_tables->btoy_tab[b]);
194 u += (yuv_tables->rtou_tab[r] + yuv_tables->gtou_tab[g] + yuv_tables->btou_tab[b]);
195 v += (yuv_tables->rtov_tab[r] + yuv_tables->gtov_tab[g] + yuv_tables->btov_tab[b]);
197 /* Bottom right pixel */
198 if(x2 < endpoint)
200 r = row_pointer2[x2++];
201 g = row_pointer2[x2++];
202 b = row_pointer2[x2++];
205 y4 = (yuv_tables->rtoy_tab[r] + yuv_tables->gtoy_tab[g] + yuv_tables->btoy_tab[b]);
206 u += (yuv_tables->rtou_tab[r] + yuv_tables->gtou_tab[g] + yuv_tables->btou_tab[b]);
207 v += (yuv_tables->rtov_tab[r] + yuv_tables->gtov_tab[g] + yuv_tables->btov_tab[b]);
209 y1 /= 0x10000;
210 y2 /= 0x10000;
211 y3 /= 0x10000;
212 y4 /= 0x10000;
213 u /= 0x40000;
214 v /= 0x40000;
215 if(y1 > 255) y1 = 255;
216 if(y2 > 255) y2 = 255;
217 if(y3 > 255) y3 = 255;
218 if(y4 > 255) y4 = 255;
219 if(u > 127) u = 127;
220 if(v > 127) v = 127;
221 if(y1 < 0) y1 = 0;
222 if(y2 < 0) y2 = 0;
223 if(y3 < 0) y3 = 0;
224 if(y4 < 0) y4 = 0;
225 if(u < -128) u = -128;
226 if(v < -128) v = -128;
228 *output_row++ = u;
229 *output_row++ = v;
230 *output_row++ = y1;
231 *output_row++ = y2;
232 *output_row++ = y3;
233 *output_row++ = y4;
236 return 0;
239 int quicktime_encode_wmx1(quicktime_t *file, unsigned char **row_pointers, int track)
241 int result = 0;
242 int written_cache = 0;
243 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
244 quicktime_wmx1_codec_t *codec = &(vtrack->codecs.wmx1_codec);
245 int width = vtrack->track->tkhd.track_width;
246 int height = vtrack->track->tkhd.track_height;
247 int bytes = codec->rows * codec->bytes_per_line;
248 long frame_difference = 0;
249 int i;
251 /* Arm cache */
252 if(codec->frames_per_chunk < WMX_CHUNK_FRAMES)
254 unsigned char *frame_cache;
255 unsigned char *row_pointer1, *row_pointer2, *endpoint;
256 if(!codec->frame_cache[codec->frames_per_chunk])
257 codec->frame_cache[codec->frames_per_chunk] = malloc(bytes);
258 frame_cache = codec->frame_cache[codec->frames_per_chunk];
260 /* Copy to cache */
261 wmx1_store_in_cache(file, frame_cache, row_pointers, track);
262 codec->frames_per_chunk++;
264 else
266 /* Write cache and start new cache. */
267 unsigned char *frame_cache;
269 result = wmx1_write_cache(file, track);
270 written_cache = 1;
272 /* Copy next frame to cache */
273 if(!codec->frame_cache[codec->frames_per_chunk])
274 codec->frame_cache[codec->frames_per_chunk] = malloc(bytes);
275 frame_cache = codec->frame_cache[codec->frames_per_chunk];
276 wmx1_store_in_cache(file, codec->frame_cache[codec->frames_per_chunk], row_pointers, track);
277 codec->frames_per_chunk++;
279 /*printf("quicktime_encode_wmx1 3\n"); */
281 /* if(!written_cache) */
282 /* quicktime_update_tables(file, */
283 /* vtrack->track, */
284 /* offset, */
285 /* vtrack->current_chunk, */
286 /* vtrack->current_position, */
287 /* codec->frames_per_chunk, */
288 /* output_bytes); */
289 /* */
290 return result;
293 int quicktime_decode_wmx1(quicktime_t *file, unsigned char **row_pointers, int track)
295 int result = 0;
296 return result;