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

📄 mpeg2demux.c

📁 从 IEEE 1394总线接收传输流
💻 C
📖 第 1 页 / 共 4 页
字号:
	(void) pthread_mutex_init(&mutex_decoders,NULL);	(void) audio_system_init();	(void) video_system_init();	terminate=0;	if (pthread_create(&demux_thread,NULL, transport_stream, NULL))	{		fprintf(stderr,"Cannot create TS demultiplexer thread\n");;		return 1;	}	return 0;}void mpeg2demux_done(){	void* result;	terminate=1;	if (pthread_join(demux_thread,&result))	/* wait for thread to exit */	{		fprintf(stderr,"Cannot join TS demux thread\n");;		exit(1);	}	while (program_map_table) {		struct ProgramMapTableEntry *temp;		temp = program_map_table->next;		free(program_map_table);		program_map_table = temp;	}	(void) video_system_done();	(void) audio_system_done();	if (pthread_mutex_destroy(&mutex_PMT))	{		fprintf(stderr,"Cannot destroy PMT mutex\n");;		exit(1);	}	if (debug) {		fprintf(stdout,"demux terminated\n");	}}void printPAT(FILE* ostream) {	int i;	if (pthread_mutex_lock(&mutex_PMT))	{		fprintf(stderr,"cannot lock PMT mutex\n");;		exit(1);	}	fprintf(ostream, "Program Association Table (containing %d descriptions):\n", number_of_programs);	for (i= 0; i < number_of_programs;i++) {		fprintf(ostream,"program %u has PSI in PID %u (0x%x)\n",  PAT[i].program_number, PAT[i].program_map_PID,PAT[i].program_map_PID);	}	if (pthread_mutex_unlock(&mutex_PMT))	{		fprintf(stderr,"cannot unlock PMT mutex\n");;		exit(1);	}}void printPMT(FILE* ostream) {	struct ProgramMapTableEntry* temp;	if (pthread_mutex_lock(&mutex_PMT))	{		fprintf(stderr,"cannot lock PMT mutex\n");;		exit(1);	}	for (temp=program_map_table; temp; temp=temp->next) {		struct stream_description *streams;		fprintf(ostream,"Mappings for program number %u with PCR_PID %u (0x%x):\n",temp->program_number, temp->PCR_PID, temp->PCR_PID);		for (streams=temp->streams; streams; streams=streams->next) {			fprintf(ostream,"\telementary stream %u (0x%x) has type %u", streams->elementary_PID, streams->elementary_PID, streams->stream_type);			switch (streams->stream_type)			{				case 0: fprintf(ostream," (reserved)"); break;				case 1: fprintf(ostream," (MPEG 1 Video)"); break;				case 2: fprintf(ostream," (MPEG 2 Video)"); break;				case 3: fprintf(ostream," (MPEG 1 Audio)"); break;				case 4: fprintf(ostream," (MPEG 2 Audio)"); break;				case 5: fprintf(ostream," (private sections)"); break;				case 6: fprintf(ostream," (PES private data)"); break;				case 7: fprintf(ostream," (MHEG)"); break;				case 8: fprintf(ostream," (DSM CC)"); break;				case 9: fprintf(ostream," (ITU-T Rec. H.222.1)"); break;				case 10: fprintf(ostream," (ISO/IEC 13818-6 type A)"); break;				case 11: fprintf(ostream," (ISO/IEC 13818-6 type B)"); break;				case 12: fprintf(ostream," (ISO/IEC 13818-6 type C)"); break;				case 13: fprintf(ostream," (ISO/IEC 13818-6 type D)"); break;				case 14: fprintf(ostream," (ISO/IEC 13818-1 auxiliary)"); break;				default: fprintf(ostream," (reserved or user private)"); break;			}			fprintf(ostream,"\n");		}	}	if (pthread_mutex_unlock(&mutex_PMT))	{		fprintf(stderr,"cannot unlock PMT mutex\n");;		exit(1);	}}void printPidTable(FILE* ostream) {	unsigned int i;	for (i=0; i < MAX_PIDS; i++)		if (pidcount[i])			fprintf(ostream, "PID %u (0x%x) occured %u times\n", i, i, pidcount[i]);}static int get_adaptation_field(){	int length=getbits8(); /* get adaptation field length */	if (length)	{		/* int discontinuity_indicator=(nextbits8() >> 7); */		/* int random_access_indicator=(nextbits8() >> 6) & 1; */		/* int elem_prio_indicator=(nextbits8() >> 5) & 1;  not used at this point; */		int pcr_flag=(getbits8() >> 4) & 1;  /* get first byte */		if (pcr_flag){			unsigned long long clk_ref_base=getbits32();			unsigned int clk_ref_ext=getbits16();			clk_ref_base<<=1; /* Create space for bit */			clk_ref_base|=(clk_ref_ext >> 15);			clk_ref_ext&=0x01ff;  /* Only lower 9 bits */    			if (pid==pcr_pid) {				setSTC(clk_ref_base,clk_ref_ext);				pcr_packets++;			}			skipbytes(length - 7);		}		else skipbytes(length - 1);	}	else	{		fprintf(stderr,"adaption field does only stuffing a byte. PID: %d\n", pid);	}	return 1;}static int get_payload(){	if (payload_unit_start_indicator){		if (pid==0) get_program_association_table(1);		else if (nextbits24()==PACKET_START_CODE_PREFIX) {			if (pthread_mutex_lock(&mutex_decoders)) /* lock decoders; they may not be reset now */			{				fprintf(stderr,"cannot lock decoders mutex\n");				exit(1);			}			get_pes_packet();			if (pthread_mutex_unlock(&mutex_decoders)) /* unlock decoders; now they can safely be reset */			{				fprintf(stderr,"cannot unlock decoders mutex\n");				exit(1);			}		}		else switch (isProgramMapTable(pid)) {			case 2:if (debug) {fprintf(stdout,"skipping Network Information Table\n");} break;			case 0:break; //skipbytes(MPEG2_TS_Packet_size - bytecount);break;			case 1:get_PMT_packet(1);break;			default: fprintf(stderr,"internal error\n");exit(1);		}	}	else	{		if (pid==0) get_program_association_table(0);		else if (pid==audio_pid) {			if (pthread_mutex_lock(&mutex_decoders)) /* lock decoders; they may not be reset now */			{				fprintf(stderr,"cannot lock decoders mutex\n");				exit(1);			}			get_audio_data();			if (pthread_mutex_unlock(&mutex_decoders)) /* unlock decoders; now they can safely be reset */			{				fprintf(stderr,"cannot unlock decoders mutex\n");				exit(1);			}		}		else if (pid==video_pid) {			if (pthread_mutex_lock(&mutex_decoders)) /* lock decoders; they may not be reset now */			{				fprintf(stderr,"cannot lock decoders mutex\n");				exit(1);			}			get_video_data();			if (pthread_mutex_unlock(&mutex_decoders)) /* unlock decoders; now they can safely be reset */			{				fprintf(stderr,"cannot unlock decoders mutex\n");				exit(1);			}		}		else  switch (isProgramMapTable(pid)) {			case 2:if (debug) {fprintf(stdout,"skipping continuation of Network Information Table\n");}break;			case 0:break; //skipbytes(MPEG2_TS_Packet_size - bytecount);break;			case 1:get_PMT_packet(0);break;			default: fprintf(stderr,"internal error\n");exit(1);		}	}	return 1;}static void copy_PAT_temp2PAT(int prognum){	struct ProgramMapTableEntry **pmt_temp;	int i;	if (pthread_mutex_lock(&mutex_PMT))	/* lock tables before we modify them */	{		fprintf(stderr,"cannot lock PMT mutex\n");		exit(1);	}	for (i=0; i < prognum; i++)	{		PAT[i].program_number=(PAT_temp[i<<2] << 8) | PAT_temp[(i<<2) +1];		PAT[i].program_map_PID=((PAT_temp[(i<<2)+2] & 0x1F) << 8) | PAT_temp[(i<<2) +3];	}	number_of_programs = prognum;	/* clean PMT now */	for (pmt_temp=&program_map_table; *pmt_temp;)	{		int number=(*pmt_temp)->program_number;		int exists=0; /* does the program number exist in PAT? */		int j;		for (j=0; j < prognum; j++)			if (PAT[j].program_number==number)			{				exists=1;				break;			}		if (!exists) /* program does not exist anymore -> we eliminate PMT entry */		{			struct ProgramMapTableEntry *t2 = *pmt_temp;			*pmt_temp=(*pmt_temp)->next;			cleanPMTEntry(t2);			free(t2);			if (current_program == number) {				fprintf(stderr,"program %d does not exist anymore", number);				current_program = -1;				set_pids_internal(-1,-1,-1); /* reset decoders */			}		} else {			pmt_temp=&(*pmt_temp)->next;		}	}	if (pthread_mutex_unlock(&mutex_PMT))	/* unlock tables */	{		fprintf(stderr, "cannot unlock PMT mutex\n");		exit(1);	}	/* cleanup pmt buffers */	for (i=0;i < PMT_BUFFERS;i++) {		if ((pmt_buffer[i].pid != -1) && !isProgramMapTable(pmt_buffer[i].pid)) {			pmt_buffer[i].pid = -1;		}	}}/* reads the rest of a PAT (as far as available in the current TS packet   returns 1 if we should continue with the next TS packet afterwards   of 0 if we shall continue this packet.*/static int get_program_association_table_rest(int expect_start){	int bytes_to_read=rest_of_pat_section <= rest_of_ts_packet()?rest_of_pat_section:rest_of_ts_packet();	if (PAT_position + bytes_to_read > PAT_temp + 4*(MAX_PROGRAMS+1))	{		fprintf(stderr, "PAT too long, discarding\n");		PAT_position=0;		return 1;	}	PAT_position += copybytes(PAT_position,bytes_to_read);	if (!(rest_of_pat_section -= bytes_to_read))	/*  if we completed a section... */	{		PAT_position -= 4;          /* remove CRC_32 */		PAT_have_bytes_of_header=0; /* we have to start new section afterwards */		if (current_pat_section == PAT_last_section)		{ /* we completed last section */			if (rest_of_ts_packet() && (nextbits8()!=0xff)) /* if we have a rest, it must be padding */			{				fprintf(stderr,"PATs end is not padding\n");				PAT_position=0;	/* we will have to start a new PAT afterwards */				return 1;			}			else			{ /* we read a complete PAT which is ok and make it the current one */				copy_PAT_temp2PAT((PAT_position-PAT_temp) / 4);				PAT_position=0;	/* we will have to start a new PAT afterwards */				return 1;			}		}		if ((!expect_start) && (!rest_of_ts_packet() || nextbits8() == 0xff))			return 1; /* skip padding at end of ts packet */	}	return 0; /* we have to continue reading this TS packet */}/* reads the (rest of the) PAT-header (as far as available in the current TS packet)   and parses it if it completes   It returns 1 if the PAT has an error and we shall discard what we already read and skip the rest of the current TS packet   or 0 if the head is ok and we could continue reading this packet*/static int get_and_parse_program_association_table_header(){	int bytes_to_read=(8-PAT_have_bytes_of_header) <= rest_of_ts_packet()?8-PAT_have_bytes_of_header:rest_of_ts_packet();	PAT_have_bytes_of_header += copybytes(PAT_header+PAT_have_bytes_of_header,bytes_to_read);	if (PAT_have_bytes_of_header==8) /* if we have a complete header now... */	{                                /*  parse it */		int section_length;		current_pat_section++;		if (PAT_header[0]!=0) /* table id */			{fprintf(stderr,"incorrect table id in program association table\n");; return 1;}		if ((PAT_header[1] >> 6) != 2)			{fprintf(stderr,"syntax error in program association table\n");; return 1;}		section_length=((PAT_header[1] & 0x0f) << 8) | PAT_header[2];		if ((section_length > 1021) || (rest_of_pat_section=section_length-5) % 4)			{fprintf(stderr,"PAT section invalid long\n");; return 1;}		transport_stream_id=PAT_header[3] << 8 | PAT_header[4];		if (PAT_header[6] != current_pat_section) {			fprintf(stderr,"pat section number %d not monoton\n", (int) PAT_header[6]);;			return 1;		}		if (current_pat_section)		{ /* not first section */			if ((PAT_header[5] & 0x3f) != PAT_version) {				fprintf(stderr,"incorrect PAT version\n"); 				return 1;			}			if (PAT_last_section != PAT_header[7]) {				fprintf(stderr,"last_section_number may not change within PAT\n");				return 1;			}		}		else		{ /* first section */			if (PAT_header[5] & 1) /* current_next says current */			{				PAT_version=PAT_header[5] & 0x3f;				PAT_last_section=PAT_header[7];			}			else				{fprintf(stderr,"skipping next PAT\n");; return 1;}		}	}	return 0;}static int get_program_association_table(int start){	int started=0;	int start_position=0;	if (start) /* if a new section starts in this packet */	{		int pointer_field=getbits8();  /* get pointer_field */		start_position=rest_of_ts_packet()-pointer_field;		if (PAT_position==0) /* if we have to start a new PAT */		{			if (pointer_field)			{				fprintf(stderr,"skipping part of a PAT, waiting for new one\n");;				return 1;			}			else			{				PAT_position=PAT_temp;				current_pat_section=-1;	/* next section number must be 0 */				rest_of_pat_section=0;	/* we do not have to complete an old pat section, but can immediately start the new one */

⌨️ 快捷键说明

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