?? quicktime.c
字號:
#include "quicktime.h"int quicktime_make_streamable(char *in_path, char *out_path){ quicktime_t file, *old_file, new_file; int moov_exists = 0, mdat_exists = 0, result, atoms = 1; long mdat_start, mdat_size; quicktime_atom_t leaf_atom; long moov_length; quicktime_init(&file);/* find the moov atom in the old file */ if(!(file.stream = fopen(in_path, "rb"))) { perror("quicktime_make_streamable"); return 1; } fseek(file.stream, 0, SEEK_END); file.total_length = ftell(file.stream); fseek(file.stream, 0, SEEK_SET);/* get the locations of moov and mdat atoms */ do {/*printf("%x\n", quicktime_position(&file)); */ result = quicktime_atom_read_header(&file, &leaf_atom); if(!result) { if(quicktime_atom_is(&leaf_atom, "moov")) { moov_exists = atoms; moov_length = leaf_atom.size; } else if(quicktime_atom_is(&leaf_atom, "mdat")) { mdat_start = quicktime_position(&file) - HEADER_LENGTH; mdat_size = leaf_atom.size; mdat_exists = atoms; } quicktime_atom_skip(&file, &leaf_atom); atoms++; } }while(!result && quicktime_position(&file) < file.total_length); fclose(file.stream); if(!moov_exists) { printf("quicktime_make_streamable: no moov atom\n"); return 1; } if(!mdat_exists) { printf("quicktime_make_streamable: no mdat atom\n"); return 1; }/* copy the old file to the new file */ if(moov_exists && mdat_exists) {/* moov wasn't the first atom */ if(moov_exists > 1) { char *buffer; long buf_size = 1000000; result = 0;/* read the header proper */ if(!(old_file = quicktime_open(in_path, 1, 0, 0))) { return 1; } quicktime_shift_offsets(&(old_file->moov), moov_length);/* open the output file */ if(!(new_file.stream = fopen(out_path, "wb"))) { perror("quicktime_make_streamable"); result = 1; } else {/* set up some flags */ new_file.wr = 1; new_file.rd = 0; quicktime_write_moov(&new_file, &(old_file->moov)); quicktime_set_position(old_file, mdat_start); if(!(buffer = calloc(1, buf_size))) { result = 1; printf("quicktime_make_streamable: out of memory\n"); } else { while(quicktime_position(old_file) < mdat_start + mdat_size && !result) { if(quicktime_position(old_file) + buf_size > mdat_start + mdat_size) buf_size = mdat_start + mdat_size - quicktime_position(old_file); if(!quicktime_read_data(old_file, buffer, buf_size)) result = 1; if(!result) { if(!quicktime_write_data(&new_file, buffer, buf_size)) result = 1; } } free(buffer); } fclose(new_file.stream); } quicktime_close(old_file); } else { printf("quicktime_make_streamable: header already at 0 offset\n"); return 0; } } return 0;}int quicktime_set_time_scale(quicktime_t *file, int time_scale){ file->moov.mvhd.time_scale = time_scale;}int quicktime_set_copyright(quicktime_t *file, char *string){ quicktime_set_udta_string(&(file->moov.udta.copyright), &(file->moov.udta.copyright_len), string);}int quicktime_set_name(quicktime_t *file, char *string){ quicktime_set_udta_string(&(file->moov.udta.name), &(file->moov.udta.name_len), string);}int quicktime_set_info(quicktime_t *file, char *string){ quicktime_set_udta_string(&(file->moov.udta.info), &(file->moov.udta.info_len), string);}int quicktime_get_time_scale(quicktime_t *file){ return file->moov.mvhd.time_scale;}char* quicktime_get_copyright(quicktime_t *file){ return file->moov.udta.copyright;}char* quicktime_get_name(quicktime_t *file){ return file->moov.udta.name;}char* quicktime_get_info(quicktime_t *file){ return file->moov.udta.info;}int quicktime_get_iod_audio_profile_level(quicktime_t *file){ return file->moov.iods.audioProfileId;}int quicktime_set_iod_audio_profile_level(quicktime_t *file, int id){ quicktime_iods_set_audio_profile(&file->moov.iods, id);}int quicktime_get_iod_video_profile_level(quicktime_t *file){ return file->moov.iods.videoProfileId;}int quicktime_set_iod_video_profile_level(quicktime_t *file, int id){ quicktime_iods_set_video_profile(&file->moov.iods, id);}int quicktime_video_tracks(quicktime_t *file){ int i, result = 0; for(i = 0; i < file->moov.total_tracks; i++) { if(file->moov.trak[i]->mdia.minf.is_video) result++; } return result;}int quicktime_audio_tracks(quicktime_t *file){ int i, result = 0; quicktime_minf_t *minf; for(i = 0; i < file->moov.total_tracks; i++) { minf = &(file->moov.trak[i]->mdia.minf); if(minf->is_audio) result++; } return result;}int quicktime_set_audio(quicktime_t *file, int channels, long sample_rate, int bits, int sample_size, int time_scale, int sample_duration, char *compressor){ int i, j; quicktime_trak_t *trak; /* delete any existing tracks */ for(i = 0; i < file->total_atracks; i++) { for (j = 0; j < file->atracks[i].totalHintTracks; j++) { quicktime_delete_trak(&(file->moov), file->atracks[i].hintTracks[j]); free(file->atracks[i].hintTracks[j]); file->atracks[i].hintTracks[j] = NULL; file->total_hint_tracks--; } quicktime_delete_audio_map(&(file->atracks[i])); quicktime_delete_trak(&(file->moov), file->atracks[i].track); } free(file->atracks); file->atracks = NULL; file->total_atracks = 0; if(channels) { /* Fake the bits parameter for some formats. */ if(quicktime_match_32(compressor, QUICKTIME_ULAW) || quicktime_match_32(compressor, QUICKTIME_IMA4)) bits = 16; file->atracks = (quicktime_audio_map_t*) calloc(1, sizeof(quicktime_audio_map_t)); trak = quicktime_add_track(&(file->moov)); quicktime_trak_init_audio(file, trak, channels, sample_rate, bits, sample_size, time_scale, sample_duration, compressor); quicktime_init_audio_map(&(file->atracks[0]), trak); file->atracks[file->total_atracks].track = trak; file->atracks[file->total_atracks].channels = channels; file->atracks[file->total_atracks].current_position = 0; file->atracks[file->total_atracks].current_chunk = 1; file->total_atracks++; } return 1; /* Return the number of tracks created */}int quicktime_set_video(quicktime_t *file, int tracks, int frame_w, int frame_h, float frame_rate, int time_scale, char *compressor){ int i, j; quicktime_trak_t *trak; /* delete any existing tracks */ for(i = 0; i < file->total_vtracks; i++) { for (j = 0; j < file->vtracks[i].totalHintTracks; j++) { quicktime_delete_trak(&(file->moov), file->vtracks[i].hintTracks[j]); file->vtracks[i].hintTracks[j] = NULL; file->total_hint_tracks--; } quicktime_delete_video_map(&(file->vtracks[i])); quicktime_delete_trak(&(file->moov), file->vtracks[i].track); } free(file->vtracks); file->vtracks = NULL; file->total_vtracks = 0; if (tracks > 0) { file->total_vtracks = tracks; file->vtracks = (quicktime_video_map_t*)calloc(1, sizeof(quicktime_video_map_t) * file->total_vtracks); for(i = 0; i < tracks; i++) { trak = quicktime_add_track(&(file->moov)); quicktime_trak_init_video(file, trak, frame_w, frame_h, frame_rate, time_scale, compressor); quicktime_init_video_map(&(file->vtracks[i]), trak); } } return 0;}int quicktime_set_audio_hint(quicktime_t *file, int audioTrack, char *payloadName, u_int* pPayloadNumber, int maxPktSize){ quicktime_audio_map_t* pMap = NULL; quicktime_trak_t* hintTrak = NULL; int timeScale; float frameRate; int sampleDuration; char rtpMapBuf[128]; char sdpBuf[256]; /* check our arguments */ if (file == NULL) { return -1; } if (audioTrack < 0 || audioTrack > file->total_atracks) { return -1; } if (payloadName == NULL) { return -1; } pMap = &file->atracks[audioTrack]; timeScale = quicktime_audio_time_scale(file, audioTrack); if (timeScale == 0) { return -1; } sampleDuration = file->atracks[audioTrack].track->mdia.minf.stbl.stts.table[0].sample_duration; /* add the hint track */ hintTrak = quicktime_add_track(&(file->moov)); if (*pPayloadNumber == 0) { (*pPayloadNumber) = 96 + file->total_hint_tracks++; } /* initialize it to reference the audio track */ quicktime_trak_init_hint(file, hintTrak, pMap->track, maxPktSize, timeScale, sampleDuration); /* set the payload info */ hintTrak->hint_udta.hinf.payt.payloadNumber = *pPayloadNumber; sprintf(rtpMapBuf, "%s/%u", payloadName, timeScale); strcpy(hintTrak->hint_udta.hinf.payt.rtpMapString, rtpMapBuf); /* set the SDP media section */ sprintf(sdpBuf, "m=audio 0 RTP/AVP %u\015\012a=rtpmap:%u %s\015\012a=control:trackID=%u\015\012", *pPayloadNumber, *pPayloadNumber, rtpMapBuf, hintTrak->tkhd.track_id); quicktime_sdp_set(&(hintTrak->hint_udta.hnti.sdp), sdpBuf); pMap->hintTracks[pMap->totalHintTracks] = hintTrak; pMap->hintPositions[pMap->totalHintTracks] = 0; pMap->totalHintTracks++; return (pMap->totalHintTracks - 1);}int quicktime_set_video_hint(quicktime_t *file, int videoTrack, char *payloadName, u_int* pPayloadNumber, int maxPktSize){ quicktime_video_map_t* pMap = NULL; quicktime_trak_t* hintTrak = NULL; float frameRate; int timeScale; int sampleDuration; char rtpMapBuf[128]; char sdpBuf[1024]; /* check our arguments */ if (file == NULL) { return -1; } if (videoTrack < 0 || videoTrack > file->total_vtracks) { return -1; } if (payloadName == NULL) { return -1; } frameRate = quicktime_video_frame_rate(file, videoTrack); if (frameRate == 0.0) { return -1; } timeScale = quicktime_video_time_scale(file, videoTrack); if (timeScale == 0) { return -1; } sampleDuration = timeScale / frameRate; if (sampleDuration == 0) { return -1; } /* add the hint track */ hintTrak = quicktime_add_track(&(file->moov)); if (*pPayloadNumber == 0) { (*pPayloadNumber) = 96 + file->total_hint_tracks++; } pMap = &file->vtracks[videoTrack]; /* initialize it to reference the video track */ quicktime_trak_init_hint(file, hintTrak, pMap->track, maxPktSize, timeScale, sampleDuration); /* set the payload info */ hintTrak->hint_udta.hinf.payt.payloadNumber = *pPayloadNumber; sprintf(rtpMapBuf, "%s/90000", payloadName); strcpy(hintTrak->hint_udta.hinf.payt.rtpMapString, rtpMapBuf); /* set the SDP media section */ sprintf(sdpBuf, "m=video 0 RTP/AVP %u\015\012a=rtpmap:%u %s\015\012a=control:trackID=%u\015\012", *pPayloadNumber, *pPayloadNumber, rtpMapBuf, hintTrak->tkhd.track_id); quicktime_sdp_set(&(hintTrak->hint_udta.hnti.sdp), sdpBuf); pMap->hintTracks[pMap->totalHintTracks] = hintTrak; pMap->hintPositions[pMap->totalHintTracks] = 0; pMap->totalHintTracks++; return (pMap->totalHintTracks - 1);}char* quicktime_get_session_sdp(quicktime_t *file){ return file->moov.udta.hnti.rtp.string;}int quicktime_set_session_sdp(quicktime_t *file, char* sdpString){ return quicktime_rtp_set(&(file->moov.udta.hnti.rtp), sdpString);}int quicktime_add_audio_sdp(quicktime_t *file, char* sdpString, int track, int hintTrack){ quicktime_trak_t* hintTrak = file->atracks[track].hintTracks[hintTrack]; quicktime_sdp_append(&(hintTrak->hint_udta.hnti.sdp), sdpString);}int quicktime_add_video_sdp(quicktime_t *file, char* sdpString, int track, int hintTrack){ quicktime_trak_t* hintTrak = file->vtracks[track].hintTracks[hintTrack]; quicktime_sdp_append(&(hintTrak->hint_udta.hnti.sdp), sdpString);}static int quicktime_set_media_hint_max_rate(quicktime_t *file, int granularity, int maxBitRate, quicktime_trak_t* hintTrak){ hintTrak->hint_udta.hinf.maxr.granularity = granularity; hintTrak->hint_udta.hinf.maxr.maxBitRate = maxBitRate; hintTrak->mdia.minf.hmhd.maxbitrate = maxBitRate; /* Give upper bound on MP4 max bitrate for 1 minute window */ hintTrak->mdia.minf.hmhd.slidingavgbitrate = maxBitRate * (60000 / granularity); return 0;}int quicktime_set_audio_hint_max_rate(quicktime_t *file, int granularity, int maxBitRate, int audioTrack, int hintTrack){ quicktime_trak_t* hintTrak = file->atracks[audioTrack].hintTracks[hintTrack]; return quicktime_set_media_hint_max_rate(file, granularity, maxBitRate, hintTrak);}int quicktime_set_video_hint_max_rate(quicktime_t *file, int granularity, int maxBitRate, int videoTrack, int hintTrack){ quicktime_trak_t* hintTrak = file->vtracks[videoTrack].hintTracks[hintTrack]; return quicktime_set_media_hint_max_rate(file, granularity, maxBitRate, hintTrak);}int quicktime_set_framerate(quicktime_t *file, float framerate){ int i; int new_time_scale, new_sample_duration; new_time_scale = quicktime_get_timescale(framerate); new_sample_duration = (int)((float)new_time_scale / framerate + 0.5); for(i = 0; i < file->total_vtracks; i++) { file->vtracks[i].track->mdia.mdhd.time_scale = new_time_scale; file->vtracks[i].track->mdia.minf.stbl.stts.table[0].sample_duration = new_sample_duration; }}quicktime_trak_t* quicktime_add_track(quicktime_moov_t *moov){ quicktime_trak_t *trak; trak = moov->trak[moov->total_tracks] = calloc(1, sizeof(quicktime_trak_t)); quicktime_trak_init(trak); trak->tkhd.track_id = moov->mvhd.next_track_id; moov->mvhd.next_track_id++; moov->total_tracks++; return trak;}/* ============================= Initialization functions */int quicktime_init(quicktime_t *file){ memset(file, 0, sizeof(quicktime_t)); quicktime_mdat_init(&(file->mdat)); quicktime_moov_init(&(file->moov)); file->cpus = 1; return 0;}int quicktime_delete(quicktime_t *file){ int i; if(file->total_atracks) { for(i = 0; i < file->total_atracks; i++) quicktime_delete_audio_map(&(file->atracks[i])); free(file->atracks); } if(file->total_vtracks) { for(i = 0; i < file->total_vtracks; i++) quicktime_delete_video_map(&(file->vtracks[i])); free(file->vtracks); } file->total_atracks = 0; file->total_vtracks = 0; if(file->preload_size) { free(file->preload_buffer); file->preload_size = 0; } quicktime_moov_delete(&(file->moov));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -