请教一个win32 下的c++缓存队列的例子

shiter
人工智能领域优质创作者
博客专家认证
2016-03-10 11:34:57
请教一个win32 下的c++缓存队列的例子,

我想弄一个直播流,encoding好了放到缓存里面,是h264的流,完后搞成rtmp直播出去


不知道使用缓存队列是否正确,想求个例子,网上怎么这个很少都是消息队列
...全文
202 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
shiter 2016-04-05
  • 打赏
  • 举报
回复
#include "stdafx.h"
#include "CircleBuffer.h"
#include "assert.h"

#define CIC_WAITTIMEOUT  3000

CPs_CircleBuffer::CPs_CircleBuffer(const unsigned int iBufferSize)
{
	m_iBufferSize = iBufferSize;
	m_pBuffer = (unsigned char*)malloc(iBufferSize);
	m_iReadCursor = 0;
	m_iWriteCursor = 0;
	m_bComplete = false;
	m_evtDataAvailable = CreateEvent(NULL, FALSE, FALSE, NULL);
}

CPs_CircleBuffer::~CPs_CircleBuffer()
{
	Uninitialise();
}

// Public functions
void CPs_CircleBuffer::Uninitialise()//没有必要public这个接口函数,long120817
{
	CloseHandle(m_evtDataAvailable);
	free(m_pBuffer);
}

//Write前一定要调用m_pCircleBuffer->GetFreeSize(),如果FreeSize不够需要等待,long120817

void  CPs_CircleBuffer::Write(const void* _pSourceBuffer, const unsigned int _iNumBytes)
{
	unsigned int iBytesToWrite = _iNumBytes;
	unsigned char* pSourceReadCursor = (unsigned char*)_pSourceBuffer;

	//CP_ASSERT(iBytesToWrite <= GetFreeSize());//修改为没有足够空间就返回,write前一定要加GetFreeSize判断,否则进入到这里相当于丢掉数据,         // long120817
	if (iBytesToWrite > GetFreeSize())
	{
		return;
	}
	//_ASSERT(m_bComplete == false);

	m_csCircleBuffer.Lock();

	if (m_iWriteCursor >= m_iReadCursor)
	{
		//              0                                            m_iBufferSize
		//              |-----------------|===========|--------------|
		//                                pR->        pW-> 
		// 计算尾部可写空间iChunkSize,long120817
		unsigned int iChunkSize = m_iBufferSize - m_iWriteCursor;

		if (iChunkSize > iBytesToWrite)
		{
			iChunkSize = iBytesToWrite;
		}

		// Copy the data
		memcpy(m_pBuffer + m_iWriteCursor,pSourceReadCursor, iChunkSize);

		pSourceReadCursor += iChunkSize;

		iBytesToWrite -= iChunkSize;

		// 更新m_iWriteCursor
		m_iWriteCursor += iChunkSize;

		if (m_iWriteCursor >= m_iBufferSize)//如果m_iWriteCursor已经到达末尾
			m_iWriteCursor -= m_iBufferSize;//返回到起点0位置,long120817

	}

	//剩余数据从Buffer起始位置开始写
	if (iBytesToWrite)
	{
		memcpy(m_pBuffer + m_iWriteCursor,pSourceReadCursor, iBytesToWrite);
		m_iWriteCursor += iBytesToWrite;
		//_ASSERT(m_iWriteCursor < m_iBufferSize);//这个断言没什么意思,应该_ASSERT(m_iWriteCursor <= m_iReadCursor);long20120817
	}

	SetEvent(m_evtDataAvailable);//设置数据写好信号量

	m_csCircleBuffer.UnLock();
}

bool  CPs_CircleBuffer::Read(void* pDestBuffer, const size_t _iBytesToRead, size_t* pbBytesRead)
{
	size_t iBytesToRead = _iBytesToRead;
	size_t iBytesRead = 0;
	DWORD dwWaitResult;
	bool bComplete = false;

	while (iBytesToRead > 0 && bComplete == false)
	{
		dwWaitResult = WaitForSingleObject(m_evtDataAvailable, CIC_WAITTIMEOUT);//等待数据写好,long120817

		if (dwWaitResult == WAIT_TIMEOUT)
		{
			//TRACE_INFO2("Circle buffer - did not fill in time!");
			*pbBytesRead = iBytesRead;
			return FALSE;//等待超时则返回
		}

		m_csCircleBuffer.Lock();

		if (m_iReadCursor > m_iWriteCursor)
		{
			//              0                                                    m_iBufferSize
			//              |=================|-----|===========================|
			//                                pW->  pR-> 
			unsigned int iChunkSize = m_iBufferSize - m_iReadCursor;

			if (iChunkSize > iBytesToRead)
				iChunkSize = (unsigned int)iBytesToRead;

			//读取操作
			memcpy((unsigned char*)pDestBuffer + iBytesRead,m_pBuffer + m_iReadCursor,iChunkSize);

			iBytesRead += iChunkSize;
			iBytesToRead -= iChunkSize;

			m_iReadCursor += iChunkSize;

			if (m_iReadCursor >= m_iBufferSize)//如果m_iReadCursor已经到达末尾
				m_iReadCursor -= m_iBufferSize;//返回到起点0位置,long120817
		}

		if (iBytesToRead && m_iReadCursor < m_iWriteCursor)
		{
			unsigned int iChunkSize = m_iWriteCursor - m_iReadCursor;

			if (iChunkSize > iBytesToRead)
				iChunkSize = (unsigned int)iBytesToRead;

			//读取操作
			memcpy((unsigned char*)pDestBuffer + iBytesRead,m_pBuffer + m_iReadCursor,iChunkSize);

			iBytesRead += iChunkSize;
			iBytesToRead -= iChunkSize;
			m_iReadCursor += iChunkSize;
		}

		//如果有更多的数据要写
		if (m_iReadCursor == m_iWriteCursor)
		{
			if (m_bComplete)//跳出下一个while循环,该值通过SetComplete()设置,此逻辑什么意思?long120817
				bComplete = true;
		}
		else//还有数据可以读,SetEvent,在下一个while循环开始可以不用再等待,long120817
			SetEvent(m_evtDataAvailable);

		m_csCircleBuffer.UnLock();
	}

	*pbBytesRead = iBytesRead;

	return bComplete ? false : true;

}
//  0                                                m_iBufferSize
//  |------------------------------------------------|
//  pR
//  pW
//读写指针归零
void  CPs_CircleBuffer::Flush()
{
	m_csCircleBuffer.Lock();
	m_iReadCursor = 0;
	m_iWriteCursor = 0;
	m_csCircleBuffer.UnLock();

}
//获取已经写的内存
unsigned int CPs_CircleBuffer::GetUsedSize()
{
	return m_iBufferSize - GetFreeSize();

}


unsigned int CPs_CircleBuffer::GetFreeSize()
{
	unsigned int iNumBytesFree;

	m_csCircleBuffer.Lock();

	if (m_iWriteCursor < m_iReadCursor)
	{
		//              0                                                    m_iBufferSize
		//              |=================|-----|===========================|
		//                                pW->  pR-> 
		iNumBytesFree = (m_iReadCursor - 1) - m_iWriteCursor;
	}
	else if (m_iWriteCursor == m_iReadCursor)
	{
		iNumBytesFree = m_iBufferSize;
	}
	else
	{
		//              0                                                    m_iBufferSize
		//              |-----------------|=====|---------------------------|
		//                                pR->   pW-> 
		iNumBytesFree = (m_iReadCursor - 1) + (m_iBufferSize - m_iWriteCursor);
	}

	m_csCircleBuffer.UnLock();

	return iNumBytesFree;

}
//该函数什么时候调用?long120817
void  CPs_CircleBuffer::SetComplete()
{
	m_csCircleBuffer.Lock();
	m_bComplete = true;
	SetEvent(m_evtDataAvailable);
	m_csCircleBuffer.UnLock();
}


#ifndef CIRCLE_BUFFER
#define  CIRCLE_BUFFER

#define CIC_READCHUNKSIZE 1024*16

#ifdef WIN32
#include <windows.h>

#define  V_MUTEX			CRITICAL_SECTION //利用临界区实现的锁变量
#define  V_MUTEX_INIT(m)		InitializeCriticalSection(m)
#define  V_MUTEX_LOCK(m)		EnterCriticalSection(m)
#define  V_MUTEX_UNLOCK(m)		LeaveCriticalSection(m)
#define  V_MUTEX_DESTORY(m)		DeleteCriticalSection(m)

#else

#define  V_MUTEX				pthread_mutex_t
#define  V_MUTEX_INIT(m)		pthread_mutex_init(m,NULL)
#define  V_MUTEX_LOCK(m)		pthread_mutex_Lock(m)
#define  V_MUTEX_UNLOCK(m)		pthread_mutex_unLock(m)
#define  V_MUTEX_DESTORY(m)		pthread_mutex_destroy(m)

#endif


class  Vlock
{
public:
	Vlock(void)
	{
		V_MUTEX_INIT(&m_Lock);
	}
	~Vlock(void)
	{
		V_MUTEX_DESTORY(&m_Lock);
	}
public:
	void Lock(){V_MUTEX_LOCK(&m_Lock);}
	void UnLock(){V_MUTEX_UNLOCK(&m_Lock);}
private:
	V_MUTEX m_Lock;
};


class  CPs_CircleBuffer
{
public:
	CPs_CircleBuffer(const unsigned int iBufferSize);
	~CPs_CircleBuffer();
public:
	// Public functions
	void  Uninitialise();
	void  Write(const void* pSourceBuffer, const unsigned int iNumBytes);
	bool  Read(void* pDestBuffer, const size_t iBytesToRead, size_t* pbBytesRead);
	void  Flush();
	unsigned int GetUsedSize();
	unsigned int GetFreeSize();
	void  SetComplete();
	bool  IsComplete();

private:       
	unsigned char*	m_pBuffer;
	unsigned int	m_iBufferSize;
	unsigned int	m_iReadCursor;
	unsigned int	m_iWriteCursor;
	HANDLE			m_evtDataAvailable;
	Vlock			m_csCircleBuffer;
	bool			m_bComplete;      
};



//
//1、创建对象
//	CPs_CircleBuffer* m_pCircleBuffer;
//m_pCircleBuffer = new CPs_CircleBuffer(bufsize);
//	2、写
//	if (m_pCircleBuffer->GetFreeSize() < CIC_READCHUNKSIZE)
//	{
//		Sleep(20);
//		continue;
//	}
//	m_pCircleBuffer->Write(internetbuffer.lpvBuffer,internetbuffer.dwBufferLength);
//	3、读
//		m_pCircleBuffer->Read(pDestBuffer,iBytesToRead, piBytesRead);
//
//	4、其他调用
//		if(m_pCircleBuffer->IsComplete())
//			break;        
//	iUsedSpace =m_pCircleBuffer->GetUsedSize();
//	m_pCircleBuffer->SetComplete();
//
//
//
#endif

自己找了一个,很好用
赵4老师 2016-03-14
  • 打赏
  • 举报
回复
引用 7 楼 wangyaninglm 的回复:
[quote=引用 5 楼 zhao4zhong1 的回复:] 我就不贴我那段代码占地方了。
奥,那个写log 的,CRITICAL_SECTION的性能咋样。。。适合视频缓冲么[/quote] 试了才会知道。
shiter 2016-03-12
  • 打赏
  • 举报
回复
引用 5 楼 zhao4zhong1 的回复:
我就不贴我那段代码占地方了。
奥,那个写log 的,CRITICAL_SECTION的性能咋样。。。适合视频缓冲么
赵4老师 2016-03-11
  • 打赏
  • 举报
回复
我就不贴我那段代码占地方了。
shenyi0106 2016-03-11
  • 打赏
  • 举报
回复
推荐你看一下linux内核中的kfifo,这是一个环形缓冲区,稳定性是不用怀疑的,只是效率可能要差一些,因为它的操作的都是copy的
shenyi0106 2016-03-11
  • 打赏
  • 举报
回复
最主要的是,非常简单,就几十行代码
孤客天涯 2016-03-11
  • 打赏
  • 举报
回复
这种队列很多呀,CList,CPtrList等等,都可以用
oyljerry 2016-03-11
  • 打赏
  • 举报
回复
http://www.docin.com/p-1270443930.html
shiter 2016-03-10
  • 打赏
  • 举报
回复
主要是求一个win32 下的c++缓存队列的例子

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧