allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / quicktime / avi_riff.c
1 #include "funcprotos.h"
2 #include "quicktime.h"
3
4
5 // This is the main file that converts the AVI tables to Quicktime tables.
6
7
8 void quicktime_read_riff(quicktime_t *file, quicktime_atom_t *parent_atom)
9 {
10         quicktime_riff_t *riff = quicktime_new_riff(file);
11         quicktime_atom_t leaf_atom;
12         int result = 0;
13         char data[5];
14
15         riff->atom = *parent_atom;
16
17 // AVI
18         quicktime_read_data(file, data, 4);
19 //printf("quicktime_read_riff 1 %llx\n", quicktime_position(file));
20
21 // Certain AVI parameters must be copied over to quicktime objects:
22 // hdrl -> moov
23 // movi -> mdat
24 // idx1 -> moov
25         do
26         {
27                 result = quicktime_atom_read_header(file, &leaf_atom);
28
29 /*
30  * printf("quicktime_read_riff 1 %llx %llx %c%c%c%c\n",
31  * leaf_atom.start,
32  * leaf_atom.size,
33  * leaf_atom.type[0],
34  * leaf_atom.type[1],
35  * leaf_atom.type[2],
36  * leaf_atom.type[3]);
37  */
38                 if(!result)
39                 {
40                         if(quicktime_atom_is(&leaf_atom, "LIST"))
41                         {
42                                 data[4] = 0;
43
44
45                                 result = !quicktime_read_data(file, data, 4);
46
47
48                                 if(!result)
49                                 {
50 // Got LIST 'hdrl'
51                                         if(quicktime_match_32(data, "hdrl"))
52                                         {
53
54 // No size here.
55 //printf("quicktime_read_riff 10 %llx\n", quicktime_position(file));
56                                                 quicktime_read_hdrl(file, &riff->hdrl, &leaf_atom);
57 //printf("quicktime_read_riff 20 %llx\n", quicktime_position(file));
58                                         }
59                                         else
60 // Got LIST 'movi'
61                                         if(quicktime_match_32(data, "movi"))
62                                         {
63 //printf("quicktime_read_riff 30 %llx\n", quicktime_position(file));
64                                                 quicktime_read_movi(file, &leaf_atom, &riff->movi);
65 //printf("quicktime_read_riff 40 %llx\n", quicktime_position(file));
66                                         }
67                                 }
68
69 // Skip it
70                                 quicktime_atom_skip(file, &leaf_atom);
71
72                         }
73                         else
74 // Got 'movi'
75                         if(quicktime_atom_is(&leaf_atom, "movi"))
76                         {
77                                 quicktime_read_movi(file, &leaf_atom, &riff->movi);
78
79                         }
80                         else
81 // Got 'idx1' original index
82                         if(quicktime_atom_is(&leaf_atom, "idx1"))
83                         {
84
85 //printf("quicktime_read_riff 50 %llx\n", quicktime_position(file));
86 // Preload idx1 here
87                                 int64_t start_position = quicktime_position(file);
88                                 long temp_size = leaf_atom.end - start_position;
89                                 char *temp = malloc(temp_size);
90                                 quicktime_set_preload(file,
91                                         (temp_size < 0x100000) ? 0x100000 : temp_size);
92                                 quicktime_read_data(file, temp, temp_size);
93                                 quicktime_set_position(file, start_position);
94                                 free(temp);
95
96 // Read idx1
97                                 quicktime_read_idx1(file, riff, &leaf_atom);
98 //printf("quicktime_read_riff 60 %llx\n", quicktime_position(file));
99
100                         }
101                         else
102 /* Skip it */
103                         {
104
105                                 quicktime_atom_skip(file, &leaf_atom);
106
107                         }
108                 }
109         }while(!result && quicktime_position(file) < parent_atom->end);
110
111 //printf("quicktime_read_riff 10\n");
112
113
114 }
115
116
117 quicktime_riff_t* quicktime_new_riff(quicktime_t *file)
118 {
119         if(file->total_riffs >= MAX_RIFFS)
120         {
121                 fprintf(stderr, "quicktime_new_riff file->total_riffs >= MAX_RIFFS\n");
122                 return 0;
123         }
124         else
125         {
126                 quicktime_riff_t *riff = calloc(1, sizeof(quicktime_riff_t));
127                 file->riff[file->total_riffs++] = riff;
128                 return riff;
129         }
130 }
131
132
133
134 void quicktime_delete_riff(quicktime_t *file, quicktime_riff_t *riff)
135 {
136         quicktime_delete_hdrl(file, &riff->hdrl);
137         quicktime_delete_movi(file, &riff->movi);
138         quicktime_delete_idx1(&riff->idx1);
139         free(riff);
140 }
141
142 void quicktime_init_riff(quicktime_t *file)
143 {
144
145 // Create new RIFF
146         quicktime_riff_t *riff = quicktime_new_riff(file);
147
148 // Write riff header
149 // RIFF 'AVI '
150         quicktime_atom_write_header(file, &riff->atom, "RIFF");
151         quicktime_write_char32(file, "AVI ");
152
153 // Write header list in first RIFF only
154         if(file->total_riffs < 2)
155         {
156                 quicktime_init_hdrl(file, &riff->hdrl);
157                 riff->have_hdrl = 1;
158         }
159
160         quicktime_init_movi(file, riff);
161 }
162
163 void quicktime_finalize_riff(quicktime_t *file, quicktime_riff_t *riff)
164 {
165 // Write partial indexes
166         quicktime_finalize_movi(file, &riff->movi);
167         if(riff->have_hdrl)
168         {
169 //printf("quicktime_finalize_riff 1\n");
170                 quicktime_finalize_hdrl(file, &riff->hdrl);
171 //printf("quicktime_finalize_riff 10\n");
172 // Write original index for first RIFF
173                 quicktime_write_idx1(file, &riff->idx1);
174 //printf("quicktime_finalize_riff 100\n");
175         }
176         quicktime_atom_write_footer(file, &riff->atom);
177 }
178
179
180
181
182 void quicktime_import_avi(quicktime_t *file)
183 {
184         int i, j, k;
185         quicktime_riff_t *first_riff = file->riff[0];
186         quicktime_idx1_t *idx1 = &first_riff->idx1;
187
188
189 /* Determine whether to use idx1 or indx indexes for offsets. */
190 /* idx1 must always be used for keyframes but it also must be */
191 /* ignored for offsets if indx exists. */
192
193
194 //printf("quicktime_import_avi 1\n");
195 /* Convert idx1 to keyframes and load offsets and sizes */
196
197
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...
202
203         int index_format = 0;
204
205         if(idx1->table_size > 1)
206         {
207
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;
214         }
215
216         for(i = 0; i < idx1->table_size; i++)
217         {
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)
222                 {
223                         quicktime_trak_t *trak = file->moov.trak[track_number];
224                         quicktime_strl_t *strl = first_riff->hdrl.strl[track_number];
225                         int is_audio = trak->mdia.minf.is_audio;
226                         int is_video = trak->mdia.minf.is_video;
227
228
229 /* Chunk offset */
230                         quicktime_stco_t *stco = &trak->mdia.minf.stbl.stco;
231 /* Sample size */
232                         quicktime_stsz_t *stsz = &trak->mdia.minf.stbl.stsz;
233 /* Samples per chunk */
234                         quicktime_stsc_t *stsc = &trak->mdia.minf.stbl.stsc;
235 /* Sample description */
236                         quicktime_stsd_t *stsd = &trak->mdia.minf.stbl.stsd;
237
238
239
240
241 /* Enter the offset and size no matter what so the sample counts */
242 /* can be used to set keyframes */
243                         if (index_format == 1)
244                                 quicktime_update_stco(stco,
245                                                 stco->total_entries + 1,
246                                                 idx1table->offset + first_riff->movi.atom.start);
247                         else
248                                 quicktime_update_stco(stco,
249                                                 stco->total_entries + 1,
250                                                 idx1table->offset);
251
252                         if(is_video)
253                         {
254 /* Just get the keyframe flag.  don't call quicktime_insert_keyframe because */
255 /* that updates idx1 and we don't have a track map. */
256                                 int is_keyframe = (idx1table->flags & AVI_KEYFRAME) == AVI_KEYFRAME;
257                                 if(is_keyframe)
258                                 {
259                                         quicktime_stss_t *stss = &trak->mdia.minf.stbl.stss;
260 /* This is done before the image size table so this value is right */
261                                         int frame = stsz->total_entries;
262
263 /* Expand table */
264                                         if(stss->entries_allocated <= stss->total_entries)
265                                         {
266                                                 stss->entries_allocated *= 2;
267                                                 stss->table = realloc(stss->table,
268                                                         sizeof(quicktime_stss_table_t) * stss->entries_allocated);
269                                         }
270                                         stss->table[stss->total_entries++].sample = frame;
271                                 }
272
273 /* Set image size */
274                                 quicktime_update_stsz(stsz,
275                                                         stsz->total_entries,
276                                                         idx1table->size);
277                         }
278                         else
279                         if(is_audio)
280                         {
281                                 strl->total_bytes += idx1table->size;
282 /* Set samples per chunk if PCM */
283                                 if(stsd->table[0].sample_size > 0)
284                                 {
285                                         quicktime_update_stsc(stsc,
286                                                 stsc->total_entries + 1,
287                                                 idx1table->size *
288                                                         8 /
289                                                         stsd->table[0].sample_size /
290                                                         stsd->table[0].channels);
291                                 }
292                         }
293                 }
294         }
295
296 //printf("quicktime_import_avi 10\n");
297
298
299 /* Convert super indexes into Quicktime indexes. */
300 /* Append to existing entries if idx1 exists. */
301 /* No keyframes here. */
302         for(i = 0; i < file->moov.total_tracks; i++)
303         {
304                 quicktime_strl_t *strl = first_riff->hdrl.strl[i];
305
306                 if(strl->have_indx)
307                 {
308                         quicktime_indx_t *indx = &strl->indx;
309                         quicktime_trak_t *trak = file->moov.trak[i];
310                         quicktime_stco_t *stco = &trak->mdia.minf.stbl.stco;
311                         quicktime_stsz_t *stsz = &trak->mdia.minf.stbl.stsz;
312                         quicktime_stsc_t *stsc = &trak->mdia.minf.stbl.stsc;
313                         quicktime_stsd_t *stsd = &trak->mdia.minf.stbl.stsd;
314 /* Get existing chunk count from the idx1 */
315                         int existing_chunks = stco->total_entries;
316
317 /* Read each indx entry */
318                         for(j = 0; j < indx->table_size; j++)
319                         {
320                                 quicktime_indxtable_t *indx_table = &indx->table[j];
321                                 quicktime_ix_t *ix = indx_table->ix;
322
323                                 for(k = 0; k < ix->table_size; k++)
324                                 {
325 /* Copy from existing chunk count to end of ix table */
326                                         if(existing_chunks <= 0)
327                                         {
328                                                 quicktime_ixtable_t *ixtable = &ix->table[k];
329
330 /* Do the same things that idx1 did to the chunk tables */
331 /* Subtract the super indexes by size of the header.  McRoweSoft seems to */
332 /* want the header before the ix offset but after the idx1 offset. */
333                                                 quicktime_update_stco(stco,
334                                                         stco->total_entries + 1,
335                                                         ixtable->relative_offset + ix->base_offset - 8);
336                                                 if(strl->is_video)
337                                                 {
338                                                         quicktime_update_stsz(stsz,
339                                                                 stsz->total_entries,
340                                                                 ixtable->size);
341                                                 }
342                                                 else
343                                                 if(strl->is_audio)
344                                                 {
345                                                         strl->total_bytes += ixtable->size;
346                                                         if(stsd->table[0].sample_size > 0)
347                                                         {
348                                                                 quicktime_update_stsc(stsc,
349                                                                         stsc->total_entries + 1,
350                                                                         ixtable->size *
351                                                                         8 /
352                                                                         stsd->table[0].sample_size /
353                                                                         stsd->table[0].channels);
354                                                         }
355                                                 }
356                                         }
357                                         else
358                                                 existing_chunks--;
359                                 }
360                         }
361                 }
362         }
363
364
365 //printf("quicktime_import_avi 20\n");
366
367
368
369
370 /* Set total samples, time to sample, for audio */
371         for(i = 0; i < file->moov.total_tracks; i++)
372         {
373                 quicktime_trak_t *trak = file->moov.trak[i];
374                 quicktime_stsz_t *stsz = &trak->mdia.minf.stbl.stsz;
375                 quicktime_stsc_t *stsc = &trak->mdia.minf.stbl.stsc;
376                 quicktime_stco_t *stco = &trak->mdia.minf.stbl.stco;
377                 quicktime_stts_t *stts = &trak->mdia.minf.stbl.stts;
378                 quicktime_stsd_t *stsd = &trak->mdia.minf.stbl.stsd;
379
380                 if(trak->mdia.minf.is_audio)
381                 {
382                         quicktime_stsc_table_t *stsc_table = stsc->table;
383                         quicktime_strl_t *strl = first_riff->hdrl.strl[i];
384                         int64_t total_entries = stsc->total_entries;
385                         int64_t chunk = stco->total_entries;
386                         int64_t sample = 0;
387
388 //printf("quicktime_import_avi %lld %lld %lld\n",
389 //strl->total_bytes, strl->bytes_per_second, (int)stsd->table[0].sample_rate);
390 // Derive stsc from bitrate for some MP3 files
391                         if(!total_entries)
392                         {
393                                 quicktime_update_stsc(stsc,
394                                         ++total_entries,
395                                         strl->total_bytes /
396                                                 strl->bytes_per_second *
397                                                 (int)stsd->table[0].sample_rate);
398                         }
399
400
401 // Derive total samples from samples per chunk table
402                         if(chunk > 0)
403                         {
404                                 sample = quicktime_sample_of_chunk(trak, chunk) +
405                                         stsc_table[total_entries - 1].samples;
406                         }
407
408                         stsz->sample_size = 1;
409                         stsz->total_entries = sample;
410                         stts->table[0].sample_count = sample;
411                 }
412                 else
413                 if(trak->mdia.minf.is_video)
414                 {
415                         stsc->total_entries = 1;
416 /* stts has 1 allocation by default */
417                         stts->table[0].sample_count = stco->total_entries;
418                 }
419         }
420
421 //printf("quicktime_import_avi 30\n");
422
423 }
424
425
426
427
428
429
430
431
432