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

📄 transport_stream.c

📁 由bmp生成mpeg2 的I_frame 数据
💻 C
📖 第 1 页 / 共 2 页
字号:

static void count_file_size(TRANSPORT_STREAM *ts)
{
	__int64 set;
	__int64 end;

	end = ts->mf->seek(ts->mf, 0, SEEK_END);
	set = ts->mf->seek(ts->mf, 0, SEEK_SET);

	ts->file_length = end-set;
}

static int fill_buffer(TRANSPORT_STREAM *ts)
{
	ts->buffer_size = ts->mf->read(ts->mf, ts->buffer, ts->buffer_max);
	ts->current = ts->buffer;
	return ts->buffer_size;
}

static unsigned char *read_unit(TRANSPORT_STREAM *ts)
{
	if( (ts->current-ts->buffer) >= ts->buffer_size ){
		return NULL;
	}
	
	return ts->current + ts->offset;
}

static void go_next_unit(TRANSPORT_STREAM *ts)
{
	ts->current += ts->unit_size;

	if( (ts->current-ts->buffer) >= ts->buffer_size ){
		fill_buffer(ts);
	}
}

static void go_prev_unit(TRANSPORT_STREAM *ts)
{
	ts->current -= ts->unit_size;
	ts_seek_raw(ts, 0, SEEK_CUR);
}

static __int64 ts_seek_raw(TRANSPORT_STREAM *ts, __int64 offset, int origin)
{
	__int64 set,end;
	__int64 newpos;
	
	end = ts->mf->tell(ts->mf);
	set = end - ts->buffer_size;

	switch(origin){
	case SEEK_SET:
		newpos = offset;
		break;
	case SEEK_CUR:
		newpos = set + (ts->current - ts->buffer) + offset;
		break;
	case SEEK_END:
		newpos = ts->file_length + offset;
		break;
	default:
		newpos = offset;
		break;
	}

	if(newpos < 0){
		newpos = 0;
	}else if(newpos > ts->file_length){
		newpos = ts->file_length;
	}

	if( (newpos < set) || (end <= newpos) ){
		set = newpos / ts->buffer_max * ts->buffer_max;
		ts->mf->seek(ts->mf, set, SEEK_SET);
		fill_buffer(ts);
	}

	ts->current = ts->buffer + newpos - set;

	return newpos;
}

static __int64 ts_tell_raw(TRANSPORT_STREAM *ts)
{
	__int64 set;

	set = ts->mf->tell(ts->mf) - ts->buffer_size;

	return set + (ts->current - ts->buffer);
}

static int select_stream(TRANSPORT_STREAM *ts)
{
	int r;
	int i,n;

	__int64 limit;
	
	unsigned char *p,*data;
	TS_HEADER header;
	PES_PACKET *packets[8192];
	unsigned char pid_type[8192];
	PES_STREAM_TYPE type;
	
	r = 0;

	memset(packets, 0, sizeof(packets));
	memset(pid_type, 0, sizeof(pid_type));
	
	limit = get_filecheck_limit();

	/* search Program Association Table */
	while( (p = read_unit(ts)) != NULL ){
		extract_ts_header(p, &header);
		if(header.pid == 0x0000){
			data = p+4;
			if(header.adaptation_field_control & 2){
				data += data[0] + 1;
			}
			extract_program_association_table(data, pid_type);
			if(pid_type[0] == TS_STREAM_TYPE_PAT){
				break;
			}
		}
		go_next_unit(ts);
		if(ts_tell_raw(ts) > limit){
			break;
		}
	}

	if(pid_type[0] != TS_STREAM_TYPE_PAT){
		ts_seek((int)ts, 0, SEEK_SET);
		goto SELECT_STREAM_FINAL;
	}

	/* search Program Map Table */
	while( (p = read_unit(ts)) != NULL ){
		extract_ts_header(p, &header);
		if(pid_type[header.pid] == TS_STREAM_TYPE_PMT){
			data = p+4;
			if(header.adaptation_field_control & 2){
				data += data[0] + 1;
			}
			ts->pid = extract_program_map_table(data, pid_type, ts->type.type);
			if(ts->pid != 0){
				return 1;
			}
		}
		go_next_unit(ts);
		if(ts_tell_raw(ts) > limit){
			break;
		}
	}
	ts_seek((int)ts, 0, SEEK_SET);

	/* no Program Map Table */
SELECT_STREAM_FINAL:
	while( (p = read_unit(ts)) != NULL ){
		extract_ts_header(p, &header);
		if( (header.pid < 0x10) || (header.pid == 0x1fff) ){
		}else if(header.adaptation_field_control & 1){
			if(packets[header.pid] == NULL){
				packets[header.pid] = (PES_PACKET *)malloc(sizeof(PES_PACKET));
				init_pes_packet(packets[header.pid]);
			}
			data = p+4;
			if(header.adaptation_field_control & 2){
				data += data[0] + 1;
			}
			n = 188 - (data-p);
			append_pes_packet_data(packets[header.pid], data, n);
			extract_pes_stream_type(packets[header.pid], &type);
			if(type.type == ts->type.type){
				ts->type.id = type.id;
				ts->pid = header.pid;
				r = 1;
				//break;
			}else if(type.type != PES_STREAM_TYPE_UNKNOWN){
				release_pes_packet(packets[header.pid]);
			}
		}
		go_next_unit(ts);
		if(ts_tell_raw(ts) > limit){
			break;
		}
	}

	for(i=0;i<8192;i++){
		if(packets[i]){
			release_pes_packet(packets[i]);
			free(packets[i]);
		}
	}

	return r;
}

static void extract_ts_header(unsigned char *buffer, TS_HEADER *header)
{
	header->sync = buffer[0] & 0xff;
	header->transport_error_indicator = (buffer[1] >> 7) & 1;
	header->payload_unit_start_indicator = (buffer[1] >> 6) & 1;
	header->transport_priority = (buffer[1] >> 5) & 1;
	header->pid = (((buffer[1] & 0x1f)) << 8) + (buffer[2] & 0xff);
	header->transport_scrambling_control = (buffer[3] >> 6) & 3;
	header->adaptation_field_control = (buffer[3] >> 4) & 3;
	header->continuity_counter = (buffer[3] & 0xf);
	if(header->pid == 0x101){
		header->sync = 0x47;
	}
}

static int read_pes_packet(TRANSPORT_STREAM *ts, PES_PACKET *out)
{
	TS_HEADER header;
	unsigned char *p,*data;
	int n;
	int start_indicator;

	start_indicator = 0;

	release_pes_packet(out);
	
	while( (p = read_unit(ts)) != NULL ){
		extract_ts_header(p, &header);
		if(header.pid != ts->pid){
			go_next_unit(ts);
			continue;
		}
		if(header.payload_unit_start_indicator && (start_indicator == 0)){
			ts->pos = ts_tell_raw(ts);
			start_indicator = 1;
		}
		if(start_indicator && (header.adaptation_field_control & 1)){
			data = p+4;
			if(header.adaptation_field_control & 2){
				data += data[0] + 1;
			}
			n = 188 - (data-p);
			if(append_pes_packet_data(out, data, n) < n){
				return 1;
			}
		}
		go_next_unit(ts);
	}

	return 0;
}

static void reserve_data_buffer(TRANSPORT_STREAM *ts, int size)
{
	if(ts->data_buffer != NULL){
		free(ts->data_buffer);
	}

	ts->data_buffer = (unsigned char *)malloc(size);
}

static void extract_program_association_table(unsigned char *buffer, unsigned char *pid_type)
{
	unsigned char *p;

	int section_length;
	int transport_stream_id;
	int version_number;
	int current_next_indicator;
	int section_number;
	int last_section_number;
	int program_number;
	int id;
	
	p = buffer;
	p += p[0] + 1; /* pointer_field */
	if(p[0] != 0x00){ /* not Program Association table_id */
		return;
	}
	section_length = ((p[1] & 0xf) << 8) + p[2];
	transport_stream_id = (p[3] << 8) + p[4];
	version_number = (p[5] & 0x3e) >> 1;
	current_next_indicator = p[5] & 1;
	section_number = p[6];
	last_section_number = p[7];

	p += 8;
	section_length -= 5;

	while(section_length > 4){
		program_number = (p[0] << 8) + p[1];
		id = ((p[2] & 0x1f) << 8) + p[3];
		if(program_number == 0){
			pid_type[id] = TS_STREAM_TYPE_NIT;
		}else{
			pid_type[id] = TS_STREAM_TYPE_PMT;
		}
		p += 4;
		section_length -= 4;
	}

	pid_type[0] = TS_STREAM_TYPE_PAT;
}

static int extract_program_map_table(unsigned char *buffer, unsigned char *pid_type, int type)
{
	unsigned char *p;

	int r;

	int section_length;
	int program_number;
	int version_number;
	int current_next_indicator;
	int section_number;
	int last_section_number;
	int PCR_PID;
	int program_info_length;

	int stream_type;
	int elementary_PID;
	int es_info_length;

	r = 0;
	
	p = buffer;
	p += p[0] + 1; /* pointer_field */
	if(p[0] != 0x02){ /* not Program Association table_id */
		return r;
	}
	section_length = ((p[1] & 0xf) << 8) + p[2];
	program_number = (p[3] << 8) + p[4];
	version_number = (p[5] & 0x3e) >> 1;
	current_next_indicator = p[5] & 1;
	section_number = p[6];
	last_section_number = p[7];
	PCR_PID = ((p[8] & 0x1f) << 8) + p[9];
	program_info_length = ((p[10] & 0xf) << 8) + p[11];
	
	p += 12 + program_info_length;
	section_length -= 9 + program_info_length;

	while(section_length > 4){
		stream_type = p[0];
		elementary_PID = ((p[1] & 0x1f) << 8) + p[2];
		es_info_length = ((p[3] & 0x0f) << 8) + p[4];
		switch(stream_type){
		case 0x01:
			pid_type[elementary_PID] = TS_STREAM_TYPE_V11172_2;
			if( (type == PES_STREAM_TYPE_VIDEO) && (r == 0) ){
				r = elementary_PID;
			}
			break;
		case 0x02:
			pid_type[elementary_PID] = TS_STREAM_TYPE_V13818_2;
			if( (type == PES_STREAM_TYPE_VIDEO) && (r == 0) ){
				r = elementary_PID;
			}
			break;
		case 0x03:
			pid_type[elementary_PID] = TS_STREAM_TYPE_A11172_3;
			break;
		case 0x04:
			pid_type[elementary_PID] = TS_STREAM_TYPE_A13818_3;
			break;
		case 0x0f:
			pid_type[elementary_PID] = TS_STREAM_TYPE_A13818_7;
			break;
		case 0x10:
			pid_type[elementary_PID] = TS_STREAM_TYPE_V14496_2;
			break;
		}			
		p += 5 + es_info_length;
		section_length -= es_info_length;
	}

	return r;
}


⌨️ 快捷键说明

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