r955: Fix the Diffkey icon.
[cinelerra_cv.git] / quicktime / trak.c
blob78d1fd11a530afa0b61e4837c2f86e50a2e230d8
1 #include "funcprotos.h"
2 #include "quicktime.h"
7 int quicktime_trak_init(quicktime_trak_t *trak)
9 quicktime_tkhd_init(&(trak->tkhd));
10 quicktime_edts_init(&(trak->edts));
11 quicktime_mdia_init(&(trak->mdia));
12 return 0;
15 int quicktime_trak_init_video(quicktime_t *file,
16 quicktime_trak_t *trak,
17 int frame_w,
18 int frame_h,
19 float frame_rate,
20 char *compressor)
23 quicktime_tkhd_init_video(file,
24 &(trak->tkhd),
25 frame_w,
26 frame_h);
27 quicktime_mdia_init_video(file,
28 &(trak->mdia),
29 frame_w,
30 frame_h,
31 frame_rate,
32 compressor);
33 quicktime_edts_init_table(&(trak->edts));
35 return 0;
38 int quicktime_trak_init_audio(quicktime_t *file,
39 quicktime_trak_t *trak,
40 int channels,
41 int sample_rate,
42 int bits,
43 char *compressor)
45 quicktime_mdia_init_audio(file, &(trak->mdia),
46 channels,
47 sample_rate,
48 bits,
49 compressor);
50 quicktime_edts_init_table(&(trak->edts));
51 return 0;
54 int quicktime_trak_delete(quicktime_trak_t *trak)
56 quicktime_mdia_delete(&(trak->mdia));
57 quicktime_edts_delete(&(trak->edts));
58 quicktime_tkhd_delete(&(trak->tkhd));
59 return 0;
63 int quicktime_trak_dump(quicktime_trak_t *trak)
65 printf(" track\n");
66 quicktime_tkhd_dump(&(trak->tkhd));
67 quicktime_edts_dump(&(trak->edts));
68 quicktime_mdia_dump(&(trak->mdia));
70 return 0;
73 // Used when reading a file
74 quicktime_trak_t* quicktime_add_trak(quicktime_t *file)
76 quicktime_moov_t *moov = &(file->moov);
77 if(moov->total_tracks < MAXTRACKS)
79 moov->trak[moov->total_tracks] = calloc(1, sizeof(quicktime_trak_t));
80 quicktime_trak_init(moov->trak[moov->total_tracks]);
81 moov->total_tracks++;
83 return moov->trak[moov->total_tracks - 1];
86 int quicktime_delete_trak(quicktime_moov_t *moov)
88 if(moov->total_tracks)
90 moov->total_tracks--;
91 quicktime_trak_delete(moov->trak[moov->total_tracks]);
92 free(moov->trak[moov->total_tracks]);
94 return 0;
98 int quicktime_read_trak(quicktime_t *file, quicktime_trak_t *trak, quicktime_atom_t *trak_atom)
100 quicktime_atom_t leaf_atom;
104 quicktime_atom_read_header(file, &leaf_atom);
106 //printf("quicktime_read_trak %llx %llx\n", quicktime_position(file), quicktime_ftell(file));
107 /* mandatory */
108 if(quicktime_atom_is(&leaf_atom, "tkhd"))
109 { quicktime_read_tkhd(file, &(trak->tkhd)); }
110 else
111 if(quicktime_atom_is(&leaf_atom, "mdia"))
112 { quicktime_read_mdia(file, &(trak->mdia), &leaf_atom); }
113 else
114 /* optional */
115 if(quicktime_atom_is(&leaf_atom, "clip"))
116 { quicktime_atom_skip(file, &leaf_atom); }
117 else
118 if(quicktime_atom_is(&leaf_atom, "matt"))
119 { quicktime_atom_skip(file, &leaf_atom); }
120 else
121 if(quicktime_atom_is(&leaf_atom, "edts"))
122 { quicktime_read_edts(file, &(trak->edts), &leaf_atom); }
123 else
124 if(quicktime_atom_is(&leaf_atom, "load"))
125 { quicktime_atom_skip(file, &leaf_atom); }
126 else
127 if(quicktime_atom_is(&leaf_atom, "tref"))
128 { quicktime_atom_skip(file, &leaf_atom); }
129 else
130 if(quicktime_atom_is(&leaf_atom, "imap"))
131 { quicktime_atom_skip(file, &leaf_atom); }
132 else
133 if(quicktime_atom_is(&leaf_atom, "udta"))
134 { quicktime_atom_skip(file, &leaf_atom); }
135 else
136 quicktime_atom_skip(file, &leaf_atom);
137 //printf("quicktime_read_trak %llx %llx\n", quicktime_position(file), leaf_atom.end);
138 }while(quicktime_position(file) < trak_atom->end);
140 return 0;
143 int quicktime_write_trak(quicktime_t *file,
144 quicktime_trak_t *trak,
145 long moov_time_scale)
147 long duration;
148 long timescale;
149 quicktime_atom_t atom;
150 quicktime_atom_write_header(file, &atom, "trak");
151 quicktime_trak_duration(trak, &duration, &timescale);
153 /*printf("quicktime_write_trak duration %d\n", duration); */
154 /* get duration in movie's units */
155 trak->tkhd.duration = (long)((float)duration / timescale * moov_time_scale);
156 trak->mdia.mdhd.duration = duration;
157 trak->mdia.mdhd.time_scale = timescale;
159 quicktime_write_tkhd(file, &(trak->tkhd));
160 quicktime_write_edts(file, &(trak->edts), trak->tkhd.duration);
161 quicktime_write_mdia(file, &(trak->mdia));
163 quicktime_atom_write_footer(file, &atom);
165 return 0;
168 int64_t quicktime_track_end(quicktime_trak_t *trak)
170 /* get the byte endpoint of the track in the file */
171 int64_t size = 0;
172 int64_t chunk, chunk_offset, chunk_samples, sample;
173 quicktime_stsz_t *stsz = &(trak->mdia.minf.stbl.stsz);
174 quicktime_stsz_table_t *table = stsz->table;
175 quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
176 quicktime_stco_t *stco;
178 /* get the last chunk offset */
179 /* the chunk offsets contain the HEADER_LENGTH themselves */
180 stco = &(trak->mdia.minf.stbl.stco);
181 chunk = stco->total_entries;
182 size = chunk_offset = stco->table[chunk - 1].offset;
184 /* get the number of samples in the last chunk */
185 chunk_samples = stsc->table[stsc->total_entries - 1].samples;
187 /* get the size of last samples */
188 if(stsz->sample_size)
190 /* assume audio so calculate the sample size */
191 size += chunk_samples * stsz->sample_size
192 * trak->mdia.minf.stbl.stsd.table[0].channels
193 * trak->mdia.minf.stbl.stsd.table[0].sample_size / 8;
195 else
197 /* assume video */
198 for(sample = stsz->total_entries - chunk_samples;
199 sample < stsz->total_entries; sample++)
201 size += stsz->table[sample].size;
205 return size;
208 long quicktime_track_samples(quicktime_t *file, quicktime_trak_t *trak)
210 /*printf("file->rd %d file->wr %d\n", file->rd, file->wr); */
211 if(file->wr)
213 /* get the sample count when creating a new file */
214 quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
215 long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
216 long chunk = trak->mdia.minf.stbl.stco.total_entries;
217 long sample;
219 if(chunk)
221 sample = quicktime_sample_of_chunk(trak, chunk);
222 sample += table[total_entries - 1].samples;
224 else
225 sample = 0;
227 return sample;
229 else
231 /* get the sample count when reading only */
232 quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts);
233 int64_t total = 0;
234 int i;
236 if(trak->mdia.minf.is_audio)
239 // Get total sample duration
240 for(i = 0; i < stts->total_entries; i++)
242 total += stts->table[i].sample_count *
243 stts->table[i].sample_duration;
246 return total;
248 else
249 if(trak->mdia.minf.is_video)
251 /* Get total number of samples */
252 for(i = 0; i < stts->total_entries; i++)
254 total += stts->table[i].sample_count;
256 return total;
258 return total;
262 long quicktime_sample_of_chunk(quicktime_trak_t *trak, long chunk)
264 quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
265 long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
266 long chunk1entry, chunk2entry;
267 long chunk1, chunk2, chunks, total = 0;
269 for(chunk1entry = total_entries - 1, chunk2entry = total_entries;
270 chunk1entry >= 0;
271 chunk1entry--, chunk2entry--)
273 chunk1 = table[chunk1entry].chunk;
275 if(chunk > chunk1)
277 if(chunk2entry < total_entries)
279 chunk2 = table[chunk2entry].chunk;
281 if(chunk < chunk2) chunk2 = chunk;
283 else
284 chunk2 = chunk;
286 chunks = chunk2 - chunk1;
288 total += chunks * table[chunk1entry].samples;
292 return total;
295 // For AVI
296 int quicktime_avg_chunk_samples(quicktime_t *file, quicktime_trak_t *trak)
298 int i, chunk = trak->mdia.minf.stbl.stco.total_entries - 1;
299 long total_samples;
301 if(chunk >= 0)
303 total_samples = quicktime_sample_of_chunk(trak, chunk);
304 return total_samples / (chunk + 1);
306 else
308 total_samples = quicktime_track_samples(file, trak);
309 return total_samples;
313 int quicktime_chunk_of_sample(int64_t *chunk_sample,
314 int64_t *chunk,
315 quicktime_trak_t *trak,
316 long sample)
318 quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
319 long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
320 long chunk2entry;
321 long chunk1, chunk2, chunk1samples, range_samples, total = 0;
323 chunk1 = 1;
324 chunk1samples = 0;
325 chunk2entry = 0;
327 if(!total_entries)
329 *chunk_sample = 0;
330 *chunk = 0;
331 return 0;
336 chunk2 = table[chunk2entry].chunk;
337 *chunk = chunk2 - chunk1;
338 range_samples = *chunk * chunk1samples;
340 if(sample < total + range_samples) break;
342 chunk1samples = table[chunk2entry].samples;
343 chunk1 = chunk2;
345 if(chunk2entry < total_entries)
347 chunk2entry++;
348 total += range_samples;
350 }while(chunk2entry < total_entries);
352 if(chunk1samples)
353 *chunk = (sample - total) / chunk1samples + chunk1;
354 else
355 *chunk = 1;
357 *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
358 return 0;
361 int64_t quicktime_chunk_to_offset(quicktime_t *file, quicktime_trak_t *trak, long chunk)
363 quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table;
364 int64_t result = 0;
366 if(trak->mdia.minf.stbl.stco.total_entries &&
367 chunk > trak->mdia.minf.stbl.stco.total_entries)
368 result = table[trak->mdia.minf.stbl.stco.total_entries - 1].offset;
369 else
370 if(trak->mdia.minf.stbl.stco.total_entries)
371 result = table[chunk - 1].offset;
372 else
373 result = HEADER_LENGTH * 2;
375 // Skip chunk header for AVI. Skip it here instead of in read_chunk because some
376 // codecs can't use read_chunk
377 if(file->use_avi)
379 //printf("quicktime_chunk_to_offset 1 %llx %llx\n", result, file->mdat.atom.start);
380 result += 8 + file->mdat.atom.start;
382 return result;
385 long quicktime_offset_to_chunk(int64_t *chunk_offset,
386 quicktime_trak_t *trak,
387 int64_t offset)
389 quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table;
390 int i;
392 for(i = trak->mdia.minf.stbl.stco.total_entries - 1; i >= 0; i--)
394 if(table[i].offset <= offset)
396 *chunk_offset = table[i].offset;
397 return i + 1;
400 *chunk_offset = HEADER_LENGTH * 2;
401 return 1;
404 int quicktime_chunk_bytes(quicktime_t *file,
405 int64_t *chunk_offset,
406 int chunk,
407 quicktime_trak_t *trak)
409 int result;
410 *chunk_offset = quicktime_chunk_to_offset(file, trak, chunk);
411 quicktime_set_position(file, *chunk_offset - 4);
412 result = quicktime_read_int32_le(file);
413 return result;
416 int64_t quicktime_sample_range_size(quicktime_trak_t *trak,
417 int64_t chunk_sample,
418 int64_t sample)
420 int64_t i, total;
421 /* For PCM audio quicktime_sample_rage_size MAKES SENSE */
422 if(trak->mdia.minf.is_audio)
424 // sample_size is in bits, so we divide by 8 at the end
425 return (sample - chunk_sample) *trak->mdia.minf.stbl.stsd.table[0].sample_size*trak->mdia.minf.stbl.stsd.table[0].channels/8;
427 else
429 /* All frames have the same size */
430 if(trak->mdia.minf.stbl.stsz.sample_size)
432 total = (sample - chunk_sample) *
433 trak->mdia.minf.stbl.stsz.sample_size;
435 /* probably video */
436 else
438 for(i = chunk_sample, total = 0; i < sample; i++)
440 total += trak->mdia.minf.stbl.stsz.table[i].size;
444 return total;
447 int64_t quicktime_sample_to_offset(quicktime_t *file,
448 quicktime_trak_t *trak,
449 int64_t sample)
451 int64_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
453 quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample);
454 chunk_offset1 = quicktime_chunk_to_offset(file, trak, chunk);
455 chunk_offset2 = chunk_offset1 +
456 quicktime_sample_range_size(trak, chunk_sample, sample);
457 return chunk_offset2;
460 long quicktime_offset_to_sample(quicktime_trak_t *trak, int64_t offset)
462 int64_t chunk_offset;
463 int64_t chunk = quicktime_offset_to_chunk(&chunk_offset, trak, offset);
464 int64_t chunk_sample = quicktime_sample_of_chunk(trak, chunk);
465 int64_t sample, sample_offset;
466 quicktime_stsz_table_t *table = trak->mdia.minf.stbl.stsz.table;
467 int64_t total_samples = trak->mdia.minf.stbl.stsz.total_entries;
469 if(trak->mdia.minf.stbl.stsz.sample_size)
471 sample = chunk_sample + (offset - chunk_offset) /
472 trak->mdia.minf.stbl.stsz.sample_size;
474 else
475 for(sample = chunk_sample, sample_offset = chunk_offset;
476 sample_offset < offset && sample < total_samples; )
478 sample_offset += table[sample].size;
479 if(sample_offset < offset) sample++;
482 return sample;
485 void quicktime_write_chunk_header(quicktime_t *file,
486 quicktime_trak_t *trak,
487 quicktime_atom_t *chunk)
489 if(file->use_avi)
491 /* Get tag from first riff strl */
492 quicktime_riff_t *first_riff = file->riff[0];
493 quicktime_hdrl_t *hdrl = &first_riff->hdrl;
494 quicktime_strl_t *strl = hdrl->strl[trak->tkhd.track_id - 1];
495 char *tag = strl->tag;
497 /* Create new RIFF object at 1 Gig mark */
498 quicktime_riff_t *riff = file->riff[file->total_riffs - 1];
499 if(quicktime_position(file) - riff->atom.start > 0x40000000)
501 quicktime_finalize_riff(file, riff);
502 quicktime_init_riff(file);
507 /* Write AVI header */
508 quicktime_atom_write_header(file, chunk, tag);
510 else
512 chunk->start = quicktime_position(file);
516 void quicktime_write_chunk_footer(quicktime_t *file,
517 quicktime_trak_t *trak,
518 int current_chunk,
519 quicktime_atom_t *chunk,
520 int samples)
522 int64_t offset = chunk->start;
523 int sample_size = quicktime_position(file) - offset;
526 // Write AVI footer
527 if(file->use_avi)
529 quicktime_atom_write_footer(file, chunk);
531 // Save version 1 index entry for first RIFF only
532 if(file->total_riffs < 2)
534 quicktime_update_idx1table(file,
535 trak,
536 offset,
537 sample_size);
540 // Save partial index entry
541 quicktime_update_ixtable(file,
542 trak,
543 offset,
544 sample_size);
547 if(offset + sample_size > file->mdat.atom.size)
548 file->mdat.atom.size = offset + sample_size;
550 quicktime_update_stco(&(trak->mdia.minf.stbl.stco),
551 current_chunk,
552 offset);
554 if(trak->mdia.minf.is_video)
555 quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz),
556 current_chunk - 1,
557 sample_size);
559 quicktime_update_stsc(&(trak->mdia.minf.stbl.stsc),
560 current_chunk,
561 samples);
564 int quicktime_write_vbr_frame(quicktime_t *file,
565 int track,
566 char *data,
567 int data_size,
568 int samples)
570 quicktime_audio_map_t *track_map = &(file->atracks[track]);
571 quicktime_trak_t *trak = track_map->track;
572 quicktime_atom_t chunk_atom;
573 int result = 0;
576 quicktime_write_chunk_header(file, trak, &chunk_atom);
577 result = !quicktime_write_data(file, data, data_size);
578 int64_t offset = chunk_atom.start;
580 // AVI case
581 if(file->use_avi)
583 quicktime_atom_write_footer(file, &chunk_atom);
584 // Save version 1 index entry for first RIFF only
585 if(file->total_riffs < 2)
587 quicktime_update_idx1table(file,
588 trak,
589 offset,
590 data_size);
593 // Save version 2 index entry
594 quicktime_update_ixtable(file,
595 trak,
596 offset,
597 data_size);
600 // Update MDAT size
601 if(offset + data_size > file->mdat.atom.size)
602 file->mdat.atom.size = offset + data_size;
604 // Update time to sample table
605 quicktime_stts_append_audio(file,
606 &(trak->mdia.minf.stbl.stts),
607 samples);
609 int64_t total_chunks = quicktime_stts_total_samples(file,
610 &(trak->mdia.minf.stbl.stts));
611 quicktime_update_stco(&(trak->mdia.minf.stbl.stco),
612 total_chunks,
613 offset);
614 quicktime_update_stsc(&(trak->mdia.minf.stbl.stsc),
615 total_chunks,
617 quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz),
618 total_chunks - 1,
619 data_size);
622 return result;
627 * int quicktime_update_tables(quicktime_t *file,
628 * quicktime_trak_t *trak,
629 * int64_t offset,
630 * int64_t chunk,
631 * int64_t sample,
632 * int64_t samples,
633 * int64_t sample_size)
635 * //if(file->use_avi)
636 * printf("quicktime_update_tables: replaced by quicktime_write_chunk_header and quicktime_write_chunk_footer\n");
638 * if(offset + sample_size > file->mdat.atom.size)
639 * file->mdat.atom.size = offset + sample_size;
641 * quicktime_update_stco(&(trak->mdia.minf.stbl.stco), chunk, offset);
643 * if(trak->mdia.minf.is_video)
644 * quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz), sample, sample_size);
647 * quicktime_update_stsc(&(trak->mdia.minf.stbl.stsc), chunk, samples);
648 * return 0;
654 * This is used for writing the header
656 int quicktime_trak_duration(quicktime_trak_t *trak,
657 long *duration,
658 long *timescale)
660 quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts);
661 int i;
662 *duration = 0;
664 for(i = 0; i < stts->total_entries; i++)
666 *duration += stts->table[i].sample_duration *
667 stts->table[i].sample_count;
670 *timescale = trak->mdia.mdhd.time_scale;
671 return 0;
674 int quicktime_trak_fix_counts(quicktime_t *file, quicktime_trak_t *trak)
676 long samples = quicktime_track_samples(file, trak);
678 if(!trak->mdia.minf.stbl.stts.is_vbr)
680 trak->mdia.minf.stbl.stts.table[0].sample_count = samples;
682 if(!trak->mdia.minf.stbl.stsz.total_entries)
684 trak->mdia.minf.stbl.stsz.sample_size = 1;
685 trak->mdia.minf.stbl.stsz.total_entries = samples;
688 return 0;
691 long quicktime_chunk_samples(quicktime_trak_t *trak, long chunk)
693 long result, current_chunk;
694 quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
695 long i = stsc->total_entries - 1;
699 current_chunk = stsc->table[i].chunk;
700 result = stsc->table[i].samples;
701 i--;
702 }while(i >= 0 && current_chunk > chunk);
704 return result;
707 int quicktime_trak_shift_offsets(quicktime_trak_t *trak, int64_t offset)
709 quicktime_stco_t *stco = &(trak->mdia.minf.stbl.stco);
710 int i;
712 for(i = 0; i < stco->total_entries; i++)
714 stco->table[i].offset += offset;
716 return 0;
719 char* quicktime_compressor(quicktime_trak_t *track)
721 return track->mdia.minf.stbl.stsd.table[0].format;
725 int quicktime_sample_duration(quicktime_trak_t *trak)
727 quicktime_stts_t *stts = &trak->mdia.minf.stbl.stts;
728 int i;
729 int max_count = 0;
730 int result = 1;
731 for(i = 0; i < stts->total_entries; i++)
733 quicktime_stts_table_t *table = &stts->table[i];
734 if(table->sample_count > max_count)
736 max_count = table->sample_count;
737 result = table->sample_duration;
740 return result;