r955: Fix the Diffkey icon.
[cinelerra_cv.git] / quicktime / jpeg.c
blobe7502c3029c2e15d0ebf58f2758cee1760709f67
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include "colormodels.h"
5 #include "funcprotos.h"
6 #include "jpeg.h"
7 #include "libmjpeg.h"
8 #include "quicktime.h"
10 // Jpeg types
11 #define JPEG_PROGRESSIVE 0
12 #define JPEG_MJPA 1
13 #define JPEG_MJPB 2
15 typedef struct
17 unsigned char *buffer;
18 long buffer_allocated;
19 long buffer_size;
20 mjpeg_t *mjpeg;
21 int jpeg_type;
22 unsigned char *temp_video;
23 int initialized;
24 int quality;
25 int use_float;
26 } quicktime_jpeg_codec_t;
28 static int delete_codec(quicktime_video_map_t *vtrack)
30 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
31 int i;
33 if(codec->mjpeg) mjpeg_delete(codec->mjpeg);
34 if(codec->buffer)
35 free(codec->buffer);
36 if(codec->temp_video)
37 free(codec->temp_video);
38 free(codec);
39 return 0;
42 void quicktime_set_jpeg(quicktime_t *file, int quality, int use_float)
44 int i;
45 char *compressor;
47 printf("1\n");
48 for(i = 0; i < file->total_vtracks; i++)
50 if(quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_JPEG) ||
51 quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_MJPA) ||
52 quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_RTJ0))
54 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[i].codec)->priv;
55 codec->quality = quality;
56 codec->use_float = use_float;
59 printf("10\n");
63 static void initialize(quicktime_video_map_t *vtrack)
65 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
66 if(!codec->initialized)
68 /* Init private items */
69 codec->mjpeg = mjpeg_new(vtrack->track->tkhd.track_width,
70 vtrack->track->tkhd.track_height,
71 1 + (codec->jpeg_type == JPEG_MJPA || codec->jpeg_type == JPEG_MJPB));
73 /* This information must be stored in the initialization routine because of */
74 /* direct copy rendering. Quicktime for Windows must have this information. */
75 if(codec->jpeg_type == JPEG_MJPA &&
76 !vtrack->track->mdia.minf.stbl.stsd.table[0].fields)
78 vtrack->track->mdia.minf.stbl.stsd.table[0].fields = 2;
79 vtrack->track->mdia.minf.stbl.stsd.table[0].field_dominance = 1;
81 codec->initialized = 1;
85 static int decode(quicktime_t *file,
86 unsigned char **row_pointers,
87 int track)
89 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
90 initialize(vtrack);
91 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
92 quicktime_trak_t *trak = vtrack->track;
93 mjpeg_t *mjpeg = codec->mjpeg;
94 long size, field2_offset = 0;
95 int track_height = trak->tkhd.track_height;
96 int track_width = trak->tkhd.track_width;
97 int result = 0;
98 int field_dominance = trak->mdia.minf.stbl.stsd.table[0].field_dominance;
100 mjpeg_set_cpus(codec->mjpeg, file->cpus);
101 if(file->row_span)
102 mjpeg_set_rowspan(codec->mjpeg, file->row_span);
103 else
104 mjpeg_set_rowspan(codec->mjpeg, 0);
106 quicktime_set_video_position(file, vtrack->current_position, track);
107 size = quicktime_frame_size(file, vtrack->current_position, track);
108 codec->buffer_size = size;
110 if(size > codec->buffer_allocated)
112 codec->buffer_allocated = size;
113 codec->buffer = realloc(codec->buffer, codec->buffer_allocated);
116 result = !quicktime_read_data(file, codec->buffer, size);
118 * printf("decode 1 %02x %02x %02x %02x %02x %02x %02x %02x\n",
119 * codec->buffer[0],
120 * codec->buffer[1],
121 * codec->buffer[2],
122 * codec->buffer[3],
123 * codec->buffer[4],
124 * codec->buffer[5],
125 * codec->buffer[6],
126 * codec->buffer[7]
127 * );
130 if(!result)
132 if(mjpeg_get_fields(mjpeg) == 2)
134 if(file->use_avi)
136 field2_offset = mjpeg_get_avi_field2(codec->buffer,
137 size,
138 &field_dominance);
140 else
142 field2_offset = mjpeg_get_quicktime_field2(codec->buffer,
143 size);
144 // Sanity check
145 if(!field2_offset)
147 printf("decode: FYI field2_offset=0\n");
148 field2_offset = mjpeg_get_field2(codec->buffer, size);
152 else
153 field2_offset = 0;
156 //printf("decode 2 %d\n", field2_offset);
158 * printf("decode result=%d field1=%llx field2=%llx size=%d %02x %02x %02x %02x\n",
159 * result,
160 * quicktime_position(file) - size,
161 * quicktime_position(file) - size + field2_offset,
162 * size,
163 * codec->buffer[0],
164 * codec->buffer[1],
165 * codec->buffer[field2_offset + 0],
166 * codec->buffer[field2_offset + 1]);
169 if(file->in_x == 0 &&
170 file->in_y == 0 &&
171 file->in_w == track_width &&
172 file->in_h == track_height &&
173 file->out_w == track_width &&
174 file->out_h == track_height)
176 int i;
177 mjpeg_decompress(codec->mjpeg,
178 codec->buffer,
179 size,
180 field2_offset,
181 row_pointers,
182 row_pointers[0],
183 row_pointers[1],
184 row_pointers[2],
185 file->color_model,
186 file->cpus);
188 else
190 int i;
191 unsigned char **temp_rows;
192 int temp_cmodel = BC_YUV888;
193 int temp_rowsize = cmodel_calculate_pixelsize(temp_cmodel) * track_width;
195 if(!codec->temp_video)
196 codec->temp_video = malloc(temp_rowsize * track_height);
197 temp_rows = malloc(sizeof(unsigned char*) * track_height);
198 for(i = 0; i < track_height; i++)
199 temp_rows[i] = codec->temp_video + i * temp_rowsize;
201 //printf("decode 10\n");
202 mjpeg_decompress(codec->mjpeg,
203 codec->buffer,
204 size,
205 field2_offset,
206 temp_rows,
207 temp_rows[0],
208 temp_rows[1],
209 temp_rows[2],
210 temp_cmodel,
211 file->cpus);
213 cmodel_transfer(row_pointers,
214 temp_rows,
215 row_pointers[0],
216 row_pointers[1],
217 row_pointers[2],
218 temp_rows[0],
219 temp_rows[1],
220 temp_rows[2],
221 file->in_x,
222 file->in_y,
223 file->in_w,
224 file->in_h,
227 file->out_w,
228 file->out_h,
229 temp_cmodel,
230 file->color_model,
232 track_width,
233 file->out_w);
235 //printf("decode 30\n");
236 free(temp_rows);
238 //printf("decode 40\n");
241 //printf("decode 2 %d\n", result);
243 return result;
246 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
248 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
249 initialize(vtrack);
250 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
251 quicktime_trak_t *trak = vtrack->track;
252 mjpeg_set_quality(codec->mjpeg, codec->quality);
253 mjpeg_set_float(codec->mjpeg, codec->use_float);
254 int64_t offset = quicktime_position(file);
255 int result = 0;
256 long field2_offset;
257 quicktime_atom_t chunk_atom;
259 //printf("encode 1\n");
260 mjpeg_set_cpus(codec->mjpeg, file->cpus);
262 mjpeg_compress(codec->mjpeg,
263 row_pointers,
264 row_pointers[0],
265 row_pointers[1],
266 row_pointers[2],
267 file->color_model,
268 file->cpus);
269 if(codec->jpeg_type == JPEG_MJPA)
271 if(file->use_avi)
273 mjpeg_insert_avi_markers(&codec->mjpeg->output_data,
274 &codec->mjpeg->output_size,
275 &codec->mjpeg->output_allocated,
277 &field2_offset);
279 else
281 mjpeg_insert_quicktime_markers(&codec->mjpeg->output_data,
282 &codec->mjpeg->output_size,
283 &codec->mjpeg->output_allocated,
285 &field2_offset);
289 quicktime_write_chunk_header(file, trak, &chunk_atom);
290 result = !quicktime_write_data(file,
291 mjpeg_output_buffer(codec->mjpeg),
292 mjpeg_output_size(codec->mjpeg));
293 quicktime_write_chunk_footer(file,
294 trak,
295 vtrack->current_chunk,
296 &chunk_atom,
299 vtrack->current_chunk++;
300 //printf("encode 100\n");
301 return result;
304 static int reads_colormodel(quicktime_t *file,
305 int colormodel,
306 int track)
308 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
309 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
311 // Some JPEG_PROGRESSIVE is BC_YUV422P
312 if(codec->jpeg_type == JPEG_PROGRESSIVE)
314 return (colormodel == BC_RGB888 ||
315 colormodel == BC_YUV888 ||
316 colormodel == BC_YUV420P ||
317 colormodel == BC_YUV422P ||
318 colormodel == BC_YUV422);
320 else
322 return (colormodel == BC_RGB888 ||
323 colormodel == BC_YUV888 ||
324 // colormodel == BC_YUV420P ||
325 colormodel == BC_YUV422P ||
326 colormodel == BC_YUV422);
327 // The BC_YUV420P option was provided only for mpeg2movie use.because some
328 // interlaced movies were accidentally in YUV4:2:0
332 static int writes_colormodel(quicktime_t *file,
333 int colormodel,
334 int track)
336 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
337 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
339 if(codec->jpeg_type == JPEG_PROGRESSIVE)
341 return (colormodel == BC_RGB888 ||
342 colormodel == BC_YUV888 ||
343 colormodel == BC_YUV420P);
345 else
347 return (colormodel == BC_RGB888 ||
348 colormodel == BC_YUV888 ||
349 colormodel == BC_YUV422P);
353 static int set_parameter(quicktime_t *file,
354 int track,
355 char *key,
356 void *value)
358 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
360 if(!strcasecmp(key, "jpeg_quality"))
362 codec->quality = *(int*)value;
364 else
365 if(!strcasecmp(key, "jpeg_usefloat"))
367 codec->use_float = *(int*)value;
369 return 0;
372 static void init_codec_common(quicktime_video_map_t *vtrack, char *compressor)
374 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
375 quicktime_jpeg_codec_t *codec;
376 int i;
378 codec = codec_base->priv = calloc(1, sizeof(quicktime_jpeg_codec_t));
379 if(quicktime_match_32(compressor, QUICKTIME_JPEG))
380 codec->jpeg_type = JPEG_PROGRESSIVE;
381 if(quicktime_match_32(compressor, QUICKTIME_MJPA))
382 codec->jpeg_type = JPEG_MJPA;
383 codec->quality = 80;
384 codec->use_float = 0;
386 /* Init public items */
387 codec_base->delete_vcodec = delete_codec;
388 codec_base->decode_video = decode;
389 codec_base->encode_video = encode;
390 codec_base->decode_audio = 0;
391 codec_base->encode_audio = 0;
392 codec_base->reads_colormodel = reads_colormodel;
393 codec_base->writes_colormodel = writes_colormodel;
394 codec_base->set_parameter = set_parameter;
395 codec_base->fourcc = compressor;
396 codec_base->title = (codec->jpeg_type == JPEG_PROGRESSIVE ? "JPEG Photo" : "Motion JPEG A");
397 codec_base->desc = codec_base->title;
401 void quicktime_init_codec_jpeg(quicktime_video_map_t *vtrack)
403 init_codec_common(vtrack, QUICKTIME_JPEG);
406 void quicktime_init_codec_mjpa(quicktime_video_map_t *vtrack)
408 init_codec_common(vtrack, QUICKTIME_MJPA);
411 void quicktime_init_codec_mjpg(quicktime_video_map_t *vtrack)
413 init_codec_common(vtrack, "MJPG");