initial commit
[goodguy/history.git] / cinelerra-5.0 / quicktime / stsc.c
1 #include "funcprotos.h"
2 #include "quicktime.h"
3
4
5
6 void quicktime_stsc_init(quicktime_stsc_t *stsc)
7 {
8         stsc->version = 0;
9         stsc->flags = 0;
10         stsc->total_entries = 0;
11         stsc->entries_allocated = 0;
12 }
13
14 void quicktime_stsc_init_table(quicktime_t *file, quicktime_stsc_t *stsc)
15 {
16         if(!stsc->entries_allocated)
17         {
18                 stsc->total_entries = 0;
19                 stsc->entries_allocated = 2048;
20                 stsc->table = (quicktime_stsc_table_t*)calloc(1, sizeof(quicktime_stsc_table_t) * stsc->entries_allocated);
21         }
22 }
23
24 void quicktime_stsc_init_video(quicktime_t *file, quicktime_stsc_t *stsc)
25 {
26 //printf("quicktime_stsc_init_video 1\n");
27         quicktime_stsc_table_t *table;
28         quicktime_stsc_init_table(file, stsc);
29         table = &(stsc->table[0]);
30         table->chunk = 1;
31         table->samples = 1;
32         table->id = 1;
33 }
34
35 void quicktime_stsc_init_audio(quicktime_t *file, quicktime_stsc_t *stsc, int sample_rate)
36 {
37         quicktime_stsc_table_t *table;
38         quicktime_stsc_init_table(file, stsc);
39         table = &(stsc->table[0]);
40         table->chunk = 1;
41         table->samples = 0;         /* set this after completion or after every audio chunk is written */
42         table->id = 1;
43 }
44
45 void quicktime_stsc_delete(quicktime_stsc_t *stsc)
46 {
47         if(stsc->total_entries) free(stsc->table);
48         stsc->total_entries = 0;
49 }
50
51 void quicktime_stsc_dump(quicktime_stsc_t *stsc)
52 {
53         int i;
54         printf("     sample to chunk\n");
55         printf("      version %d\n", stsc->version);
56         printf("      flags %ld\n", stsc->flags);
57         printf("      total_entries %jd\n", stsc->total_entries);
58         for(i = 0; i < stsc->total_entries; i++)
59         {
60                 printf("       chunk %ld samples 0x%lx id %ld\n",
61                         stsc->table[i].chunk, stsc->table[i].samples, stsc->table[i].id);
62         }
63 }
64
65 void quicktime_read_stsc(quicktime_t *file, quicktime_stsc_t *stsc)
66 {
67         int i;
68         stsc->version = quicktime_read_char(file);
69         stsc->flags = quicktime_read_int24(file);
70         stsc->total_entries = quicktime_read_int32(file);
71
72         stsc->entries_allocated = stsc->total_entries;
73         stsc->table = (quicktime_stsc_table_t*)malloc(sizeof(quicktime_stsc_table_t) * stsc->total_entries);
74         for(i = 0; i < stsc->total_entries; i++)
75         {
76                 stsc->table[i].chunk = quicktime_read_int32(file);
77                 stsc->table[i].samples = quicktime_read_int32(file);
78                 stsc->table[i].id = quicktime_read_int32(file);
79         }
80 }
81
82
83 void quicktime_write_stsc(quicktime_t *file, quicktime_stsc_t *stsc)
84 {
85         int i, last_same;
86         quicktime_atom_t atom;
87         quicktime_atom_write_header(file, &atom, "stsc");
88
89         for(i = 1, last_same = 0; i < stsc->total_entries; i++)
90         {
91                 if(stsc->table[i].samples != stsc->table[last_same].samples)
92                 {
93 /* An entry has a different sample count. */
94                         last_same++;
95                         if(last_same < i)
96                         {
97 /* Move it up the list. */
98                                 stsc->table[last_same] = stsc->table[i];
99                         }
100                 }
101         }
102         last_same++;
103         stsc->total_entries = last_same;
104
105
106         quicktime_write_char(file, stsc->version);
107         quicktime_write_int24(file, stsc->flags);
108         quicktime_write_int32(file, stsc->total_entries);
109         for(i = 0; i < stsc->total_entries; i++)
110         {
111                 quicktime_write_int32(file, stsc->table[i].chunk);
112                 quicktime_write_int32(file, stsc->table[i].samples);
113                 quicktime_write_int32(file, stsc->table[i].id);
114         }
115
116         quicktime_atom_write_footer(file, &atom);
117 }
118
119 // Chunk starts at 1
120 int quicktime_update_stsc(quicktime_stsc_t *stsc, long chunk, long samples)
121 {
122         if(chunk > stsc->entries_allocated)
123         {
124                 stsc->entries_allocated = (chunk + 1) * 2;
125                 stsc->table =(quicktime_stsc_table_t*)realloc(stsc->table, sizeof(quicktime_stsc_table_t) * stsc->entries_allocated);
126         }
127
128         stsc->table[chunk - 1].samples = samples;
129         stsc->table[chunk - 1].chunk = chunk;
130         stsc->table[chunk - 1].id = 1;
131         if(chunk > stsc->total_entries) stsc->total_entries = chunk;
132         return 0;
133 }
134
135 /* Optimizing while writing doesn't allow seeks during recording so */
136 /* entries are created for every chunk and only optimized during */
137 /* writeout.  Unfortunately there's no way to keep audio synchronized */
138 /* after overwriting  a recording as the fractional audio chunk in the */
139 /* middle always overwrites the previous location of a larger chunk.  On */
140 /* writing, the table must be optimized.  RealProducer requires an  */
141 /* optimized table. */
142