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

📄 mpgparse.cpp

📁 EM8511s中使用的mpg播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "mpgparse.h"#include <memory.h>#include <stdio.h>#if 0#ifdef _WIN32#include <windows.h>static void debug_outs (char *szMsg, ...){	char szBuf[256];	wvsprintf (szBuf, szMsg, (LPSTR)(&szMsg + 1));	OutputDebugString (szBuf);}#else#include <stdio.h>#define debug_outs	printf#endifstatic void debug_break (void){}#define ASSERT(exp)					((void)((exp)?1:(debug_outs ("ASSERT failed: line %d, file %s\n", __LINE__,__FILE__), debug_break(), 0)))#define DEBUGMSG(cond,printf_exp)	((void)((cond)?(debug_outs printf_exp),1:0))#else#define ASSERT(exp)#define DEBUGMSG(cond,printf_exp)#endif#define MPG_MIN(X,Y) (((X)<=(Y))?(X):(Y))	// to find the min between two number.static void MPEG1DemuxCallback (RMuint8 *pData, RMuint32 Length, RMuint8 PacketId, 	RMint64 Scr, RMint64 Pts, RMint64 Dts, RMuint8 Flags, RMint64 offset, void *Context){	MPEGDemux *pDemux = (MPEGDemux *)Context;	ASSERT (pDemux);	pDemux->MPEG1DemuxCallback (pData, Length, PacketId, Scr, Pts, Dts, Flags, offset);}static void PESDemuxCallback (RMuint8 *pData, RMuint32 Length, RMuint8 StreamId, RMuint8 SubStreamId, 	RMint64 Scr, RMint64 Pts, RMint64 Dts, RMuint8 Flags, RMint64 offset, void *Context){	MPEGDemux *pDemux = (MPEGDemux *)Context;	ASSERT (pDemux);	pDemux->PESDemuxCallback (pData, Length, StreamId, SubStreamId, Scr, Pts, Dts, Flags, offset);}static void AC3DTSInfoCallback (RMuint8 numberOfFrameHeaders, 	RMuint16 firstAccessUnitPointer, void *context){	MPEGDemux *pDemux = (MPEGDemux *)context;	ASSERT (pDemux);	pDemux->AC3DTSInfoCallback (numberOfFrameHeaders, firstAccessUnitPointer);}static void LPCMInfoCallback (RMuint8 numberOfFrameHeaders,	RMuint16 firstAccessUnitPointer, RMuint32 frequency, 	RMuint8 numberOfChannels, RMuint8 quantizationWordLength, 	void *context){	MPEGDemux *pDemux = (MPEGDemux *)context;	ASSERT (pDemux);	pDemux->LPCMInfoCallback (numberOfFrameHeaders, firstAccessUnitPointer,		frequency, numberOfChannels, quantizationWordLength);}MPEGDemux::MPEGDemux (){	m_file = 0;}MPEGDemux::~MPEGDemux (){	if (m_file)		m_CallbackTable.fclose (m_file, m_CallbackTable.context);}// call this after creationMPG_DEMUX_ERROR MPEGDemux::Init (){	// initialize internal mpeg demux callbacks	// initialize any internal variables	m_MPEG1Demux.m_Callback = ::MPEG1DemuxCallback;	m_MPEG1Demux.m_Context = this;	m_ProgramDemux.m_Callback = ::PESDemuxCallback;	m_ProgramDemux.m_ac3dtsCallback = ::AC3DTSInfoCallback;	m_ProgramDemux.m_lpcmCallback = ::LPCMInfoCallback;	m_ProgramDemux.m_Context = this;	m_ProgramDemux.m_IsDVDStream = 0;	m_MPEG1Demux.Reset ();	m_MPEG1Demux.ResetState ();	m_ProgramDemux.Reset ();	m_ProgramDemux.ResetState ();	m_DemuxType = 0;	if (m_file)		m_CallbackTable.fclose (m_file, m_CallbackTable.context);	m_file = 0;	m_CurrentPosition = 0;	m_IFrameState = 0;	m_BytesToSkip = 0;	m_IFrameSubState = 0;	m_StartPosition = 0;	m_ReverseErrorLoop = 0;	return MPG_DEMUX_ERROR_NOT_IMPLEMENTED;}// call this to initalize the required callbacksMPG_DEMUX_ERROR MPEGDemux::InitCallbackTable (MPG_CALLBACK_TABLE *pCallbackTable){	memcpy (&m_CallbackTable, pCallbackTable, sizeof (MPG_CALLBACK_TABLE));	return MPG_DEMUX_ERROR_NO_ERROR;}// call this to identify the file typeMPG_DEMUX_ERROR MPEGDemux::DecodeFile (RMint8 *filename){	// try to detect if the file is a valid mpeg file	if (IsTransportStream (filename))	{		// no support for transport streams		DEBUGMSG (1, ("error: no support for transport streams\n"));		return MPG_DEMUX_ERROR_NOT_AN_MPEG_FILE;	}	if (IsDVDStream (filename))	{		DEBUGMSG (1, ("DVD stream\n"));		m_DemuxType = DVD_DEMUX;		m_ProgramDemux.m_IsDVDStream = 1;	}	else if (IsProgramStream (filename))	{		DEBUGMSG (1, ("MPEG 2 program stream\n"));		m_DemuxType = PROGRAM_DEMUX;	}	else if (IsMPEG1SystemStream (filename))	{		DEBUGMSG (1, ("MPEG 1 system stream\n"));		m_DemuxType = SYSTEM_DEMUX;		if (IsVCDStream (filename))		{			DEBUGMSG (1, ("DAT file\n"));			m_DemuxType = DAT_DEMUX;		}	}	else if (IsMPEG124ElementaryStream (filename, &m_mpeg12))	{		m_DemuxType = NO_DEMUX; 	}	else	{		DEBUGMSG (1, ("error: MPG_DEMUX_ERROR_NOT_AN_MPEG_FILE\n"));		return MPG_DEMUX_ERROR_NOT_AN_MPEG_FILE;	}	ASSERT (m_file == 0);	m_file = m_CallbackTable.fopen (filename, m_CallbackTable.context);	ASSERT (m_file);	return MPG_DEMUX_ERROR_NO_ERROR;}RMuint32 MPEGDemux::GetDemuxType (void){	return m_DemuxType;}RMuint32 MPEGDemux::AssumeDVDPacketStructure (RMint32 followdvd){	if ((m_DemuxType == PROGRAM_DEMUX) || (m_DemuxType == DVD_DEMUX))	{		if (followdvd)			m_DemuxType = DVD_DEMUX;		else			m_DemuxType = PROGRAM_DEMUX;		m_ProgramDemux.m_IsDVDStream = followdvd;	}	return 0;}// call this repeatly to do workMPG_DEMUX_ERROR MPEGDemux::Schedule (){	RMuint8 *p, *ptemp;	RMint32 l, temp, readlength;	// get a buffer an demux it	if (m_CallbackTable.getMPG (&p, (RMuint32 *)&l, m_CallbackTable.context) == MPG_DEMUX_ERROR_NO_ERROR)	{		ASSERT (m_file);		if (m_DemuxType == DAT_DEMUX)			l -= (l % 2352);		ASSERT (l);				l = m_CallbackTable.fread (m_file, p, l, m_CallbackTable.context);		readlength = l;		if (l)		{			// demux it						m_CallbackTable.addref (p, m_CallbackTable.context);			ptemp = p;			while (l)			{				ASSERT (l > 0);				temp = MPG_MIN (l, 32768);				DEBUGMSG (0, ("demux (%d)\n", temp));				demux (ptemp, temp);				ptemp += temp;				l -= temp;				m_CurrentPosition += temp;				if (m_BytesToSkip)				{					if (m_IFrameSubState == MPG_FOUND_2ND_PICTURE_HEADER)					{						m_MPEG1Demux.Reset ();						m_ProgramDemux.Reset ();						if (m_BytesToSkip > 0)						{							if (l < m_BytesToSkip)							{								m_BytesToSkip -= l;								m_CurrentPosition += m_BytesToSkip;								DEBUGMSG (1, ("skipping %d bytes to %d\n", (RMint32)m_BytesToSkip, (RMint32)m_CurrentPosition));								m_CallbackTable.fseek (m_file, (RMint32)m_CurrentPosition, SEEK_SET, m_CallbackTable.context);														}							else							{								l -= m_BytesToSkip;								ptemp += m_BytesToSkip;							}						}						else						{							if (m_IFramePosition != -1)							{								m_CurrentPosition = m_IFramePosition + m_BytesToSkip;								if (m_CurrentPosition <= 0)								{									DEBUGMSG (1, ("(1) play backward hit start of file.\n"));									m_CallbackTable.fseek (m_file, 0, SEEK_SET, m_CallbackTable.context);									m_CallbackTable.release (p, m_CallbackTable.context);									return MPG_DEMUX_ERROR_FILE_DONE;								}							}							else							{								ASSERT (0);								m_StartPosition -= 1024 * 128;								if (m_StartPosition < 0)								{									DEBUGMSG (1, ("(2) play backward hit start of file.\n"));									m_CallbackTable.fseek (m_file, 0, SEEK_SET, m_CallbackTable.context);									m_CallbackTable.release (p, m_CallbackTable.context);									return MPG_DEMUX_ERROR_FILE_DONE;								}								m_CurrentPosition = m_StartPosition;							}						}						l = 0;						m_IFrameState = 0;						m_IFrameSubState = MPG_LOOKING_FOR_SEQUENCE_HEADER; 						DEBUGMSG (1, ("seeking to %d\n", (RMint32)m_CurrentPosition));						m_CallbackTable.fseek (m_file, (RMint32)m_CurrentPosition, SEEK_SET, m_CallbackTable.context);					}					else if (m_IFrameSubState == MPG_ERROR_SAME_IFRAME_DURING_REVERSE)					{						ASSERT (m_IFramePosition != -1);						m_CurrentPosition = m_IFramePosition + m_BytesToSkip - 1024*32*m_ReverseErrorLoop;						if (m_CurrentPosition < 0)						{							DEBUGMSG (1, ("(3) play backward hit start of file.\n"));							m_CallbackTable.fseek (m_file, 0, SEEK_SET, m_CallbackTable.context);							m_CallbackTable.release (p, m_CallbackTable.context);							return MPG_DEMUX_ERROR_FILE_DONE;						}						l = 0;						m_ReverseErrorLoop++;						DEBUGMSG (1, ("m_ReverseErrorLoop = %d\n", (RMint32)m_ReverseErrorLoop));						m_IFrameState = 0;						m_IFrameSubState = MPG_LOOKING_FOR_SEQUENCE_HEADER; 						DEBUGMSG (1, ("seeking to %d\n", (RMint32)m_CurrentPosition));						m_CallbackTable.fseek (m_file, (RMint32)m_CurrentPosition, SEEK_SET, m_CallbackTable.context);					}				}							}			m_CallbackTable.release (p, m_CallbackTable.context);		}		else			return MPG_DEMUX_ERROR_FILE_DONE;	}	return MPG_DEMUX_ERROR_NOT_IMPLEMENTED;}MPG_DEMUX_ERROR MPEGDemux::SendIFramesOnly (RMint32 BytesToSkip){	DEBUGMSG (1, ("MPEGDemux::SendIFramesOnly (%d)\n", BytesToSkip));	if (m_BytesToSkip)	{		if (m_IFramePosition != -1)		{			DEBUGMSG (1, ("seeking to %d\n", (RMint32)m_IFramePosition));			m_CallbackTable.fseek (m_file, (RMint32)m_IFramePosition, SEEK_SET, m_CallbackTable.context);		}	}	// reset i frame state	m_IFrameState = 0;	m_IFrameSubState = MPG_LOOKING_FOR_SEQUENCE_HEADER;	m_IFramePosition = -1;	m_BytesToSkip = BytesToSkip;	m_MPEG1Demux.Reset ();	m_ProgramDemux.Reset ();	if (m_DemuxType == DVD_DEMUX)		m_ProgramDemux.m_IsDVDStream = 1;	m_StartPosition = m_CurrentPosition;	return MPG_DEMUX_ERROR_NO_ERROR;}//////////////////////////////////////////////////////////////////#define TRANSPORT_BLOCK_LENGTH	(1024*16)RMint32 MPEGDemux::IsTransportStream (RMint8 *filename){	DEBUGMSG (1, ("IsTransportStream (%s)\n", filename));	// we will consider this a transport stream if we find at leat 5 sync words (0x47)	// in the first TRANSPORT_BLOCK_LENGTH bytes of the file	RMint32 IsTransport = 0, n, i;	RMuint32 file = m_CallbackTable.fopen (filename, m_CallbackTable.context);	if (file == 0)		return 0;	RMuint8 *pBuffer = 0;	RMuint32 length = TRANSPORT_BLOCK_LENGTH;	m_CallbackTable.getDetectionBuffer (&pBuffer, &length, m_CallbackTable.context);		ASSERT (pBuffer);	if (pBuffer)	{		n = m_CallbackTable.fread (file, pBuffer, TRANSPORT_BLOCK_LENGTH, m_CallbackTable.context);		RMuint8 *p = pBuffer; 		RMint32 sync_counter = 0;		RMint32 sync_distance = 0;		for (i=0; i<(n - 188); i++)		{			if (*p == 0x47)			{				if ((sync_distance == 0) || (sync_distance == 187))					sync_counter++;				sync_distance = 0;			}			else				sync_distance++;			p++;				}		if (sync_counter >= 5)		{			IsTransport = 1;		}	}	m_CallbackTable.fclose (file, m_CallbackTable.context);	return IsTransport;}#define PROGRAM_BLOCK_LENGTH	(1024*4)RMint32 MPEGDemux::IsProgramStream (RMint8 *filename){	DEBUGMSG (1, ("IsProgramStream (%s)\n", filename));	// we will consider this a program stream if we find 0x000001BA in the first	// PROGRAM_BLOCK_LENGTH bytes of the file.	// Then we will try to detect the pack as a MPEG-2 Pack	RMint32 IsProgram = 0, n, i;	RMuint32 file = m_CallbackTable.fopen (filename, m_CallbackTable.context);	if (file == 0)		return 0;	RMuint8 *pBuffer = 0;	RMuint32 length = PROGRAM_BLOCK_LENGTH;	m_CallbackTable.getDetectionBuffer (&pBuffer, &length, m_CallbackTable.context);	ASSERT (pBuffer);	if (pBuffer)	{		RMint32 j;		j = 0;		while (j++ < 64)		{			n = m_CallbackTable.fread (file, pBuffer, PROGRAM_BLOCK_LENGTH, m_CallbackTable.context);			RMuint8 *p = pBuffer; 			for (i=0; i<(n - 5); i++)			{				if ((p[0] == 0x00) &&					(p[1] == 0x00) &&					(p[2] == 0x01) &&					(p[3] == 0xBA))				{					// for program streams, after the pack start code,					// 01b must be present - this is how we can tell the					// difference between mpeg-2 program streams and mpeg-1 system streams					if ((p[4] & 0xC0) == 0x40)					{						IsProgram = 1;						j = 64;					}					break;				}				p++;					}		}	}	m_CallbackTable.fclose (file, m_CallbackTable.context);	return IsProgram;}#define MPEG1SYSTEM_BLOCK_LENGTH	(1024*4)RMint32 MPEGDemux::IsMPEG1SystemStream (RMint8 *filename){	DEBUGMSG (1, ("IsMPEG1SystemStream (%s)\n", filename));	// we will consider this a program stream if we find 0x000001BA in the first	// PROGRAM_BLOCK_LENGTH bytes of the file.	// Then we will try to detect the pack as a MPEG-1 Pack	RMint32 IsSystem = 0, n, i;	RMuint32 file = m_CallbackTable.fopen (filename, m_CallbackTable.context);	if (file == 0)		return 0;	RMuint8 *pBuffer = 0;	RMuint32 length = PROGRAM_BLOCK_LENGTH;	m_CallbackTable.getDetectionBuffer (&pBuffer, &length, m_CallbackTable.context);	ASSERT (pBuffer);	if (pBuffer)	{		n = m_CallbackTable.fread (file, pBuffer, MPEG1SYSTEM_BLOCK_LENGTH, m_CallbackTable.context);		RMuint8 *p = pBuffer; 		for (i=0; i<(n - 5); i++)		{			if ((p[0] == 0x00) &&				(p[1] == 0x00) &&				(p[2] == 0x01) &&				(p[3] == 0xBA))			{				// for system streams, after the pack start code,				// 0010b must be present - this is how we can tell the				// difference between mpeg-2 program streams and mpeg-1 system streams				if ((p[4] & 0xf0) == 0x20)					IsSystem = 1;				break;			}			p++;				}	}	m_CallbackTable.fclose (file, m_CallbackTable.context);	return IsSystem;}#define DVD_BLOCK_LENGTH	(2048*5)RMint32 MPEGDemux::IsDVDStream (RMint8 *filename){	DEBUGMSG (1, ("IsDVDStream (%s)\n", filename));	// we consider this a DVD stream if there are PACK start codes 2048 bytes	// apart AND the first pack is a Navigation pack	RMint32 IsDVD = 0, n;	RMuint32 file = m_CallbackTable.fopen (filename, m_CallbackTable.context);	if (file == 0)		return 0;	RMuint8 *pBuffer = 0;	RMuint32 length = DVD_BLOCK_LENGTH;	m_CallbackTable.getDetectionBuffer (&pBuffer, &length, m_CallbackTable.context);	ASSERT (pBuffer);	if (pBuffer)	{		DEBUGMSG (1, ("IsDVDStream: m_CallbackTable.fread\n"));		n = m_CallbackTable.fread (file, pBuffer, DVD_BLOCK_LENGTH, m_CallbackTable.context);		RMuint8 *p1 = pBuffer + 0;		RMuint8 *p2 = pBuffer + 2048;		RMuint8 *p3 = pBuffer + 4096;		RMuint8 *p4 = pBuffer + 6144;		RMuint8 *p5 = pBuffer + 8192;		IsDVD = 1;		// must be 5 packs seperated by 2k each		if  (!(			(p1[0] == 0x00) &&

⌨️ 快捷键说明

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