From 58171c822a925f06cb8e4e046c2aa2d34572f2cc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 5 May 2015 17:32:40 +0100 Subject: [PATCH] renderer: Use a structure for information passed from renderer to codec I need an additional opaque pointer to be passed from renderer to codec (to allow a pool owned by renderer to be used by decoder). It was decided rather than adding an extra function/parameter that entending the information to use a structure would be more maintainable. --- xbmc/cores/VideoRenderers/BaseRenderer.h | 6 ++--- xbmc/cores/VideoRenderers/LinuxRendererGL.cpp | 12 ++++++---- xbmc/cores/VideoRenderers/LinuxRendererGL.h | 4 +--- .../VideoRenderers/LinuxRendererGLES.cpp | 14 +++++++---- xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 4 +--- xbmc/cores/VideoRenderers/MMALRenderer.cpp | 15 ++++++++++++ xbmc/cores/VideoRenderers/MMALRenderer.h | 4 +--- xbmc/cores/VideoRenderers/RenderFormats.h | 18 ++++++++++++++ xbmc/cores/VideoRenderers/RenderManager.cpp | 24 +++++++------------ xbmc/cores/VideoRenderers/RenderManager.h | 6 ++--- xbmc/cores/VideoRenderers/WinRenderer.cpp | 10 +++++--- xbmc/cores/VideoRenderers/WinRenderer.h | 4 +--- xbmc/cores/dvdplayer/DVDCodecs/DVDCodecs.h | 1 + .../dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 10 ++++---- .../dvdplayer/DVDCodecs/DVDFactoryCodec.h | 3 ++- .../dvdplayer/DVDCodecs/Video/MMALCodec.cpp | 5 +++- .../dvdplayer/DVDCodecs/Video/MMALCodec.h | 1 + xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 12 ++++------ 18 files changed, 94 insertions(+), 59 deletions(-) diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoRenderers/BaseRenderer.h index 389695ac30b6c..57607146d285e 100644 --- a/xbmc/cores/VideoRenderers/BaseRenderer.h +++ b/xbmc/cores/VideoRenderers/BaseRenderer.h @@ -95,8 +95,6 @@ class CBaseRenderer /** * Returns number of references a single buffer can retain when rendering a single frame */ - virtual unsigned int GetOptimalBufferSize() { return 0; } - virtual unsigned int GetMaxBufferSize() { return 0; } virtual void SetBufferSize(int numBuffers) { } virtual void ReleaseBuffer(int idx) { } virtual bool NeedBufferForRef(int idx) { return false; } @@ -104,8 +102,8 @@ class CBaseRenderer virtual bool Supports(ERENDERFEATURE feature) { return false; } - // Supported pixel formats, can be called before configure - std::vector SupportedFormats() { return std::vector(); } + // Render info, can be called before configure + virtual CRenderInfo GetRenderInfo() { return CRenderInfo(); } virtual void RegisterRenderUpdateCallBack(const void *ctx, RenderUpdateCallBackFn fn); virtual void RegisterRenderFeaturesCallBack(const void *ctx, RenderFeaturesCallBackFn fn); diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp index 9ff1f00b1f85e..aee894bff6308 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.cpp @@ -3456,17 +3456,21 @@ void CLinuxRendererGL::UnBindPbo(YUVBUFFER& buff) glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } -unsigned int CLinuxRendererGL::GetOptimalBufferSize() +CRenderInfo CLinuxRendererGL::GetRenderInfo() { + CRenderInfo info; + info.formats = m_formats; + info.max_buffer_size = NUM_BUFFERS; if(m_format == RENDER_FMT_CVBREF) - return 2; + info.optimal_buffer_size = 2; else if (m_format == RENDER_FMT_VAAPI || m_format == RENDER_FMT_VAAPINV12 || m_format == RENDER_FMT_VDPAU || m_format == RENDER_FMT_VDPAU_420) - return 5; + info.optimal_buffer_size = 5; else - return 3; + info.optimal_buffer_size = 3; + return info; } #ifdef HAVE_LIBVDPAU diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoRenderers/LinuxRendererGL.h index 2f757d84cf869..fcdea8da71d24 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGL.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGL.h @@ -134,8 +134,6 @@ class CLinuxRendererGL : public CBaseRenderer virtual void Flush(); virtual void ReleaseBuffer(int idx); virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } - virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } - virtual unsigned int GetOptimalBufferSize(); #ifdef HAVE_LIBVDPAU virtual void AddProcessor(VDPAU::CVdpauRenderPicture* vdpau, int index); @@ -158,7 +156,7 @@ class CLinuxRendererGL : public CBaseRenderer virtual EINTERLACEMETHOD AutoInterlaceMethod(); - virtual std::vector SupportedFormats() { return m_formats; } + virtual CRenderInfo GetRenderInfo(); protected: virtual void Render(DWORD flags, int renderBuffer); diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp index 8276687cece0d..930eecb403b3b 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp @@ -2980,18 +2980,24 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod() #endif } -unsigned int CLinuxRendererGLES::GetOptimalBufferSize() +CRenderInfo CLinuxRendererGLES::GetRenderInfo() { + CRenderInfo info; + info.formats = m_formats; + info.max_buffer_size = NUM_BUFFERS; if(m_format == RENDER_FMT_OMXEGL || m_format == RENDER_FMT_CVBREF || m_format == RENDER_FMT_EGLIMG || m_format == RENDER_FMT_MEDIACODEC) - return 2; + info.optimal_buffer_size = 2; else if(m_format == RENDER_FMT_IMXMAP) + { // Let the codec control the buffer size - return GetMaxBufferSize(); + info.optimal_buffer_size = info.max_buffer_size; + } else - return 3; + info.optimal_buffer_size = 3; + return info; } #ifdef HAVE_LIBOPENMAX diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h index 7b783438ca89d..2d803d5f44fec 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h @@ -145,8 +145,6 @@ class CLinuxRendererGLES : public CBaseRenderer virtual void ReorderDrawPoints(); virtual void ReleaseBuffer(int idx); virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } - virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } - virtual unsigned int GetOptimalBufferSize(); virtual bool IsGuiLayer(); virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); @@ -160,7 +158,7 @@ class CLinuxRendererGLES : public CBaseRenderer virtual EINTERLACEMETHOD AutoInterlaceMethod(); - virtual std::vector SupportedFormats() { return m_formats; } + virtual CRenderInfo GetRenderInfo(); #ifdef HAVE_LIBOPENMAX virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index); diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.cpp b/xbmc/cores/VideoRenderers/MMALRenderer.cpp index 8d1c3381f137e..990f6c69242e5 100644 --- a/xbmc/cores/VideoRenderers/MMALRenderer.cpp +++ b/xbmc/cores/VideoRenderers/MMALRenderer.cpp @@ -39,6 +39,21 @@ #define MMAL_DEBUG_VERBOSE #endif +CRenderInfo CMMALRenderer::GetRenderInfo() +{ + CRenderInfo info; + + #if defined(MMAL_DEBUG_VERBOSE) + CLog::Log(LOGDEBUG, "%s::%s cookie:%p", CLASSNAME, __func__, (void *)m_vout_input_pool); + #endif + + info.max_buffer_size = NUM_BUFFERS; + info.optimal_buffer_size = NUM_BUFFERS; + info.opaque_pointer = (void *)m_vout_input_pool; + info.formats = m_formats; + return info; +} + static void vout_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { mmal_buffer_header_release(buffer); diff --git a/xbmc/cores/VideoRenderers/MMALRenderer.h b/xbmc/cores/VideoRenderers/MMALRenderer.h index 17b189e515bd0..eba8e0ffeef3e 100644 --- a/xbmc/cores/VideoRenderers/MMALRenderer.h +++ b/xbmc/cores/VideoRenderers/MMALRenderer.h @@ -72,7 +72,7 @@ class CMMALRenderer : public CBaseRenderer, public CThread virtual void Flush(); virtual bool IsConfigured() { return m_bConfigured; } virtual void AddProcessor(CMMALVideoBuffer *buffer, int index); - virtual std::vector SupportedFormats() { return m_formats; } + virtual CRenderInfo GetRenderInfo(); virtual bool Supports(ERENDERFEATURE feature); virtual bool Supports(EDEINTERLACEMODE mode); @@ -84,8 +84,6 @@ class CMMALRenderer : public CBaseRenderer, public CThread void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); virtual void SetBufferSize(int numBuffers) { m_NumYV12Buffers = numBuffers; } - virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } - virtual unsigned int GetOptimalBufferSize() { return NUM_BUFFERS; } virtual void SetVideoRect(const CRect& SrcRect, const CRect& DestRect); virtual bool IsGuiLayer() { return false; } diff --git a/xbmc/cores/VideoRenderers/RenderFormats.h b/xbmc/cores/VideoRenderers/RenderFormats.h index 6394ef1983157..97634c278c7c2 100644 --- a/xbmc/cores/VideoRenderers/RenderFormats.h +++ b/xbmc/cores/VideoRenderers/RenderFormats.h @@ -20,6 +20,8 @@ * */ +#include + enum ERenderFormat { RENDER_FMT_NONE = 0, RENDER_FMT_YUV420P, @@ -42,4 +44,20 @@ enum ERenderFormat { RENDER_FMT_MMAL, }; +struct CRenderInfo +{ + CRenderInfo() + { + optimal_buffer_size = 0; + max_buffer_size = 0; + opaque_pointer = NULL; + } + unsigned int optimal_buffer_size; + unsigned int max_buffer_size; + // Supported pixel formats, can be called before configure + std::vector formats; + // Can be used for initialising video codec with information from renderer (e.g. a shared image pool) + void *opaque_pointer; +}; + #endif diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp index 6de299e3c91b5..72edb11b9d35d 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.cpp +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp @@ -273,11 +273,13 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi lock2.Enter(); m_format = format; - int renderbuffers = m_pRenderer->GetOptimalBufferSize(); + CRenderInfo info = m_pRenderer->GetRenderInfo(); + int renderbuffers = info.optimal_buffer_size; m_QueueSize = renderbuffers; if (buffers > 0) m_QueueSize = std::min(buffers, renderbuffers); - m_QueueSize = std::min(m_QueueSize, (int)m_pRenderer->GetMaxBufferSize()); + + m_QueueSize = std::min(m_QueueSize, (int)info.max_buffer_size); m_QueueSize = std::min(m_QueueSize, NUM_BUFFERS); if(m_QueueSize < 2) { @@ -936,25 +938,17 @@ void CXBMCRenderManager::UpdateResolution() } } - -unsigned int CXBMCRenderManager::GetOptimalBufferSize() +// Get renderer info, can be called before configure +CRenderInfo CXBMCRenderManager::GetRenderInfo() { CSharedLock lock(m_sharedSection); + CRenderInfo info; if (!m_pRenderer) { CLog::Log(LOGERROR, "%s - renderer is NULL", __FUNCTION__); - return 0; + return CRenderInfo(); } - return m_pRenderer->GetMaxBufferSize(); -} - -// Supported pixel formats, can be called before configure -std::vector CXBMCRenderManager::SupportedFormats() -{ - CSharedLock lock(m_sharedSection); - if (m_pRenderer) - return m_pRenderer->SupportedFormats(); - return std::vector(); + return m_pRenderer->GetRenderInfo(); } int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic) diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h index 4e553cb19985d..f43bff1254419 100644 --- a/xbmc/cores/VideoRenderers/RenderManager.h +++ b/xbmc/cores/VideoRenderers/RenderManager.h @@ -162,10 +162,8 @@ class CXBMCRenderManager CLinuxRenderer *m_pRenderer; #endif - unsigned int GetOptimalBufferSize(); - - // Supported pixel formats, can be called before configure - std::vector SupportedFormats(); + // Get renderer info, can be called before configure + CRenderInfo GetRenderInfo(); void Recover(); // called after resolution switch if something special is needed diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp index 04e130091ad7f..949143de0e69f 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.cpp +++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp @@ -1331,12 +1331,16 @@ EINTERLACEMETHOD CWinRenderer::AutoInterlaceMethod() return VS_INTERLACEMETHOD_DEINTERLACE_HALF; } -unsigned int CWinRenderer::GetOptimalBufferSize() +CRenderInfo CWinRenderer::GetRenderInfo() { + CRenderInfo info; + info.formats = m_formats; + info.max_buffer_size = NUM_BUFFERS; if (m_format == RENDER_FMT_DXVA && m_processor) - return m_processor->Size(); + info.optimal_buffer_size = m_processor->Size(); else - return 3; + info.optimal_buffer_size = 3; + return info; } void CWinRenderer::ReleaseBuffer(int idx) diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h index 65b0501877688..d456af9b300e9 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.h +++ b/xbmc/cores/VideoRenderers/WinRenderer.h @@ -157,7 +157,7 @@ class CWinRenderer : public CBaseRenderer virtual bool IsConfigured() { return m_bConfigured; } virtual void Flush(); - virtual std::vector SupportedFormats() { return m_formats; } + virtual CRenderInfo GetRenderInfo(); virtual bool Supports(ERENDERFEATURE feature); virtual bool Supports(EDEINTERLACEMODE mode); @@ -168,9 +168,7 @@ class CWinRenderer : public CBaseRenderer void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255); - virtual unsigned int GetOptimalBufferSize(); virtual void SetBufferSize(int numBuffers) { m_neededBuffers = numBuffers; } - virtual unsigned int GetMaxBufferSize() { return NUM_BUFFERS; } virtual void ReleaseBuffer(int idx); virtual bool NeedBufferForRef(int idx); diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecs.h b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecs.h index 99db9fcee9937..1f2b39a1e1859 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecs.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDCodecs.h @@ -46,4 +46,5 @@ class CDVDCodecOptions public: std::vector m_keys; std::vector m_formats; + const void *m_opaque_pointer; }; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp index 7b96cc9fca2c3..8a3beb74d4ca1 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp @@ -134,15 +134,17 @@ CDVDOverlayCodec* CDVDFactoryCodec::OpenCodec(CDVDOverlayCodec* pCodec, CDVDStre } -CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigned int surfaces, const std::vector& formats) +CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, const CRenderInfo &info) { CDVDVideoCodec* pCodec = NULL; CDVDCodecOptions options; - if(formats.empty()) + if(info.formats.empty()) options.m_formats.push_back(RENDER_FMT_YUV420P); else - options.m_formats = formats; + options.m_formats = info.formats; + + options.m_opaque_pointer = info.opaque_pointer; //when support for a hardware decoder is not compiled in //only print it if it's actually available on the platform @@ -338,7 +340,7 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne } #endif - std::string value = StringUtils::Format("%d", surfaces); + std::string value = StringUtils::Format("%d", info.optimal_buffer_size); options.m_keys.push_back(CDVDCodecOption("surfaces", value)); if( (pCodec = OpenCodec(new CDVDVideoCodecFFmpeg(), hint, options)) ) return pCodec; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h index f7ce44cb33359..1fd7f72326d5f 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h @@ -22,6 +22,7 @@ #include #include "cores/VideoRenderers/RenderFormats.h" +#include "cores/VideoRenderers/BaseRenderer.h" class CDVDVideoCodec; class CDVDAudioCodec; @@ -35,7 +36,7 @@ class CDVDCodecOptions; class CDVDFactoryCodec { public: - static CDVDVideoCodec* CreateVideoCodec(CDVDStreamInfo &hint, unsigned int surfaces = 0, const std::vector& formats = std::vector()); + static CDVDVideoCodec* CreateVideoCodec(CDVDStreamInfo &hint, const CRenderInfo &info = CRenderInfo()); static CDVDAudioCodec* CreateAudioCodec(CDVDStreamInfo &hint ); static CDVDOverlayCodec* CreateOverlayCodec(CDVDStreamInfo &hint ); diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp index ff8af3569a5fa..e88d24bdec11b 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.cpp @@ -29,6 +29,7 @@ #include "DVDClock.h" #include "DVDStreamInfo.h" #include "windowing/WindowingFactory.h" +#include "cores/dvdplayer/DVDCodecs/DVDCodecs.h" #include "DVDVideoCodec.h" #include "utils/log.h" #include "utils/TimeUtils.h" @@ -114,6 +115,7 @@ CMMALVideo::CMMALVideo() m_dec_output = NULL; m_dec_input_pool = NULL; m_dec_output_pool = NULL; + m_vout_input_pool = NULL; m_deint = NULL; m_deint_connection = NULL; @@ -508,13 +510,14 @@ bool CMMALVideo::SendCodecConfigData() bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVideoPtr myself) { if (g_advancedSettings.CanLogComponent(LOGVIDEO)) - CLog::Log(LOGDEBUG, "%s::%s usemmal:%d software:%d %dx%d", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.usemmal"), hints.software, hints.width, hints.height); + CLog::Log(LOGDEBUG, "%s::%s usemmal:%d software:%d %dx%d pool:%p", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.usemmal"), hints.software, hints.width, hints.height, options.m_opaque_pointer); // we always qualify even if DVDFactoryCodec does this too. if (!CSettings::Get().GetBool("videoplayer.usemmal") || hints.software) return false; m_hints = hints; + m_vout_input_pool = (MMAL_POOL_T *)options.m_opaque_pointer; MMAL_STATUS_T status; MMAL_PARAMETER_BOOLEAN_T error_concealment; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h index 8f623368407e4..a5d872a15793f 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/MMALCodec.h @@ -144,6 +144,7 @@ class CMMALVideo MMAL_PORT_T *m_dec_output; MMAL_POOL_T *m_dec_input_pool; MMAL_POOL_T *m_dec_output_pool; + MMAL_POOL_T *m_vout_input_pool; MMAL_ES_FORMAT_T *m_es_format; MMAL_COMPONENT_T *m_deint; diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp index 353d83d575293..55fa8b1b5071a 100644 --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp @@ -178,19 +178,17 @@ double CDVDPlayerVideo::GetOutputDelay() bool CDVDPlayerVideo::OpenStream( CDVDStreamInfo &hint ) { - unsigned int surfaces = 0; - std::vector formats; -#ifdef HAS_VIDEO_PLAYBACK - surfaces = g_renderManager.GetOptimalBufferSize(); - formats = g_renderManager.SupportedFormats(); -#endif + CRenderInfo info; + #ifdef HAS_VIDEO_PLAYBACK + info = g_renderManager.GetRenderInfo(); + #endif m_pullupCorrection.ResetVFRDetection(); if(hint.flags & AV_DISPOSITION_ATTACHED_PIC) return false; CLog::Log(LOGNOTICE, "Creating video codec with codec id: %i", hint.codec); - CDVDVideoCodec* codec = CDVDFactoryCodec::CreateVideoCodec(hint, surfaces, formats); + CDVDVideoCodec* codec = CDVDFactoryCodec::CreateVideoCodec(hint, info); if(!codec) { CLog::Log(LOGERROR, "Unsupported video codec");