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

📄 demux_ts.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Demultiplexer for MPEG2 Transport Streams. * * Written by Nico <nsabbi@libero.it> * Kind feedback is appreciated; 'sucks' and alike is not. * Originally based on demux_pva.c written by Matteo Giani and FFmpeg (libavformat) sources * * This file 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 file 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream.h"#include "demuxer.h"#include "parse_es.h"#include "stheader.h"#include "bswap.h"#include "../unrarlib.h"#include "ms_hdr.h"#include "mpeg_hdr.h"#define TS_PH_PACKET_SIZE 192#define TS_FEC_PACKET_SIZE 204#define TS_PACKET_SIZE 188#define NB_PID_MAX 8192#define MAX_HEADER_SIZE 6			/* enough for PES header + length */#define MAX_CHECK_SIZE	65535#define TS_MAX_PROBE_SIZE 2000000 /* dont forget to change this in cfg-common.h too */#define NUM_CONSECUTIVE_TS_PACKETS 32#define NUM_CONSECUTIVE_AUDIO_PACKETS 348#define MAX_A52_FRAME_SIZE 3840int ts_prog;int ts_keep_broken=0;off_t ts_probe = TS_MAX_PROBE_SIZE;extern char *dvdsub_lang, *audio_lang;	//for -alangextern int demux_aid_vid_mismatch;typedef enum{	UNKNOWN		= -1,	VIDEO_MPEG1 	= 0x10000001,	VIDEO_MPEG2 	= 0x10000002,	VIDEO_MPEG4 	= 0x10000004,	VIDEO_H264 	= 0x10000005,	VIDEO_AVC	= mmioFOURCC('a', 'v', 'c', '1'),	AUDIO_MP2   	= 0x50,	AUDIO_A52   	= 0x2000,	AUDIO_LPCM_BE  	= 0x10001,	AUDIO_AAC	= mmioFOURCC('M', 'P', '4', 'A'),	SPU_DVD		= 0x3000000,	SPU_DVB		= 0x3000001,	PES_PRIVATE1	= 0xBD00000,	SL_PES_STREAM	= 0xD000000,	SL_SECTION	= 0xD100000,	MP4_OD		= 0xD200000,} es_stream_type_t;typedef struct {	uint8_t *buffer;	uint16_t buffer_len;} ts_section_t;typedef struct {	int size;	unsigned char *start;	uint16_t payload_size;	es_stream_type_t type, subtype;	float pts, last_pts;	int pid;	char lang[4];	int last_cc;				// last cc code (-1 if first packet)	int is_synced;	ts_section_t section;	uint8_t *extradata;	int extradata_alloc, extradata_len;	struct {		uint8_t au_start, au_end, last_au_end;	} sl;} ES_stream_t;typedef struct MpegTSContext {	int packet_size; 		// raw packet size, including FEC if present e.g. 188 bytes	ES_stream_t *pids[NB_PID_MAX];} MpegTSContext;typedef struct {	demux_stream_t *ds;	demux_packet_t *pack;	int offset, buffer_size;} av_fifo_t;typedef struct {	int32_t object_type;	//aka codec used	int32_t stream_type;	//video, audio etc.	uint8_t buf[4096];	uint16_t buf_size;	uint8_t szm1;} mp4_decoder_config_t;typedef struct {	//flags	uint8_t flags;	uint8_t au_start;	uint8_t au_end;	uint8_t random_accesspoint;	uint8_t random_accesspoint_only;	uint8_t padding;	uint8_t use_ts;	uint8_t idle;	uint8_t duration;		uint32_t ts_resolution, ocr_resolution;	uint8_t ts_len, ocr_len, au_len, instant_bitrate_len, degr_len, au_seqnum_len, packet_seqnum_len;	uint32_t timescale;	uint16_t au_duration, cts_duration;	uint64_t ocr, dts, cts;} mp4_sl_config_t;typedef struct {	uint16_t id;	uint8_t flags;	mp4_decoder_config_t decoder;	mp4_sl_config_t sl;} mp4_es_descr_t;typedef struct {	uint16_t id;	uint8_t flags;	mp4_es_descr_t *es;	uint16_t es_cnt;} mp4_od_t;typedef struct {	uint8_t skip;	uint8_t table_id;	uint8_t ssi;	uint16_t section_length;	uint16_t ts_id;	uint8_t version_number;	uint8_t curr_next;	uint8_t section_number;	uint8_t last_section_number;	struct pat_progs_t {		uint16_t id;		uint16_t pmt_pid;	} *progs;	uint16_t progs_cnt;	ts_section_t section;} pat_t;typedef struct {	uint16_t progid;	uint8_t skip;	uint8_t table_id;	uint8_t ssi;	uint16_t section_length;	uint8_t version_number;	uint8_t curr_next;	uint8_t section_number;	uint8_t last_section_number;	uint16_t PCR_PID;	uint16_t prog_descr_length;	ts_section_t section;	uint16_t es_cnt;	struct pmt_es_t {		uint16_t pid;		uint32_t type;	//it's 8 bit long, but cast to the right type as FOURCC		uint16_t descr_length;		uint8_t format_descriptor[5];		uint8_t lang[4];		uint16_t mp4_es_id;	} *es;	mp4_od_t iod, *od;	mp4_es_descr_t *mp4es;	int od_cnt, mp4es_cnt;} pmt_t;typedef struct {	MpegTSContext ts;	int last_pid;	av_fifo_t fifo[3];	//0 for audio, 1 for video, 2 for subs	pat_t pat;	pmt_t *pmt;	uint16_t pmt_cnt;	uint32_t prog;	int keep_broken;	char packet[TS_FEC_PACKET_SIZE];} ts_priv_t;typedef struct {	es_stream_type_t type;	ts_section_t section;} TS_pids_t;#define IS_AUDIO(x) (((x) == AUDIO_MP2) || ((x) == AUDIO_A52) || ((x) == AUDIO_LPCM_BE) || ((x) == AUDIO_AAC))#define IS_VIDEO(x) (((x) == VIDEO_MPEG1) || ((x) == VIDEO_MPEG2) || ((x) == VIDEO_MPEG4) || ((x) == VIDEO_H264) || ((x) == VIDEO_AVC))static int ts_parse(demuxer_t *demuxer, ES_stream_t *es, unsigned char *packet, int probe);extern void resync_audio_stream( sh_audio_t *sh_audio );static uint8_t get_packet_size(const unsigned char *buf, int size){	int i;	if (size < (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS))		return 0;	for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)	{		if (buf[i * TS_PACKET_SIZE] != 0x47)		{			mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]);			goto try_fec;		}	}	return TS_PACKET_SIZE;try_fec:	for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)	{		if (buf[i * TS_FEC_PACKET_SIZE] != 0x47){			mp_msg(MSGT_DEMUX, MSGL_DBG2, "GET_PACKET_SIZE, pos %d, char: %2x\n", i, buf[i * TS_PACKET_SIZE]);			goto try_philips;		}	}	return TS_FEC_PACKET_SIZE; try_philips:	for(i=0; i<NUM_CONSECUTIVE_TS_PACKETS; i++)	{		if (buf[i * TS_PH_PACKET_SIZE] != 0x47)		return 0;	}	return TS_PH_PACKET_SIZE;}int ts_check_file(demuxer_t * demuxer){	const int buf_size = (TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS);	unsigned char buf[TS_FEC_PACKET_SIZE * NUM_CONSECUTIVE_TS_PACKETS], done = 0, *ptr;	uint32_t _read, i, count = 0, is_ts;	int cc[NB_PID_MAX], last_cc[NB_PID_MAX], pid, cc_ok, c, good, bad;	uint8_t size = 0;	off_t pos = 0;	off_t init_pos;	mp_msg(MSGT_DEMUX, MSGL_V, "Checking for MPEG-TS...\n");	init_pos = stream_tell(demuxer->stream);	is_ts = 0;	while(! done)	{		i = 1;		c = 0;		while(((c=stream_read_char(demuxer->stream)) != 0x47)			&& (c >= 0)			&& (i < MAX_CHECK_SIZE)			&& ! demuxer->stream->eof		) i++;		if(c != 0x47)		{			mp_msg(MSGT_DEMUX, MSGL_V, "THIS DOESN'T LOOK LIKE AN MPEG-TS FILE!\n");			is_ts = 0;			done = 1;			continue;		}		pos = stream_tell(demuxer->stream) - 1;		buf[0] = c;		_read = stream_read(demuxer->stream, &buf[1], buf_size-1);		if(_read < buf_size-1)		{			mp_msg(MSGT_DEMUX, MSGL_V, "COULDN'T READ ENOUGH DATA, EXITING TS_CHECK\n");			stream_reset(demuxer->stream);			return 0;		}		size = get_packet_size(buf, buf_size);		if(size)		{			done = 1;			is_ts = 1;		}		if(pos - init_pos >= MAX_CHECK_SIZE)		{			done = 1;			is_ts = 0;		}	}	mp_msg(MSGT_DEMUX, MSGL_V, "TRIED UP TO POSITION %llu, FOUND %x, packet_size= %d, SEEMS A TS? %d\n", (uint64_t) pos, c, size, is_ts);	stream_seek(demuxer->stream, pos);	if(! is_ts)	  return 0;	//LET'S CHECK continuity counters	good = bad = 0;	for(count = 0; count < NB_PID_MAX; count++)	{		cc[count] = last_cc[count] = -1;	}	for(count = 0; count < NUM_CONSECUTIVE_TS_PACKETS; count++)	{		ptr = &(buf[size * count]);		pid = ((ptr[1] & 0x1f) << 8) | ptr[2];		mp_msg(MSGT_DEMUX, MSGL_DBG2, "BUF: %02x %02x %02x %02x, PID %d, SIZE: %d \n",		ptr[0], ptr[1], ptr[2], ptr[3], pid, size);		if((pid == 8191) || (pid < 16))			continue;		cc[pid] = (ptr[3] & 0xf);		cc_ok = (last_cc[pid] < 0) || ((((last_cc[pid] + 1) & 0x0f) == cc[pid]));		mp_msg(MSGT_DEMUX, MSGL_DBG2, "PID %d, COMPARE CC %d AND LAST_CC %d\n", pid, cc[pid], last_cc[pid]);		if(! cc_ok)			//return 0;			bad++;		else			good++;		last_cc[pid] = cc[pid];	}	mp_msg(MSGT_DEMUX, MSGL_V, "GOOD CC: %d, BAD CC: %d\n", good, bad);	if(good >= bad)		return size;	else		return 0;}static inline int32_t progid_idx_in_pmt(ts_priv_t *priv, uint16_t progid){	int x;	if(priv->pmt == NULL)		return -1;	for(x = 0; x < priv->pmt_cnt; x++)	{		if(priv->pmt[x].progid == progid)			return x;	}	return -1;}static inline int32_t progid_for_pid(ts_priv_t *priv, int pid, int32_t req)		//finds the first program listing a pid{	int i, j;	pmt_t *pmt;	if(priv->pmt == NULL)		return -1;	for(i=0; i < priv->pmt_cnt; i++)	{		pmt = &(priv->pmt[i]);		if(pmt->es == NULL)			return -1;		for(j = 0; j < pmt->es_cnt; j++)		{			if(pmt->es[j].pid == pid)			{				if((req == 0) || (req == pmt->progid))					return pmt->progid;			}		}	}	return -1;}static inline int pid_match_lang(ts_priv_t *priv, uint16_t pid, char *lang){	uint16_t i, j;	pmt_t *pmt;	if(priv->pmt == NULL)		return -1;	for(i=0; i < priv->pmt_cnt; i++)	{		pmt = &(priv->pmt[i]);		if(pmt->es == NULL)			return -1;		for(j = 0; j < pmt->es_cnt; j++)		{			if(pmt->es[j].pid != pid)				continue;			mp_msg(MSGT_DEMUXER, MSGL_V, "CMP LANG %s AND %s, pids: %d %d\n",pmt->es[j].lang, lang, pmt->es[j].pid, pid);			if(strncmp(pmt->es[j].lang, lang, 3) == 0)			{				return 1;			}		}	}	return -1;}typedef struct {	int32_t atype, vtype, stype;	//types	int32_t apid, vpid, spid;	//stream ids	char slang[4], alang[4];	//languages	int16_t prog;	off_t probe;} tsdemux_init_t;//stripped down version of a52_syncinfo() from liba52//copyright belongs to Michel Lespinasse <walken@zoy.org> and Aaron Holtzman <aholtzma@ess.engr.uvic.ca>static int a52_framesize(uint8_t * buf){	int rate[] = {	32,  40,  48,  56,  64,  80,  96, 112,			128, 160, 192, 224, 256, 320, 384, 448,			512, 576, 640	};	uint8_t halfrate[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3};	int frmsizecod, bitrate, half;		if((buf[0] != 0x0b) || (buf[1] != 0x77))	/* syncword */		return 0;		if(buf[5] >= 0x60)		/* bsid >= 12 */		return 0;	half = halfrate[buf[5] >> 3];		frmsizecod = buf[4] & 63;	if(frmsizecod >= 38)		return 0;	bitrate = rate[frmsizecod >> 1];		switch(buf[4] & 0xc0) 	{		case 0:	/* 48 KHz */			return 4 * bitrate;		case 0x40:	/* 44.1 KHz */			return 2 * (320 * bitrate / 147 + (frmsizecod & 1));		case 0x80: /* 32 KHz */			return 6 * bitrate;	}		return 0;}//second stage: returns the count of A52 syncwords foundstatic int a52_check(char *buf, int len){	int cnt, frame_length, ok;		cnt = ok = 0;	if(len < 8)		return 0;			while(cnt < len - 7)		{		if(buf[cnt] == 0x0B && buf[cnt+1] == 0x77)		{			frame_length = a52_framesize(&buf[cnt]);			if(frame_length>=7 && frame_length<=3840)			{				cnt += frame_length;				ok++;			}			else			    cnt++;		}		else			cnt++;	}	mp_msg(MSGT_DEMUXER, MSGL_V, "A52_CHECK(%d input bytes), found %d frame syncwords of %d bytes length\n", len, ok, frame_length);		return ok;}static off_t ts_detect_streams(demuxer_t *demuxer, tsdemux_init_t *param){	int video_found = 0, audio_found = 0, sub_found = 0, i, num_packets = 0, req_apid, req_vpid, req_spid;	int is_audio, is_video, is_sub, has_tables;	int32_t p, chosen_pid = 0;	off_t pos=0, ret = 0, init_pos;	ES_stream_t es;	unsigned char tmp[TS_FEC_PACKET_SIZE];	ts_priv_t *priv = (ts_priv_t*) demuxer->priv;	struct {		char *buf;		int pos;	} pes_priv1[8192], *pptr;	char *tmpbuf;	priv->last_pid = 8192;		//invalid pid	req_apid = param->apid;	req_vpid = param->vpid;	req_spid = param->spid;	has_tables = 0;	memset(pes_priv1, 0, sizeof(pes_priv1));	init_pos = stream_tell(demuxer->stream);	mp_msg(MSGT_DEMUXER, MSGL_INFO, "PROBING UP TO %llu, PROG: %d\n", (uint64_t) param->probe, param->prog);

⌨️ 快捷键说明

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