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

📄 main.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
			}		}		/*move to current time in TS unit*/		stream->time = stream->program->pcr_init_ts_time;		m2ts_time_inc(&stream->time, (u32) (stream->pck.dts - stream->program->pcr_init_time), 90000);		/*compute bitrate if needed*/		if (!stream->bit_rate) {			if (!stream->last_br_time) {				stream->last_br_time = stream->pck.dts + 1;				stream->bytes_since_last_time = stream->pck.data_len;			} else {				if (stream->pck.dts - stream->last_br_time - 1 >= 90000) {					u64 r = 8*stream->bytes_since_last_time;					r*=90000;					stream->bit_rate = (u32) (r / (stream->pck.dts - stream->last_br_time - 1));					stream->program->mux->needs_reconfig = 1;				} else {					stream->bytes_since_last_time += stream->pck.data_len;				}			}		}	}	return 1;}#define PES_HEADER_LENGTH 19u32 m2ts_stream_add_pes_header(GF_BitStream *bs, M2TS_Mux_Stream *stream, 								Bool use_dts, u64 dts, 								Bool use_pts, u64 cts, 								u32 au_length){	u32 pes_len;	u32 pes_header_data_length;	pes_header_data_length = 10;	gf_bs_write_int(bs,	0x1, 24);//packet start code	gf_bs_write_u8(bs,	stream->mpeg2_stream_id);// stream id 	pes_len = au_length + 3; // 3 = header size	if (use_dts) pes_len += 5;	if (use_pts) pes_len += 5;	gf_bs_write_int(bs, pes_len, 16); // pes packet length		gf_bs_write_int(bs, 0x2, 2); // reserved	gf_bs_write_int(bs, 0x0, 2); // scrambling	gf_bs_write_int(bs, 0x0, 1); // priority	gf_bs_write_int(bs, 0x1, 1); // alignment indicator	gf_bs_write_int(bs, 0x0, 1); // copyright	gf_bs_write_int(bs, 0x0, 1); // original or copy		gf_bs_write_int(bs, use_pts, 1);	gf_bs_write_int(bs, use_dts, 1);	gf_bs_write_int(bs, 0x0, 6); //6 flags = 0 (ESCR, ES_rate, DSM_trick, additional_copy, PES_CRC, PES_extension)	gf_bs_write_int(bs, pes_header_data_length, 8);	if (use_pts) {		u64 t;		gf_bs_write_int(bs, use_dts ? 0x3 : 0x2, 4); // reserved '0011' || '0010'		t = ((cts >> 30) & 0x7);		gf_bs_write_long_int(bs, t, 3);		gf_bs_write_int(bs, 1, 1); // marker bit		t = ((cts >> 15) & 0x7fff);		gf_bs_write_long_int(bs, t, 15);		gf_bs_write_int(bs, 1, 1); // marker bit		t = cts & 0x7fff;		gf_bs_write_long_int(bs, t, 15);		gf_bs_write_int(bs, 1, 1); // marker bit	}	if (use_dts) {		u64 t;		gf_bs_write_int(bs, 0x1, 4); // reserved '0001'		t = ((dts >> 30) & 0x7);		gf_bs_write_long_int(bs, t, 3);		gf_bs_write_int(bs, 1, 1); // marker bit		t = ((dts >> 15) & 0x7fff);		gf_bs_write_long_int(bs, t, 15);		gf_bs_write_int(bs, 1, 1); // marker bit		t = dts & 0x7fff;		gf_bs_write_long_int(bs, t, 15);		gf_bs_write_int(bs, 1, 1); // marker bit	}	return pes_len+4; // 4 = start code + stream_id}void m2ts_mux_pes_get_next_packet(M2TS_Mux_Stream *stream, u8 *packet){	GF_BitStream *bs;	Bool au_start, is_rap, needs_pcr;	u32 remain, adaptation_field_control, payload_length, padding_length;	assert(stream->pid);	bs = gf_bs_new(packet, 188, GF_BITSTREAM_WRITE);	au_start = 0;	if (!stream->pck_offset && (stream->pck.flags & GF_ESI_DATA_AU_START) ) au_start = 1;	remain = stream->pck.data_len - stream->pck_offset;	adaptation_field_control = M2TS_ADAPTATION_NONE;	payload_length = 184 - PES_HEADER_LENGTH*au_start;	needs_pcr = (au_start && (stream==stream->program->pcr) ) ? 1 : 0;	padding_length = 0;	if (needs_pcr) {		adaptation_field_control = M2TS_ADAPTATION_AND_PAYLOAD;		/*AF headers + PCR*/		payload_length -= 8;	} else if (remain<184) {		/*AF headers*/		payload_length -= 2;		adaptation_field_control = M2TS_ADAPTATION_AND_PAYLOAD;	}	if (remain>=payload_length) {		padding_length = 0;	} else {		padding_length = payload_length - remain; 		payload_length -= padding_length;	}	gf_bs_write_int(bs,	0x47, 8); // sync byte	gf_bs_write_int(bs,	0, 1);    // error indicator	gf_bs_write_int(bs,	au_start, 1); // start ind	gf_bs_write_int(bs,	0, 1);	  // transport priority	gf_bs_write_int(bs,	stream->pid, 13); // pid	gf_bs_write_int(bs,	0, 2);    // scrambling	gf_bs_write_int(bs,	adaptation_field_control, 2);    // we do not use adaptation field for sections 	gf_bs_write_int(bs,	stream->continuity_counter, 4);   // continuity counter	if (stream->continuity_counter < 15) stream->continuity_counter++;	else stream->continuity_counter=0;	if (au_start && (stream->pck.flags & GF_ESI_DATA_AU_RAP) ) is_rap = 1;	else is_rap = 0;	if (adaptation_field_control != M2TS_ADAPTATION_NONE) {		/*FIXME - WE NEED A REAL PCR, NOT THE DTS*/		m2ts_add_adaptation(bs, needs_pcr, stream->pck.dts, is_rap, padding_length);	}	/*FIXME - we need proper packetization here in case we're not fed with full AUs*/	if (au_start) {		m2ts_stream_add_pes_header(bs, stream, 							(stream->ifce->caps & GF_ESI_SIGNAL_DTS) ? 1 : 0, stream->pck.dts,							1, stream->pck.cts, stream->pck.data_len);	}	gf_bs_del(bs);	memcpy(packet+188-payload_length, stream->pck.data + stream->pck_offset, payload_length);	stream->pck_offset += payload_length;	assert(stream->pck_offset <= stream->pck.data_len);	m2ts_time_inc(&stream->time, payload_length, stream->bit_rate);}M2TS_Mux_Stream *m2ts_stream_new(u32 pid) {	M2TS_Mux_Stream *stream;	GF_SAFEALLOC(stream, M2TS_Mux_Stream);	stream->pid = pid;	stream->process = m2ts_stream_process_stream;	return stream;}GF_Err m2ts_output_ctrl(GF_ESInterface *_self, u32 ctrl_type, void *param){	GF_ESIPacket *esi_pck;	M2TS_Packet *pck;	M2TS_Mux_Stream *stream = (M2TS_Mux_Stream *)_self->output_udta;	switch (ctrl_type) {	case GF_ESI_OUTPUT_DATA_DISPATCH:		GF_SAFEALLOC(pck, M2TS_Packet);		esi_pck = (GF_ESIPacket *)param;		pck->data_len = esi_pck->data_len;		pck->data = malloc(sizeof(char)*pck->data_len);		memcpy(pck->data, esi_pck->data, pck->data_len);		pck->flags = esi_pck->flags;		pck->cts = esi_pck->cts;		pck->dts = esi_pck->dts;		gf_mx_p(stream->mx);		if (!stream->pck_first) {			stream->pck_first = stream->pck_last = pck;		} else {			stream->pck_last->next = pck;			stream->pck_last = pck;		}		gf_mx_v(stream->mx);		break;	}	return GF_OK;}M2TS_Mux_Stream *m2ts_program_stream_add(M2TS_Mux_Program *program, struct __elementary_stream_ifce *ifce, u32 pid, Bool is_pcr){	M2TS_Mux_Stream *stream, *st;	stream = m2ts_stream_new(pid);	stream->ifce = ifce;	stream->pid = pid;	stream->program = program;	if (is_pcr) program->pcr = stream; 	if (program->streams) {		st = program->streams;		while (st->next) st = st->next;		st->next = stream;	} else {		program->streams = stream;	}	if (program->pmt) program->pmt->table_needs_update = 1;	stream->bit_rate = ifce->bit_rate;	switch (ifce->stream_type) {	case GF_STREAM_VISUAL:		switch (ifce->object_type_indication) {		case 0x20:			stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG4;			break;		case 0x21:			stream->mpeg2_stream_type = GF_M2TS_VIDEO_H264;			break;		case 0x6A:			stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG1;			break;		case 0x60:		case 0x61:		case 0x62:		case 0x63:		case 0x64:		case 0x65:			stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG2;			break;		default:			break;		}		/*just pick first valid stream_id in visual range*/		stream->mpeg2_stream_id = 0xE0;		break;	case GF_STREAM_AUDIO:		switch (ifce->object_type_indication) {		case 0x6B:			stream->mpeg2_stream_type = GF_M2TS_AUDIO_MPEG1;			break;		case 0x69:			stream->mpeg2_stream_type = GF_M2TS_AUDIO_MPEG2;			break;		case 0x40:			stream->mpeg2_stream_type = GF_M2TS_AUDIO_AAC;			break;		}		/*just pick first valid stream_id in audio range*/		stream->mpeg2_stream_id = 0xC0;		break;	}	stream->ifce->output_ctrl = m2ts_output_ctrl;	stream->ifce->output_udta = stream;	stream->mx = gf_mx_new();	if (ifce->timescale != 90000) stream->ts_scale = 90000.0 / ifce->timescale;	return stream;}#define M2TS_PSI_REFRESH_RATE	200M2TS_Mux_Program *m2ts_mux_program_add(M2TS_Mux *muxer, u32 program_number, u32 pmt_pid){	M2TS_Mux_Program *program;	GF_SAFEALLOC(program, M2TS_Mux_Program);	program->mux = muxer;	program->number = program_number;	if (muxer->programs) {		M2TS_Mux_Program *p = muxer->programs;		while (p->next) p = p->next;		p->next = program;	} else {		muxer->programs = program;	}	program->pmt = m2ts_stream_new(pmt_pid);	program->pmt->program = program;	muxer->pat->table_needs_update = 1;	program->pmt->process = m2ts_stream_process_pmt;	program->pmt->refresh_rate_ms = M2TS_PSI_REFRESH_RATE;	return program;}M2TS_Mux *m2ts_mux_new(u32 mux_rate, Bool real_time){	GF_BitStream *bs;	M2TS_Mux *muxer;	GF_SAFEALLOC(muxer, M2TS_Mux);	muxer->pat = m2ts_stream_new(0); /* 0 = PAT_PID */	muxer->pat->process = m2ts_stream_process_pat;	muxer->pat->refresh_rate_ms = M2TS_PSI_REFRESH_RATE;	muxer->real_time = real_time;	muxer->bit_rate = mux_rate;	if (mux_rate) muxer->fixed_rate = 1;	/*format NULL packet*/	bs = gf_bs_new(muxer->null_pck, 188, GF_BITSTREAM_WRITE);	gf_bs_write_int(bs,	0x47, 8);	gf_bs_write_int(bs,	0, 1);	gf_bs_write_int(bs,	0, 1);	gf_bs_write_int(bs,	0, 1);	gf_bs_write_int(bs,	0x1FFF, 13);	gf_bs_write_int(bs,	0, 2);	gf_bs_write_int(bs,	1, 2);	gf_bs_write_int(bs,	0, 4);	gf_bs_del(bs);	return muxer;}void m2ts_mux_stream_del(M2TS_Mux_Stream *st){	while (st->tables) {		M2TS_Mux_Table *tab = st->tables->next;		while (st->tables->section) {			M2TS_Mux_Section *sec = st->tables->section->next;			free(st->tables->section->data);			free(st->tables->section);			st->tables->section = sec;		}		free(st->tables);		st->tables = tab;	}	while (st->pck_first) {		M2TS_Packet *pck = st->pck_first;		st->pck_first = pck->next;		free(pck->data);		free(pck);	}	if (st->mx) gf_mx_del(st->mx);	free(st);}void m2ts_mux_program_del(M2TS_Mux_Program *prog){	while (prog->streams) {		M2TS_Mux_Stream *st = prog->streams->next;		m2ts_mux_stream_del(prog->streams);		prog->streams = st;	}	m2ts_mux_stream_del(prog->pmt);	free(prog);}void m2ts_mux_del(M2TS_Mux *mux){	while (mux->programs) {		M2TS_Mux_Program *p = mux->programs->next;		m2ts_mux_program_del(mux->programs);		mux->programs = p;	}	m2ts_mux_stream_del(mux->pat);	free(mux);}void m2ts_mux_update_config(M2TS_Mux *mux, Bool reset_time){	M2TS_Mux_Program *prog;	if (!mux->fixed_rate) {		mux->bit_rate = 0;		/*get PAT bitrate*/		m2ts_mux_table_update_bitrate(mux, mux->pat);		mux->bit_rate += mux->pat->bit_rate;	}	prog = mux->programs;	while (prog) {		M2TS_Mux_Stream *stream = prog->streams;		while (stream) {			/*!! WATCHOUT - this is raw bitrate without PES header overhead !!*/			if (!mux->fixed_rate) {				mux->bit_rate += stream->bit_rate;				/*update PCR every 100ms - we need at least 8 bytes without padding*/				if (stream == prog->pcr) mux->bit_rate += 8*8*10;			}			/*reset mux time*/			if (reset_time) stream->time.sec = stream->time.nanosec = 0;			stream = stream->next;		}		/*get PMT bitrate*/		if (!mux->fixed_rate) {			m2ts_mux_table_update_bitrate(mux, prog->pmt);			mux->bit_rate += prog->pmt->bit_rate;		}		prog = prog->next;	}	/*reset mux time*/	if (reset_time) {		mux->time.sec = mux->time.nanosec = 0;		mux->init_sys_time = 0;	}}u32 gf_m2ts_get_sys_clock(M2TS_Mux *muxer){	return gf_sys_clock() - muxer->init_sys_time;}u32 gf_m2ts_get_ts_clock(M2TS_Mux *muxer){	u32 now, init;	init = muxer->init_ts_time.sec*1000 + muxer->init_ts_time.nanosec/1000000;	now = muxer->time.sec*1000 + muxer->time.nanosec/1000000;	return now-init;}const char *m2ts_mux_process(M2TS_Mux *muxer, u32 *status){	M2TS_Mux_Program *program;	M2TS_Mux_Stream *stream, *stream_to_process;	M2TS_Time time;	u32 now, nb_streams, nb_streams_done;	char *ret;	Bool res;	nb_streams = nb_streams_done = 0;	*status = GF_M2TS_STATE_IDLE;	now = gf_sys_clock();	if (muxer->real_time) {		if (!muxer->init_sys_time) {			muxer->init_sys_time = now;			muxer->init_ts_time = muxer->time;		} else {			u32 diff = now - muxer->init_sys_time;			M2TS_Time now = muxer->init_ts_time;			m2ts_time_inc(&now, diff, 1000);			if (m2ts_time_less(&now, &muxer->time)) 				return NULL;		}	}	stream_to_process = NULL;	time = muxer->time;	if (muxer->needs_reconfig) {		m2ts_mux_update_config(muxer, 0);		muxer->needs_reconfig = 0;	}	res = muxer->pat->process(muxer, muxer->pat);	if (res && m2ts_time_less_or_equal(&muxer->pat->time, &time) ) {		time = muxer->pat->time;		stream_to_process = muxer->pat;		/*force sending the PAT regardless of other streams*/		goto send_pck;	}	program = muxer->programs;	while (program) {		res = program->pmt->process(muxer, program->pmt);		if (res && m2ts_time_less(&program->pmt->time, &time) ) {			time = program->pmt->time;			stream_to_process = program->pmt;			/*force sending the PMT regardless of other streams*/			goto send_pck;		}		stream = program->streams;		while (stream) {			nb_streams ++;			res = stream->process(muxer, stream);			if (res) {				if (m2ts_time_less(&stream->time, &time)) {					time = stream->time;					stream_to_process = stream;				}			} else {				if (stream->ifce->caps & GF_ESI_STREAM_IS_OVER) nb_streams_done ++;			}			stream = stream->next;		}		program = program->next;	}send_pck:	ret = NULL;	if (!stream_to_process) {		if (nb_streams && (nb_streams==nb_streams_done)) {			*status = GF_M2TS_STATE_EOS;		} else {			/* padding packets ?? */			if (muxer->fixed_rate) {				GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Inserting empty packet at %d:%d\n", time.sec, time.nanosec));				ret = muxer->null_pck;			}			/*we still need to increase the mux time, even though we're not fixed-rate*/			else {				m2ts_time_inc(&muxer->time, 1504/*188*8*/, muxer->bit_rate);			}			*status = GF_M2TS_STATE_PADDING;		}	} else {		if (stream_to_process->tables) {			m2ts_mux_table_get_next_packet(stream_to_process, muxer->dst_pck);			GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sending table packet from PID %d at %d:%d\n", stream_to_process->pid, time.sec, time.nanosec));		} else {			m2ts_mux_pes_get_next_packet(stream_to_process, muxer->dst_pck);			GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sending PES packet from PID %d at %d:%d\n", stream_to_process->pid, time.sec, time.nanosec));		}		ret = muxer->dst_pck;		*status = GF_M2TS_STATE_DATA;	}	if (ret) {		muxer->tot_pck_sent++;		/*increment time*/		m2ts_time_inc(&muxer->time, 1504/*188*8*/, muxer->bit_rate);		muxer->pck_sent++;		if (now - muxer->last_br_time > 500) {			u64 size = 8*188*muxer->pck_sent*1000;			muxer->avg_br = (u32) (size/(now - muxer->last_br_time));

⌨️ 快捷键说明

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