⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 quicktime.c

📁 JPEG-MPEG編解碼技術書集的代碼
💻 C
📖 第 1 页 / 共 3 页
字号:
}

int quicktime_write_video_hint(quicktime_t *file, 
				unsigned char *hintBuffer, 
				long hintBufferSize, 
				int videoTrack,
				int hintTrack,
				long hintSampleDuration,
				u_char isKeyFrame)
{
	quicktime_trak_t* hintTrak = 
		file->vtracks[videoTrack].hintTracks[hintTrack];

	return quicktime_write_media_hint(file, hintBuffer, hintBufferSize,
		hintTrak, &(file->vtracks[videoTrack].hintPositions[hintTrack]), 
		hintSampleDuration, isKeyFrame);
}

FILE* quicktime_get_fd(quicktime_t *file)
{
	if(ftell(file->stream) != file->file_position) fseek(file->stream, file->file_position, SEEK_SET);
	return file->stream;
}

int quicktime_write_frame_init(quicktime_t *file, int track)
{
	if(ftell(file->stream) != file->file_position) fseek(file->stream, file->file_position, SEEK_SET);
	file->offset = quicktime_position(file);
	return 0;
}

int quicktime_write_frame_end(quicktime_t *file, int track)
{
	long bytes;
	file->file_position = ftell(file->stream);
	bytes = quicktime_position(file) - file->offset;
	quicktime_update_tables(file,
						file->vtracks[track].track,
						file->offset,
						file->vtracks[track].current_chunk,
						file->vtracks[track].current_position,
						1,
						bytes,
						0,
						0,
						0);
	file->vtracks[track].current_position += 1;
	file->vtracks[track].current_chunk++;
	return 0;
}

int quicktime_write_audio_init(quicktime_t *file, int track)
{
	return quicktime_write_frame_init(file, track);
}

int quicktime_write_audio_end(quicktime_t *file, int track, long samples)
{
	long bytes;
	file->file_position = ftell(file->stream);
	bytes = quicktime_position(file) - file->offset;
	quicktime_update_tables(file, 
						file->atracks[track].track,
						file->offset,
						file->atracks[track].current_chunk,
						file->atracks[track].current_position,
						samples,
						bytes, 
						0,
						0,
						0);
	file->atracks[track].current_position += samples;
	file->atracks[track].current_chunk++;
	return 0;
}


long quicktime_read_audio(quicktime_t *file, char *audio_buffer, long samples, int track)
{
	long chunk_sample, chunk;
	int result = 1, track_num;
	quicktime_trak_t *trak = file->atracks[track].track;
	long fragment_len, chunk_end;
	long position = file->atracks[track].current_position;
	long start = position, end = position + samples;
	long bytes, total_bytes = 0;
	long buffer_offset;

	quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, position);
	buffer_offset = 0;

	while(position < end && result)
	{
		quicktime_set_audio_position(file, position, track);
		fragment_len = quicktime_chunk_samples(trak, chunk);
		chunk_end = chunk_sample + fragment_len;
		fragment_len -= position - chunk_sample;
		if(position + fragment_len > chunk_end) fragment_len = chunk_end - position;
		if(position + fragment_len > end) fragment_len = end - position;

		bytes = quicktime_samples_to_bytes(trak, fragment_len);
		result = quicktime_read_data(file, &audio_buffer[buffer_offset], bytes);

		total_bytes += bytes;
		position += fragment_len;
		chunk_sample = position;
		buffer_offset += bytes;
		chunk++;
	}

	file->atracks[track].current_position = position;
	if(!result) return 0;
	return total_bytes;
}

int quicktime_read_chunk(quicktime_t *file, char *output, int track, long chunk, long byte_start, long byte_len)
{
	quicktime_set_position(file, quicktime_chunk_to_offset(file->atracks[track].track, chunk) + byte_start);
	if(quicktime_read_data(file, output, byte_len)) return 0;
	else
	return 1;
}

long quicktime_frame_size(quicktime_t *file, long frame, int track)
{
	int bytes;
	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
	{
		bytes = trak->mdia.minf.stbl.stsz.table[frame].size;
	}

	return bytes;
}

long quicktime_audio_frame_size(quicktime_t *file, long frame, int track)
{
	int bytes;
	quicktime_trak_t *trak = file->atracks[track].track;

	if(trak->mdia.minf.stbl.stsz.sample_size)
	{
		bytes = trak->mdia.minf.stbl.stsz.sample_size;
	}
	else
	{
		bytes = trak->mdia.minf.stbl.stsz.table[frame].size;
	}

	return bytes;
}

long quicktime_read_audio_frame(quicktime_t *file, unsigned char *audio_buffer,  int maxBytes, int track)
{
	long bytes;
	int result = 0;
	quicktime_trak_t *trak = file->atracks[track].track;

	bytes = quicktime_audio_frame_size(file, 
		file->atracks[track].current_position, track);

	if (bytes > maxBytes) {
		return -bytes;
	}

	quicktime_set_audio_position(file, 
		file->atracks[track].current_position, track);

	result = quicktime_read_data(file, audio_buffer, bytes);

	file->atracks[track].current_position++;

	if (!result)
		return 0;
	return bytes;
}

long quicktime_read_frame(quicktime_t *file, unsigned char *video_buffer, int track)
{
	long bytes;
	int result = 0;

	quicktime_trak_t *trak = file->vtracks[track].track;
	bytes = quicktime_frame_size(file, file->vtracks[track].current_position, track);

	if(!file->vtracks[track].frames_cached)
	{
		quicktime_set_video_position(file, file->vtracks[track].current_position, track);
		result = quicktime_read_data(file, video_buffer, bytes);
	}
	else
	{
		int i;
		unsigned char *cached_frame;

		if(file->vtracks[track].current_position >= file->vtracks[track].frames_cached) result = 1;
		if(!result)
		{
			cached_frame = file->vtracks[track].frame_cache[file->vtracks[track].current_position];

			for(i = 0; i < bytes; i++)
				video_buffer[i] = cached_frame[i];
		}
	}
	file->vtracks[track].current_position++;

	if(!result) return 0;
	return bytes;
}

int quicktime_read_frame_init(quicktime_t *file, int track)
{
	quicktime_trak_t *trak = file->vtracks[track].track;
	quicktime_set_video_position(file, file->vtracks[track].current_position, track);
	if(ftell(file->stream) != file->file_position) fseek(file->stream, file->file_position, SEEK_SET);
	return 0;
}

int quicktime_read_frame_end(quicktime_t *file, int track)
{
	file->file_position = ftell(file->stream);
	file->vtracks[track].current_position++;
	return 0;
}

int quicktime_init_video_map(quicktime_video_map_t *vtrack, quicktime_trak_t *trak)
{
	vtrack->track = trak;
	vtrack->current_position = 0;
	vtrack->current_chunk = 1;
	vtrack->frame_cache = 0;
	vtrack->frames_cached = 0;
	return 0;
}

int quicktime_delete_video_map(quicktime_video_map_t *vtrack)
{
	int i;
	if(vtrack->frames_cached)
	{
		for(i = 0; i < vtrack->frames_cached; i++)
		{
			free(vtrack->frame_cache[i]);
		}
		free(vtrack->frame_cache);
		vtrack->frames_cached = 0;
	}
	return 0;
}

int quicktime_init_audio_map(quicktime_audio_map_t *atrack, quicktime_trak_t *trak)
{
	atrack->track = trak;
	atrack->channels = trak->mdia.minf.stbl.stsd.table[0].channels;
	atrack->current_position = 0;
	atrack->current_chunk = 1;
	return 0;
}

int quicktime_delete_audio_map(quicktime_audio_map_t *atrack)
{
	int i;
	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;
}


int quicktime_dump(quicktime_t *file)
{
	printf("quicktime_dump\n");
	printf("movie data\n");
	printf(" size %ld\n", file->mdat.size);
	printf(" start %ld\n", file->mdat.start);
	quicktime_moov_dump(&(file->moov));
	return 0;
}


/* ================================== Entry points ========================== */

int quicktime_check_sig(const char *path)
{
	quicktime_t file;
	quicktime_atom_t leaf_atom;
	int result1 = 0, result2 = 0;

	quicktime_init(&file);
	if(!(file.stream = fopen(path, "rb"))) 
	{
		perror("quicktime_check_sig");
		return 0;
	}

	fseek(file.stream, 0, SEEK_END);
	file.total_length = ftell(file.stream);
	fseek(file.stream, 0, SEEK_SET);

	do
	{
		result1 = quicktime_atom_read_header(&file, &leaf_atom);

		if(!result1)
		{
/* just want the "moov" atom */
			if(quicktime_atom_is(&leaf_atom, "moov"))
			{
				result2 = 1;
			}
			else
				quicktime_atom_skip(&file, &leaf_atom);
		}
	}while(!result1 && !result2 && quicktime_position(&file) < file.total_length);

	fclose(file.stream);

	quicktime_delete(&file);
	return result2;
}

quicktime_t* quicktime_open(char *filename, int rd, int wr, int append)
{
	quicktime_t *new_file = malloc(sizeof(quicktime_t));
	char flags[10];
	int exists = 0;

	quicktime_init(new_file);
	new_file->wr = wr;
	new_file->rd = rd;
	new_file->mdat.start = 0;

	if (!strcmp(&filename[strlen(filename)-4], ".mp4")) {
		new_file->use_mp4 = TRUE;
	} else {
		new_file->use_mp4 = FALSE;
	}

	if(rd && (new_file->stream = fopen(filename, "rb")))
	{
		exists = 1; 
		fclose(new_file->stream); 
		new_file->stream = NULL;
	}


	if(rd && !wr) 
		sprintf(flags, "rb");
	else if(!rd && wr) 
		sprintf(flags, "wb");
	else if(rd && wr)
	{
		if(exists) 
			sprintf(flags, "rb+");
		else
			sprintf(flags, "wb+");
	}

	if(!(new_file->stream = fopen(filename, flags)))
	{
		perror("quicktime_open");
		free(new_file);
		return 0;
	}


	if(rd && exists)
	{
		fseek(new_file->stream, 0, SEEK_END);
		new_file->total_length = ftell(new_file->stream);

		fseek(new_file->stream, 0, SEEK_SET);

		if(quicktime_read_info(new_file))
		{
			quicktime_close(new_file);
			new_file = 0;
		}
	}

	if(wr) {
		if(!exists || !append) {
			/* start the data atom */
			quicktime_write_int32(new_file, 0);
			quicktime_write_char32(new_file, "mdat");
		} else {
			quicktime_set_position(new_file,
				 new_file->mdat.start + new_file->mdat.size);
			fseek(new_file->stream, 
				 new_file->mdat.start + new_file->mdat.size, SEEK_SET);
		}
	}
	return new_file;
}

int quicktime_write(quicktime_t *file)
{
	int result = -1;

	if(!file->wr) {
		return result;
	}

	quicktime_write_mdat(file, &(file->mdat));
	quicktime_write_moov(file, &(file->moov));

	result = fclose(file->stream);
	file->stream = NULL;
	return result;
}

int quicktime_destroy(quicktime_t *file)
{
	quicktime_delete(file);
	free(file);
	return 0;
}

int quicktime_close(quicktime_t *file)
{
	int result;
	if(file->wr)
	{
		quicktime_write_mdat(file, &(file->mdat));
		quicktime_write_moov(file, &(file->moov));
	}
	result = fclose(file->stream);

	quicktime_delete(file);
	free(file);
	return result;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -