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

📄 vmport.cpp

📁 基于NMS的video access 3.1编写的DEMO程序 实现2个功能 1) H324握手 2) VIDEO MAIL
💻 CPP
字号:
#include "VMPort.h"
#include "routine.h"

int TVMPort::OpenServices(int board, int userid, const char *ip)
{
	CTA_SERVICE_DESC ServDesc[2] = {0};
	CTA_EVENT event;

	ServDesc[0].name.svcname      = "ADI";
	ServDesc[0].name.svcmgrname   = "ADIMGR";
	ServDesc[0].mvipaddr.board    = board;
	ServDesc[0].mvipaddr.stream   = 0;
	ServDesc[0].mvipaddr.timeslot = 0;
	ServDesc[0].mvipaddr.mode     = 0;

	ServDesc[1].name.svcname      = "MSP";
	ServDesc[1].name.svcmgrname   = "MSPMGR";
	ServDesc[0].mvipaddr.board    = board;
	ServDesc[1].mvipaddr.stream   = 0;
	ServDesc[1].mvipaddr.timeslot = 0;
	ServDesc[1].mvipaddr.mode     = 0;

	if(ctaCreateQueue(NULL, 0,  &m_quehd) != 0)
		return -1;

	//初始化video
	if(ctaCreateContext(m_quehd, userid, "vmdemo", &m_VideoCtx.ctahd) != 0)
		return -1;
	if( ctaOpenServices( m_VideoCtx.ctahd, ServDesc, 2) != 0)
		return -1;
	ctaWaitEvent(m_quehd, &event, -1);
	ShowEvent(&event);
	if((event.id != CTAEVN_OPEN_SERVICES_DONE) || (event.value != CTA_REASON_FINISHED))
		return -1;

	//初始化audio
	if(ctaCreateContext(m_quehd, userid/*使用同样的userid*/, "vmdemo", &m_AudioCtx.ctahd) != 0)
		return -1;
	if( ctaOpenServices( m_AudioCtx.ctahd, ServDesc, 2) != 0)
		return -1;
	ctaWaitEvent(m_quehd, &event, -1);
	ShowEvent(&event);
	if((event.id != CTAEVN_OPEN_SERVICES_DONE) || (event.value != CTA_REASON_FINISHED))
		return -1;

	//成功

	m_board = board;
	m_userid = userid;
	strcpy(m_LocalIP, ip);
	return 0;
}

void TVMPort::FreeRes()
{
}

bool TVMPort::StartMSP(int localport, int remoteport)
{
	m_localport = localport;
	m_remoteport = remoteport;

	CreateVideoEp();
	return true;
}

bool TVMPort::StopMSP()
{
	return true;
}

bool TVMPort::CreateVideoEp()
{
	m_vmstate = 0;

	MSP_ENDPOINT_ADDR		addr = {0};
	MSP_ENDPOINT_PARAMETER	parm = {0};

	addr.size             = sizeof MSP_ENDPOINT_ADDR;
	addr.nBoard	          = m_board;
	addr.eEpType          = MSP_ENDPOINT_RTPFDX_VIDEO;

	strcpy(addr.EP.RtpRtcp.SrcIpAddress, m_LocalIP);
	addr.EP.RtpRtcp.nSrcPort = m_localport;
	strcpy(addr.EP.RtpRtcp.DestIpAddress, m_LocalIP);
	addr.EP.RtpRtcp.nDestPort = m_remoteport;

	printf("\t vm(%d) video SrcPort = %d, DestPort = %d\n",
		m_userid,
		addr.EP.RtpRtcp.nSrcPort,
		addr.EP.RtpRtcp.nDestPort
		);

	parm.size				= sizeof(parm);
	parm.eParmType  = MSP_ENDPOINT_RTPFDX_VIDEO;
	parm.EP.RtpRtcp.startRtcp	  = 0;
	parm.EP.RtpRtcp.RtpTsFreq   = 90000;
	parm.EP.RtpRtcp.Session_bw  = 64000;
	parm.EP.RtpRtcp.frameQuota  = 2;
	parm.EP.RtpRtcp.linkEvents  = 0;
	parm.EP.RtpRtcp.PayloadMap.payload_id = 96;
	parm.EP.RtpRtcp.PayloadMap.vocoder    = 100;

	parm.EP.RtpRtcp.dtmf_event_control = 0;

	return 0 == mspCreateEndpoint(m_VideoCtx.ctahd, &addr, &parm, &m_VideoCtx.msphd);
}

bool TVMPort::CreateAudioEp()
{
	m_vmstate++;

	MSP_ENDPOINT_ADDR		addr = {0};
	MSP_ENDPOINT_PARAMETER	parm = {0};

	addr.size       = sizeof MSP_ENDPOINT_ADDR;
	addr.nBoard			= m_board;
	addr.eEpType    = MSP_ENDPOINT_RTPFDX;

	strcpy(addr.EP.RtpRtcp.SrcIpAddress, m_LocalIP);
	addr.EP.RtpRtcp.nSrcPort = m_localport + 2;
	strcpy(addr.EP.RtpRtcp.DestIpAddress, m_LocalIP);
	addr.EP.RtpRtcp.nDestPort =	m_remoteport + 2;

	printf("\t vm(%d) audio SrcPort = %d, DestPort = %d\n",
		m_userid,
		addr.EP.RtpRtcp.nSrcPort,
		addr.EP.RtpRtcp.nDestPort
		);

	parm.size				= sizeof(parm);
	parm.eParmType          = MSP_ENDPOINT_RTPFDX;
	parm.EP.RtpRtcp.startRtcp	= 0;
	parm.EP.RtpRtcp.RtpTsFreq   = 8000;
	parm.EP.RtpRtcp.Session_bw  = 64000;
	parm.EP.RtpRtcp.frameQuota  = 2;
	parm.EP.RtpRtcp.linkEvents  = 0;

	parm.EP.RtpRtcp.PayloadMap.payload_id = MSP_CONST_VOCODER_AMR3267;
	parm.EP.RtpRtcp.PayloadMap.vocoder    = MSP_CONST_VOCODER_AMR3267;

	return 0 == mspCreateEndpoint(m_AudioCtx.ctahd, &addr, &parm, &m_AudioCtx.msphd);
}

void TVMPort::OnMspEvent(CTA_EVENT *pEvent)
{
	switch(m_vmstate)
	{
	case 0:
		//CreateVideoEp();
		CreateAudioEp();
		break;
	case 1:
		mspGetFilterHandle(m_VideoCtx.msphd, MSP_ENDPOINT_RTPFDX_VIDEO, &m_VideoCtx.filterhd);
		mspGetFilterHandle (m_AudioCtx.msphd, MSP_ENDPOINT_RTPFDX, &m_AudioCtx.filterhd);
		break;
	}
}

bool TVMPort::Play3GP(char *filename)
{
	m_VideoCtx.done = false;
	m_AudioCtx.done = false;

	FILE_INFO_DESC fileInfoDesc;
	FILE_INFO_PRESENTATION *pPresentation;
	FILE_INFO_STREAM_AUDIO *pStreamHeader;
	BYTE FileInfo [MAX_FILE_INFO_SIZE];
	int streamCount, infoSizeLeft, blockSize, i;
	BYTE *pFileInfo;
	DWORD ret;

	if( 0 != mmOpenFile(filename, OPEN_MODE_READ, FILE_TYPE_3GP, NULL/*FILE_FORMAT_DESC */, 0/*VERBOSE_INFO_LEVEL*/, &m_mmfile))
		return false;

	fileInfoDesc.fileInfoSize = MAX_FILE_INFO_SIZE;
	fileInfoDesc.pFileInfo = &FileInfo [0];
	if( 0 != mmGetFileInfo(&m_mmfile, &fileInfoDesc))
		return false;

	pFileInfo = fileInfoDesc.pFileInfo;
	infoSizeLeft  = fileInfoDesc.fileInfoSize;
	pPresentation = (FILE_INFO_PRESENTATION *)pFileInfo;
	blockSize     = pPresentation -> blockHeader.blkSize;
	streamCount   = pPresentation -> streamCount;

	pFileInfo    += blockSize;
	infoSizeLeft -= blockSize;

	for (i = 0; i < streamCount; i++)
	{
		blockSize     = ((FILE_INFO_BLOCK_HEADER *)pFileInfo) -> blkSize;
		pStreamHeader = (FILE_INFO_STREAM_AUDIO *)pFileInfo;

		if (pStreamHeader -> header.streamType == STREAM_TYPE_AUDIO)
		{
			m_AudioCtx.codec    = pStreamHeader -> header.codec;
			m_AudioCtx.streamID = pStreamHeader -> header.streamID;
		}
		else if (pStreamHeader-> header.streamType == STREAM_TYPE_VIDEO)
		{
			m_VideoCtx.codec    = pStreamHeader -> header.codec;
			m_VideoCtx.streamID = pStreamHeader -> header.streamID;
		}

		if (infoSizeLeft > 0)
		{
			pFileInfo    += blockSize;
			infoSizeLeft -= blockSize;
		}
	}

	DATA_FORMAT_DESC dataFormatDesc = {0};
	DATA_FORMAT_INFO dataFormatInfo;

	//open video stream
	dataFormatDesc.flags |= FORMAT_FLAG_MEM_CHUNKS; //多个内存块
	if( 0 != mmOpenStream(&m_mmfile, m_VideoCtx.streamID, STREAM_TYPE_VIDEO, m_VideoCtx.codec, &dataFormatDesc, &m_VideoCtx.mmstream, &dataFormatInfo))
		return false;
	printf("\t video estTotalStreamSize = %d minReadBufferSize = %d\n", dataFormatInfo.estTotalStreamSize, dataFormatInfo.minReadBufferSize);

	unsigned videobytes;
	int videoflag = 0;
	ret = mmReadStream (&m_VideoCtx.mmstream, SAMPLE_COUNT_MAX, (BYTE *)m_VideoCtx.playbuffer, MAX_BUFFER_SIZE, &videobytes);
	if( ret == MMERR_END_OF_STREAM)
		videoflag = ADI_PLAY_LAST_BUFFER;

	printf("\t videobytes = %d\n", videobytes);

	//open audio stream
	dataFormatDesc.flags |= FORMAT_FLAG_MEM_CHUNKS; //多个内存块
	if( 0 != mmOpenStream(&m_mmfile, m_AudioCtx.streamID, STREAM_TYPE_AUDIO, m_AudioCtx.codec, &dataFormatDesc, &m_AudioCtx.mmstream, &dataFormatInfo))
		return false;
	printf("\t audio estTotalStreamSize = %d minReadBufferSize = %d\n", dataFormatInfo.estTotalStreamSize, dataFormatInfo.minReadBufferSize);

	unsigned audiobytes;
	int audioflag = 0;
	ret = mmReadStream (&m_AudioCtx.mmstream, SAMPLE_COUNT_MAX, (BYTE *)m_AudioCtx.playbuffer, MAX_BUFFER_SIZE, &audiobytes);
	if( ret == MMERR_END_OF_STREAM)
		audioflag = ADI_PLAY_LAST_BUFFER;

	printf("\t audiobytes = %d\n", audiobytes);

	//video play
	if( 0 != adiPlayMMAsync(m_VideoCtx.ctahd, ADI_ENCODE_NATIVE_H_263P, m_VideoCtx.playbuffer, videobytes,
		videoflag,
		m_VideoCtx.filterhd, NULL))
	{
		return false;
	}

	//audio play
	if( 0 != adiPlayMMAsync(m_AudioCtx.ctahd, ADI_ENCODE_NATIVE_AMRNB, m_AudioCtx.playbuffer, audiobytes,
		audioflag,
		m_AudioCtx.filterhd, NULL) )
	{
		return false;
	}

	return true;
}

bool TVMPort::StopRP()
{
	//ADI_RECORD_STATUS recordstatus;
	//adiGetRecordStatus(m_VideoCtx.ctahd, &recordstatus, sizeof recordstatus );
	//if(recordstatus.reason == 0) //reason = 0, mean active
		adiStopRecording(m_VideoCtx.ctahd);

	//ADI_PLAY_STATUS playstatus;
	//adiGetPlayStatus(m_VideoCtx.ctahd, &playstatus, sizeof playstatus );
	//if(playstatus.reason == 0) //reason = 0, mean active
		adiStopPlaying(m_VideoCtx.ctahd);


	adiStopPlaying(m_AudioCtx.ctahd);
	return true;
}

bool TVMPort::ContinuePlay(CTA_EVENT *pEvent)
{
	DWORD ret;

	if(pEvent->ctahd == m_VideoCtx.ctahd)
	{
		unsigned videobytes;
		int videoflag = 0;
		ret = mmReadStream (&m_VideoCtx.mmstream, SAMPLE_COUNT_MAX, (BYTE *)m_VideoCtx.playbuffer, MAX_BUFFER_SIZE, &videobytes);
		if( ret == MMERR_END_OF_STREAM)
			videoflag = ADI_PLAY_LAST_BUFFER;
		printf("\t videobytes = %d\n", videobytes);

		return 0 == adiSubmitPlayBuffer(m_VideoCtx.ctahd, m_VideoCtx.playbuffer, videobytes, videoflag);
	}
	else if(pEvent->ctahd == m_AudioCtx.ctahd)
	{
		int audioflag = 0;
		unsigned audiobytes;
		ret = mmReadStream (&m_AudioCtx.mmstream, SAMPLE_COUNT_MAX, (BYTE *)m_AudioCtx.playbuffer, MAX_BUFFER_SIZE, &audiobytes);
		if( ret == MMERR_END_OF_STREAM)
			audioflag = ADI_PLAY_LAST_BUFFER;

		printf("\t audiobytes = %d\n", audiobytes);
		return 0 == adiSubmitPlayBuffer(m_AudioCtx.ctahd, m_AudioCtx.playbuffer, audiobytes, audioflag);
	}

	return false;
}

void TVMPort::OnPlayDone(CTA_EVENT *pEvent)
{
	if(pEvent->ctahd == m_VideoCtx.ctahd)
		m_VideoCtx.done = true;
	else if(pEvent->ctahd == m_AudioCtx.ctahd)
		m_AudioCtx.done = true;

	if(m_VideoCtx.done && m_AudioCtx.done)
		mmCloseFile(&m_mmfile);
}

void TVMPort::OnRecordDone(CTA_EVENT *pEvent)
{
	OnPlayDone(pEvent);
}

bool TVMPort::Record3GP(char *filename)
{
	m_VideoCtx.done = false;
	m_AudioCtx.done = false;

	ADI_MM_RECORD_PARMS  recParms;

	if( 0 != mmOpenFile (filename, OPEN_MODE_WRITE, FILE_TYPE_3GP, NULL, VERBOSE_INFO_LEVEL, &m_mmfile))
		return false;

	DATA_FORMAT_DESC dataFormatDesc = {0};

//video
	m_VideoCtx.codec = S_CODEC_H263;
	dataFormatDesc.flags |= FORMAT_FLAG_MEM_CHUNKS;
	dataFormatDesc.videoLevel   = 10;
	dataFormatDesc.videoProfile = 0;

	if( 0 != mmOpenStream(&m_mmfile, NULL, STREAM_TYPE_VIDEO, m_VideoCtx.codec, &dataFormatDesc,
		&m_VideoCtx.mmstream, NULL) )
	{
		return false;
	}

	ctaGetParms (m_VideoCtx.ctahd, ADI_RECORD_PARMID, &recParms, sizeof (ADI_MM_RECORD_PARMS));
	recParms.novideotime = 0;
	recParms.novoicetime = 0;
	recParms.videotimeout = 0;
	recParms.silencetime = 0;
	recParms.startonvideoIframe = 1;

	if( 0 != adiRecordMMAsync(m_VideoCtx.ctahd, ADI_ENCODE_NATIVE_H_263P, m_VideoCtx.recordbuffer, MAX_BUFFER_SIZE, m_VideoCtx.filterhd, m_AudioCtx.filterhd, &recParms))
	{
		return false;
	}

//audio
	m_AudioCtx.codec = S_CODEC_AMR;
	memset(&dataFormatDesc, 0 , sizeof(dataFormatDesc));
	dataFormatDesc.flags |= FORMAT_FLAG_MEM_CHUNKS;

	if( 0 != mmOpenStream(&m_mmfile, NULL, STREAM_TYPE_AUDIO, m_AudioCtx.codec, &dataFormatDesc,
		&m_AudioCtx.mmstream, NULL) )
	{
		return false;
	}

	if( 0 != adiRecordMMAsync(m_AudioCtx.ctahd, ADI_ENCODE_NATIVE_AMRNB, m_AudioCtx.recordbuffer, MAX_BUFFER_SIZE, m_VideoCtx.filterhd, m_AudioCtx.filterhd, &recParms))
	{
		return false;
	}

	return true;
}

bool TVMPort::ContinueRecord(CTA_EVENT *pEvent)
{
	printf("\t ContinueRecord\n");

	unsigned byteCountRec;

	switch(pEvent->id)
	{
	case ADIEVN_RECORD_STARTED:
		if(pEvent->ctahd == m_VideoCtx.ctahd)
			 return 0 == adiSubmitRecordBuffer(m_VideoCtx.ctahd, m_VideoCtx.recordbuffer, MAX_BUFFER_SIZE);
		else if(pEvent->ctahd == m_AudioCtx.ctahd)
			 return 0 == adiSubmitRecordBuffer(m_AudioCtx.ctahd, m_AudioCtx.recordbuffer, MAX_BUFFER_SIZE);
		break;

	case ADIEVN_RECORD_BUFFER_FULL:
		if(pEvent->ctahd == m_VideoCtx.ctahd)
		{
			mmWriteStream(&m_VideoCtx.mmstream, (BYTE *)pEvent->buffer, pEvent->size,
				NULL,  &byteCountRec,  NULL,  NULL);
			adiSubmitRecordBuffer(m_VideoCtx.ctahd, m_VideoCtx.recordbuffer, MAX_BUFFER_SIZE);
		}
		else if(pEvent->ctahd == m_AudioCtx.ctahd)
		{
			mmWriteStream(&m_AudioCtx.mmstream, (BYTE *)pEvent->buffer, pEvent->size,
				NULL,  &byteCountRec,  NULL,  NULL);
			adiSubmitRecordBuffer(m_AudioCtx.ctahd, m_AudioCtx.recordbuffer, MAX_BUFFER_SIZE);
		}
		break;
	}

	return true;
}

⌨️ 快捷键说明

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