4 #include "colormodels.h"
5 #include "funcprotos.h"
11 #define JPEG_PROGRESSIVE 0
17 unsigned char *buffer
;
18 long buffer_allocated
;
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
;
30 mjpeg_delete(codec
->mjpeg
);
34 free(codec
->temp_video
);
39 void quicktime_set_jpeg(quicktime_t
*file
, int quality
, int use_float
)
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
,
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
;
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
);
74 mjpeg_set_rowspan(codec
->mjpeg
, file
->row_span
);
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
);
93 if(mjpeg_get_fields(mjpeg
) == 2)
97 field2_offset
= mjpeg_get_avi_field2(codec
->buffer
,
103 field2_offset
= mjpeg_get_quicktime_field2(codec
->buffer
, size
);
111 * printf("decode result=%d field1=%llx field2=%llx size=%d %02x %02x %02x %02x\n",
113 * quicktime_position(file) - size,
114 * quicktime_position(file) - size + field2_offset,
118 * codec->buffer[field2_offset + 0],
119 * codec->buffer[field2_offset + 1]);
122 if(file
->in_x
== 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
)
130 mjpeg_decompress(codec
->mjpeg
,
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
,
165 cmodel_transfer(row_pointers
,
190 //printf("decode 2 %d\n", 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
);
203 quicktime_atom_t chunk_atom
;
205 //printf("encode 1\n");
206 mjpeg_set_cpus(codec
->mjpeg
, file
->cpus
);
208 mjpeg_compress(codec
->mjpeg
,
215 if(codec
->jpeg_type
== JPEG_MJPA
)
219 mjpeg_insert_avi_markers(&codec
->mjpeg
->output_data
,
220 &codec
->mjpeg
->output_size
,
221 &codec
->mjpeg
->output_allocated
,
227 mjpeg_insert_quicktime_markers(&codec
->mjpeg
->output_data
,
228 &codec
->mjpeg
->output_size
,
229 &codec
->mjpeg
->output_allocated
,
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
,
241 vtrack
->current_chunk
,
245 vtrack
->current_chunk
++;
246 //printf("encode 100\n");
250 static int reads_colormodel(quicktime_t
*file
,
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
);
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
,
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
);
293 return (colormodel
== BC_RGB888
||
294 colormodel
== BC_YUV888
||
295 colormodel
== BC_YUV422P
);
299 static int set_parameter(quicktime_t
*file
,
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
);
311 if(!strcasecmp(key
, "jpeg_usefloat"))
313 mjpeg_set_float(codec
->mjpeg
, *(int*)value
);
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
;
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
);