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

📄 mpeg3demux.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 4 页
字号:
		current_timecode = -1;
		while(timecode = next_timecode(demuxer, 
		    &current_title, 
			&current_timecode, 
			current_program))
		{
			timecode->absolute_start_time = current_time;

/*
 * printf("mpeg3demux_assign_programs %p end: %f start: %f\n", 
 * 	timecode,
 * 	timecode->end_time,
 * 	timecode->start_time);
 */

			current_time += fabs(timecode->end_time - timecode->start_time);
			timecode->absolute_end_time = current_time;
		}
	}

//for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]);

	demuxer->current_program = 0;
	return 0;
}

int mpeg3demux_copy_titles(mpeg3_demuxer_t *dst, mpeg3_demuxer_t *src)
{
	long i;
	mpeg3_t *file = dst->file;
	mpeg3_title_t *dst_title, *src_title;

	dst->total_titles = src->total_titles;
	dst->total_programs = src->total_programs;
	for(i = 0; i < MPEG3_MAX_STREAMS; i++)
	{
		dst->astream_table[i] = src->astream_table[i];
		dst->vstream_table[i] = src->vstream_table[i];
	}
	for(i = 0; i < src->total_titles; i++)
	{
		src_title = src->titles[i];
		dst_title = dst->titles[i] = mpeg3_new_title(file, src->titles[i]->fs->path);
		mpeg3_copy_title(dst_title, src_title);
	}

	mpeg3demux_open_title(dst, src->current_title);
	dst->current_timecode = 0;
	return 0;
}

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

mpeg3_demuxer_t* mpeg3_new_demuxer(mpeg3_t *file, int do_audio, int do_video, int stream_id)
{
	mpeg3_demuxer_t *demuxer = calloc(1, sizeof(mpeg3_demuxer_t));
	int i;

/* The demuxer will change the default packet size for its own use. */
	demuxer->file = file;
	demuxer->do_audio = do_audio;
	demuxer->do_video = do_video;

/* Allocate buffer + padding */
	demuxer->raw_data = calloc(1, MPEG3_RAW_SIZE);
	demuxer->data_buffer = calloc(1, MPEG3_RAW_SIZE);
/* System specific variables */
	demuxer->audio_pid = stream_id;
	demuxer->video_pid = stream_id;
	demuxer->astream = stream_id;
	demuxer->vstream = stream_id;
	demuxer->current_title = -1;
//printf("mpeg3_new_demuxer %f\n", demuxer->time);
	return demuxer;
}

int mpeg3_delete_demuxer(mpeg3_demuxer_t *demuxer)
{
	int i;

	if(demuxer->current_title >= 0)
	{
		mpeg3io_close_file(demuxer->titles[demuxer->current_title]->fs);
	}

	for(i = 0; i < demuxer->total_titles; i++)
	{
		mpeg3_delete_title(demuxer->titles[i]);
	}

	free(demuxer->data_buffer);
	free(demuxer->raw_data);
	free(demuxer);
	return 0;
}

/* Need a timecode table to do this */
double mpeg3demux_length(mpeg3_demuxer_t *demuxer)
{
	mpeg3_title_t *title;
	int i, j;
	double length;
	
	for(i = demuxer->total_titles - 1; i >= 0; i--)
	{
		title = demuxer->titles[i];
		for(j = title->timecode_table_size - 1; j >= 0; j--)
		{
			if(title->timecode_table[j].program == demuxer->current_program)
			{
/*
 * printf("mpeg3demux_length %f %f %f %f\n", 
 * 	title->timecode_table[j].end_time, 
 * 	title->timecode_table[j].start_time,
 * 	title->timecode_table[j].absolute_start_time,
 * 	title->timecode_table[j].end_time - title->timecode_table[j].start_time);
 */
				return title->timecode_table[j].end_time - 
					title->timecode_table[j].start_time + 
					title->timecode_table[j].absolute_start_time;
			}
		}
	}

	return 1;
}

int mpeg3demux_eof(mpeg3_demuxer_t *demuxer)
{
	if(demuxer->current_title >= 0)
	{
		if(mpeg3io_eof(demuxer->titles[demuxer->current_title]->fs) &&
			demuxer->current_title >= demuxer->total_titles - 1)
			return 1;
	}

	return 0;
}

int mpeg3demux_bof(mpeg3_demuxer_t *demuxer)
{
	if(demuxer->current_title >= 0)
	{
		if(mpeg3io_bof(demuxer->titles[demuxer->current_title]->fs) &&
			demuxer->current_title <= 0)
			return 1;
	}
	return 0;
}

void mpeg3demux_start_reverse(mpeg3_demuxer_t *demuxer)
{
	demuxer->reverse = 1;
}

void mpeg3demux_start_forward(mpeg3_demuxer_t *demuxer)
{
	demuxer->reverse = 0;
}

/* Seek to a byte in the current title */
int mpeg3demux_seek_byte(mpeg3_demuxer_t *demuxer, int64_t byte)
{
	long current_position;
	mpeg3_t *file = demuxer->file;
	mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
	
	demuxer->data_position = 0;
	demuxer->data_size = 0;

	demuxer->error_flag = mpeg3io_seek(title->fs, byte);

	if(!demuxer->error_flag && 
		file->is_transport_stream &&
		file->packet_size)
	{
/* Get on a packet boundary only for transport streams. */
		current_position = mpeg3io_tell(title->fs);
		if(byte % file->packet_size)
		{
			demuxer->error_flag |= mpeg3io_seek(title->fs, 
				current_position - 
				(current_position % file->packet_size));
		}
	}


// Get current cell
	for(demuxer->current_timecode = 0; 
		demuxer->current_timecode < title->timecode_table_size; 
		demuxer->current_timecode++)
	{
		if(title->timecode_table[demuxer->current_timecode].start_byte <= byte &&
			title->timecode_table[demuxer->current_timecode].end_byte > byte)
		{
			break;
		}
	}

	if(demuxer->current_timecode >= title->timecode_table_size)
		demuxer->current_timecode = title->timecode_table_size - 1;
	
	
	return demuxer->error_flag;
}

int mpeg3demux_seek_end(mpeg3_demuxer_t *demuxer)
{
	mpeg3demux_open_title(demuxer, demuxer->total_titles - 1);
	demuxer->current_timecode = 0;
	return mpeg3demux_seek_byte(demuxer, demuxer->titles[demuxer->current_title]->total_bytes);
}

int mpeg3demux_seek_start(mpeg3_demuxer_t *demuxer)
{
	mpeg3demux_open_title(demuxer, 0);
	demuxer->current_timecode = 0;
	return mpeg3demux_seek_byte(demuxer, 0);
}

/* For programs streams and toc seek to a time */
int mpeg3demux_seek_time(mpeg3_demuxer_t *demuxer, double new_time)
{
	int i, j, done = 0, result = 0;
	int64_t byte_offset, new_byte_offset;
	double guess = 0, minimum = 65535;
	mpeg3_title_t *title;
	mpeg3demux_timecode_t *timecode;

	demuxer->error_flag = 0;

	i = 0;
	j = 0;
	title = demuxer->titles[i];
	timecode = &title->timecode_table[j];


/* Get the title and timecode of the new position */
	while(!demuxer->error_flag &&
		!(timecode->absolute_start_time <= new_time &&
		timecode->absolute_end_time > new_time &&
		timecode->program == demuxer->current_program))
	{
/* Next timecode */
		j++;
		if(j >= title->timecode_table_size)
		{
			i++;
			j = 0;
			if(i >= demuxer->total_titles)
			{
				demuxer->error_flag = 1;
				return 1;
			}
		}

		title = demuxer->titles[i];
		timecode = &title->timecode_table[j];
	}

//printf("mpeg3demux_seek_time 1 %d %f %f %f\n", i, timecode->absolute_start_time, timecode->absolute_end_time, new_time);
	if(demuxer->current_title != i)
    	mpeg3demux_open_title(demuxer, i);








/* Guess the new byte position by interpolating */
	demuxer->current_timecode = j;

	byte_offset = ((new_time - timecode->absolute_start_time) /
		(timecode->absolute_end_time - timecode->absolute_start_time) *
		(timecode->end_byte - timecode->start_byte) +
		timecode->start_byte);
//printf("mpeg3demux_seek_time %f %f\n", new_time, byte_offset);










/* Binary search */
	while(!done && !result && byte_offset >= 0)
	{
		result = mpeg3demux_seek_byte(demuxer, (long)byte_offset);
//printf("seek_time 0 byte %.0f want %f result %d\n", byte_offset, new_time, result); 

		if(!result)
		{
			result = mpeg3_read_next_packet(demuxer);
// printf("seek_time 1 guess %f want %f\n", guess, new_time); 
			guess = demuxer->time + demuxer->time_offset;

			if(fabs(new_time - guess) >= fabs(minimum)) done = 1;
			else
			{
				minimum = guess - new_time;
				new_byte_offset = byte_offset + ((new_time - guess) / 
					(timecode->end_time - timecode->start_time) *
					(timecode->end_byte - timecode->start_byte));
				if(fabs(new_byte_offset - byte_offset) < 1) done = 1;
				byte_offset = new_byte_offset;
			}
		}
	}






//printf("mpeg3demux_seek_time 1\n");


/* Get one packet before the packet just read */
	if(!result && byte_offset > 0 && minimum > 0)
	{
		mpeg3_read_prev_packet(demuxer);
//printf("mpeg3demux_seek_time 2\n");
		mpeg3_read_prev_packet(demuxer);
	}

//printf("mpeg3demux_seek_time 3\n");


//printf("mpeg3demux_seek_time 2 %d %d %d\n", demuxer->current_title, demuxer->current_timecode, mpeg3demux_tell(demuxer));
	demuxer->error_flag = result;
	return result;
}













int mpeg3demux_seek_percentage(mpeg3_demuxer_t *demuxer, double percentage)
{
	double total_bytes = 0;
	double absolute_position;
	long relative_position;
	int i, new_title;
	mpeg3_title_t *title;

	demuxer->error_flag = 0;

/* Get the absolute byte position; */
	for(i = 0; i < demuxer->total_titles; i++)
		total_bytes += demuxer->titles[i]->total_bytes;

	absolute_position = percentage * total_bytes;







/* Get the title the byte is inside */
	for(new_title = 0, total_bytes = 0; new_title < demuxer->total_titles; new_title++)
	{
		total_bytes += demuxer->titles[new_title]->total_bytes;
		if(absolute_position < total_bytes) break;
	}

	if(new_title >= demuxer->total_titles)
	{
		new_title = demuxer->total_titles - 1;
	}







/* Got a title */
	title = demuxer->titles[new_title];
	total_bytes -= title->total_bytes;
	relative_position = (long)(absolute_position - total_bytes);








/* Get the timecode the byte is inside */
	for(demuxer->current_timecode = 0; 
		demuxer->current_timecode < title->timecode_table_size; 
		demuxer->current_timecode++)
	{
		if(title->timecode_table[demuxer->current_timecode].start_byte <= relative_position &&
			title->timecode_table[demuxer->current_timecode].end_byte > relative_position)
		{
			break;
		}
	}

	if(demuxer->current_timecode >= title->timecode_table_size)
		demuxer->current_timecode = title->timecode_table_size - 1;







/* Get the nearest timecode in the same program */
	while(demuxer->current_timecode < title->timecode_table_size - 1 &&
			title->timecode_table[demuxer->current_timecode].program != demuxer->current_program)
	{
		demuxer->current_timecode++;
	}

/*
 * printf("seek percentage 1 %d %d %d %d\n", demuxer->current_title, 
 * 	demuxer->current_timecode,
 * 	title->timecode_table[demuxer->current_timecode].start_byte,
 * 	title->timecode_table[demuxer->current_timecode].end_byte);
 */

/* Open the new title and seek to the correct byte */
	if(new_title != demuxer->current_title)
	{
		demuxer->error_flag = mpeg3demux_open_title(demuxer, new_title);
	}

/*
 * printf("seek percentage 2 %d %d %d %d\n", demuxer->current_title, 
 * 	demuxer->current_timecode,
 * 	title->timecode_table[demuxer->current_timecode].start_byte,
 * 	title->timecode_table[demuxer->current_timecode].end_byte);
 */

	if(!demuxer->error_flag)
		demuxer->error_flag = mpeg3io_seek(title->fs, relative_position);

	return demuxer->error_flag;
}


// Lots of optimization errors
double mpeg3demux_tell_percentage(mpeg3_demuxer_t *demuxer)
{
	double total_bytes = 0;
	double position = 0;
	int i;

	demuxer->error_flag = 0;
	position = mpeg3io_tell_gcc(demuxer->titles[demuxer->current_title]->fs);


	for(i = 0; i < demuxer->total_titles; i++)
	{
		double new_bytes = mpeg3_total_bytes_gcc(demuxer->titles[i]);
		if(i == demuxer->current_title)
		{
			position = mpeg3_add_double_gcc(total_bytes, position);
		}
		total_bytes = mpeg3_add_double_gcc(total_bytes, new_bytes);
	}

	return position / total_bytes;
}

double mpeg3demux_get_time(mpeg3_demuxer_t *demuxer)
{
	return demuxer->time;
}

int64_t mpeg3demux_tell(mpeg3_demuxer_t *demuxer)
{
	return mpeg3io_tell(demuxer->titles[demuxer->current_title]->fs);
}

int mpeg3demux_tell_title(mpeg3_demuxer_t *demuxer)
{
	return demuxer->current_title;
}

int64_t mpeg3demuxer_total_bytes(mpeg3_demuxer_t *demuxer)
{
	mpeg3_title_t *title = demuxer->titles[demuxer->current_title];
	return title->total_bytes;
}

mpeg3_demuxer_t* mpeg3_get_demuxer(mpeg3_t *file)
{
	if(file->is_program_stream || file->is_transport_stream)
	{
		if(file->total_astreams) return file->atrack[0]->demuxer;
		else
		if(file->total_vstreams) return file->vtrack[0]->demuxer;
	}
	return 0;
}

⌨️ 快捷键说明

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