5 #include "colormodels.h"
6 #include "funcprotos.h"
12 #define JPEG_PROGRESSIVE 0
18 unsigned char *buffer;
19 long buffer_allocated;
23 unsigned char *temp_video;
27 } quicktime_jpeg_codec_t;
29 static void delete_codec(quicktime_video_map_t *vtrack)
31 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
33 if(codec->mjpeg) mjpeg_delete(codec->mjpeg);
37 free(codec->temp_video);
41 void quicktime_set_jpeg(quicktime_t *file, int quality, int use_float)
46 for(i = 0; i < file->total_vtracks; i++)
48 if(quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_JPEG) ||
49 quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_MJPA) ||
50 quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_RTJ0))
52 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[i].codec)->priv;
53 codec->quality = quality;
54 codec->use_float = use_float;
61 static void initialize(quicktime_video_map_t *vtrack)
63 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
64 if(!codec->initialized)
66 /* Init private items */
67 codec->mjpeg = mjpeg_new(vtrack->track->tkhd.track_width,
68 vtrack->track->tkhd.track_height,
69 1 + (codec->jpeg_type == JPEG_MJPA || codec->jpeg_type == JPEG_MJPB));
71 /* This information must be stored in the initialization routine because of */
72 /* direct copy rendering. Quicktime for Windows must have this information. */
73 if(codec->jpeg_type == JPEG_MJPA &&
74 !vtrack->track->mdia.minf.stbl.stsd.table[0].fields)
76 vtrack->track->mdia.minf.stbl.stsd.table[0].fields = 2;
77 vtrack->track->mdia.minf.stbl.stsd.table[0].field_dominance = 1;
79 codec->initialized = 1;
83 static int decode(quicktime_t *file,
84 unsigned char **row_pointers,
87 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
89 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
90 quicktime_trak_t *trak = vtrack->track;
91 mjpeg_t *mjpeg = codec->mjpeg;
92 long size, field2_offset = 0;
93 int track_height = trak->tkhd.track_height;
94 int track_width = trak->tkhd.track_width;
96 int field_dominance = trak->mdia.minf.stbl.stsd.table[0].field_dominance;
98 mjpeg_set_cpus(codec->mjpeg, file->cpus);
100 mjpeg_set_rowspan(codec->mjpeg, file->row_span);
102 mjpeg_set_rowspan(codec->mjpeg, 0);
104 quicktime_set_video_position(file, vtrack->current_position, track);
105 size = quicktime_frame_size(file, vtrack->current_position, track);
106 codec->buffer_size = size;
108 if(size > codec->buffer_allocated)
110 codec->buffer_allocated = size;
111 codec->buffer = realloc(codec->buffer, codec->buffer_allocated);
114 result = !quicktime_read_data(file, (char*)codec->buffer, size);
116 * printf("decode 1 %02x %02x %02x %02x %02x %02x %02x %02x\n",
130 if(mjpeg_get_fields(mjpeg) == 2)
134 field2_offset = mjpeg_get_avi_field2(codec->buffer,
140 field2_offset = mjpeg_get_quicktime_field2(codec->buffer,
145 printf("decode: FYI field2_offset=0\n");
146 field2_offset = mjpeg_get_field2(codec->buffer, size);
154 //printf("decode 2 %d\n", field2_offset);
156 * printf("decode result=%d field1=%llx field2=%llx size=%d %02x %02x %02x %02x\n",
158 * quicktime_position(file) - size,
159 * quicktime_position(file) - size + field2_offset,
163 * codec->buffer[field2_offset + 0],
164 * codec->buffer[field2_offset + 1]);
167 if(file->in_x == 0 &&
169 file->in_w == track_width &&
170 file->in_h == track_height &&
171 file->out_w == track_width &&
172 file->out_h == track_height)
174 mjpeg_decompress(codec->mjpeg,
188 unsigned char **temp_rows;
189 int temp_cmodel = BC_YUV888;
190 int temp_rowsize = cmodel_calculate_pixelsize(temp_cmodel) * track_width;
192 if(!codec->temp_video)
193 codec->temp_video = malloc(temp_rowsize * track_height);
194 temp_rows = malloc(sizeof(unsigned char*) * track_height);
195 for(i = 0; i < track_height; i++)
196 temp_rows[i] = codec->temp_video + i * temp_rowsize;
198 //printf("decode 10\n");
199 mjpeg_decompress(codec->mjpeg,
210 cmodel_transfer(row_pointers,
232 //printf("decode 30\n");
235 //printf("decode 40\n");
238 //printf("decode 2 %d\n", result);
243 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
245 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
247 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
248 quicktime_trak_t *trak = vtrack->track;
249 mjpeg_set_quality(codec->mjpeg, codec->quality);
250 mjpeg_set_float(codec->mjpeg, codec->use_float);
251 //int64_t offset = quicktime_position(file);
254 quicktime_atom_t chunk_atom;
256 //printf("encode 1\n");
257 mjpeg_set_cpus(codec->mjpeg, file->cpus);
258 mjpeg_compress(codec->mjpeg, row_pointers,
259 row_pointers[0], row_pointers[1], row_pointers[2],
260 file->color_model, file->cpus);
262 if(codec->jpeg_type == JPEG_MJPA)
266 mjpeg_insert_avi_markers(&codec->mjpeg->output_data,
267 &codec->mjpeg->output_size,
268 &codec->mjpeg->output_allocated,
274 mjpeg_insert_quicktime_markers(&codec->mjpeg->output_data,
275 &codec->mjpeg->output_size,
276 &codec->mjpeg->output_allocated,
282 quicktime_write_chunk_header(file, trak, &chunk_atom);
283 result = !quicktime_write_data(file,
284 (char*)mjpeg_output_buffer(codec->mjpeg),
285 mjpeg_output_size(codec->mjpeg));
286 quicktime_write_chunk_footer(file,
288 vtrack->current_chunk,
292 vtrack->current_chunk++;
293 //printf("encode 100\n");
297 static int reads_colormodel(quicktime_t *file,
301 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
302 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
304 // Some JPEG_PROGRESSIVE is BC_YUV422P
305 if(codec->jpeg_type == JPEG_PROGRESSIVE)
307 return (colormodel == BC_RGB888 ||
308 colormodel == BC_YUV888 ||
309 colormodel == BC_YUV420P ||
310 colormodel == BC_YUV422P ||
311 colormodel == BC_YUV422);
315 return (colormodel == BC_RGB888 ||
316 colormodel == BC_YUV888 ||
317 // colormodel == BC_YUV420P ||
318 colormodel == BC_YUV422P ||
319 colormodel == BC_YUV422);
320 // The BC_YUV420P option was provided only for mpeg2movie use.because some
321 // interlaced movies were accidentally in YUV4:2:0
325 static int writes_colormodel(quicktime_t *file,
329 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
330 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
332 if(codec->jpeg_type == JPEG_PROGRESSIVE)
334 return (colormodel == BC_RGB888 ||
335 colormodel == BC_YUV888 ||
336 colormodel == BC_YUV420P);
340 return (colormodel == BC_RGB888 ||
341 colormodel == BC_YUV888 ||
342 colormodel == BC_YUV422P);
346 static int set_parameter(quicktime_t *file,
351 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
353 if(!strcasecmp(key, "jpeg_quality"))
355 codec->quality = *(int*)value;
358 if(!strcasecmp(key, "jpeg_usefloat"))
360 codec->use_float = *(int*)value;
365 static void init_codec_common(quicktime_video_map_t *vtrack, char *compressor)
367 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
368 quicktime_jpeg_codec_t *codec;
370 codec = codec_base->priv = calloc(1, sizeof(quicktime_jpeg_codec_t));
371 if(quicktime_match_32(compressor, QUICKTIME_JPEG))
372 codec->jpeg_type = JPEG_PROGRESSIVE;
373 if(quicktime_match_32(compressor, QUICKTIME_MJPA))
374 codec->jpeg_type = JPEG_MJPA;
376 codec->use_float = 0;
378 /* Init public items */
379 codec_base->delete_vcodec = delete_codec;
380 codec_base->decode_video = decode;
381 codec_base->encode_video = encode;
382 codec_base->decode_audio = 0;
383 codec_base->encode_audio = 0;
384 codec_base->reads_colormodel = reads_colormodel;
385 codec_base->writes_colormodel = writes_colormodel;
386 codec_base->set_parameter = set_parameter;
387 codec_base->fourcc = compressor;
388 codec_base->title = (codec->jpeg_type == JPEG_PROGRESSIVE ? "JPEG Photo" : "Motion JPEG A");
389 codec_base->desc = codec_base->title;
393 void quicktime_init_codec_jpeg(quicktime_video_map_t *vtrack)
395 init_codec_common(vtrack, QUICKTIME_JPEG);
398 void quicktime_init_codec_mjpa(quicktime_video_map_t *vtrack)
400 init_codec_common(vtrack, QUICKTIME_MJPA);
403 void quicktime_init_codec_mjpg(quicktime_video_map_t *vtrack)
405 init_codec_common(vtrack, QUICKTIME_MJPG);