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

📄 mpegts_in.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
				/*FIXME: we assume only simple RTP packaging (no CSRC nor extensions)*/				if ((data[0] != 0x47) && ((data[1] & 0x7F) == 33) ) {					is_rtp = 1;					//fprintf(stdout, "MPEG-TS over RTP detected\n", size);				}			}			/*process chunk*/			if (is_rtp) {				gf_m2ts_process_data(m2ts->ts, data+12, size-12);			} else {				gf_m2ts_process_data(m2ts->ts, data, size);			}		}	} else {		u32 pos = 0;		if (m2ts->start_range && m2ts->duration) {			Double perc = m2ts->start_range / (1000 * m2ts->duration);			pos = (u32) (s64) (perc * m2ts->file_size);			/*align to TS packet size*/			while (pos%188) pos++;			if (pos>=m2ts->file_size) {				m2ts->start_range = 0;				pos = 0;			}		}		fseek(m2ts->file, pos, SEEK_SET);		while (m2ts->run_state && !feof(m2ts->file) ) {			/*m2ts chunks by chunks*/			size = fread(data, 1, 188, m2ts->file);			if (!size) break;			/*process chunk*/			gf_m2ts_process_data(m2ts->ts, data, size);					/*regulate file reading*/			M2TS_Regulate(m2ts);		}		fprintf(stdout, "\nEOS reached\n");		if (m2ts->nb_playing) {			for (i=0; i<GF_M2TS_MAX_STREAMS; i++) {				GF_M2TS_PES *pes = (GF_M2TS_PES *)m2ts->ts->ess[i];				if (!pes || (pes->pid==pes->program->pmt_pid)) continue;				if (!pes->user || !pes->reframe) continue;				gf_term_on_sl_packet(m2ts->service, pes->user, NULL, 0, NULL, GF_EOS);				gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_SKIP);			}		}	}	m2ts->run_state = 2;	return 0;}static void M2TS_OnEventPCR(GF_M2TS_Demuxer *ts, u32 evt_type, void *param){	if (evt_type==GF_M2TS_EVT_PES_PCR) {		M2TSIn *m2ts = ts->user;		GF_M2TS_PES_PCK *pck = param;		if (!m2ts->nb_playing) {			m2ts->nb_playing = pck->stream->pid;			m2ts->end_range = (u32) (pck->PTS / 90);		} else if (m2ts->nb_playing == pck->stream->pid) {			m2ts->start_range = (u32) (pck->PTS / 90);		}	}}#ifdef GPAC_HAS_LINUX_DVBvoid M2TS_SetupDVB(GF_InputService *plug, M2TSIn *m2ts, char *url){	GF_Err e = GF_OK;	char *str;	const char *chan_conf;	if (strnicmp(url, "dvb://", 6)) {		e = GF_NOT_SUPPORTED;		goto exit;	}	chan_conf = gf_modules_get_option((GF_BaseInterface *)plug, "DVB", "ChannelsFile");	if (!chan_conf) {		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[DVBIn] Cannot locate channel configuration file\n"));		e = GF_SERVICE_ERROR;		goto exit;	}		if (m2ts->tuner == NULL) { 		m2ts->tuner = malloc(sizeof(GF_Tuner));	}	e = gf_dvb_tune(m2ts->tuner, url, chan_conf);	if (e) goto exit;	m2ts->th = gf_th_new();	/*start playing for tune-in*/	gf_th_run(m2ts->th, M2TS_Run, m2ts);exit:	if (e) {		gf_term_on_connect(m2ts->service, NULL, e);	}}#endifvoid M2TS_SetupLive(M2TSIn *m2ts, char *url){	GF_Err e = GF_OK;	char *str;	u16 port;	u32 sock_type = 0;	if (!strnicmp(url, "udp://", 6) || !strnicmp(url, "mpegts-udp://", 13)) {		sock_type = GF_SOCK_TYPE_UDP;	} else if (!strnicmp(url, "mpegts-tcp://", 13) ) {		sock_type = GF_SOCK_TYPE_TCP;	} else {		e = GF_NOT_SUPPORTED;		goto exit;	}	url = strchr(url, ':');	url += 3;	m2ts->sock = gf_sk_new(sock_type);	if (!m2ts->sock) { e = GF_IO_ERR; goto exit; }	/*setup port and src*/	port = 1234;	str = strrchr(url, ':');	/*take care of IPv6 address*/	if (str && strchr(str, ']')) str = strchr(url, ':');	if (str) {		port = atoi(str+1);		str[0] = 0;	}	/*do we have a source ?*/	if (strlen(url) && strcmp(url, "localhost") ) {		if (gf_sk_is_multicast_address(url)) {			gf_sk_setup_multicast(m2ts->sock, url, port, 0, 0, NULL);		} else {			gf_sk_bind(m2ts->sock, port, url, 0, GF_SOCK_REUSE_PORT);		}	}	if (str) str[0] = ':';	gf_sk_set_buffer_size(m2ts->sock, 0, UDP_BUFFER_SIZE);	gf_sk_set_block_mode(m2ts->sock, 0);	m2ts->th = gf_th_new();	gf_th_set_priority(m2ts->th, GF_THREAD_PRIORITY_HIGHEST);	/*start playing for tune-in*/	gf_th_run(m2ts->th, M2TS_Run, m2ts);exit:	if (e) {		gf_term_on_connect(m2ts->service, NULL, e);	}}void M2TS_SetupFile(M2TSIn *m2ts, char *url){#if 0	char data[188];	u32 size, fsize;	s32 nb_rwd;#endif	m2ts->file = fopen(url, "rb");	if (!m2ts->file) {		gf_term_on_connect(m2ts->service, NULL, GF_URL_ERROR);	}	fseek(m2ts->file, 0, SEEK_END);	m2ts->file_size = ftell(m2ts->file);	#if 0	/* 		estimate duration by reading the end of the file		m2ts->end_range is initialized to the PTS of the last TS packet		m2ts->nb_playing is initialized to the PID of the last TS packet	*/	m2ts->nb_playing = 0;	m2ts->ts->on_event = M2TS_OnEventPCR;	m2ts->end_range = 0;	nb_rwd = 1;	fsize = m2ts->file_size;	while (fsize % 188) fsize--;	while (1) {		fseek(m2ts->file, fsize - 188 * nb_rwd, SEEK_SET);		/*m2ts chunks by chunks*/		size = fread(data, 1, 188, m2ts->file);		if (!size) break;		/*process chunk*/		gf_m2ts_process_data(m2ts->ts, data, size);		if (m2ts->nb_playing) break;		nb_rwd ++;	}	/* 	   reset of the file 	   initialization of m2ts->start_range to the PTS of the first TS packet with PID = m2ts->nb_playing 	*/	fseek(m2ts->file, 0, SEEK_SET);	gf_m2ts_reset_parsers(m2ts->ts);	m2ts->start_range = 0;	while (1) {		/*m2ts chunks by chunks*/		size = fread(data, 1, 188, m2ts->file);		if (!size) break;		/*process chunk*/		gf_m2ts_process_data(m2ts->ts, data, size);		if (m2ts->start_range) break;	}	m2ts->duration = (m2ts->end_range - m2ts->start_range) / 300000.0;	gf_m2ts_demux_del(m2ts->ts);	/* Creation of the real demuxer for playback */	m2ts->ts = gf_m2ts_demux_new();	m2ts->ts->user = m2ts;#endif	/* reinitialization for seek */	m2ts->end_range = m2ts->start_range = 0;	m2ts->nb_playing = 0;	m2ts->th = gf_th_new();	/*start playing for tune-in*/	gf_th_run(m2ts->th, M2TS_Run, m2ts);}static GF_Err M2TS_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url){	char szURL[2048];	char *ext;	M2TSIn *m2ts = plug->priv;	m2ts->service = serv;	if (m2ts->program) free(m2ts->program);	m2ts->program = NULL;	m2ts->prog_id = 0;	strcpy(szURL, url);	ext = strrchr(szURL, '#');	if (ext) {		m2ts->program = strdup(ext+1);		ext[0] = 0;	}	m2ts->do_regulate = 0;	m2ts->duration = 0;	if (!strnicmp(url, "udp://", 6)		|| !strnicmp(url, "mpegts-udp://", 13) 		|| !strnicmp(url, "mpegts-tcp://", 13) 		) {		M2TS_SetupLive(m2ts, (char *) szURL);	} #ifdef GPAC_HAS_LINUX_DVB	else if (!strnicmp(url, "dvb://", 6)) {		// DVB Setup		M2TS_SetupDVB(plug, m2ts, (char *) szURL);	} #endif	else {		M2TS_SetupFile(m2ts, (char *) szURL);	}	return GF_OK;}static GF_Err M2TS_CloseService(GF_InputService *plug){	M2TSIn *m2ts = plug->priv;	if (m2ts->th) {		if (m2ts->run_state == 1) {			m2ts->run_state = 0;			while (m2ts->run_state!=2) gf_sleep(0);		}		gf_th_del(m2ts->th);		m2ts->th = NULL;	}	if (m2ts->file) fclose(m2ts->file);	m2ts->file = NULL;	gf_term_on_disconnect(m2ts->service, NULL, GF_OK);	return GF_OK;}static GF_Descriptor *M2TS_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url){	u32 i=0;	M2TSIn *m2ts = plug->priv;	GF_Descriptor *desc;	if (gf_list_count(m2ts->ts->programs) == 1) {		GF_M2TS_Program *prog = gf_list_get(m2ts->ts->programs, 0);		if (prog->pmt_iod) {			m2ts->do_regulate = 1;			gf_odf_desc_copy((GF_Descriptor *)prog->pmt_iod, &desc);			return desc;		}	} 	/*returning an empty IOD means "no scene description", let the terminal handle all media objects*/	desc = gf_odf_desc_new(GF_ODF_IOD_TAG);	((GF_ObjectDescriptor *) desc)->objectDescriptorID = 1;	return desc;}static GF_Err M2TS_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream){	u32 ES_ID;	GF_Err e;	M2TSIn *m2ts = plug->priv;	e = GF_STREAM_NOT_FOUND;	if (strstr(url, "ES_ID")) {		sscanf(url, "ES_ID=%d", &ES_ID);				/* In case there is a real IOD, we need to translate PID into ESID */		if (gf_list_count(m2ts->ts->programs) == 1) {			GF_M2TS_Program *prog = gf_list_get(m2ts->ts->programs, 0);			if (prog->pmt_iod) {				u32 i;				for (i=0; i<GF_M2TS_MAX_STREAMS; i++) {					GF_M2TS_PES *pes = (GF_M2TS_PES *)m2ts->ts->ess[i];					if (!pes || (pes->pid==pes->program->pmt_pid)) continue;					if (pes->mpeg4_es_id == ES_ID) {						if (pes->user) {							e = GF_SERVICE_ERROR;							gf_term_on_connect(m2ts->service, channel, e);							return e;						} else {							pes->user = channel;							e = GF_OK;							gf_term_on_connect(m2ts->service, channel, e);							return e;						}					}				}			}		} 		if ((ES_ID<GF_M2TS_MAX_STREAMS) && m2ts->ts->ess[ES_ID]) {			GF_M2TS_PES *pes = (GF_M2TS_PES *)m2ts->ts->ess[ES_ID];			if (pes->user) e = GF_SERVICE_ERROR;			else {				pes->user = channel;				e = GF_OK;			}		}	}	gf_term_on_connect(m2ts->service, channel, e);	return e;}static GF_M2TS_PES *M2TS_GetChannel(M2TSIn *m2ts, LPNETCHANNEL channel){	u32 i;	for (i=0; i<GF_M2TS_MAX_STREAMS; i++) {		GF_M2TS_PES *pes = (GF_M2TS_PES *)m2ts->ts->ess[i];		if (!pes || (pes->pid==pes->program->pmt_pid)) continue;		if (pes->user == channel) return pes;	}	return NULL;}static GF_Err M2TS_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel){	M2TSIn *m2ts = plug->priv;	GF_Err e = GF_STREAM_NOT_FOUND;	GF_M2TS_PES *pes = M2TS_GetChannel(m2ts, channel);	if (pes) {		pes->user = NULL;		e = GF_OK;	}	gf_term_on_disconnect(m2ts->service, channel, e);	return GF_OK;}static GF_Err M2TS_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com){	GF_M2TS_PES *pes;	M2TSIn *m2ts = plug->priv;	if (!com->base.on_channel) return GF_NOT_SUPPORTED;	switch (com->command_type) {	/*we cannot pull complete AUs from the stream*/	case GF_NET_CHAN_SET_PULL:		return GF_NOT_SUPPORTED;	/*we cannot seek stream by stream*/	case GF_NET_CHAN_INTERACTIVE:		return GF_NOT_SUPPORTED;	case GF_NET_CHAN_BUFFER:		com->buffer.max = REGULATE_TIME_SLOT;		com->buffer.min = 0;		return GF_OK;	case GF_NET_CHAN_DURATION:		com->duration.duration = m2ts->duration;		return GF_OK;	case GF_NET_CHAN_PLAY:		pes = M2TS_GetChannel(m2ts, com->base.on_channel);		if (!pes) return GF_STREAM_NOT_FOUND;		gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);		/*this is a multplex, only trigger the play command for the first stream activated*/		if (!m2ts->nb_playing) {			m2ts->start_range = (u32) (com->play.start_range*1000);			m2ts->end_range = (com->play.end_range>0) ? (u32) (com->play.end_range*1000) : 0;			/*start demuxer*/			if (m2ts->run_state!=1) {				gf_th_run(m2ts->th, M2TS_Run, m2ts);			}		}		m2ts->nb_playing++;		return GF_OK;	case GF_NET_CHAN_STOP:		pes = M2TS_GetChannel(m2ts, com->base.on_channel);		if (!pes) return GF_STREAM_NOT_FOUND;		gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_SKIP);		/*FIXME HOORIBLE HACK*/		return GF_OK;		assert(m2ts->nb_playing);		m2ts->nb_playing--;		/*stop demuxer*/		if (!m2ts->nb_playing && (m2ts->run_state==1)) {			m2ts->run_state=0;			while (m2ts->run_state!=2) gf_sleep(2);		}		return GF_OK;	default:		return GF_OK;	}}GF_InputService *NewM2TSReader(){	M2TSIn *reader;	GF_InputService *plug = malloc(sizeof(GF_InputService));	memset(plug, 0, sizeof(GF_InputService));	GF_REGISTER_MODULE_INTERFACE(plug, GF_NET_CLIENT_INTERFACE, "GPAC MPEG-2 TS Reader", "gpac distribution")	plug->CanHandleURL = M2TS_CanHandleURL;	plug->ConnectService = M2TS_ConnectService;	plug->CloseService = M2TS_CloseService;	plug->GetServiceDescriptor = M2TS_GetServiceDesc;	plug->ConnectChannel = M2TS_ConnectChannel;	plug->DisconnectChannel = M2TS_DisconnectChannel;	plug->ServiceCommand = M2TS_ServiceCommand;	reader = malloc(sizeof(M2TSIn));	memset(reader, 0, sizeof(M2TSIn));	plug->priv = reader;	reader->ts = gf_m2ts_demux_new();	reader->ts->on_event = M2TS_OnEvent;	reader->ts->user = reader;	return plug;}void DeleteM2TSReader(void *ifce){	GF_InputService *plug = (GF_InputService *) ifce;	M2TSIn *m2ts = plug->priv;	gf_m2ts_demux_del(m2ts->ts);	free(m2ts);	free(plug);}Bool QueryInterface(u32 InterfaceType){	switch (InterfaceType) {	case GF_NET_CLIENT_INTERFACE: return 1;	default: return 0;	}}GF_BaseInterface *LoadInterface(u32 InterfaceType){	switch (InterfaceType) {	case GF_NET_CLIENT_INTERFACE: return (GF_BaseInterface *) NewM2TSReader();	default: return NULL;	}}void ShutdownInterface(GF_BaseInterface *ifce){	switch (ifce->InterfaceType) {	case GF_NET_CLIENT_INTERFACE:  DeleteM2TSReader(ifce); break;	}}

⌨️ 快捷键说明

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