📄 trak.c
字号:
#include "quicktime.h"
int quicktime_trak_init(quicktime_trak_t *trak)
{
quicktime_tkhd_init(&(trak->tkhd));
quicktime_edts_init(&(trak->edts));
quicktime_tref_init(&(trak->tref));
quicktime_mdia_init(&(trak->mdia));
quicktime_hint_udta_init(&(trak->hint_udta));
return 0;
}
int quicktime_trak_init_video(quicktime_t *file,
quicktime_trak_t *trak,
int frame_w,
int frame_h,
float frame_rate,
int time_scale,
char *compressor)
{
quicktime_tkhd_init_video(file, &(trak->tkhd), frame_w, frame_h);
quicktime_mdia_init_video(file, &(trak->mdia), frame_w, frame_h,
frame_rate, time_scale, compressor);
quicktime_edts_init_table(&(trak->edts));
return 0;
}
int quicktime_trak_init_audio(quicktime_t *file,
quicktime_trak_t *trak,
int channels,
int sample_rate,
int bits,
int sample_size,
int time_scale,
int sample_duration,
char *compressor)
{
quicktime_mdia_init_audio(file, &(trak->mdia), channels, sample_rate, bits,
sample_size, time_scale, sample_duration, compressor);
quicktime_edts_init_table(&(trak->edts));
return 0;
}
int quicktime_trak_init_hint(quicktime_t *file,
quicktime_trak_t *trak,
quicktime_trak_t *refTrak,
int maxPktSize,
int time_scale,
int sampleDuration)
{
quicktime_tkhd_init_hint(file, &(trak->tkhd));
quicktime_edts_init_table(&(trak->edts));
quicktime_tref_init_hint(&(trak->tref), refTrak);
quicktime_mdia_init_hint(file, &(trak->mdia),
refTrak, maxPktSize, time_scale, sampleDuration);
return 0;
}
int quicktime_trak_is_hint(quicktime_trak_t *trak)
{
if (trak->tref.hint.numTracks > 0) {
return 1;
}
return 0;
}
int quicktime_trak_delete(quicktime_trak_t *trak)
{
quicktime_tkhd_delete(&(trak->tkhd));
quicktime_hint_udta_delete(&(trak->hint_udta));
return 0;
}
int quicktime_trak_dump(quicktime_trak_t *trak)
{
printf(" track\n");
quicktime_tkhd_dump(&(trak->tkhd));
quicktime_edts_dump(&(trak->edts));
quicktime_tref_dump(&(trak->tref));
quicktime_mdia_dump(&(trak->mdia));
quicktime_hint_udta_dump(&(trak->hint_udta));
return 0;
}
quicktime_trak_t* quicktime_add_trak(quicktime_moov_t *moov)
{
if(moov->total_tracks < MAXTRACKS)
{
moov->trak[moov->total_tracks] = malloc(sizeof(quicktime_trak_t));
quicktime_trak_init(moov->trak[moov->total_tracks]);
moov->total_tracks++;
}
return moov->trak[moov->total_tracks - 1];
}
quicktime_trak_t* quicktime_find_track_by_id(quicktime_moov_t *moov, int trackId)
{
int i;
for (i = 0; i < moov->total_tracks; i++) {
if (moov->trak[i]->tkhd.track_id == trackId) {
return moov->trak[i];
}
}
return NULL;
}
int quicktime_delete_trak(quicktime_moov_t *moov, quicktime_trak_t *trak)
{
int i, j;
for (i = 0; i < moov->total_tracks; i++) {
if (moov->trak[i] == trak) {
quicktime_trak_delete(trak);
free(trak);
moov->trak[i] = NULL;
for (j = i + 1; j < moov->total_tracks; j++, i++) {
moov->trak[i] = moov->trak[j];
}
moov->trak[j] = NULL;
moov->total_tracks--;
return 0;
}
}
return -1;
}
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;
}
int quicktime_write_trak(quicktime_t *file, quicktime_trak_t *trak, long moov_time_scale)
{
long duration;
long timescale;
quicktime_atom_t atom;
quicktime_atom_write_header(file, &atom, "trak");
quicktime_trak_duration(trak, &duration, ×cale);
/* printf("quicktime_write_trak duration %d\n", duration); */
/* get duration in movie's units */
if (timescale) {
trak->tkhd.duration =
(long)((float)duration / timescale * moov_time_scale);
} else {
trak->tkhd.duration = 0;
}
trak->mdia.mdhd.duration = duration;
trak->mdia.mdhd.time_scale = timescale;
if (trak->mdia.minf.is_hint) {
if (duration && timescale) {
trak->mdia.minf.hmhd.avgbitrate =
(trak->hint_udta.hinf.trpy.numBytes * 8)
/ (duration / timescale);
} else {
trak->mdia.minf.hmhd.avgbitrate = 0;
}
}
quicktime_write_tkhd(file, &(trak->tkhd));
quicktime_write_edts(file, &(trak->edts), trak->tkhd.duration);
quicktime_write_tref(file, &(trak->tref));
quicktime_write_mdia(file, &(trak->mdia));
quicktime_write_hint_udta(file, &(trak->hint_udta));
quicktime_atom_write_footer(file, &atom);
return 0;
}
long quicktime_track_end(quicktime_trak_t *trak)
{
/* get the byte endpoint of the track in the file */
long size = 0;
long chunk, chunk_offset, chunk_samples, sample;
quicktime_stsz_t *stsz = &(trak->mdia.minf.stbl.stsz);
quicktime_stsz_table_t *table = stsz->table;
quicktime_stsc_t *stsc = &(trak->mdia.minf.stbl.stsc);
quicktime_stco_t *stco;
/* get the last chunk offset */
/* the chunk offsets contain the HEADER_LENGTH themselves */
stco = &(trak->mdia.minf.stbl.stco);
chunk = stco->total_entries;
size = chunk_offset = stco->table[chunk - 1].offset;
/* get the number of samples in the last chunk */
chunk_samples = stsc->table[stsc->total_entries - 1].samples;
/* get the size of last samples */
#ifdef NOTDEF
if(stsz->sample_size)
{
/* assume audio so calculate the sample size */
size += chunk_samples * stsz->sample_size
* trak->mdia.minf.stbl.stsd.table[0].channels
* trak->mdia.minf.stbl.stsd.table[0].sample_size / 8;
}
else
{
/* assume video */
#endif
for(sample = stsz->total_entries - chunk_samples;
sample >= 0 && sample < stsz->total_entries; sample++)
{
size += stsz->table[sample].size;
}
#ifdef NOTDEF
}
#endif
/* for hint tracks */
if (quicktime_trak_is_hint(trak)) {
/* compute maximum packet duration */
if (trak->hint_udta.hinf.maxr.maxBitRate != 0) {
trak->hint_udta.hinf.dmax.milliSecs =
(trak->hint_udta.hinf.pmax.numBytes * 8) *
((float)trak->hint_udta.hinf.maxr.granularity /
(float)trak->hint_udta.hinf.maxr.maxBitRate);
}
}
return size;
}
long quicktime_track_samples(quicktime_t *file, quicktime_trak_t *trak)
{
/*printf("file->rd %d file->wr %d\n", file->rd, file->wr); */
if(file->wr)
{
/* get the sample count when creating a new file */
quicktime_stsc_table_t *table = trak->mdia.minf.stbl.stsc.table;
long total_entries = trak->mdia.minf.stbl.stsc.total_entries;
long chunk = trak->mdia.minf.stbl.stco.total_entries;
long sample;
if(chunk)
{
sample = quicktime_sample_of_chunk(trak, chunk);
sample += table[total_entries - 1].samples;
}
else
sample = 0;
return sample;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -