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

📄 mpegts.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
}static void gf_m2ts_process_pat(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *ses, unsigned char *data, u32 data_size, u8 table_id, u16 ex_table_id, u32 status){	GF_M2TS_Program *prog;	GF_M2TS_SECTION_ES *pmt;	u32 i, nb_progs, evt_type;	/*skip if already received*/	if (status==GF_M2TS_TABLE_REPEAT) {		if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_PAT_REPEAT, NULL);		return;	}	nb_progs = data_size / 4;	for (i=0; i<nb_progs; i++) {		u16 number, pid;		number = (data[0]<<8) | data[1];		pid = (data[2]&0x1f)<<8 | data[3];		data += 4;		if (number==0) {			if (!ts->nit) {				ts->nit = gf_m2ts_section_filter_new(gf_m2ts_process_nit);			}		} else {			GF_SAFEALLOC(prog, GF_M2TS_Program);			prog->streams = gf_list_new();			prog->pmt_pid = pid;			prog->number = number;			gf_list_add(ts->programs, prog);			GF_SAFEALLOC(pmt, GF_M2TS_SECTION_ES);			pmt->flags = GF_M2TS_ES_IS_SECTION;			gf_list_add(prog->streams, pmt);			pmt->pid = prog->pmt_pid;			pmt->program = prog;			ts->ess[pmt->pid] = (GF_M2TS_ES *)pmt;			pmt->sec = gf_m2ts_section_filter_new(gf_m2ts_process_pmt);		}	}	evt_type = (status==GF_M2TS_TABLE_UPDATE) ? GF_M2TS_EVT_PAT_UPDATE : GF_M2TS_EVT_PAT_FOUND;	if (ts->on_event) ts->on_event(ts, evt_type, NULL);}static GFINLINE u64 gf_m2ts_get_pts(unsigned char *data){    u64 pts;    u32 val;    pts = (u64)((data[0] >> 1) & 0x07) << 30;    val = (data[1] << 8) | data[2];    pts |= (u64)(val >> 1) << 15;    val = (data[3] << 8) | data[4];    pts |= (u64)(val >> 1);    return pts;}static void gf_m2ts_pes_header(unsigned char *data, u32 data_size, GF_M2TS_PESHeader *pesh){	Bool has_pts, has_dts;	memset(pesh, 0, sizeof(GF_M2TS_PESHeader));	pesh->id = data[0];	pesh->pck_len = (data[1]<<8) | data[2];/*		2bits		scrambling_control		= gf_bs_read_int(bs,2);	priority				= gf_bs_read_int(bs,1);*/	pesh->data_alignment = (data[3] & 0x4) ? 1 : 0;/*	copyright				= gf_bs_read_int(bs,1);	original				= gf_bs_read_int(bs,1);*/	has_pts = (data[4]&0x80);	has_dts = (data[4]&0x40);/*	ESCR_flag				= gf_bs_read_int(bs,1);	ES_rate_flag			= gf_bs_read_int(bs,1);	DSM_flag				= gf_bs_read_int(bs,1);	additional_copy_flag	= gf_bs_read_int(bs,1);	prev_crc_flag			= gf_bs_read_int(bs,1);	extension_flag			= gf_bs_read_int(bs,1);*/	pesh->hdr_data_len = data[5];	data += 6;	if (has_pts) {		pesh->PTS = gf_m2ts_get_pts(data);		data+=5;	}	if (has_dts) {		pesh->DTS = gf_m2ts_get_pts(data);		data+=5;	}}static void gf_m2ts_process_pes(GF_M2TS_Demuxer *ts, GF_M2TS_PES *pes, GF_M2TS_Header *hdr, unsigned char *data, u32 data_size, GF_M2TS_AdaptationField *paf){	Bool flush_pes = 0;	if (!pes->reframe) return;		if (hdr->payload_start) {		flush_pes = 1;	} else if (pes->pes_len && (pes->data_len + data_size  == pes->pes_len + 6)) { 		/* 6 = startcode+stream_id+length*/		/*reassemble pes*/		if (pes->data) pes->data = (char*)realloc(pes->data, pes->data_len+data_size);		else pes->data = (char*)malloc(data_size);		memcpy(pes->data+pes->data_len, data, data_size);		pes->data_len += data_size;		/*force discard*/		data_size = 0;	}	/*PES first fragment: flush previous packet*/	if (flush_pes && pes->data) {		GF_M2TS_PESHeader pesh;		/*we need at least a full, valid start code !!*/		if ((pes->data_len >= 4) && !pes->data[0] && !pes->data[1] && (pes->data[2]==0x1)) {			u32 len;            u32 stream_id = pes->data[3] | 0x100;            if ((stream_id >= 0x1c0 && stream_id <= 0x1df) ||                  (stream_id >= 0x1e0 && stream_id <= 0x1ef) ||                  (stream_id == 0x1bd)) {				/*OK read header*/				gf_m2ts_pes_header(pes->data+3, pes->data_len-3, &pesh);				/*3-byte start-code + 6 bytes header + hdr extensions*/				len = 9 + pesh.hdr_data_len;				pes->reframe(ts, pes, pesh.DTS, pesh.PTS, pes->data+len, pes->data_len-len);			} 			/*SL-packetized stream*/			else if ((u8) pes->data[3]==0xfa) {				GF_M2TS_SL_PCK sl_pck;				/*read header*/				gf_m2ts_pes_header(pes->data+3, pes->data_len-3, &pesh);				/*3-byte start-code + 6 bytes header + hdr extensions*/				len = 9 + pesh.hdr_data_len;				GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] SL Packet in PES for %d\n", pes->pid));				sl_pck.data = pes->data + len;				sl_pck.data_len = pes->data_len - len;				sl_pck.stream = (GF_M2TS_ES *)pes;				if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_SL_PCK, &sl_pck);			}		}		if (pes->data) {			free(pes->data);			pes->data = NULL;			pes->data_len = 0;			pes->pes_len = 0;		}		pes->rap = 0;		if (!data_size) return;	}	/*reassemble*/	if (pes->data) pes->data = (char*)realloc(pes->data, pes->data_len+data_size);	else pes->data = (char*)malloc(data_size);	memcpy(pes->data+pes->data_len, data, data_size);	pes->data_len += data_size;	if (paf && paf->random_access_indicator) pes->rap = 1; 	if (!pes->pes_len && (pes->data_len>=6)) pes->pes_len = (pes->data[4]<<8) | pes->data[5];}static void gf_m2ts_get_adaptation_field(GF_M2TS_Demuxer *ts, GF_M2TS_AdaptationField *paf, unsigned char *data, u32 size){	paf->discontinuity_indicator = (data[0] & 0x80) ? 1 : 0;	paf->random_access_indicator = (data[0] & 0x40) ? 1 : 0;	paf->priority_indicator = (data[0] & 0x20) ? 1 : 0;	paf->PCR_flag = (data[0] & 0x10) ? 1 : 0;	paf->OPCR_flag = (data[0] & 0x8) ? 1 : 0;	paf->splicing_point_flag = (data[0] & 0x4) ? 1 : 0;	paf->transport_private_data_flag = (data[0] & 0x2) ? 1 : 0;	paf->adaptation_field_extension_flag = (data[0] & 0x1) ? 1 : 0;	if (paf->PCR_flag == 1){		u64 PCR = (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];		paf->PCR_base = (PCR << 1) | (data[5] >> 7);		paf->PCR_ext = ((data[5] & 1) << 8) | data[6];	}#if 0	if (paf->OPCR_flag == 1){		u64 PCR = (data[7] << 24) | (data[8] << 16) | (data[9] << 8) | data[10];		paf->PCR_base = (PCR << 1) | (data[11] >> 7);		paf->PCR_ext = ((data[11] & 1) << 8) | data[12];	}#endif	}static void gf_m2ts_process_packet(GF_M2TS_Demuxer *ts, unsigned char *data){	GF_M2TS_ES *es;	GF_M2TS_Header hdr;	GF_M2TS_AdaptationField af, *paf;	u32 payload_size, af_size;	u32 pos = 0;		/* read TS packet header*/	hdr.sync = data[0];	hdr.error = (data[1] & 0x80) ? 1 : 0;	hdr.payload_start = (data[1] & 0x40) ? 1 : 0;	hdr.priority = (data[1] & 0x20) ? 1 : 0;	hdr.pid = ( (data[1]&0x1f) << 8) | data[2];	hdr.scrambling_ctrl = (data[3] >> 6) & 0x3;	hdr.adaptation_field = (data[3] >> 4) & 0x3;	hdr.continuity_counter = data[3] & 0xf;#if DEBUG_TS_PACKET	GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] Packet PID %d\n", hdr.pid));#endif	paf = NULL;	payload_size = 184;	pos = 4;	switch (hdr.adaptation_field) {	/*adaptation+data*/	case 3: 		af_size = data[4];		if (af_size>183) {			//error			return;		}		paf = &af;		memset(paf, 0, sizeof(GF_M2TS_AdaptationField));		gf_m2ts_get_adaptation_field(ts, paf, data+5, af_size);		pos += 1+af_size;		payload_size = 183 - af_size;		break;	/*adaptation only - still process in cas of PCR*/	case 2: 		af_size = data[4];		if (af_size>183) {			//error			return;		}		paf = &af;		memset(paf, 0, sizeof(GF_M2TS_AdaptationField));		gf_m2ts_get_adaptation_field(ts, paf, data+5, af_size);		payload_size = 0;		break;	/*reserved*/	case 0:		return;	default:		break;	}	data += pos;	/*PAT*/	if (hdr.pid == 0) {		gf_m2ts_gather_section(ts, ts->pat, NULL, &hdr, data, payload_size);		return;	}	else {		es = ts->ess[hdr.pid];		/*check for DVB reserved PIDs*/		if (!es) {			/*SDT*/			if (hdr.pid == 0x0011) {				gf_m2ts_gather_section(ts, ts->sdt, NULL, &hdr, data, payload_size);				return;			}			/*NIT for DVB*/			else if (hdr.pid == 0x0010) {				/*ignore them, unused at application level*/				//if (!hdr.error) gf_m2ts_gather_section(ts, ts->nit, NULL, &hdr, data, payload_size);				return;			} 			return;		}		if (es->flags & GF_M2TS_ES_IS_SECTION) { 	/* The stream uses sections to carry its payload */			GF_M2TS_SECTION_ES *ses = (GF_M2TS_SECTION_ES *)es;			if (ses->sec) gf_m2ts_gather_section(ts, ses->sec, ses, &hdr, data, payload_size);		} else {			/* regular stream using PES packets */			/* let the pes reassembler decide if packets with error shall be discarded*/			gf_m2ts_process_pes(ts, (GF_M2TS_PES *)es, &hdr, data, payload_size, paf);			if (paf && paf->PCR_flag) {				GF_M2TS_PES_PCK pck;				memset(&pck, 0, sizeof(GF_M2TS_PES_PCK));				pck.PTS = paf->PCR_base * 300 + paf->PCR_ext; // ???				pck.stream = (GF_M2TS_PES *)es;				if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_PES_PCR, &pck);			}		}	}	return;}GF_Err gf_m2ts_process_data(GF_M2TS_Demuxer *ts, char *data, u32 data_size){	u32 pos;	Bool is_align = 1;	if (ts->buffer) {		if (ts->alloc_size < ts->buffer_size+data_size) {			ts->alloc_size = ts->buffer_size+data_size;			ts->buffer = (char*)realloc(ts->buffer, sizeof(char)*ts->alloc_size);		}		memcpy(ts->buffer + ts->buffer_size, data, sizeof(char)*data_size);		ts->buffer_size += data_size;		is_align = 0;	} else {		ts->buffer = data;		ts->buffer_size = data_size;	}	/*sync input data*/	pos = gf_m2ts_sync(ts, is_align);	if (pos==ts->buffer_size) {		if (is_align) {			ts->buffer = (char*)malloc(sizeof(char)*data_size);			memcpy(ts->buffer, data, sizeof(char)*data_size);			ts->alloc_size = ts->buffer_size = data_size;		}		return GF_OK;	}	for (;;) {		/*wait for a complete packet*/		if (ts->buffer_size - pos < 188) {			ts->buffer_size -= pos;			if (!ts->buffer_size) {				if (!is_align) free(ts->buffer);				ts->buffer = NULL;				return GF_OK;			}			if (is_align) {				data = ts->buffer+pos;				ts->buffer = (char*)malloc(sizeof(char)*ts->buffer_size);				memcpy(ts->buffer, data, sizeof(char)*ts->buffer_size);				ts->alloc_size = ts->buffer_size;			} else {				memmove(ts->buffer, ts->buffer + pos, sizeof(char)*ts->buffer_size);			}			return GF_OK;		}		/*process*/		gf_m2ts_process_packet(ts, ts->buffer+pos);		pos += 188;	} 	return GF_OK;}void gf_m2ts_reset_parsers(GF_M2TS_Demuxer *ts){	u32 i;	for (i=0; i<GF_M2TS_MAX_STREAMS; i++) {		GF_M2TS_PES *pes = (GF_M2TS_PES *) ts->ess[i];		if (!pes || (pes->pid==pes->program->pmt_pid)) continue;		pes->frame_state = 0;		if (pes->data) free(pes->data);		pes->data = NULL;		pes->data_len = 0;		pes->PTS = pes->DTS = 0;	}}GF_Err gf_m2ts_set_pes_framing(GF_M2TS_PES *pes, u32 mode){	if (pes->pid==pes->program->pmt_pid) return GF_BAD_PARAM;	if (mode==GF_M2TS_PES_FRAMING_RAW) {		pes->reframe = gf_m2ts_reframe_default;		return GF_OK;	} else if (mode==GF_M2TS_PES_FRAMING_SKIP) {		pes->reframe = NULL;		return GF_OK;	} else { // mode==GF_M2TS_PES_FRAMING_DEFAULT		switch (pes->stream_type) {		case GF_M2TS_VIDEO_MPEG1: 		case GF_M2TS_VIDEO_MPEG2:			pes->reframe = gf_m2ts_reframe_mpeg_video;			break;		case GF_M2TS_AUDIO_MPEG1:		case GF_M2TS_AUDIO_MPEG2:			pes->reframe = gf_m2ts_reframe_mpeg_audio;			break;		case GF_M2TS_VIDEO_H264:			pes->reframe = gf_m2ts_reframe_avc_h264;			break;		default:			pes->reframe = gf_m2ts_reframe_default;			break;		}		return GF_OK;	}}GF_M2TS_Demuxer *gf_m2ts_demux_new(){	GF_M2TS_Demuxer *ts;	GF_SAFEALLOC(ts, GF_M2TS_Demuxer);	ts->programs = gf_list_new();	ts->SDTs = gf_list_new();	ts->pat = gf_m2ts_section_filter_new(gf_m2ts_process_pat);	ts->sdt = gf_m2ts_section_filter_new(gf_m2ts_process_sdt);	return ts;}void gf_m2ts_demux_del(GF_M2TS_Demuxer *ts){	u32 i;	if (ts->pat) gf_m2ts_section_filter_del(ts->pat);	if (ts->sdt) gf_m2ts_section_filter_del(ts->sdt);	if (ts->nit) gf_m2ts_section_filter_del(ts->nit);	for (i=0; i<8192; i++) {		if (ts->ess[i]) gf_m2ts_es_del(ts->ess[i]);	}	if (ts->buffer) free(ts->buffer);	while (gf_list_count(ts->programs)) {		GF_M2TS_Program *p = (GF_M2TS_Program *)gf_list_last(ts->programs);		gf_list_rem_last(ts->programs);		gf_list_del(p->streams);		if (p->pmt_iod) gf_odf_desc_del((GF_Descriptor *)p->pmt_iod);		free(p);	}	gf_list_del(ts->programs);	gf_m2ts_reset_sdt(ts);	gf_list_del(ts->SDTs);	free(ts);}

⌨️ 快捷键说明

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