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

📄 demux_ts.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 5 页
字号:
	idx = progid_idx_in_pmt(priv, progid);	if(idx == -1)	{		int sz = (priv->pmt_cnt + 1) * sizeof(pmt_t);		tmp = (pmt_t *) realloc(priv->pmt, sz);		if(tmp == NULL)		{			mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT: COULDN'T REALLOC %d bytes, NEXT\n", sz);			return 0;		}		priv->pmt = tmp;		idx = priv->pmt_cnt;		memset(&(priv->pmt[idx]), 0, sizeof(pmt_t));		priv->pmt_cnt++;	}	pmt = &(priv->pmt[idx]);	section = &(pmt->section);	skip = collect_section(section, is_start, buff, size);	if(! skip)		return 0;			base = &(section->buffer[skip]);	pmt->progid = progid;	mp_msg(MSGT_DEMUX, MSGL_V, "FILL_PMT(prog=%d), PMT_len: %d, IS_START: %d, TS_PID: %d, SIZE=%d, M=%d, ES_CNT=%d, IDX=%d, PMT_PTR=%p\n",		progid, pmt->section.buffer_len, is_start, pid, size, m, pmt->es_cnt, idx, pmt);	pmt->table_id = base[0];	if(pmt->table_id != 2)		return -1;	pmt->ssi = base[1] & 0x80;	pmt->section_length = (((base[1] & 0xf) << 8 ) | base[2]);	pmt->version_number = (base[5] >> 1) & 0x1f;	pmt->curr_next = (base[5] & 1);	pmt->section_number = base[6];	pmt->last_section_number = base[7];	pmt->PCR_PID = ((base[8] & 0x1f) << 8 ) | base[9];	pmt->prog_descr_length = ((base[10] & 0xf) << 8 ) | base[11];	if(pmt->prog_descr_length > pmt->section_length - 9)	{		mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, INVALID PROG_DESCR LENGTH (%d vs %d)\n", pmt->prog_descr_length, pmt->section_length - 9);		return -1;	}	if(pmt->prog_descr_length)		parse_program_descriptors(pmt, &base[12], pmt->prog_descr_length);	es_base = &base[12 + pmt->prog_descr_length];	//the beginning of th ES loop	section_bytes= pmt->section_length - 13 - pmt->prog_descr_length;	es_count  = 0;	while(section_bytes >= 5)	{		int es_pid, es_type;		es_type = es_base[0];		es_pid = ((es_base[1] & 0x1f) << 8) | es_base[2];		idx = es_pid_in_pmt(pmt, es_pid);		if(idx == -1)		{			int sz = sizeof(struct pmt_es_t) * (pmt->es_cnt + 1);			tmp_es = (struct pmt_es_t *) realloc(pmt->es, sz);			if(tmp_es == NULL)			{				mp_msg(MSGT_DEMUX, MSGL_ERR, "PARSE_PMT, COULDN'T ALLOCATE %d bytes for PMT_ES\n", sz);				continue;			}			pmt->es = tmp_es;			idx = pmt->es_cnt;			memset(&(pmt->es[idx]), 0, sizeof(struct pmt_es_t));			pmt->es_cnt++;		}		pmt->es[idx].descr_length = ((es_base[3] & 0xf) << 8) | es_base[4];		if(pmt->es[idx].descr_length > section_bytes - 5)		{			mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT, ES_DESCR_LENGTH TOO LARGE %d > %d, EXIT\n",				pmt->es[idx].descr_length, section_bytes - 5);			return -1;		}		pmt->es[idx].pid = es_pid;		if(es_type != 0x6)			pmt->es[idx].type = UNKNOWN;		else			pmt->es[idx].type = es_type;				parse_descriptors(&pmt->es[idx], &es_base[5]);		switch(es_type)		{			case 1:				pmt->es[idx].type = VIDEO_MPEG1;				break;			case 2:				pmt->es[idx].type = VIDEO_MPEG2;				break;			case 3:			case 4:				pmt->es[idx].type = AUDIO_MP2;				break;			case 6:				if(pmt->es[idx].type == 0x6)	//this could have been ovrwritten by parse_descriptors					pmt->es[idx].type = UNKNOWN;				break;			case 0x10:				pmt->es[idx].type = VIDEO_MPEG4;				break;			case 0x0f:			case 0x11:				pmt->es[idx].type = AUDIO_AAC;				break;			case 0x1b:				pmt->es[idx].type = VIDEO_H264;				break;			case 0x12:				pmt->es[idx].type = SL_PES_STREAM;				break;			case 0x13:				pmt->es[idx].type = SL_SECTION;				break;			case 0x81:				pmt->es[idx].type = AUDIO_A52;				break;			default:				mp_msg(MSGT_DEMUX, MSGL_DBG2, "UNKNOWN ES TYPE=0x%x\n", es_type);				pmt->es[idx].type = UNKNOWN;		}				tss = priv->ts.pids[es_pid];			//an ES stream		if(tss == NULL)		{			tss = new_pid(priv, es_pid);			if(tss)				tss->type = pmt->es[idx].type;		}		section_bytes -= 5 + pmt->es[idx].descr_length;		mp_msg(MSGT_DEMUX, MSGL_V, "PARSE_PMT(%d INDEX %d), STREAM: %d, FOUND pid=0x%x (%d), type=0x%x, ES_DESCR_LENGTH: %d, bytes left: %d\n",			progid, idx, es_count, pmt->es[idx].pid, pmt->es[idx].pid, pmt->es[idx].type, pmt->es[idx].descr_length, section_bytes);		es_base += 5 + pmt->es[idx].descr_length;		es_count++;	}	mp_msg(MSGT_DEMUX, MSGL_V, "----------------------------\n");	return 1;}static pmt_t* pmt_of_pid(ts_priv_t *priv, int pid, mp4_decoder_config_t **mp4_dec){	int32_t i, j, k;	if(priv->pmt)	{		for(i = 0; i < priv->pmt_cnt; i++)		{			if(priv->pmt[i].es && priv->pmt[i].es_cnt)			{				for(j = 0; j < priv->pmt[i].es_cnt; j++)				{					if(priv->pmt[i].es[j].pid == pid)					{						//search mp4_es_id						if(priv->pmt[i].es[j].mp4_es_id)						{							for(k = 0; k < priv->pmt[i].mp4es_cnt; k++)							{								if(priv->pmt[i].mp4es[k].id == priv->pmt[i].es[j].mp4_es_id)								{									*mp4_dec = &(priv->pmt[i].mp4es[k].decoder);									break;								}							}						}												return &(priv->pmt[i]);					}				}			}			}	}		return NULL;}static inline int32_t pid_type_from_pmt(ts_priv_t *priv, int pid){	int32_t pmt_idx, pid_idx, i, j;	pmt_idx = progid_idx_in_pmt(priv, priv->prog);	if(pmt_idx != -1)	{		pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid);		if(pid_idx != -1)			return priv->pmt[pmt_idx].es[pid_idx].type;	}	//else	//{		for(i = 0; i < priv->pmt_cnt; i++)		{			pmt_t *pmt = &(priv->pmt[i]);			for(j = 0; j < pmt->es_cnt; j++)				if(pmt->es[j].pid == pid)					return pmt->es[j].type;		}	//}	return UNKNOWN;}static inline uint8_t *pid_lang_from_pmt(ts_priv_t *priv, int pid){	int32_t pmt_idx, pid_idx, i, j;	pmt_idx = progid_idx_in_pmt(priv, priv->prog);	if(pmt_idx != -1)	{		pid_idx = es_pid_in_pmt(&(priv->pmt[pmt_idx]), pid);		if(pid_idx != -1)			return priv->pmt[pmt_idx].es[pid_idx].lang;	}	else	{		for(i = 0; i < priv->pmt_cnt; i++)		{			pmt_t *pmt = &(priv->pmt[i]);			for(j = 0; j < pmt->es_cnt; j++)				if(pmt->es[j].pid == pid)					return pmt->es[j].lang;		}	}	return NULL;}static int fill_packet(demuxer_t *demuxer, demux_stream_t *ds, demux_packet_t **dp, int *dp_offset){	int ret = 0;	if((*dp != NULL) && (*dp_offset > 0))	{			ret = *dp_offset;			resize_demux_packet(*dp, ret);	//shrinked to the right size			ds_add_packet(ds, *dp);			mp_msg(MSGT_DEMUX, MSGL_DBG2, "ADDED %d  bytes to %s fifo, PTS=%.3f\n", ret, (ds == demuxer->audio ? "audio" : (ds == demuxer->video ? "video" : "sub")), (*dp)->pts);	}	*dp = NULL;	*dp_offset = 0;	return ret;}static int fill_extradata(mp4_decoder_config_t * mp4_dec, ES_stream_t *tss){	uint8_t *tmp;		mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4_dec: %p, pid: %d\n", mp4_dec, tss->pid);			if(mp4_dec->buf_size > tss->extradata_alloc)	{		tmp = (uint8_t *) realloc(tss->extradata, mp4_dec->buf_size);		if(!tmp)			return 0;		tss->extradata = tmp;		tss->extradata_alloc = mp4_dec->buf_size;	}	memcpy(tss->extradata, mp4_dec->buf, mp4_dec->buf_size);	tss->extradata_len = mp4_dec->buf_size;	mp_msg(MSGT_DEMUX, MSGL_V, "EXTRADATA: %p, alloc=%d, len=%d\n", tss->extradata, tss->extradata_alloc, tss->extradata_len);		return tss->extradata_len;}// 0 = EOF or no stream found// else = [-] number of bytes written to the packetstatic int ts_parse(demuxer_t *demuxer , ES_stream_t *es, unsigned char *packet, int probe){	ES_stream_t *tss;	uint8_t done = 0;	int buf_size, is_start, pid, base;	int len, cc, cc_ok, afc, retv = 0, is_video, is_audio, is_sub;	ts_priv_t * priv = (ts_priv_t*) demuxer->priv;	stream_t *stream = demuxer->stream;	char *p;	demux_stream_t *ds = NULL;	demux_packet_t **dp = NULL;	int *dp_offset = 0, *buffer_size = 0;	int32_t progid, pid_type, bad, ts_error;	int junk = 0, rap_flag = 0;	pmt_t *pmt;	mp4_decoder_config_t *mp4_dec;	while(! done)	{		bad = ts_error = 0;		ds = (demux_stream_t*) NULL;		dp = (demux_packet_t **) NULL;		dp_offset = buffer_size = NULL;		rap_flag = 0;		mp4_dec = NULL;		es->is_synced = 0;		junk = priv->ts.packet_size - TS_PACKET_SIZE;		buf_size = priv->ts.packet_size - junk;		if(stream_eof(stream))		{			if(! probe)			{				ts_dump_streams(priv);				demuxer->filepos = stream_tell(demuxer->stream);			}			return 0;		}		if(! ts_sync(stream))		{			mp_msg(MSGT_DEMUX, MSGL_INFO, "TS_PARSE: COULDN'T SYNC\n");			return 0;		}		len = stream_read(stream, &packet[1], 3);		if (len != 3)			return 0;		if((packet[1]  >> 7) & 0x01)	//transport error			ts_error = 1;		buf_size -= 4;		is_start = packet[1] & 0x40;		pid = ((packet[1] & 0x1f) << 8) | packet[2];		tss = priv->ts.pids[pid];			//an ES stream		if(tss == NULL)		{			tss = new_pid(priv, pid);			if(tss == NULL)				continue;		}		if(((pid > 1) && (pid < 16)) || (pid == 8191))		//invalid pid		{			stream_skip(stream, buf_size-1+junk);			continue;		}		cc = (packet[3] & 0xf);		cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));		tss->last_cc = cc;		    		bad = ts_error; // || (! cc_ok);    		afc = (packet[3] >> 4) & 3;		if(afc > 1)		{			int c;			c = stream_read_char(stream);			buf_size--;			rap_flag = (stream_read_char(stream) & 0x40) >> 6;			buf_size--;			c = min(c-1, buf_size);			stream_skip(stream, c);			buf_size -= c;			if(buf_size == 0)				continue;		}				if(! (afc % 2))	//no payload in this TS packet		{			stream_skip(stream, buf_size-1+junk);			continue;		}				if(bad)		{			// logically this packet should be dropped, but if I do it			// certain streams play corrupted. Maybe the decoders know			// how to deal with it, but at least I consider the packet			// as "not initial"			mp_msg(MSGT_DEMUX, MSGL_V, "ts_parse: PID=%d, Transport error: %d, CC_OK: %s\n\n", tss->pid, ts_error, (cc_ok ? "yes" : "no"));			if(priv->keep_broken == 0)			{				stream_skip(stream, buf_size-1+junk);				continue;			}						is_start = 0;	//queued to the packet data		}		//find the program that the pid belongs to; if (it's the right one or -1) && pid_type==SL_SECTION		//call parse_sl_section()		pmt = pmt_of_pid(priv, pid, &mp4_dec);		if(mp4_dec)		{			fill_extradata(mp4_dec, tss);			if(IS_VIDEO(mp4_dec->object_type) || IS_AUDIO(mp4_dec->object_type))			{				tss->type = SL_PES_STREAM;				tss->subtype = mp4_dec->object_type;			}		}						//TABLE PARSING		base = priv->ts.packet_size - buf_size;		if(pid  == 0)		{			stream_read(stream,&packet[base], buf_size);			stream_skip(stream, junk);			parse_pat(priv, is_start, &packet[base], buf_size);			continue;		}		else if((tss->type == SL_SECTION) && pmt)		{			int k, ok=0, mp4_es_id = -1;			ts_section_t *section;			for(k = 0; k < pmt->mp4es_cnt; k++)			{				if(pmt->mp4es[k].decoder.object_type == MP4_OD && pmt->mp4es[k].decoder.stream_type == MP4_OD)					mp4_es_id = pmt->mp4es[k].id;			}			mp_msg(MSGT_DEMUX, MSGL_DBG2, "MP4ESID: %d\n", mp4_es_id);			for(k = 0; k < pmt->es_cnt; k++)			{				if(pmt->es[k].mp4_es_id == mp4_es_id)					ok = 1;			}			stream_read(stream,&packet[base], buf_size);			stream_skip(stream, junk);			if(ok)			{				section = &(tss->section);				parse_sl_section(pmt, section, progid, pid, is_start, &packet[base], buf_size);			}			continue;		}		else		{			progid = prog_id_in_pat(priv, pid);			if(progid != -1)			{				if(pid != demuxer->video->id && pid != demuxer->audio->id && pid != demuxer->sub->id)				{					stream_read(stream,&packet[base], buf_size);					stream_skip(stream, junk);					parse_pmt(priv, progid, pid, is_start, &packet[base], buf_size);					continue;				}				else					mp_msg(MSGT_DEMUX, MSGL_ERR, "Argh! Data pid %d used in the PMT, Skipping PMT parsing!\n", pid);			}		}		priv->last_pid = pid;		is_video = IS_VIDEO(tss->type) || (tss->type==SL_PES_STREAM && IS_VIDEO(tss->subtype));		is_audio = IS_AUDIO(tss->type) || (tss->type==SL_PES_STREAM && IS_AUDIO(tss->subtype)) || (tss->type == PES_PRIVATE1);		is_sub	= ((tss->type == SPU_DVD) || (tss->type == SPU_DVB));		pid_type = pid_type_from_pmt(priv, pid);			// PES CONTENT STARTS HERE		if(! probe)		{			if((pid == demuxer->sub->id))	//or the lang is right			{				pid_type = SPU_DVD;			}			if(is_video && (demuxer->video->id == tss->pid))			{				ds = demuxer->video;				dp = &priv->fifo[1].pack;				dp_offset = &priv->fifo[1].offset;				buffer_size = &priv->fifo[1].buffer_size;			}			else if(is_audio && (demuxer->audio->id == tss->pid))			{				ds = demuxer->audio;				dp = &priv->fifo[0].pack;				dp_offset = &priv->fifo[0].offset;				buffer_size = &priv->fifo[0].buffer_size;			}			else if(is_sub				|| (pid_type == SPU_DVD) || (pid_type == SPU_DVB))			{				//SUBS are infrequent, so the initial detection may fail				// and we may need to add them at play-time				if(demuxer->sub->id == -1)				{					uint16_t p;					p = progid_for_pid(priv, tss->pid, priv->prog);					if(p == priv->prog)					{						int asgn = 0;						uint8_t *lang;						if(!strcmp(dvdsub_lang, ""))							asgn = 1;						else						{							lang = pid_lang_from_pmt(priv, pid);							if(lang != NULL)								asgn = (strncmp(lang, dvdsub_lang, 3) == 0);							else								asgn = 0;						}						if(asgn)						{							demuxer->sub->id = tss->pid;							mp_msg(MSGT_DEMUX, MSGL_INFO, "CHOSEN SUBs pid 0x%x (%d) FROM PROG %d\n", tss->pid, tss->pid, priv->prog);						}					}					else					{						mp_msg(MSGT_DEMUX, MSGL_V, "DISCARDED SUBs pid 0x%x (%d) NOT CHOSEN OR NOT 

⌨️ 快捷键说明

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