r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / quicktime / jpeg.c
blobd6a803913dc323f4cdea9f47a30747fa097caa3b
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 } quicktime_jpeg_codec_t;
25 static int delete_codec(quicktime_video_map_t *vtrack)
27 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
28 int i;
30 mjpeg_delete(codec->mjpeg);
31 if(codec->buffer)
32 free(codec->buffer);
33 if(codec->temp_video)
34 free(codec->temp_video);
35 free(codec);
36 return 0;
39 void quicktime_set_jpeg(quicktime_t *file, int quality, int use_float)
41 int i;
42 char *compressor;
44 for(i = 0; i < file->total_vtracks; i++)
46 if(quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_JPEG) ||
47 quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_MJPA) ||
48 quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_RTJ0))
50 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[i].codec)->priv;
51 mjpeg_set_quality(codec->mjpeg, quality);
52 mjpeg_set_float(codec->mjpeg, use_float);
57 static int decode(quicktime_t *file,
58 unsigned char **row_pointers,
59 int track)
61 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
62 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
63 quicktime_trak_t *trak = vtrack->track;
64 mjpeg_t *mjpeg = codec->mjpeg;
65 long size, field2_offset = 0;
66 int track_height = trak->tkhd.track_height;
67 int track_width = trak->tkhd.track_width;
68 int result = 0;
69 int field_dominance = trak->mdia.minf.stbl.stsd.table[0].field_dominance;
71 //printf(__FUNCTION__ " 1 %d\n", vtrack->current_position);
72 mjpeg_set_cpus(codec->mjpeg, file->cpus);
73 if(file->row_span)
74 mjpeg_set_rowspan(codec->mjpeg, file->row_span);
75 else
76 mjpeg_set_rowspan(codec->mjpeg, 0);
78 quicktime_set_video_position(file, vtrack->current_position, track);
79 size = quicktime_frame_size(file, vtrack->current_position, track);
80 codec->buffer_size = size;
82 if(size > codec->buffer_allocated)
84 codec->buffer_allocated = size;
85 codec->buffer = realloc(codec->buffer, codec->buffer_allocated);
88 //printf("decode 1 %llx %llx\n", quicktime_position(file), quicktime_position(file) + size);
89 result = !quicktime_read_data(file, codec->buffer, size);
91 if(!result)
93 if(mjpeg_get_fields(mjpeg) == 2)
95 if(file->use_avi)
97 field2_offset = mjpeg_get_avi_field2(codec->buffer,
98 size,
99 &field_dominance);
101 else
103 field2_offset = mjpeg_get_quicktime_field2(codec->buffer, size);
106 else
107 field2_offset = 0;
111 * printf("decode result=%d field1=%llx field2=%llx size=%d %02x %02x %02x %02x\n",
112 * result,
113 * quicktime_position(file) - size,
114 * quicktime_position(file) - size + field2_offset,
115 * size,
116 * codec->buffer[0],
117 * codec->buffer[1],
118 * codec->buffer[field2_offset + 0],
119 * codec->buffer[field2_offset + 1]);
122 if(file->in_x == 0 &&
123 file->in_y == 0 &&
124 file->in_w == track_width &&
125 file->in_h == track_height &&
126 file->out_w == track_width &&
127 file->out_h == track_height)
129 int i;
130 mjpeg_decompress(codec->mjpeg,
131 codec->buffer,
132 size,
133 field2_offset,
134 row_pointers,
135 row_pointers[0],
136 row_pointers[1],
137 row_pointers[2],
138 file->color_model,
139 file->cpus);
141 else
143 int i;
144 unsigned char **temp_rows;
145 int temp_cmodel = BC_YUV888;
146 int temp_rowsize = cmodel_calculate_pixelsize(temp_cmodel) * track_width;
148 if(!codec->temp_video)
149 codec->temp_video = malloc(temp_rowsize * track_height);
150 temp_rows = malloc(sizeof(unsigned char*) * track_height);
151 for(i = 0; i < track_height; i++)
152 temp_rows[i] = codec->temp_video + i * temp_rowsize;
154 mjpeg_decompress(codec->mjpeg,
155 codec->buffer,
156 size,
157 field2_offset,
158 temp_rows,
159 temp_rows[0],
160 temp_rows[1],
161 temp_rows[2],
162 temp_cmodel,
163 file->cpus);
165 cmodel_transfer(row_pointers,
166 temp_rows,
167 row_pointers[0],
168 row_pointers[1],
169 row_pointers[2],
170 temp_rows[0],
171 temp_rows[1],
172 temp_rows[2],
173 file->in_x,
174 file->in_y,
175 file->in_w,
176 file->in_h,
179 file->out_w,
180 file->out_h,
181 temp_cmodel,
182 file->color_model,
184 track_width,
185 file->out_w);
187 free(temp_rows);
190 //printf("decode 2 %d\n", result);
192 return result;
195 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
197 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
198 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
199 quicktime_trak_t *trak = vtrack->track;
200 int64_t offset = quicktime_position(file);
201 int result = 0;
202 long field2_offset;
203 quicktime_atom_t chunk_atom;
205 //printf("encode 1\n");
206 mjpeg_set_cpus(codec->mjpeg, file->cpus);
208 mjpeg_compress(codec->mjpeg,
209 row_pointers,
210 row_pointers[0],
211 row_pointers[1],
212 row_pointers[2],
213 file->color_model,
214 file->cpus);
215 if(codec->jpeg_type == JPEG_MJPA)
217 if(file->use_avi)
219 mjpeg_insert_avi_markers(&codec->mjpeg->output_data,
220 &codec->mjpeg->output_size,
221 &codec->mjpeg->output_allocated,
223 &field2_offset);
225 else
227 mjpeg_insert_quicktime_markers(&codec->mjpeg->output_data,
228 &codec->mjpeg->output_size,
229 &codec->mjpeg->output_allocated,
231 &field2_offset);
235 quicktime_write_chunk_header(file, trak, &chunk_atom);
236 result = !quicktime_write_data(file,
237 mjpeg_output_buffer(codec->mjpeg),
238 mjpeg_output_size(codec->mjpeg));
239 quicktime_write_chunk_footer(file,
240 trak,
241 vtrack->current_chunk,
242 &chunk_atom,
245 vtrack->current_chunk++;
246 //printf("encode 100\n");
247 return result;
250 static int reads_colormodel(quicktime_t *file,
251 int colormodel,
252 int track)
254 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
255 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
257 // Some JPEG_PROGRESSIVE is BC_YUV422P
258 if(codec->jpeg_type == JPEG_PROGRESSIVE)
260 return (colormodel == BC_RGB888 ||
261 colormodel == BC_YUV888 ||
262 colormodel == BC_YUV420P ||
263 colormodel == BC_YUV422P ||
264 colormodel == BC_YUV422);
266 else
268 return (colormodel == BC_RGB888 ||
269 colormodel == BC_YUV888 ||
270 // colormodel == BC_YUV420P ||
271 colormodel == BC_YUV422P ||
272 colormodel == BC_YUV422);
273 // The BC_YUV420P option was provided only for mpeg2movie use.because some
274 // interlaced movies were accidentally in YUV4:2:0
278 static int writes_colormodel(quicktime_t *file,
279 int colormodel,
280 int track)
282 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
283 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
285 if(codec->jpeg_type == JPEG_PROGRESSIVE)
287 return (colormodel == BC_RGB888 ||
288 colormodel == BC_YUV888 ||
289 colormodel == BC_YUV420P);
291 else
293 return (colormodel == BC_RGB888 ||
294 colormodel == BC_YUV888 ||
295 colormodel == BC_YUV422P);
299 static int set_parameter(quicktime_t *file,
300 int track,
301 char *key,
302 void *value)
304 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
306 if(!strcasecmp(key, "jpeg_quality"))
308 mjpeg_set_quality(codec->mjpeg, *(int*)value);
310 else
311 if(!strcasecmp(key, "jpeg_usefloat"))
313 mjpeg_set_float(codec->mjpeg, *(int*)value);
315 return 0;
318 static void init_codec_common(quicktime_video_map_t *vtrack, char *compressor)
320 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
321 quicktime_jpeg_codec_t *codec;
322 int i, jpeg_type;
324 if(quicktime_match_32(compressor, QUICKTIME_JPEG))
325 jpeg_type = JPEG_PROGRESSIVE;
326 if(quicktime_match_32(compressor, QUICKTIME_MJPA))
327 jpeg_type = JPEG_MJPA;
329 /* Init public items */
330 codec_base->priv = calloc(1, sizeof(quicktime_jpeg_codec_t));
331 codec_base->delete_vcodec = delete_codec;
332 codec_base->decode_video = decode;
333 codec_base->encode_video = encode;
334 codec_base->decode_audio = 0;
335 codec_base->encode_audio = 0;
336 codec_base->reads_colormodel = reads_colormodel;
337 codec_base->writes_colormodel = writes_colormodel;
338 codec_base->set_parameter = set_parameter;
339 codec_base->fourcc = compressor;
340 codec_base->title = jpeg_type == JPEG_PROGRESSIVE ? "JPEG Photo" : "Motion JPEG A";
341 codec_base->desc = codec_base->title;
343 /* Init private items */
344 codec = codec_base->priv;
345 codec->mjpeg = mjpeg_new(vtrack->track->tkhd.track_width,
346 vtrack->track->tkhd.track_height,
347 1 + (jpeg_type == JPEG_MJPA || jpeg_type == JPEG_MJPB));
348 codec->jpeg_type = jpeg_type;
350 /* This information must be stored in the initialization routine because of */
351 /* direct copy rendering. Quicktime for Windows must have this information. */
352 if(jpeg_type == JPEG_MJPA &&
353 !vtrack->track->mdia.minf.stbl.stsd.table[0].fields)
355 vtrack->track->mdia.minf.stbl.stsd.table[0].fields = 2;
356 vtrack->track->mdia.minf.stbl.stsd.table[0].field_dominance = 1;
360 void quicktime_init_codec_jpeg(quicktime_video_map_t *vtrack)
362 init_codec_common(vtrack, QUICKTIME_JPEG);
365 void quicktime_init_codec_mjpa(quicktime_video_map_t *vtrack)
367 init_codec_common(vtrack, QUICKTIME_MJPA);