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

📄 mpegts.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
	u8 table_id;	u16 extended_table_id;	u32 status, section_start;	GF_M2TS_Table *t, *prev_t;	unsigned char *data;	Bool section_valid = 0;	/*parse header*/	data = sec->section;	/*look for proper table*/	prev_t = NULL;	table_id = data[0];	t = sec->table;	while (t) {		if (t->table_id==table_id) break;		prev_t = t;		t = t->next;	}	/*create table*/	if (!t) {		GF_SAFEALLOC(t, GF_M2TS_Table);		t->table_id = table_id;		if (prev_t) prev_t->next = t;		else sec->table = t;	}	extended_table_id = 0;	section_start = 3;//	sec->table_id = data[0]; 	has_syntax_indicator = (data[1] & 0x80) ? 1 : 0;	if (has_syntax_indicator) {		/*remove crc32*/		sec->length -= 4;		if (gf_m2ts_crc32_check(data, sec->length)) {			s32 cur_sec_num;			extended_table_id = (data[3]<<8) | data[4];			t->version_number = (data[5] >> 1) & 0x1f;			t->current_next_indicator = (data[5] & 0x1) ? 1 : 0;			cur_sec_num = data[6];			t->last_section_number = data[7];			section_start = 8;			section_valid = 1;			/*we missed something*/			if (cur_sec_num && (t->section_number + 1 != cur_sec_num)) {				section_valid = 0;				GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] corrupted table (lost section %d)\n", cur_sec_num ? cur_sec_num-1 : 31) );			}			t->section_number = cur_sec_num;		} else {			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] corrupted section (CRC32 failed)\n"));		}	} else if (!sec->had_error) {		section_valid = 1;	}	/*process section*/	if (section_valid) {		/*table is spread across several sections, gather*/		if (t->last_section_number) {			u32 pay_size = t->data_size + sec->length - section_start;			t->data = (char*)realloc(t->data, sizeof(char)*pay_size);			memcpy(t->data + t->data_size, sec->section + section_start, sizeof(char)*(sec->length - section_start) );			t->data_size = pay_size;			if (sec->section) free(sec->section);			sec->section = NULL;			sec->length = sec->received = 0;		}		/*not done yet*/		if (t->last_section_number > t->section_number) return;		if (!t->is_init) status = GF_M2TS_TABLE_FOUND;		else status = (t->last_version_number==t->version_number) ? GF_M2TS_TABLE_REPEAT : GF_M2TS_TABLE_UPDATE;		t->last_version_number = t->version_number;		t->is_init = 1;		if (t->current_next_indicator) {			if (t->data) {				sec->process_section(ts, ses, t->data, t->data_size, t->table_id, extended_table_id, status);				free(t->data);				t->data = NULL;				t->data_size = 0;			} else {				sec->process_section(ts, ses, sec->section + section_start, sec->length - section_start, t->table_id, extended_table_id, status);			}		}	} else {		sec->cc = -1;	}	/*clean-up (including broken sections)*/	if (sec->section) free(sec->section);	sec->section = NULL;	sec->length = sec->received = 0;}static Bool gf_m2ts_is_long_section(u8 table_id){	switch (table_id) {	case GF_M2TS_TABLE_ID_MPEG4_BIFS:	case GF_M2TS_TABLE_ID_MPEG4_OD:	case GF_M2TS_TABLE_ID_EIT_ACTUAL_PF:	case GF_M2TS_TABLE_ID_ST:	case GF_M2TS_TABLE_ID_SIT:		return 1;	default:		return 0;	}}static void gf_m2ts_gather_section(GF_M2TS_Demuxer *ts, GF_M2TS_SectionFilter *sec, GF_M2TS_SECTION_ES *ses, GF_M2TS_Header *hdr, unsigned char *data, u32 data_size){	u8 expect_cc = (sec->cc<0) ? hdr->continuity_counter : (sec->cc + 1) & 0xf;	Bool disc = (expect_cc == hdr->continuity_counter) ? 0 : 1;	sec->cc = expect_cc;	if (hdr->error || 		(hdr->adaptation_field==2)) /* 2 = no payload in TS packet */		return; 	if (hdr->payload_start) {		u32 ptr_field;		ptr_field = data[0];		if (ptr_field+1>data_size) {			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] Invalid section start (@ptr_field=%d, @data_size=%d)\n", ptr_field, data_size) );			return;		}		/*end of previous section*/		if (sec->length && sec->received + ptr_field >= sec->length) {			memcpy(sec->section + sec->received, data, sizeof(char)*ptr_field);			sec->received += ptr_field;			gf_m2ts_section_complete(ts, sec, ses);		}		data += ptr_field+1;		data_size -= ptr_field+1;		if (sec->section) free(sec->section);		sec->length = sec->received = 0;		sec->section = (char*)malloc(sizeof(char)*data_size);		memcpy(sec->section, data, sizeof(char)*data_size);		sec->received = data_size;		sec->had_error = 0;	} else if (disc || hdr->error) {		if (sec->section) free(sec->section);		sec->section = NULL;		sec->received = sec->length = 0;		return;	} else if (!sec->section) {		return;	} else {		if (sec->received+data_size > sec->length) {#if 0			GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] skipping %d bytes of garbage in section\n", data_size - (sec->length - sec->received) ));#endif			data_size = sec->length - sec->received;		}		if (sec->length) {			memcpy(sec->section + sec->received, data, sizeof(char)*data_size);		} else {			sec->section = (char*)realloc(sec->section, sizeof(char)*(sec->received+data_size));			memcpy(sec->section + sec->received, data, sizeof(char)*data_size);		}		sec->received += data_size;	}	if (hdr->error) sec->had_error = 1;	/*alloc final buffer*/	if (!sec->length && (sec->received >= 3)) {		if (gf_m2ts_is_long_section(sec->section[0])) {			sec->length = 3 + ( ((sec->section[1]<<8) | sec->section[2]) & 0xfff );		} else {			sec->length = 3 + ( ((sec->section[1]<<8) | sec->section[2]) & 0x3ff );		}		sec->section = (char*)realloc(sec->section, sizeof(char)*sec->length);	}	if (sec->received < sec->length) return;	/*OK done*/	gf_m2ts_section_complete(ts, sec, ses);}static void gf_m2ts_process_sdt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *ses, unsigned char *data, u32 data_size, u8 table_id, u16 ex_table_id, u32 status){	u32 orig_net_id, pos, evt_type;	/*skip if already received*/	if (status==GF_M2TS_TABLE_REPEAT) {		if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_SDT_REPEAT, NULL);		return;	}	if (table_id != GF_M2TS_TABLE_ID_SDT_ACTUAL) {		gf_m2ts_reset_sdt(ts);		return;	}	/*reset service desc*/	free(ses->sec->section);	ses->sec->section = NULL;	ses->sec->length = ses->sec->received = 0;//	GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] SDT for actual ts\n"));	gf_m2ts_reset_sdt(ts);	orig_net_id = (data[0] << 8) | data[1];	pos = 3;	while (pos < data_size) {		GF_M2TS_SDT *sdt;		u32 descs_size, d_pos, ulen;				GF_SAFEALLOC(sdt, GF_M2TS_SDT);		gf_list_add(ts->SDTs, sdt);		sdt->service_id = (data[pos]<<8) + data[pos+1];		sdt->EIT_schedule = (data[pos+2] & 0x2) ? 1 : 0;		sdt->EIT_present_following = (data[pos+2] & 0x1);		sdt->running_status = (data[pos+3]>>5) & 0x7;		sdt->free_CA_mode = (data[pos+3]>>4) & 0x1;		descs_size = ((data[pos+3]&0xf)<<8) | data[pos+4];		pos += 5;		d_pos = 0;		while (d_pos < descs_size) {			u8 d_tag = data[pos+d_pos];			u8 d_len = data[pos+d_pos+1];			switch (d_tag) {			case GF_M2TS_DVB_SERVICE_DESCRIPTOR: 				if (sdt->provider) free(sdt->provider);				sdt->provider = NULL;				if (sdt->service) free(sdt->service);				sdt->service = NULL;								d_pos+=2;				sdt->service_type = data[pos+d_pos];				ulen = data[pos+d_pos+1];				d_pos += 2;				sdt->provider = (char*)malloc(sizeof(char)*(ulen+1));				memcpy(sdt->provider, data+pos+d_pos, sizeof(char)*ulen);				sdt->provider[ulen] = 0;				d_pos += ulen;				ulen = data[pos+d_pos];				d_pos += 1;				sdt->service = (char*)malloc(sizeof(char)*(ulen+1));				memcpy(sdt->service, data+pos+d_pos, sizeof(char)*ulen);				sdt->service[ulen] = 0;				d_pos += ulen;				break;			default:				GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] Skipping descriptor (0x%x) not supported\n", d_tag));				d_pos += d_len;				if (d_len == 0) d_pos = descs_size;				break;			}		}		pos += descs_size;	}	evt_type = GF_M2TS_EVT_SDT_FOUND;	if (ts->on_event) ts->on_event(ts, evt_type, NULL);}static void gf_m2ts_process_mpeg4section(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *es, unsigned char *data, u32 data_size, u8 table_id, u16 ex_table_id, u32 status){	GF_M2TS_SL_PCK sl_pck;	/*skip if already received*/	if (status==GF_M2TS_TABLE_REPEAT) return;	GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG-2 TS] Section for PID %d\n", es->pid) );	sl_pck.data = data;	sl_pck.data_len = data_size;	sl_pck.stream = (GF_M2TS_ES *)es;	if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_SL_PCK, &sl_pck);}static void gf_m2ts_process_int(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *ip_not_table, unsigned char *data, u32 data_size, u8 table_id, u16 ex_table_id, u32 status){	fprintf(stdout, "Processing IP/MAC Notification table (PID %d) %s\n", ip_not_table->pid, (status==GF_M2TS_TABLE_REPEAT)?"repeated":"");}#if 0static void gf_m2ts_process_mpe(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *mpe, unsigned char *data, u32 data_size, u8 table_id, u16 ex_table_id, u32 status){	fprintf(stdout, "Processing MPE Datagram (PID %d)\n", mpe->pid);}#endifstatic void gf_m2ts_process_nit(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *mpe, unsigned char *data, u32 data_size, u8 table_id, u16 ex_table_id, u32 status){}static void gf_m2ts_process_pmt(GF_M2TS_Demuxer *ts, GF_M2TS_SECTION_ES *pmt, unsigned char *data, u32 data_size, u8 table_id, u16 ex_table_id, u32 status){	u32 info_length, pos, desc_len, evt_type;	/*skip if already received*/	if (status==GF_M2TS_TABLE_REPEAT) {		if (ts->on_event) ts->on_event(ts, GF_M2TS_EVT_PMT_REPEAT, pmt->program);		return;	}		pmt->program->pcr_pid = ((data[0] & 0x1f) << 8) | data[1];	info_length = ((data[2]&0xf)<<8) | data[3];	if (info_length != 0) {		/* ...Read Descriptors ... */		u8 tag, len;		u32 first_loop_len = 0;		tag = data[4];		len = data[5];		while (info_length > first_loop_len) {			if (tag == GF_M2TS_MPEG4_IOD_DESCRIPTOR) { 				u8 scope, label;								u32 size;				GF_BitStream *iod_bs;				scope = data[6];				label = data[7];								iod_bs = gf_bs_new(data+8, data_size-8, GF_BITSTREAM_READ);#if 0				printf("Parsing IOD descriptor ... ");				if (gf_odf_parse_descriptor(iod_bs , (GF_Descriptor **) &pmt->program->pmt_iod, &size) == GF_OK)					printf("done.\n");				else 					printf("error.\n");#else				if (pmt->program->pmt_iod) gf_odf_desc_del((GF_Descriptor *)pmt->program->pmt_iod);				gf_odf_parse_descriptor(iod_bs , (GF_Descriptor **) &pmt->program->pmt_iod, &size);#endif				gf_bs_del(iod_bs );			} else {				GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] Skipping descriptor (0x%x) and others not supported\n", tag));			}			first_loop_len += 2 + len;		}	}	if (data_size <= 4 + info_length) return;	data += 4 + info_length;	data_size -= 4 + info_length;	pos = 0;	while (pos<data_size) {		GF_M2TS_PES *pes = NULL;		GF_M2TS_SECTION_ES *ses = NULL;		GF_M2TS_ES *es;		u32 pid, stream_type;				stream_type = data[0];		pid = ((data[1] & 0x1f) << 8) | data[2];		desc_len = ((data[3] & 0xf) << 8) | data[4];		switch (stream_type) {			/* PES */			case GF_M2TS_VIDEO_MPEG1: 			case GF_M2TS_VIDEO_MPEG2:			case GF_M2TS_AUDIO_MPEG1:			case GF_M2TS_AUDIO_MPEG2:			case GF_M2TS_AUDIO_AAC:			case GF_M2TS_VIDEO_MPEG4:			case GF_M2TS_SYSTEMS_MPEG4_PES:			case GF_M2TS_VIDEO_H264:			case GF_M2TS_AUDIO_AC3:			case GF_M2TS_AUDIO_DTS:			case GF_M2TS_SUBTITLE_DVB:			case GF_M2TS_PRIVATE_DATA:				GF_SAFEALLOC(pes, GF_M2TS_PES);				es = (GF_M2TS_ES *)pes;				break;			/* Sections */			case GF_M2TS_PRIVATE_SECTION:			case GF_M2TS_SYSTEMS_MPEG4_SECTIONS:				GF_SAFEALLOC(ses, GF_M2TS_SECTION_ES);				es = (GF_M2TS_ES *)ses;				es->flags |= GF_M2TS_ES_IS_SECTION;				/* carriage of ISO_IEC_14496 data in sections */				if (stream_type == GF_M2TS_SYSTEMS_MPEG4_SECTIONS) {					ses->sec = gf_m2ts_section_filter_new(gf_m2ts_process_mpeg4section);				}				break;			default:				GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] Stream type (0x%x) for PID %d not supported\n", stream_type, pid ) );				return;		}				es->stream_type = stream_type; 		es->program = pmt->program;		es->pid = pid;		ts->ess[es->pid] = es;		gf_list_add(pmt->program->streams, es);		pos += 5;		data += 5;		while (desc_len) {			u8 tag = data[0];			u32 len = data[1];			switch (tag) {			case GF_M2TS_ISO_639_LANGUAGE_DESCRIPTOR: 				pes->lang = GF_4CC(' ', data[2], data[3], data[4]);				break;			case GF_M2TS_MPEG4_SL_DESCRIPTOR: 			{				//u32 esd_index = 0;				pes->mpeg4_es_id = ((data[7] & 0x1f) << 8) | data[8];				pes->flags |= GF_M2TS_ES_IS_SL;/*				while ( (GF_ESD *esd = (GF_ESD*)gf_list_enum(pmt->program->pmt_iod->ESDescriptors, &esd_index)) ) {					if (esd->ESID == pes->ES_ID) pes->esd = esd;				}*/			}				break;			case GF_M2TS_DVB_DATA_BROADCAST_ID_DESCRIPTOR: 				 {				 	u32 id = data[2]<<8 | data[3];					if (id == 0xB) {					 	ses->sec = gf_m2ts_section_filter_new(gf_m2ts_process_int);					 	gf_list_add(ts->ip_mac_not_tables, es);					}				 }				break;			default:				GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS] skipping descriptor (0x%x) not supported\n", tag));				break;			}			data += len+2;			pos += len+2;			if (desc_len < len+2) {				GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS] Invalid PMT es descriptor size for PID %d\n", pes->pid ) );				break;			}			desc_len-=len+2;		}		if (!(es->flags & GF_M2TS_ES_IS_SECTION) ) gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);	}	evt_type = (status==GF_M2TS_TABLE_FOUND) ? GF_M2TS_EVT_PMT_FOUND : GF_M2TS_EVT_PMT_UPDATE;	if (ts->on_event) ts->on_event(ts, evt_type, pmt->program);

⌨️ 快捷键说明

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