1+ // AniHub.LipSync.cpp : Defines the exported functions for the DLL application.
2+ //
3+
4+ #include " SimpleInterface.h"
5+
6+ #include < string>
7+ #include < iostream>
8+ #include < stdio.h>
9+ #include < io.h>
10+ #include < filesystem>
11+ #include < fstream>
12+ #include < sstream>
13+
14+ #include " ffmpegcpp.h"
15+ #include " ffmpeg.h"
16+
17+ using namespace std ;
18+ using namespace ffmpegcpp ;
19+
20+
21+ struct Context
22+ {
23+ Muxer* muxer = nullptr ;
24+
25+ VideoCodec* videoCodec = nullptr ;
26+ AudioCodec* audioCodec = nullptr ;
27+
28+ Demuxer* videoDemuxer = nullptr ;
29+ Demuxer* audioDemuxer = nullptr ;
30+
31+ const char * videoFilterString = nullptr ;
32+ const char * audioFilterString = nullptr ;
33+
34+ Filter* videoFilter = nullptr ;
35+ Filter* audioFilter = nullptr ;
36+
37+ VideoFrameSink* videoEncoder = nullptr ;
38+ AudioFrameSink* audioEncoder = nullptr ;
39+
40+ RawVideoDataSource* source = nullptr ;
41+
42+ vector<Demuxer*> uniqueDemuxers;
43+
44+ bool errored = false ;
45+ string error;
46+ };
47+
48+ void SetError (Context* ctx, string error)
49+ {
50+ ctx->errored = true ;
51+ ctx->error = string (error);
52+ }
53+
54+ void CleanUp (Context* ctx)
55+ {
56+ if (ctx->muxer != nullptr ) delete ctx->muxer ;
57+
58+ if (ctx->videoEncoder != nullptr ) delete ctx->videoEncoder ;
59+ if (ctx->audioEncoder != nullptr ) delete ctx->audioEncoder ;
60+
61+ if (ctx->videoFilter != nullptr ) delete ctx->videoFilter ;
62+ if (ctx->audioFilter != nullptr ) delete ctx->audioFilter ;
63+
64+ if (ctx->videoCodec != nullptr ) delete ctx->videoCodec ;
65+ if (ctx->audioCodec != nullptr ) delete ctx->audioCodec ;
66+
67+ for (int i = 0 ; i < ctx->uniqueDemuxers .size (); ++i)
68+ {
69+ delete ctx->uniqueDemuxers [i];
70+ }
71+
72+ delete ctx;
73+ }
74+
75+ Demuxer* GetExistingDemuxer (Context* ctx, const char * fileName)
76+ {
77+ if (ctx->videoDemuxer != nullptr && string (ctx->videoDemuxer ->GetFileName ()) == string (fileName)) return ctx->videoDemuxer ;
78+ if (ctx->audioDemuxer != nullptr && string (ctx->audioDemuxer ->GetFileName ()) == string (fileName)) return ctx->audioDemuxer ;
79+ return nullptr ;
80+ }
81+
82+ void * ffmpegCppCreate (const char * outputFileName)
83+ {
84+ Context* ctx = new Context ();
85+ try
86+ {
87+ // create the output muxer but don't add any streams yet
88+ ctx->muxer = new Muxer (outputFileName);
89+ return ctx;
90+ }
91+ catch (FFmpegException e)
92+ {
93+ SetError (ctx, string (" Failed to create output file " + string (outputFileName) + " : " + string (e.what ())));
94+ return nullptr ;
95+ }
96+ }
97+
98+ void ffmpegCppAddVideoStream (void * handle, const char * videoFileName)
99+ {
100+ Context* ctx = (Context*)handle;
101+ try
102+ {
103+ // create the demuxer or re-use the previous one
104+ ctx->videoDemuxer = GetExistingDemuxer (ctx, videoFileName);
105+ if (ctx->videoDemuxer == nullptr )
106+ {
107+ ctx->videoDemuxer = new Demuxer (videoFileName);
108+ ctx->uniqueDemuxers .push_back (ctx->videoDemuxer );
109+ }
110+
111+ // create the encoder
112+ ctx->videoCodec = new VideoCodec (ctx->muxer ->GetDefaultVideoFormat ()->id );
113+ ctx->videoEncoder = new VideoEncoder (ctx->videoCodec , ctx->muxer );
114+ }
115+ catch (FFmpegException e)
116+ {
117+ SetError (ctx, string (" Failed to add video stream " + string (videoFileName) + " : " + string (e.what ())));
118+ }
119+ }
120+
121+ void ffmpegCppAddAudioStream (void * handle, const char * audioFileName)
122+ {
123+ Context* ctx = (Context*)handle;
124+ try
125+ {
126+ // create the demuxer or re-use the previous one
127+ ctx->audioDemuxer = GetExistingDemuxer (ctx, audioFileName);
128+ if (ctx->audioDemuxer == nullptr )
129+ {
130+ ctx->audioDemuxer = new Demuxer (audioFileName);
131+ ctx->uniqueDemuxers .push_back (ctx->audioDemuxer );
132+ }
133+
134+ // create the encoder
135+ ctx->audioCodec = new AudioCodec (ctx->muxer ->GetDefaultAudioFormat ()->id );
136+ ctx->audioEncoder = new AudioEncoder (ctx->audioCodec , ctx->muxer );
137+ }
138+ catch (FFmpegException e)
139+ {
140+ SetError (ctx, string (" Failed to add audio stream " + string (audioFileName) + " : " + string (e.what ())));
141+ }
142+ }
143+
144+ void ffmpegCppAddVideoFilter (void * handle, const char * filterString)
145+ {
146+ Context* ctx = (Context*)handle;
147+ ctx->videoFilterString = filterString;
148+ }
149+
150+ void ffmpegCppAddAudioFilter (void * handle, const char * filterString)
151+ {
152+ Context* ctx = (Context*)handle;
153+ ctx->audioFilterString = filterString;
154+ }
155+
156+ void ffmpegCppGenerate (void * handle)
157+ {
158+ Context* ctx = (Context*)handle;
159+ try
160+ {
161+ // create a filter if necessary
162+ FrameSink* videoFrameSink = ctx->videoEncoder ;
163+ FrameSink* audioFrameSink = ctx->audioEncoder ;
164+ if (ctx->videoFilterString != nullptr )
165+ {
166+ ctx->videoFilter = new Filter (ctx->videoFilterString , ctx->videoEncoder );
167+ videoFrameSink = ctx->videoFilter ;
168+ }
169+ if (ctx->audioFilterString != nullptr )
170+ {
171+ ctx->audioFilter = new Filter (ctx->audioFilterString , ctx->audioEncoder );
172+ audioFrameSink = ctx->audioFilter ;
173+ }
174+
175+ // connect the input and output streams
176+ if (ctx->videoDemuxer != nullptr )
177+ {
178+ ctx->videoDemuxer ->DecodeBestVideoStream (videoFrameSink);
179+ }
180+ if (ctx->audioDemuxer != nullptr )
181+ {
182+ ctx->audioDemuxer ->DecodeBestAudioStream (audioFrameSink);
183+ }
184+
185+ // now go over all the streams and process all frames
186+ for (int i = 0 ; i < ctx->uniqueDemuxers .size (); ++i)
187+ {
188+ ctx->uniqueDemuxers [i]->PreparePipeline ();
189+ }
190+
191+ // finally, we can start writing data to our pipelines. Open the floodgates
192+ // to start reading frames from the input, decoding them, optionally filtering them,
193+ // encoding them and writing them to the final container.
194+ // This can be interweaved if you want to.
195+ for (int i = 0 ; i < ctx->uniqueDemuxers .size (); ++i)
196+ {
197+ Demuxer* demuxer = ctx->uniqueDemuxers [i];
198+ while (!demuxer->IsDone ()) demuxer->Step ();
199+ }
200+
201+ // close the muxer and save the file to disk
202+ ctx->muxer ->Close ();
203+ }
204+ catch (FFmpegException e)
205+ {
206+ SetError (ctx, string (" Failed to generate output file: " + string (e.what ())));
207+ }
208+ }
209+
210+ void ffmpegCppAddFilter (void * handle, const char * filterString)
211+ {
212+ // TODO
213+ }
214+
215+
216+ bool ffmpegCppIsError (void * handle)
217+ {
218+ return ((Context*)handle)->errored ;
219+ }
220+
221+ const char * ffmpegCppGetError (void * handle)
222+ {
223+ return ((Context*)handle)->error .c_str ();
224+ }
225+
226+ void ffmpegCppClose (void * handle)
227+ {
228+ CleanUp ((Context*)handle);
229+ }
0 commit comments