📄 quicktime.c
字号:
quicktime_mdat_delete(&(file->mdat));
return 0;
}
/* =============================== Optimization functions */
int quicktime_set_cpus(quicktime_t *file, int cpus)
{
if(cpus > 0) file->cpus = cpus;
return 0;
}
int quicktime_set_preload(quicktime_t *file, long preload)
{
if(!file->preload_size)
{
file->preload_size = preload;
file->preload_buffer = calloc(1, preload);
file->preload_start = 0;
file->preload_end = 0;
file->preload_ptr = 0;
}
}
int quicktime_get_timescale(float frame_rate)
{
int timescale = 600;
/* Encode the 29.97, 23.976, 59.94 framerates as per DV freaks */
if(frame_rate - (int)frame_rate != 0) timescale = (int)(frame_rate * 1001 + 0.5);
else
if((600 / frame_rate) - (int)(600 / frame_rate) != 0) timescale = (int)(frame_rate * 100 + 0.5);
return timescale;
}
int quicktime_seek_end(quicktime_t *file)
{
quicktime_set_position(file, file->mdat.size + file->mdat.start);
/*printf("quicktime_seek_end %ld\n", file->mdat.size + file->mdat.start); */
quicktime_update_positions(file);
return 0;
}
int quicktime_seek_start(quicktime_t *file)
{
quicktime_set_position(file, file->mdat.start + HEADER_LENGTH);
quicktime_update_positions(file);
return 0;
}
long quicktime_audio_length(quicktime_t *file, int track)
{
if(file->total_atracks > 0)
return quicktime_track_samples(file, file->atracks[track].track);
return 0;
}
long quicktime_video_length(quicktime_t *file, int track)
{
/*printf("quicktime_video_length %d %d\n", quicktime_track_samples(file, file->vtracks[track].track), track); */
if(file->total_vtracks > 0)
return quicktime_track_samples(file, file->vtracks[track].track);
return 0;
}
long quicktime_audio_position(quicktime_t *file, int track)
{
return file->atracks[track].current_position;
}
long quicktime_video_position(quicktime_t *file, int track)
{
return file->vtracks[track].current_position;
}
int quicktime_update_positions(quicktime_t *file)
{
/* Used for routines that change the positions of all tracks, like */
/* seek_end and seek_start but not for routines that reposition one track, like */
/* set_audio_position. */
long mdat_offset = quicktime_position(file) - file->mdat.start;
long sample, chunk, chunk_offset;
int i;
if(file->total_atracks)
{
sample = quicktime_offset_to_sample(file->atracks[0].track, mdat_offset);
chunk = quicktime_offset_to_chunk(&chunk_offset, file->atracks[0].track, mdat_offset);
for(i = 0; i < file->total_atracks; i++)
{
file->atracks[i].current_position = sample;
file->atracks[i].current_chunk = chunk;
}
}
if(file->total_vtracks)
{
sample = quicktime_offset_to_sample(file->vtracks[0].track, mdat_offset);
chunk = quicktime_offset_to_chunk(&chunk_offset, file->vtracks[0].track, mdat_offset);
for(i = 0; i < file->total_vtracks; i++)
{
file->vtracks[i].current_position = sample;
file->vtracks[i].current_chunk = chunk;
}
}
return 0;
}
int quicktime_set_audio_position(quicktime_t *file, long sample, int track)
{
long offset, chunk_sample, chunk;
quicktime_trak_t *trak;
if(file->total_atracks)
{
trak = file->atracks[track].track;
file->atracks[track].current_position = sample;
quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, sample);
file->atracks[track].current_chunk = chunk;
offset = quicktime_sample_to_offset(trak, sample);
quicktime_set_position(file, offset);
/*quicktime_update_positions(file); */
}
return 0;
}
int quicktime_set_video_position(quicktime_t *file, long frame, int track)
{
long offset, chunk_sample, chunk;
quicktime_trak_t *trak;
if(file->total_vtracks)
{
trak = file->vtracks[track].track;
file->vtracks[track].current_position = frame;
quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, frame);
file->vtracks[track].current_chunk = chunk;
offset = quicktime_sample_to_offset(trak, frame);
quicktime_set_position(file, offset);
/*quicktime_update_positions(file); */
}
return 0;
}
int quicktime_has_audio(quicktime_t *file)
{
if(quicktime_audio_tracks(file)) return 1;
return 0;
}
long quicktime_audio_sample_rate(quicktime_t *file, int track)
{
if(file->total_atracks)
return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].sample_rate;
return 0;
}
int quicktime_audio_bits(quicktime_t *file, int track)
{
if(file->total_atracks)
return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].sample_size;
return 0;
}
int quicktime_audio_time_scale(quicktime_t *file, int track)
{
if(file->total_atracks) {
return file->atracks[track].track->mdia.mdhd.time_scale;
}
return 0;
}
int quicktime_audio_sample_duration(quicktime_t *file, int track)
{
if(file->total_atracks) {
return file->atracks[track].track->mdia.minf.stbl.stts.table[0].sample_duration;
}
return 0;
}
char* quicktime_audio_compressor(quicktime_t *file, int track)
{
if (file->atracks[track].track == NULL)
return (NULL);
return file->atracks[track].track->mdia.minf.stbl.stsd.table[0].format;
}
int quicktime_track_channels(quicktime_t *file, int track)
{
if(track < file->total_atracks)
return file->atracks[track].channels;
return 0;
}
int quicktime_channel_location(quicktime_t *file, int *quicktime_track, int *quicktime_channel, int channel)
{
int current_channel = 0, current_track = 0;
*quicktime_channel = 0;
*quicktime_track = 0;
for(current_channel = 0, current_track = 0; current_track < file->total_atracks; )
{
if(channel >= current_channel)
{
*quicktime_channel = channel - current_channel;
*quicktime_track = current_track;
}
current_channel += file->atracks[current_track].channels;
current_track++;
}
return 0;
}
int quicktime_has_video(quicktime_t *file)
{
if(quicktime_video_tracks(file)) return 1;
return 0;
}
int quicktime_video_width(quicktime_t *file, int track)
{
if(file->total_vtracks) {
int width =
file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].width;
if (width) {
return width;
}
return file->vtracks[track].track->tkhd.track_width;
}
return 0;
}
int quicktime_video_height(quicktime_t *file, int track)
{
if(file->total_vtracks) {
int height = file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].height;
if (height) {
return height;
}
return file->vtracks[track].track->tkhd.track_height;
}
return 0;
}
int quicktime_video_depth(quicktime_t *file, int track)
{
if(file->total_vtracks)
return file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].depth;
return 0;
}
int quicktime_set_depth(quicktime_t *file, int depth, int track)
{
int i;
for(i = 0; i < file->total_vtracks; i++)
{
file->vtracks[i].track->mdia.minf.stbl.stsd.table[0].depth = depth;
}
}
float quicktime_video_frame_rate(quicktime_t *file, int track)
{
float ret = 0;
int num = 0;
if(file->total_vtracks) {
ret = file->vtracks[track].track->mdia.mdhd.time_scale;
if (file->vtracks[track].track->mdia.minf.stbl.stts.table[0].sample_duration == 0)
num = 1;
ret /=
file->vtracks[track].track->mdia.minf.stbl.stts.table[num].sample_duration;
}
return ret;
}
char* quicktime_video_compressor(quicktime_t *file, int track)
{
if (file->vtracks[track].track == NULL)
return (NULL);
return file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].format;
}
int quicktime_video_time_scale(quicktime_t *file, int track)
{
if(file->total_vtracks) {
return file->vtracks[track].track->mdia.mdhd.time_scale;
}
return 0;
}
int quicktime_video_frame_time(quicktime_t *file, int track, long frame,
long *start, int *duration)
{
quicktime_stts_t *stts;
int i;
long f;
if (file->total_vtracks == 0) {
return 0;
}
stts = &(file->vtracks[track].track->mdia.minf.stbl.stts);
if (frame < file->last_frame) {
/* we need to reset our cached values */
file->last_frame = 0;
file->last_start = 0;
file->last_stts_index = 0;
}
i = file->last_stts_index;
f = file->last_frame;
*start = file->last_start;
while (i < stts->total_entries) {
if (f + stts->table[i].sample_count <= frame) {
*start += stts->table[i].sample_duration
* stts->table[i].sample_count;
f += stts->table[i].sample_count;
i++;
} else {
/* cache the results for future use */
file->last_stts_index = i;
file->last_frame = f;
file->last_start = *start;
*start += stts->table[i].sample_duration * (frame - f);
*duration = stts->table[i].sample_duration;
return 1;
}
}
/* error */
return 0;
}
int quicktime_get_mp4_video_decoder_config(quicktime_t *file, int track, u_char** ppBuf, int* pBufSize)
{
quicktime_esds_t* esds;
if (!file->total_vtracks) {
return 0;
}
esds = &file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].esds;
return quicktime_esds_get_decoder_config(esds, ppBuf, pBufSize);
}
int quicktime_set_mp4_video_decoder_config(quicktime_t *file, int track, u_char* pBuf, int bufSize)
{
quicktime_esds_t* esds;
if (!file->total_vtracks) {
return 0;
}
esds = &file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].esds;
return quicktime_esds_set_decoder_config(esds, pBuf, bufSize);
}
int quicktime_get_mp4_audio_decoder_config(quicktime_t *file, int track, u_char** ppBuf, int* pBufSize)
{
quicktime_esds_t* esds;
if (!file->total_atracks) {
return 0;
}
esds = &file->atracks[track].track->mdia.minf.stbl.stsd.table[0].esds;
return quicktime_esds_get_decoder_config(esds, ppBuf, pBufSize);
}
int quicktime_set_mp4_audio_decoder_config(quicktime_t *file, int track, u_char* pBuf, int bufSize)
{
quicktime_esds_t* esds;
if (!file->total_atracks) {
return 0;
}
esds = &file->atracks[track].track->mdia.minf.stbl.stsd.table[0].esds;
return quicktime_esds_set_decoder_config(esds, pBuf, bufSize);
}
long quicktime_samples_to_bytes(quicktime_trak_t *track, long samples)
{
return samples
* track->mdia.minf.stbl.stsd.table[0].channels
* track->mdia.minf.stbl.stsd.table[0].sample_size / 8;
}
int quicktime_write_audio(quicktime_t *file, char *audio_buffer, long samples, int track)
{
long offset;
int result;
long bytes;
/* Defeat 32 bit file size limit. */
if(quicktime_test_position(file)) return 1;
/* write chunk for 1 track */
bytes = samples * quicktime_audio_bits(file, track) / 8 * file->atracks[track].channels;
offset = quicktime_position(file);
result = quicktime_write_data(file, audio_buffer, bytes);
if(result) result = 0; else result = 1; /* defeat fwrite's return */
quicktime_update_tables(file,
file->atracks[track].track,
offset,
file->atracks[track].current_chunk,
file->atracks[track].current_position,
samples,
0,
0,
0,
0);
file->atracks[track].current_position += samples;
file->atracks[track].current_chunk++;
return result;
}
int quicktime_write_audio_frame(quicktime_t *file, unsigned char *audio_buffer, long bytes, int track)
{
long offset = quicktime_position(file);
int result = 0;
/* Defeat 32 bit file size limit. */
if(quicktime_test_position(file)) return 1;
result = quicktime_write_data(file, audio_buffer, bytes);
if(result) result = 0; else result = 1;
quicktime_update_tables(file,
file->atracks[track].track,
offset,
file->atracks[track].current_chunk,
file->atracks[track].current_position,
1,
bytes,
0,
0,
0);
file->atracks[track].current_position += 1;
file->atracks[track].current_chunk++;
return result;
}
int quicktime_write_video_frame(quicktime_t *file,
unsigned char *video_buffer,
long bytes,
int track,
u_char isKeyFrame,
long duration,
long renderingOffset)
{
long offset = quicktime_position(file);
int result = 0;
/* Defeat 32 bit file size limit. */
if(quicktime_test_position(file)) return 1;
result = quicktime_write_data(file, video_buffer, bytes);
if(result) result = 0; else result = 1;
quicktime_update_tables(file,
file->vtracks[track].track,
offset,
file->vtracks[track].current_chunk,
file->vtracks[track].current_position,
1,
bytes,
duration,
isKeyFrame,
renderingOffset);
file->vtracks[track].current_position += 1;
file->vtracks[track].current_chunk++;
return result;
}
static int quicktime_write_media_hint(quicktime_t* file,
u_char* hintBuffer,
long hintBufferSize,
quicktime_trak_t* hintTrak,
long* pSampleNumber,
long hintSampleDuration,
u_char isSyncSample)
{
long offset = quicktime_position(file);
quicktime_hint_info_t hintInfo;
int result = 0;
/* handle 32 bit file size limit */
if (quicktime_test_position(file)) {
return 1;
}
/* get info about this hint */
quicktime_get_hint_info(hintBuffer, hintBufferSize, &hintInfo);
/* update overall info */
hintTrak->hint_udta.hinf.trpy.numBytes += hintInfo.trpy;
hintTrak->hint_udta.hinf.nump.numPackets += hintInfo.nump;
hintTrak->hint_udta.hinf.tpyl.numBytes += hintInfo.tpyl;
hintTrak->hint_udta.hinf.dmed.numBytes += hintInfo.dmed;
hintTrak->hint_udta.hinf.drep.numBytes += hintInfo.drep;
hintTrak->hint_udta.hinf.dimm.numBytes += hintInfo.dimm;
hintTrak->hint_udta.hinf.tmin.milliSecs =
MAX(hintInfo.tmin, hintTrak->hint_udta.hinf.tmin.milliSecs);
hintTrak->hint_udta.hinf.tmax.milliSecs =
MAX(hintInfo.tmax, hintTrak->hint_udta.hinf.tmax.milliSecs);
hintTrak->hint_udta.hinf.pmax.numBytes =
MAX(hintInfo.pmax, hintTrak->hint_udta.hinf.pmax.numBytes);
hintTrak->mdia.minf.hmhd.maxPDUsize =
hintTrak->hint_udta.hinf.pmax.numBytes;
hintTrak->mdia.minf.hmhd.avgPDUsize =
hintTrak->hint_udta.hinf.trpy.numBytes
/ hintTrak->hint_udta.hinf.nump.numPackets;
/* write the hint data */
result = quicktime_write_data(file, hintBuffer, hintBufferSize);
result = (result ? 0 : 1);
quicktime_update_tables(file, hintTrak, offset, *pSampleNumber + 1,
*pSampleNumber, 1, hintBufferSize, hintSampleDuration, isSyncSample, 0);
(*pSampleNumber)++;
return result;
}
int quicktime_write_audio_hint(quicktime_t *file,
unsigned char *hintBuffer,
long hintBufferSize,
int audioTrack,
int hintTrack,
long hintSampleDuration)
{
quicktime_trak_t* hintTrak =
file->atracks[audioTrack].hintTracks[hintTrack];
return quicktime_write_media_hint(file, hintBuffer, hintBufferSize,
hintTrak, &(file->atracks[audioTrack].hintPositions[hintTrack]),
hintSampleDuration, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -