00001 #include "funcprotos.h"
00002 #include "quicktime.h"
00003 #include <string.h>
00004
00005
00006 void quicktime_mjqt_init(quicktime_mjqt_t *mjqt)
00007 {
00008 }
00009
00010 void quicktime_mjqt_delete(quicktime_mjqt_t *mjqt)
00011 {
00012 }
00013
00014 void quicktime_mjqt_dump(quicktime_mjqt_t *mjqt)
00015 {
00016 }
00017
00018
00019 void quicktime_mjht_init(quicktime_mjht_t *mjht)
00020 {
00021 }
00022
00023 void quicktime_mjht_delete(quicktime_mjht_t *mjht)
00024 {
00025 }
00026
00027 void quicktime_mjht_dump(quicktime_mjht_t *mjht)
00028 {
00029 }
00030
00031
00032 void quicktime_set_mpeg4_header(quicktime_stsd_table_t *table,
00033 unsigned char *data,
00034 int size)
00035 {
00036 if(table->esds.mpeg4_header)
00037 {
00038 free(table->esds.mpeg4_header);
00039 }
00040
00041 table->esds.mpeg4_header = calloc(1, size);
00042 memcpy(table->esds.mpeg4_header, data, size);
00043 table->esds.mpeg4_header_size = size;
00044 }
00045
00046 static void read_wave(quicktime_t *file,
00047 quicktime_stsd_table_t *table,
00048 quicktime_atom_t *parent_atom)
00049 {
00050 quicktime_atom_t leaf_atom;
00051 while(quicktime_position(file) < parent_atom->end)
00052 {
00053 quicktime_atom_read_header(file, &leaf_atom);
00054 if(quicktime_atom_is(&leaf_atom, "esds"))
00055 {
00056 quicktime_read_esds(file, &leaf_atom, &table->esds);
00057 }
00058 else
00059 quicktime_atom_skip(file, &leaf_atom);
00060 }
00061 }
00062
00063 void quicktime_read_stsd_audio(quicktime_t *file,
00064 quicktime_stsd_table_t *table,
00065 quicktime_atom_t *parent_atom)
00066 {
00067 quicktime_atom_t leaf_atom;
00068
00069 table->version = quicktime_read_int16(file);
00070 table->revision = quicktime_read_int16(file);
00071 quicktime_read_data(file, table->vendor, 4);
00072 table->channels = quicktime_read_int16(file);
00073 table->sample_size = quicktime_read_int16(file);
00074 table->compression_id = quicktime_read_int16(file);
00075 table->packet_size = quicktime_read_int16(file);
00076 table->sample_rate = quicktime_read_fixed32(file);
00077
00078
00079 if(table->sample_rate + 65536 == 96000 ||
00080 table->sample_rate + 65536 == 88200) table->sample_rate += 65536;
00081
00082
00083
00084 if(table->version > 0)
00085 {
00086 table->samples_per_packet = quicktime_read_int32(file);
00087 table->bytes_per_packet = quicktime_read_int32(file);
00088 table->bytes_per_frame = quicktime_read_int32(file);
00089 table->bytes_per_sample = quicktime_read_int32(file);
00090
00091
00092 if(table->version == 2)
00093 {
00094 quicktime_set_position(file, quicktime_position(file) + 0x14);
00095 }
00096
00097 while(quicktime_position(file) < parent_atom->end)
00098 {
00099 quicktime_atom_read_header(file, &leaf_atom);
00100
00101 if(quicktime_atom_is(&leaf_atom, "wave"))
00102 {
00103 read_wave(file, table, &leaf_atom);
00104 }
00105 else
00106 {
00107 quicktime_atom_skip(file, &leaf_atom);
00108 }
00109 }
00110 }
00111
00112
00113
00114 quicktime_esds_samplerate(table, &table->esds);
00115 }
00116
00117 void quicktime_write_stsd_audio(quicktime_t *file, quicktime_stsd_table_t *table)
00118 {
00119 quicktime_write_int16(file, table->version);
00120 quicktime_write_int16(file, table->revision);
00121 quicktime_write_data(file, table->vendor, 4);
00122 quicktime_write_int16(file, table->channels);
00123 quicktime_write_int16(file, table->sample_size);
00124
00125 quicktime_write_int16(file, table->compression_id);
00126 quicktime_write_int16(file, table->packet_size);
00127 quicktime_write_fixed32(file, table->sample_rate);
00128
00129
00130 if(table->esds.mpeg4_header_size && table->esds.mpeg4_header)
00131 {
00132
00133 quicktime_write_int32(file, 0);
00134 quicktime_write_int32(file, 0);
00135 quicktime_write_int32(file, 0);
00136 quicktime_write_int32(file, 0);
00137
00138 quicktime_atom_t wave_atom;
00139 quicktime_atom_t frma_atom;
00140 quicktime_atom_t mp4a_atom;
00141 quicktime_atom_write_header(file, &wave_atom, "wave");
00142
00143 quicktime_atom_write_header(file, &frma_atom, "frma");
00144 quicktime_write_data(file, "mp4a", 4);
00145 quicktime_atom_write_footer(file, &frma_atom);
00146
00147 quicktime_atom_write_header(file, &mp4a_atom, "mp4a");
00148 quicktime_write_int32(file, 0x0);
00149 quicktime_atom_write_footer(file, &mp4a_atom);
00150
00151 quicktime_write_esds(file, &table->esds, 0, 1);
00152 quicktime_atom_write_footer(file, &wave_atom);
00153 }
00154 }
00155
00156
00157 struct __attribute__((__packed__)) ImageDescription {
00158
00159 char cType[4];
00160 int32_t resvd1;
00161 int16_t resvd2;
00162 int16_t dataRefIndex;
00163 int16_t version;
00164 int16_t revisionLevel;
00165 char vendor[4];
00166 uint32_t temporalQuality;
00167 uint32_t spatialQuality;
00168 int16_t width;
00169 int16_t height;
00170 int32_t hRes;
00171 int32_t vRes;
00172 int32_t dataSize;
00173 int16_t frameCount;
00174 char name[32];
00175 int16_t depth;
00176 int16_t clutID;
00177 };
00178
00179
00180 void quicktime_read_stsd_video(quicktime_t *file,
00181 quicktime_stsd_table_t *table,
00182 quicktime_atom_t *parent_atom)
00183 {
00184 quicktime_atom_t leaf_atom;
00185 int len;
00186
00187 table->version = quicktime_read_int16(file);
00188 table->revision = quicktime_read_int16(file);
00189 quicktime_read_data(file, table->vendor, 4);
00190 table->temporal_quality = quicktime_read_int32(file);
00191 table->spatial_quality = quicktime_read_int32(file);
00192 table->width = quicktime_read_int16(file);
00193 table->height = quicktime_read_int16(file);
00194 table->dpi_horizontal = quicktime_read_fixed32(file);
00195 table->dpi_vertical = quicktime_read_fixed32(file);
00196 table->data_size = quicktime_read_int32(file);
00197 table->frames_per_sample = quicktime_read_int16(file);
00198 len = quicktime_read_char(file);
00199 quicktime_read_data(file, table->compressor_name, 31);
00200 table->depth = quicktime_read_int16(file);
00201 table->ctab_id = quicktime_read_int16(file);
00202
00203
00204
00205 struct ImageDescription *id;
00206 int stsd_size,fourcc,c,d;
00207 stsd_size = parent_atom->end - parent_atom->start;
00208 table->extradata_size = stsd_size - 4;
00209 id = (struct ImageDescription *) malloc(table->extradata_size);
00210 table->extradata = (char *) id;
00211
00212 memcpy(id->cType, table->format, 4);
00213 id->version = table->version;
00214 id->revisionLevel = table->revision;
00215 memcpy(id->vendor, table->vendor, 4);
00216 id->temporalQuality = table->temporal_quality;
00217 id->spatialQuality = table->spatial_quality;
00218 id->width = table->width;
00219 id->height = table->height;
00220 id->hRes = table->dpi_horizontal;
00221 id->vRes = table->dpi_vertical;
00222 id->dataSize = table->data_size;
00223 id->frameCount = table->frames_per_sample;
00224 id->name[0] = len;
00225 memcpy(&(id->name[1]), table->compressor_name, 31);
00226 id->depth = table->depth;
00227 id->clutID = table->ctab_id;
00228 if (quicktime_position(file) < parent_atom->end)
00229 {
00230 int position = quicktime_position(file);
00231 int datalen = parent_atom->end - position;
00232 quicktime_read_data(file, ((char*)&id->clutID)+2, datalen);
00233 quicktime_set_position(file, position);
00234 }
00235
00236
00237 while(quicktime_position(file) < parent_atom->end)
00238 {
00239 quicktime_atom_read_header(file, &leaf_atom);
00240
00241
00242
00243
00244
00245
00246
00247 if(quicktime_atom_is(&leaf_atom, "esds"))
00248 {
00249 quicktime_read_esds(file, &leaf_atom, &table->esds);
00250 }
00251 else
00252 if(quicktime_atom_is(&leaf_atom, "avcC"))
00253 {
00254 quicktime_read_avcc(file, &leaf_atom, &table->avcc);
00255 }
00256 else
00257 if(quicktime_atom_is(&leaf_atom, "ctab"))
00258 {
00259 quicktime_read_ctab(file, &(table->ctab));
00260 }
00261 else
00262 if(quicktime_atom_is(&leaf_atom, "gama"))
00263 {
00264 table->gamma = quicktime_read_fixed32(file);
00265 }
00266 else
00267 if(quicktime_atom_is(&leaf_atom, "fiel"))
00268 {
00269 table->fields = quicktime_read_char(file);
00270 table->field_dominance = quicktime_read_char(file);
00271 }
00272 else
00273 quicktime_atom_skip(file, &leaf_atom);
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 }
00287
00288 }
00289
00290 void quicktime_write_stsd_video(quicktime_t *file, quicktime_stsd_table_t *table)
00291 {
00292 quicktime_write_int16(file, table->version);
00293 quicktime_write_int16(file, table->revision);
00294 quicktime_write_data(file, table->vendor, 4);
00295 quicktime_write_int32(file, table->temporal_quality);
00296 quicktime_write_int32(file, table->spatial_quality);
00297 quicktime_write_int16(file, table->width);
00298 quicktime_write_int16(file, table->height);
00299 quicktime_write_fixed32(file, table->dpi_horizontal);
00300 quicktime_write_fixed32(file, table->dpi_vertical);
00301 quicktime_write_int32(file, table->data_size);
00302 quicktime_write_int16(file, table->frames_per_sample);
00303 quicktime_write_char(file, strlen(table->compressor_name));
00304 quicktime_write_data(file, table->compressor_name, 31);
00305 quicktime_write_int16(file, table->depth);
00306 quicktime_write_int16(file, table->ctab_id);
00307
00308
00309
00310 if(table->fields)
00311 {
00312 quicktime_atom_t atom;
00313
00314 quicktime_atom_write_header(file, &atom, "fiel");
00315 quicktime_write_char(file, table->fields);
00316 quicktime_write_char(file, table->field_dominance);
00317 quicktime_atom_write_footer(file, &atom);
00318 }
00319
00320
00321 if(table->esds.mpeg4_header_size && table->esds.mpeg4_header)
00322 {
00323 quicktime_write_esds(file, &table->esds, 1, 0);
00324 }
00325
00326 if(table->avcc.data_size)
00327 {
00328 quicktime_write_avcc(file, &table->avcc);
00329 }
00330
00331
00332 if(table->version == 1)
00333 quicktime_write_int32(file, 0x0);
00334 }
00335
00336 void quicktime_read_stsd_table(quicktime_t *file, quicktime_minf_t *minf, quicktime_stsd_table_t *table)
00337 {
00338 quicktime_atom_t leaf_atom;
00339
00340 quicktime_atom_read_header(file, &leaf_atom);
00341
00342 table->format[0] = leaf_atom.type[0];
00343 table->format[1] = leaf_atom.type[1];
00344 table->format[2] = leaf_atom.type[2];
00345 table->format[3] = leaf_atom.type[3];
00346 quicktime_read_data(file, table->reserved, 6);
00347 table->data_reference = quicktime_read_int16(file);
00348
00349 if(minf->is_audio) quicktime_read_stsd_audio(file, table, &leaf_atom);
00350 if(minf->is_video) quicktime_read_stsd_video(file, table, &leaf_atom);
00351 }
00352
00353 void quicktime_stsd_table_init(quicktime_stsd_table_t *table)
00354 {
00355 int i;
00356 table->format[0] = 'y';
00357 table->format[1] = 'u';
00358 table->format[2] = 'v';
00359 table->format[3] = '2';
00360 for(i = 0; i < 6; i++) table->reserved[i] = 0;
00361 table->data_reference = 1;
00362
00363 table->version = 0;
00364 table->revision = 0;
00365 table->vendor[0] = 'l';
00366 table->vendor[1] = 'n';
00367 table->vendor[2] = 'u';
00368 table->vendor[3] = 'x';
00369
00370 table->temporal_quality = 100;
00371 table->spatial_quality = 258;
00372 table->width = 0;
00373 table->height = 0;
00374 table->dpi_horizontal = 72;
00375 table->dpi_vertical = 72;
00376 table->data_size = 0;
00377 table->frames_per_sample = 1;
00378 for(i = 0; i < 32; i++) table->compressor_name[i] = 0;
00379 sprintf(table->compressor_name, "Quicktime for Linux");
00380 table->depth = 24;
00381 table->ctab_id = 65535;
00382 quicktime_ctab_init(&(table->ctab));
00383 table->gamma = 0;
00384 table->fields = 0;
00385 table->field_dominance = 1;
00386 quicktime_mjqt_init(&(table->mjqt));
00387 quicktime_mjht_init(&(table->mjht));
00388
00389 table->channels = 0;
00390 table->sample_size = 0;
00391 table->compression_id = 0;
00392 table->packet_size = 0;
00393 table->sample_rate = 0;
00394
00395 table->extradata = 0;
00396 table->extradata_size = 0;
00397
00398 }
00399
00400 void quicktime_stsd_table_delete(quicktime_stsd_table_t *table)
00401 {
00402 quicktime_ctab_delete(&(table->ctab));
00403 quicktime_mjqt_delete(&(table->mjqt));
00404 quicktime_mjht_delete(&(table->mjht));
00405 if(table->extradata) free(table->extradata);
00406 quicktime_delete_avcc(&(table->avcc));
00407 quicktime_delete_esds(&(table->esds));
00408
00409 }
00410
00411 void quicktime_stsd_video_dump(quicktime_stsd_table_t *table)
00412 {
00413 printf(" version %d\n", table->version);
00414 printf(" revision %d\n", table->revision);
00415 printf(" vendor %c%c%c%c\n", table->vendor[0], table->vendor[1], table->vendor[2], table->vendor[3]);
00416 printf(" temporal_quality %ld\n", table->temporal_quality);
00417 printf(" spatial_quality %ld\n", table->spatial_quality);
00418 printf(" width %d\n", table->width);
00419 printf(" height %d\n", table->height);
00420 printf(" dpi_horizontal %f\n", table->dpi_horizontal);
00421 printf(" dpi_vertical %f\n", table->dpi_vertical);
00422 printf(" data_size %ld\n", table->data_size);
00423 printf(" frames_per_sample %d\n", table->frames_per_sample);
00424 printf(" compressor_name %s\n", table->compressor_name);
00425 printf(" depth %d\n", table->depth);
00426 printf(" ctab_id %d\n", table->ctab_id);
00427 printf(" gamma %f\n", table->gamma);
00428 if(table->fields)
00429 {
00430 printf(" fields %d\n", table->fields);
00431 printf(" field dominance %d\n", table->field_dominance);
00432 }
00433 if(!table->ctab_id) quicktime_ctab_dump(&(table->ctab));
00434 quicktime_mjqt_dump(&(table->mjqt));
00435 quicktime_mjht_dump(&(table->mjht));
00436 quicktime_esds_dump(&table->esds);
00437 quicktime_avcc_dump(&table->avcc);
00438 }
00439
00440 void quicktime_stsd_audio_dump(quicktime_stsd_table_t *table)
00441 {
00442 printf(" version %d\n", table->version);
00443 printf(" revision %d\n", table->revision);
00444 printf(" vendor %c%c%c%c\n", table->vendor[0], table->vendor[1], table->vendor[2], table->vendor[3]);
00445 printf(" channels %d\n", table->channels);
00446 printf(" sample_size %d\n", table->sample_size);
00447 printf(" compression_id %d\n", table->compression_id);
00448 printf(" packet_size %d\n", table->packet_size);
00449 printf(" sample_rate %f\n", table->sample_rate);
00450 if(table->version > 0)
00451 {
00452 printf(" samples_per_packet %d\n", table->samples_per_packet);
00453 printf(" bytes_per_packet %d\n", table->bytes_per_packet);
00454 printf(" bytes_per_frame %d\n", table->bytes_per_frame);
00455 printf(" bytes_per_sample %d\n", table->bytes_per_sample);
00456 }
00457 quicktime_esds_dump(&table->esds);
00458 quicktime_avcc_dump(&table->avcc);
00459 }
00460
00461 void quicktime_stsd_table_dump(void *minf_ptr, quicktime_stsd_table_t *table)
00462 {
00463 quicktime_minf_t *minf = minf_ptr;
00464 printf(" format %c%c%c%c\n", table->format[0], table->format[1], table->format[2], table->format[3]);
00465 quicktime_print_chars(" reserved ", table->reserved, 6);
00466 printf(" data_reference %d\n", table->data_reference);
00467
00468 if(minf->is_audio) quicktime_stsd_audio_dump(table);
00469 if(minf->is_video) quicktime_stsd_video_dump(table);
00470 }
00471
00472 void quicktime_write_stsd_table(quicktime_t *file, quicktime_minf_t *minf, quicktime_stsd_table_t *table)
00473 {
00474 quicktime_atom_t atom;
00475 quicktime_atom_write_header(file, &atom, table->format);
00476
00477 quicktime_write_data(file, table->reserved, 6);
00478 quicktime_write_int16(file, table->data_reference);
00479
00480 if(minf->is_audio) quicktime_write_stsd_audio(file, table);
00481 if(minf->is_video) quicktime_write_stsd_video(file, table);
00482
00483 quicktime_atom_write_footer(file, &atom);
00484 }