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

📄 demux_ts.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include "config.h"#include "mp_msg.h"#include "help_mp.h"#include "stream/stream.h"#include "demuxer.h"#include "parse_es.h"#include "stheader.h"#include "unrarlib.h"#include "ms_hdr.h"#include "mpeg_hdr.h"#undef memcpy#define memcpy uc_memcpy#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 3840#ifndef SIZE_MAX#define SIZE_MAX ((size_t)-1)#endif#define TYPE_AUDIO 1#define TYPE_VIDEO 2int ts_prog;int ts_keep_broken=0;off_t ts_probe = 0;extern char *dvdsub_lang, *audio_lang;	//for -alangtypedef enum{	UNKNOWN		= -1,	VIDEO_MPEG1 	= 0x10000001,	VIDEO_MPEG2 	= 0x10000002,	VIDEO_MPEG4 	= 0x10000004,	VIDEO_H264 	= 0x10000005,	VIDEO_AVC	= mmioFOURCC('a', 'v', 'c', '1'),	VIDEO_VC1	= mmioFOURCC('W', 'V', 'C', '1'),	AUDIO_MP2   	= 0x50,	AUDIO_A52   	= 0x2000,	AUDIO_DTS	= 0x2001,	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 {	void *sh;	int id;	int type;} sh_av_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];	sh_av_t streams[NB_PID_MAX];} MpegTSContext;typedef struct {	demux_stream_t *ds;	demux_packet_t *pack;	int offset, buffer_size;} av_fifo_t;#define MAX_EXTRADATA_SIZE 64*1024typedef struct {	int32_t object_type;	//aka codec used	int32_t stream_type;	//video, audio etc.	uint8_t buf[MAX_EXTRADATA_SIZE];	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 {	uint64_t size;	float duration;	float first_pts;	float last_pts;} TS_stream_info;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;	uint32_t vbitrate;	int keep_broken;	int last_aid;	int last_vid;	char packet[TS_FEC_PACKET_SIZE];	TS_stream_info vstr, astr;} 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) || ((x) == AUDIO_DTS))#define IS_VIDEO(x) (((x) == VIDEO_MPEG1) || ((x) == VIDEO_MPEG2) || ((x) == VIDEO_MPEG4) || ((x) == VIDEO_H264) || ((x) == VIDEO_AVC)  || ((x) == VIDEO_VC1))static int ts_parse(demuxer_t *demuxer, ES_stream_t *es, unsigned char *packet, int probe);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;}static int parse_avc_sps(uint8_t *buf, int len, int *w, int *h);static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es){	int i;	ts_priv_t *priv = (ts_priv_t*) demuxer->priv;	if(priv->ts.streams[es->pid].sh)		return;	if((IS_AUDIO(es->type) || IS_AUDIO(es->subtype)) && priv->last_aid+1 < MAX_A_STREAMS)	{		sh_audio_t *sh = new_sh_audio_aid(demuxer, priv->last_aid, es->pid);		if(sh)		{			sh->format = IS_AUDIO(es->type) ? es->type : es->subtype;			sh->ds = demuxer->audio;			priv->ts.streams[es->pid].id = priv->last_aid;			priv->ts.streams[es->pid].sh = sh;			priv->ts.streams[es->pid].type = TYPE_AUDIO;			mp_msg(MSGT_DEMUX, MSGL_V, "\r\nADDED AUDIO PID %d, type: %x stream n. %d\r\n", es->pid, sh->format, priv->last_aid);			priv->last_aid++;		}		if(es->extradata && es->extradata_len)		{			sh->wf = (WAVEFORMATEX *) malloc(sizeof (WAVEFORMATEX) + es->extradata_len);			sh->wf->cbSize = es->extradata_len;			memcpy(sh->wf + 1, es->extradata, es->extradata_len);		}	}	if((IS_VIDEO(es->type) || IS_VIDEO(es->subtype)) && priv->last_vid+1 < MAX_V_STREAMS)	{		sh_video_t *sh = new_sh_video_vid(demuxer, priv->last_vid, es->pid);		if(sh)		{			sh->format = IS_VIDEO(es->type) ? es->type : es->subtype;;			sh->ds = demuxer->video;			priv->ts.streams[es->pid].id = priv->last_vid;			priv->ts.streams[es->pid].sh = sh;			priv->ts.streams[es->pid].type = TYPE_VIDEO;			mp_msg(MSGT_DEMUX, MSGL_V, "\r\nADDED VIDEO PID %d, type: %x stream n. %d\r\n", es->pid, sh->format, priv->last_vid);			priv->last_vid++;			if(sh->format == VIDEO_AVC && es->extradata && es->extradata_len)			{				int w = 0, h = 0;				sh->bih = (BITMAPINFOHEADER *) calloc(1, sizeof(BITMAPINFOHEADER) + es->extradata_len);				sh->bih->biSize= sizeof(BITMAPINFOHEADER) + es->extradata_len;				sh->bih->biCompression = sh->format;				memcpy(sh->bih + 1, es->extradata, es->extradata_len);				mp_msg(MSGT_DEMUXER,MSGL_DBG2, "EXTRADATA(%d BYTES): \n", es->extradata_len);				for(i = 0;i < es->extradata_len; i++)					mp_msg(MSGT_DEMUXER,MSGL_DBG2, "%02x ", (int) es->extradata[i]);				mp_msg(MSGT_DEMUXER,MSGL_DBG2,"\n");				if(parse_avc_sps(es->extradata, es->extradata_len, &w, &h))				{					sh->bih->biWidth = w;					sh->bih->biHeight = h;				}			}		}	}}static 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 %"PRIu64", 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	uint16_t prog;	off_t probe;} tsdemux_init_t;//stripped down version of a52_syncinfo() from liba52

⌨️ 快捷键说明

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