📄 trak.c
字号:
return total_samples / (chunk + 1); } else { total_samples = quicktime_track_samples(file, trak); return total_samples; }}int quicktime_chunk_of_sample(int64_t *chunk_sample, int64_t *chunk, quicktime_trak_t *trak, int64_t sample) { quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table; long total_entries = trak->mdia.minf.stbl.stsc.total_entries; long chunk2entry; long chunk1, chunk2, chunk1samples, range_samples, total = 0; chunk1 = 1; chunk1samples = 0; chunk2entry = 0; if(!total_entries) { *chunk_sample = 0; *chunk = 0; return 0; } do { chunk2 = table[chunk2entry].chunk; *chunk = chunk2 - chunk1; range_samples = *chunk * chunk1samples; if(sample < total + range_samples) break; chunk1samples = table[chunk2entry].samples; chunk1 = chunk2; if(chunk2entry < total_entries) { chunk2entry++; total += range_samples; } }while(chunk2entry < total_entries); if(chunk1samples) *chunk = (sample - total) / chunk1samples + chunk1; else *chunk = 1; *chunk_sample = total + (*chunk - chunk1) * chunk1samples; return 0; }int64_t quicktime_chunk_to_offset(quicktime_t *file, quicktime_trak_t *trak, long chunk){ quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table; int64_t result = 0; if(trak->mdia.minf.stbl.stco.total_entries && chunk > trak->mdia.minf.stbl.stco.total_entries) result = table[trak->mdia.minf.stbl.stco.total_entries - 1].offset; else if(trak->mdia.minf.stbl.stco.total_entries) result = table[chunk - 1].offset; else result = HEADER_LENGTH * 2; return result;}long quicktime_offset_to_chunk(int64_t *chunk_offset, quicktime_trak_t *trak, int64_t offset){ quicktime_stco_table_t *table = trak->mdia.minf.stbl.stco.table; int i; for(i = trak->mdia.minf.stbl.stco.total_entries - 1; i >= 0; i--) { if(table[i].offset <= offset) { *chunk_offset = table[i].offset; return i + 1; } } *chunk_offset = HEADER_LENGTH * 2; return 1;}int64_t quicktime_sample_range_size(quicktime_trak_t *trak, long chunk_sample, long sample){int64_t i, total; /* LQT: For audio, quicktime_sample_rage_size makes no sense */ if(trak->mdia.minf.is_audio) return 0; else { /* All frames have the same size */ if(trak->mdia.minf.stbl.stsz.sample_size) { total = (sample - chunk_sample) * trak->mdia.minf.stbl.stsz.sample_size; }/* probably video */ else { for(i = chunk_sample, total = 0; i < sample; i++) { total += trak->mdia.minf.stbl.stsz.table[i].size; } } } return total;}int64_t quicktime_sample_to_offset(quicktime_t *file, quicktime_trak_t *trak, long sample){ int64_t chunk, chunk_sample, chunk_offset1, chunk_offset2; quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample); chunk_offset1 = quicktime_chunk_to_offset(file, trak, chunk); chunk_offset2 = chunk_offset1 + quicktime_sample_range_size(trak, chunk_sample, sample); return chunk_offset2;}void quicktime_write_chunk_header(quicktime_t *file, quicktime_trak_t *trak, quicktime_atom_t *chunk) { if(file->file_type & (LQT_FILE_AVI|LQT_FILE_AVI_ODML)) { /* Get tag from first riff strl */ quicktime_strl_t *strl = trak->strl; char *tag = strl->tag; /* Create new RIFF object at 1 Gig mark */ if(file->file_type == LQT_FILE_AVI_ODML) { quicktime_riff_t *riff = file->riff[file->total_riffs - 1]; if(quicktime_position(file) - riff->atom.start > file->max_riff_size) { quicktime_finalize_riff(file, riff); quicktime_init_riff(file); } } /* Write AVI header */ quicktime_atom_write_header(file, chunk, tag); } else { chunk->start = quicktime_position(file); } }void quicktime_write_chunk_footer(quicktime_t *file, quicktime_trak_t *trak, int current_chunk, quicktime_atom_t *chunk, int samples) { int64_t offset = chunk->start; int sample_size = quicktime_position(file) - offset; // Write AVI footer if(file->file_type & (LQT_FILE_AVI|LQT_FILE_AVI_ODML)) { quicktime_atom_write_footer(file, chunk); // Save original index entry for first RIFF only if(file->total_riffs < 2) { quicktime_update_idx1table(file, trak, offset, sample_size); } // Save partial index entry if(file->file_type == LQT_FILE_AVI_ODML) quicktime_update_ixtable(file, trak, offset, sample_size); if(sample_size > trak->strl->strh.dwSuggestedBufferSize) trak->strl->strh.dwSuggestedBufferSize = ((sample_size+15)/16)*16; } if(offset + sample_size > file->mdat.atom.size) file->mdat.atom.size = offset + sample_size; quicktime_update_stco(&(trak->mdia.minf.stbl.stco), current_chunk, offset); if(trak->mdia.minf.is_video || trak->mdia.minf.is_text) quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz), current_chunk - 1, sample_size); /* Need to increase sample count for CBR (the VBR routines to it themselves) */ if(trak->mdia.minf.is_audio && !trak->mdia.minf.is_audio_vbr) trak->mdia.minf.stbl.stts.table->sample_count += samples; if(trak->mdia.minf.is_panorama) { quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz), current_chunk - 1, sample_size); } if(trak->mdia.minf.is_qtvr) { quicktime_update_stsz(&(trak->mdia.minf.stbl.stsz), current_chunk - 1, sample_size); } quicktime_update_stsc(&(trak->mdia.minf.stbl.stsc), current_chunk, samples); }int quicktime_trak_duration(quicktime_trak_t *trak, int64_t *duration, int *timescale) { quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts); int i; *duration = 0; for(i = 0; i < stts->total_entries; i++) { *duration += stts->table[i].sample_duration * stts->table[i].sample_count; } if(timescale) *timescale = trak->mdia.mdhd.time_scale; return 0; }int quicktime_trak_fix_counts(quicktime_t *file, quicktime_trak_t *trak, int moov_time_scale) { int64_t duration; int timescale; quicktime_stts_t * stts; long samples = quicktime_track_samples(file, trak); quicktime_trak_duration(trak, &duration, ×cale); /* get duration in movie's units */ trak->tkhd.duration = (long)((float)duration / timescale * moov_time_scale); trak->mdia.mdhd.duration = duration; trak->mdia.mdhd.time_scale = timescale; trak->edts.elst.table[0].duration = trak->tkhd.duration; if(trak->mdia.minf.is_panorama) trak->edts.elst.total_entries = 1; stts = &trak->mdia.minf.stbl.stts; quicktime_compress_stsc(&trak->mdia.minf.stbl.stsc); if(trak->mdia.minf.is_video || trak->mdia.minf.is_text || trak->mdia.minf.is_timecode) { quicktime_compress_stts(stts); if(trak->mdia.minf.stbl.stts.total_entries == 1) trak->mdia.minf.stbl.stts.table[0].sample_count = samples; } else if(trak->mdia.minf.is_audio_vbr) { quicktime_compress_stts(stts); } else trak->mdia.minf.stbl.stts.table[0].sample_count = samples; if(trak->mdia.minf.is_video && IS_MP4(file->file_type) && trak->mdia.minf.stbl.has_ctts) { quicktime_fix_ctts(&trak->mdia.minf.stbl.ctts); } if(!trak->mdia.minf.stbl.stsz.total_entries) { // trak->mdia.minf.stbl.stsz.sample_size = 1; trak->mdia.minf.stbl.stsz.total_entries = samples; } return 0; }long quicktime_chunk_samples(quicktime_trak_t *trak, long chunk){ long result, current_chunk; quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc); quicktime_stts_t *stts = &(trak->mdia.minf.stbl.stts); quicktime_stsd_t *stsd = &(trak->mdia.minf.stbl.stsd); long i = stsc->total_entries - 1; if(!stsc->total_entries) return 0; do { current_chunk = stsc->table[i].chunk; result = stsc->table[i].samples; i--; }while(i >= 0 && current_chunk > chunk); /* LQT: Multiply with duration */ if(stsd->table[0].compression_id == -2) result *= stts->table[0].sample_duration; return result;}int quicktime_trak_shift_offsets(quicktime_trak_t *trak, int64_t offset){ quicktime_stco_t *stco = &(trak->mdia.minf.stbl.stco); int i; for(i = 0; i < stco->total_entries; i++) { stco->table[i].offset += offset; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -