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

📄 mpeg2demux.c

📁 从 IEEE 1394总线接收传输流
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * MPEG2-TS over IEEE 1394 decoder - receive and decode MPEG-2 transport *                                   streams according to IEC 61883-4 * * Copyright (C) 2000-2007, Manfred Weihs <mweihs@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* * Exception from GNU General Public License: * There are two functions (head_check and decode_header) in this file * which are modifications of functions taken from mpg123. * The modifications are under GNU GPL, but the the original code is * under copyright (C) 1995-1999 by Michael Hipp and has its own license. * mpg123 can be obtained under http://www.mpg123.de *//*  MPEG 2 transport stream demultiplexer  many ideas and some code taken from Alex Theo de Jong (NIST, February 1996)*/#include <stdlib.h>#include <stdio.h>#include <pthread.h>#include <sys/time.h>#include <errno.h>#include "iso1394dataflowsource.h"#include "synchronisation.h"#include "audio/audiobuffer.h"#include "video/videobuffer.h"#include "mpeg2demux.h"#include "audio/common.h"#define MAX_PIDS  0x2000      /* Maximum number of PIDs in one stream (= 2^13) */#define MAX_PROGRAMS 150      /* maximum number of programs (determines entries in PAT and PMT) */#define PMT_BUFFERS 10        /* number of PMT buffers (this is the number of _uncompleted_ PMT sections which can be hold in memory at a given time) */#define SYNC_BYTE  0x47#define PACKET_START_CODE_PREFIX  0x000001#define PRIVATE_STREAM_2 0xbf#define PADDING_STREAM 0xbeextern int debug;struct stream_description {	int stream_type,elementary_PID;	struct stream_description *next;};struct ProgramMapTableEntry {	int PCR_PID,program_number;	struct stream_description *streams;	struct ProgramMapTableEntry *next;};struct PAT_entry{	unsigned short int program_number,program_map_PID;};struct PMT_buffer_entry{	int pid;	unsigned int byte_count;	unsigned char buffer[1024];};struct TimestampStorage {	int have_timestamp;	unsigned long long timestamp;};static volatile int terminate;    /* tell demux thread to terminate */struct TimestampStorage audio_pts = { 0, 0};static int audio_pid, video_pid, pcr_pid;static int current_program; /* program we are currently decoding, -1 means no special program */static int track_program; /* program number we track, -1 means no program                                                      -2 means any program                                                      -3 means first program of PAT                           *//* various counters */static int transport_packets, transport_packet_errors,           sync_byte_errors, lost_packets,           audio_packets, video_packets,audio_frames,pcr_packets;static int pidcount[MAX_PIDS];static unsigned char continuity_counters[MAX_PIDS];/* Transport Header Info */static int transport_error_indicator, payload_unit_start_indicator,            pid, adaptation_field_control,           transport_scrambling_control;/*  program associated table */static struct PAT_entry PAT[MAX_PROGRAMS];static unsigned char PAT_temp[(MAX_PROGRAMS+1)*4];  /* one quadlet for crc */static int current_pat_section,rest_of_pat_section; /* number of pat section currently read and remaining number of bytes */static unsigned char *PAT_position;                 /* current position in PAT; NULL if no PAT is pending */static unsigned char PAT_header[8];                 /* puffer for the head of the current PAT section */static int PAT_have_bytes_of_header;static int PAT_version,PAT_last_section;static pthread_t demux_thread;static pthread_mutex_t mutex_decoders;              /* this mutex is necessary to prevent the demux to access the decoders (their buffers) during reset */static int transport_stream_id, number_of_programs;/* program map table */static struct PMT_buffer_entry pmt_buffer[PMT_BUFFERS]; /* pmt sections will be stored here, until they are complete, and will be interpreted afterwards */static struct ProgramMapTableEntry *program_map_table;static pthread_mutex_t mutex_PMT;/* global (static) variables needed by audiobufferfill */static int have_mpegaudio_header;static int bytes_already_in_audiobuffer; /* number of bytes we already read *//* global (static) variables needed by get_audio_head */static unsigned long old_mpegaudio_head,skipped_mpegaudio_bytes;/* global (static) variables needed by head_read */static unsigned char audio_hbuf[4];static int audio_header_bytes_read;static int get_sync_byte() { 	return (getbits8() == SYNC_BYTE) ? 1 : 0; }static  void copy_PAT_temp2PAT(int prognum);	/* needed by get_program_association_table */static int get_program_association_table_rest(int expect_start);static int get_and_parse_program_association_table_header();static int get_program_association_table(int start);static int get_pes_packet();static int get_pes_packet_data(int stream_id);static int get_pes_packet_header(unsigned long long *pts, unsigned long long *dts, int *havepts);static int get_PMT_packet(int section_start);static int get_audio_data();static int get_video_data();static void set_pids_internal(int videopid, int audiopid, int pcrpid);/* audio fifo management */static int head_read(unsigned long *head);static int head_check(unsigned long head);static int decode_header(struct frame *fr,unsigned long newhead, int *ssize);static int get_audio_head(struct frame *fr, int *ssize);static int audiobufferfill();/** returns the pid of an audio stream, -1 if no audio stream exists */static int getAudioPid(const struct ProgramMapTableEntry *pmt){	int result=-1;	struct stream_description *hilf;	hilf=pmt->streams;	while (hilf)	{		if (hilf->stream_type==3 || hilf->stream_type==4) result=hilf->elementary_PID;		hilf=hilf->next;	}	return result;}/** returns the pid of an video stream, -1 if no video stream exists */static int getVideoPid(const struct ProgramMapTableEntry *pmt){	int result=-1;	struct stream_description *hilf;	hilf=pmt->streams;	while (hilf)	{		if (hilf->stream_type==1 || hilf->stream_type==2) result=hilf->elementary_PID;		hilf=hilf->next;	}	return result;}  /** returns the pid of the pcr */static int getPCRPid(const struct ProgramMapTableEntry *pmt) {	return pmt->PCR_PID;}static void cleanPMTEntry(struct ProgramMapTableEntry *pmt){	while (pmt->streams) {		struct stream_description *sd=pmt->streams;		pmt->streams = sd->next;		free(sd);	}}static struct ProgramMapTableEntry* getProgramMapTableEntry(int number){	struct ProgramMapTableEntry* temp=program_map_table;	while (temp && (temp->program_number != number)) {		temp=temp->next;	}	return temp;}static int isProgramMapTable(int PID){	int i;	for (i=0;i < number_of_programs;i++)		if (PAT[i].program_map_PID == PID) return PAT[i].program_number?1:2;	return 0;}static int getFirstProgram(){	int i;	for (i=0;i < number_of_programs;i++)		if (PAT[i].program_number) return PAT[i].program_number;	return -1;}/* returns the index in the pmt buffer or the index of an empty one, if it not yet exists of -1 if the buffer is full */static int get_PMT_Buffer_Index(int number){	int hilf=-1,i;	for (i=0;i < PMT_BUFFERS;i++)		if (pmt_buffer[i].pid == number)			return i;		else if ((pmt_buffer[i].pid == -1) && (hilf == -1))			hilf=i;	return hilf;}static int get_adaptation_field();static int get_payload();static int get_transport_packet(){  	if (get_sync_byte()){  /* check for sync byte */		unsigned int bits=getbits16();		unsigned char continuity_counter;		transport_packets++;		transport_error_indicator=bits >> 15;		payload_unit_start_indicator=(bits >> 14) & 1;		pid=bits & 0x00001fff;		transport_scrambling_control=(nextbits8() >> 6)&0x3;		adaptation_field_control=(nextbits8() >> 4)&0x3;		continuity_counter= getbits8() & 0xf;		if (!pidcount[pid]++) {			if (debug) {				fprintf(stdout,"new pid: %d\n", pid);			}		}		if (transport_error_indicator){			transport_packet_errors++;			return 0;  /* error set! */		}		if (pid==0x1fff){			return 1;  /* padding; just go to next */		}		if (pidcount[pid] > 1)  /* only check continuity counters, if this is not the first packet */		{			if (continuity_counters[pid] == continuity_counter && adaptation_field_control & 1)			{				if (debug) {					fprintf(stdout,"skipping duplicate packet in stream %d\n", pid);				}				return 1;			}			if (adaptation_field_control & 1) continuity_counters[pid]=(continuity_counters[pid] +1) & 0x0f;			if (continuity_counters[pid]!=continuity_counter)			{				if (adaptation_field_control & 2) /* has adaptation_field */				{					fprintf(stderr,"maybe lost %d packet(s) of stream %d; could also be discontinous; adaption field control: %d\n", (continuity_counter-continuity_counters[pid] + 16) % 16, pid, adaptation_field_control);				}				else				{					fprintf(stderr,"lost %d packet(s) of stream %d\n", (continuity_counter-continuity_counters[pid] + 16) % 16, pid);					lost_packets++;					if (!pid)	/* (== PAT) */						PAT_position=0;	/* we have to discard, what we already read from pat */					if (isProgramMapTable(pid)) {						int bufferindex=get_PMT_Buffer_Index(pid);						if (bufferindex != -1)							pmt_buffer[bufferindex].pid=-1;  /* we have to throw away any started PMT section */					}				}			}		}		continuity_counters[pid]=continuity_counter;		if (adaptation_field_control==2 || adaptation_field_control==3)			get_adaptation_field();		if (adaptation_field_control==1 || adaptation_field_control==3)			get_payload();		return 1;	}	else 	{		sync_byte_errors++;		fprintf(stderr,"sync error\n");		return 0;	}}static void* transport_stream(void* arg){	do {		if (nextpacket()) {			if (!get_transport_packet()) {				fprintf(stderr, "incorrect packet %d\n", transport_packets);			}		} else {			fprintf(stderr, "source did not deliver packet\n");			if ((videobufferend + 1) % VIDEOPESPACKETSINBUFFER == videobufferstart) { /* if buffer is full */				fprintf(stderr,"Video buffer full! Cannot deliver clearscreen event\n");			} else { /* send clearscreen to video system */				videobuffer[videobufferend].flags = VIDEOBUFFER_FLAGS_CLEARSCREEN;				videobufferend++;				videobufferend %= VIDEOPESPACKETSINBUFFER; /* advance ringbuffercounter */				if (sem_post(&videobuffer_sem))				{					fprintf(stderr,"Cannot V semaphore\n");					exit(0);				}				videobuffer[videobufferend].havedts=0;				videobuffer[videobufferend].continuation=1; /* next packet should be continuation of started one */				videobuffer[videobufferend].length=0;				videobuffer[videobufferend].flags = 0;			}		}	}	while (!terminate);	return NULL;}int mpeg2demux_init(){		int i;	audio_pid=-1; /* disable all pids at start */	video_pid=-1;	pcr_pid=-1;	track_program=-1;	current_program=-1;	have_mpegaudio_header=0;	/* initialization for audiobufferfill */	old_mpegaudio_head = 0,skipped_mpegaudio_bytes=0;	/* initialization for get_audio_head */	transport_packets=0;	transport_packet_errors=0;	sync_byte_errors=0;	lost_packets=0;	audio_packets=0;	video_packets=0;	pcr_packets=0;	audio_frames=0;	number_of_programs=0;	PAT_position=NULL;	for (i=0;i < MAX_PIDS;i++) pidcount[i]=0;	program_map_table=NULL;	for (i=0; i < PMT_BUFFERS;i++) pmt_buffer[i].pid=-1;	(void) pthread_mutex_init(&mutex_PMT,NULL);

⌨️ 快捷键说明

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