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

📄 mp4.cpp

📁 EM8511s中使用的mp4播放器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#include <stdio.h>#include <memory.h>#include <string.h>#include "mp4.h"int gettime ();#if 0#define MP4_ENABLE_DEBUG	1static FILE *f = 0;#ifdef _WIN32#include <windows.h>static void debug_outs (char *szMsg, ...){	char szBuf[256];	wvsprintf (szBuf, szMsg, (LPSTR)(&szMsg + 1));	OutputDebugString (szBuf);}static void debug_break (void) {	_asm int 3;}#else#include <stdio.h>#define debug_outs	printfstatic void debug_break (void) {}#endif#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 MP4_SWAP_ENDIANESS32(x)		(((x & 0x000000ff) << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | ((x & 0xff000000) >> 24))#define MP4_SWAP_ENDIANESS16(x)		(((x & 0x00ff) << 8) | ((x & 0xff00) >> 8))#define MP4_DEMUX_STATE_GET_DATA					0#define MP4_DEMUX_STATE_READ_DATA					1#define MP4_DEMUX_STATE_PARSE_DATA					2#define MP4_DEMUX_STATE_PARSE_CHUNK					3#define MP4_DEMUX_STATE_SEND_DATA					4#define MP4_RANDOM_ACCESS_ONLY						5#define MP4_DEMUX_STATE_END_OF_FILE					6#define MP4_MIN(X,Y) (((X)<=(Y))?(X):(Y))	// to find the min between two number.#define MP4_MAX(X,Y) (((X)>=(Y))?(X):(Y))	// to find the min between two number.MP4Demux::MP4Demux (){}MP4Demux::~MP4Demux (){	if (m_handle)		m_CallbackTable.fclose (m_handle, m_CallbackTable.context);}MP4_ERROR MP4Demux::Init (){	RMint32 i;	m_valid = 0;	m_tmpidx = MP4_MIN_READ_LENGTH;	m_handle = 0;	m_videoDSILength = 0;	for (i=0; i<MP4_MAX_AUDIOTRACKS; i++)		m_audioDSILength[i] = 0;	for (i=0; i<MP4_MAX_SUBPICTRACKS; i++)		m_spDSILength[i] = 0;	m_currentHandlerType = 0;	m_mdatpos = 0;	m_pData = 0;	m_total_chunk_size = 0;	m_samples_per_chunk = 0;		m_chunkTime = 0;	m_video_samples_per_chunk = 0;	m_video_sample_count = 0;	m_videoTime = 0;	m_video_stts_sample_delta_count = 0;	m_video_ctts_sample_delta_count = 0;	m_video_ctts_sample_delta = 0;	for (i=0; i<MP4_MAX_AUDIOTRACKS; i++)	{		m_audio_samples_per_chunk[i] = 0;		m_audio_sample_count[i] = 0;		m_audioTime[i] = 0;		m_audio_stts_sample_delta_count[i] = 0;		m_audio_ctts_sample_delta_count[i] = 0;		m_audio_ctts_sample_delta[i] = 0;	}	for (i=0; i<MP4_MAX_SUBPICTRACKS; i++)	{		m_subpi_samples_per_chunk[i] = 0;		m_subpi_sample_count[i] = 0;		m_subpiTime[i] = 0;		m_subpi_stts_sample_delta_count[i] = 0;		m_subpi_ctts_sample_delta_count[i] = 0;		m_subpi_ctts_sample_delta[i] = 0;	}		m_trackindex = -1;	for (i=0; i<MP4_MAX_TRACKS; i++)	{		m_trackids[i] = 0;		m_tracktimescales[i] = 0;		m_spWidth[i] = 720;		m_spHeight[i] = 480;	}	m_videoTrackIndex = -1;	for (i=0; i<MP4_MAX_AUDIOTRACKS; i++)		m_audioTrackIndex[i] = -1;	for (i=0; i<MP4_MAX_SUBPICTRACKS; i++)		m_subpiTrackIndex[i] = -1;	m_visualHeight = 480;	m_visualWidth = 720;	m_firstVideoChunk = 1;	m_chpl_present = 0;	m_naudioStreams = 0;	m_nspStreams = 0;	m_RandomAccessPointsOnly = 0;	m_next_next_chunk = 0;	m_currentAudioTrack = 0;	m_currentSubpiTrack = 0;	m_skipcount = 0;	m_skipcount_resetvalue = 0;	return MP4_ERROR_NO_ERROR;}MP4_ERROR MP4Demux::InitCallbackTable (MP4_CALLBACK_TABLE *pTable){	m_CallbackTable.context = pTable->context;	m_CallbackTable.fopen = pTable->fopen;	m_CallbackTable.fseek = pTable->fseek;	m_CallbackTable.ftell = pTable->ftell;	m_CallbackTable.fread = pTable->fread;	m_CallbackTable.fclose = pTable->fclose;	m_CallbackTable.addref = pTable->addref;	m_CallbackTable.release = pTable->release;	m_CallbackTable.info = pTable->info;	m_CallbackTable.getData = pTable->getData;	m_CallbackTable.putDSI = pTable->putDSI;	m_CallbackTable.putChunk = pTable->putChunk;	return MP4_ERROR_NO_ERROR;}MP4_ERROR MP4Demux::Demux (RMint8 *filename){	RMint32 i;	ASSERT (m_handle == 0);	DEBUGMSG (1, ("MP4Demux::Demux (%s)\n", filename));	m_handle = m_CallbackTable.fopen (filename, m_CallbackTable.context);	ASSERT (m_handle);	if (m_handle == 0)		return MP4_ERROR_FILE_NOT_FOUND;	while (NextBox (0) == 0);	ASSERT (m_video_stco.IsInitialized ());	ASSERT (m_video_stsz.IsInitialized ());	ASSERT (m_video_stsc.IsInitialized ());	ASSERT (m_audio_stco[0].IsInitialized ());	ASSERT (m_audio_stsz[0].IsInitialized ());	ASSERT (m_audio_stsc[0].IsInitialized ());	RMuint32 video_present, audio_present;	video_present = 		m_video_stco.IsInitialized () &&		m_video_stsz.IsInitialized () &&		m_video_stsc.IsInitialized ();   	audio_present = 		m_audio_stco[0].IsInitialized () &&		m_audio_stsz[0].IsInitialized () &&		m_audio_stsc[0].IsInitialized ();	if ((video_present == 0) && (audio_present == 0))	{		return MP4_ERROR_FILE_NOT_SUPPORTED;	}	m_currentOffset = m_mdatpos;	ASSERT (m_currentOffset);	m_State = MP4_DEMUX_STATE_GET_DATA;	m_CallbackTable.fseek (m_handle, m_mdatpos, SEEK_SET, m_CallbackTable.context);	m_video_chunk_index = 1;	TRACK_TIMESCALE ts;	for (i=0; i<MP4_MAX_AUDIOTRACKS; i++)	{		m_audio_chunk_index[i] = 1;		if (m_audioTrackIndex[i] != -1)			ts.audioTimeScale[i] = m_tracktimescales[m_audioTrackIndex[i]];		else			ts.audioTimeScale[i] = 0;	}	for (i=0; i<MP4_MAX_SUBPICTRACKS; i++)	{		m_subpi_chunk_index[i] = 1;		if (m_subpiTrackIndex[i] != -1)			ts.subpiTimeScale[i] = m_tracktimescales[m_subpiTrackIndex[i]];		else			ts.subpiTimeScale[i] = 0;	}	if (m_videoTrackIndex != -1)		ts.videoTimeScale = m_tracktimescales[m_videoTrackIndex];	else		ts.videoTimeScale = 0;	m_CallbackTable.info (MP4_MSG_TRACK_TIMESCALE, &ts, m_CallbackTable.context);	if (m_videoDSILength)		m_CallbackTable.putDSI (0, 0, m_videoDSI, m_videoDSILength, ts.videoTimeScale/2, m_CallbackTable.context);	for (i=0; i<MP4_MAX_AUDIOTRACKS; i++)	{		if (m_audioDSILength[i])			m_CallbackTable.putDSI (1 | (i << 8), 0, m_audioDSI[i], m_audioDSILength[i], 0, m_CallbackTable.context);	}	for (i=0; i<MP4_MAX_SUBPICTRACKS; i++)	{		if (m_spDSILength[i])		{			SPU_DIMENSIONS spDimensions;			ASSERT (m_subpiTrackIndex[i] != -1);			ASSERT (m_subpiTrackIndex[i] < MP4_MAX_TRACKS);			if (m_subpiTrackIndex[i] != -1)			{				spDimensions.spWidth = m_spWidth[m_subpiTrackIndex[i]];				spDimensions.spHeight = m_spHeight[m_subpiTrackIndex[i]];				m_CallbackTable.info (MP4_MSG_SPU_DIMENSIONS, &spDimensions, m_CallbackTable.context);				m_CallbackTable.putDSI (2 | (i << 8), 0, m_spDSI[i], m_spDSILength[i], 0, m_CallbackTable.context);			}		}		else if (i < m_nspStreams)		{			SPU_DIMENSIONS spDimensions;			spDimensions.spWidth = 0;			spDimensions.spHeight = 0;			m_CallbackTable.info (MP4_MSG_SPU_DIMENSIONS, &spDimensions, m_CallbackTable.context);			m_CallbackTable.putDSI (2 | (i << 8), 0, 0, 0, 0, m_CallbackTable.context);		}	}	if (m_videoDSILength)	{		VIDEO_DIMENSIONS visualDimensions;		visualDimensions.visualWidth = m_visualWidth;		visualDimensions.visualHeight = m_visualHeight;		m_CallbackTable.info (MP4_MSG_VIDEO_DIMENSIONS, &visualDimensions, m_CallbackTable.context);	}	m_firstVideoChunk = 1;	return MP4_ERROR_NO_ERROR;}MP4_ERROR MP4Demux::Schedule (){	RMuint32 error, error0, error1, error2, error3, error4, error5, error6;	switch (m_State)	{	case MP4_DEMUX_STATE_GET_DATA:		ASSERT (m_pData == 0);		if (m_CallbackTable.getData (&m_pData, &m_DataLength, m_CallbackTable.context) == 0)		{			m_CallbackTable.addref (m_pData, m_CallbackTable.context);			m_State = MP4_DEMUX_STATE_READ_DATA;		}		break;	case MP4_DEMUX_STATE_READ_DATA:		ASSERT (m_pData);		ASSERT (m_DataLength);		ASSERT (m_currentOffset == m_CallbackTable.ftell (m_handle, m_CallbackTable.context));		m_mdatLeft = m_mdatpos + m_mdatlength - m_currentOffset;		ASSERT ((RMint32)m_mdatLeft >= 0);		m_DataLength = MP4_MIN (m_DataLength, m_mdatLeft);		m_DataLength = m_CallbackTable.fread (m_handle, m_pData, m_DataLength, m_CallbackTable.context);		DEBUGMSG (0, ("m_DataLength = %d\n", (RMint32)m_DataLength));		DEBUGMSG (0, ("m_mdatLeft = %d\n", (RMint32)m_mdatLeft));		if (m_DataLength)		{			m_pPutData = m_pData;			m_DataLeft = m_DataLength;			if (m_total_chunk_size)				m_State = MP4_DEMUX_STATE_SEND_DATA;			else if (m_samples_per_chunk > 0)				m_State = MP4_DEMUX_STATE_PARSE_CHUNK;			else				m_State = MP4_DEMUX_STATE_PARSE_DATA;		}		else		{			ASSERT (m_pData);			m_CallbackTable.release (m_pData, m_CallbackTable.context);			m_pData = 0;			m_State = MP4_DEMUX_STATE_END_OF_FILE;			return MP4_ERROR_END_OF_FILE;		}		break;	case MP4_DEMUX_STATE_PARSE_DATA:		{			RMuint32 voffset = m_video_stco.get32 (&error0);			// XXX need to change if you want to support more than			// 2 audio or 4 sp streams			RMuint32 aoffset0 = m_audio_stco[0].get32 (&error1);			RMuint32 soffset0 = m_subpi_stco[0].get32 (&error2);			RMuint32 aoffset1 = m_audio_stco[1].get32 (&error3);			RMuint32 soffset1 = m_subpi_stco[1].get32 (&error4);			RMuint32 soffset2 = m_subpi_stco[2].get32 (&error5);			RMuint32 soffset3 = m_subpi_stco[3].get32 (&error6);			if (error0 && error1 && error2 && error3 && error4)				m_State = MP4_DEMUX_STATE_END_OF_FILE;			else if (m_currentOffset == voffset)			{				DEBUGMSG (0, ("voffset: %d\n", (RMint32)voffset));				RMuint32 first_entry;								m_video_stco.advance32 (&error);				m_State = MP4_DEMUX_STATE_PARSE_CHUNK;				first_entry = m_video_stsc.get32 (&error);				if (first_entry == m_video_chunk_index)				{					m_video_stsc.advance32 (&error);					ASSERT (error == 0);					m_video_samples_per_chunk = m_video_stsc.get32 (&error);					ASSERT (error == 0);					DEBUGMSG (0, ("video samples/chunk: %d\n", (RMint32)m_video_samples_per_chunk));					m_video_stsc.advance32 (&error);					ASSERT (error == 0);					m_video_stsc.get32 (&error);					ASSERT (error == 0);					m_video_stsc.advance32 (&error);					ASSERT (error == 0);				}								m_video_chunk_index++;				m_currentID = 0;				m_samples_per_chunk = m_video_samples_per_chunk;				DEBUGMSG (0, ("m_video_samples_per_chunk: %d\n", (RMint32)m_video_samples_per_chunk));				ASSERT (m_samples_per_chunk > 0);			}			else if ((m_currentOffset == aoffset0) || (m_currentOffset == aoffset1))			{				RMuint32 aoffset;				RMint32 ai;				if (m_currentOffset == aoffset0)				{					aoffset = aoffset0;					ai = 0;					m_current_au_index = 0;				}				else				{					aoffset = aoffset1;					ai = 1;					m_current_au_index = 1;				}				DEBUGMSG (0, ("aoffset: %d\n", (RMint32)aoffset));				RMuint32 first_entry;				m_audio_stco[ai].advance32 (&error);				m_State = MP4_DEMUX_STATE_PARSE_CHUNK;				first_entry = m_audio_stsc[ai].get32 (&error);				if (first_entry == m_audio_chunk_index[ai])				{					m_audio_stsc[ai].advance32 (&error);					ASSERT (error == 0);					m_audio_samples_per_chunk[ai] = m_audio_stsc[ai].get32 (&error);					ASSERT (error == 0);					m_audio_stsc[ai].advance32 (&error);					ASSERT (error == 0);					m_audio_stsc[ai].get32 (&error);					ASSERT (error == 0);					m_audio_stsc[ai].advance32 (&error);					ASSERT (error == 0);				}				m_audio_chunk_index[ai]++;				m_currentID = 1 | (ai << 8);				m_samples_per_chunk = m_audio_samples_per_chunk[ai];				DEBUGMSG (0, ("m_audio_samples_per_chunk: %d\n", (RMint32)m_audio_samples_per_chunk));				ASSERT (m_samples_per_chunk > 0);			}			else if ((m_currentOffset == soffset0) || (m_currentOffset == soffset1) ||				(m_currentOffset == soffset2) || (m_currentOffset == soffset3))			{				RMuint32 soffset;				RMint32 si;				if (m_currentOffset == soffset0)				{					soffset = soffset0;					si = 0;					m_current_sp_index = 0;				}				else if (m_currentOffset == soffset1)				{					soffset = soffset1;					si = 1;					m_current_sp_index = 1;				}				else if (m_currentOffset == soffset2)				{					soffset = soffset2;					si = 2;					m_current_sp_index = 2;				}				else if (m_currentOffset == soffset3)				{					soffset = soffset3;					si = 3;					m_current_sp_index = 3;				}				DEBUGMSG (0, ("soffset: %d\n", (RMint32)soffset));				RMuint32 first_entry;

⌨️ 快捷键说明

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