00001 #include "funcprotos.h"
00002 #include "quicktime.h"
00003 #include "workarounds.h"
00004
00005
00006 #include <zlib.h>
00007
00008
00009 int quicktime_moov_init(quicktime_moov_t *moov)
00010 {
00011 int i;
00012
00013 moov->total_tracks = 0;
00014 for(i = 0 ; i < MAXTRACKS; i++) moov->trak[i] = 0;
00015 quicktime_mvhd_init(&(moov->mvhd));
00016 quicktime_udta_init(&(moov->udta));
00017 quicktime_ctab_init(&(moov->ctab));
00018 return 0;
00019 }
00020
00021 int quicktime_moov_delete(quicktime_moov_t *moov)
00022 {
00023 int i;
00024 while(moov->total_tracks) quicktime_delete_trak(moov);
00025 quicktime_mvhd_delete(&(moov->mvhd));
00026 quicktime_udta_delete(&(moov->udta));
00027 quicktime_ctab_delete(&(moov->ctab));
00028 return 0;
00029 }
00030
00031 void quicktime_moov_dump(quicktime_moov_t *moov)
00032 {
00033 int i;
00034 printf("movie\n");
00035 quicktime_mvhd_dump(&(moov->mvhd));
00036 quicktime_udta_dump(&(moov->udta));
00037 for(i = 0; i < moov->total_tracks; i++)
00038 quicktime_trak_dump(moov->trak[i]);
00039 quicktime_ctab_dump(&(moov->ctab));
00040 }
00041
00042 static void* zalloc(void *opaque, unsigned int items, unsigned int size)
00043 {
00044 return calloc(items, size);
00045 }
00046
00047 static void zfree(void *opaque, void *ptr)
00048 {
00049 free(ptr);
00050 }
00051
00052 static int read_cmov(quicktime_t *file,
00053 quicktime_atom_t *parent_atom,
00054 quicktime_atom_t *moov_atom)
00055 {
00056 quicktime_atom_t leaf_atom;
00057
00058 do
00059 {
00060 quicktime_atom_read_header(file, &leaf_atom);
00061
00062
00063 if(quicktime_atom_is(&leaf_atom, "dcom"))
00064 {
00065 char data[5];
00066
00067 quicktime_read_data(file, data, 4);
00068 data[4] = 0;
00069 if(strcmp(data, "zlib"))
00070 {
00071 fprintf(stderr,
00072 "read_cmov: compression '%c%c%c%c' not zlib. Giving up and going to a movie.\n",
00073 data[0],
00074 data[1],
00075 data[2],
00076 data[3]);
00077 return 1;
00078 }
00079
00080 quicktime_atom_skip(file, &leaf_atom);
00081 }
00082 else
00083
00084 if(quicktime_atom_is(&leaf_atom, "cmvd"))
00085 {
00086
00087 int uncompressed_size = quicktime_read_int32(file);
00088
00089 int compressed_size = leaf_atom.end - quicktime_position(file);
00090 if(compressed_size > uncompressed_size)
00091 {
00092 fprintf(stderr,
00093 "read_cmov: FYI compressed_size=%d uncompressed_size=%d\n",
00094 compressed_size,
00095 uncompressed_size);
00096 }
00097
00098 unsigned char *data_in = calloc(1, compressed_size);
00099 quicktime_read_data(file, data_in, compressed_size);
00100
00101 unsigned char *data_out = calloc(1, uncompressed_size + 0x400);
00102 z_stream zlib;
00103 zlib.zalloc = zalloc;
00104 zlib.zfree = zfree;
00105 zlib.opaque = NULL;
00106 zlib.avail_out = uncompressed_size + 0x400;
00107 zlib.next_out = data_out;
00108 zlib.avail_in = compressed_size;
00109 zlib.next_in = data_in;
00110 inflateInit(&zlib);
00111 inflate(&zlib, Z_PARTIAL_FLUSH);
00112 inflateEnd(&zlib);
00113 free(data_in);
00114 file->moov_data = data_out;
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 file->moov_end = moov_atom->end;
00126 file->moov_size = moov_atom->size;
00127 moov_atom->end = moov_atom->start + uncompressed_size;
00128 moov_atom->size = uncompressed_size;
00129 file->old_preload_size = file->preload_size;
00130 file->old_preload_buffer = file->preload_buffer;
00131 file->old_preload_start = file->preload_start;
00132 file->old_preload_end = file->preload_end;
00133 file->old_preload_ptr = file->preload_ptr;
00134 file->preload_size = uncompressed_size;
00135 file->preload_buffer = data_out;
00136 file->preload_start = moov_atom->start;
00137 file->preload_end = file->preload_start + uncompressed_size;
00138 file->preload_ptr = 0;
00139 quicktime_set_position(file, file->preload_start + 8);
00140
00141 if(quicktime_read_moov(file,
00142 &file->moov,
00143 moov_atom))
00144 return 1;
00145
00146 moov_atom->size = file->moov_size;
00147 moov_atom->end = file->moov_end;
00148 file->preload_size = file->old_preload_size;
00149 file->preload_buffer = file->old_preload_buffer;
00150 file->preload_start = file->old_preload_start;
00151 file->preload_end = file->old_preload_end;
00152 file->preload_ptr = file->old_preload_ptr;
00153 quicktime_set_position(file, moov_atom->end);
00154 }
00155 else
00156 quicktime_atom_skip(file, &leaf_atom);
00157 }while(quicktime_position(file) < parent_atom->end);
00158 return 0;
00159 }
00160
00161
00162 int quicktime_read_moov(quicktime_t *file,
00163 quicktime_moov_t *moov,
00164 quicktime_atom_t *parent_atom)
00165 {
00166
00167 quicktime_atom_t leaf_atom;
00168
00169
00170
00171
00172 do
00173 {
00174
00175 quicktime_atom_read_header(file, &leaf_atom);
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 if(quicktime_atom_is(&leaf_atom, "cmov"))
00186 {
00187 file->compressed_moov = 1;
00188 if(read_cmov(file, &leaf_atom, parent_atom)) return 1;
00189
00190 }
00191 else
00192 if(quicktime_atom_is(&leaf_atom, "mvhd"))
00193 {
00194 quicktime_read_mvhd(file, &(moov->mvhd), &leaf_atom);
00195 }
00196 else
00197 if(quicktime_atom_is(&leaf_atom, "clip"))
00198 {
00199 quicktime_atom_skip(file, &leaf_atom);
00200 }
00201 else
00202 if(quicktime_atom_is(&leaf_atom, "trak"))
00203 {
00204 quicktime_trak_t *trak = quicktime_add_trak(file);
00205 quicktime_read_trak(file, trak, &leaf_atom);
00206 }
00207 else
00208 if(quicktime_atom_is(&leaf_atom, "udta"))
00209 {
00210 quicktime_read_udta(file, &(moov->udta), &leaf_atom);
00211 quicktime_atom_skip(file, &leaf_atom);
00212 }
00213 else
00214 if(quicktime_atom_is(&leaf_atom, "ctab"))
00215 {
00216 quicktime_read_ctab(file, &(moov->ctab));
00217 }
00218 else
00219 quicktime_atom_skip(file, &leaf_atom);
00220 }while(quicktime_position(file) < parent_atom->end);
00221
00222 return 0;
00223 }
00224
00225 void quicktime_write_moov(quicktime_t *file, quicktime_moov_t *moov)
00226 {
00227 quicktime_atom_t atom;
00228 int i;
00229 long int64_t_duration = 0;
00230 long duration, timescale;
00231 int result;
00232
00233
00234
00235 file->mdat.atom.end = quicktime_position(file);
00236 result = quicktime_atom_write_header(file, &atom, "moov");
00237
00238
00239 if(result)
00240 {
00241 quicktime_set_position(file, file->mdat.atom.end - (int64_t)0x100000);
00242 file->mdat.atom.end = quicktime_position(file);
00243 quicktime_atom_write_header(file, &atom, "moov");
00244 }
00245
00246
00247 for(i = 0; i < moov->total_tracks; i++)
00248 {
00249 quicktime_trak_fix_counts(file, moov->trak[i]);
00250 quicktime_trak_duration(moov->trak[i], &duration, ×cale);
00251
00252 duration = (long)((float)duration / timescale * moov->mvhd.time_scale);
00253
00254 if(duration > int64_t_duration)
00255 {
00256 int64_t_duration = duration;
00257 }
00258 }
00259 moov->mvhd.duration = int64_t_duration;
00260 moov->mvhd.selection_duration = int64_t_duration;
00261
00262 quicktime_write_mvhd(file, &(moov->mvhd));
00263 quicktime_write_udta(file, &(moov->udta));
00264 for(i = 0; i < moov->total_tracks; i++)
00265 {
00266 quicktime_write_trak(file, moov->trak[i], moov->mvhd.time_scale);
00267 }
00268
00269
00270 quicktime_atom_write_footer(file, &atom);
00271
00272 quicktime_set_position(file, file->mdat.atom.end);
00273 }
00274
00275 void quicktime_update_durations(quicktime_moov_t *moov)
00276 {
00277
00278 }
00279
00280 int quicktime_shift_offsets(quicktime_moov_t *moov, int64_t offset)
00281 {
00282 int i;
00283 for(i = 0; i < moov->total_tracks; i++)
00284 {
00285 quicktime_trak_shift_offsets(moov->trak[i], offset);
00286 }
00287 return 0;
00288 }