diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dea605..7cb8533 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,12 +11,8 @@ endif() project(ffmpeg-api VERSION 1.0.0) -add_library(${PROJECT_NAME} SHARED - src/recorder.cpp - src/audio_mixer.cpp - src/utils.cpp - # Add any extra C++ source files here -) +file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.cpp) +add_library(${PROJECT_NAME} SHARED ${SOURCES}) set_property(TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Final>") set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/include/audio_mixer.hpp b/include/audio_mixer.hpp index 406fe16..379c08b 100644 --- a/include/audio_mixer.hpp +++ b/include/audio_mixer.hpp @@ -6,10 +6,14 @@ #include -namespace ffmpeg { +BEGIN_FFMPEG_NAMESPACE_V class FFMPEG_API_DLL AudioMixer { public: + AudioMixer() = delete; + AudioMixer(const AudioMixer&) = delete; + AudioMixer(AudioMixer&&) = delete; + /** * @brief Mixes a video file and an audio file into a single MP4 output. * @@ -23,25 +27,7 @@ class FFMPEG_API_DLL AudioMixer { * @warning The audio file is expected to contain stereo (dual-channel) audio. Using other formats might lead to unexpected results. * @warning The video file is expected to contain a single video stream. Only the first video stream will be copied. */ - geode::Result mixVideoAudio(std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File); - - /** - * @deprecated sampleRate parameter is no longer used. Use the other overload of this function instead. - * - * @brief Mixes a video file and raw audio data into a single MP4 output. - * - * This function takes an input video file and raw audio data (in the form of a vector of floating-point samples), - * and merges them into a single MP4 output file. - * - * @param videoFile The path to the input video file. - * @param raw A vector containing the raw audio data (floating-point samples). - * @param outputMp4File The path where the output MP4 file will be saved. - * @param sampleRate The sample rate of the raw audio data. - * - * @warning The raw audio data is expected to be stereo (dual-channel). Using mono or multi-channel audio might lead to issues. - * @warning The video file is expected to contain a single video stream. Only the first video stream will be copied. - */ - [[deprecated]] void mixVideoRaw(std::filesystem::path videoFile, const std::vector& raw, std::filesystem::path outputMp4File, uint32_t sampleRate); + static geode::Result<> mixVideoAudio(std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File); /** * @brief Mixes a video file and raw audio data into a single MP4 output. @@ -56,7 +42,7 @@ class FFMPEG_API_DLL AudioMixer { * @warning The raw audio data is expected to be stereo (dual-channel). Using mono or multi-channel audio might lead to issues. * @warning The video file is expected to contain a single video stream. Only the first video stream will be copied. */ - geode::Result mixVideoRaw(const std::filesystem::path& videoFile, const std::vector& raw, const std::filesystem::path &outputMp4File); + static geode::Result<> mixVideoRaw(const std::filesystem::path& videoFile, const std::vector& raw, const std::filesystem::path &outputMp4File); }; -} \ No newline at end of file +END_FFMPEG_NAMESPACE_V \ No newline at end of file diff --git a/include/events.hpp b/include/events.hpp index 6612527..142e391 100644 --- a/include/events.hpp +++ b/include/events.hpp @@ -5,162 +5,140 @@ #include namespace ffmpeg::events { - -class CreateRecorderEvent : public geode::Event { -public: - void setPtr(void* ptr) {m_ptr = ptr;} - void* getPtr() {return m_ptr;} -private: - void* m_ptr; -}; - -class DeleteRecorderEvent : public geode::Event { -public: - DeleteRecorderEvent(void* ptr) {m_ptr = ptr;} - void* getPtr() {return m_ptr;} -private: - void* m_ptr; -}; - -class InitRecorderEvent : public geode::Event { -public: - InitRecorderEvent(void* ptr, RenderSettings settings) { - m_ptr = ptr; - m_renderSettings = settings; - } - - void setResult(const geode::Result& result) {m_result = geode::Result(result);} - geode::Result getResult() {return m_result;} - - void* getPtr() {return m_ptr;} - - const RenderSettings& getRenderSettings() {return m_renderSettings;} - -private: - RenderSettings m_renderSettings; - void* m_ptr; - geode::Result m_result = geode::Ok(); -}; - -class StopRecorderEvent : public geode::Event { -public: - StopRecorderEvent(void* ptr) {m_ptr = ptr;} - void* getPtr() {return m_ptr;} -private: - void* m_ptr; -}; - -class WriteFrameRecorderEvent : public geode::Event { -public: - WriteFrameRecorderEvent(void* ptr, const std::vector& frameData) { - m_ptr = ptr; - m_frameData = &frameData; - } - - void setResult(const geode::Result& result) {m_result = geode::Result(result);} - geode::Result getResult() {return m_result;} - - void* getPtr() {return m_ptr;} - - const std::vector& getFrameData() {return *m_frameData;} - -private: - const std::vector* m_frameData; - void* m_ptr; - geode::Result m_result = geode::Ok(); -}; - -class CodecRecorderEvent : public geode::Event { -public: - CodecRecorderEvent(void* ptr) {m_ptr = ptr;} - void* getPtr() {return m_ptr;} - - void setCodecs(std::vector codecs) {m_codecs = codecs;} - std::vector getCodecs() {return m_codecs;} -private: - void* m_ptr; - std::vector m_codecs; -}; - -class CreateMixerEvent : public geode::Event { -public: - void setPtr(void* ptr) {m_ptr = ptr;} - void* getPtr() {return m_ptr;} -private: - void* m_ptr; -}; - -class DeleteMixerEvent : public geode::Event { -public: - DeleteMixerEvent(void* ptr) {m_ptr = ptr;} - void* getPtr() {return m_ptr;} -private: - void* m_ptr; -}; - -class MixVideoAudioEvent : public geode::Event { -public: - MixVideoAudioEvent(void* ptr, std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File) { - m_ptr = ptr; - m_videoFile = videoFile; - m_audioFile = audioFile; - m_outputMp4File = outputMp4File; - } - - void setResult(const geode::Result& result) {m_result = geode::Result(result);} - geode::Result getResult() {return m_result;} - - void* getPtr() {return m_ptr;} - - std::filesystem::path getVideoFile() {return m_videoFile;} - std::filesystem::path getAudioFile() {return m_audioFile;} - std::filesystem::path getOutputMp4File() {return m_outputMp4File;} - -private: - std::filesystem::path m_videoFile; - std::filesystem::path m_audioFile; - std::filesystem::path m_outputMp4File; - void* m_ptr; - geode::Result m_result = geode::Ok(); -}; - -class MixVideoRawEvent : public geode::Event { -public: - MixVideoRawEvent(void* ptr, std::filesystem::path videoFile, const std::vector& raw, std::filesystem::path outputMp4File) { - m_ptr = ptr; - m_videoFile = videoFile; - m_raw = &raw; - m_outputMp4File = outputMp4File; - } - - void setResult(const geode::Result& result) {m_result = geode::Result(result);} - geode::Result getResult() {return m_result;} - - void* getPtr() {return m_ptr;} - - std::filesystem::path getVideoFile() {return m_videoFile;} - const std::vector& getRaw() {return *m_raw;} - std::filesystem::path getOutputMp4File() {return m_outputMp4File;} - -private: - std::filesystem::path m_videoFile; - const std::vector* m_raw; - std::filesystem::path m_outputMp4File; - void* m_ptr; - geode::Result m_result = geode::Ok(); -}; - +namespace impl { +#define DEFAULT_RESULT_ERROR geode::Err("Event was not handled") + + class CreateRecorderEvent : public geode::Event { + public: + CreateRecorderEvent() {m_ptr = nullptr;} + void setPtr(void* ptr) {m_ptr = ptr;} + void* getPtr() const {return m_ptr;} + private: + void* m_ptr; + }; + + class DeleteRecorderEvent : public geode::Event { + public: + DeleteRecorderEvent(void* ptr) {m_ptr = ptr;} + void* getPtr() const {return m_ptr;} + private: + void* m_ptr; + }; + + class InitRecorderEvent : public geode::Event { + public: + InitRecorderEvent(void* ptr, RenderSettings&& settings) { + m_ptr = ptr; + m_renderSettings = std::move(settings); + } + + void setResult(geode::Result<>&& result) {m_result = std::move(result);} + geode::Result<> getResult() {return m_result;} + + void* getPtr() const {return m_ptr;} + + const RenderSettings& getRenderSettings() {return m_renderSettings;} + + private: + RenderSettings m_renderSettings; + void* m_ptr; + geode::Result<> m_result = geode::Ok(); + }; + + class StopRecorderEvent : public geode::Event { + public: + StopRecorderEvent(void* ptr) {m_ptr = ptr;} + void* getPtr() const {return m_ptr;} + private: + void* m_ptr; + }; + + class WriteFrameRecorderEvent : public geode::Event { + public: + WriteFrameRecorderEvent(void* ptr, const std::vector& frameData) { + m_ptr = ptr; + m_frameData = &frameData; + } + + void setResult(geode::Result<>&& result) {m_result = std::move(result);} + geode::Result<> getResult() {return m_result;} + + void* getPtr() const {return m_ptr;} + + const std::vector& getFrameData() const {return *m_frameData;} + + private: + const std::vector* m_frameData; + void* m_ptr; + geode::Result<> m_result = DEFAULT_RESULT_ERROR; + }; + + class CodecRecorderEvent : public geode::Event { + public: + CodecRecorderEvent() = default; + + void setCodecs(std::vector&& codecs) {m_codecs = std::move(codecs);} + const std::vector& getCodecs() const {return m_codecs;} + private: + std::vector m_codecs; + }; + + class MixVideoAudioEvent : public geode::Event { + public: + MixVideoAudioEvent(std::filesystem::path&& videoFile, std::filesystem::path&& audioFile, std::filesystem::path&& outputMp4File) { + m_videoFile = std::move(videoFile); + m_audioFile = std::move(audioFile); + m_outputMp4File = std::move(outputMp4File); + } + + void setResult(geode::Result<>&& result) {m_result = std::move(result);} + geode::Result<> getResult() {return m_result;} + + std::filesystem::path const& getVideoFile() {return m_videoFile;} + std::filesystem::path const& getAudioFile() {return m_audioFile;} + std::filesystem::path const& getOutputMp4File() {return m_outputMp4File;} + + private: + std::filesystem::path m_videoFile; + std::filesystem::path m_audioFile; + std::filesystem::path m_outputMp4File; + geode::Result<> m_result = DEFAULT_RESULT_ERROR; + }; + + class MixVideoRawEvent : public geode::Event { + public: + MixVideoRawEvent(std::filesystem::path&& videoFile, const std::vector& raw, std::filesystem::path&& outputMp4File) { + m_videoFile = std::move(videoFile); + m_raw = &raw; + m_outputMp4File = std::move(outputMp4File); + } + + void setResult(const geode::Result<>& result) {m_result = geode::Result(result);} + geode::Result<> getResult() {return m_result;} + + std::filesystem::path const& getVideoFile() const {return m_videoFile;} + std::vector const& getRaw() const {return *m_raw;} + std::filesystem::path const& getOutputMp4File() const {return m_outputMp4File;} + + private: + std::filesystem::path m_videoFile; + const std::vector* m_raw; + std::filesystem::path m_outputMp4File; + geode::Result<> m_result = DEFAULT_RESULT_ERROR; + }; +#undef DEFAULT_RESULT_ERROR +} class Recorder { public: Recorder() { - CreateRecorderEvent createEvent; + impl::CreateRecorderEvent createEvent; createEvent.post(); m_ptr = createEvent.getPtr(); } ~Recorder() { - DeleteRecorderEvent deleteEvent(m_ptr); + impl::DeleteRecorderEvent deleteEvent(m_ptr); deleteEvent.post(); } @@ -175,8 +153,8 @@ class Recorder { * * @return true if initialization is successful, false otherwise. */ - geode::Result init(const RenderSettings& settings) { - InitRecorderEvent initEvent(m_ptr, settings); + geode::Result<> init(RenderSettings&& settings) { + impl::InitRecorderEvent initEvent(m_ptr, std::move(settings)); initEvent.post(); return initEvent.getResult(); } @@ -187,8 +165,7 @@ class Recorder { * releases allocated resources, and properly closes the output file. */ void stop() { - StopRecorderEvent stopEvent(m_ptr); - stopEvent.post(); + impl::StopRecorderEvent(m_ptr).post(); } /** @@ -204,8 +181,8 @@ class Recorder { * * @warning Ensure that the frameData size matches the expected dimensions of the frame. */ - geode::Result writeFrame(const std::vector& frameData) { - WriteFrameRecorderEvent writeFrameEvent(m_ptr, frameData); + geode::Result<> writeFrame(const std::vector& frameData) { + impl::WriteFrameRecorderEvent writeFrameEvent(m_ptr, frameData); writeFrameEvent.post(); return writeFrameEvent.getResult(); } @@ -218,8 +195,8 @@ class Recorder { * * @return A vector representing the names of available codecs. */ - std::vector getAvailableCodecs() { - CodecRecorderEvent codecEvent(m_ptr); + static std::vector getAvailableCodecs() { + impl::CodecRecorderEvent codecEvent; codecEvent.post(); return codecEvent.getCodecs(); } @@ -229,16 +206,7 @@ class Recorder { class AudioMixer { public: - AudioMixer() { - CreateMixerEvent createEvent; - createEvent.post(); - m_ptr = createEvent.getPtr(); - } - - ~AudioMixer() { - DeleteMixerEvent deleteEvent(m_ptr); - deleteEvent.post(); - } + AudioMixer() = delete; /** * @brief Mixes a video file and an audio file into a single MP4 output. @@ -253,8 +221,8 @@ class AudioMixer { * @warning The audio file is expected to contain stereo (dual-channel) audio. Using other formats might lead to unexpected results. * @warning The video file is expected to contain a single video stream. Only the first video stream will be copied. */ - geode::Result mixVideoAudio(std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File) { - MixVideoAudioEvent mixEvent(m_ptr, videoFile, audioFile, outputMp4File); + static geode::Result<> mixVideoAudio(std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File) { + impl::MixVideoAudioEvent mixEvent(std::move(videoFile), std::move(audioFile), std::move(outputMp4File)); mixEvent.post(); return mixEvent.getResult(); } @@ -272,13 +240,11 @@ class AudioMixer { * @warning The raw audio data is expected to be stereo (dual-channel). Using mono or multi-channel audio might lead to issues. * @warning The video file is expected to contain a single video stream. Only the first video stream will be copied. */ - geode::Result mixVideoRaw(const std::filesystem::path& videoFile, const std::vector& raw, const std::filesystem::path &outputMp4File) { - MixVideoRawEvent mixEvent(m_ptr, videoFile, raw, outputMp4File); + static geode::Result<> mixVideoRaw(std::filesystem::path videoFile, const std::vector& raw, std::filesystem::path outputMp4File) { + impl::MixVideoRawEvent mixEvent(std::move(videoFile), raw, std::move(outputMp4File)); mixEvent.post(); return mixEvent.getResult(); } -private: - void* m_ptr = nullptr; }; } \ No newline at end of file diff --git a/include/export.hpp b/include/export.hpp index 5a4bd6c..37317ad 100644 --- a/include/export.hpp +++ b/include/export.hpp @@ -10,4 +10,14 @@ #endif #else #define FFMPEG_API_DLL __attribute__((visibility("default"))) -#endif \ No newline at end of file +#endif + +#define FFMPEG_API_VERSION 2 + +#define BEGIN_FFMPEG_NAMESPACE namespace ffmpeg { +#define FFMPEG_API_VERSION_NS GEODE_CONCAT(v, FFMPEG_API_VERSION) +#define BEGIN_FFMPEG_NAMESPACE_V \ + BEGIN_FFMPEG_NAMESPACE \ + inline namespace FFMPEG_API_VERSION_NS { +#define END_FFMPEG_NAMESPACE } +#define END_FFMPEG_NAMESPACE_V }} \ No newline at end of file diff --git a/include/recorder.hpp b/include/recorder.hpp index 847dc7a..e862439 100644 --- a/include/recorder.hpp +++ b/include/recorder.hpp @@ -22,7 +22,7 @@ class AVFilterContext; class AVFilter; class AVFilterGraph; -namespace ffmpeg { +BEGIN_FFMPEG_NAMESPACE_V class FFMPEG_API_DLL Recorder { public: @@ -37,7 +37,7 @@ class FFMPEG_API_DLL Recorder { * * @return true if initialization is successful, false otherwise. */ - geode::Result init(const RenderSettings& settings); + geode::Result<> init(const RenderSettings& settings); /** * @brief Stops the recording process and finalizes the output file. * @@ -59,7 +59,7 @@ class FFMPEG_API_DLL Recorder { * * @warning Ensure that the frameData size matches the expected dimensions of the frame. */ - geode::Result writeFrame(const std::vector& frameData); + geode::Result<> writeFrame(const std::vector& frameData); /** * @brief Retrieves a list of available codecs for video encoding. @@ -69,10 +69,10 @@ class FFMPEG_API_DLL Recorder { * * @return A vector representing the names of available codecs. */ - std::vector getAvailableCodecs(); + static std::vector getAvailableCodecs(); private: - geode::Result filterFrame(AVFrame* inputFrame, AVFrame* outputFrame); + geode::Result<> filterFrame(AVFrame* inputFrame, AVFrame* outputFrame); private: AVFormatContext* m_formatContext = nullptr; @@ -83,7 +83,7 @@ class FFMPEG_API_DLL Recorder { AVFrame* m_frame = nullptr; AVFrame* m_convertedFrame = nullptr; AVFrame* m_filteredFrame = nullptr; - AVPacket* m_packet; + AVPacket* m_packet = nullptr; SwsContext* m_swsCtx = nullptr; AVFilterGraph* m_filterGraph = nullptr; AVFilterContext* m_buffersrcCtx = nullptr; @@ -94,4 +94,4 @@ class FFMPEG_API_DLL Recorder { bool m_init = false; }; -} \ No newline at end of file +END_FFMPEG_NAMESPACE_V \ No newline at end of file diff --git a/src/audio_mixer.cpp b/src/audio_mixer.cpp index 996f6bc..cb31172 100644 --- a/src/audio_mixer.cpp +++ b/src/audio_mixer.cpp @@ -141,8 +141,8 @@ geode::Result> resampleAudio(const std::vector& inputA return geode::Ok(outputAudio); } -namespace ffmpeg { - geode::Result AudioMixer::mixVideoAudio(std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File) { +BEGIN_FFMPEG_NAMESPACE_V + geode::Result<> AudioMixer::mixVideoAudio(std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File) { constexpr int frameSize = 1024; AVFormatContext* wavFormatContext = nullptr; @@ -157,23 +157,19 @@ namespace ffmpeg { if(raw.isErr()) return geode::Err(raw.unwrapErr()); - geode::Result res = mixVideoRaw(videoFile, raw.unwrap(), outputMp4File); + geode::Result<> res = mixVideoRaw(videoFile, raw.unwrap(), outputMp4File); avformat_close_input(&wavFormatContext); return res; } - void AudioMixer::mixVideoRaw(std::filesystem::path videoFile, const std::vector& raw, std::filesystem::path outputMp4File, uint32_t) { - mixVideoRaw(videoFile, raw, outputMp4File); - } - - geode::Result AudioMixer::mixVideoRaw(const std::filesystem::path& videoFile, const std::vector& raw, const std::filesystem::path &outputMp4File) { + geode::Result<> AudioMixer::mixVideoRaw(const std::filesystem::path& videoFile, const std::vector& raw, const std::filesystem::path &outputMp4File) { constexpr int frameSize = 1024; constexpr uint32_t sampleRate = 44100; int ret = 0; - + AVFormatContext* videoFormatContext = nullptr; if (ret = avformat_open_input(&videoFormatContext, videoFile.string().c_str(), nullptr, nullptr); ret < 0) return geode::Err("Could not open MP4 file: " + utils::getErrorString(ret)); @@ -227,7 +223,7 @@ namespace ffmpeg { outputAudioStream->codecpar->bits_per_coded_sample = 16; outputAudioStream->codecpar->format = AVSampleFormat::AV_SAMPLE_FMT_FLTP; outputAudioStream->codecpar->frame_size = frameSize; - + outputFormatContext->audio_codec = avcodec_find_encoder(AV_CODEC_ID_AAC); outputFormatContext->audio_codec_id = AV_CODEC_ID_AAC; outputFormatContext->bit_rate = 128000; @@ -333,4 +329,4 @@ namespace ffmpeg { return geode::Ok(); } -} \ No newline at end of file +END_FFMPEG_NAMESPACE_V \ No newline at end of file diff --git a/src/compat.cpp b/src/compat.cpp new file mode 100644 index 0000000..46f9709 --- /dev/null +++ b/src/compat.cpp @@ -0,0 +1,45 @@ +// This file contains code for backwards compatibility with older ABI versions. + +#include "audio_mixer.hpp" +#include "recorder.hpp" + +namespace ffmpeg { + class FFMPEG_API_DLL AudioMixer { + public: + void mixVideoAudio(std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File) { + (void) FFMPEG_API_VERSION_NS::AudioMixer::mixVideoAudio(std::move(videoFile), std::move(audioFile), std::move(outputMp4File)); + } + + void mixVideoRaw(std::filesystem::path videoFile, const std::vector& raw, std::filesystem::path outputMp4File, uint32_t sampleRate) { + (void) FFMPEG_API_VERSION_NS::AudioMixer::mixVideoRaw(videoFile, raw, outputMp4File); + } + + void mixVideoRaw(const std::filesystem::path& videoFile, const std::vector& raw, const std::filesystem::path &outputMp4File) { + (void) FFMPEG_API_VERSION_NS::AudioMixer::mixVideoRaw(videoFile, raw, outputMp4File); + } + }; + + class FFMPEG_API_DLL Recorder { +#define self reinterpret_cast(this) + public: + bool init(const RenderSettings& settings) { + auto res = self->init(settings); + return res.isOk(); + } + + void stop() { + self->stop(); + } + + bool writeFrame(const std::vector& frameData) { + auto res = self->writeFrame(frameData); + return res.isOk(); + } + + std::vector getAvailableCodecs() { + return FFMPEG_API_VERSION_NS::Recorder::getAvailableCodecs(); + } +#undef self + }; + +} \ No newline at end of file diff --git a/src/event-api/events.cpp b/src/event-api/events.cpp index 066118e..31d29b4 100644 --- a/src/event-api/events.cpp +++ b/src/event-api/events.cpp @@ -4,61 +4,49 @@ using namespace geode::prelude; -$execute { - new EventListener>(+[](ffmpeg::events::CreateRecorderEvent* e) { +$on_mod(Loaded) { + using namespace ffmpeg::events::impl; + + new EventListener>(+[](CreateRecorderEvent* e) { e->setPtr(new ffmpeg::Recorder); return ListenerResult::Stop; }); - new EventListener>(+[](ffmpeg::events::DeleteRecorderEvent* e) { + new EventListener>(+[](DeleteRecorderEvent* e) { delete (ffmpeg::Recorder*)e->getPtr(); return ListenerResult::Stop; }); - new EventListener>(+[](ffmpeg::events::InitRecorderEvent* e) { + new EventListener>(+[](InitRecorderEvent* e) { ffmpeg::Recorder* ptr = (ffmpeg::Recorder*)e->getPtr(); e->setResult(ptr->init(e->getRenderSettings())); return ListenerResult::Stop; }); - new EventListener>(+[](ffmpeg::events::StopRecorderEvent* e) { + new EventListener>(+[](StopRecorderEvent* e) { ffmpeg::Recorder* ptr = (ffmpeg::Recorder*)e->getPtr(); ptr->stop(); return ListenerResult::Stop; }); - new EventListener>(+[](ffmpeg::events::WriteFrameRecorderEvent* e) { + new EventListener>(+[](WriteFrameRecorderEvent* e) { ffmpeg::Recorder* ptr = (ffmpeg::Recorder*)e->getPtr(); e->setResult(ptr->writeFrame(e->getFrameData())); return ListenerResult::Stop; }); - new EventListener>(+[](ffmpeg::events::CodecRecorderEvent* e) { - ffmpeg::Recorder* ptr = (ffmpeg::Recorder*)e->getPtr(); - e->setCodecs(ptr->getAvailableCodecs()); - return ListenerResult::Stop; - }); - - - new EventListener>(+[](ffmpeg::events::CreateMixerEvent* e) { - e->setPtr(new ffmpeg::AudioMixer); - return ListenerResult::Stop; - }); - - new EventListener>(+[](ffmpeg::events::DeleteMixerEvent* e) { - delete (ffmpeg::AudioMixer*)e->getPtr(); + new EventListener>(+[](CodecRecorderEvent* e) { + e->setCodecs(ffmpeg::Recorder::getAvailableCodecs()); return ListenerResult::Stop; }); - new EventListener>(+[](ffmpeg::events::MixVideoAudioEvent* e) { - ffmpeg::AudioMixer* ptr = (ffmpeg::AudioMixer*)e->getPtr(); - e->setResult(ptr->mixVideoAudio(e->getVideoFile(), e->getAudioFile(), e->getOutputMp4File())); + new EventListener>(+[](MixVideoAudioEvent* e) { + e->setResult(ffmpeg::AudioMixer::mixVideoAudio(e->getVideoFile(), e->getAudioFile(), e->getOutputMp4File())); return ListenerResult::Stop; }); - new EventListener>(+[](ffmpeg::events::MixVideoRawEvent* e) { - ffmpeg::AudioMixer* ptr = (ffmpeg::AudioMixer*)e->getPtr(); - e->setResult(ptr->mixVideoRaw(e->getVideoFile(), e->getRaw(), e->getOutputMp4File())); + new EventListener>(+[](MixVideoRawEvent* e) { + e->setResult(ffmpeg::AudioMixer::mixVideoRaw(e->getVideoFile(), e->getRaw(), e->getOutputMp4File())); return ListenerResult::Stop; }); } \ No newline at end of file diff --git a/src/recorder.cpp b/src/recorder.cpp index e938ade..e2baa11 100644 --- a/src/recorder.cpp +++ b/src/recorder.cpp @@ -11,7 +11,7 @@ extern "C" { #include } -namespace ffmpeg { +BEGIN_FFMPEG_NAMESPACE_V std::vector Recorder::getAvailableCodecs() { std::vector vec; @@ -39,7 +39,7 @@ const AVCodec* getCodecByName(const std::string& name) { return nullptr; } -geode::Result Recorder::init(const RenderSettings& settings) { +geode::Result<> Recorder::init(const RenderSettings& settings) { int ret = avformat_alloc_output_context2(&m_formatContext, NULL, NULL, settings.m_outputFile.string().c_str()); if (!m_formatContext) return geode::Err("Could not create output context: " + utils::getErrorString(ret)); @@ -186,7 +186,7 @@ geode::Result Recorder::init(const RenderSettings& settings) { return geode::Ok(); } -geode::Result Recorder::writeFrame(const std::vector& frameData) { +geode::Result<> Recorder::writeFrame(const std::vector& frameData) { if (!m_init || !m_frame) return geode::Err("Recorder is not initialized."); @@ -195,7 +195,7 @@ geode::Result Recorder::writeFrame(const std::vector& frameData) if(m_buffersrcCtx) { std::memcpy(m_frame->data[0], frameData.data(), frameData.size()); - geode::Result res = filterFrame(m_frame, m_filteredFrame); + geode::Result<> res = filterFrame(m_frame, m_filteredFrame); if(res.isErr()) return res; @@ -238,7 +238,7 @@ geode::Result Recorder::writeFrame(const std::vector& frameData) return geode::Ok(); } -geode::Result Recorder::filterFrame(AVFrame* inputFrame, AVFrame* outputFrame) { +geode::Result<> Recorder::filterFrame(AVFrame* inputFrame, AVFrame* outputFrame) { int ret = 0; if (ret = av_buffersrc_add_frame(m_buffersrcCtx, inputFrame); ret < 0) { avfilter_graph_free(&m_filterGraph); @@ -289,4 +289,4 @@ void Recorder::stop() { av_packet_free(&m_packet); } -} \ No newline at end of file +END_FFMPEG_NAMESPACE_V \ No newline at end of file