initial commit
[goodguy/history.git] / cinelerra-5.0 / quicktime / avi_hdrl.c
1 #include "funcprotos.h"
2 #include "quicktime.h"
3
4
5
6 void quicktime_delete_hdrl(quicktime_t *file, quicktime_hdrl_t *hdrl)
7 {
8         int i;
9         for(i = 0; i < file->moov.total_tracks; i++)
10         {
11                 quicktime_delete_strl(hdrl->strl[i]);
12         }
13 }
14
15
16 void quicktime_read_hdrl(quicktime_t *file,
17         quicktime_hdrl_t *hdrl,
18         quicktime_atom_t *parent_atom)
19 {
20         quicktime_atom_t leaf_atom;
21         char data[4];
22         int current_track = 0;
23
24 //printf("quicktime_read_hdrl 1\n");
25         do
26         {
27                 quicktime_atom_read_header(file, &leaf_atom);
28
29 /* Got LIST */
30                 if(quicktime_atom_is(&leaf_atom, "LIST"))
31                 {
32                         data[0] = data[1] = data[2] = data[3] = 0;
33                         quicktime_read_data(file, data, 4);
34
35 /* Got strl */
36                         if(quicktime_match_32(data, "strl"))
37                         {
38                                 quicktime_strl_t *strl =
39                                         hdrl->strl[current_track++] =
40                                         quicktime_new_strl();
41                                 quicktime_read_strl(file, strl, &leaf_atom);
42                         }
43                 }
44
45                 quicktime_atom_skip(file, &leaf_atom);
46         }while(quicktime_position(file) < parent_atom->end);
47
48         quicktime_atom_skip(file, &leaf_atom);
49 }
50
51 void quicktime_init_hdrl(quicktime_t *file, quicktime_hdrl_t *hdrl)
52 {
53         int i;
54         quicktime_atom_t avih_atom;
55         int current_track;
56
57 // LIST 'hdrl'
58         quicktime_atom_write_header(file, &hdrl->atom, "LIST");
59         quicktime_write_char32(file, "hdrl");
60
61
62 // avih
63         quicktime_atom_write_header(file, &avih_atom, "avih");
64
65         if(file->total_vtracks) {
66                 int d = quicktime_frame_rate_d(file, 0);
67                 int n = quicktime_frame_rate_n(file, 0);
68                 quicktime_write_int32_le(file, (uint32_t)(1000000. * d / n));
69         }
70         else
71                 quicktime_write_int32_le(file, 0);
72
73         hdrl->bitrate_offset = quicktime_position(file);
74         quicktime_write_int32_le(file, 0); /* bitrate in bytes */
75     quicktime_write_int32_le(file, 0); /* padding */
76     quicktime_write_int32_le(file,
77                 AVI_TRUSTCKTYPE |
78                 AVI_HASINDEX |
79                 AVI_MUSTUSEINDEX |
80                 AVI_ISINTERLEAVED); /* flags */
81         hdrl->frames_offset = quicktime_position(file);
82     quicktime_write_int32_le(file, 0); /* nb frames, filled later */
83     quicktime_write_int32_le(file, 0); /* initial frame */
84     quicktime_write_int32_le(file, file->moov.total_tracks); /* nb streams */
85     quicktime_write_int32_le(file, 0); /* suggested buffer size */
86
87         if(file->total_vtracks)
88     {
89                 quicktime_write_int32_le(file, file->vtracks[0].track->tkhd.track_width);
90         quicktime_write_int32_le(file, file->vtracks[0].track->tkhd.track_height);
91         }
92         else
93     {
94                 quicktime_write_int32_le(file, 0);
95         quicktime_write_int32_le(file, 0);
96         }
97     quicktime_write_int32_le(file, 0); /* reserved */
98     quicktime_write_int32_le(file, 0); /* reserved */
99     quicktime_write_int32_le(file, 0); /* reserved */
100     quicktime_write_int32_le(file, 0); /* reserved */
101
102         quicktime_atom_write_footer(file, &avih_atom);
103
104
105 /* Write stream lists. */
106 /* Need the track maps to get the WAV ID for audio. */
107         current_track = 0;
108         for(i = 0; i < file->total_vtracks; i++)
109         {
110                 quicktime_video_map_t *video_map = &file->vtracks[i];
111                 quicktime_trak_t *trak = video_map->track;
112                 quicktime_strl_t *strl =
113                         hdrl->strl[current_track++] =
114                         quicktime_new_strl();
115                 quicktime_init_strl(file,
116                         0,
117                         video_map,
118                         trak,
119                         strl);
120         }
121
122         for(i = 0; i < file->total_atracks; i++)
123         {
124                 quicktime_audio_map_t *audio_map = &file->atracks[i];
125                 quicktime_trak_t *trak = audio_map->track;
126                 quicktime_strl_t *strl =
127                         hdrl->strl[current_track++] =
128                         quicktime_new_strl();
129                 quicktime_init_strl(file,
130                         audio_map,
131                         0,
132                         trak,
133                         strl);
134         }
135
136 /*
137  * for(i = 0; i < file->moov.total_tracks; i++)
138  * {
139  * printf("quicktime_init_hdrl 10 %d %p\n", i, file->riff[0]->hdrl.strl[i]->tag);
140  * }
141  */
142
143 /* ODML header */
144         quicktime_init_odml(file, hdrl);
145         quicktime_atom_write_footer(file, &hdrl->atom);
146 }
147
148
149 void quicktime_finalize_hdrl(quicktime_t *file, quicktime_hdrl_t *hdrl)
150 {
151         int i;
152         int64_t position = quicktime_position(file);
153         int64_t total_frames = 0;
154         double frame_rate = 0;
155
156         for(i = 0; i < file->moov.total_tracks; i++)
157         {
158                 quicktime_trak_t *trak = file->moov.trak[i];
159                 quicktime_strl_t *strl = hdrl->strl[i];
160
161                 if(trak->mdia.minf.is_video)
162                 {
163                         int length;
164                         quicktime_set_position(file, strl->length_offset);
165                         total_frames = length = quicktime_track_samples(file, trak);
166                         quicktime_write_int32_le(file, length);
167                         frame_rate = (double)trak->mdia.mdhd.time_scale /
168                                 trak->mdia.minf.stbl.stts.table[0].sample_duration;
169                 }
170                 else
171                 if(trak->mdia.minf.is_audio)
172                 {
173                         int length, samples_per_chunk, wav_id, sample_size, sample_rate;
174                         quicktime_set_position(file, strl->length_offset);
175                         length = quicktime_track_samples(file, trak);
176                         quicktime_write_int32_le(file, length);
177
178 // dwScale and dwRate as per MSDN - // http://msdn.microsoft.com/library/default.asp?
179 //   url=/library/en-us/wcemultimedia5/html/wce50conAVIStreamHeaders.asp
180                         quicktime_set_position(file, strl->samples_per_chunk_offset);
181                         wav_id = ((quicktime_codec_t*)(file->atracks[0].codec))->wav_id;
182                         samples_per_chunk = wav_id == 1 ? 1 :
183                                 quicktime_avg_chunk_samples(file, trak);
184                         quicktime_write_int32_le(file, samples_per_chunk);
185                         sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
186                         quicktime_write_int32_le(file, sample_rate);
187                         quicktime_set_position(file, strl->sample_size_offset);
188
189 // dwSampleSize as per MSDN
190 // as per http://www.virtualdub.org/blog/pivot/entry.php?id=27, many programs ignore this value
191 // sample_size in quicktime is in bits... so we must divide by 8
192 // FIXME: This has to be zero for _all_ VBR encodings, and other values are used for specific encodings
193                         sample_size = trak->mdia.minf.stbl.stsd.table[0].sample_size;
194                         quicktime_write_int32_le(file, wav_id != 1 ? sample_size :
195                                 trak->mdia.minf.stbl.stsd.table[0].channels * sample_size / 8);
196                 }
197         }
198
199         if(total_frames)
200         {
201                 quicktime_set_position(file, hdrl->bitrate_offset);
202                 quicktime_write_int32_le(file,
203                         file->total_length / (total_frames / frame_rate));
204                 quicktime_set_position(file, hdrl->frames_offset);
205                 quicktime_write_int32_le(file, total_frames);
206         }
207
208         quicktime_set_position(file, position);
209 }
210
211
212
213
214
215
216