00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include "colormodels.h"
00005 #include "funcprotos.h"
00006 #include "jpeg.h"
00007 #include "libmjpeg.h"
00008 #include "quicktime.h"
00009
00010
00011 #define JPEG_PROGRESSIVE 0
00012 #define JPEG_MJPA 1
00013 #define JPEG_MJPB 2
00014
00015 typedef struct
00016 {
00017 unsigned char *buffer;
00018 long buffer_allocated;
00019 long buffer_size;
00020 mjpeg_t *mjpeg;
00021 int jpeg_type;
00022 unsigned char *temp_video;
00023 int initialized;
00024 int quality;
00025 int use_float;
00026 } quicktime_jpeg_codec_t;
00027
00028 static int delete_codec(quicktime_video_map_t *vtrack)
00029 {
00030 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00031 int i;
00032
00033 if(codec->mjpeg) mjpeg_delete(codec->mjpeg);
00034 if(codec->buffer)
00035 free(codec->buffer);
00036 if(codec->temp_video)
00037 free(codec->temp_video);
00038 free(codec);
00039 return 0;
00040 }
00041
00042 void quicktime_set_jpeg(quicktime_t *file, int quality, int use_float)
00043 {
00044 int i;
00045 char *compressor;
00046
00047 printf("1\n");
00048 for(i = 0; i < file->total_vtracks; i++)
00049 {
00050 if(quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_JPEG) ||
00051 quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_MJPA) ||
00052 quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_RTJ0))
00053 {
00054 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[i].codec)->priv;
00055 codec->quality = quality;
00056 codec->use_float = use_float;
00057 }
00058 }
00059 printf("10\n");
00060 }
00061
00062
00063 static void initialize(quicktime_video_map_t *vtrack)
00064 {
00065 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00066 if(!codec->initialized)
00067 {
00068
00069 codec->mjpeg = mjpeg_new(vtrack->track->tkhd.track_width,
00070 vtrack->track->tkhd.track_height,
00071 1 + (codec->jpeg_type == JPEG_MJPA || codec->jpeg_type == JPEG_MJPB));
00072
00073
00074
00075 if(codec->jpeg_type == JPEG_MJPA &&
00076 !vtrack->track->mdia.minf.stbl.stsd.table[0].fields)
00077 {
00078 vtrack->track->mdia.minf.stbl.stsd.table[0].fields = 2;
00079 vtrack->track->mdia.minf.stbl.stsd.table[0].field_dominance = 1;
00080 }
00081 codec->initialized = 1;
00082 }
00083 }
00084
00085 static int decode(quicktime_t *file,
00086 unsigned char **row_pointers,
00087 int track)
00088 {
00089 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00090 initialize(vtrack);
00091 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00092 quicktime_trak_t *trak = vtrack->track;
00093 mjpeg_t *mjpeg = codec->mjpeg;
00094 long size, field2_offset = 0;
00095 int track_height = trak->tkhd.track_height;
00096 int track_width = trak->tkhd.track_width;
00097 int result = 0;
00098 int field_dominance = trak->mdia.minf.stbl.stsd.table[0].field_dominance;
00099
00100 mjpeg_set_cpus(codec->mjpeg, file->cpus);
00101 if(file->row_span)
00102 mjpeg_set_rowspan(codec->mjpeg, file->row_span);
00103 else
00104 mjpeg_set_rowspan(codec->mjpeg, 0);
00105
00106 quicktime_set_video_position(file, vtrack->current_position, track);
00107 size = quicktime_frame_size(file, vtrack->current_position, track);
00108 codec->buffer_size = size;
00109
00110 if(size > codec->buffer_allocated)
00111 {
00112 codec->buffer_allocated = size;
00113 codec->buffer = realloc(codec->buffer, codec->buffer_allocated);
00114 }
00115
00116 result = !quicktime_read_data(file, codec->buffer, size);
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 if(!result)
00131 {
00132 if(mjpeg_get_fields(mjpeg) == 2)
00133 {
00134 if(file->use_avi)
00135 {
00136 field2_offset = mjpeg_get_avi_field2(codec->buffer,
00137 size,
00138 &field_dominance);
00139 }
00140 else
00141 {
00142 field2_offset = mjpeg_get_quicktime_field2(codec->buffer,
00143 size);
00144
00145 if(!field2_offset)
00146 {
00147 printf("decode: FYI field2_offset=0\n");
00148 field2_offset = mjpeg_get_field2(codec->buffer, size);
00149 }
00150 }
00151 }
00152 else
00153 field2_offset = 0;
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 if(file->in_x == 0 &&
00170 file->in_y == 0 &&
00171 file->in_w == track_width &&
00172 file->in_h == track_height &&
00173 file->out_w == track_width &&
00174 file->out_h == track_height)
00175 {
00176 int i;
00177 mjpeg_decompress(codec->mjpeg,
00178 codec->buffer,
00179 size,
00180 field2_offset,
00181 row_pointers,
00182 row_pointers[0],
00183 row_pointers[1],
00184 row_pointers[2],
00185 file->color_model,
00186 file->cpus);
00187 }
00188 else
00189 {
00190 int i;
00191 unsigned char **temp_rows;
00192 int temp_cmodel = BC_YUV888;
00193 int temp_rowsize = cmodel_calculate_pixelsize(temp_cmodel) * track_width;
00194
00195 if(!codec->temp_video)
00196 codec->temp_video = malloc(temp_rowsize * track_height);
00197 temp_rows = malloc(sizeof(unsigned char*) * track_height);
00198 for(i = 0; i < track_height; i++)
00199 temp_rows[i] = codec->temp_video + i * temp_rowsize;
00200
00201
00202 mjpeg_decompress(codec->mjpeg,
00203 codec->buffer,
00204 size,
00205 field2_offset,
00206 temp_rows,
00207 temp_rows[0],
00208 temp_rows[1],
00209 temp_rows[2],
00210 temp_cmodel,
00211 file->cpus);
00212
00213 cmodel_transfer(row_pointers,
00214 temp_rows,
00215 row_pointers[0],
00216 row_pointers[1],
00217 row_pointers[2],
00218 temp_rows[0],
00219 temp_rows[1],
00220 temp_rows[2],
00221 file->in_x,
00222 file->in_y,
00223 file->in_w,
00224 file->in_h,
00225 0,
00226 0,
00227 file->out_w,
00228 file->out_h,
00229 temp_cmodel,
00230 file->color_model,
00231 0,
00232 track_width,
00233 file->out_w);
00234
00235
00236 free(temp_rows);
00237
00238
00239 }
00240 }
00241
00242
00243 return result;
00244 }
00245
00246 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
00247 {
00248 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00249 initialize(vtrack);
00250 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00251 quicktime_trak_t *trak = vtrack->track;
00252 mjpeg_set_quality(codec->mjpeg, codec->quality);
00253 mjpeg_set_float(codec->mjpeg, codec->use_float);
00254 int64_t offset = quicktime_position(file);
00255 int result = 0;
00256 long field2_offset;
00257 quicktime_atom_t chunk_atom;
00258
00259
00260 mjpeg_set_cpus(codec->mjpeg, file->cpus);
00261
00262 mjpeg_compress(codec->mjpeg,
00263 row_pointers,
00264 row_pointers[0],
00265 row_pointers[1],
00266 row_pointers[2],
00267 file->color_model,
00268 file->cpus);
00269 if(codec->jpeg_type == JPEG_MJPA)
00270 {
00271 if(file->use_avi)
00272 {
00273 mjpeg_insert_avi_markers(&codec->mjpeg->output_data,
00274 &codec->mjpeg->output_size,
00275 &codec->mjpeg->output_allocated,
00276 2,
00277 &field2_offset);
00278 }
00279 else
00280 {
00281 mjpeg_insert_quicktime_markers(&codec->mjpeg->output_data,
00282 &codec->mjpeg->output_size,
00283 &codec->mjpeg->output_allocated,
00284 2,
00285 &field2_offset);
00286 }
00287 }
00288
00289 quicktime_write_chunk_header(file, trak, &chunk_atom);
00290 result = !quicktime_write_data(file,
00291 mjpeg_output_buffer(codec->mjpeg),
00292 mjpeg_output_size(codec->mjpeg));
00293 quicktime_write_chunk_footer(file,
00294 trak,
00295 vtrack->current_chunk,
00296 &chunk_atom,
00297 1);
00298
00299 vtrack->current_chunk++;
00300
00301 return result;
00302 }
00303
00304 static int reads_colormodel(quicktime_t *file,
00305 int colormodel,
00306 int track)
00307 {
00308 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00309 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00310
00311
00312 if(codec->jpeg_type == JPEG_PROGRESSIVE)
00313 {
00314 return (colormodel == BC_RGB888 ||
00315 colormodel == BC_YUV888 ||
00316 colormodel == BC_YUV420P ||
00317 colormodel == BC_YUV422P ||
00318 colormodel == BC_YUV422);
00319 }
00320 else
00321 {
00322 return (colormodel == BC_RGB888 ||
00323 colormodel == BC_YUV888 ||
00324
00325 colormodel == BC_YUV422P ||
00326 colormodel == BC_YUV422);
00327
00328
00329 }
00330 }
00331
00332 static int writes_colormodel(quicktime_t *file,
00333 int colormodel,
00334 int track)
00335 {
00336 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00337 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00338
00339 if(codec->jpeg_type == JPEG_PROGRESSIVE)
00340 {
00341 return (colormodel == BC_RGB888 ||
00342 colormodel == BC_YUV888 ||
00343 colormodel == BC_YUV420P);
00344 }
00345 else
00346 {
00347 return (colormodel == BC_RGB888 ||
00348 colormodel == BC_YUV888 ||
00349 colormodel == BC_YUV422P);
00350 }
00351 }
00352
00353 static int set_parameter(quicktime_t *file,
00354 int track,
00355 char *key,
00356 void *value)
00357 {
00358 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv;
00359
00360 if(!strcasecmp(key, "jpeg_quality"))
00361 {
00362 codec->quality = *(int*)value;
00363 }
00364 else
00365 if(!strcasecmp(key, "jpeg_usefloat"))
00366 {
00367 codec->use_float = *(int*)value;
00368 }
00369 return 0;
00370 }
00371
00372 static void init_codec_common(quicktime_video_map_t *vtrack, char *compressor)
00373 {
00374 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
00375 quicktime_jpeg_codec_t *codec;
00376 int i;
00377
00378 codec = codec_base->priv = calloc(1, sizeof(quicktime_jpeg_codec_t));
00379 if(quicktime_match_32(compressor, QUICKTIME_JPEG))
00380 codec->jpeg_type = JPEG_PROGRESSIVE;
00381 if(quicktime_match_32(compressor, QUICKTIME_MJPA))
00382 codec->jpeg_type = JPEG_MJPA;
00383 codec->quality = 80;
00384 codec->use_float = 0;
00385
00386
00387 codec_base->delete_vcodec = delete_codec;
00388 codec_base->decode_video = decode;
00389 codec_base->encode_video = encode;
00390 codec_base->decode_audio = 0;
00391 codec_base->encode_audio = 0;
00392 codec_base->reads_colormodel = reads_colormodel;
00393 codec_base->writes_colormodel = writes_colormodel;
00394 codec_base->set_parameter = set_parameter;
00395 codec_base->fourcc = compressor;
00396 codec_base->title = (codec->jpeg_type == JPEG_PROGRESSIVE ? "JPEG Photo" : "Motion JPEG A");
00397 codec_base->desc = codec_base->title;
00398
00399 }
00400
00401 void quicktime_init_codec_jpeg(quicktime_video_map_t *vtrack)
00402 {
00403 init_codec_common(vtrack, QUICKTIME_JPEG);
00404 }
00405
00406 void quicktime_init_codec_mjpa(quicktime_video_map_t *vtrack)
00407 {
00408 init_codec_common(vtrack, QUICKTIME_MJPA);
00409 }
00410
00411 void quicktime_init_codec_mjpg(quicktime_video_map_t *vtrack)
00412 {
00413 init_codec_common(vtrack, "MJPG");
00414 }
00415
00416
00417
00418
00419