00001
00002
00003 #include "colormodels.h"
00004 #include "funcprotos.h"
00005 #include "quicktime.h"
00006
00007
00008 typedef struct
00009 {
00010 unsigned char *work_buffer;
00011 int buffer_size;
00012 unsigned char *output_temp;
00013 } quicktime_rle_codec_t;
00014
00015
00016 static int delete_codec(quicktime_video_map_t *vtrack)
00017 {
00018 quicktime_rle_codec_t *codec;
00019 codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00020 if(codec->work_buffer) free(codec->work_buffer);
00021 if(codec->output_temp) free(codec->output_temp);
00022 free(codec);
00023 }
00024
00025 static int reads_colormodel(quicktime_t *file,
00026 int colormodel,
00027 int track)
00028 {
00029 return (colormodel == BC_RGB888);
00030 }
00031
00032 static int source_cmodel(quicktime_t *file, int track)
00033 {
00034 int depth = quicktime_video_depth(file, track);
00035 if(depth == 24)
00036 return BC_RGB888;
00037 else
00038 return BC_ARGB8888;
00039 }
00040
00041
00042
00043 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
00044 {
00045 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00046 quicktime_trak_t *trak = vtrack->track;
00047 quicktime_rle_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
00048 int depth = quicktime_video_depth(file, track);
00049 int width = trak->tkhd.track_width;
00050 int height = trak->tkhd.track_height;
00051 int size;
00052 int result = 0;
00053 unsigned char *ptr;
00054 int start_line;
00055 int total_lines;
00056 int header;
00057 int row_bytes;
00058 int pixel_size;
00059 unsigned char *row_ptr;
00060 unsigned char *pixel;
00061 unsigned char *buffer_end;
00062 int code;
00063 int r, g, b, i;
00064 int need_temp;
00065 unsigned char **temp_rows = malloc(sizeof(unsigned char*) * height);
00066 int cmodel = source_cmodel(file, track);
00067 int skip;
00068
00069 quicktime_set_video_position(file, vtrack->current_position, track);
00070 size = quicktime_frame_size(file, vtrack->current_position, track);
00071 row_bytes = depth / 8 * width;
00072 pixel_size = depth / 8;
00073
00074 if(size <= 8) return 0;
00075 if(codec->buffer_size < size && codec->work_buffer)
00076 {
00077 free(codec->work_buffer);
00078 codec->work_buffer = 0;
00079 }
00080 if(!codec->work_buffer)
00081 {
00082 codec->work_buffer = malloc(size);
00083 codec->buffer_size = size;
00084 }
00085
00086 if(!quicktime_read_data(file,
00087 codec->work_buffer,
00088 size))
00089 result = -1;
00090
00091 ptr = codec->work_buffer;
00092 buffer_end = ptr + size;
00093
00094
00095 ptr += 4;
00096
00097
00098 header = (ptr[0] << 8) | ptr[1];
00099 ptr += 2;
00100
00101
00102 if(header & 0x0008)
00103 {
00104 start_line = (ptr[0] << 8) | ptr[1];
00105 ptr += 4;
00106 total_lines = (ptr[0] << 8) | ptr[1];
00107 ptr += 4;
00108 }
00109 else
00110
00111 {
00112 start_line = 0;
00113 total_lines = height;
00114 }
00115
00116
00117 if(cmodel != file->color_model ||
00118 file->in_x != 0 ||
00119 file->in_y != 0 ||
00120 file->in_w != width ||
00121 file->in_h != height ||
00122 file->out_w != width ||
00123 file->out_h != height)
00124 need_temp = 1;
00125
00126 if(need_temp)
00127 {
00128 if(!codec->output_temp)
00129 codec->output_temp = calloc(1, height * row_bytes);
00130 row_ptr = codec->output_temp + start_line * row_bytes;
00131 for(i = 0; i < height; i++)
00132 temp_rows[i] = codec->output_temp + i * row_bytes;
00133 }
00134 else
00135 {
00136 row_ptr = row_pointers[start_line];
00137 for(i = 0; i < height; i++)
00138 temp_rows[i] = row_pointers[i];
00139 }
00140
00141 switch(depth)
00142 {
00143 case 24:
00144 while(total_lines--)
00145 {
00146 skip = *ptr++;
00147 pixel = row_ptr + (skip - 1) * pixel_size;
00148
00149 while(ptr < buffer_end &&
00150 (code = (char)*ptr++) != -1)
00151 {
00152 if(code == 0)
00153 {
00154
00155 pixel += (*ptr++ - 1) * pixel_size;
00156 }
00157 else
00158
00159 if(code < 0)
00160 {
00161 code *= -1;
00162 r = *ptr++;
00163 g = *ptr++;
00164 b = *ptr++;
00165 while(code--)
00166 {
00167 *pixel++ = r;
00168 *pixel++ = g;
00169 *pixel++ = b;
00170 }
00171 }
00172 else
00173
00174 {
00175 while(code--)
00176 {
00177 *pixel++ = *ptr++;
00178 *pixel++ = *ptr++;
00179 *pixel++ = *ptr++;
00180 }
00181 }
00182 }
00183
00184
00185 row_ptr += row_bytes;
00186 }
00187 break;
00188 }
00189
00190
00191 if(need_temp)
00192 {
00193 cmodel_transfer(row_pointers,
00194 temp_rows,
00195 row_pointers[0],
00196 row_pointers[1],
00197 row_pointers[2],
00198 0,
00199 0,
00200 0,
00201 file->in_x,
00202 file->in_y,
00203 file->in_w,
00204 file->in_h,
00205 0,
00206 0,
00207 file->out_w,
00208 file->out_h,
00209 cmodel,
00210 file->color_model,
00211 0,
00212 width,
00213 file->out_w);
00214 }
00215
00216 free(temp_rows);
00217
00218 return 0;
00219 }
00220
00221
00222
00223 void quicktime_init_codec_rle(quicktime_video_map_t *vtrack)
00224 {
00225 quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
00226 quicktime_rle_codec_t *codec;
00227 codec_base->priv = calloc(1, sizeof(quicktime_rle_codec_t));
00228 codec_base->delete_vcodec = delete_codec;
00229 codec_base->decode_video = decode;
00230 codec_base->reads_colormodel = reads_colormodel;
00231 codec_base->fourcc = "rle ";
00232 codec_base->title = "RLE";
00233 codec_base->desc = "Run length encoding";
00234
00235 codec = (quicktime_rle_codec_t*)codec_base->priv;
00236 }
00237