1 #include "funcprotos.h"
3 #include "workarounds.h"
9 int quicktime_moov_init(quicktime_moov_t
*moov
)
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
));
21 int quicktime_moov_delete(quicktime_moov_t
*moov
)
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
));
31 void quicktime_moov_dump(quicktime_moov_t
*moov
)
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
)
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"))
66 //printf("read_cmov 1 %lld\n", quicktime_position(file));
67 quicktime_read_data(file
, data
, 4);
69 if(strcmp(data
, "zlib"))
72 "read_cmov: compression '%c%c%c%c' not zlib. Giving up and going to a movie.\n",
80 quicktime_atom_skip(file
, &leaf_atom
);
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
)
93 "read_cmov: FYI compressed_size=%d uncompressed_size=%d\n",
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);
103 zlib
.zalloc
= zalloc
;
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
;
111 inflate(&zlib
, Z_PARTIAL_FLUSH
);
114 file
->moov_data
= data_out
;
117 * FILE *test = fopen("/tmp/test", "w");
118 * fwrite(data_out, uncompressed_size, 1, test);
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);
141 if(quicktime_read_moov(file
,
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
);
156 quicktime_atom_skip(file
, &leaf_atom
);
157 }while(quicktime_position(file
) < parent_atom
->end
);
162 int quicktime_read_moov(quicktime_t
*file
,
163 quicktime_moov_t
*moov
,
164 quicktime_atom_t
*parent_atom
)
167 quicktime_atom_t leaf_atom
;
169 /* AVI translation: */
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",
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. */
192 if(quicktime_atom_is(&leaf_atom
, "mvhd"))
194 quicktime_read_mvhd(file
, &(moov
->mvhd
), &leaf_atom
);
197 if(quicktime_atom_is(&leaf_atom
, "clip"))
199 quicktime_atom_skip(file
, &leaf_atom
);
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
);
208 if(quicktime_atom_is(&leaf_atom
, "udta"))
210 quicktime_read_udta(file
, &(moov
->udta
), &leaf_atom
);
211 quicktime_atom_skip(file
, &leaf_atom
);
214 if(quicktime_atom_is(&leaf_atom
, "ctab"))
216 quicktime_read_ctab(file
, &(moov
->ctab
));
219 quicktime_atom_skip(file
, &leaf_atom
);
220 }while(quicktime_position(file
) < parent_atom
->end
);
225 void quicktime_write_moov(quicktime_t
*file
, quicktime_moov_t
*moov
)
227 quicktime_atom_t atom
;
229 long int64_t_duration
= 0;
230 long duration
, timescale
;
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
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
, ×cale
);
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
)
283 for(i
= 0; i
< moov
->total_tracks
; i
++)
285 quicktime_trak_shift_offsets(moov
->trak
[i
], offset
);