📄 quicktime.c
字号:
}int quicktime_write_video_hint(quicktime_t *file, unsigned char *hintBuffer, long hintBufferSize, int videoTrack, int hintTrack, long hintSampleDuration, u_char isKeyFrame){ quicktime_trak_t* hintTrak = file->vtracks[videoTrack].hintTracks[hintTrack]; return quicktime_write_media_hint(file, hintBuffer, hintBufferSize, hintTrak, &(file->vtracks[videoTrack].hintPositions[hintTrack]), hintSampleDuration, isKeyFrame);}FILE* quicktime_get_fd(quicktime_t *file){ if(ftell(file->stream) != file->file_position) fseek(file->stream, file->file_position, SEEK_SET); return file->stream;}int quicktime_write_frame_init(quicktime_t *file, int track){ if(ftell(file->stream) != file->file_position) fseek(file->stream, file->file_position, SEEK_SET); file->offset = quicktime_position(file); return 0;}int quicktime_write_frame_end(quicktime_t *file, int track){ long bytes; file->file_position = ftell(file->stream); bytes = quicktime_position(file) - file->offset; quicktime_update_tables(file, file->vtracks[track].track, file->offset, file->vtracks[track].current_chunk, file->vtracks[track].current_position, 1, bytes, 0, 0, 0); file->vtracks[track].current_position += 1; file->vtracks[track].current_chunk++; return 0;}int quicktime_write_audio_init(quicktime_t *file, int track){ return quicktime_write_frame_init(file, track);}int quicktime_write_audio_end(quicktime_t *file, int track, long samples){ long bytes; file->file_position = ftell(file->stream); bytes = quicktime_position(file) - file->offset; quicktime_update_tables(file, file->atracks[track].track, file->offset, file->atracks[track].current_chunk, file->atracks[track].current_position, samples, bytes, 0, 0, 0); file->atracks[track].current_position += samples; file->atracks[track].current_chunk++; 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;}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_frame_size(quicktime_t *file, long frame, int track){ int bytes; quicktime_trak_t *trak = file->vtracks[track].track; if(trak->mdia.minf.stbl.stsz.sample_size) { bytes = trak->mdia.minf.stbl.stsz.sample_size; } else { bytes = trak->mdia.minf.stbl.stsz.table[frame].size; } return bytes;}long quicktime_audio_frame_size(quicktime_t *file, long frame, int track){ int bytes; quicktime_trak_t *trak = file->atracks[track].track; if(trak->mdia.minf.stbl.stsz.sample_size) { bytes = trak->mdia.minf.stbl.stsz.sample_size; } else { bytes = trak->mdia.minf.stbl.stsz.table[frame].size; } return 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;}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;}int quicktime_read_frame_init(quicktime_t *file, int track){ quicktime_trak_t *trak = file->vtracks[track].track; quicktime_set_video_position(file, file->vtracks[track].current_position, track); if(ftell(file->stream) != file->file_position) fseek(file->stream, file->file_position, SEEK_SET); return 0;}int quicktime_read_frame_end(quicktime_t *file, int track){ file->file_position = ftell(file->stream); file->vtracks[track].current_position++; return 0;}int quicktime_init_video_map(quicktime_video_map_t *vtrack, quicktime_trak_t *trak){ vtrack->track = trak; vtrack->current_position = 0; vtrack->current_chunk = 1; vtrack->frame_cache = 0; vtrack->frames_cached = 0; return 0;}int quicktime_delete_video_map(quicktime_video_map_t *vtrack){ int i; if(vtrack->frames_cached) { for(i = 0; i < vtrack->frames_cached; i++) { free(vtrack->frame_cache[i]); } free(vtrack->frame_cache); vtrack->frames_cached = 0; } return 0;}int quicktime_init_audio_map(quicktime_audio_map_t *atrack, quicktime_trak_t *trak){ atrack->track = trak; atrack->channels = trak->mdia.minf.stbl.stsd.table[0].channels; atrack->current_position = 0; atrack->current_chunk = 1; return 0;}int quicktime_delete_audio_map(quicktime_audio_map_t *atrack){ int i; return 0;}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;}int quicktime_dump(quicktime_t *file){ printf("quicktime_dump\n"); printf("movie data\n"); printf(" size %ld\n", file->mdat.size); printf(" start %ld\n", file->mdat.start); quicktime_moov_dump(&(file->moov)); return 0;}/* ================================== Entry points ========================== */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;}quicktime_t* quicktime_open(char *filename, int rd, int wr, int append){ quicktime_t *new_file = malloc(sizeof(quicktime_t)); char flags[10]; int exists = 0; quicktime_init(new_file); new_file->wr = wr; new_file->rd = rd; new_file->mdat.start = 0; if (!strcmp(&filename[strlen(filename)-4], ".mp4")) { new_file->use_mp4 = TRUE; } else { new_file->use_mp4 = FALSE; } if(rd && (new_file->stream = fopen(filename, "rb"))) { exists = 1; fclose(new_file->stream); new_file->stream = NULL; } if(rd && !wr) sprintf(flags, "rb"); else if(!rd && wr) sprintf(flags, "wb"); else if(rd && wr) { if(exists) sprintf(flags, "rb+"); else sprintf(flags, "wb+"); } if(!(new_file->stream = fopen(filename, flags))) { perror("quicktime_open"); free(new_file); return 0; } if(rd && exists) { fseek(new_file->stream, 0, SEEK_END); new_file->total_length = ftell(new_file->stream); fseek(new_file->stream, 0, SEEK_SET); if(quicktime_read_info(new_file)) { quicktime_close(new_file); new_file = 0; } } if(wr) { if(!exists || !append) { /* start the data atom */ quicktime_write_int32(new_file, 0); quicktime_write_char32(new_file, "mdat"); } else { quicktime_set_position(new_file, new_file->mdat.start + new_file->mdat.size); fseek(new_file->stream, new_file->mdat.start + new_file->mdat.size, SEEK_SET); } } return new_file;}int quicktime_write(quicktime_t *file){ int result = -1; if(!file->wr) { return result; } quicktime_write_mdat(file, &(file->mdat)); quicktime_write_moov(file, &(file->moov)); result = fclose(file->stream); file->stream = NULL; return result;}int quicktime_destroy(quicktime_t *file){ quicktime_delete(file); free(file); return 0;}int quicktime_close(quicktime_t *file){ int result; if(file->wr) { quicktime_write_mdat(file, &(file->mdat)); quicktime_write_moov(file, &(file->moov)); } result = fclose(file->stream); quicktime_delete(file); free(file); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -