Browse Source

Z991239-1621 #comment fea Linux下新增视频回显库

陈礼鹏80274480 4 years ago
parent
commit
791b0e4b26

+ 0 - 1
Other/libvideocapture/ivideocaptureinterface.cpp

@@ -8,7 +8,6 @@ IVideoCapture* CreateVideoCaptureObj(ICaptureCallback* pCallback)
 }
 
 
-//这里不能直接delete pAudioRender,因为没有把IAudioRender的析构函数定义为虚函数
 void  DestroyVideoCaptureObj(IVideoCapture* pIVideoCapture)
 {
 	pIVideoCapture->VideoCaptureDestroy();

+ 62 - 0
Other/libvideorender/CMakeLists.txt

@@ -0,0 +1,62 @@
+set(MODULE_NAME "videorender")
+set(MODULE_PREFIX "LIB_VIDEORENDER_FUNC")
+
+
+if(RVC_DEBUG_MODE)
+    set(SPBASE_LIB spbased)
+else()
+    set(SPBASE_LIB spbase)
+endif(RVC_DEBUG_MODE)
+
+
+set(${MODULE_PREFIX}_SRCS
+    ivideorenderinterface.h
+	ivideorenderinterface.cpp
+	libvideorender.h
+	libvideorender.cpp
+)
+
+add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
+
+
+if(WIN32)
+conan_cmake_run(REQUIRES SDL2/2.0.9@LR04.02_ThirdParty/testing
+BASIC_SETUP CMAKE_TARGETS)
+else(WIN32)
+conan_cmake_run(REQUIRES SDL2/2.0.12@LR04.02_ThirdParty/shared
+BASIC_SETUP CMAKE_TARGETS)
+endif(WIN32)
+
+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 "LIBVIDEORENDER_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)

+ 14 - 0
Other/libvideorender/ivideorenderinterface.cpp

@@ -0,0 +1,14 @@
+#include "ivideorenderinterface.h"
+#include "libvideorender.h"
+
+
+IVideoRender* CreateVideoRenderObj(IRenderCallback* pCallback)
+{
+	return new VideoRenderImpl(pCallback);
+}
+
+
+void  DestroyVideoRenderObj(IVideoRender* pIVideoCapture)
+{
+	pIVideoCapture->VideoRenderDestroy();
+}

+ 39 - 0
Other/libvideorender/ivideorenderinterface.h

@@ -0,0 +1,39 @@
+#pragma  once
+
+#ifdef _WIN32
+#ifdef LIBVIDEORENDER_EXPORTS
+#define LIBVIDEORENDER_API __declspec(dllexport)
+#else
+#define LIBVIDEORENDER_API __declspec(dllimport)
+#endif
+# elif ( defined(__GNUC__) &&  __GNUC__ >= 4 )
+#define LIBVIDEORENDER_API __attribute__((visibility("default")))
+#else // RVC_OS_WIN
+#define LIBVIDEORENDER_API
+#endif // RVC_OS_WIN
+
+struct video_frame;
+
+struct IRenderCallback
+{
+	virtual void Debug(const char* fmt, ...) = 0;
+	virtual void OnRenderFailed() = 0;
+	virtual void OnVideoRenderExcption() = 0;
+};
+
+class IVideoRender 
+{
+public:
+	virtual int VideoRenderSetParam() = 0;
+	virtual int StartVideoRender() = 0;
+	virtual int StopVideoRender() = 0;
+	virtual void VideoRenderDestroy() = 0;
+	virtual int ShowVideoWindow() = 0;
+	virtual int HideVideoWindow() = 0;
+	virtual int RenderVideoFrame(video_frame* pframe) = 0;
+};
+
+
+extern "C" LIBVIDEORENDER_API IVideoRender* CreateVideoRenderObj(IRenderCallback* pCallback);
+extern "C" LIBVIDEORENDER_API void DestroyVideoRenderObj(IVideoRender* pIVideoRender);
+

+ 239 - 0
Other/libvideorender/libvideorender.cpp

@@ -0,0 +1,239 @@
+#include"libvideorender.h"
+#include "../libvideoframework/videoutil.h"
+
+
+VideoRenderImpl::VideoRenderImpl(IRenderCallback* pCallback)
+{
+	m_sdl_window = NULL;
+	m_rending_texture = NULL;
+	m_renderer = NULL;
+	m_callback = pCallback;
+
+	m_cx = SDL_WINDOWPOS_UNDEFINED;
+	m_cy = SDL_WINDOWPOS_UNDEFINED;
+	m_width = 640;
+	m_height = 360;
+	m_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIDDEN | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR;
+}
+
+
+VideoRenderImpl::~VideoRenderImpl()
+{
+	if (NULL != m_rending_texture) {
+		SDL_DestroyTexture(m_rending_texture);
+		m_rending_texture = NULL;
+	}
+
+	if (NULL != m_renderer) {
+		SDL_DestroyRenderer(m_renderer);
+		m_renderer = NULL;
+	}
+
+	if (NULL != m_sdl_window) {
+		SDL_DestroyWindow(m_sdl_window);
+		m_sdl_window = NULL;
+	}
+		
+	SDL_Quit();
+}
+
+
+int VideoRenderImpl::VideoRenderSetParam()
+{
+	if (NULL == m_sdl_window) /*init SDL*/
+	{
+		if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
+		{
+			m_callback->Debug("RENDER: Couldn't initialize SDL2: %s", SDL_GetError());
+			return -1;
+		}
+
+		SDL_SetHint("SDL_HINT_RENDER_SCALE_QUALITY", "1");
+
+		m_sdl_window = SDL_CreateWindow(
+			"rvc video",    // window title
+			m_cx,           // initial x position
+			m_cy,           // initial y position
+			m_width,        // width, in pixels
+			m_height,       // height, in pixels
+			m_flags
+		);
+
+		if (NULL == m_sdl_window){
+			m_callback->Debug("RENDER: (SDL2) Couldn't open window: %s", SDL_GetError());
+			VideoRenderDestroy();
+			return -2;
+		}
+
+		int display_index = SDL_GetWindowDisplayIndex(m_sdl_window);
+		SDL_DisplayMode display_mode;
+		int err = SDL_GetDesktopDisplayMode(display_index, &display_mode);
+		if (0 == err){
+			m_callback->Debug("RENDER: video display %i ->  %dx%dpx @ %dhz",
+					display_index,
+					display_mode.w,
+					display_mode.h,
+					display_mode.refresh_rate);
+		}
+		else {
+			m_callback->Debug("RENDER: Couldn't determine display mode for video display %i", display_index);
+		}
+
+		if (m_width > display_mode.w) {
+			m_width = display_mode.w;
+		}
+		if (m_height > display_mode.h) {
+			m_height = display_mode.h;
+		}
+
+		SDL_SetWindowSize(m_sdl_window, m_width, m_height);
+	}
+
+	/* Allocate a renderer info struct*/
+	SDL_RendererInfo* rend_info = (SDL_RendererInfo*)malloc(sizeof(SDL_RendererInfo));
+	if (NULL == rend_info){
+		m_callback->Debug("RENDER: Couldn't allocate memory for the renderer info data structure");
+		VideoRenderDestroy();
+		return -5;
+	}
+	
+	/* Print the list of the available renderers*/
+	m_callback->Debug("RENDER: Available SDL2 rendering drivers:");
+	for (int i = 0; i < SDL_GetNumRenderDrivers(); i++){
+		if (SDL_GetRenderDriverInfo(i, rend_info) < 0){
+			m_callback->Debug("Couldn't get SDL2 render driver information: %s", SDL_GetError());
+		}
+		else{
+			m_callback->Debug(" %2d: %s", i, rend_info->name);
+			m_callback->Debug("    SDL_RENDERER_TARGETTEXTURE [%c]", (rend_info->flags & SDL_RENDERER_TARGETTEXTURE) ? 'X' : ' ');
+			m_callback->Debug("    SDL_RENDERER_SOFTWARE      [%c]", (rend_info->flags & SDL_RENDERER_SOFTWARE) ? 'X' : ' ');
+			m_callback->Debug("    SDL_RENDERER_ACCELERATED   [%c]", (rend_info->flags & SDL_RENDERER_ACCELERATED) ? 'X' : ' ');
+			m_callback->Debug("    SDL_RENDERER_PRESENTVSYNC  [%c]", (rend_info->flags & SDL_RENDERER_PRESENTVSYNC) ? 'X' : ' ');
+		}
+	}
+	free(rend_info);
+
+	m_renderer = SDL_CreateRenderer(m_sdl_window, -1,
+		SDL_RENDERER_TARGETTEXTURE |
+		SDL_RENDERER_PRESENTVSYNC |
+		SDL_RENDERER_ACCELERATED);
+
+	if (m_renderer == NULL)
+	{
+		m_callback->Debug("RENDER: (SDL2) Couldn't get a accelerated renderer: %s", SDL_GetError());
+		m_callback->Debug("RENDER: (SDL2) trying with a software renderer");
+
+		m_renderer = SDL_CreateRenderer(m_sdl_window, -1,
+			SDL_RENDERER_TARGETTEXTURE |
+			SDL_RENDERER_SOFTWARE);
+
+		if (m_renderer == NULL)
+		{
+			m_callback->Debug("RENDER: (SDL2) Couldn't get a software renderer: %s", SDL_GetError());
+			m_callback->Debug("RENDER: (SDL2) giving up...");
+			VideoRenderDestroy();
+			return -3;
+		}
+	}
+	
+	/* Allocate a renderer info struct*/
+	SDL_RendererInfo* render_info = (SDL_RendererInfo*)malloc(sizeof(SDL_RendererInfo));
+	if (NULL == render_info){
+		m_callback->Debug("RENDER: Couldn't allocate memory for the renderer info data structure");
+		VideoRenderDestroy();
+		return -5;
+	}
+	
+	/* Print the name of the current rendering driver */
+	if (SDL_GetRendererInfo(m_renderer, render_info) < 0){
+		m_callback->Debug("Couldn't get SDL2 rendering driver information: %s", SDL_GetError());
+	}
+	m_callback->Debug("RENDER: rendering driver in use: %s", render_info->name);
+	m_callback->Debug("    SDL_RENDERER_TARGETTEXTURE [%c]", (render_info->flags & SDL_RENDERER_TARGETTEXTURE) ? 'X' : ' ');
+	m_callback->Debug("    SDL_RENDERER_SOFTWARE      [%c]", (render_info->flags & SDL_RENDERER_SOFTWARE) ? 'X' : ' ');
+	m_callback->Debug("    SDL_RENDERER_ACCELERATED   [%c]", (render_info->flags & SDL_RENDERER_ACCELERATED) ? 'X' : ' ');
+	m_callback->Debug("    SDL_RENDERER_PRESENTVSYNC  [%c]", (render_info->flags & SDL_RENDERER_PRESENTVSYNC) ? 'X' : ' ');
+
+	free(render_info);
+
+	SDL_RenderSetLogicalSize(m_renderer, m_width, m_height);
+	SDL_SetRenderDrawBlendMode(m_renderer, SDL_BLENDMODE_NONE);
+
+	m_rending_texture = SDL_CreateTexture(m_renderer,
+		SDL_PIXELFORMAT_RGB24,  
+		SDL_TEXTUREACCESS_STREAMING,
+		m_width,
+		m_height);
+
+	if (m_rending_texture == NULL){
+		m_callback->Debug("RENDER: (SDL2) Couldn't get a texture for rendering: %s", SDL_GetError());
+		VideoRenderDestroy();
+		return -4;
+	}
+
+	return 0;
+}
+
+
+int VideoRenderImpl::StartVideoRender()
+{
+	return 0;
+}
+
+int VideoRenderImpl::ShowVideoWindow()
+{
+	int iret = -1;
+	if (NULL != m_sdl_window){
+		SDL_ShowWindow(m_sdl_window);
+		iret = 0;
+	}
+	return iret;
+}
+
+int VideoRenderImpl::HideVideoWindow()
+{
+	int iret = -1;
+	if (NULL != m_sdl_window) {
+		SDL_HideWindow(m_sdl_window);
+		iret = 0;
+	}
+	return iret;
+}
+
+
+int VideoRenderImpl::StopVideoRender()
+{
+	return 0;
+}
+
+
+void VideoRenderImpl::VideoRenderDestroy()
+{
+	delete this;
+}
+
+
+int VideoRenderImpl::RenderVideoFrame(video_frame* pframe)
+{
+	int iret = -1;
+	if (NULL == m_sdl_window || NULL == pframe || NULL == m_renderer || m_rending_texture){
+		return iret;
+	}
+
+	SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, 255); /*black*/
+	SDL_RenderClear(m_renderer);
+
+	/* since data is continuous we can use SDL_UpdateTexture
+	 * instead of SDL_UpdateYUVTexture.
+	 * no need to use SDL_Lock/UnlockTexture (it doesn't seem faster)
+	 */
+	SDL_UpdateTexture(m_rending_texture, NULL, pframe->data, pframe->width);
+
+	SDL_RenderCopy(m_renderer, m_rending_texture, NULL, NULL);
+
+	SDL_RenderPresent(m_renderer);
+
+	iret = 0;
+
+	return iret;
+}

+ 39 - 0
Other/libvideorender/libvideorender.h

@@ -0,0 +1,39 @@
+#pragma once
+
+#include "ivideorenderinterface.h"
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_video.h>
+#include <SDL2/SDL_render.h>
+#include <SDL2/SDL_rect.h>
+#include <SDL2/SDL_mutex.h>
+
+
+class VideoRenderImpl : public IVideoRender
+{
+public:
+	VideoRenderImpl(IRenderCallback* pCallback);
+	~VideoRenderImpl();
+
+	int VideoRenderSetParam();
+	int StartVideoRender();
+	int StopVideoRender();
+	void VideoRenderDestroy();
+	int ShowVideoWindow();
+	int HideVideoWindow();
+	int RenderVideoFrame(video_frame* pframe);
+
+
+private:
+	SDL_Window* m_sdl_window;
+	SDL_Texture* m_rending_texture;
+	SDL_Renderer* m_renderer;
+	IRenderCallback* m_callback;
+
+	int m_cx;
+	int m_cy;
+	uint32_t m_videowidth;
+	uint32_t m_videoheight;
+	uint32_t m_width;
+	uint32_t m_height;
+	uint32_t m_flags;
+};