r858: Merge 2.1:
[cinelerra_cv/ct.git] / quicktime / avi_riff.c
blob6f7290c319eec80a0c20f59eb3f73731b9c730c4
1 #include "funcprotos.h"
2 #include "quicktime.h"
5 void quicktime_read_riff(quicktime_t *file, quicktime_atom_t *parent_atom)
7 quicktime_riff_t *riff = quicktime_new_riff(file);
8 quicktime_atom_t leaf_atom;
9 int result = 0;
10 int i;
11 char data[5];
13 riff->atom = *parent_atom;
15 // AVI
16 quicktime_read_data(file, data, 4);
17 //printf("quicktime_read_riff 1 %llx\n", quicktime_position(file));
19 // Certain AVI parameters must be copied over to quicktime objects:
20 // hdrl -> moov
21 // movi -> mdat
22 // idx1 -> moov
25 result = quicktime_atom_read_header(file, &leaf_atom);
28 * printf("quicktime_read_riff 1 %llx %llx %c%c%c%c\n",
29 * leaf_atom.start,
30 * leaf_atom.size,
31 * leaf_atom.type[0],
32 * leaf_atom.type[1],
33 * leaf_atom.type[2],
34 * leaf_atom.type[3]);
36 if(!result)
38 if(quicktime_atom_is(&leaf_atom, "LIST"))
40 data[4] = 0;
43 result = !quicktime_read_data(file, data, 4);
46 if(!result)
48 // Got LIST 'hdrl'
49 if(quicktime_match_32(data, "hdrl"))
52 // No size here.
53 //printf("quicktime_read_riff 10 %llx\n", quicktime_position(file));
54 quicktime_read_hdrl(file, &riff->hdrl, &leaf_atom);
55 //printf("quicktime_read_riff 20 %llx\n", quicktime_position(file));
57 else
58 // Got LIST 'movi'
59 if(quicktime_match_32(data, "movi"))
61 //printf("quicktime_read_riff 30 %llx\n", quicktime_position(file));
62 quicktime_read_movi(file, &leaf_atom, &riff->movi);
63 //printf("quicktime_read_riff 40 %llx\n", quicktime_position(file));
67 // Skip it
68 quicktime_atom_skip(file, &leaf_atom);
71 else
72 // Got 'movi'
73 if(quicktime_atom_is(&leaf_atom, "movi"))
75 quicktime_read_movi(file, &leaf_atom, &riff->movi);
78 else
79 // Got 'idx1' original index
80 if(quicktime_atom_is(&leaf_atom, "idx1"))
83 //printf("quicktime_read_riff 50 %llx\n", quicktime_position(file));
84 // Preload idx1 here
85 int64_t start_position = quicktime_position(file);
86 long temp_size = leaf_atom.end - start_position;
87 unsigned char *temp = malloc(temp_size);
88 quicktime_set_preload(file,
89 (temp_size < 0x100000) ? 0x100000 : temp_size);
90 quicktime_read_data(file, temp, temp_size);
91 quicktime_set_position(file, start_position);
92 free(temp);
94 // Read idx1
95 quicktime_read_idx1(file, riff, &leaf_atom);
96 //printf("quicktime_read_riff 60 %llx\n", quicktime_position(file));
99 else
100 /* Skip it */
103 quicktime_atom_skip(file, &leaf_atom);
107 }while(!result && quicktime_position(file) < parent_atom->end);
109 //printf("quicktime_read_riff 10\n");
115 quicktime_riff_t* quicktime_new_riff(quicktime_t *file)
117 if(file->total_riffs >= MAX_RIFFS)
119 fprintf(stderr, "quicktime_new_riff file->total_riffs >= MAX_RIFFS\n");
120 return 0;
122 else
124 quicktime_riff_t *riff = calloc(1, sizeof(quicktime_riff_t));
125 file->riff[file->total_riffs++] = riff;
126 return riff;
132 void quicktime_delete_riff(quicktime_t *file, quicktime_riff_t *riff)
134 int i = 0;
135 quicktime_delete_hdrl(file, &riff->hdrl);
136 quicktime_delete_movi(file, &riff->movi);
137 quicktime_delete_idx1(&riff->idx1);
138 free(riff);
141 void quicktime_init_riff(quicktime_t *file)
144 // Create new RIFF
145 quicktime_riff_t *riff = quicktime_new_riff(file);
147 // Write riff header
148 // RIFF 'AVI '
149 quicktime_atom_write_header(file, &riff->atom, "RIFF");
150 quicktime_write_char32(file, "AVI ");
152 // Write header list in first RIFF only
153 if(file->total_riffs < 2)
155 quicktime_init_hdrl(file, &riff->hdrl);
156 riff->have_hdrl = 1;
159 quicktime_init_movi(file, riff);
162 void quicktime_finalize_riff(quicktime_t *file, quicktime_riff_t *riff)
164 // Write partial indexes
165 quicktime_finalize_movi(file, &riff->movi);
166 if(riff->have_hdrl)
168 //printf("quicktime_finalize_riff 1\n");
169 quicktime_finalize_hdrl(file, &riff->hdrl);
170 //printf("quicktime_finalize_riff 10\n");
171 // Write original index for first RIFF
172 quicktime_write_idx1(file, &riff->idx1);
173 //printf("quicktime_finalize_riff 100\n");
175 quicktime_atom_write_footer(file, &riff->atom);
181 void quicktime_import_avi(quicktime_t *file)
183 int i, j, k;
184 quicktime_riff_t *first_riff = file->riff[0];
185 quicktime_idx1_t *idx1 = &first_riff->idx1;
186 quicktime_hdrl_t *hdrl = &first_riff->hdrl;
190 /* Determine whether to use idx1 or indx indexes for offsets. */
191 /* idx1 must always be used for keyframes but it also must be */
192 /* ignored for offsets if indx exists. */
195 //printf("quicktime_import_avi 1\n");
196 /* Convert idx1 to keyframes and load offsets and sizes */
198 // This is a check from mplayer that gives us the right strategy
199 // for calculating real offset.
200 // is_odml is not currently set anywhere, but when we will support
201 // odml, this will be ready...
203 int index_format = 0;
205 if(idx1->table_size > 1)
208 if((idx1->table[0].offset < first_riff->movi.atom.start + 4 ||
209 idx1->table[1].offset < first_riff->movi.atom.start + 4) &&
210 !file->is_odml)
211 index_format = 1;
212 else
213 index_format = 0;
216 for(i = 0; i < idx1->table_size; i++)
218 quicktime_idx1table_t *idx1table = idx1->table + i;
219 char *tag = idx1table->tag;
220 int track_number = (tag[0] - '0') * 10 + (tag[1] - '0');
221 if(track_number < file->moov.total_tracks)
223 quicktime_trak_t *trak = file->moov.trak[track_number];
224 int is_audio = trak->mdia.minf.is_audio;
225 int is_video = trak->mdia.minf.is_video;
228 /* Chunk offset */
229 quicktime_stco_t *stco = &trak->mdia.minf.stbl.stco;
230 /* Sample size */
231 quicktime_stsz_t *stsz = &trak->mdia.minf.stbl.stsz;
232 /* Samples per chunk */
233 quicktime_stsc_t *stsc = &trak->mdia.minf.stbl.stsc;
234 /* Sample description */
235 quicktime_stsd_t *stsd = &trak->mdia.minf.stbl.stsd;
240 /* Enter the offset and size no matter what so the sample counts */
241 /* can be used to set keyframes */
242 if (index_format == 1)
243 quicktime_update_stco(stco,
244 stco->total_entries + 1,
245 idx1table->offset + first_riff->movi.atom.start);
246 else
247 quicktime_update_stco(stco,
248 stco->total_entries + 1,
249 idx1table->offset);
251 if(is_video)
253 /* Just get the keyframe flag. don't call quicktime_insert_keyframe because */
254 /* that updates idx1 and we don't have a track map. */
255 int is_keyframe = (idx1table->flags & AVI_KEYFRAME) == AVI_KEYFRAME;
256 if(is_keyframe)
258 quicktime_stss_t *stss = &trak->mdia.minf.stbl.stss;
259 /* This is done before the image size table so this value is right */
260 int frame = stsz->total_entries;
262 /* Expand table */
263 if(stss->entries_allocated <= stss->total_entries)
265 stss->entries_allocated *= 2;
266 stss->table = realloc(stss->table,
267 sizeof(quicktime_stss_table_t) * stss->entries_allocated);
269 stss->table[stss->total_entries++].sample = frame;
272 /* Set image size */
273 quicktime_update_stsz(stsz,
274 stsz->total_entries,
275 idx1table->size);
277 else
278 if(is_audio)
280 /* Set samples per chunk if PCM */
281 if(stsd->table[0].sample_size > 0)
283 quicktime_update_stsc(stsc,
284 stsc->total_entries + 1,
285 idx1table->size *
286 8 /
287 stsd->table[0].sample_size /
288 stsd->table[0].channels);
294 //printf("quicktime_import_avi 10\n");
297 /* Convert super indexes into Quicktime indexes. */
298 /* Append to existing entries if idx1 exists. */
299 /* No keyframes here. */
300 for(i = 0; i < file->moov.total_tracks; i++)
302 quicktime_strl_t *strl = first_riff->hdrl.strl[i];
304 if(strl->have_indx)
306 quicktime_indx_t *indx = &strl->indx;
307 quicktime_trak_t *trak = file->moov.trak[i];
308 quicktime_stco_t *stco = &trak->mdia.minf.stbl.stco;
309 quicktime_stsz_t *stsz = &trak->mdia.minf.stbl.stsz;
310 quicktime_stsc_t *stsc = &trak->mdia.minf.stbl.stsc;
311 quicktime_stsd_t *stsd = &trak->mdia.minf.stbl.stsd;
312 /* Get existing chunk count from the idx1 */
313 int existing_chunks = stco->total_entries;
315 /* Read each indx entry */
316 for(j = 0; j < indx->table_size; j++)
318 quicktime_indxtable_t *indx_table = &indx->table[j];
319 quicktime_ix_t *ix = indx_table->ix;
321 for(k = 0; k < ix->table_size; k++)
323 /* Copy from existing chunk count to end of ix table */
324 if(existing_chunks <= 0)
326 quicktime_ixtable_t *ixtable = &ix->table[k];
328 /* Do the same things that idx1 did to the chunk tables */
329 /* Subtract the super indexes by size of the header. McRoweSoft seems to */
330 /* want the header before the ix offset but after the idx1 offset. */
331 quicktime_update_stco(stco,
332 stco->total_entries + 1,
333 ixtable->relative_offset + ix->base_offset - 8);
334 if(strl->is_video)
336 quicktime_update_stsz(stsz,
337 stsz->total_entries,
338 ixtable->size);
340 else
341 if(strl->is_audio)
343 if(stsd->table[0].sample_size > 0)
345 quicktime_update_stsc(stsc,
346 stsc->total_entries + 1,
347 ixtable->size *
348 8 /
349 stsd->table[0].sample_size /
350 stsd->table[0].channels);
354 else
355 existing_chunks--;
362 //printf("quicktime_import_avi 20\n");
367 /* Set total samples, time to sample, for audio */
368 for(i = 0; i < file->moov.total_tracks; i++)
370 quicktime_trak_t *trak = file->moov.trak[i];
371 quicktime_stsz_t *stsz = &trak->mdia.minf.stbl.stsz;
372 quicktime_stsc_t *stsc = &trak->mdia.minf.stbl.stsc;
373 quicktime_stco_t *stco = &trak->mdia.minf.stbl.stco;
374 quicktime_stts_t *stts = &trak->mdia.minf.stbl.stts;
376 if(trak->mdia.minf.is_audio)
378 quicktime_stsc_table_t *stsc_table = stsc->table;
379 long total_entries = stsc->total_entries;
380 long chunk = stco->total_entries;
381 long sample = 0;
383 if(chunk > 0)
385 sample = quicktime_sample_of_chunk(trak, chunk) +
386 stsc_table[total_entries - 1].samples;
389 stsz->sample_size = 1;
390 stsz->total_entries = sample;
391 stts->table[0].sample_count = sample;
393 else
394 if(trak->mdia.minf.is_video)
396 stsc->total_entries = 1;
397 /* stts has 1 allocation by default */
398 stts->table[0].sample_count = stco->total_entries;
402 //printf("quicktime_import_avi 30\n");