bunch of small fixes, add msg.txt to about prefs
[goodguy/history.git] / cinelerra-5.0 / quicktime / stsdtable.c
1 #include "funcprotos.h"
2 #include "quicktime.h"
3 #include <string.h>
4
5
6 void quicktime_mjqt_init(quicktime_mjqt_t *mjqt)
7 {
8 }
9
10 void quicktime_mjqt_delete(quicktime_mjqt_t *mjqt)
11 {
12 }
13
14 void quicktime_mjqt_dump(quicktime_mjqt_t *mjqt)
15 {
16 }
17
18
19 void quicktime_mjht_init(quicktime_mjht_t *mjht)
20 {
21 }
22
23 void quicktime_mjht_delete(quicktime_mjht_t *mjht)
24 {
25 }
26
27 void quicktime_mjht_dump(quicktime_mjht_t *mjht)
28 {
29 }
30
31 // Set esds header to a copy of the argument
32 void quicktime_set_mpeg4_header(quicktime_stsd_table_t *table,
33         unsigned char *data, 
34         int size)
35 {
36         if(table->esds.mpeg4_header)
37         {
38                 free(table->esds.mpeg4_header);
39         }
40
41         table->esds.mpeg4_header = calloc(1, size);
42         memcpy(table->esds.mpeg4_header, data, size);
43         table->esds.mpeg4_header_size = size;
44 }
45
46 static void read_wave(quicktime_t *file, 
47         quicktime_stsd_table_t *table, 
48         quicktime_atom_t *parent_atom)
49 {
50         quicktime_atom_t leaf_atom;
51 //printf("read_wave 1 start=0x%llx\n", quicktime_position(file));
52         while(quicktime_position(file) < parent_atom->end)
53         {
54                 quicktime_atom_read_header(file, &leaf_atom);
55                 if(quicktime_atom_is(&leaf_atom, "esds"))
56                 {
57                         quicktime_read_esds(file, &leaf_atom, &table->esds);
58                 }
59                 else
60                 if(quicktime_atom_is(&leaf_atom, "frma"))
61                 {
62 // Extra data for QDM2
63                         quicktime_read_frma(file, parent_atom, &leaf_atom, &table->frma);
64                 }
65                 else
66                         quicktime_atom_skip(file, &leaf_atom);
67         }
68 }
69
70 void quicktime_read_stsd_audio(quicktime_t *file, 
71         quicktime_stsd_table_t *table, 
72         quicktime_atom_t *parent_atom)
73 {
74         quicktime_atom_t leaf_atom;
75
76         table->version = quicktime_read_int16(file);
77         table->revision = quicktime_read_int16(file);
78         quicktime_read_data(file, table->vendor, 4);
79         table->channels = quicktime_read_int16(file);
80         table->sample_size = quicktime_read_int16(file);
81         table->compression_id = quicktime_read_int16(file);
82         table->packet_size = quicktime_read_int16(file);
83         table->sample_rate = quicktime_read_fixed32(file);
84
85 // Kluge for fixed32 limitation
86 if(table->sample_rate + 65536 == 96000 ||
87         table->sample_rate + 65536 == 88200) table->sample_rate += 65536;
88
89
90 // Version 1 fields
91         if(table->version > 0)
92         {
93                 table->samples_per_packet = quicktime_read_int32(file);
94                 table->bytes_per_packet = quicktime_read_int32(file);
95                 table->bytes_per_frame = quicktime_read_int32(file);
96                 table->bytes_per_sample = quicktime_read_int32(file);
97
98 // Skip another 20 bytes
99                 if(table->version == 2)
100                 {
101                         quicktime_set_position(file, quicktime_position(file) + 0x14);
102                 }
103         }
104
105         while(quicktime_position(file) < parent_atom->end) {
106                 quicktime_atom_read_header(file, &leaf_atom);
107                 if( quicktime_atom_is(&leaf_atom, "wave") )
108                         read_wave(file, table, &leaf_atom);
109                 else if( quicktime_atom_is(&leaf_atom, "esds") )
110                         quicktime_read_esds(file, &leaf_atom, &table->esds);
111                 else
112                         quicktime_atom_skip(file, &leaf_atom);
113         }
114
115 // FFMPEG says the esds sometimes contains a sample rate that overrides
116 // the sample table.
117         quicktime_esds_samplerate(table, &table->esds);
118 }
119
120 void quicktime_write_stsd_audio(quicktime_t *file, quicktime_stsd_table_t *table)
121 {
122         quicktime_write_int16(file, table->version);
123         quicktime_write_int16(file, table->revision);
124         quicktime_write_data(file, table->vendor, 4);
125         quicktime_write_int16(file, table->channels);
126         quicktime_write_int16(file, table->sample_size);
127
128         quicktime_write_int16(file, table->compression_id);
129         quicktime_write_int16(file, table->packet_size);
130         quicktime_write_fixed32(file, table->sample_rate);
131
132 // Write header for mp4a
133         if(table->esds.mpeg4_header_size && table->esds.mpeg4_header)
134         {
135 // Android requires leaving out the WAVE header
136                 if( table->version > 0 ) {
137 // newer version info
138                         int padding = table->version == 1 ?
139                                 0x10/sizeof(int32_t) : 0x24/sizeof(int32_t);
140                         while( --padding >= 0 ) quicktime_write_int32(file, 0);
141
142                         quicktime_atom_t wave_atom;
143                         quicktime_atom_t frma_atom;
144                         quicktime_atom_t mp4a_atom;
145                         quicktime_atom_write_header(file, &wave_atom, "wave");
146
147                         quicktime_atom_write_header(file, &frma_atom, "frma");
148                         quicktime_write_data(file, "mp4a", 4);
149                         quicktime_atom_write_footer(file, &frma_atom);
150         
151                         quicktime_atom_write_header(file, &mp4a_atom, "mp4a");
152                         quicktime_write_int32(file, 0x0);
153                         quicktime_atom_write_footer(file, &mp4a_atom);
154                         quicktime_write_esds(file, &table->esds, 0, 1);
155                         quicktime_atom_write_footer(file, &wave_atom);
156                 }
157                 else
158                         quicktime_write_esds(file, &table->esds, 0, 1);
159         }
160 }
161
162 // Lifted from mplayer and changed a bit
163 struct __attribute__((__packed__)) ImageDescription {
164 //  int32_t                    idSize;                     /* total size of ImageDescription including extra data ( CLUTs and other per sequence data ) */
165     char                       cType[4];                   /* what kind of codec compressed this data */
166     int32_t                    resvd1;                     /* reserved for Apple use */
167     int16_t                    resvd2;                     /* reserved for Apple use */
168     int16_t                    dataRefIndex;               /* set to zero  */
169     int16_t                    version;                    /* which version is this data */
170     int16_t                    revisionLevel;              /* what version of that codec did this */
171     char                       vendor[4];                  /* whose  codec compressed this data */
172     uint32_t                   temporalQuality;            /* what was the temporal quality factor  */
173     uint32_t                   spatialQuality;             /* what was the spatial quality factor */
174     int16_t                    width;                      /* how many pixels wide is this data */
175     int16_t                    height;                     /* how many pixels high is this data */
176     int32_t                    hRes;                       /* horizontal resolution */
177     int32_t                    vRes;                       /* vertical resolution */
178     int32_t                    dataSize;                   /* if known, the size of data for this image descriptor */
179     int16_t                    frameCount;                 /* number of frames this description applies to */
180     char                       name[32];                   /* name of codec ( in case not installed )  */
181     int16_t                    depth;                      /* what depth is this data (1-32) or ( 33-40 grayscale ) */
182     int16_t                    clutID;                     /* clut id or if 0 clut follows  or -1 if no clut */
183 };
184
185
186 void quicktime_read_stsd_video(quicktime_t *file, 
187         quicktime_stsd_table_t *table, 
188         quicktime_atom_t *parent_atom)
189 {
190         quicktime_atom_t leaf_atom;
191         int len;
192         
193         table->version = quicktime_read_int16(file);
194         table->revision = quicktime_read_int16(file);
195         quicktime_read_data(file, table->vendor, 4);
196         table->temporal_quality = quicktime_read_int32(file);
197         table->spatial_quality = quicktime_read_int32(file);
198         table->width = quicktime_read_int16(file);
199         table->height = quicktime_read_int16(file);
200         table->dpi_horizontal = quicktime_read_fixed32(file);
201         table->dpi_vertical = quicktime_read_fixed32(file);
202         table->data_size = quicktime_read_int32(file);
203         table->frames_per_sample = quicktime_read_int16(file);
204         len = quicktime_read_char(file);
205         quicktime_read_data(file, table->compressor_name, 31);
206         table->depth = quicktime_read_int16(file);
207         table->ctab_id = quicktime_read_int16(file);
208
209
210 /* The data needed for SVQ3 codec and maybe some others ? */
211         struct ImageDescription *id;
212         int stsd_size = parent_atom->end - parent_atom->start;
213         table->extradata_size = stsd_size - 4;
214         id = (struct ImageDescription *) malloc(table->extradata_size);     // we do not include size
215         table->extradata = (char *) id;
216         
217         memcpy(id->cType, table->format, 4);         // Fourcc
218         id->version = table->version;
219         id->revisionLevel = table->revision;
220         memcpy(id->vendor, table->vendor, 4);     // I think mplayer screws up on this one, it turns bytes around! :)
221         id->temporalQuality = table->temporal_quality;
222         id->spatialQuality = table->spatial_quality;
223         id->width = table->width;
224         id->height = table->height;
225         id->hRes = table->dpi_horizontal;
226         id->vRes = table->dpi_vertical;
227         id->dataSize = table->data_size;
228         id->frameCount = table->frames_per_sample;
229         id->name[0] = len;
230         memcpy(&(id->name[1]), table->compressor_name, 31);
231         id->depth = table->depth;
232         id->clutID = table->ctab_id;
233         if (quicktime_position(file) < parent_atom->end)
234         {
235                 int position = quicktime_position(file);     // remember position
236                 int datalen = parent_atom->end - position;
237                 quicktime_read_data(file, ((char*)&id->clutID)+2, datalen);
238                 quicktime_set_position(file, position);      // return to previous position so parsing can go on
239         }
240         
241         while(quicktime_position(file) < parent_atom->end)
242         {
243                 quicktime_atom_read_header(file, &leaf_atom);
244 /*
245  * printf("quicktime_read_stsd_video 1 %llx %llx %llx %s\n", 
246  * leaf_atom.start, leaf_atom.end, quicktime_position(file),
247  * leaf_atom.type);
248  */
249
250
251                 if(quicktime_atom_is(&leaf_atom, "esds"))
252                 {
253                         quicktime_read_esds(file, &leaf_atom, &table->esds);
254                 }
255                 else
256                 if(quicktime_atom_is(&leaf_atom, "avcC"))
257                 {
258                         quicktime_read_avcc(file, &leaf_atom, &table->avcc);
259                 }
260                 else
261                 if(quicktime_atom_is(&leaf_atom, "ctab"))
262                 {
263                         quicktime_read_ctab(file, &(table->ctab));
264                 }
265                 else
266                 if(quicktime_atom_is(&leaf_atom, "gama"))
267                 {
268                         table->gamma = quicktime_read_fixed32(file);
269                 }
270                 else
271                 if(quicktime_atom_is(&leaf_atom, "fiel"))
272                 {
273                         table->fields = quicktime_read_char(file);
274                         table->field_dominance = quicktime_read_char(file);
275                 }
276                 else
277                         quicktime_atom_skip(file, &leaf_atom);
278
279
280 /*              if(quicktime_atom_is(&leaf_atom, "mjqt")) */
281 /*              { */
282 /*                      quicktime_read_mjqt(file, &(table->mjqt)); */
283 /*              } */
284 /*              else */
285 /*              if(quicktime_atom_is(&leaf_atom, "mjht")) */
286 /*              { */
287 /*                      quicktime_read_mjht(file, &(table->mjht)); */
288 /*              } */
289 /*              else */
290         }
291 //printf("quicktime_read_stsd_video 2\n");
292 }
293
294 void quicktime_write_stsd_video(quicktime_t *file, quicktime_stsd_table_t *table)
295 {
296         quicktime_write_int16(file, table->version);
297         quicktime_write_int16(file, table->revision);
298         quicktime_write_data(file, table->vendor, 4);
299         quicktime_write_int32(file, table->temporal_quality);
300         quicktime_write_int32(file, table->spatial_quality);
301         quicktime_write_int16(file, table->width);
302         quicktime_write_int16(file, table->height);
303         quicktime_write_fixed32(file, table->dpi_horizontal);
304         quicktime_write_fixed32(file, table->dpi_vertical);
305         quicktime_write_int32(file, table->data_size);
306         quicktime_write_int16(file, table->frames_per_sample);
307         quicktime_write_char(file, strlen(table->compressor_name));
308         quicktime_write_data(file, table->compressor_name, 31);
309         quicktime_write_int16(file, table->depth);
310         quicktime_write_int16(file, table->ctab_id);
311
312
313 // Write field order for mjpa
314         if(table->fields)
315         {
316                 quicktime_atom_t atom;
317
318                 quicktime_atom_write_header(file, &atom, "fiel");
319                 quicktime_write_char(file, table->fields);
320                 quicktime_write_char(file, table->field_dominance);
321                 quicktime_atom_write_footer(file, &atom);
322         }
323
324 // Write header for mp4v
325         if(table->esds.mpeg4_header_size && table->esds.mpeg4_header)
326         {
327                 quicktime_write_esds(file, &table->esds, 1, 0);
328         }
329
330         if(table->avcc.data_size)
331         {
332                 quicktime_write_avcc(file, &table->avcc);
333         }
334
335 // Write another 32 bits
336         if(table->version == 1)
337                 quicktime_write_int32(file, 0x0);
338 }
339
340 void quicktime_read_stsd_table(quicktime_t *file, quicktime_minf_t *minf, quicktime_stsd_table_t *table)
341 {
342         quicktime_atom_t leaf_atom;
343
344         quicktime_atom_read_header(file, &leaf_atom);
345
346         table->format[0] = leaf_atom.type[0];
347         table->format[1] = leaf_atom.type[1];
348         table->format[2] = leaf_atom.type[2];
349         table->format[3] = leaf_atom.type[3];
350         quicktime_read_data(file, table->reserved, 6);
351         table->data_reference = quicktime_read_int16(file);
352
353         if(minf->is_audio) quicktime_read_stsd_audio(file, table, &leaf_atom);
354         if(minf->is_video) quicktime_read_stsd_video(file, table, &leaf_atom);
355 }
356
357 void quicktime_stsd_table_init(quicktime_stsd_table_t *table)
358 {
359         int i;
360         table->format[0] = 'y';
361         table->format[1] = 'u';
362         table->format[2] = 'v';
363         table->format[3] = '2';
364         for(i = 0; i < 6; i++) table->reserved[i] = 0;
365         table->data_reference = 1;
366
367         table->version = 0;
368         table->revision = 0;
369         table->vendor[0] = 'l';
370         table->vendor[1] = 'n';
371         table->vendor[2] = 'u';
372         table->vendor[3] = 'x';
373
374         table->temporal_quality = 100;
375         table->spatial_quality = 258;
376         table->width = 0;
377         table->height = 0;
378         table->dpi_horizontal = 72;
379         table->dpi_vertical = 72;
380         table->data_size = 0;
381         table->frames_per_sample = 1;
382         for(i = 0; i < 32; i++) table->compressor_name[i] = 0;
383         sprintf(table->compressor_name, "Quicktime for Linux");
384         table->depth = 24;
385         table->ctab_id = 65535;
386         quicktime_ctab_init(&(table->ctab));
387         table->gamma = 0;
388         table->fields = 0;
389         table->field_dominance = 1;
390         quicktime_mjqt_init(&(table->mjqt));
391         quicktime_mjht_init(&(table->mjht));
392         
393         table->channels = 0;
394         table->sample_size = 0;
395         table->compression_id = 0;
396         table->packet_size = 0;
397         table->sample_rate = 0;
398
399         table->extradata = 0;
400         table->extradata_size = 0;
401 }
402
403 void quicktime_stsd_table_delete(quicktime_stsd_table_t *table)
404 {
405         quicktime_ctab_delete(&(table->ctab));
406         quicktime_mjqt_delete(&(table->mjqt));
407         quicktime_mjht_delete(&(table->mjht));
408         quicktime_delete_avcc(&(table->avcc));
409         quicktime_delete_esds(&(table->esds));
410         quicktime_delete_frma(&(table->frma));
411         
412 }
413
414 void quicktime_stsd_video_dump(quicktime_stsd_table_t *table)
415 {
416         printf("       version %d\n", table->version);
417         printf("       revision %d\n", table->revision);
418         printf("       vendor %c%c%c%c\n", table->vendor[0], table->vendor[1], table->vendor[2], table->vendor[3]);
419         printf("       temporal_quality %ld\n", table->temporal_quality);
420         printf("       spatial_quality %ld\n", table->spatial_quality);
421         printf("       width %d\n", table->width);
422         printf("       height %d\n", table->height);
423         printf("       dpi_horizontal %f\n", table->dpi_horizontal);
424         printf("       dpi_vertical %f\n", table->dpi_vertical);
425         printf("       data_size %ld\n", table->data_size);
426         printf("       frames_per_sample %d\n", table->frames_per_sample);
427         printf("       compressor_name %s\n", table->compressor_name);
428         printf("       depth %d\n", table->depth);
429         printf("       ctab_id %d\n", table->ctab_id);
430         printf("       gamma %f\n", table->gamma);
431         if(table->fields)
432         {
433                 printf("       fields %d\n", table->fields);
434                 printf("       field dominance %d\n", table->field_dominance);
435         }
436         if(!table->ctab_id) quicktime_ctab_dump(&(table->ctab));
437         quicktime_mjqt_dump(&(table->mjqt));
438         quicktime_mjht_dump(&(table->mjht));
439         quicktime_esds_dump(&table->esds);
440         quicktime_avcc_dump(&table->avcc);
441         quicktime_frma_dump(&table->frma);
442 }
443
444 void quicktime_stsd_audio_dump(quicktime_stsd_table_t *table)
445 {
446         printf("       version %d\n", table->version);
447         printf("       revision %d\n", table->revision);
448         printf("       vendor %c%c%c%c\n", table->vendor[0], table->vendor[1], table->vendor[2], table->vendor[3]);
449         printf("       channels %d\n", table->channels);
450         printf("       sample_size %d\n", table->sample_size);
451         printf("       compression_id 0x%x\n", table->compression_id);
452         printf("       packet_size %d\n", table->packet_size);
453         printf("       sample_rate %f\n", table->sample_rate);
454         if(table->version > 0)
455         {
456                 printf("       samples_per_packet %d\n", table->samples_per_packet);
457                 printf("       bytes_per_packet %d\n", table->bytes_per_packet);
458                 printf("       bytes_per_frame %d\n", table->bytes_per_frame);
459                 printf("       bytes_per_sample %d\n", table->bytes_per_sample);
460         }
461         quicktime_esds_dump(&table->esds);
462         quicktime_avcc_dump(&table->avcc);
463         quicktime_frma_dump(&table->frma);
464 }
465
466 void quicktime_stsd_table_dump(void *minf_ptr, quicktime_stsd_table_t *table)
467 {
468         quicktime_minf_t *minf = minf_ptr;
469         printf("       format %c%c%c%c\n", table->format[0], table->format[1], table->format[2], table->format[3]);
470         quicktime_print_chars("       reserved ", table->reserved, 6);
471         printf("       data_reference %d\n", table->data_reference);
472
473         if(minf->is_audio) quicktime_stsd_audio_dump(table);
474         if(minf->is_video) quicktime_stsd_video_dump(table);
475 }
476
477 void quicktime_write_stsd_table(quicktime_t *file, quicktime_minf_t *minf, quicktime_stsd_table_t *table)
478 {
479         quicktime_atom_t atom;
480         quicktime_atom_write_header(file, &atom, table->format);
481 /*printf("quicktime_write_stsd_table %c%c%c%c\n", table->format[0], table->format[1], table->format[2], table->format[3]); */
482         quicktime_write_data(file, table->reserved, 6);
483         quicktime_write_int16(file, table->data_reference);
484         
485         if(minf->is_audio) quicktime_write_stsd_audio(file, table);
486         if(minf->is_video) quicktime_write_stsd_video(file, table);
487
488         quicktime_atom_write_footer(file, &atom);
489 }