long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track) { quicktime_audio_map_t *track_map = &file->atracks[track]; quicktime_trak_t *trak = track_map->track; int64_t position, chunk, chunk_sample; long ret, bytes, chunk_offset, chunk_len; int result = 0; position = file->atracks[track].current_position; quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position); ret = 0; while( samples > 0 ) { int64_t offset = quicktime_sample_to_offset(file, trak, position); quicktime_set_position(file, offset); chunk_offset = position - chunk_sample; chunk_len = quicktime_chunk_samples(trak, chunk) - chunk_offset; if( chunk_len > samples ) chunk_len = samples; else ++chunk; chunk_sample = (position += chunk_len); bytes = quicktime_samples_to_bytes(trak, chunk_len); result = !quicktime_read_data(file, &audio_buffer[ret], bytes); if( result ) break; ret += bytes; samples -= chunk_len; } //printf("quicktime_read_audio 5\n"); track_map->current_position = position; track_map->current_chunk = chunk; return !result ? ret : 0; }
int64_t quicktime_read_int64_le(quicktime_t *file) { uint64_t result, a, b, c, d, e, f, g, h; char data[8]; quicktime_read_data(file, data, 8); a = (unsigned char)data[7]; b = (unsigned char)data[6]; c = (unsigned char)data[5]; d = (unsigned char)data[4]; e = (unsigned char)data[3]; f = (unsigned char)data[2]; g = (unsigned char)data[1]; h = (unsigned char)data[0]; result = (a << 56) | (b << 48) | (c << 40) | (d << 32) | (e << 24) | (f << 16) | (g << 8) | h; return (int64_t)result; }
static int chunk_len(quicktime_t *file, int64_t offset, int64_t next_chunk) { int result = 0; unsigned char buffer[BUFFER_FRAGMENT]; int accum = 0; int segment_count = 0; int page_size = 0; int i; while(offset < next_chunk) { quicktime_set_position(file, offset); result = !quicktime_read_data(file, (char*)buffer, BUFFER_FRAGMENT); if(result || memcmp(buffer, "OggS", 4)) return accum; // Decode size of OggS page segment_count = buffer[SEGMENT_OFFSET]; // Decode one segment at a time i = LACE_OFFSET; page_size = 0; while(segment_count > 0) { page_size += buffer[i++]; segment_count--; } accum += i + page_size; offset += i + page_size; } return accum; }
int quicktime_read_chunk(quicktime_t *file, char *output, int track, long chunk, long byte_start, long byte_len) { quicktime_set_position(file, quicktime_chunk_to_offset(file->atracks[track].track, chunk) + byte_start); if(quicktime_read_data(file, output, byte_len)) return 0; else return 1; }
long quicktime_read_frame(quicktime_t *file, unsigned char *video_buffer, int track) { long bytes; int result = 0; quicktime_trak_t *trak = file->vtracks[track].track; bytes = quicktime_frame_size(file, file->vtracks[track].current_position, track); if(!file->vtracks[track].frames_cached) { quicktime_set_video_position(file, file->vtracks[track].current_position, track); result = quicktime_read_data(file, video_buffer, bytes); } else { int i; unsigned char *cached_frame; if(file->vtracks[track].current_position >= file->vtracks[track].frames_cached) result = 1; if(!result) { cached_frame = file->vtracks[track].frame_cache[file->vtracks[track].current_position]; for(i = 0; i < bytes; i++) video_buffer[i] = cached_frame[i]; } } file->vtracks[track].current_position++; if(!result) return 0; return bytes; }
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); }
static int decode(quicktime_t *file, unsigned char **row_pointers, int track) { int bytes; quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; int width = quicktime_video_width(file, track); int height = quicktime_video_height(file, track); int result = 0; initialize(vtrack, codec, width, height); quicktime_set_video_position(file, vtrack->current_position, track); bytes = quicktime_frame_size(file, vtrack->current_position, track); result = !quicktime_read_data(file, (char*)codec->work_buffer, bytes); if(codec->is_2vuy) convert_decode_2vuy(codec); else convert_decode_yuv2(codec); cmodel_transfer(row_pointers, codec->rows, row_pointers[0], row_pointers[1], row_pointers[2], 0, 0, 0, file->in_x, file->in_y, file->in_w, file->in_h, 0, 0, file->out_w, file->out_h, BC_YUV422, file->color_model, 0, codec->coded_w, file->out_w); return result; }
int quicktime_read_avcc(quicktime_t *file, quicktime_atom_t *parent_atom, quicktime_avcc_t *avcc) { avcc->data_size = parent_atom->size - 8; quicktime_read_data(file, avcc->data, avcc->data_size); quicktime_atom_skip(file, parent_atom); return 0; }
float quicktime_read_fixed16(quicktime_t *file) { unsigned char data[2]; quicktime_read_data(file, data, 2); //printf("quicktime_read_fixed16 %02x%02x\n", data[0], data[1]); if(data[1]) return (float)data[0] + (float)data[1] / 256; else return (float)data[0]; }
int quicktime_read_esds(quicktime_t *file, quicktime_esds_t *esds) { u_int8_t tag; u_int32_t length; esds->version = quicktime_read_char(file); esds->flags = quicktime_read_int24(file); /* get and verify ES_DescrTag */ tag = quicktime_read_char(file); if (tag == 0x03) { /* read length */ if (quicktime_read_mp4_descr_length(file) < 5 + 15) { return 1; } /* skip 3 bytes */ quicktime_set_position(file, quicktime_position(file) + 3); } else { /* skip 2 bytes */ quicktime_set_position(file, quicktime_position(file) + 2); } /* get and verify DecoderConfigDescrTab */ if (quicktime_read_char(file) != 0x04) { return 1; } /* read length */ if (quicktime_read_mp4_descr_length(file) < 15) { return 1; } /* skip 13 bytes */ quicktime_set_position(file, quicktime_position(file) + 13); /* get and verify DecSpecificInfoTag */ if (quicktime_read_char(file) != 0x05) { return 1; } /* read length */ esds->decoderConfigLen = quicktime_read_mp4_descr_length(file); free(esds->decoderConfig); esds->decoderConfig = malloc(esds->decoderConfigLen); if (esds->decoderConfig) { quicktime_read_data(file, esds->decoderConfig, esds->decoderConfigLen); } else { esds->decoderConfigLen = 0; } /* will skip the remainder of the atom */ return 0; }
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); }
static int decode(quicktime_t *file, unsigned char **row_pointers, int track) { int i; int64_t bytes; int result = 0; quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_v308_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; int width = vtrack->track->tkhd.track_width; int height = vtrack->track->tkhd.track_height; unsigned char **input_rows; if(!codec->work_buffer) codec->work_buffer = malloc(vtrack->track->tkhd.track_width * vtrack->track->tkhd.track_height * 3); quicktime_set_video_position(file, vtrack->current_position, track); bytes = quicktime_frame_size(file, vtrack->current_position, track); result = !quicktime_read_data(file, codec->work_buffer, bytes); input_rows = malloc(sizeof(unsigned char*) * height); for(i = 0; i < height; i++) input_rows[i] = codec->work_buffer + i * width * 3; cmodel_transfer(row_pointers, input_rows, row_pointers[0], row_pointers[1], row_pointers[2], 0, 0, 0, file->in_x, file->in_y, file->in_w, file->in_h, 0, 0, file->out_w, file->out_h, BC_VYU888, file->color_model, 0, width, file->out_w); free(input_rows); return result; }
long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track) { int64_t chunk_sample, chunk; int result = 0, track_num; quicktime_trak_t *trak = file->atracks[track].track; int64_t fragment_len, chunk_end; int64_t start_position = file->atracks[track].current_position; int64_t position = file->atracks[track].current_position; int64_t start = position, end = position + samples; int64_t bytes, total_bytes = 0; int64_t buffer_offset; //printf("quicktime_read_audio 1\n"); quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position); buffer_offset = 0; while(position < end && !result) { quicktime_set_audio_position(file, position, track); fragment_len = quicktime_chunk_samples(trak, chunk); chunk_end = chunk_sample + fragment_len; fragment_len -= position - chunk_sample; if(position + fragment_len > chunk_end) fragment_len = chunk_end - position; if(position + fragment_len > end) fragment_len = end - position; bytes = quicktime_samples_to_bytes(trak, fragment_len); /* * printf("quicktime_read_audio 2 %llx %llx %d\n", * quicktime_position(file), * quicktime_position(file) + bytes, * samples); * sleep(1); */ result = !quicktime_read_data(file, &audio_buffer[buffer_offset], bytes); //printf("quicktime_read_audio 4\n"); total_bytes += bytes; position += fragment_len; chunk_sample = position; buffer_offset += bytes; chunk++; } //printf("quicktime_read_audio 5\n"); // Create illusion of track being advanced only by samples file->atracks[track].current_position = start_position + samples; if(result) return 0; return total_bytes; }
int quicktime_read_int16_le(quicktime_t *file) { unsigned long result; unsigned long a, b; char data[2]; quicktime_read_data(file, data, 2); a = (unsigned char)data[0]; b = (unsigned char)data[1]; result = (b << 8) | a; return (int)result; }
void quicktime_read_dref_table(quicktime_t *file, quicktime_dref_table_t *table) { table->size = quicktime_read_int32(file); quicktime_read_char32(file, table->type); table->version = quicktime_read_char(file); table->flags = quicktime_read_int24(file); if(table->data_reference) free(table->data_reference); table->data_reference = malloc(table->size); if(table->size > 12) quicktime_read_data(file, table->data_reference, table->size - 12); table->data_reference[table->size - 12] = 0; }
long quicktime_read_int24(quicktime_t *file) { unsigned long result; unsigned long a, b, c; char data[4]; quicktime_read_data(file, data, 3); a = (unsigned char)data[0]; b = (unsigned char)data[1]; c = (unsigned char)data[2]; result = (a << 16) | (b << 8) | c; return (long)result; }
long quicktime_read_frame(quicktime_t *file, unsigned char *video_buffer, int track) { int64_t bytes; int result = 0; quicktime_trak_t *trak = file->vtracks[track].track; bytes = quicktime_frame_size(file, file->vtracks[track].current_position, track); quicktime_set_video_position(file, file->vtracks[track].current_position, track); result = quicktime_read_data(file, video_buffer, bytes); file->vtracks[track].current_position++; if(!result) return 0; return bytes; }
long quicktime_read_int32_le(quicktime_t *file) { unsigned long result; unsigned long a, b, c, d; char data[4]; quicktime_read_data(file, data, 4); a = (unsigned char)data[0]; b = (unsigned char)data[1]; c = (unsigned char)data[2]; d = (unsigned char)data[3]; result = (d << 24) | (c << 16) | (b << 8) | a; return (long)result; }
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); }
long quicktime_read_frame(quicktime_t *file, unsigned char *video_buffer, int track) { int result = 0; int64_t bytes = quicktime_frame_size(file, file->vtracks[track].current_position, track); quicktime_set_video_position(file, file->vtracks[track].current_position, track); /* * printf("quicktime_read_frame 0x%llx %lld\n", * quicktime_ftell(file), * bytes); */ result = quicktime_read_data(file, (char*)video_buffer, bytes); file->vtracks[track].current_position++; if(!result) return 0; return bytes; }
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_tkhd(quicktime_t *file, quicktime_tkhd_t *tkhd) { tkhd->version = quicktime_read_char(file); tkhd->flags = quicktime_read_int24(file); tkhd->creation_time = quicktime_read_int32(file); tkhd->modification_time = quicktime_read_int32(file); tkhd->track_id = quicktime_read_int32(file); tkhd->reserved1 = quicktime_read_int32(file); tkhd->duration = quicktime_read_int32(file); quicktime_read_data(file, tkhd->reserved2, 8); tkhd->layer = quicktime_read_int16(file); tkhd->alternate_group = quicktime_read_int16(file); tkhd->volume = quicktime_read_fixed16(file); tkhd->reserved3 = quicktime_read_int16(file); quicktime_read_matrix(file, &(tkhd->matrix)); tkhd->track_width = quicktime_read_fixed32(file); tkhd->track_height = quicktime_read_fixed32(file); }
float quicktime_read_fixed32(quicktime_t *file) { unsigned long a, b, c, d; unsigned char data[4]; quicktime_read_data(file, data, 4); a = data[0]; b = data[1]; c = data[2]; d = data[3]; a = (a << 8) + b; b = (c << 8) + d; if(b) return (float)a + (float)b / 65536; else return a; }
int quicktime_read_mvhd(quicktime_t *file, quicktime_mvhd_t *mvhd) { mvhd->version = quicktime_read_char(file); mvhd->flags = quicktime_read_int24(file); mvhd->creation_time = quicktime_read_int32(file); mvhd->modification_time = quicktime_read_int32(file); mvhd->time_scale = quicktime_read_int32(file); mvhd->duration = quicktime_read_int32(file); mvhd->preferred_rate = quicktime_read_fixed32(file); mvhd->preferred_volume = quicktime_read_fixed16(file); quicktime_read_data(file, mvhd->reserved, 10); quicktime_read_matrix(file, &(mvhd->matrix)); mvhd->preview_time = quicktime_read_int32(file); mvhd->preview_duration = quicktime_read_int32(file); mvhd->poster_time = quicktime_read_int32(file); mvhd->selection_time = quicktime_read_int32(file); mvhd->selection_duration = quicktime_read_int32(file); mvhd->current_time = quicktime_read_int32(file); mvhd->next_track_id = quicktime_read_int32(file); return 0; }
long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track) { long chunk_sample, chunk; int result = 1, track_num; quicktime_trak_t *trak = file->atracks[track].track; long fragment_len, chunk_end; long position = file->atracks[track].current_position; long start = position, end = position + samples; long bytes, total_bytes = 0; long buffer_offset; quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position); buffer_offset = 0; while(position < end && result) { quicktime_set_audio_position(file, position, track); fragment_len = quicktime_chunk_samples(trak, chunk); chunk_end = chunk_sample + fragment_len; fragment_len -= position - chunk_sample; if(position + fragment_len > chunk_end) fragment_len = chunk_end - position; if(position + fragment_len > end) fragment_len = end - position; bytes = quicktime_samples_to_bytes(trak, fragment_len); result = quicktime_read_data(file, &audio_buffer[buffer_offset], bytes); total_bytes += bytes; position += fragment_len; chunk_sample = position; buffer_offset += bytes; chunk++; } file->atracks[track].current_position = position; if(!result) return 0; return total_bytes; }
long quicktime_read_audio_frame(quicktime_t *file, unsigned char *audio_buffer, int maxBytes, int track) { long bytes; int result = 0; quicktime_trak_t *trak = file->atracks[track].track; bytes = quicktime_audio_frame_size(file, file->atracks[track].current_position, track); if (bytes > maxBytes) { return -bytes; } quicktime_set_audio_position(file, file->atracks[track].current_position, track); result = quicktime_read_data(file, audio_buffer, bytes); file->atracks[track].current_position++; if (!result) return 0; return bytes; }
int quicktime_atom_read_header(quicktime_t *file, quicktime_atom_t *atom) { int result = 0; char header[10]; if(file->use_avi) { reset(atom); atom->start = quicktime_position(file); if(!quicktime_read_data(file, header, HEADER_LENGTH)) return 1; atom->type[0] = header[0]; atom->type[1] = header[1]; atom->type[2] = header[2]; atom->type[3] = header[3]; atom->type[4] = 0; atom->size = (((unsigned char)header[4]) ) | (((unsigned char)header[5]) << 8 ) | (((unsigned char)header[6]) << 16) | (((unsigned char)header[7]) << 24); atom->end = quicktime_add3(atom->start, atom->size, 8); } else { int64_t size2; reset(atom); atom->start = quicktime_position(file); if(!quicktime_read_data(file, header, HEADER_LENGTH)) return 1; result = read_type(header, atom->type); atom->size = read_size(header); atom->end = atom->start + atom->size; /* * printf("quicktime_atom_read_header 1 %c%c%c%c start %llx size %llx end %llx ftell %llx %llx\n", * atom->type[0], atom->type[1], atom->type[2], atom->type[3], * atom->start, atom->size, atom->end, * file->file_position, * (int64_t)FTELL(file->stream)); */ /* Skip placeholder atom */ if(quicktime_match_32(atom->type, "wide")) { atom->start = quicktime_position(file); reset(atom); if(!quicktime_read_data(file, header, HEADER_LENGTH)) return 1; result = read_type(header, atom->type); atom->size -= 8; if(atom->size <= 0) { /* Wrapper ended. Get new atom size */ atom->size = read_size(header); } atom->end = atom->start + atom->size; } else /* Get extended size */ if(atom->size == 1) { if(!quicktime_read_data(file, header, HEADER_LENGTH)) return 1; atom->size = read_size64(header); atom->end = atom->start + atom->size; /* * printf("quicktime_atom_read_header 2 %c%c%c%c start %llx size %llx end %llx ftell %llx\n", * atom->type[0], atom->type[1], atom->type[2], atom->type[3], * atom->start, atom->size, atom->end, * file->file_position); */ } } return result; }
int main(int argc, char *argv[]) { quicktime_t *file; FILE *output; int result = 0; int i, j; int64_t length; char string[1024], *prefix = 0, *input = 0; char *data = 0; int bytes = 0, old_bytes = 0; float output_rate = 0; float input_rate; int64_t input_frame; int64_t new_length; int width, height; int rgb_to_ppm = 0; if(argc < 3) { usage(); } for(i = 1, j = 0; i < argc; i++) { if(!strcmp(argv[i], "-f")) { if(i + 1 < argc) { output_rate = atof(argv[++i]); } else usage(); } else if(j == 0) { input = argv[i]; j++; } else if(j == 1) { prefix = argv[i]; j++; } } if(!prefix || !input) usage(); if(!(file = quicktime_open(input, 1, 0))) { printf("Open failed\n"); exit(1); } if(!quicktime_video_tracks(file)) { printf("No video tracks.\n"); exit(1); } if(quicktime_match_32(quicktime_video_compressor(file, 0), QUICKTIME_RAW)) { printf("Converting to ppm.\n"); rgb_to_ppm = 1; } length = quicktime_video_length(file, 0); input_rate = quicktime_frame_rate(file, 0); if(!output_rate) output_rate = input_rate; new_length = output_rate / input_rate * length; width = quicktime_video_width(file, 0); height = quicktime_video_height(file, 0); for(i = 0; i < new_length; i++) { /* Get output file */ sprintf(string, "%s%06d", prefix, i); if(!(output = fopen(string, "wb"))) { perror("Open failed"); exit(1); } /* Get input frame */ input_frame = (int64_t)(input_rate / output_rate * i); bytes = quicktime_frame_size(file, input_frame, 0); if(data) { if(bytes > old_bytes) { free(data); data = 0; } } if(!data) { old_bytes = bytes; data = malloc(bytes); } quicktime_set_video_position(file, input_frame, 0); quicktime_read_data(file, data, bytes); if(rgb_to_ppm) { fprintf(output, "P6\n%d %d\n%d\n", width, height, 0xff); } if(!fwrite(data, bytes, 1, output)) { perror("write failed"); } fclose(output); } quicktime_close(file); }
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; }
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; }