"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/jpeg_old.c" (9 Jan 2007, 24382 Bytes) of package /linux/privat/old/quicktime4linux-2.3-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include <stdio.h>
    2 #include "jpeg_old.h"
    3 #include "quicktime.h"
    4 
    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
   59 
   60 /* Buffer and error handling from jpeg-6b examples */
   61 
   62 METHODDEF(void)
   63 my_error_exit (j_common_ptr cinfo)
   64 {
   65   /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
   66   my_error_ptr myerr = (my_error_ptr) cinfo->err;
   67 
   68   /* Always display the message. */
   69   /* We could postpone this until after returning, if we chose. */
   70   (*cinfo->err->output_message) (cinfo);
   71 
   72   /* Return control to the setjmp point */
   73   longjmp(myerr->setjmp_buffer, 1);
   74 }
   75 
   76 void quicktime_jpeg_delete_compress_engine(mjpa_compress_engine *compressor)
   77 {
   78     jpeg_destroy((j_common_ptr)&(compressor->jpeg_compress));
   79     if(compressor->output_buffer)
   80         free(compressor->output_buffer);
   81     free(compressor);
   82 }
   83 
   84 
   85 void quicktime_endcompressor_jpeg(mjpa_compress_engine *engine)
   86 {
   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));
   92 }
   93 
   94 static int quicktime_delete_codec_jpeg(quicktime_video_map_t *vtrack)
   95 {
   96     quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
   97     int i;
   98 
   99     for(i = 0; i < codec->total_compressors; i++)
  100     {
  101         if(codec->compressors[i])
  102         {
  103             quicktime_endcompressor_jpeg(codec->compressors[i]);
  104             quicktime_jpeg_delete_compress_engine(codec->compressors[i]);
  105             codec->compressors[i] = 0;
  106         }
  107 
  108         if(codec->decompressors[i])
  109         {
  110             quicktime_enddecompressor_jpeg(codec->decompressors[i]);
  111             jpeg_destroy_decompress(&(codec->decompressors[i]->jpeg_decompress));
  112 
  113             free(codec->decompressors[i]);
  114             codec->decompressors[i] = 0;
  115         }
  116     }
  117     if(codec->input_buffer)
  118         free(codec->input_buffer);
  119     free(codec);
  120     return 0;
  121 }
  122 
  123 static inline int quicktime_read_int32_jpeg(char **data, int *length)
  124 {
  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])));
  132 }
  133 
  134 static inline int quicktime_write_int32_jpeg(char **data, int *length, int value)
  135 {
  136     if(*length < 4) return 0;
  137     *length -= 4;
  138 
  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;
  144 }
  145 
  146 static inline int quicktime_read_int16_jpeg(char **data, int *length)
  147 {
  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]));
  153 }
  154 
  155 static inline int quicktime_readbyte_jpeg(char **data, int *length)
  156 {
  157     if(*length < 1) return 0;
  158     *length -= 1;
  159     *data += 1;
  160     return (unsigned char)(*data)[-1];
  161 }
  162 
  163 int quicktime_read_markers_jpeg(quicktime_mjpeg_hdr *mjpeg_hdr, struct jpeg_decompress_struct *jpeg_decompress)
  164 {
  165     int done = 0;
  166     int length;
  167     char *data;
  168     jpeg_saved_marker_ptr marker_ptr;
  169 
  170     if(jpeg_decompress)
  171         marker_ptr = jpeg_decompress->marker_list;
  172 
  173     while((marker_ptr || !jpeg_decompress) && !done)
  174     {
  175         if((marker_ptr && marker_ptr->marker == JPEG_APP0 + 1) || !jpeg_decompress)
  176         {
  177             if(marker_ptr)
  178             {
  179                 length = marker_ptr->data_length;
  180                 data = marker_ptr->data;
  181             }
  182             else
  183             {
  184                 length = QUICKTIME_JPEG_MARKSIZE;
  185                 data = mjpeg_hdr->mjpeg_marker;
  186             }
  187 
  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;
  207         }
  208         if(marker_ptr) marker_ptr = marker_ptr->next;
  209     }
  210     return 0;
  211 }
  212 
  213 static inline void quicktime_skipmarker_jpeg(char **buffer_ptr, int *buffer_size, int *len)
  214 {
  215     if(*len > 0)
  216     {
  217         *buffer_ptr += *len;
  218         *len = 0;
  219         *buffer_size -= *len;
  220     }
  221 }
  222 
  223 int quicktime_getmarker_jpeg(char **buffer_ptr, int *buffer_size, int *len)
  224 {
  225     int c, done = 0;  /* 1 - completion    2 - error */
  226 
  227     while(!done && *buffer_size > 0)
  228     {
  229         c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
  230 /* look for FF */
  231         while(!done && c != 0xFF)
  232         {
  233             if(!*buffer_size) done = 2;
  234             c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
  235         }
  236 
  237 /* now we've got 1 0xFF, keep reading until not 0xFF */
  238         do
  239         {
  240             if(!*buffer_size) done = 2;
  241             c = quicktime_readbyte_jpeg(buffer_ptr, buffer_size);
  242         }while (!done && c == 0xFF);
  243         
  244 /* not a 00 or FF */
  245         if (c != 0) done = 1; 
  246     }
  247 
  248     *len = 0;
  249     if(done == 1) 
  250         return c;
  251     else
  252         return 0;
  253 }
  254 
  255 int quicktime_fixmarker_jpeg(quicktime_mjpeg_hdr *mjpeg_hdr, char *buffer, long output_size, int write_next_offset)
  256 {
  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;
  262 
  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;
  271 
  272     while(!done && buffer_size > 0)
  273     {
  274         marker = quicktime_getmarker_jpeg(&buffer_ptr, &buffer_size, &len);
  275         offset = buffer_ptr - buffer - 1;
  276         len = 0;
  277 
  278         switch(marker)
  279         {
  280             case M_SOI:
  281                 len = 0;
  282                 break;
  283             
  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;
  290             
  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;
  297 
  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;
  304 
  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;
  313 
  314             case (JPEG_APP0 + 1):
  315                 app1_offset = offset + 3;
  316                 len = quicktime_read_int16_jpeg(&buffer_ptr, &buffer_size) - 2;
  317                 break;
  318 
  319             case 0:
  320             case M_EOI:
  321                 done = 1;
  322                 break;
  323         }
  324 
  325         if(!done) quicktime_skipmarker_jpeg(&buffer_ptr, &buffer_size, &len);
  326     }
  327 
  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;
  332 
  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); */
  341 
  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;
  353 }
  354 
  355 void quicktime_create_mjpa_objects(mjpa_decompress_engine *engine)
  356 {
  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));
  361 }
  362 
  363 void quicktime_delete_mjpa_objects(mjpa_decompress_engine *engine)
  364 {
  365     jpeg_destroy_decompress(&(engine->jpeg_decompress));
  366 }
  367 
  368 
  369 void quicktime_decompressor_jpeg(mjpa_decompress_engine *engine)
  370 {
  371 /* Run continuously */
  372     unsigned char **interlaced_row;
  373     unsigned char **last_row;
  374 
  375     while(!engine->done)
  376     {
  377         pthread_mutex_lock(&(engine->input_lock));
  378 
  379 /* Image decompression core */
  380         if(!engine->done)
  381         {
  382             if(setjmp(engine->jpeg_error.setjmp_buffer))
  383             {
  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;
  388             }
  389 
  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);
  393 
  394             jpeg_read_header(&(engine->jpeg_decompress), TRUE);
  395 
  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); */
  403 
  404             if(engine->markers_only)
  405             {
  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));
  410             }
  411 
  412             jpeg_start_decompress(&(engine->jpeg_decompress));
  413             if(!engine->interlaced)
  414             {
  415                 while(engine->jpeg_decompress.output_scanline < engine->jpeg_decompress.output_height)
  416                 {
  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);
  420                 }
  421             }
  422             else
  423             {
  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)
  428                 {
  429                     jpeg_read_scanlines(&(engine->jpeg_decompress), 
  430                         (JSAMPROW*)interlaced_row, 
  431                         1);
  432 
  433                     interlaced_row += 2;
  434                 }
  435             }
  436             jpeg_finish_decompress(&(engine->jpeg_decompress));
  437         }
  438 
  439 finish:
  440         pthread_mutex_unlock(&(engine->output_lock));
  441     }
  442 }
  443 
  444 int quicktime_startdecompressor_jpeg(mjpa_decompress_engine *engine)
  445 {
  446     pthread_attr_t  attr;
  447     struct sched_param param;
  448     pthread_mutexattr_t mutex_attr;
  449 
  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));
  455 
  456     pthread_attr_init(&attr);
  457     pthread_create(&(engine->tid), &attr, (void*)quicktime_decompressor_jpeg, engine);
  458     return 0;
  459 }
  460 
  461 int quicktime_enddecompressor_jpeg(mjpa_decompress_engine *engine)
  462 {
  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;
  469 }
  470 
  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)
  477 {
  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;
  484 }
  485 
  486 int quicktime_decompresswait_jpeg(mjpa_decompress_engine *engine)
  487 {
  488     pthread_mutex_lock(&(engine->output_lock));
  489     return 0;
  490 }
  491 
  492 
  493 static int quicktime_decode_jpeg(quicktime_t *file, unsigned char **row_pointers, int track)
  494 {
  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;
  511 
  512 /* Create decompression engines as needed */
  513     for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1); i++)
  514     {
  515         if(!codec->decompressors[i])
  516         {
  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++;
  528         }
  529     }
  530 
  531 /* Read the entire chunk from disk. */
  532 
  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)
  536     {
  537         free(codec->input_buffer);
  538         codec->input_buffer = 0;
  539     }
  540     if(!codec->input_buffer)
  541     {
  542         codec->input_buffer = malloc(size);
  543         codec->buffer_size = size;
  544     }
  545     result = quicktime_read_data(file, codec->input_buffer, size);
  546     result = !result;
  547 
  548 /* Start the decompressors */
  549     if(field_dominance >= 2 && interlaced) 
  550         row_offset = 1;
  551     else
  552         row_offset = 0;
  553 
  554     field_offset = 0;
  555     for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; i++)
  556     {
  557         interlaced_row = row_pointers + row_offset;
  558 
  559         if(i > 0) size_remaining = size - field_offset;
  560         else
  561         size_remaining = size;
  562 
  563         quicktime_decompressfield_jpeg(codec->decompressors[i], 
  564                         codec->input_buffer + field_offset, 
  565                         size_remaining, 
  566                         interlaced_row, 
  567                         (interlaced && i == 0), 
  568                         0);
  569 
  570         if(interlaced && i == 0)
  571         {
  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, 
  579                         0, 
  580                         1);
  581         }
  582 
  583 /* Wait for decompressor completion on uniprocessor */
  584         if(file->cpus < 2)
  585         {
  586             quicktime_decompresswait_jpeg(codec->decompressors[i]);
  587         }
  588 
  589         row_offset ^= 1;
  590     }
  591 
  592 /* Wait for decompressor completion */
  593     for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result && file->cpus > 1; i++)
  594     {
  595         quicktime_decompresswait_jpeg(codec->decompressors[i]);
  596     }
  597 
  598     return result;
  599 }
  600 
  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)
  606 {
  607     unsigned char **interlaced_row, **last_row;
  608 
  609     last_row = &row_pointers[engine->height - 1];
  610     engine->output_size = 0;
  611     jpeg_buffer_dest(&(engine->jpeg_compress), engine);
  612 
  613 /* Initialize interlaced output */
  614     jpeg_start_compress(&(engine->jpeg_compress), TRUE);
  615 
  616 /* Write a fake MJPA marker */
  617     if(engine->is_mjpa)
  618     {
  619         jpeg_write_marker(&(engine->jpeg_compress), 
  620                     JPEG_APP0 + 1, 
  621                     engine->mjpeg_hdr.mjpeg_marker, 
  622                     QUICKTIME_JPEG_MARKSIZE);
  623     }
  624 
  625     if(!engine->interlaced)
  626     {
  627         while(engine->jpeg_compress.next_scanline < engine->jpeg_compress.image_height)
  628         {
  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);
  632         }
  633     }
  634     else
  635     {
  636         interlaced_row = row_pointers;
  637         while(engine->jpeg_compress.next_scanline < engine->jpeg_compress.image_height)
  638         {
  639             if(interlaced_row > last_row) interlaced_row = last_row;
  640             jpeg_write_scanlines(&engine->jpeg_compress, 
  641                 (JSAMPROW*)interlaced_row, 
  642                 1);
  643 
  644             interlaced_row += 2;
  645         }
  646     }
  647     jpeg_finish_compress(&engine->jpeg_compress);
  648 
  649     if(engine->is_mjpa)
  650     {
  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);
  656     }
  657     *image_size = engine->output_size;
  658     return engine->output_buffer;
  659 }
  660 
  661 /* Main loop for JPEG compression */
  662 void quicktime_compressor_jpeg(mjpa_compress_engine *engine)
  663 {
  664     long fake_size;
  665 
  666 /* Run continuously */
  667     while(!engine->done)
  668     {
  669         pthread_mutex_lock(&(engine->input_lock));
  670 
  671         if(!engine->done)
  672         {
  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));
  676         }
  677     }
  678 }
  679 
  680 void quicktime_startcompressor_jpeg(mjpa_compress_engine *engine)
  681 {
  682     pthread_attr_t  attr;
  683     struct sched_param param;
  684     pthread_mutexattr_t mutex_attr;
  685 
  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));
  691 
  692     pthread_attr_init(&attr);
  693     pthread_create(&(engine->tid), &attr, (void*)quicktime_compressor_jpeg, engine);
  694 }
  695 
  696 void quicktime_compressfield_jpeg(mjpa_compress_engine *engine, 
  697                 unsigned char **row_pointers, int write_next_offset)
  698 {
  699     engine->row_pointers = row_pointers;
  700     engine->write_next_offset = write_next_offset;
  701     pthread_mutex_unlock(&(engine->input_lock));
  702 }
  703 
  704 void quicktime_compresswait_jpeg(mjpa_compress_engine *engine)
  705 {
  706     pthread_mutex_lock(&(engine->output_lock));
  707 }
  708 
  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)
  716 {
  717     mjpa_compress_engine *new_compressor;
  718 
  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;
  735 
  736 /* Progression made it twice as slow.    */
  737 /*          jpeg_simple_progression(&(codec->compressors[i]->jpeg_compress)); */
  738 
  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)
  742     {
  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;
  750     }
  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); */
  755 
  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;
  764 }
  765 
  766 static int quicktime_encode_jpeg(quicktime_t *file, unsigned char **row_pointers, int track)
  767 {
  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;
  783 
  784 /* Create compression engines as needed */
  785     for(i = 0; i < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1); i++)
  786     {
  787         if(!codec->compressors[i])
  788         {
  789             codec->compressors[i] = quicktime_jpeg_new_compress_engine(width, 
  790                                         height, 
  791                                         codec->quality, 
  792                                         codec->use_float,
  793                                         interlaced,
  794                                         is_mjpa,
  795                                         i);
  796 
  797 /* Start threads waiting */
  798             quicktime_startcompressor_jpeg(codec->compressors[i]);
  799 
  800             codec->total_compressors++;
  801         }
  802     }
  803 
  804 
  805 /* Start the compressors on the image fields */
  806     for(row_offset = 0; row_offset < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; row_offset++)
  807     {
  808         quicktime_compressfield_jpeg(codec->compressors[row_offset], 
  809                 row_pointers + row_offset, !row_offset);
  810 
  811         if(file->cpus < 2 && row_offset < TOTAL_MJPA_COMPRESSORS - 1)
  812         {
  813             quicktime_compresswait_jpeg(codec->compressors[row_offset]);
  814         }
  815     }
  816 
  817 /* Wait for the compressors and write to disk */
  818     for(row_offset = 0; row_offset < (interlaced ? TOTAL_MJPA_COMPRESSORS : 1) && !result; row_offset++)
  819     {
  820         if(file->cpus > 1 || row_offset == TOTAL_MJPA_COMPRESSORS - 1)
  821         {
  822             quicktime_compresswait_jpeg(codec->compressors[row_offset]);
  823         }
  824 
  825         result = quicktime_write_data(file, 
  826                     codec->compressors[row_offset]->output_buffer, 
  827                     codec->compressors[row_offset]->output_size);
  828         result = !result;
  829     }
  830 
  831     bytes = quicktime_position(file) - offset;
  832     quicktime_update_tables(file,
  833                         vtrack->track,
  834                         offset,
  835                         vtrack->current_chunk,
  836                         vtrack->current_position,
  837                         1,
  838                         bytes);
  839 
  840     vtrack->current_chunk++;
  841     return result;
  842 }
  843