void quicktime_init_maps(quicktime_t *file) { int i, track; /* 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]); } }
gavl_time_t lqt_gavl_duration(quicktime_t * file) { gavl_time_t ret = 0, time; int i, imax; int timescale; int64_t time_scaled; imax = quicktime_audio_tracks(file); for(i = 0; i < imax; i++) { timescale = quicktime_sample_rate(file, i); time_scaled = quicktime_audio_length(file, i); time = gavl_time_unscale(timescale, time_scaled); if(ret < time) ret = time; } imax = quicktime_video_tracks(file); for(i = 0; i < imax; i++) { timescale = lqt_video_time_scale(file, i); time_scaled = lqt_video_duration(file, i); time = gavl_time_unscale(timescale, time_scaled); if(ret < time) ret = time; } return ret; }
int lqt_gavl_get_audio_format(quicktime_t * file, int track, gavl_audio_format_t * format) { int i; const lqt_channel_t * channel_setup; if(track >= quicktime_audio_tracks(file) || track < 0) return 0; format->num_channels = quicktime_track_channels(file, track); format->samplerate = quicktime_sample_rate(file, track); format->sample_format = sampleformat_lqt_2_gavl(lqt_get_sample_format(file, track)); format->interleave_mode = GAVL_INTERLEAVE_ALL; format->samples_per_frame = 1024; // Meaningless but better than 0 channel_setup = lqt_get_channel_setup(file, track); if(channel_setup) { for(i = 0; i < format->num_channels; i++) { format->channel_locations[i] = channel_lqt_2_gavl(channel_setup[i]); } } else gavl_set_channel_setup(format); return 1; }
void lqt_gavl_add_audio_track(quicktime_t * file, gavl_audio_format_t * format, lqt_codec_info_t * codec) { int track = quicktime_audio_tracks(file); lqt_add_audio_track(file, format->num_channels, format->samplerate, 16, NULL); if(codec) lqt_gavl_set_audio_codec(file, track, format, codec); }
void lqt_gavl_seek_scaled(quicktime_t * file, gavl_time_t * time, int scale) { int imax; int i; int64_t video_time_save = -1; int video_timescale_save = -1; int64_t time_scaled; int timescale; /* We synchronize to the first video track */ imax = quicktime_video_tracks(file); for(i = 0; i < imax; i++) { timescale = lqt_video_time_scale(file, i); time_scaled = gavl_time_rescale(scale, timescale, *time); lqt_seek_video(file, i, time_scaled); if(!i) { video_timescale_save = timescale; video_time_save = time_scaled; } } if(video_time_save >= 0) *time = gavl_time_unscale(video_timescale_save, video_time_save); imax = quicktime_audio_tracks(file); for(i = 0; i < imax; i++) { timescale = quicktime_sample_rate(file, i); time_scaled = gavl_time_rescale(scale, timescale, *time); quicktime_set_audio_position(file, time_scaled, i); } imax = lqt_text_tracks(file); for(i = 0; i < imax; i++) { if(lqt_is_chapter_track(file, i)) continue; timescale = lqt_text_time_scale(file, i); time_scaled = gavl_time_rescale(scale, timescale, *time); lqt_set_text_time(file, i, time_scaled); } }
int quicktime_has_audio(quicktime_t *file) { if(quicktime_audio_tracks(file)) return 1; 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; }
void decode_mov(decode_t *decode) { quicktime_t *qt_handle=NULL; unsigned char **p_raw_buffer; char *p_v_codec=NULL,*p_a_codec=NULL,*p_buffer=NULL,*p_tmp=NULL; int s_width=0,s_height=0,s_channel=0,s_bits=0,s_buff_size=0,s_audio_size=0,s_video_size=0,s_sample=0; int s_cont,s_frames; double s_fps=0; long s_audio_rate,s_qt_pos; uint16_t *p_mask1, *p_mask2; char msgbuf[TC_BUF_MIN]; qt_handle = quicktime_open((char * )decode->name, 1, 0); if (qt_handle == NULL) { QT_ABORT("can't open quicktime!"); } quicktime_set_preload(qt_handle, 10240000); s_fps = quicktime_frame_rate(qt_handle, 0); if (decode->format == TC_CODEC_PCM) { if (quicktime_audio_tracks(qt_handle) == 0) { QT_ABORT("no audio track in quicktime found!"); } s_channel = quicktime_track_channels(qt_handle, 0); s_audio_rate = quicktime_sample_rate(qt_handle, 0); s_bits = quicktime_audio_bits(qt_handle, 0); s_audio_size = quicktime_audio_length(qt_handle,0); p_a_codec = quicktime_audio_compressor(qt_handle, 0); if (decode->frame_limit[1] < s_audio_size) { s_audio_size = decode->frame_limit[1] - decode->frame_limit[0]; } else { s_audio_size -= decode->frame_limit[0]; } if (decode->verbose) { tc_log_info(__FILE__, "Audio codec=%s, rate=%ld Hz, bits=%d, channels=%d", p_a_codec, s_audio_rate, s_bits, s_channel); } if ((s_bits != 8) && (s_bits != 16)) { tc_snprintf(msgbuf, sizeof(msgbuf), "unsupported %d bit rate" " in quicktime!", s_bits); QT_ABORT(msgbuf); } if (s_channel > 2) { tc_snprintf(msgbuf, sizeof(msgbuf), "too many audio tracks " "(%d) found in quicktime!", s_channel); QT_ABORT(msgbuf); } if (strlen(p_a_codec) == 0) { QT_ABORT("unsupported codec (empty!) in quicktime!"); } if (quicktime_supported_audio(qt_handle, 0) != 0) { s_qt_pos = quicktime_audio_position(qt_handle,0); s_sample = (1.00 * s_channel * s_bits *s_audio_rate)/(s_fps * 8); s_buff_size = s_sample * sizeof(uint16_t); p_buffer = tc_malloc(s_buff_size); if (s_bits == 16) s_sample /= 2; if (s_channel == 1) { p_mask1=(uint16_t *)p_buffer; quicktime_set_audio_position(qt_handle, s_qt_pos + decode->frame_limit[0], 0); for (; s_audio_size > 0; s_audio_size -= s_sample) { if (quicktime_decode_audio(qt_handle, p_mask1, NULL, s_sample, 0) < 0) { QT_ABORT("error reading quicktime audio frame"); } QT_WRITE(decode->fd_out, p_buffer, s_buff_size); } } else { s_sample /= 2; p_mask1 = (uint16_t *)p_buffer; p_mask2 = tc_malloc(s_sample * sizeof(uint16_t)); s_qt_pos += decode->frame_limit[0]; quicktime_set_audio_position(qt_handle, s_qt_pos, 0); for (; s_audio_size > 0; s_audio_size -= s_sample) { if (quicktime_decode_audio(qt_handle, p_mask1, NULL, s_sample, 0) < 0) { QT_ABORT("error reading quicktime audio frame"); } quicktime_set_audio_position(qt_handle, s_qt_pos, 0); if (quicktime_decode_audio(qt_handle,p_mask2, NULL,s_sample, 1) < 0) { QT_ABORT("error reading quicktime audio frame"); } for (s_cont = s_sample - 1; s_cont >= 0; s_cont--) p_mask1[s_cont<<1] = p_mask1[s_cont]; for (s_cont = 0; s_cont < s_sample; s_cont++) p_mask1[1+(s_cont<<1)] = p_mask2[s_cont]; s_qt_pos += s_sample; QT_WRITE(decode->fd_out, p_buffer, s_buff_size >> 1); } free(p_mask2); } free(p_buffer); } #if !defined(LIBQUICKTIME_000904) else if ((strcasecmp(p_a_codec, QUICKTIME_RAW) == 0)
void probe_mov(info_t *ipipe) { quicktime_t *qt_file=NULL; char *codec=NULL; int j, tracks; /* open movie for video probe */ if(qt_file==NULL) if(NULL == (qt_file = quicktime_open((char *)ipipe->name,1,0))){ tc_log_error(__FILE__,"can't open quicktime!"); ipipe->error=1; return; } // extract audio parameters tracks=quicktime_audio_tracks(qt_file); if(tracks>TC_MAX_AUD_TRACKS) { tc_log_warn(__FILE__, "only %d of %d audio tracks scanned", TC_MAX_AUD_TRACKS, tracks); tracks=TC_MAX_AUD_TRACKS; } for(j=0; j<tracks; ++j) { ipipe->probe_info->track[j].samplerate = quicktime_sample_rate(qt_file, j); ipipe->probe_info->track[j].chan = quicktime_track_channels(qt_file, j); ipipe->probe_info->track[j].bits = quicktime_audio_bits(qt_file, j); codec = quicktime_audio_compressor(qt_file, j); if(strcasecmp(codec,QUICKTIME_RAW)==0 || strcasecmp(codec,QUICKTIME_TWOS)==0) ipipe->probe_info->track[j].format = CODEC_PCM; else if(strcasecmp(codec,QUICKTIME_IMA4)==0) ipipe->probe_info->track[j].format = CODEC_IMA4; else /* XXX not right but works */ ipipe->probe_info->track[j].format = CODEC_PCM; if (! binary_dump) tc_log_info(__FILE__, "audio codec=%s", codec); if(ipipe->probe_info->track[j].chan>0) ++ipipe->probe_info->num_tracks; } // read all video parameter from input file ipipe->probe_info->width = quicktime_video_width(qt_file, 0); ipipe->probe_info->height = quicktime_video_height(qt_file, 0); ipipe->probe_info->fps = quicktime_frame_rate(qt_file, 0); ipipe->probe_info->frames = quicktime_video_length(qt_file, 0); codec = quicktime_video_compressor(qt_file, 0); //check for supported codecs if(codec!=NULL) { if(strlen(codec)==0) { ipipe->probe_info->codec=TC_CODEC_RGB; } else { if(strcasecmp(codec,QUICKTIME_DV)==0) ipipe->probe_info->codec=TC_CODEC_DV; if(strcasecmp(codec,"dvsd")==0) ipipe->probe_info->codec=TC_CODEC_DV; if(strcasecmp(codec,"DIV3")==0) ipipe->probe_info->codec=TC_CODEC_DIVX3; if(strcasecmp(codec,"DIVX")==0) ipipe->probe_info->codec=TC_CODEC_DIVX4; if(strcasecmp(codec,"DX50")==0) ipipe->probe_info->codec=TC_CODEC_DIVX5; if(strcasecmp(codec,"MJPG")==0 || strcasecmp(codec,"JPEG")==0) ipipe->probe_info->codec=TC_CODEC_MJPEG; if(strcasecmp(codec,"YUV2")==0) ipipe->probe_info->codec=TC_CODEC_YUV2; if(strcasecmp(codec,"SVQ1")==0) ipipe->probe_info->codec=TC_CODEC_SVQ1; if(strcasecmp(codec,"SVQ3")==0) ipipe->probe_info->codec=TC_CODEC_SVQ3; } } else ipipe->probe_info->codec=TC_CODEC_UNKNOWN; if (! binary_dump) tc_log_info(__FILE__, "video codec=%s", codec); ipipe->probe_info->magic=TC_MAGIC_MOV; tc_frc_code_from_value(&(ipipe->probe_info->frc), ipipe->probe_info->fps); return; }