📄 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 + -