allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / quicktime / avi_strl.c
1 #include "funcprotos.h"
2 #include "quicktime.h"
3 #include <string.h>
4
5
6 // Update during close:
7 // length
8 // samples per chunk
9 #define JUNK_SIZE 0x1018
10
11
12
13 quicktime_strl_t* quicktime_new_strl()
14 {
15         quicktime_strl_t *strl = calloc(1, sizeof(quicktime_strl_t));
16         return strl;
17 }
18
19
20 void quicktime_init_strl(quicktime_t *file,
21         quicktime_audio_map_t *atrack,
22         quicktime_video_map_t *vtrack,
23         quicktime_trak_t *trak,
24         quicktime_strl_t *strl)
25 {
26         quicktime_atom_t list_atom, strh_atom, strf_atom;
27         quicktime_atom_t junk_atom;
28         int i;
29
30 /* Construct tag */
31         if(vtrack)
32         {
33                 strl->tag[0] = '0' + (trak->tkhd.track_id - 1) / 10;
34                 strl->tag[1] = '0' + (trak->tkhd.track_id - 1) % 10;
35                 strl->tag[2] = 'd';
36                 strl->tag[3] = 'c';
37         }
38         else
39         if(atrack)
40         {
41                 strl->tag[0] = '0' + (trak->tkhd.track_id - 1) / 10;
42                 strl->tag[1] = '0' + (trak->tkhd.track_id - 1) % 10;
43                 strl->tag[2] = 'w';
44                 strl->tag[3] = 'b';
45         }
46
47
48 /* LIST 'strl' */
49         quicktime_atom_write_header(file, &list_atom, "LIST");
50         quicktime_write_char32(file, "strl");
51
52 /* 'strh' */
53         quicktime_atom_write_header(file, &strh_atom, "strh");
54
55
56
57 /* vids */
58         if(vtrack)
59         {
60                 quicktime_write_char32(file, "vids");
61                 quicktime_write_char32(file,
62                         trak->mdia.minf.stbl.stsd.table[0].format);
63 /* flags */
64         quicktime_write_int32_le(file, 0);
65 /* priority */
66         quicktime_write_int16_le(file, 0);
67 /* language */
68         quicktime_write_int16_le(file, 0);
69 /* initial frame */
70         quicktime_write_int32_le(file, 0);
71
72 /* framerate denominator */
73         quicktime_write_int32_le(file,
74                         trak->mdia.minf.stbl.stts.table[0].sample_duration);
75 /* framerate numerator */
76         quicktime_write_int32_le(file,
77                         trak->mdia.mdhd.time_scale);
78
79 /* start */
80         quicktime_write_int32_le(file, 0);
81                 strl->length_offset = quicktime_position(file);
82 /* length: fill later */
83         quicktime_write_int32_le(file, 0);
84 /* suggested buffer size */
85         quicktime_write_int32_le(file, 0);
86 /* quality */
87         quicktime_write_int32_le(file, -1);
88 /* sample size */
89         quicktime_write_int32_le(file, 0);
90         quicktime_write_int16_le(file, 0);
91         quicktime_write_int16_le(file, 0);
92         quicktime_write_int16_le(file, trak->tkhd.track_width);
93         quicktime_write_int16_le(file, trak->tkhd.track_height);
94         }
95         else
96 /* auds */
97         if(atrack)
98         {
99         quicktime_write_char32(file, "auds");
100         quicktime_write_int32_le(file, 0);
101 /* flags */
102         quicktime_write_int32_le(file, 0);
103 /* priority */
104         quicktime_write_int16_le(file, 0);
105 /* language */
106         quicktime_write_int16_le(file, 0);
107 /* initial frame */
108         quicktime_write_int32_le(file, 0);
109                 strl->samples_per_chunk_offset = quicktime_position(file);
110 /* samples per chunk */
111         quicktime_write_int32_le(file, 0);
112 /* sample rate * samples per chunk  if uncompressed */
113 /* sample rate if compressed */
114         quicktime_write_int32_le(file, 0);
115 /* start */
116         quicktime_write_int32_le(file, 0);
117                 strl->length_offset = quicktime_position(file);
118 /* length, XXX: filled later */
119         quicktime_write_int32_le(file, 0);
120 /* suggested buffer size */
121         quicktime_write_int32_le(file, 0);
122 /* quality */
123         quicktime_write_int32_le(file, -1);
124 /* sample size: 0 for compressed and number of bytes for uncompressed */
125                 strl->sample_size_offset = quicktime_position(file);
126         quicktime_write_int32_le(file, 0);
127         quicktime_write_int32_le(file, 0);
128         quicktime_write_int32_le(file, 0);
129         }
130         quicktime_atom_write_footer(file, &strh_atom);
131
132
133
134
135
136
137
138 /* strf */
139         quicktime_atom_write_header(file, &strf_atom, "strf");
140
141         if(vtrack)
142         {
143 /* atom size repeated */
144                 quicktime_write_int32_le(file, 40);
145                 quicktime_write_int32_le(file, trak->tkhd.track_width);
146                 quicktime_write_int32_le(file, trak->tkhd.track_height);
147 /* planes */
148                 quicktime_write_int16_le(file, 1);
149 /* depth */
150                 quicktime_write_int16_le(file, 24);
151                 quicktime_write_char32(file,
152                         trak->mdia.minf.stbl.stsd.table[0].format);
153                 quicktime_write_int32_le(file,
154                         trak->tkhd.track_width * trak->tkhd.track_height * 3);
155                 quicktime_write_int32_le(file, 0);
156                 quicktime_write_int32_le(file, 0);
157                 quicktime_write_int32_le(file, 0);
158                 quicktime_write_int32_le(file, 0);
159         }
160         else
161         if(atrack)
162         {
163 /* By now the codec is instantiated so the WAV ID is available. */
164                 quicktime_codec_t *codec_base = atrack->codec;
165                 int wav_id = codec_base->wav_id;
166
167                 quicktime_write_int16_le(file,
168                         wav_id);
169                 quicktime_write_int16_le(file,
170                         trak->mdia.minf.stbl.stsd.table[0].channels);
171 /* nSamplesPerSec as per MSDN */
172                 quicktime_write_int32_le(file,
173                         trak->mdia.minf.stbl.stsd.table[0].sample_rate);
174                 if (wav_id == 0x01)     // PCM
175                 {
176 /* nAvgBytesPerSec as per MSDN*/
177                         quicktime_write_int32_le(file, trak->mdia.minf.stbl.stsd.table[0].sample_rate * trak->mdia.minf.stbl.stsd.table[0].sample_size * trak->mdia.minf.stbl.stsd.table[0].channels / 8);
178 /* nBlockAlign as per MSDN, very important value */
179 /* nBlockAlign have to be the same is used in many players instead of dwSampleSize - so they should be the same */
180 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcemultimedia5/html/wce50conAVIStreamHeaders.asp */
181 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcemultimedia5/html/wce50lrfwaveformatex91.asp */
182                         quicktime_write_int16_le(file, trak->mdia.minf.stbl.stsd.table[0].sample_size * trak->mdia.minf.stbl.stsd.table[0].channels / 8);
183                 }
184                 else
185                 {
186 /* FIXME: These two are complete rubbish, according to my knowledge, they depend on the codec */
187                         quicktime_write_int32_le(file, 256000 / 8);        // nAvgBytesPerSec
188                         quicktime_write_int16_le(file, 1);          // nBlockAling
189                 }
190
191 /* bits per sample */
192                 quicktime_write_int16_le(file,
193                         trak->mdia.minf.stbl.stsd.table[0].sample_size);
194                 quicktime_write_int16_le(file, 0);
195         }
196
197         quicktime_atom_write_footer(file, &strf_atom);
198
199
200
201
202 /* Junk is required in Windows. */
203 /* In Heroine Kernel it's padding for the super index */
204         strl->indx_offset = quicktime_position(file);
205         strl->padding_size = JUNK_SIZE;
206
207
208
209         quicktime_atom_write_header(file, &junk_atom, "JUNK");
210         for(i = 0; i < strl->padding_size; i += 4)
211                 quicktime_write_int32_le(file, 0);
212         quicktime_atom_write_footer(file, &junk_atom);
213
214
215 /* Initialize super index */
216         quicktime_init_indx(file, &strl->indx, strl);
217
218
219         quicktime_atom_write_footer(file, &list_atom);
220 }
221
222
223
224 void quicktime_delete_strl(quicktime_strl_t *strl)
225 {
226         quicktime_delete_indx(&strl->indx);
227         free(strl);
228 }
229
230 void quicktime_read_strl(quicktime_t *file,
231         quicktime_strl_t *strl,
232         quicktime_atom_t *parent_atom)
233 {
234 // These are 0 if no track is currently being processed.
235 // Set to 1 if audio or video track is being processed.
236         char data[4], codec[4];
237         int denominator = 0;
238         int numerator = 0;
239         double frame_rate = 0;
240         int width = 0;
241         int height = 0;
242         int depth = 0;
243         int frames = 0;
244         int bytes_per_sample = 0;
245         int sample_size = 0;
246         int samples_per_chunk = 0;
247         int channels = 0;
248         int sample_rate = 0;
249         int compression_id = 0;
250         quicktime_trak_t *trak = 0;
251
252         codec[0] = codec[1] = codec[2] = codec[3] = 0;
253
254 /* AVI translation: */
255 /* vids -> trak */
256 /* auds -> trak */
257 /* Only one track is in each strl object */
258         do
259         {
260                 quicktime_atom_t leaf_atom;
261                 quicktime_atom_read_header(file, &leaf_atom);
262
263 // strh
264                 if(quicktime_atom_is(&leaf_atom, "strh"))
265                 {
266 // stream type
267                         quicktime_read_data(file, data, 4);
268
269                         if(quicktime_match_32(data, "vids"))
270                         {
271                                 trak = quicktime_add_trak(file);
272                                 width = 0;
273                                 height = 0;
274                                 depth = 24;
275                                 frames = 0;
276                                 strl->is_video = 1;
277
278
279                                 trak->tkhd.track_id = file->moov.mvhd.next_track_id;
280                                 file->moov.mvhd.next_track_id++;
281
282
283 /* Codec */
284                                 quicktime_read_data(file,
285                                         codec,
286                                         4);
287 /* Blank */
288                                 quicktime_set_position(file, quicktime_position(file) + 12);
289                                 denominator = quicktime_read_int32_le(file);
290                                 numerator = quicktime_read_int32_le(file);
291 /*
292  * printf("quicktime_read_strl 1 %c%c%c%c %d %d\n",
293  * codec[0],
294  * codec[1],
295  * codec[2],
296  * codec[3],
297  * numerator,
298  * denominator);
299  */
300                                 if(denominator != 0)
301                                         frame_rate = (double)numerator / denominator;
302                                 else
303                                         frame_rate = numerator;
304
305 // Canon TX1
306                                 if(numerator == 1000000 &&
307                                         denominator == 33333)
308                                         frame_rate = 30.00;
309
310 /* Blank */
311                                 quicktime_set_position(file, quicktime_position(file) + 4);
312                                 frames = quicktime_read_int32_le(file);
313                         }
314                         else
315 /* AVI auds */
316                         if(quicktime_match_32(data, "auds"))
317                         {
318                                 trak = quicktime_add_trak(file);
319                                 sample_size = 16;
320                                 channels = 2;
321                                 sample_rate = 0;
322                                 compression_id = 0;
323                                 strl->is_audio = 1;
324
325                                 trak->tkhd.track_id = file->moov.mvhd.next_track_id;
326                                 file->moov.mvhd.next_track_id++;
327 // codec tag
328                                 quicktime_read_data(file,
329                                         codec,
330                                         4);
331 //printf("quicktime_read_strl 2 %c%c%c%c\n", codec[0], codec[1], codec[2], codec[3]);
332 // flags 32, priority 16, language 16, initial frame 32
333                                 quicktime_set_position(file, quicktime_position(file) + 12);
334
335                                 samples_per_chunk = quicktime_read_int32_le(file);
336                                 strl->bytes_per_second = quicktime_read_int32_le(file);
337                                 quicktime_set_position(file, quicktime_position(file) + 4);
338 /* length of track */
339                                 strl->samples = quicktime_read_int32_le(file);
340 /* suggested buffer size, quality */
341                                 quicktime_set_position(file, quicktime_position(file) + 8);
342
343 // If this is 0 use constant samples_per_chunk to guess locations.
344 // If it isn't 0 synthesize samples per chunk table to get locations.
345 // McRowesoft doesn't really obey this rule so we may need to base it on codec ID.
346                                 bytes_per_sample = quicktime_read_int32_le(file);
347 //printf("quicktime_read_strl 20 %d\n", samples_per_chunk);
348                         }
349                 }
350 // strf
351                 else
352                 if(quicktime_atom_is(&leaf_atom, "strf"))
353                 {
354                         if(strl->is_video)
355                         {
356 /* atom size repeated */
357                                 quicktime_read_int32_le(file);
358                                 width = quicktime_read_int32_le(file);
359                                 height = quicktime_read_int32_le(file);
360 /* Panes */
361                                 quicktime_read_int16_le(file);
362 /* Depth in bits */
363                                 depth = quicktime_read_int16_le(file);
364                                 quicktime_read_data(file,
365                                         codec,
366                                         4);
367                         }
368                         else
369                         if(strl->is_audio)
370                         {
371                                 compression_id = quicktime_read_int16_le(file);
372                                 channels = quicktime_read_int16_le(file);
373                                 sample_rate = quicktime_read_int32_le(file);
374                                 quicktime_set_position(file, quicktime_position(file) + 6);
375                                 sample_size = quicktime_read_int16_le(file);
376 //printf("quicktime_read_strl 40 %d %d %d\n", channels, sample_rate, sample_size);
377                         }
378                 }
379                 else
380 // Super index.
381 // Read the super index + all the partial indexes now
382                 if(quicktime_atom_is(&leaf_atom, "indx"))
383                 {
384 //printf("quicktime_read_strl 50\n");
385                         quicktime_read_indx(file, strl, &leaf_atom);
386                         strl->have_indx = 1;
387                 }
388
389 //printf("quicktime_read_strl 60\n");
390
391
392 // Next object
393                 quicktime_atom_skip(file, &leaf_atom);
394         }while(quicktime_position(file) < parent_atom->end);
395 //printf("quicktime_read_strl 70 %d %d\n", strl->is_audio, strl->is_video);
396
397
398         if(strl->is_video)
399         {
400 /* Generate quicktime structures */
401                 quicktime_trak_init_video(file,
402                         trak,
403                         width,
404                         height,
405                         frame_rate,
406                         codec);
407                 quicktime_mhvd_init_video(file,
408                         &file->moov.mvhd,
409                         frame_rate);
410                 trak->mdia.mdhd.duration = frames;
411 //                      trak->mdia.mdhd.time_scale = 1;
412                 memcpy(trak->mdia.minf.stbl.stsd.table[0].format, codec, 4);
413                 trak->mdia.minf.stbl.stsd.table[0].depth = depth;
414         }
415         else
416         if(strl->is_audio)
417         {
418 /* Generate quicktime structures */
419 //printf("quicktime_read_strl 70 %d\n", sample_size);
420                 quicktime_trak_init_audio(file,
421                                         trak,
422                                         channels,
423                                         sample_rate,
424                                         sample_size,
425                                         codec);
426
427
428 // We store a constant samples per chunk based on the
429 // packet size if sample_size zero
430 // and calculate the samples per chunk based on the chunk size if sample_size
431 // is nonzero.
432 //              trak->mdia.minf.stbl.stsd.table[0].sample_size = bytes_per_sample;
433                 trak->mdia.minf.stbl.stsd.table[0].compression_id = compression_id;
434
435 /* Synthesize stsc table for constant samples per chunk */
436                 if(!bytes_per_sample)
437                 {
438 /* Should be enough entries allocated in quicktime_stsc_init_table */
439                         trak->mdia.minf.stbl.stsc.table[0].samples = samples_per_chunk;
440                         trak->mdia.minf.stbl.stsc.total_entries = 1;
441                 }
442 //printf("quicktime_read_strl samples=%d samples_per_chunk=%d bytes_per_sample=%d bytes_per_second=%d\n",
443 //strl->samples, samples_per_chunk, bytes_per_sample, strl->bytes_per_second);
444         }
445
446
447 //printf("quicktime_read_strl 100\n");
448 }
449
450
451
452