1 #include "funcprotos.h"
6 // Update during close:
9 #define JUNK_SIZE 0x1018
13 quicktime_strl_t* quicktime_new_strl()
15 quicktime_strl_t *strl = calloc(1, sizeof(quicktime_strl_t));
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)
26 quicktime_atom_t list_atom, strh_atom, strf_atom;
27 quicktime_atom_t junk_atom;
33 strl->tag[0] = '0' + (trak->tkhd.track_id - 1) / 10;
34 strl->tag[1] = '0' + (trak->tkhd.track_id - 1) % 10;
41 strl->tag[0] = '0' + (trak->tkhd.track_id - 1) / 10;
42 strl->tag[1] = '0' + (trak->tkhd.track_id - 1) % 10;
49 quicktime_atom_write_header(file, &list_atom, "LIST");
50 quicktime_write_char32(file, "strl");
53 quicktime_atom_write_header(file, &strh_atom, "strh");
60 quicktime_write_char32(file, "vids");
61 quicktime_write_char32(file,
62 trak->mdia.minf.stbl.stsd.table[0].format);
64 quicktime_write_int32_le(file, 0);
66 quicktime_write_int16_le(file, 0);
68 quicktime_write_int16_le(file, 0);
70 quicktime_write_int32_le(file, 0);
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);
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);
87 quicktime_write_int32_le(file, -1);
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);
99 quicktime_write_char32(file, "auds");
100 quicktime_write_int32_le(file, 0);
102 quicktime_write_int32_le(file, 0);
104 quicktime_write_int16_le(file, 0);
106 quicktime_write_int16_le(file, 0);
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);
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);
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);
130 quicktime_atom_write_footer(file, &strh_atom);
139 quicktime_atom_write_header(file, &strf_atom, "strf");
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);
148 quicktime_write_int16_le(file, 1);
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);
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;
167 quicktime_write_int16_le(file,
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
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);
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
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);
197 quicktime_atom_write_footer(file, &strf_atom);
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;
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);
215 /* Initialize super index */
216 quicktime_init_indx(file, &strl->indx, strl);
219 quicktime_atom_write_footer(file, &list_atom);
224 void quicktime_delete_strl(quicktime_strl_t *strl)
226 quicktime_delete_indx(&strl->indx);
230 void quicktime_read_strl(quicktime_t *file,
231 quicktime_strl_t *strl,
232 quicktime_atom_t *parent_atom)
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];
239 double frame_rate = 0;
244 int bytes_per_sample = 0;
246 int samples_per_chunk = 0;
249 int compression_id = 0;
250 quicktime_trak_t *trak = 0;
252 codec[0] = codec[1] = codec[2] = codec[3] = 0;
254 /* AVI translation: */
257 /* Only one track is in each strl object */
260 quicktime_atom_t leaf_atom;
261 quicktime_atom_read_header(file, &leaf_atom);
264 if(quicktime_atom_is(&leaf_atom, "strh"))
267 quicktime_read_data(file, data, 4);
269 if(quicktime_match_32(data, "vids"))
271 trak = quicktime_add_trak(file);
279 trak->tkhd.track_id = file->moov.mvhd.next_track_id;
280 file->moov.mvhd.next_track_id++;
284 quicktime_read_data(file,
288 quicktime_set_position(file, quicktime_position(file) + 12);
289 denominator = quicktime_read_int32_le(file);
290 numerator = quicktime_read_int32_le(file);
292 * printf("quicktime_read_strl 1 %c%c%c%c %d %d\n",
301 frame_rate = (double)numerator / denominator;
303 frame_rate = numerator;
306 if(numerator == 1000000 &&
307 denominator == 33333)
311 quicktime_set_position(file, quicktime_position(file) + 4);
312 frames = quicktime_read_int32_le(file);
316 if(quicktime_match_32(data, "auds"))
318 trak = quicktime_add_trak(file);
325 trak->tkhd.track_id = file->moov.mvhd.next_track_id;
326 file->moov.mvhd.next_track_id++;
328 quicktime_read_data(file,
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);
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);
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);
352 if(quicktime_atom_is(&leaf_atom, "strf"))
356 /* atom size repeated */
357 quicktime_read_int32_le(file);
358 width = quicktime_read_int32_le(file);
359 height = quicktime_read_int32_le(file);
361 quicktime_read_int16_le(file);
363 depth = quicktime_read_int16_le(file);
364 quicktime_read_data(file,
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);
381 // Read the super index + all the partial indexes now
382 if(quicktime_atom_is(&leaf_atom, "indx"))
384 //printf("quicktime_read_strl 50\n");
385 quicktime_read_indx(file, strl, &leaf_atom);
389 //printf("quicktime_read_strl 60\n");
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);
400 /* Generate quicktime structures */
401 quicktime_trak_init_video(file,
407 quicktime_mhvd_init_video(file,
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;
418 /* Generate quicktime structures */
419 //printf("quicktime_read_strl 70 %d\n", sample_size);
420 quicktime_trak_init_audio(file,
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
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;
435 /* Synthesize stsc table for constant samples per chunk */
436 if(!bytes_per_sample)
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;
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);
447 //printf("quicktime_read_strl 100\n");