00001 #include "quicktime.h"
00002 #include "jpeglib.h"
00003 #include <setjmp.h>
00004
00005
00006
00007
00008 struct my_error_mgr {
00009 struct jpeg_error_mgr pub;
00010
00011 jmp_buf setjmp_buffer;
00012 };
00013
00014 typedef struct my_error_mgr* my_error_ptr;
00015
00016 METHODDEF(void)
00017 my_error_exit (j_common_ptr cinfo)
00018 {
00019
00020 my_error_ptr myerr = (my_error_ptr) cinfo->err;
00021
00022
00023
00024 (*cinfo->err->output_message) (cinfo);
00025
00026
00027 longjmp(myerr->setjmp_buffer, 1);
00028 }
00029
00030 int quicktime_init_codec_jpeg(quicktime_video_map_t *vtrack)
00031 {
00032 vtrack->codecs.jpeg_codec.quality = 100;
00033 vtrack->codecs.jpeg_codec.use_float = 0;
00034 vtrack->codecs.jpeg_codec.chunk_buffer = 0;
00035 vtrack->codecs.jpeg_codec.chunk_buffer_len = 0;
00036 quicktime_fastjpg_init(&(vtrack->codecs.jpeg_codec.fastjpg));
00037 }
00038
00039 int quicktime_delete_codec_jpeg(quicktime_video_map_t *vtrack)
00040 {
00041 if(vtrack->codecs.jpeg_codec.chunk_buffer)
00042 {
00043 free(vtrack->codecs.jpeg_codec.chunk_buffer);
00044 }
00045 quicktime_fastjpg_delete(&(vtrack->codecs.jpeg_codec.fastjpg));
00046 }
00047
00048 int quicktime_set_jpeg(quicktime_t *file, int quality, int use_float)
00049 {
00050 int i;
00051 char *compressor;
00052
00053 for(i = 0; i < file->total_vtracks; i++)
00054 {
00055 if(quicktime_match_32(quicktime_video_compressor(file, i), QUICKTIME_JPEG))
00056 {
00057 quicktime_jpeg_codec_t *codec = &(file->vtracks[i].codecs.jpeg_codec);
00058 codec->quality = quality;
00059 codec->use_float = use_float;
00060 }
00061 }
00062 }
00063
00064 int quicktime_decode_jpeg(quicktime_t *file, unsigned char **row_pointers, int track)
00065 {
00066 int result = 0;
00067 long i, chunk_size;
00068 quicktime_trak_t *trak = file->vtracks[track].track;
00069 char *chunk;
00070
00071 if(file->vtracks[track].frames_cached)
00072 {
00073 chunk = file->vtracks[track].frame_cache[file->vtracks[track].current_position];
00074 chunk_size = quicktime_frame_size(file, file->vtracks[track].current_position, track);
00075 }
00076 else
00077 {
00078 chunk_size = quicktime_frame_size(file, file->vtracks[track].current_position, track);
00079 if(file->vtracks[track].codecs.jpeg_codec.chunk_buffer)
00080 {
00081 if(file->vtracks[track].codecs.jpeg_codec.chunk_buffer_len < chunk_size)
00082 {
00083 free(file->vtracks[track].codecs.jpeg_codec.chunk_buffer);
00084 file->vtracks[track].codecs.jpeg_codec.chunk_buffer = 0;
00085 }
00086 }
00087 if(!file->vtracks[track].codecs.jpeg_codec.chunk_buffer)
00088 {
00089 file->vtracks[track].codecs.jpeg_codec.chunk_buffer = malloc(chunk_size);
00090 file->vtracks[track].codecs.jpeg_codec.chunk_buffer_len = chunk_size;
00091 }
00092 chunk = file->vtracks[track].codecs.jpeg_codec.chunk_buffer;
00093 quicktime_set_video_position(file, file->vtracks[track].current_position, track);
00094 result = quicktime_read_data(file, chunk, chunk_size);
00095 if(result) result = 0; else result = 1;
00096 }
00097
00098 result = quicktime_fastjpg_decode(chunk,
00099 chunk_size,
00100 row_pointers,
00101 &(file->vtracks[track].codecs.jpeg_codec.fastjpg),
00102 (int)trak->tkhd.track_width,
00103 (int)trak->tkhd.track_height,
00104 0);
00105
00106 return result;
00107 }
00108
00109 int quicktime_encode_jpeg(quicktime_t *file, unsigned char **row_pointers, int track)
00110 {
00111 long offset = quicktime_position(file);
00112 int result = 0;
00113 int i;
00114 quicktime_trak_t *trak = file->vtracks[track].track;
00115 int height = trak->tkhd.track_height;
00116 int width = trak->tkhd.track_width;
00117 struct jpeg_compress_struct jpeg_compress;
00118 struct jpeg_error_mgr jpeg_error;
00119 JSAMPROW row_pointer[1];
00120 long bytes;
00121
00122 jpeg_compress.err = jpeg_std_error(&jpeg_error);
00123 jpeg_create_compress(&jpeg_compress);
00124 jpeg_stdio_dest(&jpeg_compress, quicktime_get_fd(file));
00125 jpeg_compress.image_width = width;
00126 jpeg_compress.image_height = height;
00127 jpeg_compress.input_components = 3;
00128 jpeg_compress.in_color_space = JCS_RGB;
00129 jpeg_set_defaults(&jpeg_compress);
00130 jpeg_set_quality(&jpeg_compress, file->vtracks[track].codecs.jpeg_codec.quality, 0);
00131 if(file->vtracks[track].codecs.jpeg_codec.use_float)
00132 jpeg_compress.dct_method = JDCT_FLOAT;
00133
00134 jpeg_start_compress(&jpeg_compress, TRUE);
00135 while(jpeg_compress.next_scanline < jpeg_compress.image_height)
00136 {
00137 row_pointer[0] = row_pointers[jpeg_compress.next_scanline];
00138 jpeg_write_scanlines(&jpeg_compress, row_pointer, 1);
00139 }
00140 jpeg_finish_compress(&jpeg_compress);
00141 jpeg_destroy((j_common_ptr)&jpeg_compress);
00142
00143 bytes = quicktime_position(file) - offset;
00144 quicktime_update_tables(file,
00145 file->vtracks[track].track,
00146 offset,
00147 file->vtracks[track].current_chunk,
00148 file->vtracks[track].current_position,
00149 1,
00150 bytes);
00151
00152 file->vtracks[track].current_chunk++;
00153 return result;
00154 }