@@ -18,51 +18,59 @@ using namespace std;
1818using namespace ffmpegcpp ;
1919
2020
21- struct Context
21+ template <class CodecType , class FrameSinkType >
22+ struct StreamContext
2223{
23- Muxer* muxer = nullptr ;
24+ CodecType* codec = nullptr ;
2425
25- VideoCodec* videoCodec = nullptr ;
26- AudioCodec* audioCodec = nullptr ;
26+ string sourceFileName ;
27+ Demuxer* demuxer = nullptr ;
2728
28- Demuxer* videoDemuxer = nullptr ;
29- Demuxer* audioDemuxer = nullptr ;
29+ bool hasFilter = false ;
30+ string filterString;
31+ Filter* filter = nullptr ;
3032
31- const char * videoFilterString = nullptr ;
32- const char * audioFilterString = nullptr ;
33+ FrameSinkType* encoder = nullptr ;
3334
34- Filter* videoFilter = nullptr ;
35- Filter* audioFilter = nullptr ;
35+ void CleanUp ()
36+ {
37+ if (encoder != nullptr ) delete encoder;
38+ if (filter != nullptr ) delete filter;
39+ if (codec != nullptr ) delete codec;
40+ // the demuxer can be shared amongst different contexts, so we don't delete them here
41+ }
42+ };
3643
37- VideoFrameSink* videoEncoder = nullptr ;
38- AudioFrameSink* audioEncoder = nullptr ;
44+ struct Context
45+ {
46+ string outputFileName;
47+ Muxer* muxer = nullptr ;
3948
40- RawVideoDataSource* source = nullptr ;
49+ StreamContext<VideoCodec, VideoFrameSink> videoContext;
50+ StreamContext<AudioCodec, AudioFrameSink> audioContext;
4151
4252 vector<Demuxer*> uniqueDemuxers;
4353
4454 bool errored = false ;
45- string error;
55+ char * error;
4656};
4757
4858void SetError (Context* ctx, string error)
4959{
5060 ctx->errored = true ;
51- ctx->error = string (error);
61+ string err = string (error);
62+ ctx->error = new char [err.length () + 1 ];
63+ strcpy (ctx->error , err.c_str ());
5264}
5365
5466void CleanUp (Context* ctx)
5567{
5668 if (ctx->muxer != nullptr ) delete ctx->muxer ;
5769
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 ;
70+ ctx->videoContext .CleanUp ();
71+ ctx->audioContext .CleanUp ();
6372
64- if (ctx->videoCodec != nullptr ) delete ctx->videoCodec ;
65- if (ctx->audioCodec != nullptr ) delete ctx->audioCodec ;
73+ if (ctx->error != nullptr ) delete ctx->error ;
6674
6775 for (int i = 0 ; i < ctx->uniqueDemuxers .size (); ++i)
6876 {
@@ -74,8 +82,10 @@ void CleanUp(Context* ctx)
7482
7583Demuxer* GetExistingDemuxer (Context* ctx, const char * fileName)
7684{
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 ;
85+ for (int i = 0 ; i < ctx->uniqueDemuxers .size (); ++i)
86+ {
87+ if (string (ctx->uniqueDemuxers [i]->GetFileName ()) == string (fileName)) return ctx->uniqueDemuxers [i];
88+ }
7989 return nullptr ;
8090}
8191
@@ -85,12 +95,13 @@ void* ffmpegCppCreate(const char* outputFileName)
8595 try
8696 {
8797 // create the output muxer but don't add any streams yet
88- ctx->muxer = new Muxer (outputFileName);
98+ ctx->outputFileName = string (outputFileName);
99+ ctx->muxer = new Muxer (ctx->outputFileName .c_str ());
89100 return ctx;
90101 }
91102 catch (FFmpegException e)
92103 {
93- SetError (ctx, string (" Failed to create output file " + string ( outputFileName) + " : " + string (e.what ())));
104+ SetError (ctx, string (" Failed to create output file " + ctx-> outputFileName + " : " + string (e.what ())));
94105 return nullptr ;
95106 }
96107}
@@ -101,16 +112,17 @@ void ffmpegCppAddVideoStream(void* handle, const char* videoFileName)
101112 try
102113 {
103114 // create the demuxer or re-use the previous one
104- ctx->videoDemuxer = GetExistingDemuxer (ctx, videoFileName);
105- if (ctx->videoDemuxer == nullptr )
115+ ctx->videoContext .sourceFileName = videoFileName;
116+ ctx->videoContext .demuxer = GetExistingDemuxer (ctx, videoFileName);
117+ if (ctx->videoContext .demuxer == nullptr )
106118 {
107- ctx->videoDemuxer = new Demuxer (videoFileName );
108- ctx->uniqueDemuxers .push_back (ctx->videoDemuxer );
119+ ctx->videoContext . demuxer = new Demuxer (ctx-> videoContext . sourceFileName . c_str () );
120+ ctx->uniqueDemuxers .push_back (ctx->videoContext . demuxer );
109121 }
110122
111123 // create the encoder
112- ctx->videoCodec = new VideoCodec (ctx->muxer ->GetDefaultVideoFormat ()->id );
113- ctx->videoEncoder = new VideoEncoder (ctx->videoCodec , ctx->muxer );
124+ ctx->videoContext . codec = new VideoCodec (ctx->muxer ->GetDefaultVideoFormat ()->id );
125+ ctx->videoContext . encoder = new VideoEncoder (ctx->videoContext . codec , ctx->muxer );
114126 }
115127 catch (FFmpegException e)
116128 {
@@ -124,16 +136,17 @@ void ffmpegCppAddAudioStream(void* handle, const char* audioFileName)
124136 try
125137 {
126138 // create the demuxer or re-use the previous one
127- ctx->audioDemuxer = GetExistingDemuxer (ctx, audioFileName);
128- if (ctx->audioDemuxer == nullptr )
139+ ctx->audioContext .sourceFileName = audioFileName;
140+ ctx->audioContext .demuxer = GetExistingDemuxer (ctx, audioFileName);
141+ if (ctx->audioContext .demuxer == nullptr )
129142 {
130- ctx->audioDemuxer = new Demuxer (audioFileName );
131- ctx->uniqueDemuxers .push_back (ctx->audioDemuxer );
143+ ctx->audioContext . demuxer = new Demuxer (ctx-> audioContext . sourceFileName . c_str () );
144+ ctx->uniqueDemuxers .push_back (ctx->audioContext . demuxer );
132145 }
133146
134147 // create the encoder
135- ctx->audioCodec = new AudioCodec (ctx->muxer ->GetDefaultAudioFormat ()->id );
136- ctx->audioEncoder = new AudioEncoder (ctx->audioCodec , ctx->muxer );
148+ ctx->audioContext . codec = new AudioCodec (ctx->muxer ->GetDefaultAudioFormat ()->id );
149+ ctx->audioContext . encoder = new AudioEncoder (ctx->audioContext . codec , ctx->muxer );
137150 }
138151 catch (FFmpegException e)
139152 {
@@ -144,13 +157,15 @@ void ffmpegCppAddAudioStream(void* handle, const char* audioFileName)
144157void ffmpegCppAddVideoFilter (void * handle, const char * filterString)
145158{
146159 Context* ctx = (Context*)handle;
147- ctx->videoFilterString = filterString;
160+ ctx->videoContext .filterString = filterString;
161+ ctx->videoContext .hasFilter = true ;
148162}
149163
150164void ffmpegCppAddAudioFilter (void * handle, const char * filterString)
151165{
152166 Context* ctx = (Context*)handle;
153- ctx->audioFilterString = filterString;
167+ ctx->audioContext .filterString = filterString;
168+ ctx->audioContext .hasFilter = true ;
154169}
155170
156171void ffmpegCppGenerate (void * handle)
@@ -159,27 +174,27 @@ void ffmpegCppGenerate(void* handle)
159174 try
160175 {
161176 // create a filter if necessary
162- FrameSink* videoFrameSink = ctx->videoEncoder ;
163- FrameSink* audioFrameSink = ctx->audioEncoder ;
164- if (ctx->videoFilterString != nullptr )
177+ FrameSink* videoFrameSink = ctx->videoContext . encoder ;
178+ FrameSink* audioFrameSink = ctx->audioContext . encoder ;
179+ if (ctx->videoContext . hasFilter )
165180 {
166- ctx->videoFilter = new Filter (ctx->videoFilterString , ctx-> videoEncoder );
167- videoFrameSink = ctx->videoFilter ;
181+ ctx->videoContext . filter = new Filter (ctx->videoContext . filterString . c_str (), videoFrameSink );
182+ videoFrameSink = ctx->videoContext . filter ;
168183 }
169- if (ctx->audioFilterString != nullptr )
184+ if (ctx->audioContext . hasFilter )
170185 {
171- ctx->audioFilter = new Filter (ctx->audioFilterString , ctx-> audioEncoder );
172- audioFrameSink = ctx->audioFilter ;
186+ ctx->audioContext . filter = new Filter (ctx->audioContext . filterString . c_str (), audioFrameSink );
187+ audioFrameSink = ctx->audioContext . filter ;
173188 }
174189
175190 // connect the input and output streams
176- if (ctx->videoDemuxer != nullptr )
191+ if (ctx->videoContext . demuxer != nullptr )
177192 {
178- ctx->videoDemuxer ->DecodeBestVideoStream (videoFrameSink);
193+ ctx->videoContext . demuxer ->DecodeBestVideoStream (videoFrameSink);
179194 }
180- if (ctx->audioDemuxer != nullptr )
195+ if (ctx->audioContext . demuxer != nullptr )
181196 {
182- ctx->audioDemuxer ->DecodeBestAudioStream (audioFrameSink);
197+ ctx->audioContext . demuxer ->DecodeBestAudioStream (audioFrameSink);
183198 }
184199
185200 // now go over all the streams and process all frames
@@ -207,20 +222,15 @@ void ffmpegCppGenerate(void* handle)
207222 }
208223}
209224
210- void ffmpegCppAddFilter (void * handle, const char * filterString)
211- {
212- // TODO
213- }
214-
215-
216225bool ffmpegCppIsError (void * handle)
217226{
218227 return ((Context*)handle)->errored ;
219228}
220229
221230const char * ffmpegCppGetError (void * handle)
222231{
223- return ((Context*)handle)->error .c_str ();
232+ Context* ctx = (Context*)handle;
233+ return ctx->error ;
224234}
225235
226236void ffmpegCppClose (void * handle)
0 commit comments