|
|
@@ -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;
|
|
|
+}
|