1
+ #pragma once
2
+
3
+ #include " render_settings.hpp"
4
+
5
+ #include < Geode/loader/Event.hpp>
6
+
7
+ namespace ffmpeg ::events {
8
+
9
+ class CreateRecorderEvent : public geode ::Event {
10
+ public:
11
+ void setPtr (void * ptr) {m_ptr = ptr;}
12
+ void * getPtr () {return m_ptr;}
13
+ private:
14
+ void * m_ptr;
15
+ };
16
+
17
+ class DeleteRecorderEvent : public geode ::Event {
18
+ public:
19
+ DeleteRecorderEvent (void * ptr) {m_ptr = ptr;}
20
+ void * getPtr () {return m_ptr;}
21
+ private:
22
+ void * m_ptr;
23
+ };
24
+
25
+ class InitRecorderEvent : public geode ::Event {
26
+ public:
27
+ InitRecorderEvent (void * ptr, RenderSettings settings) {
28
+ m_ptr = ptr;
29
+ m_renderSettings = settings;
30
+ }
31
+
32
+ void setResult (const geode::Result<void >& result) {m_result = geode::Result (result);}
33
+ geode::Result<void > getResult () {return m_result;}
34
+
35
+ void * getPtr () {return m_ptr;}
36
+
37
+ const RenderSettings& getRenderSettings () {return m_renderSettings;}
38
+
39
+ private:
40
+ RenderSettings m_renderSettings;
41
+ void * m_ptr;
42
+ geode::Result<void > m_result = geode::Ok();
43
+ };
44
+
45
+ class StopRecorderEvent : public geode ::Event {
46
+ public:
47
+ StopRecorderEvent (void * ptr) {m_ptr = ptr;}
48
+ void * getPtr () {return m_ptr;}
49
+ private:
50
+ void * m_ptr;
51
+ };
52
+
53
+ class WriteFrameRecorderEvent : public geode ::Event {
54
+ public:
55
+ WriteFrameRecorderEvent (void * ptr, const std::vector<uint8_t >& frameData) {
56
+ m_ptr = ptr;
57
+ m_frameData = &frameData;
58
+ }
59
+
60
+ void setResult (const geode::Result<void >& result) {m_result = geode::Result (result);}
61
+ geode::Result<void > getResult () {return m_result;}
62
+
63
+ void * getPtr () {return m_ptr;}
64
+
65
+ const std::vector<uint8_t >& getFrameData () {return *m_frameData;}
66
+
67
+ private:
68
+ const std::vector<uint8_t >* m_frameData;
69
+ void * m_ptr;
70
+ geode::Result<void > m_result = geode::Ok();
71
+ };
72
+
73
+ class CodecRecorderEvent : public geode ::Event {
74
+ public:
75
+ CodecRecorderEvent (void * ptr) {m_ptr = ptr;}
76
+ void * getPtr () {return m_ptr;}
77
+
78
+ void setCodecs (std::vector<std::string> codecs) {m_codecs = codecs;}
79
+ std::vector<std::string> getCodecs () {return m_codecs;}
80
+ private:
81
+ void * m_ptr;
82
+ std::vector<std::string> m_codecs;
83
+ };
84
+
85
+ class CreateMixerEvent : public geode ::Event {
86
+ public:
87
+ void setPtr (void * ptr) {m_ptr = ptr;}
88
+ void * getPtr () {return m_ptr;}
89
+ private:
90
+ void * m_ptr;
91
+ };
92
+
93
+ class DeleteMixerEvent : public geode ::Event {
94
+ public:
95
+ DeleteMixerEvent (void * ptr) {m_ptr = ptr;}
96
+ void * getPtr () {return m_ptr;}
97
+ private:
98
+ void * m_ptr;
99
+ };
100
+
101
+ class MixVideoAudioEvent : public geode ::Event {
102
+ public:
103
+ MixVideoAudioEvent (void * ptr, std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File) {
104
+ m_ptr = ptr;
105
+ m_videoFile = videoFile;
106
+ m_audioFile = audioFile;
107
+ m_outputMp4File = outputMp4File;
108
+ }
109
+
110
+ void setResult (const geode::Result<void >& result) {m_result = geode::Result (result);}
111
+ geode::Result<void > getResult () {return m_result;}
112
+
113
+ void * getPtr () {return m_ptr;}
114
+
115
+ std::filesystem::path getVideoFile () {return m_videoFile;}
116
+ std::filesystem::path getAudioFile () {return m_audioFile;}
117
+ std::filesystem::path getOutputMp4File () {return m_outputMp4File;}
118
+
119
+ private:
120
+ std::filesystem::path m_videoFile;
121
+ std::filesystem::path m_audioFile;
122
+ std::filesystem::path m_outputMp4File;
123
+ void * m_ptr;
124
+ geode::Result<void > m_result = geode::Ok();
125
+ };
126
+
127
+ class MixVideoRawEvent : public geode ::Event {
128
+ public:
129
+ MixVideoRawEvent (void * ptr, std::filesystem::path videoFile, const std::vector<float >& raw, std::filesystem::path outputMp4File) {
130
+ m_ptr = ptr;
131
+ m_videoFile = videoFile;
132
+ m_raw = &raw;
133
+ m_outputMp4File = outputMp4File;
134
+ }
135
+
136
+ void setResult (const geode::Result<void >& result) {m_result = geode::Result (result);}
137
+ geode::Result<void > getResult () {return m_result;}
138
+
139
+ void * getPtr () {return m_ptr;}
140
+
141
+ std::filesystem::path getVideoFile () {return m_videoFile;}
142
+ const std::vector<float >& getRaw () {return *m_raw;}
143
+ std::filesystem::path getOutputMp4File () {return m_outputMp4File;}
144
+
145
+ private:
146
+ std::filesystem::path m_videoFile;
147
+ const std::vector<float >* m_raw;
148
+ std::filesystem::path m_outputMp4File;
149
+ void * m_ptr;
150
+ geode::Result<void > m_result = geode::Ok();
151
+ };
152
+
153
+
154
+ class Recorder {
155
+ public:
156
+ Recorder () {
157
+ CreateRecorderEvent createEvent;
158
+ createEvent.post ();
159
+ m_ptr = createEvent.getPtr ();
160
+ }
161
+
162
+ ~Recorder () {
163
+ DeleteRecorderEvent deleteEvent (m_ptr);
164
+ deleteEvent.post ();
165
+ }
166
+
167
+ /* *
168
+ * @brief Initializes the Recorder with the specified rendering settings.
169
+ *
170
+ * This function configures the recorder with the given render settings,
171
+ * allocates necessary resources, and prepares for video encoding.
172
+ *
173
+ * @param settings The rendering settings that define the output characteristics,
174
+ * including codec, bitrate, resolution, and pixel format.
175
+ *
176
+ * @return true if initialization is successful, false otherwise.
177
+ */
178
+ geode::Result<void > init (const RenderSettings& settings) {
179
+ InitRecorderEvent initEvent (m_ptr, settings);
180
+ initEvent.post ();
181
+ return initEvent.getResult ();
182
+ }
183
+ /* *
184
+ * @brief Stops the recording process and finalizes the output file.
185
+ *
186
+ * This function ensures that all buffered frames are written to the output file,
187
+ * releases allocated resources, and properly closes the output file.
188
+ */
189
+ void stop () {
190
+ StopRecorderEvent stopEvent (m_ptr);
191
+ stopEvent.post ();
192
+ }
193
+
194
+ /* *
195
+ * @brief Writes a single video frame to the output.
196
+ *
197
+ * This function takes the frame data as a byte vector and encodes it
198
+ * to the output file. The frame data must match the expected format and
199
+ * dimensions defined during initialization.
200
+ *
201
+ * @param frameData A vector containing the raw frame data to be written.
202
+ *
203
+ * @return true if the frame is successfully written, false if there is an error.
204
+ *
205
+ * @warning Ensure that the frameData size matches the expected dimensions of the frame.
206
+ */
207
+ geode::Result<void > writeFrame (const std::vector<uint8_t >& frameData) {
208
+ WriteFrameRecorderEvent writeFrameEvent (m_ptr, frameData);
209
+ writeFrameEvent.post ();
210
+ return writeFrameEvent.getResult ();
211
+ }
212
+
213
+ /* *
214
+ * @brief Retrieves a list of available codecs for video encoding.
215
+ *
216
+ * This function iterates through all available codecs in FFmpeg and
217
+ * returns a sorted vector of codec names.
218
+ *
219
+ * @return A vector representing the names of available codecs.
220
+ */
221
+ std::vector<std::string> getAvailableCodecs () {
222
+ CodecRecorderEvent codecEvent (m_ptr);
223
+ codecEvent.post ();
224
+ return codecEvent.getCodecs ();
225
+ }
226
+ private:
227
+ void * m_ptr = nullptr ;
228
+ };
229
+
230
+ class AudioMixer {
231
+ public:
232
+ AudioMixer () {
233
+ CreateMixerEvent createEvent;
234
+ createEvent.post ();
235
+ m_ptr = createEvent.getPtr ();
236
+ }
237
+
238
+ ~AudioMixer () {
239
+ DeleteMixerEvent deleteEvent (m_ptr);
240
+ deleteEvent.post ();
241
+ }
242
+
243
+ /* *
244
+ * @brief Mixes a video file and an audio file into a single MP4 output.
245
+ *
246
+ * This function takes an input video file and an audio file, and merges them into a single MP4 output file.
247
+ * The output MP4 file will have both the video and audio streams synchronized.
248
+ *
249
+ * @param videoFile The path to the input video file.
250
+ * @param audioFile The path to the input audio file.
251
+ * @param outputMp4File The path where the output MP4 file will be saved.
252
+ *
253
+ * @warning The audio file is expected to contain stereo (dual-channel) audio. Using other formats might lead to unexpected results.
254
+ * @warning The video file is expected to contain a single video stream. Only the first video stream will be copied.
255
+ */
256
+ geode::Result<void > mixVideoAudio (std::filesystem::path videoFile, std::filesystem::path audioFile, std::filesystem::path outputMp4File) {
257
+ MixVideoAudioEvent mixEvent (m_ptr, videoFile, audioFile, outputMp4File);
258
+ mixEvent.post ();
259
+ return mixEvent.getResult ();
260
+ }
261
+
262
+ /* *
263
+ * @brief Mixes a video file and raw audio data into a single MP4 output.
264
+ *
265
+ * This function takes an input video file and raw audio data (in the form of a vector of floating-point samples),
266
+ * and merges them into a single MP4 output file.
267
+ *
268
+ * @param videoFile The path to the input video file.
269
+ * @param raw A vector containing the raw audio data (floating-point samples).
270
+ * @param outputMp4File The path where the output MP4 file will be saved.
271
+ *
272
+ * @warning The raw audio data is expected to be stereo (dual-channel). Using mono or multi-channel audio might lead to issues.
273
+ * @warning The video file is expected to contain a single video stream. Only the first video stream will be copied.
274
+ */
275
+ geode::Result<void > mixVideoRaw (const std::filesystem::path& videoFile, const std::vector<float >& raw, const std::filesystem::path &outputMp4File) {
276
+ MixVideoRawEvent mixEvent (m_ptr, videoFile, raw, outputMp4File);
277
+ mixEvent.post ();
278
+ return mixEvent.getResult ();
279
+ }
280
+ private:
281
+ void * m_ptr = nullptr ;
282
+ };
283
+
284
+ }
0 commit comments