int quicktime_read_minf(quicktime_t *file, quicktime_minf_t *minf, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; long pos = quicktime_position(file); do { quicktime_atom_read_header(file, &leaf_atom); /* mandatory */ if(quicktime_atom_is(&leaf_atom, "vmhd")) { minf->is_video = 1; quicktime_read_vmhd(file, &(minf->vmhd)); } else if(quicktime_atom_is(&leaf_atom, "smhd")) { minf->is_audio = 1; quicktime_read_smhd(file, &(minf->smhd)); } else if(quicktime_atom_is(&leaf_atom, "gmhd")) { minf->is_hint = 1; quicktime_read_gmhd(file, &(minf->gmhd), &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "hmhd")) { minf->is_hint = 1; quicktime_read_hmhd(file, &(minf->hmhd), &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "hdlr")) { quicktime_read_hdlr(file, &(minf->hdlr)); /* Main Actor doesn't write component name */ quicktime_atom_skip(file, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "dinf")) { quicktime_read_dinf(file, &(minf->dinf), &leaf_atom); } else quicktime_atom_skip(file, &leaf_atom); }while(quicktime_position(file) < parent_atom->end); quicktime_set_position(file, pos); do { quicktime_atom_read_header(file, &leaf_atom); if(quicktime_atom_is(&leaf_atom, "stbl")) { quicktime_read_stbl(file, minf, &(minf->stbl), &leaf_atom); } else { quicktime_atom_skip(file, &leaf_atom); } } while(quicktime_position(file) < parent_atom->end); return 0; }
int quicktime_read_mdia(quicktime_t *file, quicktime_mdia_t *mdia, quicktime_atom_t *trak_atom) { quicktime_atom_t leaf_atom; do { quicktime_atom_read_header(file, &leaf_atom); /* mandatory */ if(quicktime_atom_is(&leaf_atom, "mdhd")) { quicktime_read_mdhd(file, &(mdia->mdhd)); } else if(quicktime_atom_is(&leaf_atom, "hdlr")) { quicktime_read_hdlr(file, &(mdia->hdlr)); /* Main Actor doesn't write component name */ quicktime_atom_skip(file, &leaf_atom); /*printf("quicktime_read_mdia %ld\n", quicktime_position(file)); */ } else if(quicktime_atom_is(&leaf_atom, "minf")) { quicktime_read_minf(file, &(mdia->minf), &leaf_atom); } else quicktime_atom_skip(file, &leaf_atom); }while(quicktime_position(file) < trak_atom->end); return 0; }
void quicktime_read_hdrl(quicktime_t *file, quicktime_hdrl_t *hdrl, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; char data[4]; int current_track = 0; //printf("quicktime_read_hdrl 1\n"); do { quicktime_atom_read_header(file, &leaf_atom); /* Got LIST */ if(quicktime_atom_is(&leaf_atom, "LIST")) { data[0] = data[1] = data[2] = data[3] = 0; quicktime_read_data(file, data, 4); /* Got strl */ if(quicktime_match_32(data, "strl")) { quicktime_strl_t *strl = hdrl->strl[current_track++] = quicktime_new_strl(); quicktime_read_strl(file, strl, &leaf_atom); } } quicktime_atom_skip(file, &leaf_atom); }while(quicktime_position(file) < parent_atom->end); quicktime_atom_skip(file, &leaf_atom); }
void quicktime_read_stsd_audio(quicktime_t *file, quicktime_stsd_table_t *table, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; table->version = quicktime_read_int16(file); table->revision = quicktime_read_int16(file); quicktime_read_data(file, table->vendor, 4); table->channels = quicktime_read_int16(file); table->sample_size = quicktime_read_int16(file); table->compression_id = quicktime_read_int16(file); table->packet_size = quicktime_read_int16(file); table->sample_rate = quicktime_read_fixed32(file); // Kluge for fixed32 limitation if(table->sample_rate + 65536 == 96000 || table->sample_rate + 65536 == 88200) table->sample_rate += 65536; // Version 1 fields if(table->version > 0) { table->samples_per_packet = quicktime_read_int32(file); table->bytes_per_packet = quicktime_read_int32(file); table->bytes_per_frame = quicktime_read_int32(file); table->bytes_per_sample = quicktime_read_int32(file); // Skip another 20 bytes if(table->version == 2) { quicktime_set_position(file, quicktime_position(file) + 0x14); } while(quicktime_position(file) < parent_atom->end) { quicktime_atom_read_header(file, &leaf_atom); if(quicktime_atom_is(&leaf_atom, "wave")) { read_wave(file, table, &leaf_atom); } else { quicktime_atom_skip(file, &leaf_atom); } } } // FFMPEG says the esds sometimes contains a sample rate that overrides // the sample table. quicktime_esds_samplerate(table, &table->esds); }
void quicktime_read_dinf(quicktime_t *file, quicktime_dinf_t *dinf, quicktime_atom_t *dinf_atom) { quicktime_atom_t leaf_atom; do { quicktime_atom_read_header(file, &leaf_atom); if(quicktime_atom_is(&leaf_atom, "dref")) { quicktime_read_dref(file, &(dinf->dref)); } else quicktime_atom_skip(file, &leaf_atom); }while(quicktime_position(file) < dinf_atom->end); }
int quicktime_read_gmhd(quicktime_t *file, quicktime_gmhd_t *gmhd, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; do { quicktime_atom_read_header(file, &leaf_atom); if (quicktime_atom_is(&leaf_atom, "gmin")) { quicktime_read_gmin(file, &(gmhd->gmin)); } else { quicktime_atom_skip(file, &leaf_atom); } } while (quicktime_position(file) < parent_atom->end); }
int quicktime_read_tref(quicktime_t *file, quicktime_tref_t *tref, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; do { quicktime_atom_read_header(file, &leaf_atom); if (quicktime_atom_is(&leaf_atom, "hint")) { quicktime_read_hint(file, &(tref->hint), &leaf_atom); } else { quicktime_atom_skip(file, &leaf_atom); } } while (quicktime_position(file) < parent_atom->end); }
int quicktime_read_moov(quicktime_t *file, quicktime_moov_t *moov, quicktime_atom_t *parent_atom) { /* mandatory mvhd */ quicktime_atom_t leaf_atom; do { quicktime_atom_read_header(file, &leaf_atom); if(quicktime_atom_is(&leaf_atom, "mvhd")) { quicktime_read_mvhd(file, &(moov->mvhd)); } else if(quicktime_atom_is(&leaf_atom, "iods")) { quicktime_read_iods(file, &(moov->iods)); quicktime_atom_skip(file, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "clip")) { quicktime_atom_skip(file, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "trak")) { quicktime_trak_t *trak = quicktime_add_trak(moov); quicktime_read_trak(file, trak, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "udta")) { quicktime_read_udta(file, &(moov->udta), &leaf_atom); quicktime_atom_skip(file, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "ctab")) { quicktime_read_ctab(file, &(moov->ctab)); } else { quicktime_atom_skip(file, &leaf_atom); } }while(quicktime_position(file) < parent_atom->end); return 0; }
void quicktime_read_stsd_table(quicktime_t *file, quicktime_minf_t *minf, quicktime_stsd_table_t *table) { quicktime_atom_t leaf_atom; quicktime_atom_read_header(file, &leaf_atom); table->format[0] = leaf_atom.type[0]; table->format[1] = leaf_atom.type[1]; table->format[2] = leaf_atom.type[2]; table->format[3] = leaf_atom.type[3]; quicktime_read_data(file, table->reserved, 6); table->data_reference = quicktime_read_int16(file); if(minf->is_audio) quicktime_read_stsd_audio(file, table, &leaf_atom); if(minf->is_video) quicktime_read_stsd_video(file, table, &leaf_atom); }
static void read_wave(quicktime_t *file, quicktime_stsd_table_t *table, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; while(quicktime_position(file) < parent_atom->end) { quicktime_atom_read_header(file, &leaf_atom); if(quicktime_atom_is(&leaf_atom, "esds")) { quicktime_read_esds(file, &leaf_atom, &table->esds); } else quicktime_atom_skip(file, &leaf_atom); } }
int quicktime_read_hnti(quicktime_t *file, quicktime_hnti_t *hnti, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; do { quicktime_atom_read_header(file, &leaf_atom); if (quicktime_atom_is(&leaf_atom, "rtp ")) { quicktime_read_rtp(file, &(hnti->rtp), &leaf_atom); } else { quicktime_atom_skip(file, &leaf_atom); } } while (quicktime_position(file) < parent_atom->end); return 0; }
int quicktime_check_sig(char *path) { quicktime_t file; quicktime_atom_t leaf_atom; int result = 0, result1 = 0, result2 = 0; char avi_test[12]; quicktime_init(&file); result = quicktime_file_open(&file, path, 1, 0); if(!result) { // Check for Microsoft AVI quicktime_read_data(&file, avi_test, 12); quicktime_set_position(&file, 0); if(quicktime_match_32(avi_test, "RIFF") && quicktime_match_32(avi_test + 8, "AVI ")) { result2 = 1; } else { do { result1 = quicktime_atom_read_header(&file, &leaf_atom); if(!result1) { /* just want the "moov" atom */ if(quicktime_atom_is(&leaf_atom, "moov")) { result2 = 1; } else quicktime_atom_skip(&file, &leaf_atom); } }while(!result1 && !result2 && quicktime_position(&file) < file.total_length); } } //printf(__FUNCTION__ " 2 %d\n", result2); quicktime_file_close(&file); quicktime_delete(&file); return result2; }
int quicktime_read_trak(quicktime_t *file, quicktime_trak_t *trak, quicktime_atom_t *trak_atom) { quicktime_atom_t leaf_atom; do { quicktime_atom_read_header(file, &leaf_atom); /* mandatory */ if(quicktime_atom_is(&leaf_atom, "tkhd")) { quicktime_read_tkhd(file, &(trak->tkhd)); } else if(quicktime_atom_is(&leaf_atom, "mdia")) { quicktime_read_mdia(file, &(trak->mdia), &leaf_atom); } else /* optional */ if(quicktime_atom_is(&leaf_atom, "clip")) { quicktime_atom_skip(file, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "matt")) { quicktime_atom_skip(file, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "edts")) { quicktime_read_edts(file, &(trak->edts), &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "load")) { quicktime_atom_skip(file, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "tref")) { quicktime_read_tref(file, &(trak->tref), &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "imap")) { quicktime_atom_skip(file, &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "udta")) { quicktime_read_hint_udta(file, &(trak->hint_udta), &leaf_atom); } else quicktime_atom_skip(file, &leaf_atom); }while(quicktime_position(file) < trak_atom->end); return 0; }
static void read_wave(quicktime_t *file, quicktime_stsd_table_t *table, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; //printf("read_wave 1 start=0x%llx\n", quicktime_position(file)); while(quicktime_position(file) < parent_atom->end) { quicktime_atom_read_header(file, &leaf_atom); if(quicktime_atom_is(&leaf_atom, "esds")) { quicktime_read_esds(file, &leaf_atom, &table->esds); } else if(quicktime_atom_is(&leaf_atom, "frma")) { // Extra data for QDM2 quicktime_read_frma(file, parent_atom, &leaf_atom, &table->frma); } else quicktime_atom_skip(file, &leaf_atom); } }
int quicktime_check_sig(const char *path) { quicktime_t file; quicktime_atom_t leaf_atom; int result1 = 0, result2 = 0; quicktime_init(&file); if(!(file.stream = fopen(path, "rb"))) { perror("quicktime_check_sig"); return 0; } fseek(file.stream, 0, SEEK_END); file.total_length = ftell(file.stream); fseek(file.stream, 0, SEEK_SET); do { result1 = quicktime_atom_read_header(&file, &leaf_atom); if(!result1) { /* just want the "moov" atom */ if(quicktime_atom_is(&leaf_atom, "moov")) { result2 = 1; } else quicktime_atom_skip(&file, &leaf_atom); } }while(!result1 && !result2 && quicktime_position(&file) < file.total_length); fclose(file.stream); quicktime_delete(&file); return result2; }
int quicktime_read_hinf(quicktime_t *file, quicktime_hinf_t *hinf, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; do { quicktime_atom_read_header(file, &leaf_atom); if (quicktime_atom_is(&leaf_atom, "trpy")) { quicktime_read_trpy(file, &(hinf->trpy)); } else if (quicktime_atom_is(&leaf_atom, "nump")) { quicktime_read_nump(file, &(hinf->nump)); } else if (quicktime_atom_is(&leaf_atom, "tpyl")) { quicktime_read_tpyl(file, &(hinf->tpyl)); } else if (quicktime_atom_is(&leaf_atom, "maxr")) { quicktime_read_maxr(file, &(hinf->maxr)); } else if (quicktime_atom_is(&leaf_atom, "dmed")) { quicktime_read_dmed(file, &(hinf->dmed)); } else if (quicktime_atom_is(&leaf_atom, "dimm")) { quicktime_read_dimm(file, &(hinf->dimm)); } else if (quicktime_atom_is(&leaf_atom, "drep")) { quicktime_read_drep(file, &(hinf->drep)); } else if (quicktime_atom_is(&leaf_atom, "tmin")) { quicktime_read_tmin(file, &(hinf->tmin)); } else if (quicktime_atom_is(&leaf_atom, "tmax")) { quicktime_read_tmax(file, &(hinf->tmax)); } else if (quicktime_atom_is(&leaf_atom, "pmax")) { quicktime_read_pmax(file, &(hinf->pmax)); } else if (quicktime_atom_is(&leaf_atom, "dmax")) { quicktime_read_dmax(file, &(hinf->dmax)); } else if (quicktime_atom_is(&leaf_atom, "payt")) { quicktime_read_payt(file, &(hinf->payt), &leaf_atom); } else { quicktime_atom_skip(file, &leaf_atom); } } while (quicktime_position(file) < parent_atom->end); }
int quicktime_read_info(quicktime_t *file) { int result = 0, got_header = 0; int i, channel, trak_channel, track; int64_t start_position = quicktime_position(file); quicktime_atom_t leaf_atom; quicktime_trak_t *trak; char avi_avi[4]; int got_avi = 0; int got_asf = 0; quicktime_set_position(file, 0LL); /* Test file format */ do { file->use_avi = 1; file->use_asf = 1; result = quicktime_atom_read_header(file, &leaf_atom); if(!result && quicktime_atom_is(&leaf_atom, "RIFF")) { quicktime_read_data(file, avi_avi, 4); if(quicktime_match_32(avi_avi, "AVI ")) { got_avi = 1; } else { result = 0; break; } } else { result = 0; break; } }while(1); if(!got_avi) file->use_avi = 0; if(!got_asf) file->use_asf = 0; quicktime_set_position(file, 0LL); /* McRoweSoft AVI section */ if(file->use_avi) { //printf("quicktime_read_info 1\n"); /* Import first RIFF */ do { result = quicktime_atom_read_header(file, &leaf_atom); if(!result) { if(quicktime_atom_is(&leaf_atom, "RIFF")) { quicktime_read_riff(file, &leaf_atom); /* Return success */ got_header = 1; } } }while(!result && !got_header && quicktime_position(file) < file->total_length); //printf("quicktime_read_info 10\n"); /* Construct indexes. */ quicktime_import_avi(file); //printf("quicktime_read_info 20\n"); } /* Quicktime section */ else if(!file->use_avi) { do { result = quicktime_atom_read_header(file, &leaf_atom); if(!result) { if(quicktime_atom_is(&leaf_atom, "mdat")) { quicktime_read_mdat(file, &(file->mdat), &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "moov")) { /* Set preload and preload the moov atom here */ int64_t start_position = quicktime_position(file); long temp_size = leaf_atom.end - start_position; unsigned char *temp = malloc(temp_size); quicktime_set_preload(file, (temp_size < 0x100000) ? 0x100000 : temp_size); quicktime_read_data(file, temp, temp_size); quicktime_set_position(file, start_position); free(temp); if(quicktime_read_moov(file, &(file->moov), &leaf_atom)) return 1; got_header = 1; } else quicktime_atom_skip(file, &leaf_atom); } }while(!result && quicktime_position(file) < file->total_length); /* go back to the original position */ quicktime_set_position(file, start_position); } /* Initialize track map objects */ if(got_header) { quicktime_init_maps(file); } /* Shut down preload in case of an obsurdly high temp_size */ quicktime_set_preload(file, 0); //printf("quicktime_read_info 100\n"); return !got_header; }
int quicktime_read_info(quicktime_t *file) { int result = 0, found_moov = 0; int i, j, k, m, channel, trak_channel, track; long start_position = quicktime_position(file); quicktime_atom_t leaf_atom; quicktime_trak_t *trak; char avi_test[4]; /* Check for Microsoft AVI */ quicktime_read_char32(file, avi_test); if(quicktime_match_32(avi_test, "RIFF")) { quicktime_read_char32(file, avi_test); quicktime_read_char32(file, avi_test); if(quicktime_match_32(avi_test, "AVI ")) file->use_avi = 1; } quicktime_set_position(file, 0); do { result = quicktime_atom_read_header(file, &leaf_atom); if(!result) { if(quicktime_atom_is(&leaf_atom, "mdat")) { quicktime_read_mdat(file, &(file->mdat), &leaf_atom); } else if(quicktime_atom_is(&leaf_atom, "moov")) { quicktime_read_moov(file, &(file->moov), &leaf_atom); found_moov = 1; } else { quicktime_atom_skip(file, &leaf_atom); } } }while(!result && quicktime_position(file) < file->total_length); /* go back to the original position */ quicktime_set_position(file, start_position); if(found_moov) { /* get tables for all the different tracks */ file->total_atracks = quicktime_audio_tracks(file); file->atracks = (quicktime_audio_map_t*)calloc(1, sizeof(quicktime_audio_map_t) * file->total_atracks); for(i = 0, track = 0; i < file->total_atracks; i++) { while(!file->moov.trak[track]->mdia.minf.is_audio) track++; quicktime_init_audio_map(&(file->atracks[i]), file->moov.trak[track]); } file->total_vtracks = quicktime_video_tracks(file); file->vtracks = (quicktime_video_map_t*)calloc(1, sizeof(quicktime_video_map_t) * file->total_vtracks); for(track = 0, i = 0; i < file->total_vtracks; i++) { while(!file->moov.trak[track]->mdia.minf.is_video) track++; quicktime_init_video_map(&(file->vtracks[i]), file->moov.trak[track]); } /* for all tracks */ for (track = 0; track < file->moov.total_tracks; track++) { /* check if it's a hint track */ if (!file->moov.trak[track]->mdia.minf.is_hint) { continue; } /* it is, so for each reference */ for (j = 0; j < file->moov.trak[track]->tref.hint.numTracks; j++) { /* get the reference track id */ long refTrackId = file->moov.trak[track]->tref.hint.trackIds[j]; /* check each audio track */ for(k = 0; k < file->total_atracks; k++) { if (file->atracks[k].track->tkhd.track_id == refTrackId) { int m = file->atracks[k].totalHintTracks++; file->atracks[k].hintTracks[m] = file->moov.trak[track]; file->atracks[k].hintPositions[m] = 0; file->moov.trak[track]->tref.hint.traks[j] = file->atracks[k].track; file->total_hint_tracks++; break; } } /* check each video track */ for(k = 0; k < file->total_vtracks; k++) { if (file->vtracks[k].track->tkhd.track_id == refTrackId) { int m = file->vtracks[k].totalHintTracks++; file->vtracks[k].hintTracks[m] = file->moov.trak[track]; file->vtracks[k].hintPositions[m] = 0; file->moov.trak[track]->tref.hint.traks[j] = file->vtracks[k].track; file->total_hint_tracks++; break; } } } } } if(found_moov) return 0; else return 1; }
void quicktime_read_stsd_video(quicktime_t *file, quicktime_stsd_table_t *table, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; int len; table->version = quicktime_read_int16(file); table->revision = quicktime_read_int16(file); quicktime_read_data(file, table->vendor, 4); table->temporal_quality = quicktime_read_int32(file); table->spatial_quality = quicktime_read_int32(file); table->width = quicktime_read_int16(file); table->height = quicktime_read_int16(file); table->dpi_horizontal = quicktime_read_fixed32(file); table->dpi_vertical = quicktime_read_fixed32(file); table->data_size = quicktime_read_int32(file); table->frames_per_sample = quicktime_read_int16(file); len = quicktime_read_char(file); quicktime_read_data(file, table->compressor_name, 31); table->depth = quicktime_read_int16(file); table->ctab_id = quicktime_read_int16(file); /* The data needed for SVQ3 codec and maybe some others ? */ struct ImageDescription *id; int stsd_size,fourcc,c,d; stsd_size = parent_atom->end - parent_atom->start; table->extradata_size = stsd_size - 4; id = (struct ImageDescription *) malloc(table->extradata_size); // we do not include size table->extradata = (char *) id; memcpy(id->cType, table->format, 4); // Fourcc id->version = table->version; id->revisionLevel = table->revision; memcpy(id->vendor, table->vendor, 4); // I think mplayer screws up on this one, it turns bytes around! :) id->temporalQuality = table->temporal_quality; id->spatialQuality = table->spatial_quality; id->width = table->width; id->height = table->height; id->hRes = table->dpi_horizontal; id->vRes = table->dpi_vertical; id->dataSize = table->data_size; id->frameCount = table->frames_per_sample; id->name[0] = len; memcpy(&(id->name[1]), table->compressor_name, 31); id->depth = table->depth; id->clutID = table->ctab_id; if (quicktime_position(file) < parent_atom->end) { int position = quicktime_position(file); // remember position int datalen = parent_atom->end - position; quicktime_read_data(file, ((char*)&id->clutID)+2, datalen); quicktime_set_position(file, position); // return to previous position so parsing can go on } while(quicktime_position(file) < parent_atom->end) { quicktime_atom_read_header(file, &leaf_atom); /* * printf("quicktime_read_stsd_video 1 %llx %llx %llx %s\n", * leaf_atom.start, leaf_atom.end, quicktime_position(file), * leaf_atom.type); */ if(quicktime_atom_is(&leaf_atom, "esds")) { quicktime_read_esds(file, &leaf_atom, &table->esds); } else if(quicktime_atom_is(&leaf_atom, "avcC")) { quicktime_read_avcc(file, &leaf_atom, &table->avcc); } else if(quicktime_atom_is(&leaf_atom, "ctab")) { quicktime_read_ctab(file, &(table->ctab)); } else if(quicktime_atom_is(&leaf_atom, "gama")) { table->gamma = quicktime_read_fixed32(file); } else if(quicktime_atom_is(&leaf_atom, "fiel")) { table->fields = quicktime_read_char(file); table->field_dominance = quicktime_read_char(file); } else quicktime_atom_skip(file, &leaf_atom); /* if(quicktime_atom_is(&leaf_atom, "mjqt")) */ /* { */ /* quicktime_read_mjqt(file, &(table->mjqt)); */ /* } */ /* else */ /* if(quicktime_atom_is(&leaf_atom, "mjht")) */ /* { */ /* quicktime_read_mjht(file, &(table->mjht)); */ /* } */ /* else */ } //printf("quicktime_read_stsd_video 2\n"); }
void quicktime_read_riff(quicktime_t *file, quicktime_atom_t *parent_atom) { quicktime_riff_t *riff = quicktime_new_riff(file); quicktime_atom_t leaf_atom; int result = 0; int i; char data[5]; riff->atom = *parent_atom; // AVI quicktime_read_data(file, data, 4); //printf("quicktime_read_riff 1 %llx\n", quicktime_position(file)); // Certain AVI parameters must be copied over to quicktime objects: // hdrl -> moov // movi -> mdat // idx1 -> moov do { result = quicktime_atom_read_header(file, &leaf_atom); /* * printf("quicktime_read_riff 1 %llx %llx %c%c%c%c\n", * leaf_atom.start, * leaf_atom.size, * leaf_atom.type[0], * leaf_atom.type[1], * leaf_atom.type[2], * leaf_atom.type[3]); */ if(!result) { if(quicktime_atom_is(&leaf_atom, "LIST")) { data[4] = 0; result = !quicktime_read_data(file, data, 4); if(!result) { // Got LIST 'hdrl' if(quicktime_match_32(data, "hdrl")) { // No size here. //printf("quicktime_read_riff 10 %llx\n", quicktime_position(file)); quicktime_read_hdrl(file, &riff->hdrl, &leaf_atom); //printf("quicktime_read_riff 20 %llx\n", quicktime_position(file)); } else // Got LIST 'movi' if(quicktime_match_32(data, "movi")) { //printf("quicktime_read_riff 30 %llx\n", quicktime_position(file)); quicktime_read_movi(file, &leaf_atom, &riff->movi); //printf("quicktime_read_riff 40 %llx\n", quicktime_position(file)); } } // Skip it quicktime_atom_skip(file, &leaf_atom); } else // Got 'movi' if(quicktime_atom_is(&leaf_atom, "movi")) { quicktime_read_movi(file, &leaf_atom, &riff->movi); } else // Got 'idx1' original index if(quicktime_atom_is(&leaf_atom, "idx1")) { //printf("quicktime_read_riff 50 %llx\n", quicktime_position(file)); // Preload idx1 here int64_t start_position = quicktime_position(file); long temp_size = leaf_atom.end - start_position; unsigned char *temp = malloc(temp_size); quicktime_set_preload(file, (temp_size < 0x100000) ? 0x100000 : temp_size); quicktime_read_data(file, temp, temp_size); quicktime_set_position(file, start_position); free(temp); // Read idx1 quicktime_read_idx1(file, riff, &leaf_atom); //printf("quicktime_read_riff 60 %llx\n", quicktime_position(file)); } else /* Skip it */ { quicktime_atom_skip(file, &leaf_atom); } } }while(!result && quicktime_position(file) < parent_atom->end); //printf("quicktime_read_riff 10\n"); }
int quicktime_make_streamable(char *in_path, char *out_path) { quicktime_t file, *old_file, new_file; int moov_exists = 0, mdat_exists = 0, result, atoms = 1; int64_t mdat_start, mdat_size; quicktime_atom_t leaf_atom; int64_t moov_start, moov_end; int ftyp_exists = 0; int ftyp_size = 0; unsigned char *ftyp_data = 0; quicktime_init(&file); /* find the moov atom in the old file */ if(!(file.stream = fopen(in_path, "rb"))) { perror("quicktime_make_streamable"); return 1; } file.total_length = quicktime_get_file_length(in_path); /* get the locations of moov and mdat atoms */ do { result = quicktime_atom_read_header(&file, &leaf_atom); //printf("0x%llx %s\n", quicktime_position(&file), leaf_atom.type); if(!result) { if(quicktime_atom_is(&leaf_atom, "ftyp")) { ftyp_exists = 1; ftyp_data = calloc(1, leaf_atom.size); ftyp_size = leaf_atom.size; quicktime_set_position(&file, quicktime_position(&file) - HEADER_LENGTH); quicktime_read_data(&file, (char*)ftyp_data, ftyp_size); } else if(quicktime_atom_is(&leaf_atom, "moov")) { moov_exists = atoms; } else if(quicktime_atom_is(&leaf_atom, "mdat")) { mdat_start = quicktime_position(&file) - HEADER_LENGTH; mdat_size = leaf_atom.size; mdat_exists = atoms; } quicktime_atom_skip(&file, &leaf_atom); atoms++; } }while(!result && quicktime_position(&file) < file.total_length); fclose(file.stream); if(!moov_exists) { printf("quicktime_make_streamable: no moov atom\n"); if(ftyp_data) free(ftyp_data); return 1; } if(!mdat_exists) { printf("quicktime_make_streamable: no mdat atom\n"); if(ftyp_data) free(ftyp_data); return 1; } /* copy the old file to the new file */ if(moov_exists && mdat_exists) { /* moov wasn't the first atom */ if(moov_exists > 1) { char *buffer; int64_t buf_size = 1000000; result = 0; /* read the header proper */ if(!(old_file = quicktime_open(in_path, 1, 0))) { if(ftyp_data) free(ftyp_data); return 1; } /* open the output file */ if(!(new_file.stream = fopen(out_path, "wb"))) { perror("quicktime_make_streamable"); result = 1; } else { /* set up some flags */ new_file.wr = 1; new_file.rd = 0; /* Write ftyp header */ if(ftyp_exists) { quicktime_write_data(&new_file, (char*)ftyp_data, ftyp_size); } /* Write moov once to get final size with our substituted headers */ moov_start = quicktime_position(&new_file); quicktime_write_moov(&new_file, &(old_file->moov), 0); moov_end = quicktime_position(&new_file); printf("make_streamable 0x%llx 0x%llx\n", (long long)moov_end - moov_start, (long long)mdat_start); quicktime_shift_offsets(&(old_file->moov), moov_end - moov_start - mdat_start + ftyp_size); /* Write again with shifted offsets */ quicktime_set_position(&new_file, moov_start); quicktime_write_moov(&new_file, &(old_file->moov), 0); quicktime_set_position(old_file, mdat_start); if(!(buffer = calloc(1, buf_size))) { result = 1; printf("quicktime_make_streamable: out of memory\n"); } else { while(quicktime_position(old_file) < mdat_start + mdat_size && !result) { if(quicktime_position(old_file) + buf_size > mdat_start + mdat_size) buf_size = mdat_start + mdat_size - quicktime_position(old_file); if(!quicktime_read_data(old_file, buffer, buf_size)) result = 1; if(!result) { if(!quicktime_write_data(&new_file, buffer, buf_size)) result = 1; } } free(buffer); } fclose(new_file.stream); } quicktime_close(old_file); } else { printf("quicktime_make_streamable: header already at 0 offset\n"); if(ftyp_data) free(ftyp_data); return 0; } } if(ftyp_data) free(ftyp_data); return 0; }
int quicktime_make_streamable(char *in_path, char *out_path) { quicktime_t file, *old_file, new_file; int moov_exists = 0, mdat_exists = 0, result, atoms = 1; int64_t mdat_start, mdat_size; quicktime_atom_t leaf_atom; int64_t moov_length; quicktime_init(&file); /* find the moov atom in the old file */ if(!(file.stream = fopen(in_path, "rb"))) { perror("quicktime_make_streamable"); return 1; } file.total_length = quicktime_get_file_length(in_path); /* get the locations of moov and mdat atoms */ do { /*printf("%x\n", quicktime_position(&file)); */ result = quicktime_atom_read_header(&file, &leaf_atom); if(!result) { if(quicktime_atom_is(&leaf_atom, "moov")) { moov_exists = atoms; moov_length = leaf_atom.size; } else if(quicktime_atom_is(&leaf_atom, "mdat")) { mdat_start = quicktime_position(&file) - HEADER_LENGTH; mdat_size = leaf_atom.size; mdat_exists = atoms; } quicktime_atom_skip(&file, &leaf_atom); atoms++; } }while(!result && quicktime_position(&file) < file.total_length); fclose(file.stream); if(!moov_exists) { printf("quicktime_make_streamable: no moov atom\n"); return 1; } if(!mdat_exists) { printf("quicktime_make_streamable: no mdat atom\n"); return 1; } /* copy the old file to the new file */ if(moov_exists && mdat_exists) { /* moov wasn't the first atom */ if(moov_exists > 1) { char *buffer; int64_t buf_size = 1000000; result = 0; /* read the header proper */ if(!(old_file = quicktime_open(in_path, 1, 0))) { return 1; } quicktime_shift_offsets(&(old_file->moov), moov_length); /* open the output file */ if(!(new_file.stream = fopen(out_path, "wb"))) { perror("quicktime_make_streamable"); result = 1; } else { /* set up some flags */ new_file.wr = 1; new_file.rd = 0; quicktime_write_moov(&new_file, &(old_file->moov)); quicktime_set_position(old_file, mdat_start); if(!(buffer = calloc(1, buf_size))) { result = 1; printf("quicktime_make_streamable: out of memory\n"); } else { while(quicktime_position(old_file) < mdat_start + mdat_size && !result) { if(quicktime_position(old_file) + buf_size > mdat_start + mdat_size) buf_size = mdat_start + mdat_size - quicktime_position(old_file); if(!quicktime_read_data(old_file, buffer, buf_size)) result = 1; if(!result) { if(!quicktime_write_data(&new_file, buffer, buf_size)) result = 1; } } free(buffer); } fclose(new_file.stream); } quicktime_close(old_file); } else { printf("quicktime_make_streamable: header already at 0 offset\n"); return 0; } } return 0; }
void quicktime_read_stsd_video(quicktime_t *file, quicktime_stsd_table_t *table, quicktime_atom_t *parent_atom) { quicktime_atom_t leaf_atom; int len; table->version = quicktime_read_int16(file); table->revision = quicktime_read_int16(file); quicktime_read_data(file, table->vendor, 4); table->temporal_quality = quicktime_read_int32(file); table->spatial_quality = quicktime_read_int32(file); table->width = quicktime_read_int16(file); table->height = quicktime_read_int16(file); table->dpi_horizontal = quicktime_read_fixed32(file); table->dpi_vertical = quicktime_read_fixed32(file); table->data_size = quicktime_read_int32(file); table->frames_per_sample = quicktime_read_int16(file); len = quicktime_read_char(file); quicktime_read_data(file, table->compressor_name, 31); table->depth = quicktime_read_int16(file); table->ctab_id = quicktime_read_int16(file); while(quicktime_position(file) < parent_atom->end) { quicktime_atom_read_header(file, &leaf_atom); /* * printf("quicktime_read_stsd_video 1 %llx %llx %llx %s\n", * leaf_atom.start, leaf_atom.end, quicktime_position(file), * leaf_atom.type); */ if(quicktime_atom_is(&leaf_atom, "esds")) { quicktime_read_esds(file, &leaf_atom, &table->esds); } else if(quicktime_atom_is(&leaf_atom, "avcC")) { quicktime_read_avcc(file, &leaf_atom, &table->avcc); } else if(quicktime_atom_is(&leaf_atom, "ctab")) { quicktime_read_ctab(file, &(table->ctab)); } else if(quicktime_atom_is(&leaf_atom, "gama")) { table->gamma = quicktime_read_fixed32(file); } else if(quicktime_atom_is(&leaf_atom, "fiel")) { table->fields = quicktime_read_char(file); table->field_dominance = quicktime_read_char(file); } else quicktime_atom_skip(file, &leaf_atom); /* if(quicktime_atom_is(&leaf_atom, "mjqt")) */ /* { */ /* quicktime_read_mjqt(file, &(table->mjqt)); */ /* } */ /* else */ /* if(quicktime_atom_is(&leaf_atom, "mjht")) */ /* { */ /* quicktime_read_mjht(file, &(table->mjht)); */ /* } */ /* else */ } //printf("quicktime_read_stsd_video 2\n"); }