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

📄 mpegts_in.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Authors: Jean le Feuvre *				Copyright (c) 2005-200X ENST *					All rights reserved * *  This file is part of GPAC / M2TS reader module * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *		 */#include <gpac/modules/service.h>#include <gpac/modules/codec.h>#include <gpac/mpegts.h>#include <gpac/thread.h>#include <gpac/network.h>#include <gpac/constants.h>#ifdef GPAC_HAS_LINUX_DVB#include <fcntl.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <linux/dvb/dmx.h>#include <linux/dvb/frontend.h>// DVB devices definition// TODO: using adapter0/..0 by default; multi-frontend to be done#define DMX   "/dev/dvb/adapter0/demux0"#define FRONT "/dev/dvb/adapter0/frontend0"#define DVR   "/dev/dvb/adapter0/dvr0"typedef struct {	u32 freq;	u16 vpid;	u16 apid;     fe_spectral_inversion_t specInv;    fe_modulation_t modulation;    fe_bandwidth_t bandwidth;    fe_transmit_mode_t TransmissionMode;    fe_guard_interval_t guardInterval;    fe_code_rate_t HP_CodeRate;    fe_code_rate_t LP_CodeRate;    fe_hierarchy_t hierarchy;        int ts_fd;} GF_Tuner;#define DVB_BUFFER_SIZE 3760							// DVB buffer size 188x20#endif#define UDP_BUFFER_SIZE	0x40000typedef struct{	GF_ClientService *service;	Bool do_regulate;	GF_M2TS_Demuxer *ts;	char *program;	u32 prog_id;	/*demuxer thread*/	GF_Thread *th;	u32 run_state;	/*net playing*/	GF_Socket *sock;	#ifdef GPAC_HAS_LINUX_DVB	/*dvb playing*/	GF_Tuner *tuner;#endif		/*local file playing*/	FILE *file;	u32 start_range, end_range;	u32 file_size;	Double duration;	u32 nb_playing;} M2TSIn;#ifdef GPAC_HAS_LINUX_DVBstatic GF_Err gf_dvb_tune(GF_Tuner *tuner, char *url, const char *chan_path) {	struct dmx_pes_filter_params pesFilterParams;    struct dvb_frontend_parameters frp;    int demux1, front1;    FILE *chanfile;    char line[255], chan_name_t[255];	char freq_str[255], inv[255], bw[255], lcr[255], hier[255], cr[255], mod[255], transm[255], gi[255], apid_str[255], vpid_str[255];    const char *chan_conf = ":%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:";    char *chan_name;	    if((chanfile=fopen(chan_path, "r"))==NULL) {		return GF_BAD_PARAM;	}	chan_name=url+6;	while(!feof(chanfile)) {		if ( fgets(line, 255, chanfile) != NULL) {			if (line[0]=='#') continue;			if (line[0]=='\r') continue;			if (line[0]=='\n') continue;			strncpy(chan_name_t, line, index(line, ':')-line); 			if (strncmp(chan_name,chan_name_t,strlen(chan_name))==0) {				sscanf(strstr(line,":"), chan_conf, freq_str, inv, bw, lcr, cr, mod, transm, gi, hier, apid_str, vpid_str);				tuner->freq = (uint32_t) atoi(freq_str);				tuner->apid = (uint16_t) atoi(apid_str);				tuner->vpid = (uint16_t) atoi(vpid_str);				//Inversion				if(! strcmp(inv, "INVERSION_ON")) tuner->specInv = INVERSION_ON;				else if(! strcmp(inv, "INVERSION_OFF")) tuner->specInv = INVERSION_OFF;				else tuner->specInv = INVERSION_AUTO;				//LP Code Rate				if(! strcmp(lcr, "FEC_1_2")) tuner->LP_CodeRate =FEC_1_2;				else if(! strcmp(lcr, "FEC_2_3")) tuner->LP_CodeRate =FEC_2_3;				else if(! strcmp(lcr, "FEC_3_4")) tuner->LP_CodeRate =FEC_3_4;				else if(! strcmp(lcr, "FEC_4_5")) tuner->LP_CodeRate =FEC_4_5;				else if(! strcmp(lcr, "FEC_6_7")) tuner->LP_CodeRate =FEC_6_7;				else if(! strcmp(lcr, "FEC_8_9")) tuner->LP_CodeRate =FEC_8_9;				else if(! strcmp(lcr, "FEC_5_6")) tuner->LP_CodeRate =FEC_5_6;				else if(! strcmp(lcr, "FEC_7_8")) tuner->LP_CodeRate =FEC_7_8;				else if(! strcmp(lcr, "FEC_NONE")) tuner->LP_CodeRate =FEC_NONE;				else tuner->LP_CodeRate =FEC_AUTO;				//HP Code Rate				if(! strcmp(cr, "FEC_1_2")) tuner->HP_CodeRate =FEC_1_2;				else if(! strcmp(cr, "FEC_2_3")) tuner->HP_CodeRate =FEC_2_3;				else if(! strcmp(cr, "FEC_3_4")) tuner->HP_CodeRate =FEC_3_4;				else if(! strcmp(cr, "FEC_4_5")) tuner->HP_CodeRate =FEC_4_5;				else if(! strcmp(cr, "FEC_6_7")) tuner->HP_CodeRate =FEC_6_7;				else if(! strcmp(cr, "FEC_8_9")) tuner->HP_CodeRate =FEC_8_9;				else if(! strcmp(cr, "FEC_5_6")) tuner->HP_CodeRate =FEC_5_6;				else if(! strcmp(cr, "FEC_7_8")) tuner->HP_CodeRate =FEC_7_8;				else if(! strcmp(cr, "FEC_NONE")) tuner->HP_CodeRate =FEC_NONE;				else tuner->HP_CodeRate =FEC_AUTO;				//Modulation							if(! strcmp(mod, "QAM_128")) tuner->modulation = QAM_128;				else if(! strcmp(mod, "QAM_256")) tuner->modulation = QAM_256;				else if(! strcmp(mod, "QAM_64")) tuner->modulation = QAM_64;				else if(! strcmp(mod, "QAM_32")) tuner->modulation = QAM_32;				else if(! strcmp(mod, "QAM_16")) tuner->modulation = QAM_16;				//Bandwidth								if(! strcmp(bw, "BANDWIDTH_6_MHZ")) tuner->bandwidth = BANDWIDTH_6_MHZ;				else if(! strcmp(bw, "BANDWIDTH_7_MHZ")) tuner->bandwidth = BANDWIDTH_7_MHZ;				else if(! strcmp(bw, "BANDWIDTH_8_MHZ")) tuner->bandwidth = BANDWIDTH_8_MHZ;				//Transmission Mode				if(! strcmp(transm, "TRANSMISSION_MODE_2K")) tuner->TransmissionMode = TRANSMISSION_MODE_2K;				else if(! strcmp(transm, "TRANSMISSION_MODE_8K")) tuner->TransmissionMode = TRANSMISSION_MODE_8K;				//Guard Interval				if(! strcmp(gi, "GUARD_INTERVAL_1_32")) tuner->guardInterval = GUARD_INTERVAL_1_32;				else if(! strcmp(gi, "GUARD_INTERVAL_1_16")) tuner->guardInterval = GUARD_INTERVAL_1_16;				else if(! strcmp(gi, "GUARD_INTERVAL_1_8")) tuner->guardInterval = GUARD_INTERVAL_1_8;				else tuner->guardInterval = GUARD_INTERVAL_1_4;				//Hierarchy							if(! strcmp(hier, "HIERARCHY_1")) tuner->hierarchy = HIERARCHY_1;				else if(! strcmp(hier, "HIERARCHY_2")) tuner->hierarchy = HIERARCHY_2;				else if(! strcmp(hier, "HIERARCHY_4")) tuner->hierarchy = HIERARCHY_4;								else if(! strcmp(hier, "HIERARCHY_AUTO")) tuner->hierarchy = HIERARCHY_AUTO;				else tuner->hierarchy = HIERARCHY_NONE;								break;			}		}	}    fclose(chanfile);            // Open frontend    if((front1 = open(FRONT,O_RDWR)) < 0){    	return GF_IO_ERR;    }    // Open demuxes    if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) < 0){        return GF_IO_ERR;    }	// Set FrontendParameters - DVB-T    frp.frequency = tuner->freq;	frp.inversion = tuner->specInv;	frp.u.ofdm.bandwidth = tuner->bandwidth;	frp.u.ofdm.code_rate_HP = tuner->HP_CodeRate;	frp.u.ofdm.code_rate_LP = tuner->LP_CodeRate;	frp.u.ofdm.constellation = tuner->modulation;	frp.u.ofdm.transmission_mode = tuner->TransmissionMode;	frp.u.ofdm.guard_interval = tuner->guardInterval;	frp.u.ofdm.hierarchy_information = tuner->hierarchy;    // Set frontend    if (ioctl(front1, FE_SET_FRONTEND, &frp) < 0){   		return GF_IO_ERR;	}	// Set dumex	pesFilterParams.pid      = 0x2000;				// Linux-DVB API take PID=2000 for FULL/RAW TS flag	pesFilterParams.input    = DMX_IN_FRONTEND;	pesFilterParams.output   = DMX_OUT_TS_TAP;	pesFilterParams.pes_type = DMX_PES_OTHER;	pesFilterParams.flags    = DMX_IMMEDIATE_START;	if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){  		return GF_IO_ERR;	}	if ((tuner->ts_fd = open(DVR, O_RDONLY/*|O_NONBLOCK*/)) < 0){	        return GF_IO_ERR;  	}		return GF_OK;}#endifstatic Bool M2TS_CanHandleURL(GF_InputService *plug, const char *url){	char *sExt;		if (!strnicmp(url, "udp://", 6) 		|| !strnicmp(url, "mpegts-udp://", 13) 		|| !strnicmp(url, "mpegts-tcp://", 13) #ifdef GPAC_HAS_LINUX_DVB		|| !strnicmp(url, "dvb://", 6) #endif	) {		return 1;	}		sExt = strrchr(url, '.');	if (!sExt) return 0;	if (gf_term_check_extension(plug, "video/mpeg-2", "ts m2t", "MPEG-2 TS", sExt)) return 1;	return 0;}#define REGULATE_TIME_SLOT	200/*!! FIXME - THIS IS PLAIN WRONG AND UGLY - WE NEED TO ESTIMATE THE TS BITRATE AND REGULATE BASED ON THAT !!!*/static void M2TS_Regulate(M2TSIn *m2ts){	u32 to_sleep;	GF_NetworkCommand com;	com.command_type = GF_NET_BUFFER_QUERY;	/*sleep untill the buffer occupancy is too low - note that this work because all streams in this	demuxer are synchronized*/	while (m2ts->run_state) {		/*wait for a connected channel !!*/		if (!m2ts->nb_playing && m2ts->do_regulate) {			gf_sleep(50);		} else {			gf_term_on_command(m2ts->service, &com, GF_OK);			if (com.buffer.occupancy < REGULATE_TIME_SLOT) {				//gf_sleep(1);				return;			}			to_sleep = com.buffer.occupancy  - REGULATE_TIME_SLOT;			//fprintf(stdout, "MPEG-2 TS regulate: %d ms in buffers - sleeping %d ms\n", com.buffer.occupancy, to_sleep);			while (m2ts->run_state && (to_sleep>REGULATE_TIME_SLOT)) {				gf_sleep(REGULATE_TIME_SLOT);				to_sleep -= REGULATE_TIME_SLOT;			}		}	}}static void MP2TS_DeclareStream(M2TSIn *m2ts, GF_M2TS_PES *stream){	GF_ObjectDescriptor *od;	GF_ESD *esd;	/*create a stream description for this channel*/	esd = gf_odf_desc_esd_new(0);	esd->ESID = stream->pid;	/*ASSIGN PCR here*/	esd->OCRESID = stream->program->pcr_pid;	switch (stream->stream_type) {	case GF_M2TS_VIDEO_MPEG1:		esd->decoderConfig->streamType = GF_STREAM_VISUAL;		esd->decoderConfig->objectTypeIndication = 0x6A;		break;	case GF_M2TS_VIDEO_MPEG2:		esd->decoderConfig->streamType = GF_STREAM_VISUAL;		esd->decoderConfig->objectTypeIndication = 0x65;		break;	case GF_M2TS_VIDEO_MPEG4:		esd->decoderConfig->streamType = GF_STREAM_VISUAL;		esd->decoderConfig->objectTypeIndication = 0x20;		break;	case GF_M2TS_VIDEO_H264:		esd->decoderConfig->streamType = GF_STREAM_VISUAL;		esd->decoderConfig->objectTypeIndication = 0x21;		break;	case GF_M2TS_AUDIO_MPEG1:		esd->decoderConfig->streamType = GF_STREAM_AUDIO;		esd->decoderConfig->objectTypeIndication = 0x6B;		break;	case GF_M2TS_AUDIO_MPEG2:		esd->decoderConfig->streamType = GF_STREAM_AUDIO;		esd->decoderConfig->objectTypeIndication = 0x69;		break;	case GF_M2TS_AUDIO_AAC:		esd->decoderConfig->streamType = GF_STREAM_AUDIO;		esd->decoderConfig->objectTypeIndication = 0x40;		break;	default:		gf_odf_desc_del((GF_Descriptor *)esd);		return;	}	esd->decoderConfig->bufferSizeDB = 0;	/*we only use AUstart indicator*/	esd->slConfig->useAccessUnitStartFlag = 1;	esd->slConfig->useAccessUnitEndFlag = 0;	esd->slConfig->useRandomAccessPointFlag = 1;	esd->slConfig->AUSeqNumLength = 0;	esd->slConfig->timestampResolution = 90000;		/*decoder config*/	if (0) {		esd->decoderConfig->decoderSpecificInfo->dataLength = 0;	}	/*declare object to terminal*/	od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG);	gf_list_add(od->ESDescriptors, esd);	od->objectDescriptorID = stream->pid;		/*declare but don't regenerate scene*/	gf_term_add_media(m2ts->service, (GF_Descriptor*)od, 1);	m2ts->do_regulate = 1;	/*wait for connection*/	while (!stream->user) gf_sleep(0);}static void MP2TS_SetupProgram(M2TSIn *m2ts, GF_M2TS_Program *prog){	u32 i, count;	count = gf_list_count(prog->streams);#ifdef GPAC_HAS_LINUX_DVB	if (m2ts->tuner) {		Bool found = 0;		for (i=0; i<count; i++) {			GF_M2TS_PES *pes = gf_list_get(prog->streams, i);			if (pes->pid==m2ts->tuner->vpid) found = 1;			else if (pes->pid==m2ts->tuner->apid) found = 1;		}		if (!found) return;	}#endif		for (i=0; i<count; i++) {		GF_M2TS_PES *pes = gf_list_get(prog->streams, i);		if (pes->pid==prog->pmt_pid) continue;		gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_SKIP);		MP2TS_DeclareStream(m2ts, pes);	}	/*force scene regeneration*/	gf_term_add_media(m2ts->service, NULL, 0);}static void MP2TS_SendPacket(M2TSIn *m2ts, GF_M2TS_PES_PCK *pck){	GF_SLHeader slh;	if (!pck->stream->user) return;	if (!pck->stream->program->first_dts && pck->PTS) {		pck->stream->program->first_dts = (pck->DTS ? pck->DTS : pck->PTS) - m2ts->start_range * 90;	}	memset(&slh, 0, sizeof(GF_SLHeader));	slh.accessUnitStartFlag = (pck->flags & GF_M2TS_PES_PCK_AU_START) ? 1 : 0;	if (slh.accessUnitStartFlag) {		if (pck->PTS < pck->stream->program->first_dts) return;		slh.compositionTimeStampFlag = 1;		slh.compositionTimeStamp = pck->PTS - pck->stream->program->first_dts;		if (pck->DTS) {			slh.decodingTimeStampFlag = 1;			slh.decodingTimeStamp = pck->DTS - pck->stream->program->first_dts;		}		slh.randomAccessPointFlag = (pck->flags & GF_M2TS_PES_PCK_RAP) ? 1 : 0;	}	gf_term_on_sl_packet(m2ts->service, pck->stream->user, pck->data, pck->data_len, &slh, GF_OK);}static GFINLINE void MP2TS_SendSLPacket(M2TSIn *m2ts, GF_M2TS_SL_PCK *pck){	gf_term_on_sl_packet(m2ts->service, pck->stream->user, pck->data, pck->data_len, NULL, GF_OK);}static void M2TS_OnEvent(GF_M2TS_Demuxer *ts, u32 evt_type, void *param){	M2TSIn *m2ts = (M2TSIn *) ts->user;	switch (evt_type) {	case GF_M2TS_EVT_PAT_FOUND:		/* In case the TS has one program, wait for the PMT to send connect, in case of IOD in PMT */		if (gf_list_count(m2ts->ts->programs) != 1)			gf_term_on_connect(m2ts->service, NULL, GF_OK);		break;	case GF_M2TS_EVT_PMT_FOUND:		if (gf_list_count(m2ts->ts->programs) == 1)			gf_term_on_connect(m2ts->service, NULL, GF_OK);				/*do not setup if we've been asked for a dedicated program*/		if (!m2ts->program) MP2TS_SetupProgram(m2ts, param);		break;	case GF_M2TS_EVT_PAT_UPDATE:	case GF_M2TS_EVT_PMT_UPDATE:	case GF_M2TS_EVT_SDT_UPDATE:		break;	case GF_M2TS_EVT_SDT_FOUND:		if (m2ts->program) {			u32 i, count, prog_id;			prog_id = atoi(m2ts->program);			count = gf_list_count(ts->SDTs);			for (i=0; i<count; i++) {				GF_M2TS_SDT *sdt = gf_list_get(ts->SDTs, i);				if (!stricmp(sdt->service, m2ts->program)) m2ts->prog_id = sdt->service_id;				else if (sdt->service_id==prog_id)  m2ts->prog_id = sdt->service_id;			}			if (m2ts->prog_id) {				GF_M2TS_Program *prog;				free(m2ts->program);				m2ts->program = NULL;				count = gf_list_count(ts->programs);				for (i=0; i<count; i++) {					prog = gf_list_get(ts->programs, i);					if (prog->number==m2ts->prog_id) {						MP2TS_SetupProgram(m2ts, prog);						break;					}				}			}		}		break;	case GF_M2TS_EVT_PES_PCK:		MP2TS_SendPacket(m2ts, param);		break;	case GF_M2TS_EVT_SL_PCK:		MP2TS_SendSLPacket(m2ts, param);		break;	}}u32 M2TS_Run(void *_p){	GF_Err e;	char data[UDP_BUFFER_SIZE];#ifdef GPAC_HAS_LINUX_DVB	char dvbts[DVB_BUFFER_SIZE];#endif	u32 size, i;	M2TSIn *m2ts = _p;	m2ts->run_state = 1;	m2ts->ts->on_event = M2TS_OnEvent;	gf_m2ts_reset_parsers(m2ts->ts);#ifdef GPAC_HAS_LINUX_DVB	if (m2ts->tuner) {		// in case of DVB		while (m2ts->run_state) {			s32 ts_size = read(m2ts->tuner->ts_fd, dvbts, DVB_BUFFER_SIZE);			if (ts_size>0) gf_m2ts_process_data(m2ts->ts, dvbts, (u32) ts_size);		}		} else#endif	 if (m2ts->sock) {		Bool first_run, is_rtp;		first_run = 1;		is_rtp = 0;		while (m2ts->run_state) {			size = 0;			/*m2ts chunks by chunks*/			e = gf_sk_receive(m2ts->sock, data, UDP_BUFFER_SIZE, 0, &size);			if (!size || e) {				gf_sleep(1);				continue;			}			if (first_run) {				first_run = 0;

⌨️ 快捷键说明

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