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

📄 avi.cpp

📁 EM8511s中使用的avi播放器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "avi.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 AVI_DEMUX_STATE_CHUNK_NAME_BYTE0		0#define AVI_DEMUX_STATE_CHUNK_NAME_BYTE1		1#define AVI_DEMUX_STATE_CHUNK_NAME_BYTE2		2#define AVI_DEMUX_STATE_CHUNK_NAME_BYTE3		3#define AVI_DEMUX_STATE_CHUNK_LENGTH_BYTE0		4#define AVI_DEMUX_STATE_CHUNK_LENGTH_BYTE1		5#define AVI_DEMUX_STATE_CHUNK_LENGTH_BYTE2		6#define AVI_DEMUX_STATE_CHUNK_LENGTH_BYTE3		7#define AVI_DEMUX_STATE_WRITE_CHUNK				8#define AVI_DEMUX_STATE_RESTORE_STATE			9#define AVI_DEMUX_STATE_INVALID					10#define AVI_MIN(X,Y) (((X)<=(Y))?(X):(Y))	// to find the min between two number.AVIDemux::AVIDemux (){	DEBUGMSG (1, ("AVIDemux::AVIDemux\n"));	m_handle = 0;	m_savedbuf = 0;	m_savedbuflen = 0;	m_savedp = 0;	Init ();}AVIDemux::~AVIDemux (){	DEBUGMSG (1, ("AVIDemux::~AVIDemux\n"));	if (m_handle)	{		ASSERT (m_CallbackTable.fclose);		m_CallbackTable.fclose (m_handle, m_CallbackTable.context);	}}AVI_DEMUX_ERROR AVIDemux::Init (){	DEBUGMSG (1, ("AVIDemux::Init\n"));	if (m_handle)	{		if (m_CallbackTable.fclose)			m_CallbackTable.fclose (m_handle, m_CallbackTable.context);	}	m_CallbackTable.fopen = 0;	m_CallbackTable.fread = 0;	m_CallbackTable.fseek = 0;	m_CallbackTable.fclose = 0;	m_CallbackTable.addref = 0;	m_CallbackTable.release = 0;	m_CallbackTable.info = 0;	m_CallbackTable.putChunk = 0;	m_handle = 0;	m_nStreamHeader = 0;	m_nStreamFormat = 0;	m_moviOffset = 0;	m_sizeOfFile = 0;	m_chunkstart = 0;	m_bytecounter = 0;	RMint32 i;	for (i=0; i<AVI_MAX_STREAMS_SUPPORTED; i++)		m_vbrmp3[i] = 0;	for (i=0; i<AVI_MAX_INDEX_HELPER; i++)	{		m_IndexHelper[i].chunkOffset = 0;		m_IndexHelper[i].indexOffset = 0;		m_IndexHelper[i].videoFrameCount = 0;		for (RMint32 j=0; j<AVI_MAX_STREAMS_SUPPORTED; j++)			m_IndexHelper[i].audioByteOrFrameCount[j] = 0;	}	m_avih.TotalFrames = 0;	m_demuxstate = AVI_DEMUX_STATE_INVALID;	m_idx1Offset = 0;	m_currentFramePosition = 0;	m_KeyFramesOnly = 0;	m_IndexCacheValid = 0;	m_IndexCacheOffset = 0;	m_KeyFrameDelayInMS = 500;	m_IndexIsRelativeToStartOfFile = 0;	return AVI_DEMUX_ERROR_NO_ERROR;}AVI_DEMUX_ERROR AVIDemux::InitCallbackTable (AVI_CALLBACK_TABLE *pCallbackTable){	DEBUGMSG (1, ("AVIDemux::InitCallbackTable\n"));	m_CallbackTable.context = pCallbackTable->context;	m_CallbackTable.fopen = pCallbackTable->fopen;	m_CallbackTable.fread = pCallbackTable->fread;	m_CallbackTable.ftell = pCallbackTable->ftell;	m_CallbackTable.fseek = pCallbackTable->fseek;	m_CallbackTable.fclose = pCallbackTable->fclose;	m_CallbackTable.addref = pCallbackTable->addref;	m_CallbackTable.release = pCallbackTable->release;	m_CallbackTable.info = pCallbackTable->info;	m_CallbackTable.getbuffer = pCallbackTable->getbuffer;	m_CallbackTable.putChunk = pCallbackTable->putChunk;	m_CallbackTable.loading = pCallbackTable->loading;	m_CallbackTable.gettimems = pCallbackTable->gettimems;	return AVI_DEMUX_ERROR_NO_ERROR;}static RMint32 isChar (RMint8 character){	if(((character >= 'a') &&	    (character <= 'z')) ||	   ((character >= 'A') &&	    (character <= 'Z')) ||	   ((character >= '0') &&	    (character <= '9')) ||	   (character == ' '))		return 1;	return 0;}AVI_DEMUX_ERROR AVIDemux::DemuxFile (RMint8 *filename){	ASSERT (m_handle == 0);	ASSERT (m_CallbackTable.fopen);	m_handle = m_CallbackTable.fopen (filename, m_CallbackTable.context);	ASSERT (m_handle);	if (m_handle == 0)	{		DEBUGMSG (1, ("fopen (%s) failed\n", filename));		return AVI_DEMUX_ERROR_NOT_AN_AVI_FILE;	}	AVI_CHUNK chunk;	RMuint32 name;	RMuint32 n;	ASSERT (sizeof(chunk) == 8);	// verify that this is a AVI RIFF file	n = m_CallbackTable.fread (m_handle, &chunk, sizeof(chunk), m_CallbackTable.context);	ASSERT (n == sizeof(chunk));	if (n != sizeof(chunk))	{		m_CallbackTable.fclose (m_handle, m_CallbackTable.context);		m_handle = 0;		DEBUGMSG (1, ("not an AVI RIFF file: too short\n"));		return AVI_DEMUX_ERROR_NOT_AN_AVI_FILE;	}		if (chunk.Name != AVI_FOURCC ('R','I','F','F'))	{		m_CallbackTable.fclose (m_handle, m_CallbackTable.context);		m_handle = 0;		DEBUGMSG (1, ("not an AVI RIFF file: no RIFF header\n"));		return AVI_DEMUX_ERROR_NOT_AN_AVI_FILE;	}	m_RIFFlength = chunk.Length;	RMuint32 rifflength = m_RIFFlength;	ASSERT (sizeof(name) == 4);	// next 4 bytes must be 'AVI '	n = m_CallbackTable.fread (m_handle, &name, sizeof(name), m_CallbackTable.context);	ASSERT (n == sizeof(name));	if (name != AVI_FOURCC('A','V','I',' '))	{		m_CallbackTable.fclose (m_handle, m_CallbackTable.context);		m_handle = 0;		DEBUGMSG (1, ("not an AVI RIFF file: name is not 'AVI '\n"));		return AVI_DEMUX_ERROR_NOT_AN_AVI_FILE;	}	rifflength -= sizeof(name);	ASSERT ((RMint32)rifflength > 0);	RMuint32 listOffset;	RMuint32 subListLength, subChunkLength, position, mainchunkLength;	// actually not the length of the file, but the length of the riff 	// chunk	m_sizeOfFile = rifflength;	ASSERT (m_CallbackTable.loading);	m_CallbackTable.loading (0, m_CallbackTable.context);	// parse all the chunks	while (rifflength > 0)	{		// read the next chunk		rifflength -= sizeof (chunk);		n = m_CallbackTable.fread (m_handle, &chunk, sizeof (chunk), m_CallbackTable.context);		ASSERT (n == sizeof (chunk));			ASSERT (chunk.Length <= rifflength);		if (n == 0)		{			DEBUGMSG (1, ("read error?\n"));			if (m_moviOffset)			{				// ok a movi offset was found, let's do our best to play 				// this file - in anycase, the file is corrupted.				// if an idx1 chunk has not been found, then you won't be				// able to seek or do I frames				rifflength = 0;				continue;			}			// not even a m_moviOffset has been found - abort			return AVI_DEMUX_ERROR_NOT_AN_AVI_FILE;		}		if (((isChar ((RMint8)((chunk.Name >> 24) & 0xff))) == 0) ||			((isChar ((RMint8)((chunk.Name >> 16) & 0xff))) == 0) ||			((isChar ((RMint8)((chunk.Name >>  8) & 0xff))) == 0) ||			((isChar ((RMint8)((chunk.Name >>  0) & 0xff))) == 0))		{			ASSERT (0);			// invalid chunk name			n = m_CallbackTable.ftell (m_handle, m_CallbackTable.context);			m_CallbackTable.fseek (m_handle, n - (sizeof (chunk) - 1), m_CallbackTable.context);			rifflength += (sizeof (chunk) - 1);			continue;		}		switch (chunk.Name)		{		case AVI_FOURCC ('L','I','S','T'):			// this is the main LIST chunk			mainchunkLength = chunk.Length;			DEBUGMSG (1, ("LIST chunk\n"));			listOffset = m_CallbackTable.ftell (m_handle, m_CallbackTable.context);			// we recognize 3 kinds of LIST chunks: 'hdrl', 'strl', amd 'movi'			n = m_CallbackTable.fread (m_handle, &name, sizeof(name), m_CallbackTable.context);			ASSERT (n == sizeof(name));			switch (name)			{			case AVI_FOURCC ('h','d','r','l'):				n = m_CallbackTable.fread (m_handle, &name, sizeof(name), m_CallbackTable.context);				ASSERT (n == sizeof(name));				ASSERT (name == AVI_FOURCC ('a','v','i','h'));				n = m_CallbackTable.fread (m_handle, &subChunkLength, sizeof(subChunkLength), m_CallbackTable.context);				ASSERT (n == sizeof(subChunkLength));				position = m_CallbackTable.ftell (m_handle, m_CallbackTable.context);				ASSERT (subChunkLength >= sizeof(m_avih));				n = m_CallbackTable.fread (m_handle, &m_avih, sizeof(m_avih), m_CallbackTable.context);				ASSERT (n == sizeof (m_avih));				DEBUGMSG (1, ("aviHeader:\n"));				DEBUGMSG (1, (" MicroSecPerFrame: %lu\n", m_avih.MicroSecPerFrame));				DEBUGMSG (1, (" MaxBytesPerSec: %lu\n", m_avih.MaxBytesPerSec));				DEBUGMSG (1, (" Flags: %lu\n", m_avih.Flags));				DEBUGMSG (1, (" TotalFrames: %lu\n", m_avih.TotalFrames));				DEBUGMSG (1, (" InitialFrames: %lu\n", m_avih.InitialFrames));				DEBUGMSG (1, (" Streams: %lu\n", m_avih.Streams));				DEBUGMSG (1, (" SuggestedBufferSize: %lu\n", m_avih.SuggestedBufferSize));				DEBUGMSG (1, (" Width: %lu\n", m_avih.Width));				DEBUGMSG (1, (" Height: %lu\n", m_avih.Height));				DEBUGMSG (1, (" Scale: %lu\n", m_avih.Scale));				DEBUGMSG (1, (" Rate: %lu\n", m_avih.Rate));				DEBUGMSG (1, (" Start: %lu\n", m_avih.Start));				DEBUGMSG (1, (" Length: %lu\n", m_avih.Length));				ASSERT (m_CallbackTable.info);				m_CallbackTable.info (AVI_DEMUX_MSG_AVIHDR, &m_avih, m_CallbackTable.context);				m_CallbackTable.fseek (m_handle, position + subChunkLength, m_CallbackTable.context);				mainchunkLength -= 4;	// for 'hdrl'							mainchunkLength -= (subChunkLength + 8);	// for 'avih'				// XXX to do: handle more than one sublist				while ((RMint32)mainchunkLength > 0)				{					n = m_CallbackTable.fread (m_handle, &name, sizeof(name), m_CallbackTable.context);					ASSERT (n == sizeof(name));										n = m_CallbackTable.fread (m_handle, &subChunkLength, sizeof(subListLength), m_CallbackTable.context);					ASSERT (n == sizeof(subChunkLength));					mainchunkLength -= 8;	// for the header of this subchunk					mainchunkLength -= subChunkLength;	// for this subchunk					if (name == AVI_FOURCC ('L','I','S','T'))					{											subListLength = subChunkLength;						n = m_CallbackTable.fread (m_handle, &name, sizeof(name), m_CallbackTable.context);						ASSERT (n == sizeof(name));						ASSERT (subListLength >= 4);						subListLength -= 4;						if (name == AVI_FOURCC ('s','t','r','l'))						{							while ((RMint32)subListLength > 3)							{															n = m_CallbackTable.fread (m_handle, &name, sizeof(name), m_CallbackTable.context);								subListLength -= 4;								ASSERT (n == sizeof(name));								switch (name)								{								case AVI_FOURCC ('s','t','r','h'):									n = m_CallbackTable.fread (m_handle, &subChunkLength, sizeof(subChunkLength), m_CallbackTable.context);									ASSERT (n == sizeof(subChunkLength));									subListLength -= 4;									position = m_CallbackTable.ftell (m_handle, m_CallbackTable.context);									ASSERT (subChunkLength >= sizeof(AVI_STREAM_HEADER));									n = m_CallbackTable.fread (m_handle, &m_StreamHeaders[m_nStreamHeader], sizeof(AVI_STREAM_HEADER), m_CallbackTable.context);									ASSERT (n == sizeof(AVI_STREAM_HEADER));									ASSERT (m_CallbackTable.info);												DEBUGMSG (1, ("strh:\n"));									DEBUGMSG (1, (" rate: %lu (0x%08lx)\n", 										AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], Rate),										AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], Rate)));									DEBUGMSG (1, (" scale: %lu (0x%08lx)\n", 										AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], Scale),										AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], Scale)));									m_CallbackTable.info (AVI_DEMUX_MSG_STREAMHDR, &m_StreamHeaders[m_nStreamHeader], m_CallbackTable.context);									if (AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], fccType))									{										DEBUGMSG (1, (" fccType: %c%c%c%c\n", 												(RMint8)(AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], fccType) >>  0),												(RMint8)(AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], fccType) >>  8), 												(RMint8)(AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], fccType) >> 16), 												(RMint8)(AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamHeader], fccType) >> 24)));									}									else									{										DEBUGMSG (1, (" fccType: 0000\n"));									}									subListLength -= subChunkLength;									m_CallbackTable.fseek (m_handle, position+subChunkLength, m_CallbackTable.context);									m_nStreamHeader++;									break;								case AVI_FOURCC ('s','t','r','f'):									if (AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], fccType) == AVI_FOURCC('v','i','d','s'))									{										n = m_CallbackTable.fread (m_handle, &subChunkLength, sizeof(subChunkLength), m_CallbackTable.context);										ASSERT (n == sizeof(subChunkLength));										subListLength -= 4;										position = m_CallbackTable.ftell (m_handle, m_CallbackTable.context);										ASSERT (subChunkLength >= sizeof(AVI_BITMAPINFO));										n = m_CallbackTable.fread (m_handle, &m_StreamFormats[m_nStreamFormat], sizeof(AVI_BITMAPINFO), m_CallbackTable.context);										ASSERT (n == sizeof(AVI_BITMAPINFO));										ASSERT (m_CallbackTable.info);										m_CallbackTable.info (AVI_DEMUX_MSG_BITMAPINFO, &m_StreamFormats[m_nStreamFormat], m_CallbackTable.context);										DEBUGMSG (1, ("vids:\n"));										DEBUGMSG (1, (" width: %u\n",m_StreamFormats[m_nStreamFormat].bmi.Width));										DEBUGMSG (1, (" height: %u\n",m_StreamFormats[m_nStreamFormat].bmi.Width));										subListLength -= subChunkLength;										m_CallbackTable.fseek (m_handle, position+subChunkLength, m_CallbackTable.context);									}									else if (AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], fccType) == AVI_FOURCC('a','u','d','s'))									{										n = m_CallbackTable.fread (m_handle, &subChunkLength, sizeof(subChunkLength), m_CallbackTable.context);										ASSERT (n == sizeof(subChunkLength));										subListLength -= 4;										position = m_CallbackTable.ftell (m_handle, m_CallbackTable.context);										ASSERT (subChunkLength >= sizeof(AVI_WAVEFORMATEX));										n = m_CallbackTable.fread (m_handle, &m_StreamFormats[m_nStreamFormat], sizeof(AVI_WAVEFORMATEX), m_CallbackTable.context);										ASSERT (n == sizeof(AVI_WAVEFORMATEX));										ASSERT (m_CallbackTable.info);										m_CallbackTable.info (AVI_DEMUX_MSG_WAVEFORMATEX, &m_StreamFormats[m_nStreamFormat], m_CallbackTable.context);										if ((AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], Scale) == 1152) ||											((AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], Rate) == m_StreamFormats[m_nStreamFormat].wfx.nSamplesPerSec) &&											 (AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], SampleSize) == 0)))										{											DEBUGMSG (1, ("assuming variable bitrate mp3\n"));											m_vbrmp3[m_nStreamFormat] = 1;										}										DEBUGMSG (1, ("auds:\n"));										DEBUGMSG (1, (" formattag: %u\n", m_StreamFormats[m_nStreamFormat].wfx.wFormatTag));										DEBUGMSG (1, (" channels: %u\n", m_StreamFormats[m_nStreamFormat].wfx.nChannels));

⌨️ 快捷键说明

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