r1053: Add Russian translation.
[cinelerra_cv.git] / quicktime / jpeg_old.c
blobc5efc47f588a77207af54318e116699e56da62a5
1 #include <stdio.h>
2 #include "jpeg_old.h"
3 #include "quicktime.h"
5 /* JPEG MARKERS */
6 #define M_SOF0 0xc0
7 #define M_SOF1 0xc1
8 #define M_SOF2 0xc2
9 #define M_SOF3 0xc3
10 #define M_SOF5 0xc5
11 #define M_SOF6 0xc6
12 #define M_SOF7 0xc7
13 #define M_JPG 0xc8
14 #define M_SOF9 0xc9
15 #define M_SOF10 0xca
16 #define M_SOF11 0xcb
17 #define M_SOF13 0xcd
18 #define M_SOF14 0xce
19 #define M_SOF15 0xcf
20 #define M_DHT 0xc4
21 #define M_DAC 0xcc
22 #define M_RST0 0xd0
23 #define M_RST1 0xd1
24 #define M_RST2 0xd2
25 #define M_RST3 0xd3
26 #define M_RST4 0xd4
27 #define M_RST5 0xd5
28 #define M_RST6 0xd6
29 #define M_RST7 0xd7
30 #define M_SOI 0xd8
31 #define M_EOI 0xd9
32 #define M_SOS 0xda
33 #define M_DQT 0xdb
34 #define M_DNL 0xdc
35 #define M_DRI 0xdd
36 #define M_DHP 0xde
37 #define M_EXP 0xdf
38 #define M_APP0 0xe0
39 #define M_APP1 0xe1
40 #define M_APP2 0xe2
41 #define M_APP3 0xe3
42 #define M_APP4 0xe4
43 #define M_APP5 0xe5
44 #define M_APP6 0xe6
45 #define M_APP7 0xe7
46 #define M_APP8 0xe8
47 #define M_APP9 0xe9
48 #define M_APP10 0xea
49 #define M_APP11 0xeb
50 #define M_APP12 0xec
51 #define M_APP13 0xed
52 #define M_APP14 0xee
53 #define M_APP15 0xef
54 #define M_JPG0 0xf0
55 #define M_JPG13 0xfd
56 #define M_COM 0xfe
57 #define M_TEM 0x01
58 #define M_ERROR 0x100
60 /* Buffer and error handling from jpeg-6b examples */
62 METHODDEF(void)
63 my_error_exit (j_common_ptr cinfo)
65 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
66 my_error_ptr myerr = (my_error_ptr) cinfo->err;
68 /* Always display the message. */
69 /* We could postpone this until after returning, if we chose. */
70 (*cinfo->err->output_message) (cinfo);
72 /* Return control to the setjmp point */
73 longjmp(myerr->setjmp_buffer, 1);
76 void quicktime_jpeg_delete_compress_engine(mjpa_compress_engine *compressor)
78 jpeg_destroy((j_common_ptr)&(compressor->jpeg_compress));
79 if(compressor->output_buffer)
80 free(compressor->output_buffer);
81 free(compressor);
85 void quicktime_endcompressor_jpeg(mjpa_compress_engine *engine)
87 engine->done = 1;
88 pthread_mutex_unlock(&(engine->input_lock));
89 pthread_join(engine->tid, 0);
90 pthread_mutex_destroy(&(engine->input_lock));
91 pthread_mutex_destroy(&(engine->output_lock));
94 static int quicktime_delete_codec_jpeg(quicktime_video_map_t *vtrack)
96 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
97 int i;
99 for(i = 0; i < codec->total_compressors; i++)
101 if(codec->compressors[i])
103 quicktime_endcompressor_jpeg(codec->compressors[i]);
104 quicktime_jpeg_delete_compress_engine(codec->compressors[i]);
105 codec->compressors[i] = 0;
108 if(codec->decompressors[i])
110 quicktime_enddecompressor_jpeg(codec->decompressors[i]);
111 jpeg_destroy_decompress(&(codec->decompressors[i]->jpeg_decompress));
113 free(codec->decompressors[i]);
114 codec->decompressors[i] = 0;
117 if(codec->input_buffer)
118 free(codec->input_buffer);
119 free(codec);
120 return 0;
123 static inline int quicktime_read_int32_jpeg(char **data, int *length)
125 if(*length < 4) return 0;
126 *length -= 4;
127 *data += 4;
128 return (int)((((unsigned char)(*data)[-4]) << 24) |
129 (((unsigned char)(*data)[-3]) << 16) |
130 (((unsigned char)(*data)[-2]) << 8) |
131 (((unsigned char)(*data)[-1])));
134 static inline int quicktime_write_int32_jpeg(char **data, int *length, int value)
136 if(*length < 4) return 0;
137 *length -= 4;
139 *(*data)++ = (unsigned int)(value & 0xff000000) >> 24;
140 *(*data)++ = (unsigned int)(value & 0xff0000) >> 16;
141 *(*data)++ = (unsigned int)(value & 0xff00) >> 8;
142 *(*data)++ = (unsigned char)(value & 0xff);
143 return 0;
146 static inline int quicktime_read_int16_jpeg(char **data, int *length)
148 if(*length < 2) return 0;
149 *length -= 2;
150 *data += 2;
151 return (((int16_t)((unsigned char)(*data)[-2]) << 8) |
152 ((unsigned char)(*data)[-1]));
155 static inline int quicktime_readbyte_jpeg(char **data, int *length)
157 if(*length < 1) return 0;
158 *length -= 1;
159 *data += 1;
160 return (unsigned char)(*data)[-1];
163 int quicktime_read_markers_jpeg(quicktime_mjpeg_hdr *mjpeg_hdr, struct jpeg_decompress_struct *jpeg_decompress)
165 int done = 0;
166 int length;
167 char *data;
168 jpeg_saved_marker_ptr marker_ptr;
170 if(jpeg_decompress)
171 marker_ptr = jpeg_decompress->marker_list;
173 while((marker_ptr || !jpeg_decompress) && !done)
175 if((marker_ptr && marker_ptr->marker == JPEG_APP0 + 1) || !jpeg_decompress)
177 if(marker_ptr)
179 length = marker_ptr->data_length;
180 data = marker_ptr->data;
182 else
184 length = QUICKTIME_JPEG_MARKSIZE;
185 data = mjpeg_hdr->mjpeg_marker;
188 quicktime_read_int32_jpeg(&data, &length);
189 quicktime_read_int32_jpeg(&data, &length);
190 mjpeg_hdr->field_size = quicktime_read_int32_jpeg(&data, &length);
191 mjpeg_hdr->padded_field_size = quicktime_read_int32_jpeg(&data, &length);
192 mjpeg_hdr->next_offset = quicktime_read_int32_jpeg(&data, &length);
193 mjpeg_hdr->quant_offset = quicktime_read_int32_jpeg(&data, &length);
194 mjpeg_hdr->huffman_offset = quicktime_read_int32_jpeg(&data, &length);
195 mjpeg_hdr->image_offset = quicktime_read_int32_jpeg(&data, &length);
196 mjpeg_hdr->scan_offset = quicktime_read_int32_jpeg(&data, &length);
197 mjpeg_hdr->data_offset = quicktime_read_int32_jpeg(&data, &length);
198 /* printf("%x %x %x %x %x %x %x %x\n", mjpeg_hdr->field_size, */
199 /* mjpeg_hdr->padded_field_size, */
200 /* mjpeg_hdr->next_offset, */
201 /* mjpeg_hdr->quant_offset, */
202 /* mjpeg_hdr->huffman_offset, */
203 /* mjpeg_hdr->image_offset, */
204 /* mjpeg_hdr->scan_offset, */
205 /* mjpeg_hdr->data_offset); */
206 done = 1;
208 if(marker_ptr) marker_ptr = marker_ptr->next;
210 return 0;
213 static inline void quicktime_skipmarker_jpeg(char **buffer_ptr, int *buffer_size, int *len)
215 if(*len > 0)
217 *buffer_ptr += *len;
218 *len = 0;
219 *buffer_size -= *len;
223 int quicktime_getmarker_jpeg(char **buffer_ptr, int *buffer_size, int *len)
225 int c, done = 0; /* 1 - completion 2 - error */
227 while(!done && *buffer_size > 0)
229 c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
230 /* look for FF */
231 while(!done && c != 0xFF)
233 if(!*buffer_size) done = 2;
234 c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
237 /* now we've got 1 0xFF, keep reading until not 0xFF */
240 if(!*buffer_size) done = 2;
241 c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
242 }while (!done && c == 0xFF);
244 /* not a 00 or FF */
245 if (c != 0) done = 1;
248 *len = 0;
249 if(done == 1)
250 return c;
251 else
252 return 0;
255 int quicktime_fixmarker_jpeg(quicktime_mjpeg_hdr *mjpeg_hdr, char *buffer, long output_size, int write_next_offset)
257 char *buffer_ptr = buffer;
258 int buffer_size = output_size;
259 int done = 0, offset = 0, app1_offset = 0;
260 int marker = 0;
261 int len;
263 mjpeg_hdr->field_size = 0;
264 mjpeg_hdr->padded_field_size = 0;
265 mjpeg_hdr->next_offset = 0;
266 mjpeg_hdr->quant_offset = 0;
267 mjpeg_hdr->huffman_offset = 0;
268 mjpeg_hdr->image_offset = 0;
269 mjpeg_hdr->scan_offset = 0;
270 mjpeg_hdr->data_offset = 0;
272 while(!done && buffer_size > 0)
274 marker = quicktime_getmarker_jpeg(&buffer_ptr, &buffer_size, &len);
275 offset = buffer_ptr - buffer - 1;
276 len = 0;
278 switch(marker)
280 case M_SOI:
281 len = 0;
282 break;
284 case M_DHT:
285 mjpeg_hdr->huffman_offset = offset - 1;
286 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size);
287 if(!mjpeg_hdr->mjpg_kludge)
288 len -= 2;
289 break;
291 case M_DQT:
292 mjpeg_hdr->quant_offset = offset - 1;
293 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size);
294 if(!mjpeg_hdr->mjpg_kludge)
295 len -= 2;
296 break;
298 case M_SOF0:
299 mjpeg_hdr->image_offset = offset - 1;
300 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size);
301 if(!mjpeg_hdr->mjpg_kludge)
302 len -= 2;
303 break;
305 case M_SOS:
306 mjpeg_hdr->scan_offset = offset - 1;
307 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size);
308 if(!mjpeg_hdr->mjpg_kludge)
309 len -= 2;
310 mjpeg_hdr->data_offset = offset + len + 3;
311 done = 1;
312 break;
314 case (JPEG_APP0 + 1):
315 app1_offset = offset + 3;
316 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size) - 2;
317 break;
319 case 0:
320 case M_EOI:
321 done = 1;
322 break;
325 if(!done) quicktime_skipmarker_jpeg(&buffer_ptr, &buffer_size, &len);
328 mjpeg_hdr->field_size = mjpeg_hdr->padded_field_size = mjpeg_hdr->next_offset = output_size;
329 buffer_ptr = buffer + app1_offset;
330 buffer_size = output_size - app1_offset;
331 if(!write_next_offset) mjpeg_hdr->next_offset = 0;
333 /* printf("%d %x %x %x %x %x %x %x %x \n", row_offset, mjpeg_hdr->field_size, */
334 /* mjpeg_hdr->padded_field_size, */
335 /* mjpeg_hdr->next_offset, */
336 /* mjpeg_hdr->quant_offset, */
337 /* mjpeg_hdr->huffman_offset, */
338 /* mjpeg_hdr->image_offset, */
339 /* mjpeg_hdr->scan_offset, */
340 /* mjpeg_hdr->data_offset); */
342 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, 0);
343 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, QUICKTIME_JPEG_TAG);
344 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->field_size);
345 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->padded_field_size);
346 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->next_offset);
347 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->quant_offset);
348 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->huffman_offset);
349 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->image_offset);
350 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->scan_offset);
351 quicktime_write_int32_jpeg(&buffer_ptr, &buffer_size, mjpeg_hdr->data_offset);
352 return 0;
355 void quicktime_create_mjpa_objects(mjpa_decompress_engine *engine)
357 engine->jpeg_decompress.err = jpeg_std_error(&(engine->jpeg_error.pub));
358 engine->jpeg_error.pub.error_exit = my_error_exit;
359 /* Ideally the error handler would be set here but it must be called in a thread */
360 jpeg_create_decompress(&(engine->jpeg_decompress));
363 void quicktime_delete_mjpa_objects(mjpa_decompress_engine *engine)
365 jpeg_destroy_decompress(&(engine->jpeg_decompress));
369 void quicktime_decompressor_jpeg(mjpa_decompress_engine *engine)
371 /* Run continuously */
372 unsigned char **interlaced_row;
373 unsigned char **last_row;
375 while(!engine->done)
377 pthread_mutex_lock(&(engine->input_lock));
379 /* Image decompression core */
380 if(!engine->done)
382 if(setjmp(engine->jpeg_error.setjmp_buffer))
384 /* If we get here, the JPEG code has signaled an error. */
385 quicktime_delete_mjpa_objects(engine);
386 quicktime_create_mjpa_objects(engine);
387 goto finish;
390 jpeg_buffer_src(&(engine->jpeg_decompress), engine->input_ptr, engine->input_size);
391 if(engine->markers_only)
392 jpeg_save_markers(&(engine->jpeg_decompress), JPEG_APP0 + 1, QUICKTIME_JPEG_MARKSIZE);
394 jpeg_read_header(&(engine->jpeg_decompress), TRUE);
396 /* printf("jpeg %d %d %d %d %d %d\n", */
397 /* engine->jpeg_decompress.comp_info[0].h_samp_factor, */
398 /* engine->jpeg_decompress.comp_info[0].v_samp_factor, */
399 /* engine->jpeg_decompress.comp_info[1].h_samp_factor, */
400 /* engine->jpeg_decompress.comp_info[1].v_samp_factor, */
401 /* engine->jpeg_decompress.comp_info[2].h_samp_factor, */
402 /* engine->jpeg_decompress.comp_info[2].v_samp_factor); */
404 if(engine->markers_only)
406 quicktime_read_markers_jpeg(&(engine->mjpeg_hdr), &(engine->jpeg_decompress));
407 engine->field_offset = engine->mjpeg_hdr.next_offset;
408 pthread_mutex_unlock(&(engine->output_lock));
409 pthread_mutex_lock(&(engine->input_lock));
412 jpeg_start_decompress(&(engine->jpeg_decompress));
413 if(!engine->interlaced)
415 while(engine->jpeg_decompress.output_scanline < engine->jpeg_decompress.output_height)
417 jpeg_read_scanlines(&engine->jpeg_decompress,
418 (JSAMPROW*)&engine->row_pointers[engine->jpeg_decompress.output_scanline],
419 engine->jpeg_decompress.output_height - engine->jpeg_decompress.output_scanline);
422 else
424 interlaced_row = engine->row_pointers;
425 last_row = &(engine->row_pointers[engine->height]);
426 while(engine->jpeg_decompress.output_scanline < engine->jpeg_decompress.output_height &&
427 interlaced_row < last_row)
429 jpeg_read_scanlines(&(engine->jpeg_decompress),
430 (JSAMPROW*)interlaced_row,
433 interlaced_row += 2;
436 jpeg_finish_decompress(&(engine->jpeg_decompress));
439 finish:
440 pthread_mutex_unlock(&(engine->output_lock));
444 int quicktime_startdecompressor_jpeg(mjpa_decompress_engine *engine)
446 pthread_attr_t attr;
447 struct sched_param param;
448 pthread_mutexattr_t mutex_attr;
450 pthread_mutexattr_init(&mutex_attr);
451 pthread_mutex_init(&(engine->input_lock), &mutex_attr);
452 pthread_mutex_lock(&(engine->input_lock));
453 pthread_mutex_init(&(engine->output_lock), &mutex_attr);
454 pthread_mutex_lock(&(engine->output_lock));
456 pthread_attr_init(&attr);
457 pthread_create(&(engine->tid), &attr, (void*)quicktime_decompressor_jpeg, engine);
458 return 0;
461 int quicktime_enddecompressor_jpeg(mjpa_decompress_engine *engine)
463 engine->done = 1;
464 pthread_mutex_unlock(&(engine->input_lock));
465 pthread_join(engine->tid, 0);
466 pthread_mutex_destroy(&(engine->input_lock));
467 pthread_mutex_destroy(&(engine->output_lock));
468 return 0;
471 int quicktime_decompressfield_jpeg(mjpa_decompress_engine *engine,
472 char *input_ptr,
473 long input_size,
474 unsigned char **row_pointers,
475 int markers_only,
476 int resume)
478 engine->markers_only = markers_only;
479 engine->row_pointers = row_pointers;
480 engine->input_ptr = input_ptr;
481 engine->input_size = input_size;
482 pthread_mutex_unlock(&(engine->input_lock));
483 return 0;
486 int quicktime_decompresswait_jpeg(mjpa_decompress_engine *engine)
488 pthread_mutex_lock(&(engine->output_lock));
489 return 0;
493 static int quicktime_decode_jpeg(quicktime_t *file, unsigned char **row_pointers, int track)
495 int result = 0;
496 register int i;
497 long color_channels, bytes;
498 quicktime_trak_t *trak = file->vtracks[track].track;
499 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
500 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
501 int is_mjpa = codec->jpeg_type == 1;
502 int is_mjpb = codec->jpeg_type == 2;
503 int interlaced = is_mjpa || is_mjpb;
504 int row_offset, field_offset;
505 unsigned char **interlaced_row, **last_row;
506 int field_dominance = trak->mdia.minf.stbl.stsd.table[0].field_dominance;
507 long size;
508 long size_remaining;
509 int height = (int)trak->tkhd.track_height;
510 int width = (int)trak->tkhd.track_width;
512 /* Create decompression engines as needed */
513 for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1); i++)
515 if(!codec->decompressors[i])
517 codec->decompressors[i] = malloc(sizeof(mjpa_decompress_engine));
518 codec->decompressors[i]->done = 0;
519 quicktime_create_mjpa_objects(codec->decompressors[i]);
520 codec->decompressors[i]->is_mjpa = is_mjpa;
521 codec->decompressors[i]->mjpeg_hdr.mjpg_kludge = 0;
522 codec->decompressors[i]->interlaced = interlaced;
523 codec->decompressors[i]->width = width;
524 codec->decompressors[i]->height = height;
525 codec->decompressors[i]->codec = codec;
526 quicktime_startdecompressor_jpeg(codec->decompressors[i]);
527 codec->total_decompressors++;
531 /* Read the entire chunk from disk. */
533 quicktime_set_video_position(file, vtrack->current_position, track);
534 size = quicktime_frame_size(file, vtrack->current_position, track);
535 if(size > codec->buffer_size && codec->input_buffer)
537 free(codec->input_buffer);
538 codec->input_buffer = 0;
540 if(!codec->input_buffer)
542 codec->input_buffer = malloc(size);
543 codec->buffer_size = size;
545 result = quicktime_read_data(file, codec->input_buffer, size);
546 result = !result;
548 /* Start the decompressors */
549 if(field_dominance >= 2 && interlaced)
550 row_offset = 1;
551 else
552 row_offset = 0;
554 field_offset = 0;
555 for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; i++)
557 interlaced_row = row_pointers + row_offset;
559 if(i > 0) size_remaining = size - field_offset;
560 else
561 size_remaining = size;
563 quicktime_decompressfield_jpeg(codec->decompressors[i],
564 codec->input_buffer + field_offset,
565 size_remaining,
566 interlaced_row,
567 (interlaced && i == 0),
570 if(interlaced && i == 0)
572 /* Get field offset from first field */
573 quicktime_decompresswait_jpeg(codec->decompressors[i]);
574 field_offset = codec->decompressors[i]->field_offset;
575 quicktime_decompressfield_jpeg(codec->decompressors[i],
576 codec->input_buffer,
577 field_offset,
578 interlaced_row,
583 /* Wait for decompressor completion on uniprocessor */
584 if(file->cpus < 2)
586 quicktime_decompresswait_jpeg(codec->decompressors[i]);
589 row_offset ^= 1;
592 /* Wait for decompressor completion */
593 for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result && file->cpus > 1; i++)
595 quicktime_decompresswait_jpeg(codec->decompressors[i]);
598 return result;
601 /* Compress a JPEG field */
602 unsigned char* quicktime_compress_jpeg(mjpa_compress_engine *engine,
603 unsigned char **row_pointers,
604 long *image_size,
605 int write_next_offset)
607 unsigned char **interlaced_row, **last_row;
609 last_row = &row_pointers[engine->height - 1];
610 engine->output_size = 0;
611 jpeg_buffer_dest(&(engine->jpeg_compress), engine);
613 /* Initialize interlaced output */
614 jpeg_start_compress(&(engine->jpeg_compress), TRUE);
616 /* Write a fake MJPA marker */
617 if(engine->is_mjpa)
619 jpeg_write_marker(&(engine->jpeg_compress),
620 JPEG_APP0 + 1,
621 engine->mjpeg_hdr.mjpeg_marker,
622 QUICKTIME_JPEG_MARKSIZE);
625 if(!engine->interlaced)
627 while(engine->jpeg_compress.next_scanline < engine->jpeg_compress.image_height)
629 jpeg_write_scanlines(&engine->jpeg_compress,
630 &(row_pointers[engine->jpeg_compress.next_scanline]),
631 engine->jpeg_compress.image_height - engine->jpeg_compress.next_scanline);
634 else
636 interlaced_row = row_pointers;
637 while(engine->jpeg_compress.next_scanline < engine->jpeg_compress.image_height)
639 if(interlaced_row > last_row) interlaced_row = last_row;
640 jpeg_write_scanlines(&engine->jpeg_compress,
641 (JSAMPROW*)interlaced_row,
644 interlaced_row += 2;
647 jpeg_finish_compress(&engine->jpeg_compress);
649 if(engine->is_mjpa)
651 /* Fix markers and write whole thing */
652 quicktime_fixmarker_jpeg(&(engine->mjpeg_hdr),
653 engine->output_buffer,
654 engine->output_size,
655 write_next_offset);
657 *image_size = engine->output_size;
658 return engine->output_buffer;
661 /* Main loop for JPEG compression */
662 void quicktime_compressor_jpeg(mjpa_compress_engine *engine)
664 long fake_size;
666 /* Run continuously */
667 while(!engine->done)
669 pthread_mutex_lock(&(engine->input_lock));
671 if(!engine->done)
673 /* Image compression core */
674 quicktime_compress_jpeg(engine, engine->row_pointers, &fake_size, engine->write_next_offset);
675 pthread_mutex_unlock(&(engine->output_lock));
680 void quicktime_startcompressor_jpeg(mjpa_compress_engine *engine)
682 pthread_attr_t attr;
683 struct sched_param param;
684 pthread_mutexattr_t mutex_attr;
686 pthread_mutexattr_init(&mutex_attr);
687 pthread_mutex_init(&(engine->input_lock), &mutex_attr);
688 pthread_mutex_lock(&(engine->input_lock));
689 pthread_mutex_init(&(engine->output_lock), &mutex_attr);
690 pthread_mutex_lock(&(engine->output_lock));
692 pthread_attr_init(&attr);
693 pthread_create(&(engine->tid), &attr, (void*)quicktime_compressor_jpeg, engine);
696 void quicktime_compressfield_jpeg(mjpa_compress_engine *engine,
697 unsigned char **row_pointers, int write_next_offset)
699 engine->row_pointers = row_pointers;
700 engine->write_next_offset = write_next_offset;
701 pthread_mutex_unlock(&(engine->input_lock));
704 void quicktime_compresswait_jpeg(mjpa_compress_engine *engine)
706 pthread_mutex_lock(&(engine->output_lock));
709 mjpa_compress_engine* quicktime_jpeg_new_compress_engine(int width,
710 int height,
711 int quality,
712 int use_float,
713 int interlaced,
714 int is_mjpa,
715 int field_number)
717 mjpa_compress_engine *new_compressor;
719 new_compressor = malloc(sizeof(mjpa_compress_engine));
720 new_compressor->output_buffer = malloc(512);
721 new_compressor->output_allocated = 512;
722 new_compressor->output_size = 0;
723 new_compressor->row_pointers = 0;
724 new_compressor->write_next_offset = 0;
725 new_compressor->done = 0;
726 /* Initialize the jpeglib structures here */
727 new_compressor->jpeg_compress.err = jpeg_std_error(&(new_compressor->jpeg_error));
728 jpeg_create_compress(&(new_compressor->jpeg_compress));
729 new_compressor->jpeg_compress.input_components = 3;
730 new_compressor->jpeg_compress.in_color_space = JCS_RGB;
731 jpeg_set_defaults(&(new_compressor->jpeg_compress));
732 jpeg_set_quality(&(new_compressor->jpeg_compress), quality, 0);
733 if(use_float)
734 new_compressor->jpeg_compress.dct_method = JDCT_FLOAT;
736 /* Progression made it twice as slow. */
737 /* jpeg_simple_progression(&(codec->compressors[i]->jpeg_compress)); */
739 /* Changing the sampling to all values but default increased compression time. */
740 /* 211111 sampling is required for playback on the LML33 */
741 if(interlaced)
743 /* Fix sampling for interlaced */
744 new_compressor->jpeg_compress.comp_info[0].h_samp_factor = 2;
745 new_compressor->jpeg_compress.comp_info[0].v_samp_factor = 1;
746 new_compressor->jpeg_compress.comp_info[1].h_samp_factor = 1;
747 new_compressor->jpeg_compress.comp_info[1].v_samp_factor = 1;
748 new_compressor->jpeg_compress.comp_info[2].h_samp_factor = 1;
749 new_compressor->jpeg_compress.comp_info[2].v_samp_factor = 1;
751 /* Huffman optimization saved %5 */
752 /* codec->compressors[i]->jpeg_compress.optimize_coding = TRUE; */
753 /* Omitting tables saved the same %5 */
754 /* jpeg_suppress_tables(&(codec->compressors[i]->jpeg_compress), TRUE); */
756 new_compressor->jpeg_compress.image_width = width;
757 new_compressor->jpeg_compress.image_height = !interlaced ? height : (height >> 1);
758 new_compressor->is_mjpa = is_mjpa;
759 new_compressor->mjpeg_hdr.mjpg_kludge = 0;
760 new_compressor->width = width;
761 new_compressor->height = height;
762 new_compressor->interlaced = interlaced;
763 return new_compressor;
766 static int quicktime_encode_jpeg(quicktime_t *file, unsigned char **row_pointers, int track)
768 long offset = quicktime_position(file);
769 int result = 0;
770 register int i;
771 quicktime_trak_t *trak = file->vtracks[track].track;
772 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
773 quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
774 int is_mjpa = codec->jpeg_type == 1;
775 int is_mjpb = codec->jpeg_type == 2;
776 int interlaced = is_mjpa || is_mjpb;
777 int row_offset;
778 int image_start;
779 unsigned char **interlaced_row, **last_row;
780 long bytes;
781 int height = (int)trak->tkhd.track_height;
782 int width = (int)trak->tkhd.track_width;
784 /* Create compression engines as needed */
785 for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1); i++)
787 if(!codec->compressors[i])
789 codec->compressors[i] = quicktime_jpeg_new_compress_engine(width,
790 height,
791 codec->quality,
792 codec->use_float,
793 interlaced,
794 is_mjpa,
797 /* Start threads waiting */
798 quicktime_startcompressor_jpeg(codec->compressors[i]);
800 codec->total_compressors++;
805 /* Start the compressors on the image fields */
806 for(row_offset = 0; row_offset < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; row_offset++)
808 quicktime_compressfield_jpeg(codec->compressors[row_offset],
809 row_pointers + row_offset, !row_offset);
811 if(file->cpus < 2 && row_offset < TOTAL_MJPA_COMPRESSORS - 1)
813 quicktime_compresswait_jpeg(codec->compressors[row_offset]);
817 /* Wait for the compressors and write to disk */
818 for(row_offset = 0; row_offset < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; row_offset++)
820 if(file->cpus > 1 || row_offset == TOTAL_MJPA_COMPRESSORS - 1)
822 quicktime_compresswait_jpeg(codec->compressors[row_offset]);
825 result = quicktime_write_data(file,
826 codec->compressors[row_offset]->output_buffer,
827 codec->compressors[row_offset]->output_size);
828 result = !result;
831 bytes = quicktime_position(file) - offset;
832 quicktime_update_tables(file,
833 vtrack->track,
834 offset,
835 vtrack->current_chunk,
836 vtrack->current_position,
838 bytes);
840 vtrack->current_chunk++;
841 return result;