r665: Merged the official release 2.0.
[cinelerra_cv.git] / quicktime / moov.c
blobbeadcd832d51ec290bc274e5c6698ac566f92400
1 #include "funcprotos.h"
2 #include "quicktime.h"
3 #include "workarounds.h"
6 #include <zlib.h>
9 int quicktime_moov_init(quicktime_moov_t *moov)
11 int i;
13 moov->total_tracks = 0;
14 for(i = 0 ; i < MAXTRACKS; i++) moov->trak[i] = 0;
15 quicktime_mvhd_init(&(moov->mvhd));
16 quicktime_udta_init(&(moov->udta));
17 quicktime_ctab_init(&(moov->ctab));
18 return 0;
21 int quicktime_moov_delete(quicktime_moov_t *moov)
23 int i;
24 while(moov->total_tracks) quicktime_delete_trak(moov);
25 quicktime_mvhd_delete(&(moov->mvhd));
26 quicktime_udta_delete(&(moov->udta));
27 quicktime_ctab_delete(&(moov->ctab));
28 return 0;
31 void quicktime_moov_dump(quicktime_moov_t *moov)
33 int i;
34 printf("movie\n");
35 quicktime_mvhd_dump(&(moov->mvhd));
36 quicktime_udta_dump(&(moov->udta));
37 for(i = 0; i < moov->total_tracks; i++)
38 quicktime_trak_dump(moov->trak[i]);
39 quicktime_ctab_dump(&(moov->ctab));
42 static void* zalloc(void *opaque, unsigned int items, unsigned int size)
44 return calloc(items, size);
47 static void zfree(void *opaque, void *ptr)
49 free(ptr);
52 static int read_cmov(quicktime_t *file,
53 quicktime_atom_t *parent_atom,
54 quicktime_atom_t *moov_atom)
56 quicktime_atom_t leaf_atom;
60 quicktime_atom_read_header(file, &leaf_atom);
62 /* Algorithm used to compress */
63 if(quicktime_atom_is(&leaf_atom, "dcom"))
65 char data[5];
66 //printf("read_cmov 1 %lld\n", quicktime_position(file));
67 quicktime_read_data(file, data, 4);
68 data[4] = 0;
69 if(strcmp(data, "zlib"))
71 fprintf(stderr,
72 "read_cmov: compression '%c%c%c%c' not zlib. Giving up and going to a movie.\n",
73 data[0],
74 data[1],
75 data[2],
76 data[3]);
77 return 1;
80 quicktime_atom_skip(file, &leaf_atom);
82 else
83 /* Size of uncompressed data followed by compressed data */
84 if(quicktime_atom_is(&leaf_atom, "cmvd"))
86 /* Size of uncompressed data */
87 int uncompressed_size = quicktime_read_int32(file);
88 /* Read compressed data */
89 int compressed_size = leaf_atom.end - quicktime_position(file);
90 if(compressed_size > uncompressed_size)
92 fprintf(stderr,
93 "read_cmov: FYI compressed_size=%d uncompressed_size=%d\n",
94 compressed_size,
95 uncompressed_size);
98 unsigned char *data_in = calloc(1, compressed_size);
99 quicktime_read_data(file, data_in, compressed_size);
100 /* Decompress to another buffer */
101 unsigned char *data_out = calloc(1, uncompressed_size + 0x400);
102 z_stream zlib;
103 zlib.zalloc = zalloc;
104 zlib.zfree = zfree;
105 zlib.opaque = NULL;
106 zlib.avail_out = uncompressed_size + 0x400;
107 zlib.next_out = data_out;
108 zlib.avail_in = compressed_size;
109 zlib.next_in = data_in;
110 inflateInit(&zlib);
111 inflate(&zlib, Z_PARTIAL_FLUSH);
112 inflateEnd(&zlib);
113 free(data_in);
114 file->moov_data = data_out;
117 * FILE *test = fopen("/tmp/test", "w");
118 * fwrite(data_out, uncompressed_size, 1, test);
119 * fclose(test);
120 * exit(0);
124 /* Trick library into reading temporary buffer for the moov */
125 file->moov_end = moov_atom->end;
126 file->moov_size = moov_atom->size;
127 moov_atom->end = moov_atom->start + uncompressed_size;
128 moov_atom->size = uncompressed_size;
129 file->old_preload_size = file->preload_size;
130 file->old_preload_buffer = file->preload_buffer;
131 file->old_preload_start = file->preload_start;
132 file->old_preload_end = file->preload_end;
133 file->old_preload_ptr = file->preload_ptr;
134 file->preload_size = uncompressed_size;
135 file->preload_buffer = data_out;
136 file->preload_start = moov_atom->start;
137 file->preload_end = file->preload_start + uncompressed_size;
138 file->preload_ptr = 0;
139 quicktime_set_position(file, file->preload_start + 8);
140 /* Try again */
141 if(quicktime_read_moov(file,
142 &file->moov,
143 moov_atom))
144 return 1;
145 /* Exit the compressed state */
146 moov_atom->size = file->moov_size;
147 moov_atom->end = file->moov_end;
148 file->preload_size = file->old_preload_size;
149 file->preload_buffer = file->old_preload_buffer;
150 file->preload_start = file->old_preload_start;
151 file->preload_end = file->old_preload_end;
152 file->preload_ptr = file->old_preload_ptr;
153 quicktime_set_position(file, moov_atom->end);
155 else
156 quicktime_atom_skip(file, &leaf_atom);
157 }while(quicktime_position(file) < parent_atom->end);
158 return 0;
162 int quicktime_read_moov(quicktime_t *file,
163 quicktime_moov_t *moov,
164 quicktime_atom_t *parent_atom)
166 /* mandatory mvhd */
167 quicktime_atom_t leaf_atom;
169 /* AVI translation: */
170 /* strh -> mvhd */
174 //printf("quicktime_read_moov 1 %llx\n", quicktime_position(file));
175 quicktime_atom_read_header(file, &leaf_atom);
178 * printf("quicktime_read_moov 2 %c%c%c%c\n",
179 * leaf_atom.type[0],
180 * leaf_atom.type[1],
181 * leaf_atom.type[2],
182 * leaf_atom.type[3]);
185 if(quicktime_atom_is(&leaf_atom, "cmov"))
187 file->compressed_moov = 1;
188 if(read_cmov(file, &leaf_atom, parent_atom)) return 1;
189 /* Now were reading the compressed moov atom from the beginning. */
191 else
192 if(quicktime_atom_is(&leaf_atom, "mvhd"))
194 quicktime_read_mvhd(file, &(moov->mvhd), &leaf_atom);
196 else
197 if(quicktime_atom_is(&leaf_atom, "clip"))
199 quicktime_atom_skip(file, &leaf_atom);
201 else
202 if(quicktime_atom_is(&leaf_atom, "trak"))
204 quicktime_trak_t *trak = quicktime_add_trak(file);
205 quicktime_read_trak(file, trak, &leaf_atom);
207 else
208 if(quicktime_atom_is(&leaf_atom, "udta"))
210 quicktime_read_udta(file, &(moov->udta), &leaf_atom);
211 quicktime_atom_skip(file, &leaf_atom);
213 else
214 if(quicktime_atom_is(&leaf_atom, "ctab"))
216 quicktime_read_ctab(file, &(moov->ctab));
218 else
219 quicktime_atom_skip(file, &leaf_atom);
220 }while(quicktime_position(file) < parent_atom->end);
222 return 0;
225 void quicktime_write_moov(quicktime_t *file, quicktime_moov_t *moov)
227 quicktime_atom_t atom;
228 int i;
229 long int64_t_duration = 0;
230 long duration, timescale;
231 int result;
234 // Try moov header immediately
235 file->mdat.atom.end = quicktime_position(file);
236 result = quicktime_atom_write_header(file, &atom, "moov");
238 // Disk full. Rewind and try again
239 if(result)
241 quicktime_set_position(file, file->mdat.atom.end - (int64_t)0x100000);
242 file->mdat.atom.end = quicktime_position(file);
243 quicktime_atom_write_header(file, &atom, "moov");
246 /* get the duration from the int64_t track in the mvhd's timescale */
247 for(i = 0; i < moov->total_tracks; i++)
249 quicktime_trak_fix_counts(file, moov->trak[i]);
250 quicktime_trak_duration(moov->trak[i], &duration, &timescale);
252 duration = (long)((float)duration / timescale * moov->mvhd.time_scale);
254 if(duration > int64_t_duration)
256 int64_t_duration = duration;
259 moov->mvhd.duration = int64_t_duration;
260 moov->mvhd.selection_duration = int64_t_duration;
262 quicktime_write_mvhd(file, &(moov->mvhd));
263 quicktime_write_udta(file, &(moov->udta));
264 for(i = 0; i < moov->total_tracks; i++)
266 quicktime_write_trak(file, moov->trak[i], moov->mvhd.time_scale);
268 /*quicktime_write_ctab(file, &(moov->ctab)); */
270 quicktime_atom_write_footer(file, &atom);
271 // Rewind to end of mdat
272 quicktime_set_position(file, file->mdat.atom.end);
275 void quicktime_update_durations(quicktime_moov_t *moov)
280 int quicktime_shift_offsets(quicktime_moov_t *moov, int64_t offset)
282 int i;
283 for(i = 0; i < moov->total_tracks; i++)
285 quicktime_trak_shift_offsets(moov->trak[i], offset);
287 return 0;