From 3079b42cc4a7a17c0d8bd3afdd462d6363cc4ee7 Mon Sep 17 00:00:00 2001 From: IceCryptonym Date: Sat, 11 Apr 2020 20:05:18 +1000 Subject: [PATCH] Nitpicks --- main.cpp | 19 ++-- src/WallpaperEngine/Core/CVideo.cpp | 108 +++++++++------------- src/WallpaperEngine/Core/CVideo.h | 15 ++- src/WallpaperEngine/Irrlicht/CContext.cpp | 11 ++- src/WallpaperEngine/Irrlicht/CContext.h | 8 +- src/WallpaperEngine/Render/CScene.cpp | 34 +------ src/WallpaperEngine/Render/CScene.h | 17 +--- src/WallpaperEngine/Render/CVideo.cpp | 95 +++++++++++++++---- src/WallpaperEngine/Render/CVideo.h | 23 +++-- src/WallpaperEngine/Render/CWallpaper.cpp | 28 +++++- src/WallpaperEngine/Render/CWallpaper.h | 32 +++++-- 11 files changed, 229 insertions(+), 161 deletions(-) diff --git a/main.cpp b/main.cpp index aa70682..4248094 100644 --- a/main.cpp +++ b/main.cpp @@ -165,21 +165,26 @@ int main (int argc, char* argv[]) WallpaperEngine::Core::CProject* project = WallpaperEngine::Core::CProject::fromFile (project_path); WallpaperEngine::Render::CWallpaper* wallpaper; - if (strcmp (project->getType ().c_str (), "scene") == 0) + if (project->getType () == "scene") { - wallpaper = new WallpaperEngine::Render::CScene (project->getWallpaper ()->as (), IrrlichtContext); + WallpaperEngine::Core::CScene* scene = project->getWallpaper ()->as (); + wallpaper = new WallpaperEngine::Render::CScene (scene, IrrlichtContext); IrrlichtContext->getDevice ()->getSceneManager ()->setAmbientLight ( - wallpaper->getWallpaperData ()->as ()->getAmbientColor ().toSColor () + scene->getAmbientColor ().toSColor () ); } - else if (strcmp (project->getType ().c_str (), "video") == 0) + else if (project->getType () == "video") { wallpaper = new WallpaperEngine::Render::CVideo ( project->getWallpaper ()->as (), - IrrlichtContext->getDevice ()->getVideoDriver () + IrrlichtContext ); } - + else + { + throw std::runtime_error ("Unsupported wallpaper type"); + } + irr::u32 minimumTime = 1000 / maximumFPS; irr::u32 startTime = 0; irr::u32 endTime = 0; @@ -191,7 +196,7 @@ int main (int argc, char* argv[]) startTime = IrrlichtContext->getDevice ()->getTimer ()->getTime (); - wallpaper->renderWallpaper (); + IrrlichtContext->renderFrame (wallpaper); endTime = IrrlichtContext->getDevice ()->getTimer ()->getTime (); diff --git a/src/WallpaperEngine/Core/CVideo.cpp b/src/WallpaperEngine/Core/CVideo.cpp index 0fa2f36..bda74da 100644 --- a/src/WallpaperEngine/Core/CVideo.cpp +++ b/src/WallpaperEngine/Core/CVideo.cpp @@ -46,17 +46,23 @@ CVideo::CVideo ( if (avcodec_open2 (m_codecCtx, codec, NULL) < 0) throw std::runtime_error ("Failed to open codec"); -} -void CVideo::initFrames (int width, int height) -{ m_videoFrame = av_frame_alloc (); m_videoFrameRGB = av_frame_alloc (); if (m_videoFrameRGB == nullptr) throw std::runtime_error ("Failed to allocate video frame"); +} + +void CVideo::setSize (int width, int height) +{ + if (buffer != nullptr) + av_free (buffer); + + if (m_swsCtx != nullptr) + sws_freeContext (m_swsCtx); int numBytes = av_image_get_buffer_size (AV_PIX_FMT_RGB24, width, height, 1); - uint8_t* buffer = (uint8_t*)av_malloc (numBytes * sizeof (uint8_t)); + buffer = (uint8_t*)av_malloc (numBytes * sizeof (uint8_t)); av_image_fill_arrays (m_videoFrameRGB->data, m_videoFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, width, height, 1); @@ -65,65 +71,6 @@ void CVideo::initFrames (int width, int height) width, height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL); - - avcodec_flush_buffers (m_codecCtx); -} - -void CVideo::getNextFrame () -{ - bool eof = false; - AVPacket packet; - packet.data = nullptr; - - // Find video streams packet - do - { - if (packet.data != nullptr) - av_packet_unref (&packet); - - int readError = av_read_frame (m_formatCtx, &packet); - if (readError == AVERROR_EOF) - { - eof = true; - break; - } - else if (readError < 0) - { - char err[AV_ERROR_MAX_STRING_SIZE]; - throw std::runtime_error (av_make_error_string (err, AV_ERROR_MAX_STRING_SIZE, readError)); - } - - } while (packet.stream_index != m_videoStream); - - // Send video stream packet to codec - if (avcodec_send_packet (m_codecCtx, &packet) < 0) - return; - - // Receive frame from codec - if (avcodec_receive_frame (m_codecCtx, m_videoFrame) < 0) - return; - - sws_scale (m_swsCtx, (uint8_t const* const*)m_videoFrame->data, m_videoFrame->linesize, - 0, m_codecCtx->height, m_videoFrameRGB->data, m_videoFrameRGB->linesize); - - av_packet_unref (&packet); - - if (eof) - restartStream (); -} - -void CVideo::writeFrameToImage (irr::video::IImage* image) -{ - uint8_t* frameData = m_videoFrameRGB->data[0]; - if (frameData == nullptr) - return; - - irr::u32 imgWidth = image->getDimension().Width; - irr::u32 imgHeight = image->getDimension().Height; - - unsigned char* data = (unsigned char*)image->lock (); - memcpy (data, frameData, imgWidth * imgHeight * 3); - image->unlock (); } void CVideo::restartStream () @@ -132,4 +79,39 @@ void CVideo::restartStream () avcodec_flush_buffers (m_codecCtx); } +AVFormatContext* CVideo::getFormatContext () +{ + return this->m_formatCtx; +} + +AVCodecContext* CVideo::getCodecContext () +{ + return this->m_codecCtx; +} + +AVFrame* CVideo::getVideoFrame () +{ + return this->m_videoFrame; +} + +AVFrame* CVideo::getVideoFrameRGB () +{ + return this->m_videoFrameRGB; +} + +SwsContext* CVideo::getSwsContext () +{ + return this->m_swsCtx; +} + +int CVideo::getVideoStreamIndex () +{ + return this->m_videoStream; +} + +int CVideo::getAudioStreamIndex () +{ + return this->m_audioStream; +} + const std::string CVideo::Type = "video"; diff --git a/src/WallpaperEngine/Core/CVideo.h b/src/WallpaperEngine/Core/CVideo.h index e51162a..22ca896 100644 --- a/src/WallpaperEngine/Core/CVideo.h +++ b/src/WallpaperEngine/Core/CVideo.h @@ -22,24 +22,29 @@ namespace WallpaperEngine::Core const irr::io::path& filename ); - void initFrames (int width, int height); + void setSize (int width, int height); + void restartStream (); - void getNextFrame (); - void writeFrameToImage (irr::video::IImage* image); + AVFormatContext* getFormatContext (); + AVCodecContext* getCodecContext (); + AVFrame* getVideoFrame (); + AVFrame* getVideoFrameRGB (); + SwsContext* getSwsContext (); + int getVideoStreamIndex (); + int getAudioStreamIndex (); protected: friend class CWallpaper; static const std::string Type; - void restartStream (); - private: AVFormatContext* m_formatCtx = nullptr; AVCodecContext* m_codecCtx = nullptr; AVFrame* m_videoFrame = nullptr; AVFrame* m_videoFrameRGB = nullptr; SwsContext* m_swsCtx = nullptr; + uint8_t* buffer = nullptr; int m_videoStream = -1, m_audioStream = -1; }; diff --git a/src/WallpaperEngine/Irrlicht/CContext.cpp b/src/WallpaperEngine/Irrlicht/CContext.cpp index d68f5f4..83465b3 100644 --- a/src/WallpaperEngine/Irrlicht/CContext.cpp +++ b/src/WallpaperEngine/Irrlicht/CContext.cpp @@ -162,7 +162,7 @@ void CContext::initializeViewports (irr::SIrrlichtCreationParameters &irrlichtCr irrlichtCreationParameters.WindowId = reinterpret_cast (DefaultRootWindow (display)); } -void CContext::renderFrame (Render::CScene* scene) +void CContext::renderFrame (Render::CWallpaper* wallpaper) { this->m_time = this->getDevice ()->getTimer ()->getTime () / 1000.0f; this->m_pointerPosition.X = this->m_eventReceiver->getPosition ().X / (irr::f32) this->getDevice ()->getVideoDriver ()->getScreenSize ().Width; @@ -170,7 +170,7 @@ void CContext::renderFrame (Render::CScene* scene) if (this->m_viewports.empty () == true) { - this->drawScene (scene, true); + this->drawWallpaper (wallpaper, true); } else { @@ -181,14 +181,15 @@ void CContext::renderFrame (Render::CScene* scene) { // change viewport to render to the correct portion of the display this->getDevice ()->getVideoDriver ()->setViewPort (*cur); - this->drawScene (scene, false); + this->drawWallpaper (wallpaper, false); } } } -void CContext::drawScene (Render::CScene* scene, bool backBuffer) +void CContext::drawWallpaper (Render::CWallpaper* wallpaper, bool backBuffer) { - this->getDevice ()->getVideoDriver ()->beginScene (backBuffer, true, scene->getWallpaperData ()->as ()->getClearColor ().toSColor()); + // TODO: Get scene clear color + this->getDevice ()->getVideoDriver ()->beginScene (backBuffer, true); this->getDevice ()->getSceneManager ()->drawAll (); this->getDevice ()->getVideoDriver ()->endScene (); } diff --git a/src/WallpaperEngine/Irrlicht/CContext.h b/src/WallpaperEngine/Irrlicht/CContext.h index c456b92..d254f55 100644 --- a/src/WallpaperEngine/Irrlicht/CContext.h +++ b/src/WallpaperEngine/Irrlicht/CContext.h @@ -5,7 +5,7 @@ #include -#include "WallpaperEngine/Render/CScene.h" +#include "WallpaperEngine/Render/CWallpaper.h" #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h" @@ -13,7 +13,7 @@ namespace WallpaperEngine::Render { - class CScene; + class CWallpaper; }; namespace WallpaperEngine::Irrlicht @@ -29,7 +29,7 @@ namespace WallpaperEngine::Irrlicht void insertShaderVariable (Render::Shaders::Variables::CShaderVariable* variable); const std::vector& getShaderVariables () const; - void renderFrame (Render::CScene* scene); + void renderFrame (Render::CWallpaper* wallpaper); irr::IrrlichtDevice* getDevice (); irr::io::path resolveMaterials (const std::string& materialName); @@ -38,7 +38,7 @@ namespace WallpaperEngine::Irrlicht irr::io::path resolveIncludeShader (const std::string& includeShader); private: void initializeViewports (irr::SIrrlichtCreationParameters& irrlichtCreationParameters); - void drawScene (Render::CScene* scene, bool backBuffer); + void drawWallpaper (Render::CWallpaper* wallpaper, bool backBuffer); irr::io::path resolveFile (const irr::io::path& file); diff --git a/src/WallpaperEngine/Render/CScene.cpp b/src/WallpaperEngine/Render/CScene.cpp index 3491696..d8f3c08 100644 --- a/src/WallpaperEngine/Render/CScene.cpp +++ b/src/WallpaperEngine/Render/CScene.cpp @@ -1,5 +1,3 @@ -#include "WallpaperEngine/Irrlicht/CContext.h" - #include "WallpaperEngine/Core/Objects/CImage.h" #include "WallpaperEngine/Core/Objects/CSound.h" @@ -12,12 +10,7 @@ using namespace WallpaperEngine; using namespace WallpaperEngine::Render; CScene::CScene (Core::CScene* scene, Irrlicht::CContext* context) : - CWallpaper (scene, Type), - irr::scene::ISceneNode ( - context->getDevice ()->getSceneManager ()->getRootSceneNode (), - context->getDevice ()->getSceneManager () - ), - m_context (context) + CWallpaper (scene, Type, context) { this->m_camera = new CCamera (this, scene->getCamera ()); this->m_camera->setOrthogonalProjection ( @@ -47,16 +40,6 @@ CScene::CScene (Core::CScene* scene, Irrlicht::CContext* context) : this->m_nextId = ++highestId; this->setAutomaticCulling (irr::scene::EAC_OFF); - this->m_boundingBox = irr::core::aabbox3d(0, 0, 0, 0, 0, 0); -} - -CScene::~CScene () -{ -} - -Irrlicht::CContext* CScene::getContext () -{ - return this->m_context; } CCamera* CScene::getCamera () const @@ -73,20 +56,9 @@ void CScene::render () { } -void CScene::renderWallpaper () +Core::CScene* CScene::getScene () { - this->m_context->renderFrame (this); -} - -const irr::core::aabbox3d& CScene::getBoundingBox () const -{ - return this->m_boundingBox; -} -void CScene::OnRegisterSceneNode () -{ - SceneManager->registerNodeForRendering (this); - - ISceneNode::OnRegisterSceneNode (); + return this->getWallpaperData ()->as (); } const std::string CScene::Type = "scene"; diff --git a/src/WallpaperEngine/Render/CScene.h b/src/WallpaperEngine/Render/CScene.h index fe4440f..96f1c86 100644 --- a/src/WallpaperEngine/Render/CScene.h +++ b/src/WallpaperEngine/Render/CScene.h @@ -8,30 +8,21 @@ #include "WallpaperEngine/Irrlicht/CContext.h" -namespace WallpaperEngine::Irrlicht -{ - class CContext; -}; - namespace WallpaperEngine::Render { class CCamera; - class CScene : public CWallpaper, public irr::scene::ISceneNode + class CScene : public CWallpaper { public: - CScene (Core::CScene* scene, Irrlicht::CContext* context); - ~CScene () override; + CScene (Core::CScene* scene, WallpaperEngine::Irrlicht::CContext* context); - Irrlicht::CContext* getContext (); CCamera* getCamera () const; int nextId (); void render () override; - const irr::core::aabbox3d& getBoundingBox() const override; - void OnRegisterSceneNode () override; - void renderWallpaper () override; + Core::CScene* getScene (); protected: friend class CWallpaper; @@ -40,8 +31,6 @@ namespace WallpaperEngine::Render private: CCamera* m_camera; - Irrlicht::CContext* m_context; irr::u32 m_nextId; - irr::core::aabbox3d m_boundingBox; }; } diff --git a/src/WallpaperEngine/Render/CVideo.cpp b/src/WallpaperEngine/Render/CVideo.cpp index f8c0e51..72228af 100644 --- a/src/WallpaperEngine/Render/CVideo.cpp +++ b/src/WallpaperEngine/Render/CVideo.cpp @@ -4,31 +4,92 @@ using namespace WallpaperEngine; using namespace WallpaperEngine::Render; -CVideo::CVideo (Core::CVideo* video, irr::video::IVideoDriver* driver) : - CWallpaper (video, Type), - m_driver (driver) +CVideo::CVideo (Core::CVideo* video, WallpaperEngine::Irrlicht::CContext* context) : + CWallpaper (video, Type, context) { - int width = driver->getScreenSize ().Width; - int height = driver->getScreenSize ().Height; - video->initFrames (width, height); - m_frameImage = m_driver->createImage (irr::video::ECOLOR_FORMAT::ECF_R8G8B8, - irr::core::dimension2du(width, height)); } -void CVideo::renderWallpaper () +void CVideo::render () { - m_driver->beginScene (); + irr::video::IVideoDriver* driver = m_context->getDevice ()->getVideoDriver (); + int width = driver->getScreenSize ().Width; + int height = driver->getScreenSize ().Height; - Core::CVideo* video = m_wallpaperData->as (); - video->getNextFrame (); - video->writeFrameToImage (m_frameImage); + m_frameImage = m_context->getDevice ()->getVideoDriver ()->createImage (irr::video::ECOLOR_FORMAT::ECF_R8G8B8, + irr::core::dimension2du(width, height)); - m_driver->removeTexture (m_frameTexture); - m_frameTexture = m_driver->addTexture ("frameTexture", m_frameImage); + getVideo ()->setSize (width, height); + getNextFrame (); + writeFrameToImage (); - m_driver->draw2DImage (m_frameTexture, irr::core::vector2di(0)); + driver->removeTexture (m_frameTexture); + m_frameTexture = driver->addTexture ("frameTexture", m_frameImage); + m_frameImage->drop (); - m_driver->endScene (); + driver->draw2DImage (m_frameTexture, irr::core::vector2di(0)); +} + +void CVideo::getNextFrame () +{ + Core::CVideo* videoData = getVideo (); + bool eof = false; + AVPacket packet; + packet.data = nullptr; + + // Find video streams packet + do + { + if (packet.data != nullptr) + av_packet_unref (&packet); + + int readError = av_read_frame (videoData->getFormatContext (), &packet); + if (readError == AVERROR_EOF) + { + eof = true; + break; + } + else if (readError < 0) + { + char err[AV_ERROR_MAX_STRING_SIZE]; + throw std::runtime_error (av_make_error_string (err, AV_ERROR_MAX_STRING_SIZE, readError)); + } + + } while (packet.stream_index != videoData->getVideoStreamIndex ()); + + // Send video stream packet to codec + if (avcodec_send_packet (videoData->getCodecContext (), &packet) < 0) + return; + + // Receive frame from codec + if (avcodec_receive_frame (videoData->getCodecContext (), videoData->getVideoFrame ()) < 0) + return; + + sws_scale (videoData->getSwsContext (), (uint8_t const* const*)videoData->getVideoFrame ()->data, videoData->getVideoFrame ()->linesize, + 0, videoData->getCodecContext ()->height, videoData->getVideoFrameRGB ()->data, videoData->getVideoFrameRGB ()->linesize); + + av_packet_unref (&packet); + + if (eof) + videoData->restartStream (); +} + +void CVideo::writeFrameToImage () +{ + uint8_t* frameData = getVideo ()->getVideoFrameRGB ()->data[0]; + if (frameData == nullptr) + return; + + irr::u32 imgWidth = m_frameImage->getDimension().Width; + irr::u32 imgHeight = m_frameImage->getDimension().Height; + + unsigned char* data = (unsigned char*)m_frameImage->lock (); + memcpy (data, frameData, imgWidth * imgHeight * 3); + m_frameImage->unlock (); +} + +Core::CVideo* CVideo::getVideo () +{ + return this->getWallpaperData ()->as (); } const std::string CVideo::Type = "video"; diff --git a/src/WallpaperEngine/Render/CVideo.h b/src/WallpaperEngine/Render/CVideo.h index 5327dce..6a9bc2e 100644 --- a/src/WallpaperEngine/Render/CVideo.h +++ b/src/WallpaperEngine/Render/CVideo.h @@ -6,16 +6,26 @@ #include "WallpaperEngine/Render/CWallpaper.h" +#include "WallpaperEngine/Irrlicht/CContext.h" + +extern "C" +{ + #include + #include + #include + #include +} + namespace WallpaperEngine::Render { - class CWallpaper; - class CVideo : public CWallpaper { public: - CVideo (Core::CVideo* video, irr::video::IVideoDriver* driver); + CVideo (Core::CVideo* video, WallpaperEngine::Irrlicht::CContext* context); - void renderWallpaper () override; + void render () override; + + Core::CVideo* getVideo (); protected: friend class CWallpaper; @@ -23,9 +33,10 @@ namespace WallpaperEngine::Render static const std::string Type; private: + void getNextFrame (); + void writeFrameToImage (); + irr::video::IImage* m_frameImage; irr::video::ITexture* m_frameTexture; - - irr::video::IVideoDriver* m_driver; }; }; diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp index 015ea73..788e4cd 100644 --- a/src/WallpaperEngine/Render/CWallpaper.cpp +++ b/src/WallpaperEngine/Render/CWallpaper.cpp @@ -2,12 +2,38 @@ using namespace WallpaperEngine::Render; -CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type) : +CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, WallpaperEngine::Irrlicht::CContext* context) : + irr::scene::ISceneNode ( + context->getDevice ()->getSceneManager ()->getRootSceneNode (), + context->getDevice ()->getSceneManager () + ), + m_context (context), m_wallpaperData (wallpaperData), m_type (type) { } +CWallpaper::~CWallpaper () +{ +} + +void CWallpaper::OnRegisterSceneNode () +{ + SceneManager->registerNodeForRendering (this); + + ISceneNode::OnRegisterSceneNode (); +} + +WallpaperEngine::Irrlicht::CContext* CWallpaper::getContext () const +{ + return this->m_context; +} + +const irr::core::aabbox3d& CWallpaper::getBoundingBox () const +{ + return this->m_boundingBox; +} + WallpaperEngine::Core::CWallpaper* CWallpaper::getWallpaperData () { return this->m_wallpaperData; diff --git a/src/WallpaperEngine/Render/CWallpaper.h b/src/WallpaperEngine/Render/CWallpaper.h index 623ffe2..8f260a7 100644 --- a/src/WallpaperEngine/Render/CWallpaper.h +++ b/src/WallpaperEngine/Render/CWallpaper.h @@ -1,12 +1,21 @@ #pragma once -#include +#include #include "WallpaperEngine/Core/CWallpaper.h" +#include "WallpaperEngine/Core/CScene.h" +#include "WallpaperEngine/Core/CVideo.h" + +#include "WallpaperEngine/Irrlicht/CContext.h" + +namespace WallpaperEngine::Irrlicht +{ + class CContext; +}; namespace WallpaperEngine::Render { - class CWallpaper + class CWallpaper : public irr::scene::ISceneNode { public: template const T* as () const { assert (is ()); return (const T*) this; } @@ -14,16 +23,23 @@ namespace WallpaperEngine::Render template bool is () { return this->m_type == T::Type; } - CWallpaper (Core::CWallpaper* wallpaperData, std::string type); + CWallpaper (Core::CWallpaper* wallpaperData, std::string type, WallpaperEngine::Irrlicht::CContext* context); + ~CWallpaper () override; + + void OnRegisterSceneNode () override; + + WallpaperEngine::Irrlicht::CContext* getContext () const; + const irr::core::aabbox3d& getBoundingBox () const override; + + protected: + WallpaperEngine::Irrlicht::CContext* m_context; + Core::CWallpaper* m_wallpaperData; Core::CWallpaper* getWallpaperData (); - virtual void renderWallpaper () = 0; - - protected: - Core::CWallpaper* m_wallpaperData; - private: + irr::core::aabbox3d m_boundingBox = irr::core::aabbox3d (0, 0, 0, 0, 0, 0); + std::string m_type; }; }