00001 #include <stdio.h>
00002 #include "jpeg_old.h"
00003 #include "quicktime.h"
00004
00005
00006 #define M_SOF0 0xc0
00007 #define M_SOF1 0xc1
00008 #define M_SOF2 0xc2
00009 #define M_SOF3 0xc3
00010 #define M_SOF5 0xc5
00011 #define M_SOF6 0xc6
00012 #define M_SOF7 0xc7
00013 #define M_JPG 0xc8
00014 #define M_SOF9 0xc9
00015 #define M_SOF10 0xca
00016 #define M_SOF11 0xcb
00017 #define M_SOF13 0xcd
00018 #define M_SOF14 0xce
00019 #define M_SOF15 0xcf
00020 #define M_DHT 0xc4
00021 #define M_DAC 0xcc
00022 #define M_RST0 0xd0
00023 #define M_RST1 0xd1
00024 #define M_RST2 0xd2
00025 #define M_RST3 0xd3
00026 #define M_RST4 0xd4
00027 #define M_RST5 0xd5
00028 #define M_RST6 0xd6
00029 #define M_RST7 0xd7
00030 #define M_SOI 0xd8
00031 #define M_EOI 0xd9
00032 #define M_SOS 0xda
00033 #define M_DQT 0xdb
00034 #define M_DNL 0xdc
00035 #define M_DRI 0xdd
00036 #define M_DHP 0xde
00037 #define M_EXP 0xdf
00038 #define M_APP0 0xe0
00039 #define M_APP1 0xe1
00040 #define M_APP2 0xe2
00041 #define M_APP3 0xe3
00042 #define M_APP4 0xe4
00043 #define M_APP5 0xe5
00044 #define M_APP6 0xe6
00045 #define M_APP7 0xe7
00046 #define M_APP8 0xe8
00047 #define M_APP9 0xe9
00048 #define M_APP10 0xea
00049 #define M_APP11 0xeb
00050 #define M_APP12 0xec
00051 #define M_APP13 0xed
00052 #define M_APP14 0xee
00053 #define M_APP15 0xef
00054 #define M_JPG0 0xf0
00055 #define M_JPG13 0xfd
00056 #define M_COM 0xfe
00057 #define M_TEM 0x01
00058 #define M_ERROR 0x100
00059
00060
00061
00062 METHODDEF(void)
00063 my_error_exit (j_common_ptr cinfo)
00064 {
00065
00066 my_error_ptr myerr = (my_error_ptr) cinfo->err;
00067
00068
00069
00070 (*cinfo->err->output_message) (cinfo);
00071
00072
00073 longjmp(myerr->setjmp_buffer, 1);
00074 }
00075
00076 void quicktime_jpeg_delete_compress_engine(mjpa_compress_engine *compressor)
00077 {
00078 jpeg_destroy((j_common_ptr)&(compressor->jpeg_compress));
00079 if(compressor->output_buffer)
00080 free(compressor->output_buffer);
00081 free(compressor);
00082 }
00083
00084
00085 void quicktime_endcompressor_jpeg(mjpa_compress_engine *engine)
00086 {
00087 engine->done = 1;
00088 pthread_mutex_unlock(&(engine->input_lock));
00089 pthread_join(engine->tid, 0);
00090 pthread_mutex_destroy(&(engine->input_lock));
00091 pthread_mutex_destroy(&(engine->output_lock));
00092 }
00093
00094 static int quicktime_delete_codec_jpeg(quicktime_video_map_t *vtrack)
00095 {
00096 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00097 int i;
00098
00099 for(i = 0; i < codec->total_compressors; i++)
00100 {
00101 if(codec->compressors[i])
00102 {
00103 quicktime_endcompressor_jpeg(codec->compressors[i]);
00104 quicktime_jpeg_delete_compress_engine(codec->compressors[i]);
00105 codec->compressors[i] = 0;
00106 }
00107
00108 if(codec->decompressors[i])
00109 {
00110 quicktime_enddecompressor_jpeg(codec->decompressors[i]);
00111 jpeg_destroy_decompress(&(codec->decompressors[i]->jpeg_decompress));
00112
00113 free(codec->decompressors[i]);
00114 codec->decompressors[i] = 0;
00115 }
00116 }
00117 if(codec->input_buffer)
00118 free(codec->input_buffer);
00119 free(codec);
00120 return 0;
00121 }
00122
00123 static inline int quicktime_read_int32_jpeg(char **data, int *length)
00124 {
00125 if(*length < 4) return 0;
00126 *length -= 4;
00127 *data += 4;
00128 return (int)((((unsigned char)(*data)[-4]) << 24) |
00129 (((unsigned char)(*data)[-3]) << 16) |
00130 (((unsigned char)(*data)[-2]) << 8) |
00131 (((unsigned char)(*data)[-1])));
00132 }
00133
00134 static inline int quicktime_write_int32_jpeg(char **data, int *length, int value)
00135 {
00136 if(*length < 4) return 0;
00137 *length -= 4;
00138
00139 *(*data)++ = (unsigned int)(value & 0xff000000) >> 24;
00140 *(*data)++ = (unsigned int)(value & 0xff0000) >> 16;
00141 *(*data)++ = (unsigned int)(value & 0xff00) >> 8;
00142 *(*data)++ = (unsigned char)(value & 0xff);
00143 return 0;
00144 }
00145
00146 static inline int quicktime_read_int16_jpeg(char **data, int *length)
00147 {
00148 if(*length < 2) return 0;
00149 *length -= 2;
00150 *data += 2;
00151 return (((int16_t)((unsigned char)(*data)[-2]) << 8) |
00152 ((unsigned char)(*data)[-1]));
00153 }
00154
00155 static inline int quicktime_readbyte_jpeg(char **data, int *length)
00156 {
00157 if(*length < 1) return 0;
00158 *length -= 1;
00159 *data += 1;
00160 return (unsigned char)(*data)[-1];
00161 }
00162
00163 int quicktime_read_markers_jpeg(quicktime_mjpeg_hdr *mjpeg_hdr, struct jpeg_decompress_struct *jpeg_decompress)
00164 {
00165 int done = 0;
00166 int length;
00167 char *data;
00168 jpeg_saved_marker_ptr marker_ptr;
00169
00170 if(jpeg_decompress)
00171 marker_ptr = jpeg_decompress->marker_list;
00172
00173 while((marker_ptr || !jpeg_decompress) && !done)
00174 {
00175 if((marker_ptr && marker_ptr->marker == JPEG_APP0 + 1) || !jpeg_decompress)
00176 {
00177 if(marker_ptr)
00178 {
00179 length = marker_ptr->data_length;
00180 data = marker_ptr->data;
00181 }
00182 else
00183 {
00184 length = QUICKTIME_JPEG_MARKSIZE;
00185 data = mjpeg_hdr->mjpeg_marker;
00186 }
00187
00188 quicktime_read_int32_jpeg(&data, &length);
00189 quicktime_read_int32_jpeg(&data, &length);
00190 mjpeg_hdr->field_size = quicktime_read_int32_jpeg(&data, &length);
00191 mjpeg_hdr->padded_field_size = quicktime_read_int32_jpeg(&data, &length);
00192 mjpeg_hdr->next_offset = quicktime_read_int32_jpeg(&data, &length);
00193 mjpeg_hdr->quant_offset = quicktime_read_int32_jpeg(&data, &length);
00194 mjpeg_hdr->huffman_offset = quicktime_read_int32_jpeg(&data, &length);
00195 mjpeg_hdr->image_offset = quicktime_read_int32_jpeg(&data, &length);
00196 mjpeg_hdr->scan_offset = quicktime_read_int32_jpeg(&data, &length);
00197 mjpeg_hdr->data_offset = quicktime_read_int32_jpeg(&data, &length);
00198
00199
00200
00201
00202
00203
00204
00205
00206 done = 1;
00207 }
00208 if(marker_ptr) marker_ptr = marker_ptr->next;
00209 }
00210 return 0;
00211 }
00212
00213 static inline void quicktime_skipmarker_jpeg(char **buffer_ptr, int *buffer_size, int *len)
00214 {
00215 if(*len > 0)
00216 {
00217 *buffer_ptr += *len;
00218 *len = 0;
00219 *buffer_size -= *len;
00220 }
00221 }
00222
00223 int quicktime_getmarker_jpeg(char **buffer_ptr, int *buffer_size, int *len)
00224 {
00225 int c, done = 0;
00226
00227 while(!done && *buffer_size > 0)
00228 {
00229 c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
00230
00231 while(!done && c != 0xFF)
00232 {
00233 if(!*buffer_size) done = 2;
00234 c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
00235 }
00236
00237
00238 do
00239 {
00240 if(!*buffer_size) done = 2;
00241 c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
00242 }while (!done && c == 0xFF);
00243
00244
00245 if (c != 0) done = 1;
00246 }
00247
00248 *len = 0;
00249 if(done == 1)
00250 return c;
00251 else
00252 return 0;
00253 }
00254
00255 int quicktime_fixmarker_jpeg(quicktime_mjpeg_hdr *mjpeg_hdr, char *buffer, long output_size, int write_next_offset)
00256 {
00257 char *buffer_ptr = buffer;
00258 int buffer_size = output_size;
00259 int done = 0, offset = 0, app1_offset = 0;
00260 int marker = 0;
00261 int len;
00262
00263 mjpeg_hdr->field_size = 0;
00264 mjpeg_hdr->padded_field_size = 0;
00265 mjpeg_hdr->next_offset = 0;
00266 mjpeg_hdr->quant_offset = 0;
00267 mjpeg_hdr->huffman_offset = 0;
00268 mjpeg_hdr->image_offset = 0;
00269 mjpeg_hdr->scan_offset = 0;
00270 mjpeg_hdr->data_offset = 0;
00271
00272 while(!done && buffer_size > 0)
00273 {
00274 marker = quicktime_getmarker_jpeg(&buffer_ptr, &buffer_size, &len);
00275 offset = buffer_ptr - buffer - 1;
00276 len = 0;
00277
00278 switch(marker)
00279 {
00280 case M_SOI:
00281 len = 0;
00282 break;
00283
00284 case M_DHT:
00285 mjpeg_hdr->huffman_offset = offset - 1;
00286 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size);
00287 if(!mjpeg_hdr->mjpg_kludge)
00288 len -= 2;
00289 break;
00290
00291 case M_DQT:
00292 mjpeg_hdr->quant_offset = offset - 1;
00293 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size);
00294 if(!mjpeg_hdr->mjpg_kludge)
00295 len -= 2;
00296 break;
00297
00298 case M_SOF0:
00299 mjpeg_hdr->image_offset = offset - 1;
00300 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size);
00301 if(!mjpeg_hdr->mjpg_kludge)
00302 len -= 2;
00303 break;
00304
00305 case M_SOS:
00306 mjpeg_hdr->scan_offset = offset - 1;
00307 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size);
00308 if(!mjpeg_hdr->mjpg_kludge)
00309 len -= 2;
00310 mjpeg_hdr->data_offset = offset + len + 3;
00311 done = 1;
00312 break;
00313
00314 case (JPEG_APP0 + 1):
00315 app1_offset = offset + 3;
00316 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size) - 2;
00317 break;
00318
00319 case 0:
00320 case M_EOI:
00321 done = 1;
00322 break;
00323 }
00324
00325 if(!done) quicktime_skipmarker_jpeg(&buffer_ptr, &buffer_size, &len);
00326 }
00327
00328 mjpeg_hdr->field_size = mjpeg_hdr->padded_field_size = mjpeg_hdr->next_offset = output_size;
00329 buffer_ptr = buffer + app1_offset;
00330 buffer_size = output_size - app1_offset;
00331 if(!write_next_offset) mjpeg_hdr->next_offset = 0;
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, 0);
00343 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, QUICKTIME_JPEG_TAG);
00344 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->field_size);
00345 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->padded_field_size);
00346 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->next_offset);
00347 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->quant_offset);
00348 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->huffman_offset);
00349 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->image_offset);
00350 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->scan_offset);
00351 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->data_offset);
00352 return 0;
00353 }
00354
00355 void quicktime_create_mjpa_objects(mjpa_decompress_engine *engine)
00356 {
00357 engine->jpeg_decompress.err = jpeg_std_error(&(engine->jpeg_error.pub));
00358 engine->jpeg_error.pub.error_exit = my_error_exit;
00359
00360 jpeg_create_decompress(&(engine->jpeg_decompress));
00361 }
00362
00363 void quicktime_delete_mjpa_objects(mjpa_decompress_engine *engine)
00364 {
00365 jpeg_destroy_decompress(&(engine->jpeg_decompress));
00366 }
00367
00368
00369 void quicktime_decompressor_jpeg(mjpa_decompress_engine *engine)
00370 {
00371
00372 unsigned char **interlaced_row;
00373 unsigned char **last_row;
00374
00375 while(!engine->done)
00376 {
00377 pthread_mutex_lock(&(engine->input_lock));
00378
00379
00380 if(!engine->done)
00381 {
00382 if(setjmp(engine->jpeg_error.setjmp_buffer))
00383 {
00384
00385 quicktime_delete_mjpa_objects(engine);
00386 quicktime_create_mjpa_objects(engine);
00387 goto finish;
00388 }
00389
00390 jpeg_buffer_src(&(engine->jpeg_decompress), engine->input_ptr, engine->input_size);
00391 if(engine->markers_only)
00392 jpeg_save_markers(&(engine->jpeg_decompress), JPEG_APP0 + 1, QUICKTIME_JPEG_MARKSIZE);
00393
00394 jpeg_read_header(&(engine->jpeg_decompress), TRUE);
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 if(engine->markers_only)
00405 {
00406 quicktime_read_markers_jpeg(&(engine->mjpeg_hdr), &(engine->jpeg_decompress));
00407 engine->field_offset = engine->mjpeg_hdr.next_offset;
00408 pthread_mutex_unlock(&(engine->output_lock));
00409 pthread_mutex_lock(&(engine->input_lock));
00410 }
00411
00412 jpeg_start_decompress(&(engine->jpeg_decompress));
00413 if(!engine->interlaced)
00414 {
00415 while(engine->jpeg_decompress.output_scanline < engine->jpeg_decompress.output_height)
00416 {
00417 jpeg_read_scanlines(&engine->jpeg_decompress,
00418 (JSAMPROW*)&engine->row_pointers[engine->jpeg_decompress.output_scanline],
00419 engine->jpeg_decompress.output_height - engine->jpeg_decompress.output_scanline);
00420 }
00421 }
00422 else
00423 {
00424 interlaced_row = engine->row_pointers;
00425 last_row = &(engine->row_pointers[engine->height]);
00426 while(engine->jpeg_decompress.output_scanline < engine->jpeg_decompress.output_height &&
00427 interlaced_row < last_row)
00428 {
00429 jpeg_read_scanlines(&(engine->jpeg_decompress),
00430 (JSAMPROW*)interlaced_row,
00431 1);
00432
00433 interlaced_row += 2;
00434 }
00435 }
00436 jpeg_finish_decompress(&(engine->jpeg_decompress));
00437 }
00438
00439 finish:
00440 pthread_mutex_unlock(&(engine->output_lock));
00441 }
00442 }
00443
00444 int quicktime_startdecompressor_jpeg(mjpa_decompress_engine *engine)
00445 {
00446 pthread_attr_t attr;
00447 struct sched_param param;
00448 pthread_mutexattr_t mutex_attr;
00449
00450 pthread_mutexattr_init(&mutex_attr);
00451 pthread_mutex_init(&(engine->input_lock), &mutex_attr);
00452 pthread_mutex_lock(&(engine->input_lock));
00453 pthread_mutex_init(&(engine->output_lock), &mutex_attr);
00454 pthread_mutex_lock(&(engine->output_lock));
00455
00456 pthread_attr_init(&attr);
00457 pthread_create(&(engine->tid), &attr, (void*)quicktime_decompressor_jpeg, engine);
00458 return 0;
00459 }
00460
00461 int quicktime_enddecompressor_jpeg(mjpa_decompress_engine *engine)
00462 {
00463 engine->done = 1;
00464 pthread_mutex_unlock(&(engine->input_lock));
00465 pthread_join(engine->tid, 0);
00466 pthread_mutex_destroy(&(engine->input_lock));
00467 pthread_mutex_destroy(&(engine->output_lock));
00468 return 0;
00469 }
00470
00471 int quicktime_decompressfield_jpeg(mjpa_decompress_engine *engine,
00472 char *input_ptr,
00473 long input_size,
00474 unsigned char **row_pointers,
00475 int markers_only,
00476 int resume)
00477 {
00478 engine->markers_only = markers_only;
00479 engine->row_pointers = row_pointers;
00480 engine->input_ptr = input_ptr;
00481 engine->input_size = input_size;
00482 pthread_mutex_unlock(&(engine->input_lock));
00483 return 0;
00484 }
00485
00486 int quicktime_decompresswait_jpeg(mjpa_decompress_engine *engine)
00487 {
00488 pthread_mutex_lock(&(engine->output_lock));
00489 return 0;
00490 }
00491
00492
00493 static int quicktime_decode_jpeg(quicktime_t *file, unsigned char **row_pointers, int track)
00494 {
00495 int result = 0;
00496 register int i;
00497 long color_channels, bytes;
00498 quicktime_trak_t *trak = file->vtracks[track].track;
00499 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00500 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00501 int is_mjpa = codec->jpeg_type == 1;
00502 int is_mjpb = codec->jpeg_type == 2;
00503 int interlaced = is_mjpa || is_mjpb;
00504 int row_offset, field_offset;
00505 unsigned char **interlaced_row, **last_row;
00506 int field_dominance = trak->mdia.minf.stbl.stsd.table[0].field_dominance;
00507 long size;
00508 long size_remaining;
00509 int height = (int)trak->tkhd.track_height;
00510 int width = (int)trak->tkhd.track_width;
00511
00512
00513 for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1); i++)
00514 {
00515 if(!codec->decompressors[i])
00516 {
00517 codec->decompressors[i] = malloc(sizeof(mjpa_decompress_engine));
00518 codec->decompressors[i]->done = 0;
00519 quicktime_create_mjpa_objects(codec->decompressors[i]);
00520 codec->decompressors[i]->is_mjpa = is_mjpa;
00521 codec->decompressors[i]->mjpeg_hdr.mjpg_kludge = 0;
00522 codec->decompressors[i]->interlaced = interlaced;
00523 codec->decompressors[i]->width = width;
00524 codec->decompressors[i]->height = height;
00525 codec->decompressors[i]->codec = codec;
00526 quicktime_startdecompressor_jpeg(codec->decompressors[i]);
00527 codec->total_decompressors++;
00528 }
00529 }
00530
00531
00532
00533 quicktime_set_video_position(file, vtrack->current_position, track);
00534 size = quicktime_frame_size(file, vtrack->current_position, track);
00535 if(size > codec->buffer_size && codec->input_buffer)
00536 {
00537 free(codec->input_buffer);
00538 codec->input_buffer = 0;
00539 }
00540 if(!codec->input_buffer)
00541 {
00542 codec->input_buffer = malloc(size);
00543 codec->buffer_size = size;
00544 }
00545 result = quicktime_read_data(file, codec->input_buffer, size);
00546 result = !result;
00547
00548
00549 if(field_dominance >= 2 && interlaced)
00550 row_offset = 1;
00551 else
00552 row_offset = 0;
00553
00554 field_offset = 0;
00555 for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; i++)
00556 {
00557 interlaced_row = row_pointers + row_offset;
00558
00559 if(i > 0) size_remaining = size - field_offset;
00560 else
00561 size_remaining = size;
00562
00563 quicktime_decompressfield_jpeg(codec->decompressors[i],
00564 codec->input_buffer + field_offset,
00565 size_remaining,
00566 interlaced_row,
00567 (interlaced && i == 0),
00568 0);
00569
00570 if(interlaced && i == 0)
00571 {
00572
00573 quicktime_decompresswait_jpeg(codec->decompressors[i]);
00574 field_offset = codec->decompressors[i]->field_offset;
00575 quicktime_decompressfield_jpeg(codec->decompressors[i],
00576 codec->input_buffer,
00577 field_offset,
00578 interlaced_row,
00579 0,
00580 1);
00581 }
00582
00583
00584 if(file->cpus < 2)
00585 {
00586 quicktime_decompresswait_jpeg(codec->decompressors[i]);
00587 }
00588
00589 row_offset ^= 1;
00590 }
00591
00592
00593 for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result && file->cpus > 1; i++)
00594 {
00595 quicktime_decompresswait_jpeg(codec->decompressors[i]);
00596 }
00597
00598 return result;
00599 }
00600
00601
00602 unsigned char* quicktime_compress_jpeg(mjpa_compress_engine *engine,
00603 unsigned char **row_pointers,
00604 long *image_size,
00605 int write_next_offset)
00606 {
00607 unsigned char **interlaced_row, **last_row;
00608
00609 last_row = &row_pointers[engine->height - 1];
00610 engine->output_size = 0;
00611 jpeg_buffer_dest(&(engine->jpeg_compress), engine);
00612
00613
00614 jpeg_start_compress(&(engine->jpeg_compress), TRUE);
00615
00616
00617 if(engine->is_mjpa)
00618 {
00619 jpeg_write_marker(&(engine->jpeg_compress),
00620 JPEG_APP0 + 1,
00621 engine->mjpeg_hdr.mjpeg_marker,
00622 QUICKTIME_JPEG_MARKSIZE);
00623 }
00624
00625 if(!engine->interlaced)
00626 {
00627 while(engine->jpeg_compress.next_scanline < engine->jpeg_compress.image_height)
00628 {
00629 jpeg_write_scanlines(&engine->jpeg_compress,
00630 &(row_pointers[engine->jpeg_compress.next_scanline]),
00631 engine->jpeg_compress.image_height - engine->jpeg_compress.next_scanline);
00632 }
00633 }
00634 else
00635 {
00636 interlaced_row = row_pointers;
00637 while(engine->jpeg_compress.next_scanline < engine->jpeg_compress.image_height)
00638 {
00639 if(interlaced_row > last_row) interlaced_row = last_row;
00640 jpeg_write_scanlines(&engine->jpeg_compress,
00641 (JSAMPROW*)interlaced_row,
00642 1);
00643
00644 interlaced_row += 2;
00645 }
00646 }
00647 jpeg_finish_compress(&engine->jpeg_compress);
00648
00649 if(engine->is_mjpa)
00650 {
00651
00652 quicktime_fixmarker_jpeg(&(engine->mjpeg_hdr),
00653 engine->output_buffer,
00654 engine->output_size,
00655 write_next_offset);
00656 }
00657 *image_size = engine->output_size;
00658 return engine->output_buffer;
00659 }
00660
00661
00662 void quicktime_compressor_jpeg(mjpa_compress_engine *engine)
00663 {
00664 long fake_size;
00665
00666
00667 while(!engine->done)
00668 {
00669 pthread_mutex_lock(&(engine->input_lock));
00670
00671 if(!engine->done)
00672 {
00673
00674 quicktime_compress_jpeg(engine, engine->row_pointers, &fake_size, engine->write_next_offset);
00675 pthread_mutex_unlock(&(engine->output_lock));
00676 }
00677 }
00678 }
00679
00680 void quicktime_startcompressor_jpeg(mjpa_compress_engine *engine)
00681 {
00682 pthread_attr_t attr;
00683 struct sched_param param;
00684 pthread_mutexattr_t mutex_attr;
00685
00686 pthread_mutexattr_init(&mutex_attr);
00687 pthread_mutex_init(&(engine->input_lock), &mutex_attr);
00688 pthread_mutex_lock(&(engine->input_lock));
00689 pthread_mutex_init(&(engine->output_lock), &mutex_attr);
00690 pthread_mutex_lock(&(engine->output_lock));
00691
00692 pthread_attr_init(&attr);
00693 pthread_create(&(engine->tid), &attr, (void*)quicktime_compressor_jpeg, engine);
00694 }
00695
00696 void quicktime_compressfield_jpeg(mjpa_compress_engine *engine,
00697 unsigned char **row_pointers, int write_next_offset)
00698 {
00699 engine->row_pointers = row_pointers;
00700 engine->write_next_offset = write_next_offset;
00701 pthread_mutex_unlock(&(engine->input_lock));
00702 }
00703
00704 void quicktime_compresswait_jpeg(mjpa_compress_engine *engine)
00705 {
00706 pthread_mutex_lock(&(engine->output_lock));
00707 }
00708
00709 mjpa_compress_engine* quicktime_jpeg_new_compress_engine(int width,
00710 int height,
00711 int quality,
00712 int use_float,
00713 int interlaced,
00714 int is_mjpa,
00715 int field_number)
00716 {
00717 mjpa_compress_engine *new_compressor;
00718
00719 new_compressor = malloc(sizeof(mjpa_compress_engine));
00720 new_compressor->output_buffer = malloc(512);
00721 new_compressor->output_allocated = 512;
00722 new_compressor->output_size = 0;
00723 new_compressor->row_pointers = 0;
00724 new_compressor->write_next_offset = 0;
00725 new_compressor->done = 0;
00726
00727 new_compressor->jpeg_compress.err = jpeg_std_error(&(new_compressor->jpeg_error));
00728 jpeg_create_compress(&(new_compressor->jpeg_compress));
00729 new_compressor->jpeg_compress.input_components = 3;
00730 new_compressor->jpeg_compress.in_color_space = JCS_RGB;
00731 jpeg_set_defaults(&(new_compressor->jpeg_compress));
00732 jpeg_set_quality(&(new_compressor->jpeg_compress), quality, 0);
00733 if(use_float)
00734 new_compressor->jpeg_compress.dct_method = JDCT_FLOAT;
00735
00736
00737
00738
00739
00740
00741 if(interlaced)
00742 {
00743
00744 new_compressor->jpeg_compress.comp_info[0].h_samp_factor = 2;
00745 new_compressor->jpeg_compress.comp_info[0].v_samp_factor = 1;
00746 new_compressor->jpeg_compress.comp_info[1].h_samp_factor = 1;
00747 new_compressor->jpeg_compress.comp_info[1].v_samp_factor = 1;
00748 new_compressor->jpeg_compress.comp_info[2].h_samp_factor = 1;
00749 new_compressor->jpeg_compress.comp_info[2].v_samp_factor = 1;
00750 }
00751
00752
00753
00754
00755
00756 new_compressor->jpeg_compress.image_width = width;
00757 new_compressor->jpeg_compress.image_height = !interlaced ? height : (height >> 1);
00758 new_compressor->is_mjpa = is_mjpa;
00759 new_compressor->mjpeg_hdr.mjpg_kludge = 0;
00760 new_compressor->width = width;
00761 new_compressor->height = height;
00762 new_compressor->interlaced = interlaced;
00763 return new_compressor;
00764 }
00765
00766 static int quicktime_encode_jpeg(quicktime_t *file, unsigned char **row_pointers, int track)
00767 {
00768 long offset = quicktime_position(file);
00769 int result = 0;
00770 register int i;
00771 quicktime_trak_t *trak = file->vtracks[track].track;
00772 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00773 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00774 int is_mjpa = codec->jpeg_type == 1;
00775 int is_mjpb = codec->jpeg_type == 2;
00776 int interlaced = is_mjpa || is_mjpb;
00777 int row_offset;
00778 int image_start;
00779 unsigned char **interlaced_row, **last_row;
00780 long bytes;
00781 int height = (int)trak->tkhd.track_height;
00782 int width = (int)trak->tkhd.track_width;
00783
00784
00785 for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1); i++)
00786 {
00787 if(!codec->compressors[i])
00788 {
00789 codec->compressors[i] = quicktime_jpeg_new_compress_engine(width,
00790 height,
00791 codec->quality,
00792 codec->use_float,
00793 interlaced,
00794 is_mjpa,
00795 i);
00796
00797
00798 quicktime_startcompressor_jpeg(codec->compressors[i]);
00799
00800 codec->total_compressors++;
00801 }
00802 }
00803
00804
00805
00806 for(row_offset = 0; row_offset < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; row_offset++)
00807 {
00808 quicktime_compressfield_jpeg(codec->compressors[row_offset],
00809 row_pointers + row_offset, !row_offset);
00810
00811 if(file->cpus < 2 && row_offset < TOTAL_MJPA_COMPRESSORS - 1)
00812 {
00813 quicktime_compresswait_jpeg(codec->compressors[row_offset]);
00814 }
00815 }
00816
00817
00818 for(row_offset = 0; row_offset < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; row_offset++)
00819 {
00820 if(file->cpus > 1 || row_offset == TOTAL_MJPA_COMPRESSORS - 1)
00821 {
00822 quicktime_compresswait_jpeg(codec->compressors[row_offset]);
00823 }
00824
00825 result = quicktime_write_data(file,
00826 codec->compressors[row_offset]->output_buffer,
00827 codec->compressors[row_offset]->output_size);
00828 result = !result;
00829 }
00830
00831 bytes = quicktime_position(file) - offset;
00832 quicktime_update_tables(file,
00833 vtrack->track,
00834 offset,
00835 vtrack->current_chunk,
00836 vtrack->current_position,
00837 1,
00838 bytes);
00839
00840 vtrack->current_chunk++;
00841 return result;
00842 }
00843