📄 lqt_quicktime.c
字号:
// return file->vtracks[track].track->tkhd.track_width;// return 0; if((track < 0) || (track >= file->total_vtracks)) return 0; return file->vtracks[track].track->mdia.minf.stbl.stsd.table->width; }int quicktime_video_height(quicktime_t *file, int track){// if(file->total_vtracks)// return file->vtracks[track].track->tkhd.track_height;// return 0; if((track < 0) || (track >= file->total_vtracks)) return 0; return file->vtracks[track].track->mdia.minf.stbl.stsd.table->height;}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;}void quicktime_set_cmodel(quicktime_t *file, int colormodel) { int i; for(i = 0; i < file->total_vtracks; i++) file->vtracks[i].io_cmodel = colormodel; }int lqt_get_cmodel(quicktime_t * file, int track) { if((track < file->total_vtracks) && (track >= 0)) return file->vtracks[track].io_cmodel; else return LQT_COLORMODEL_NONE; }void lqt_set_cmodel(quicktime_t *file, int track, int colormodel) { if((track < file->total_vtracks) && (track >= 0)) file->vtracks[track].io_cmodel = colormodel; else lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "lqt_set_cmodel: No track No. %d", track); }void quicktime_set_row_span(quicktime_t *file, int row_span){int i; for(i = 0; i < file->total_vtracks; i++) file->vtracks[i].io_row_span = row_span;}void lqt_set_row_span(quicktime_t *file, int track, int row_span) { file->vtracks[track].io_row_span = row_span; }void lqt_set_row_span_uv(quicktime_t *file, int track, int row_span_uv) { file->vtracks[track].io_row_span_uv = row_span_uv; }#if 0static void quicktime_set_window(quicktime_t *file, int in_x, /* Location of input frame to take picture */ int in_y, int in_w, int in_h, int out_w, /* Dimensions of output frame */ int out_h){ if(in_x >= 0 && in_y >= 0 && in_w > 0 && in_h > 0 && out_w > 0 && out_h > 0) { file->in_x = in_x; file->in_y = in_y; file->in_w = in_w; file->in_h = in_h; file->out_w = out_w; file->out_h = out_h; }}#endifvoid 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; }}double quicktime_frame_rate(quicktime_t *file, int track){ if(file->total_vtracks > track) return (float)file->vtracks[track].track->mdia.mdhd.time_scale / file->vtracks[track].track->mdia.minf.stbl.stts.table[0].sample_duration; return 0;}/* * Return the timestamp of the NEXT frame to be decoded. * Call this BEFORE one of the decoding functions. */ int64_t lqt_frame_time(quicktime_t * file, int track) { return file->vtracks[track].timestamp; }/* * Return the Duration of the entire track */int64_t lqt_video_duration(quicktime_t * file, int track) { int64_t dummy1; int64_t dummy2; return quicktime_sample_to_time(&(file->vtracks[track].track->mdia.minf.stbl.stts), -1, &dummy1, &dummy2); }/* * Get the timescale of the track. Divide the return values * of lqt_frame_duration and lqt_frame_time by the scale to * get the time in seconds. */ int lqt_video_time_scale(quicktime_t * file, int track) { if(file->total_vtracks <= track) return 0; return file->vtracks[track].track->mdia.mdhd.time_scale; }/* * Get the duration of the NEXT frame to be decoded. * If constant is not NULL it will be set to 1 if the * frame duration is constant throughout the whole track */int lqt_frame_duration(quicktime_t * file, int track, int *constant) { if(file->total_vtracks <= track) return 0; if(constant) { if(file->vtracks[track].track->mdia.minf.stbl.stts.total_entries == 1) *constant = 1; else if((file->vtracks[track].track->mdia.minf.stbl.stts.total_entries == 2) && (file->vtracks[track].track->mdia.minf.stbl.stts.table[1].sample_count == 1)) *constant = 1; else *constant = 0; } return file->vtracks[track].track->mdia.minf.stbl.stts.table[file->vtracks[track].stts_index].sample_duration; }char* quicktime_video_compressor(quicktime_t *file, int track){ if ((track < 0) || (track >= file->total_vtracks)) return NULL; return file->vtracks[track].track->mdia.minf.stbl.stsd.table[0].format;}int quicktime_write_audio(quicktime_t *file, uint8_t *audio_buffer, long samples, int track){ int result; int64_t bytes; quicktime_atom_t chunk_atom; quicktime_audio_map_t *track_map = &file->atracks[track]; quicktime_trak_t *trak = track_map->track; /* write chunk for 1 track */ bytes = samples * quicktime_audio_bits(file, track) / 8 * file->atracks[track].channels; quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, audio_buffer, bytes); quicktime_write_chunk_footer(file, trak, track_map->current_chunk, &chunk_atom, samples); /* file->atracks[track].current_position += samples; */ file->atracks[track].current_chunk++; return result;}int quicktime_write_frame(quicktime_t *file, unsigned char *video_buffer, int64_t bytes, int track){ int result = 0; quicktime_atom_t chunk_atom; quicktime_video_map_t *vtrack = &file->vtracks[track]; quicktime_trak_t *trak = vtrack->track; quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, video_buffer, bytes); quicktime_write_chunk_footer(file, trak, vtrack->current_chunk, &chunk_atom, 1); if(file->vtracks[track].current_position) quicktime_update_stts(&file->vtracks[track].track->mdia.minf.stbl.stts, file->vtracks[track].current_position-1, file->vtracks[track].track->mdia.minf.stbl.stts.default_duration); file->vtracks[track].current_position++; file->vtracks[track].current_chunk++; return result;}long quicktime_frame_size(quicktime_t *file, long frame, int track) { long bytes = 0; 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 { long total_frames = quicktime_track_samples(file, trak); if(frame < 0) frame = 0; else if(frame > total_frames - 1) frame = total_frames - 1; bytes = trak->mdia.minf.stbl.stsz.table[frame].size; } return bytes; }int quicktime_read_frame_init(quicktime_t *file, int track) { int64_t offset; quicktime_trak_t *trak = file->vtracks[track].track; offset = quicktime_sample_to_offset(file, trak, file->vtracks[track].current_position); quicktime_set_position(file, offset); if(quicktime_ftell(file) != file->file_position) { fseeko(file->stream, file->file_position, SEEK_SET); file->ftell_position = file->file_position; } return 0; }int quicktime_read_frame_end(quicktime_t *file, int track) { file->file_position = quicktime_ftell(file); file->vtracks[track].current_position++; return 0; }long quicktime_read_frame(quicktime_t *file, unsigned char *video_buffer, int track) { int64_t bytes, offset, chunk_sample, chunk; int result = 0; quicktime_trak_t *trak = file->vtracks[track].track; bytes = quicktime_frame_size(file, file->vtracks[track].current_position, track); quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, file->vtracks[track].current_position); file->vtracks[track].current_chunk = chunk; offset = quicktime_sample_to_offset(file, trak, file->vtracks[track].current_position); quicktime_set_position(file, offset); result = quicktime_read_data(file, video_buffer, bytes); lqt_update_frame_position(&file->vtracks[track]); if(!result) return 0; return bytes; }long quicktime_get_keyframe_before(quicktime_t *file, long frame, int track){ quicktime_trak_t *trak = file->vtracks[track].track; quicktime_stss_t *stss = &trak->mdia.minf.stbl.stss; int i;// Offset 1 frame++; for(i = stss->total_entries - 1; i >= 0; i--) { if(stss->table[i].sample <= frame) return stss->table[i].sample - 1; } return 0;}#if 0static long quicktime_get_keyframe_after(quicktime_t *file, long frame, int track){ quicktime_trak_t *trak = file->vtracks[track].track; quicktime_stss_t *stss = &trak->mdia.minf.stbl.stss; int i; // Offset 1 frame++; for(i = 0; i < stss->total_entries; i++) { if(stss->table[i].sample >= frame) return stss->table[i].sample - 1; } return 0;}#endifvoid quicktime_insert_keyframe(quicktime_t *file, long frame, int track){ quicktime_trak_t *trak = file->vtracks[track].track; quicktime_stss_t *stss = &trak->mdia.minf.stbl.stss; int i; if(file->file_type & (LQT_FILE_AVI|LQT_FILE_AVI_ODML)) { // Set keyframe flag in idx1 table. if(file->total_riffs == 1) quicktime_set_idx1_keyframe(file, trak, frame); // Set keyframe flag in indx table. if(file->file_type == LQT_FILE_AVI_ODML) { quicktime_set_indx_keyframe(file, trak, frame); } } // Offset 1 frame++; // Get the keyframe greater or equal to new frame for(i = 0; i < stss->total_entries; i++) { if(stss->table[i].sample >= frame) break; }// Expand table if(stss->entries_allocated <= stss->total_entries) { stss->entries_allocated *= 2; stss->table = realloc(stss->table, sizeof(quicktime_stss_table_t) * stss->entries_allocated); }// Insert before existing frame if(i < stss->total_entries) { if(stss->table[i].sample > frame) { int j, k; for(j = stss->total_entries, k = stss->total_entries - 1; k >= i; j--, k--) { stss->table[j] = stss->table[k]; } stss->table[i].sample = frame; } } else// Insert after last frame stss->table[i].sample = frame; stss->total_entries++;}int quicktime_has_keyframes(quicktime_t *file, int track){ quicktime_trak_t *trak = file->vtracks[track].track; quicktime_stss_t *stss = &trak->mdia.minf.stbl.stss; return stss->total_entries > 0;}int quicktime_init_video_map(quicktime_video_map_t *vtrack, quicktime_trak_t *trak, int encode, lqt_codec_info_t * info){ vtrack->track = trak; vtrack->current_position = 0; vtrack->current_chunk = 1; vtrack->io_cmodel = BC_RGB888; quicktime_init_vcodec(vtrack, encode, info); return 0;}int quicktime_delete_video_map(quicktime_video_map_t *vtrack){ quicktime_delete_vcodec(vtrack); if(vtrack->temp_frame) lqt_rows_free(vtrack->temp_frame); if(vtrack->timecodes) free(vtrack->timecodes); return 0;}int quicktime_init_audio_map(quicktime_t * file, quicktime_audio_map_t *atrack, quicktime_trak_t *trak, int encode, lqt_codec_info_t * info) { if(!encode) atrack->total_samples = quicktime_track_samples(file, trak); atrack->track = trak;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -