Selaa lähdekoodia

#IQBX #comment libaudioqueue 编译通过

80374374 1 vuosi sitten
vanhempi
sitoutus
ae2ed1fb3d

+ 3 - 0
Other/win/CMakeLists.txt

@@ -13,6 +13,9 @@ add_subdirectory(libbizchan)
 add_subdirectory(libimgplayer)
 add_subdirectory(libwmpplayer)
 add_subdirectory(libmediaplayer)
+add_subdirectory(libaudioqueue)
+# lack of SDL
+# add_subdirectory(libpictureplayer)
 
 # 汇总要依赖拷贝的第三方库
 set(RVC_CONAN_DEP_LIBS ${RVC_CONAN_DEP_LIBS} ${OTHER_CONAN_DEP_LIBS} PARENT_SCOPE)

+ 64 - 0
Other/win/libaudioqueue/CMakeLists.txt

@@ -0,0 +1,64 @@
+set(MODULE_NAME "audioqueue")
+set(MODULE_PREFIX "LIB_AUDIOQUEUE_FUNC")
+
+
+#if(RVC_DEBUG_MODE)
+#    set(SPBASE_LIB spbased)
+#else()
+#    set(SPBASE_LIB spbase)
+#endif(RVC_DEBUG_MODE)
+
+if(MSVC)
+    set(STDAFXCPP stdafx.cpp)
+else()
+	 set(STDAFXCPP )
+endif(MSVC)
+
+set(${MODULE_PREFIX}_SRCS
+    libaudioqueue.h
+	#dllmain.cpp
+    libaudioqueue.cpp
+	${STDAFXCPP}
+)
+
+add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
+
+if(MSVC)
+add_precompiled_header(${MODULE_NAME} stdafx.h SOURCE_CXX stdafx.cpp FORCEINCLUDE)
+endif(MSVC)
+
+target_include_directories(${MODULE_NAME} PRIVATE
+	"${CONAN_RVCFRAMEWORK_ROOT}/include"
+	${RVC_COMMON_INCLUDE_DIR}
+	${OTHER_LIB_PLATFORM_BASE_DIR}/libsharememory
+	)
+
+message(STATUS "rvc common include dir is ${RVC_COMMON_INCLUDE_DIR}")
+
+target_link_directories(${MODULE_NAME} PRIVATE
+	${CONAN_LIB_DIRS_RVCFRAMEWORK}
+	)
+
+target_link_libraries(${MODULE_NAME} PRIVATE ${${MODULE_PREFIX}_LIBS}	
+	#${SPBASE_LIB}
+	sharememory
+	)  
+
+
+target_compile_definitions(${MODULE_NAME} PUBLIC "LIBAUDIOQUEUE_EXPORTS")
+
+if(MSVC)
+	install(TARGETS ${MODULE_NAME} 
+    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}" COMPONENT libraries
+    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT develops EXCLUDE_FROM_ALL
+    LIBRARY DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT libraries
+    )
+else()
+install(TARGETS ${MODULE_NAME} 
+    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}"
+    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}"
+    LIBRARY DESTINATION "${RVC_RUNTIME_PATH}"
+    COMPONENT libraries)
+endif(MSVC)
+
+set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "other/")

+ 36 - 0
Other/win/libaudioqueue/ReadMe.txt

@@ -0,0 +1,36 @@
+========================================================================
+    动态链接库:libaudioqueue 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 libaudioqueue DLL。
+
+本文件概要介绍组成 libaudioqueue 应用程序的每个文件的内容。
+
+
+libaudioqueue.vcxproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 
+    的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+libaudioqueue.vcxproj.filters
+    这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。 
+    它包含有关项目文件与筛选器之间的关联信息。 在 IDE 
+    中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。
+    例如,“.cpp”文件与“源文件”筛选器关联。
+
+libaudioqueue.cpp
+    这是主 DLL 源文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h,StdAfx.cpp
+    这些文件用于生成名为 libaudioqueue.pch 的预编译头 (PCH) 文件和
+    名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 19 - 0
Other/win/libaudioqueue/dllmain.cpp

@@ -0,0 +1,19 @@
+// dllmain.cpp : 定义 DLL 应用程序的入口点。
+#include "stdafx.h"
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+                       DWORD  ul_reason_for_call,
+                       LPVOID lpReserved
+					 )
+{
+	switch (ul_reason_for_call)
+	{
+	case DLL_PROCESS_ATTACH:
+	case DLL_THREAD_ATTACH:
+	case DLL_THREAD_DETACH:
+	case DLL_PROCESS_DETACH:
+		break;
+	}
+	return TRUE;
+}
+

+ 428 - 0
Other/win/libaudioqueue/libaudioqueue.cpp

@@ -0,0 +1,428 @@
+// libaudioqueue.cpp : 定义 DLL 应用程序的导出函数。
+//
+
+#include "stdafx.h"
+#include "libaudioqueue.h"
+#include "libsharememory.h"
+#include <windows.h>
+
+
+typedef struct  Qnode
+{
+	unsigned int videoframeindex;
+	unsigned int nextqnodeindex;
+}Qnode, *queueptr;
+
+typedef struct linkqueue
+{
+	unsigned int frontindex;
+	unsigned int rearindex;
+	unsigned int queuelens;
+}linkqueue;
+
+class libaudioqueue_impl
+{
+private:
+		Clibsharememory m_ShareMem;
+		LPVOID m_lpMem;
+		linkqueue*m_pQueue;
+		int m_nQueueAddrLens;
+		int m_nQnodeAddrLens;
+		int m_nFrameAddrLens;
+		int m_nDataAddrlens;
+		LPCTSTR szShareMemName;
+		unsigned long aQnodeAddr[MAX_AUDIOQUEUE_LENS];
+		unsigned long aAudioFrameAddr[MAX_AUDIOQUEUE_LENS];
+		unsigned long aAudioDataAddr[MAX_AUDIOQUEUE_LENS];
+public:
+	libaudioqueue_impl(LPCTSTR audioqueuename,int framesize=MAX_AUDIOQNODE_SIZE)
+	{
+		m_lpMem = NULL;
+		m_pQueue = NULL;
+		szShareMemName = NULL;
+		m_nQueueAddrLens = 0;
+		m_nQnodeAddrLens = 0;
+		m_nFrameAddrLens = 0;
+		m_nDataAddrlens = 0;
+		for(int i=0;i<MAX_AUDIOQUEUE_LENS;i++)
+		{
+			aQnodeAddr[i] = 0;
+			aAudioFrameAddr[i] = 0;
+			aAudioDataAddr[i] = 0;
+		}
+		InitQueue(audioqueuename,framesize);
+	}
+
+	~libaudioqueue_impl()
+	{
+		ClearAudioQueue();
+	}
+
+	//初始化队列
+	bool InitQueue(LPCTSTR szName,int framesize=MAX_AUDIOQNODE_SIZE)
+	{
+		m_nQueueAddrLens = sizeof(linkqueue);
+		m_nQnodeAddrLens = MAX_AUDIOQUEUE_LENS*sizeof(Qnode);
+		m_nFrameAddrLens = MAX_AUDIOQUEUE_LENS*sizeof(audio_frame);
+		m_nDataAddrlens	= MAX_AUDIOQUEUE_LENS*framesize;
+		int nMemTotalNum = m_nQueueAddrLens+m_nQnodeAddrLens+m_nFrameAddrLens+m_nDataAddrlens;
+		if (m_ShareMem.Create(szName,nMemTotalNum)&&(m_nDataAddrlens!=0))
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				memset(m_lpMem,0,nMemTotalNum);
+				m_pQueue = (linkqueue *)m_lpMem;
+				for(int i =0;i<MAX_AUDIOQUEUE_LENS;i++)
+				{
+					aQnodeAddr[i] = (unsigned long)m_pQueue+m_nQueueAddrLens+sizeof(Qnode)*i;
+					aAudioFrameAddr[i] = (unsigned long)m_pQueue+m_nQueueAddrLens+m_nQnodeAddrLens+sizeof(audio_frame)*i;
+					aAudioDataAddr[i] = (unsigned long)m_pQueue+m_nQueueAddrLens+m_nQnodeAddrLens+m_nFrameAddrLens+framesize*i;
+				}
+				m_pQueue->frontindex = m_pQueue->rearindex = 0;
+				m_pQueue->queuelens = 0;
+				m_ShareMem.Unlock();
+			}
+
+		} 
+		else if(m_ShareMem.Open(szName))
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				m_pQueue = (linkqueue *)m_lpMem;
+				for(int i =0;i<MAX_AUDIOQUEUE_LENS;i++)
+				{
+					aQnodeAddr[i] = (unsigned long)m_pQueue+m_nQueueAddrLens+sizeof(Qnode)*i;
+					aAudioFrameAddr[i] = (unsigned long)m_pQueue+m_nQueueAddrLens+m_nQnodeAddrLens+sizeof(audio_frame)*i;
+					aAudioDataAddr[i] = (unsigned long)m_pQueue+m_nQueueAddrLens+m_nQnodeAddrLens+m_nFrameAddrLens+framesize*i;
+				}
+				m_ShareMem.Unlock();
+			}
+		}
+		return true;
+	}
+	//返回队列的元素个数,音频队列长度
+	int GetAudioLens()
+	{
+		if(m_ShareMem.IsValid())
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				int num = m_pQueue->queuelens;
+				m_ShareMem.Unlock();
+				return num;
+			}
+			else
+			{
+				return 0;
+			}
+		}
+		else
+		{
+			return 0;
+		}
+	}
+	//往音频循环队列尾部插节点
+	bool InsertAudio(audio_frame* Audio)
+	{
+		if(m_ShareMem.IsValid())
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				unsigned int nRearNextIndex = 0;
+				//保存当前对位指针的序列号
+				queueptr rearptrfront = (queueptr)aQnodeAddr[m_pQueue->rearindex];
+				//如果队列已满
+				if(m_pQueue->queuelens == MAX_AUDIOQUEUE_LENS)
+				{
+					m_pQueue->rearindex = (m_pQueue->rearindex+1)%MAX_AUDIOQUEUE_LENS;
+					m_pQueue->frontindex = (m_pQueue->frontindex+1)%MAX_AUDIOQUEUE_LENS;
+					m_pQueue->queuelens = MAX_AUDIOQUEUE_LENS;
+				}
+				else if (m_pQueue->queuelens == 0)
+				{
+					m_pQueue->rearindex  = 0;
+					m_pQueue->frontindex  = 0;
+					m_pQueue->queuelens++;
+				}
+				else
+				{
+					m_pQueue->rearindex = (m_pQueue->rearindex+1)%MAX_AUDIOQUEUE_LENS;
+					m_pQueue->frontindex = m_pQueue->frontindex;
+					m_pQueue->queuelens++;
+				}
+				if (Audio!=NULL)
+				{
+					queueptr rearqnodetmp			= (queueptr)aQnodeAddr[m_pQueue->rearindex];
+					rearqnodetmp->videoframeindex	= m_pQueue->rearindex;
+					rearqnodetmp->nextqnodeindex	= 0;
+					audio_frame*audiotmp			= (audio_frame*)aAudioFrameAddr[m_pQueue->rearindex];
+					audiotmp->data					= (char*)aAudioDataAddr[m_pQueue->rearindex];
+					audiotmp->bitspersample			= Audio->bitspersample;
+					audiotmp->format				= Audio->format;
+					audiotmp->framesize				= Audio->framesize;
+					audiotmp->nchannels				= Audio->nchannels;
+					audiotmp->samplespersec			= Audio->samplespersec;
+					audiotmp->iseriesnumber			= Audio->iseriesnumber;
+					memcpy(audiotmp->data,Audio->data,Audio->framesize);
+					rearptrfront->nextqnodeindex = m_pQueue->rearindex;
+					//delete Audio->data;
+					//delete Audio;
+				}
+				m_ShareMem.Unlock();
+				return true;
+			}
+			else
+			{
+				return false;
+			}
+
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	//读音频队列头部节点
+	bool GetAudio(audio_frame* Audio)	
+	{
+		if(m_ShareMem.IsValid())
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				if (m_pQueue->queuelens == 0)
+				{
+					m_ShareMem.Unlock();
+					return false;
+				}
+				else
+				{
+					audio_frame*audiotemp = (audio_frame*)aAudioFrameAddr[m_pQueue->frontindex];;
+					Audio->format			= audiotemp->format;
+					Audio->framesize		= audiotemp->framesize;
+					Audio->bitspersample	= audiotemp->bitspersample;
+					Audio->nchannels		= audiotemp->nchannels;
+					Audio->samplespersec	= audiotemp->samplespersec;
+					Audio->iseriesnumber	= audiotemp->iseriesnumber;
+					memcpy(Audio->data,(char*)aAudioDataAddr[m_pQueue->frontindex],audiotemp->framesize);
+					m_ShareMem.Unlock();
+					return true;
+				}
+			}
+			else
+			{
+				return false;
+			}
+		}
+		else
+		{
+			return false;
+		}		
+	}
+
+	//读视频队列头部节点,并删除头部节点
+	bool GetAudioAndDel(audio_frame* Audio)
+	{
+		if(m_ShareMem.IsValid())
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				if (m_pQueue->queuelens == 0)
+				{
+					m_ShareMem.Unlock();
+					return false;
+				}
+				else
+				{
+					audio_frame*audiotemp = (audio_frame*)aAudioFrameAddr[m_pQueue->frontindex];
+					Audio->format			= audiotemp->format;
+					Audio->framesize		= audiotemp->framesize;
+					Audio->bitspersample	= audiotemp->bitspersample;
+					Audio->nchannels		= audiotemp->nchannels;
+					Audio->samplespersec	= audiotemp->samplespersec;
+					Audio->iseriesnumber    = audiotemp->iseriesnumber;
+					memcpy(Audio->data,(char*)aAudioDataAddr[m_pQueue->frontindex],audiotemp->framesize);
+					char*data = (char*)aAudioDataAddr[m_pQueue->frontindex];
+					memset(data,0,audiotemp->framesize);
+					memset(audiotemp,0,sizeof(audio_frame));
+					queueptr qnodetmp			= (queueptr)aQnodeAddr[m_pQueue->frontindex];
+					m_pQueue->frontindex		= qnodetmp->nextqnodeindex;
+					qnodetmp					= (queueptr)aQnodeAddr[m_pQueue->rearindex];
+					qnodetmp->nextqnodeindex	= 0;
+					m_pQueue->queuelens--;
+					m_ShareMem.Unlock();
+					return true;
+				}
+			}
+			else
+			{
+				return false;
+			}
+		}
+		else
+		{
+			return false;
+		}		
+	}
+	//清除队列
+	bool ClearAudioQueue()
+	{
+		if(m_ShareMem.IsValid())
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				if (m_pQueue->queuelens != 0)
+				{
+					while(m_pQueue->queuelens != 0)
+					{
+						audio_frame*audiotemp = (audio_frame*)aAudioFrameAddr[m_pQueue->frontindex];
+						char*data = (char*)aAudioDataAddr[m_pQueue->frontindex];
+						memset(data,0,audiotemp->framesize);
+						memset(audiotemp,0,sizeof(audio_frame));
+						queueptr qnodetmp			= (queueptr)aQnodeAddr[m_pQueue->frontindex];
+						m_pQueue->frontindex		= qnodetmp->nextqnodeindex;
+						qnodetmp					= (queueptr)aQnodeAddr[m_pQueue->rearindex];
+						qnodetmp->nextqnodeindex	= 0;
+						m_pQueue->queuelens--;	
+					}					
+				}
+				m_ShareMem.Unlock();
+				return true;
+			}
+			else
+			{
+				return false;
+			}
+		}
+		else
+		{
+			return false;
+		}		
+	}
+	//删除队头的数据
+	bool DeleteHeadAudio()
+	{
+		if(m_ShareMem.IsValid())
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				if (m_pQueue->queuelens != 0)
+				{	
+					audio_frame*audiotemp = (audio_frame*)aAudioFrameAddr[m_pQueue->frontindex];
+					char*data = (char*)aAudioDataAddr[m_pQueue->frontindex];
+					memset(data,0,audiotemp->framesize);
+					memset(audiotemp,0,sizeof(audio_frame));
+					queueptr qnodetmp			= (queueptr)aQnodeAddr[m_pQueue->frontindex];
+					m_pQueue->frontindex		= qnodetmp->nextqnodeindex;
+					qnodetmp					= (queueptr)aQnodeAddr[m_pQueue->rearindex];
+					qnodetmp->nextqnodeindex	= 0;
+					m_pQueue->queuelens--;			
+				}
+				m_ShareMem.Unlock();
+				return true;
+			}
+			else
+			{
+				return false;
+			}
+		}
+		else
+		{
+			return false;
+		}	
+	}
+	//获取图像的大小
+	int GetFrameSize()
+	{
+		if(m_ShareMem.IsValid())
+		{
+			m_lpMem = m_ShareMem.Lock(1000);
+			if(m_lpMem != NULL)
+			{
+				int nFrameSize = 0;
+				if (m_pQueue->queuelens != 0)
+				{	
+					audio_frame*audiotmp	= (audio_frame*)aAudioFrameAddr[m_pQueue->frontindex];
+					nFrameSize				= audiotmp->framesize;
+				}
+				m_ShareMem.Unlock();
+				return nFrameSize;
+			}
+			else
+			{
+				return 0;
+			}
+		}
+		else
+		{
+			return 0;
+		}
+	}
+};
+
+// 这是已导出类的构造函数。
+// 有关类定义的信息,请参阅 libaudioqueue.h
+Clibaudioqueue::Clibaudioqueue(LPCTSTR audioqueuename,int framesize)
+{
+	m_pImpl = new libaudioqueue_impl(audioqueuename,framesize);
+	return;
+}
+
+Clibaudioqueue::~Clibaudioqueue()
+{
+	ClearAudioQueue();
+	delete m_pImpl;
+	return;
+}
+
+
+bool Clibaudioqueue::InsertAudio(audio_frame* Audio)
+{
+	bool bRst = m_pImpl->InsertAudio(Audio);
+	return bRst;
+}
+
+bool Clibaudioqueue::GetAudio(audio_frame* Audio)
+{
+	bool bRst = m_pImpl->GetAudio(Audio);
+	return bRst;
+}
+
+bool Clibaudioqueue::GetAudioAndDel(audio_frame* Audio)
+{
+	bool bRst = m_pImpl->GetAudioAndDel(Audio);
+	return bRst;
+}
+
+int Clibaudioqueue::GetAudioLens(void)
+{
+	int i = m_pImpl->GetAudioLens();
+	return i; 
+}
+
+void Clibaudioqueue::ClearAudioQueue()
+{
+	m_pImpl->ClearAudioQueue();
+	return; 
+}
+
+int Clibaudioqueue::GetFrameSize()
+{
+	int i = m_pImpl->GetFrameSize();
+	return i; 
+}	
+
+void Clibaudioqueue::DeleteHeadAudio()
+{
+	m_pImpl->DeleteHeadAudio();
+	return;
+}
+

+ 62 - 0
Other/win/libaudioqueue/libaudioqueue.h

@@ -0,0 +1,62 @@
+// 下列 ifdef 块是创建使从 DLL 导出更简单的
+// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 LIBAUDIOQUEUE_EXPORTS
+// 符号编译的。在使用此 DLL 的
+// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
+// LIBAUDIOQUEUE_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
+// 符号视为是被导出的。
+#ifndef LIBAUDIOQUEUE
+#define LIBAUDIOQUEUE
+
+#ifdef LIBAUDIOQUEUE_EXPORTS
+#define LIBAUDIOQUEUE_API __declspec(dllexport)
+#else
+#define LIBAUDIOQUEUE_API __declspec(dllimport)
+#endif
+
+using namespace std ;
+
+#define MAX_AUDIOQUEUE_LENS     45					//音频队列最大节点数量
+#define MAX_AUDIOQNODE_SIZE     16000				//音频队列单个节点默认最大长度
+
+typedef struct audio_frame 
+{
+	char *data;
+	int samplespersec;   //采样率
+	int framesize;	//数据长度
+	int nchannels;  //通道数
+	int format;			/* AUDIO_FORMAT, 1: PCM*/
+	int bitspersample;	//每个采样点多少bit位
+	int iseriesnumber;
+}audio_frame;
+
+class libaudioqueue_impl;  //桥接
+
+
+// 此类是从 libaudioqueue.dll 导出的
+class LIBAUDIOQUEUE_API Clibaudioqueue 
+{
+public:
+	//audioqueuename:用于访问音频共享内存的共享内存文件名。framesize:默认最大长度,一般使用默认值即可
+	Clibaudioqueue(LPCTSTR audioqueuename,int framesize=MAX_AUDIOQNODE_SIZE);
+	~Clibaudioqueue();
+	// TODO: 在此添加您的方法。
+private:
+	libaudioqueue_impl*m_pImpl;
+public:
+	//插音频到队尾
+	bool InsertAudio(audio_frame* Audio);
+	//读队头
+	bool GetAudio(audio_frame* Audio);
+	//读队头并删除队头数据
+	bool GetAudioAndDel(audio_frame* Audio);
+	//获得音频队列的长度
+	int GetAudioLens(void);
+	//获得音频单个节点的大小
+	int GetFrameSize(void);
+	//清空队列
+	void ClearAudioQueue();
+	//删除队头数据
+	void DeleteHeadAudio();
+};
+
+#endif

+ 8 - 0
Other/win/libaudioqueue/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// SpBase.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file

+ 57 - 0
Other/win/libpictureplayer/CMakeLists.txt

@@ -0,0 +1,57 @@
+set(MODULE_NAME "pictureplayer")
+set(MODULE_PREFIX "LIB_PICTUREPLAYER_FUNC")
+
+
+set(${MODULE_PREFIX}_SRCS
+	CPicturePlayer.h
+	CPicturePlayer.cpp
+	libpictureplayer.h
+	libpictureplayer.cpp
+)
+
+add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
+
+message(STATUS "CONAN_INCLUDE_DIRS_SDL2 :${CONAN_INCLUDE_DIRS_SDL2}")
+
+target_include_directories(${MODULE_NAME} PRIVATE
+	${RVC_COMMON_INCLUDE_DIR}
+	${CONAN_INCLUDE_DIRS_SDL2}
+	${CONAN_RVCFRAMEWORK_ROOT}/include
+	)
+
+
+target_link_directories(${MODULE_NAME} PRIVATE
+	${CONAN_LIB_DIRS_SDL2}
+	${CONAN_LIB_DIRS_RVCFRAMEWORK}
+	)
+
+
+target_link_libraries(${MODULE_NAME} PRIVATE ${${MODULE_PREFIX}_LIBS}	PRIVATE
+	${CONAN_LIBS_SDL2}
+	)  
+
+
+target_compile_definitions(${MODULE_NAME} PUBLIC "LIBPICTUREPLAYER_EXPORTS")
+
+
+if(MSVC)
+	install(TARGETS ${MODULE_NAME} 
+    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}" COMPONENT libraries
+    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT develops EXCLUDE_FROM_ALL
+    LIBRARY DESTINATION "${RVC_LIBRARY_PATH}" COMPONENT libraries
+    )
+else()
+install(TARGETS ${MODULE_NAME} 
+    RUNTIME DESTINATION "${RVC_RUNTIME_PATH}"
+    ARCHIVE DESTINATION "${RVC_LIBRARY_PATH}"
+    LIBRARY DESTINATION "${RVC_RUNTIME_PATH}"
+    COMPONENT libraries)
+endif(MSVC)
+
+
+# ����Ҫ���������ĵ�������
+if(MSVC)
+set(OTHER_CONAN_DEP_LIBS ${OTHER_CONAN_DEP_LIBS} ${CONAN_BIN_DIRS} PARENT_SCOPE)
+else()
+set(OTHER_CONAN_DEP_LIBS ${OTHER_CONAN_DEP_LIBS} ${CONAN_LIB_DIRS} PARENT_SCOPE)
+ENDIF(MSVC)

+ 377 - 0
Other/win/libpictureplayer/CPicturePlayer.cpp

@@ -0,0 +1,377 @@
+#include <stdio.h>
+//#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "CPicturePlayer.h"
+
+#define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
+#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
+
+static char* rvc_strdup(const char* strdata)
+{
+	char* strbuffer = NULL;
+	if (NULL == strdata)
+	{
+		return strbuffer;
+	}
+	
+	uint8_t ulen = strlen(strdata);
+	if (strbuffer = (char*)malloc(ulen + 1)) 
+	{
+		memset(strbuffer, 0, ulen + 1);
+		memcpy(strbuffer, strdata, ulen);
+	}
+
+	return strbuffer;
+}
+
+
+static void rvc_strfree(char* strdata)
+{
+	if (NULL != strdata)
+	{
+		free(strdata);
+		strdata = NULL;
+	}
+}
+
+
+static char* GB2312ToUtf8(const char* gb2312)
+{
+	int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
+	wchar_t* wstr = new wchar_t[len+1];
+	memset(wstr, 0, len+1);
+	MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
+	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
+	char* str = new char[len+1];
+	memset(str, 0, len+1);
+	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
+	if(wstr) delete[] wstr;
+	return str;
+}
+
+
+CPicturePlayer::CPicturePlayer(CPicHostApi* pHostApi)
+{
+	m_thid = NULL;
+	m_bplaying = false;
+	
+	m_window = NULL;
+	m_nfile_cnt = 0;
+	m_nplay_cnt = 0;
+	m_nplay_interval = 5000;
+	m_stricopath = NULL;
+	m_play_exit_event = NULL;
+	memset(m_strroot_path, 0, MAX_PATH);
+	for (size_t i = 0; i < MAX_FILECOUNT; i++){
+		memset(m_strfile_names[i], 0, MAX_PATH);
+	}
+	m_pHostApi = pHostApi;
+	if (NULL != m_pHostApi){
+		char strIcoPath[MAX_PATH] = { 0 };
+		if (0 == pHostApi->GetPicPlayerIcoPath(strIcoPath, MAX_PATH)) {
+			m_stricopath = rvc_strdup(strIcoPath);
+		}
+	}
+	else
+	{
+		m_pHostApi->PicDebug(PIC_LOG_ERROR,"new CPicturePlayer failed!");
+	}
+
+	for (int inum = 0; inum < MAX_DISPLAYNUM; inum++){
+		memset(&m_dispalymode[inum], 0, sizeof(SDL_DisplayMode));
+	}
+	m_show_width = 0;
+	m_show_height = 0;
+	m_busrstop = false;
+
+	Uint32 uRet = SDL_WasInit(SDL_INIT_VIDEO);
+
+	if (0 == uRet) {
+		if (SDL_Init(SDL_INIT_VIDEO))
+		{
+			m_pHostApi->PicDebug(PIC_LOG_ERROR, "Could not initialize SDL - %s", SDL_GetError());
+			m_pHostApi->PicDebug(PIC_LOG_ERROR, "(Did you set the DISPLAY variable?)");
+		}
+		else {
+			uRet = SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);
+			m_pHostApi->PicDebug(PIC_LOG_DEBUG, "initialize SDL success, and init ret = %d.", uRet);
+		}
+	}
+}
+
+CPicturePlayer::~CPicturePlayer()
+{
+	DeInit();
+}
+
+size_t CPicturePlayer::GetVideoDisplayInfo()
+{
+	size_t uCount = SDL_GetNumVideoDisplays();
+	m_pHostApi->PicDebug(PIC_LOG_DEBUG,"VideoDisplays Number is %d.", uCount);
+	for (size_t i = 0; i < uCount && i < MAX_DISPLAYNUM; i++){
+		SDL_GetDesktopDisplayMode(i, &m_dispalymode[i]);
+		m_pHostApi->PicDebug(PIC_LOG_DEBUG,"VideoDisplays{%d} format = %d", i, m_dispalymode[i].format);
+		m_pHostApi->PicDebug(PIC_LOG_DEBUG,"VideoDisplays{%d} w = %d", i, m_dispalymode[i].w);
+		m_pHostApi->PicDebug(PIC_LOG_DEBUG,"VideoDisplays{%d} h = %d", i, m_dispalymode[i].h);
+		m_pHostApi->PicDebug(PIC_LOG_DEBUG,"VideoDisplays{%d} refresh_rate = %d", i, m_dispalymode[i].refresh_rate);
+	}
+	return uCount;
+}
+
+int CPicturePlayer::InitParam(rvc_picture_player_param_t* tparam)
+{
+	int iRet = -1;
+	if (NULL == tparam) {
+		return iRet;
+	}
+
+	//if (0 != SDL_Init(SDL_INIT_VIDEO)) {
+	//	m_pHostApi->PicDebug(PIC_LOG_ERROR,"Could not initialize SDL - %s", SDL_GetError());
+	//	m_pHostApi->PicDebug(PIC_LOG_ERROR, "(Did you set the DISPLAY variable?)");
+	//	return iRet;
+	//}
+
+	//sem_init(&m_play_exit_sem, 0, 0);
+	m_play_exit_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+	m_busrstop = false;
+
+	m_nfile_cnt = tparam->nfile_cnt;
+	m_nplay_cnt = tparam->nplay_cnt;
+	m_nplay_interval = tparam->nplay_interval;
+	_snprintf(m_strroot_path, MAX_PATH, "%s", tparam->strroot_path);
+	for (size_t index = 0; index < m_nfile_cnt; index++) {
+		_snprintf(m_strfile_names[index], MAX_PATH, "%s", tparam->strfile_names[index]);
+	}
+
+	m_uflag = SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU;
+	//if (tparam->bfull_screen) {
+	//	m_uflag += SDL_WINDOW_FULLSCREEN;
+	//}
+
+	size_t uVideoPlayNum = GetVideoDisplayInfo();
+
+	m_idispalycx = 0;
+	m_idispalycy = 0;
+	int idispaly_width = m_dispalymode[0].w;
+	int idispaly_height = m_dispalymode[0].h;
+
+	if (false == tparam->bprim_monitor && uVideoPlayNum > 1) {
+		m_idispalycx = m_dispalymode[0].w;
+		idispaly_width = m_dispalymode[1].w;
+		idispaly_height = m_dispalymode[1].h;
+	}
+
+	m_show_width = idispaly_width;
+	m_show_height = idispaly_height;
+	//2.设置播放器ico
+	//if (NULL != m_stricopath) {
+	//	SDL_Surface* IconSurface = SDL_LoadBMP(m_stricopath);
+	//	if (NULL == IconSurface) {
+	//		m_pHostApi->PicDebug(PIC_LOG_ERROR, "SDL_LoadBMP(%s) failed: %s", m_stricopath, SDL_GetError());
+	//	}
+	//	else {
+	//		SDL_SetWindowIcon(m_window, IconSurface);
+	//		SDL_FreeSurface(IconSurface);
+	//	}
+	//}
+
+	iRet = 0;
+	return iRet;
+}
+
+
+int CPicturePlayer::DeInit()
+{
+	int iRet = -1;
+	rvc_strfree(m_stricopath);
+	m_stricopath = NULL;
+	m_show_width = 0;
+	m_show_height = 0;
+	m_busrstop = false;
+	//sem_destroy(&m_play_exit_sem);
+	if (NULL != m_play_exit_event){
+		CloseHandle(m_play_exit_event);
+		m_play_exit_event = NULL;
+	}
+
+	if (NULL != m_window) {
+		SDL_DestroyWindow(m_window);
+	}
+
+	SDL_Quit();
+
+	iRet = 0;
+
+	return iRet;
+}
+
+
+bool CPicturePlayer::StartPicPlay()
+{
+	bool bRet = false;
+
+	SDL_SysWMinfo info;
+	HWND hwnd;
+
+	//1.创建播放窗体
+	m_window = SDL_CreateWindow("picture player",
+		m_idispalycx,
+		m_idispalycy,
+		m_show_width,
+		m_show_height,
+		m_uflag
+	);
+
+	if (NULL == m_window) {
+		m_pHostApi->PicDebug(PIC_LOG_ERROR, "SDL_CreateWindow() failed: %s.", SDL_GetError());
+		return false;
+	}
+	else {
+		int cx = 0, cy = 0;
+		SDL_GetWindowPosition(m_window, &cx, &cy);
+		m_pHostApi->PicDebug(PIC_LOG_DEBUG, "window flag is 0x%08x, cx = %d, cy = %d.", SDL_GetWindowFlags(m_window), cx, cy);
+	}
+
+	m_bplaying = true;
+
+	m_pHostApi->PicDebug(PIC_LOG_DEBUG, "set m_bplaying = true");
+
+	SDL_VERSION(&info.version);
+	if (SDL_GetWindowWMInfo(m_window, &info)){
+		hwnd = info.info.win.window;
+		m_pHostApi->PicDebug(PIC_LOG_DEBUG, "SDL_GetWindowWMInfo success.");
+		SetWindowPos(hwnd,
+			HWND_TOPMOST,
+			m_idispalycx,
+			m_idispalycy,
+			m_show_width,
+			m_show_height,
+			SWP_NOMOVE | SWP_NOSIZE);
+	}
+	else {
+		m_pHostApi->PicDebug(PIC_LOG_DEBUG, "SDL_GetWindowWMInfo failed.");
+	}
+
+	SDL_Surface* surface = SDL_GetWindowSurface(m_window);
+
+	int iPlayCount = 0;
+	for (; iPlayCount < m_nplay_cnt; iPlayCount++)
+	{
+		if (m_busrstop) {
+			break;
+		}
+
+		int index = 0;
+		for (; index < m_nfile_cnt; index++)
+		{
+			if (m_busrstop) {
+				break;
+			}
+			
+			char* strfilename = GB2312ToUtf8(m_strfile_names[index]);
+			SDL_Surface* image = IMG_Load(strfilename);
+			SAFE_DELETE_ARRAY(strfilename)
+
+			if (NULL == image) {
+				m_pHostApi->PicDebug(PIC_LOG_ERROR, "IMG_Load %s failed!", m_strfile_names[index]);
+				strfilename = GB2312ToUtf8(m_strfile_names[index]);
+				image = SDL_LoadBMP(strfilename);
+				SAFE_DELETE_ARRAY(strfilename)
+				if (NULL == image) {
+					continue;
+				}
+			}
+			else {
+				m_pHostApi->PicDebug(PIC_LOG_DEBUG, "IMG_Load %s success!", m_strfile_names[index]);
+			}
+
+			SDL_Rect dst;
+			dst.x = 0;
+			dst.y = 0;
+			dst.w = m_show_width;
+			dst.h = m_show_height;
+
+			int itimems = m_nplay_interval;
+			SDL_BlitSurface(image, NULL, surface, &dst);
+			DWORD t1 = 0,t2 = 0;
+			t1 = GetTickCount();
+			while(itimems > 0){
+				DWORD dwRet = WaitForSingleObject(m_play_exit_event, 10);
+				if (dwRet == WAIT_TIMEOUT){
+
+					SDL_Event event;
+					while(SDL_PollEvent(&event)){
+						switch(event.type){
+							case SDL_QUIT:
+								break;
+						}
+					}
+
+					SDL_UpdateWindowSurface(m_window);
+
+					itimems--;
+
+					t2 = GetTickCount();
+					if (t2 - t1 > m_nplay_interval){
+						m_pHostApi->PicDebug(PIC_LOG_DEBUG, "%s:%d it's time to leave and itimems is %d.", __FUNCTION__, __LINE__, itimems);
+						break;
+					}
+				}
+				else {
+					m_pHostApi->PicDebug(PIC_LOG_DEBUG, "%s:%d break circle.", __FUNCTION__, __LINE__);
+					SDL_Delay(200);
+					break;
+				}
+			}
+
+			SDL_FreeSurface(surface);
+			SDL_FreeSurface(image);
+		}
+	}
+
+	if (iPlayCount == m_nplay_cnt) {
+		m_pHostApi->PicDebug(PIC_LOG_INFO, "%d times picture playing task finished, exit.", iPlayCount);
+	}
+	else{
+		m_pHostApi->PicDebug(PIC_LOG_INFO, "user stop picture playing task, exit.");
+	}
+
+	SDL_DestroyWindow(m_window);
+	m_window = NULL;
+	bRet = true;
+
+	return bRet;
+}
+
+
+int CPicturePlayer::StopPicPlay()
+{
+	int iRet = -1;
+	//sem_post(&m_play_exit_sem);
+	SetEvent(m_play_exit_event);
+	m_busrstop = true;
+	m_pHostApi->PicDebug(PIC_LOG_DEBUG, "stop picture play, set user stop flag true.");
+
+	iRet = 0;
+
+	return iRet;
+}
+
+
+bool CPicturePlayer::GetPicPlayingFlag()
+{
+	m_pHostApi->PicDebug(PIC_LOG_DEBUG, "m_bplaying flag is %s", m_bplaying ? "true" : "false");
+	return m_bplaying;
+}
+
+
+bool CPicturePlayer::SetPicPlayingFlag(bool bret)
+{
+	m_bplaying = bret;
+	m_pHostApi->PicDebug(PIC_LOG_DEBUG, "after set m_bplaying flag is %s", m_bplaying ? "true" : "false");
+	return true;
+}

+ 105 - 0
Other/win/libpictureplayer/CPicturePlayer.h

@@ -0,0 +1,105 @@
+#ifndef __CPICTURE_PLAYER_H__
+#define __CPICTURE_PLAYER_H__
+
+#include <stdio.h>
+#include <stdint.h>
+//#include <stdbool.h>
+//#include <semaphore.h>
+#include <Windows.h>
+
+#include "ipicdatastruct.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+#if defined(_WIN32)
+#include <SDL.h>
+#include <SDL_video.h>
+#include <SDL_render.h>
+#include <SDL_rect.h>
+#include <SDL_mutex.h>
+#include <SDL_image.h>
+#include <SDL_syswm.h>
+#else
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_video.h>
+#include <SDL2/SDL_render.h>
+#include <SDL2/SDL_rect.h>
+#include <SDL2/SDL_mutex.h>
+#include <SDL2/SDL_image.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#ifndef MAX_FILECOUNT
+#define MAX_FILECOUNT 32
+#endif // !MAX_FILECOUNT
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+#ifndef MAX_DISPLAYNUM
+#define MAX_DISPLAYNUM 5
+#endif // !MAX_DISPLAYNUM
+
+
+typedef struct rvc_picture_player_param_s {
+	int icx;
+	int icy;
+	uint8_t uwindow_width;
+	uint8_t uwindow_height;
+	bool bfull_screen;                           
+	bool bprim_monitor;                          
+	int nfile_cnt;		                        
+	int nplay_cnt;		                        
+	int nplay_interval;		                    
+	char strroot_path[MAX_PATH];		            
+	char strfile_names[MAX_FILECOUNT][MAX_PATH]; 
+}rvc_picture_player_param_t;
+
+
+class CPicturePlayer
+{
+public:
+	CPicturePlayer(CPicHostApi* pHostApi);
+	~CPicturePlayer();
+
+	int InitParam(rvc_picture_player_param_t* tparam);
+	int DeInit();
+	bool StartPicPlay();
+	int StopPicPlay();
+	bool GetPicPlayingFlag();
+	bool SetPicPlayingFlag(bool bret);
+	size_t GetVideoDisplayInfo();
+
+public:
+	SDL_Window* m_window;
+	CPicHostApi* m_pHostApi;
+	int m_nfile_cnt;
+	int m_nplay_cnt;
+	int m_nplay_interval;
+	char m_strroot_path[MAX_PATH];
+	char m_strfile_names[MAX_FILECOUNT][MAX_PATH];
+	int m_show_width;
+	int m_show_height;
+	bool m_busrstop;
+	Uint32 m_uflag;
+	int m_idispalycx;
+	int m_idispalycy;
+	
+private:
+	bool m_bplaying;
+	char* m_stricopath;
+	SDL_Thread* m_thid;
+	SDL_DisplayMode m_dispalymode[MAX_DISPLAYNUM];
+	//sem_t m_play_exit_sem;
+	HANDLE m_play_exit_event;
+};
+
+
+#endif

+ 48 - 0
Other/win/libpictureplayer/ReadMe.txt

@@ -0,0 +1,48 @@
+========================================================================
+    DYNAMIC LINK LIBRARY : libpictureplayer Project Overview
+========================================================================
+
+AppWizard has created this libpictureplayer DLL for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your libpictureplayer application.
+
+
+libpictureplayer.vcxproj
+    This is the main project file for VC++ projects generated using an Application Wizard.
+    It contains information about the version of Visual C++ that generated the file, and
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+libpictureplayer.vcxproj.filters
+    This is the filters file for VC++ projects generated using an Application Wizard. 
+    It contains information about the association between the files in your project 
+    and the filters. This association is used in the IDE to show grouping of files with
+    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+    "Source Files" filter).
+
+libpictureplayer.cpp
+    This is the main DLL source file.
+
+	When created, this DLL does not export any symbols. As a result, it
+	will not produce a .lib file when it is built. If you wish this project
+	to be a project dependency of some other project, you will either need to
+	add code to export some symbols from the DLL so that an export library
+	will be produced, or you can set the Ignore Input Library property to Yes
+	on the General propert page of the Linker folder in the project's Property
+	Pages dialog box.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named libpictureplayer.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////

+ 19 - 0
Other/win/libpictureplayer/dllmain.cpp

@@ -0,0 +1,19 @@
+// dllmain.cpp : Defines the entry point for the DLL application.
+#include "stdafx.h"
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+                       DWORD  ul_reason_for_call,
+                       LPVOID lpReserved
+					 )
+{
+	switch (ul_reason_for_call)
+	{
+	case DLL_PROCESS_ATTACH:
+	case DLL_THREAD_ATTACH:
+	case DLL_THREAD_DETACH:
+	case DLL_PROCESS_DETACH:
+		break;
+	}
+	return TRUE;
+}
+

+ 54 - 0
Other/win/libpictureplayer/ipicdatastruct.h

@@ -0,0 +1,54 @@
+#ifndef __I_PIC_DATA_STRUCT_H__
+#define __I_PIC_DATA_STRUCT_H__
+
+#ifdef RVC_OS_WIN
+#ifndef RVC_NO_VTABLE
+#define RVC_NO_VTABLE __declspec(novtable)
+#endif // !RVC_NO_VTABLE
+
+#else
+#ifndef RVC_NO_VTABLE
+#define RVC_NO_VTABLE 
+#endif // !RVC_NO_VTABLE
+#endif // RVC_OS_WIN
+
+#ifndef MAX_FILECOUNT
+#define MAX_FILECOUNT 32
+#endif // !MAX_FILECOUNT
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+
+enum pic_loglevel{
+	PIC_LOG_NO,
+	PIC_LOG_DEBUG,
+	PIC_LOG_INFO,
+	PIC_LOG_ERROR
+};
+
+struct CPicPlayConfig
+{
+	bool bFullScreen;                           // 是否全屏
+	bool bPrimMonitor;                          // 是否主屏显示
+	int nWndX;                                  // 窗口X坐标
+	int nWndY;                                  // 窗口Y坐标
+	int nWndWidth;                              // 窗口宽度
+	int nWndHeight;                             // 窗口高度
+	int nFileCnt;		                        // 文件个数
+	int nPlayCnt;		                        // 播放次数
+	int nPlayInterval;		                    // 播放时间间隔
+	char strRootPath[MAX_PATH];		            // 根目录
+	char strFileNames[MAX_FILECOUNT][MAX_PATH]; // 文件名数组
+};
+
+
+struct RVC_NO_VTABLE CPicHostApi
+{
+	virtual void PicDebug(pic_loglevel elvel, const char* fmt, ...) = 0;
+	virtual int LoadPlayConfig(CPicPlayConfig& config, int CfgInx = 0) = 0;
+	virtual int GetPicPlayerIcoPath(char* strPath, size_t uLen) = 0;
+};
+
+#endif

+ 283 - 0
Other/win/libpictureplayer/libpictureplayer.cpp

@@ -0,0 +1,283 @@
+#include "libpictureplayer.h"
+#include "CPicturePlayer.h"
+//#include <unistd.h>
+#include <string.h>
+#include <process.h>
+#include <io.h>
+
+
+static unsigned int __stdcall PicturePlayingFunc(void* param) 
+{
+	CPicturePlayer* is = (CPicturePlayer*)param;
+
+	is->m_pHostApi->PicDebug(PIC_LOG_DEBUG, "enter PicturePlayingFunc");
+
+	is->StartPicPlay();
+
+	is->SetPicPlayingFlag(false);
+
+	is->m_pHostApi->PicDebug(PIC_LOG_DEBUG, "leave PicturePlayingFunc");
+
+	return 0;
+}
+
+
+class libpictureplayer_impl
+{
+public:
+	CPicPlayConfig m_stPlayConfig;
+	CPicHostApi* m_pHostApi;
+	CPicturePlayer* m_Player;
+	bool m_bIsPlay;
+	//pthread_t m_PlayThreadId;
+	HANDLE m_PlayThread;
+
+public:
+	libpictureplayer_impl(CPicHostApi* pHostApi) {
+		m_bIsPlay = false;
+		m_pHostApi = pHostApi;
+		memset(&m_stPlayConfig, 0, sizeof(m_stPlayConfig));
+		m_Player = new CPicturePlayer(pHostApi);
+		if (NULL == m_Player) {
+			pHostApi->PicDebug(PIC_LOG_DEBUG, "new PicturePlayer failed!");
+		}
+		m_PlayThread = NULL;
+	}
+
+	~libpictureplayer_impl()
+	{
+		m_pHostApi = NULL;
+		delete m_Player;
+		m_Player = NULL;
+		m_bIsPlay = false;
+		m_PlayThread = NULL;
+	}
+
+	bool isStop() 
+	{
+		//return !m_bIsPlay;
+		return !m_Player->GetPicPlayingFlag();
+	}
+
+	bool CheckIsPlay(void* pthreadid)
+	{
+		bool bret = false;
+		HANDLE threadHandle = m_PlayThread;
+		if (NULL != threadHandle)
+		{
+			bret = true;
+			*(HANDLE*)pthreadid = threadHandle;
+		}
+
+		return bret;
+	}
+
+	bool StartPlayMedia(CPicPlayConfig& config)
+	{
+		bool bRet = false;
+		//if (m_bIsPlay){
+		//	return true;
+		//}
+
+		memcpy(&m_stPlayConfig, &config, sizeof(CPicPlayConfig));
+
+		rvc_picture_player_param_t tplayer_param = { 0 };
+		tplayer_param.icx = m_stPlayConfig.nWndX;
+		tplayer_param.icy = m_stPlayConfig.nWndY;
+		tplayer_param.uwindow_width = m_stPlayConfig.nWndWidth;
+		tplayer_param.uwindow_height = m_stPlayConfig.nWndHeight;
+
+		tplayer_param.bfull_screen = m_stPlayConfig.bFullScreen;
+		tplayer_param.nplay_cnt = m_stPlayConfig.nPlayCnt;
+		tplayer_param.nplay_interval = m_stPlayConfig.nPlayInterval;
+
+		char strFileName[MAX_PATH] = { 0 };
+		_snprintf(strFileName, MAX_PATH, "%s%s", m_stPlayConfig.strRootPath, m_stPlayConfig.strFileNames[0]);
+		if (IsFileExist(strFileName)) {
+			memcpy(tplayer_param.strfile_names[0], strFileName, strlen(strFileName));
+			tplayer_param.nfile_cnt = 1;
+		}
+		else {
+			m_pHostApi->PicDebug(PIC_LOG_DEBUG, "File %s is not exist.", strFileName);
+			tplayer_param.nfile_cnt = 0;
+		}
+		
+
+		//if (0 == GetPicturePlayingParams(&tplayer_param)) 
+		{
+			if (0 == m_Player->InitParam(&tplayer_param))
+			{
+				m_pHostApi->PicDebug(PIC_LOG_DEBUG, "init picture player success and begin start picture play.");
+				m_PlayThread = (HANDLE)_beginthreadex(NULL, 0, &PicturePlayingFunc, m_Player, 0, NULL);
+				if (NULL != m_PlayThread) {
+					m_pHostApi->PicDebug(PIC_LOG_DEBUG, "create picture play thread success.");
+					m_bIsPlay = true;
+					bRet = true;
+					m_pHostApi->PicDebug(PIC_LOG_DEBUG, "start picture play Success.");
+				}
+				else {
+					m_pHostApi->PicDebug(PIC_LOG_DEBUG, "create picture play thread failed.");
+				}
+			}
+			else {
+				m_pHostApi->PicDebug(PIC_LOG_ERROR, "init picture player failed!");
+			}
+		}
+		//else {
+		//	m_pHostApi->PicDebug("get picture playing params failed!");
+		//}
+
+		return bRet;
+	}
+
+	int GetPicturePlayingParams(rvc_picture_player_param_t* pParam)
+	{
+		int iRet = -1;
+		if (NULL == pParam) {
+			return iRet;
+		}
+
+		pParam->bfull_screen = m_stPlayConfig.bFullScreen;
+		pParam->nplay_cnt = m_stPlayConfig.nPlayCnt;
+		pParam->nplay_interval = m_stPlayConfig.nPlayInterval;
+
+		size_t uValidCount = 0;
+		for (int i = 0; i < m_stPlayConfig.nFileCnt && i < MAX_FILECOUNT; i++) {
+			char strFileName[MAX_PATH] = { 0 };
+			_snprintf(strFileName, MAX_PATH, "%s%s", m_stPlayConfig.strRootPath, m_stPlayConfig.strFileNames[i]);
+			if (IsFileExist(strFileName)) {
+				memcpy(pParam->strfile_names[i], strFileName, strlen(strFileName));
+				uValidCount++;
+			}
+			else {
+				m_pHostApi->PicDebug(PIC_LOG_DEBUG, "File %s is not exist.", strFileName);
+				continue;
+			}
+		}
+		pParam->nfile_cnt = uValidCount;
+		if (NULL != m_pHostApi) {
+			m_pHostApi->PicDebug(PIC_LOG_DEBUG, "pParam uFilesCount = %d", uValidCount);
+		}
+		if (uValidCount > 0) {
+			iRet = 0;
+		}
+
+		return iRet;
+	}
+
+	bool StartPlay(int nCfgInx, int nWndX, int nWndY, int nWndWidth, int nWndHeight)
+	{
+		bool bRet = false;
+		if (true == m_Player->GetPicPlayingFlag()){
+			m_pHostApi->PicDebug(PIC_LOG_DEBUG, "now is playing!");
+			return true;
+		}
+
+		int iRet = m_pHostApi->LoadPlayConfig(m_stPlayConfig, nCfgInx);
+		if (0 != iRet){
+			m_pHostApi->PicDebug(PIC_LOG_DEBUG, "Load ImgConfiguration failed!");
+			return bRet;
+		}
+		else{
+			m_pHostApi->PicDebug(PIC_LOG_DEBUG, "Load ImgConfiguration succeeded while play local image!");
+			m_pHostApi->PicDebug(PIC_LOG_DEBUG, "m_stPlayConfig.strRootPath: %s", m_stPlayConfig.strRootPath);
+		}
+
+		m_stPlayConfig.nWndX = nWndX;
+		m_stPlayConfig.nWndY = nWndY;
+		m_stPlayConfig.nWndWidth = nWndWidth;
+		m_stPlayConfig.nWndHeight = nWndHeight;
+
+		rvc_picture_player_param_t tplayer_param = { 0 };
+		tplayer_param.icx = m_stPlayConfig.nWndX;
+		tplayer_param.icy = m_stPlayConfig.nWndY;
+		tplayer_param.uwindow_width = m_stPlayConfig.nWndWidth;
+		tplayer_param.uwindow_height = m_stPlayConfig.nWndHeight;
+
+		if (0 == GetPicturePlayingParams(&tplayer_param)) {
+			if (0 == m_Player->InitParam(&tplayer_param))
+			{
+				m_pHostApi->PicDebug(PIC_LOG_DEBUG, "init picture player Success.");
+				m_pHostApi->PicDebug(PIC_LOG_DEBUG, "start picture play success.");
+				m_PlayThread = (HANDLE)_beginthreadex(NULL, 0, &PicturePlayingFunc, m_Player, 0, NULL);
+				if (NULL != m_PlayThread) {
+					m_pHostApi->PicDebug(PIC_LOG_DEBUG, "create picture play thread success.");
+					m_bIsPlay = true;
+					bRet = true;
+					m_pHostApi->PicDebug(PIC_LOG_DEBUG, "start picture play success.");
+				}
+				else {
+					m_pHostApi->PicDebug(PIC_LOG_DEBUG, "create picture play thread failed.");
+				}
+			}
+		}
+		else {
+			m_pHostApi->PicDebug(PIC_LOG_DEBUG, "get picture playing params failed!");
+		}
+
+		return bRet;
+	}
+
+	bool StopPlay()
+	{
+		if (NULL != m_Player)
+		{
+			if (m_Player->GetPicPlayingFlag())
+			{
+				m_Player->StopPicPlay();
+				m_bIsPlay = false;
+			}
+			else
+			{
+				m_pHostApi->PicDebug(PIC_LOG_DEBUG, "picture playing already stopped!");
+			}
+		}
+		return true;
+	}
+
+	bool IsFileExist(const char* pFilePath)
+	{
+		bool bRet = false;
+		if (NULL != pFilePath) {
+			if (0 == _access(pFilePath, 0)) {
+				bRet = true;
+			}
+		}
+		return bRet;
+	}
+};
+
+Clibpictureplayer::Clibpictureplayer(CPicHostApi* pHostApi)
+{
+	m_pImpl = new libpictureplayer_impl(pHostApi);
+}
+
+Clibpictureplayer::~Clibpictureplayer()
+{
+	delete m_pImpl;
+	m_pImpl = NULL;
+}
+
+void Clibpictureplayer::Play(int nCfgInx, int nWndX, int nWndY, int nWndWidth, int nWndHeight)
+{
+	m_pImpl->StartPlay(nCfgInx, nWndX, nWndY, nWndWidth, nWndHeight);
+}
+
+void Clibpictureplayer::PlayMedia(CPicPlayConfig& config)
+{
+	m_pImpl->StartPlayMedia(config);
+}
+
+bool Clibpictureplayer::checkIsStop() {
+	return m_pImpl->isStop();
+}
+
+bool Clibpictureplayer::checkIsPlay(void* pthreadid)
+{
+	return m_pImpl->CheckIsPlay(pthreadid);
+}
+
+void Clibpictureplayer::Close()
+{
+	m_pImpl->StopPlay();
+}

+ 35 - 0
Other/win/libpictureplayer/libpictureplayer.h

@@ -0,0 +1,35 @@
+#pragma once
+#include <stdio.h>
+#include "ipicdatastruct.h"
+
+#ifdef _WIN32
+#ifdef LIBPICTUREPLAYER_EXPORTS
+#define LIBPICTUREPLAYER_API __declspec(dllexport)
+#else
+#define LIBPICTUREPLAYER_API __declspec(dllimport)
+#endif
+# elif ( defined(__GNUC__) &&  __GNUC__ >= 4 )
+#define LIBPICTUREPLAYER_API __attribute__((visibility("default")))
+#else // RVC_OS_WIN
+#define LIBPICTUREPLAYER_API
+#endif // RVC_OS_WIN
+
+
+class libpictureplayer_impl;
+
+
+class  LIBPICTUREPLAYER_API Clibpictureplayer
+{
+public:
+	Clibpictureplayer(CPicHostApi* pHostApi);
+	~Clibpictureplayer();
+
+	void Play(int nCfgInx, int nWndX, int nWndY, int nWndWidth, int nWndHeight);
+	void PlayMedia(CPicPlayConfig& config);
+	bool checkIsStop();
+	bool checkIsPlay(void* pthreadid);
+	void Close();
+
+private:
+	libpictureplayer_impl* m_pImpl;
+};

+ 8 - 0
Other/win/libpictureplayer/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// libpictureplayer.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file

+ 16 - 0
Other/win/libpictureplayer/stdafx.h

@@ -0,0 +1,16 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include <windows.h>
+
+
+
+// TODO: reference additional headers your program requires here

+ 8 - 0
Other/win/libpictureplayer/targetver.h

@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>