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];
244 int bytes_per_sample
;
247 int samples_per_chunk
;
251 int bytes_per_second
;
252 quicktime_trak_t
*trak
= 0;
253 quicktime_riff_t
*first_riff
= file
->riff
[0];
256 codec
[0] = codec
[1] = codec
[2] = codec
[3] = 0;
258 /* AVI translation: */
261 /* Only one track is in each strl object */
264 quicktime_atom_t leaf_atom
;
265 quicktime_atom_read_header(file
, &leaf_atom
);
268 if(quicktime_atom_is(&leaf_atom
, "strh"))
271 quicktime_read_data(file
, data
, 4);
273 if(quicktime_match_32(data
, "vids"))
275 trak
= quicktime_add_trak(file
);
283 trak
->tkhd
.track_id
= file
->moov
.mvhd
.next_track_id
;
284 file
->moov
.mvhd
.next_track_id
++;
288 quicktime_read_data(file
,
291 //printf("quicktime_read_strl 1 %c%c%c%c\n", codec[0], codec[1], codec[2], codec[3]);
293 quicktime_set_position(file
, quicktime_position(file
) + 12);
294 denominator
= quicktime_read_int32_le(file
);
295 numerator
= quicktime_read_int32_le(file
);
297 frame_rate
= (double)numerator
/ denominator
;
299 frame_rate
= numerator
;
302 quicktime_set_position(file
, quicktime_position(file
) + 4);
303 frames
= quicktime_read_int32_le(file
);
306 if(quicktime_match_32(data
, "auds"))
308 trak
= quicktime_add_trak(file
);
315 trak
->tkhd
.track_id
= file
->moov
.mvhd
.next_track_id
;
316 file
->moov
.mvhd
.next_track_id
++;
317 quicktime_read_data(file
,
320 //printf("quicktime_read_strl 2 %c%c%c%c\n", codec[0], codec[1], codec[2], codec[3]);
321 quicktime_set_position(file
, quicktime_position(file
) + 12);
322 samples_per_chunk
= quicktime_read_int32_le(file
);
323 bytes_per_second
= quicktime_read_int32_le(file
);
325 quicktime_set_position(file
, quicktime_position(file
) + 4);
326 /* length of track */
327 samples
= quicktime_read_int32_le(file
);
328 /* suggested buffer size, quality */
329 quicktime_set_position(file
, quicktime_position(file
) + 8);
331 // If this is 0 use constant samples_per_chunk to guess locations.
332 // If it isn't 0 synthesize samples per chunk table to get locations.
333 // McRowesoft doesn't really obey this rule so we may need to base it on codec ID.
334 bytes_per_sample
= quicktime_read_int32_le(file
);
335 //printf("quicktime_read_strl 20 %d\n", samples_per_chunk);
340 if(quicktime_atom_is(&leaf_atom
, "strf"))
344 /* atom size repeated */
345 quicktime_read_int32_le(file
);
346 width
= quicktime_read_int32_le(file
);
347 height
= quicktime_read_int32_le(file
);
349 quicktime_read_int16_le(file
);
351 depth
= quicktime_read_int16_le(file
);
352 quicktime_read_data(file
,
359 compression_id
= quicktime_read_int16_le(file
);
360 channels
= quicktime_read_int16_le(file
);
361 sample_rate
= quicktime_read_int32_le(file
);
362 quicktime_set_position(file
, quicktime_position(file
) + 6);
363 sample_size
= quicktime_read_int16_le(file
);
364 //printf("quicktime_read_strl 40 %d %d %d\n", channels, sample_rate, sample_size);
369 // Read the super index + all the partial indexes now
370 if(quicktime_atom_is(&leaf_atom
, "indx"))
372 //printf("quicktime_read_strl 50\n");
373 quicktime_read_indx(file
, strl
, &leaf_atom
);
377 //printf("quicktime_read_strl 60\n");
381 quicktime_atom_skip(file
, &leaf_atom
);
382 }while(quicktime_position(file
) < parent_atom
->end
);
383 //printf("quicktime_read_strl 70 %d %d\n", strl->is_audio, strl->is_video);
388 /* Generate quicktime structures */
389 quicktime_trak_init_video(file
,
395 quicktime_mhvd_init_video(file
,
398 trak
->mdia
.mdhd
.duration
= frames
;
399 // trak->mdia.mdhd.time_scale = 1;
400 memcpy(trak
->mdia
.minf
.stbl
.stsd
.table
[0].format
, codec
, 4);
401 trak
->mdia
.minf
.stbl
.stsd
.table
[0].depth
= depth
;
406 /* Generate quicktime structures */
407 //printf("quicktime_read_strl 70 %d\n", sample_size);
408 quicktime_trak_init_audio(file
,
416 // We store a constant samples per chunk based on the
417 // packet size if sample_size zero
418 // and calculate the samples per chunk based on the chunk size if sample_size
420 // trak->mdia.minf.stbl.stsd.table[0].sample_size = bytes_per_sample;
421 trak
->mdia
.minf
.stbl
.stsd
.table
[0].compression_id
= compression_id
;
423 /* Synthesize stsc table for constant samples per chunk */
424 if(!bytes_per_sample
)
426 /* Should be enough entries allocated in quicktime_stsc_init_table */
427 trak
->mdia
.minf
.stbl
.stsc
.table
[0].samples
= samples_per_chunk
;
428 trak
->mdia
.minf
.stbl
.stsc
.total_entries
= 1;
433 //printf("quicktime_read_strl 100\n");