@@ -2,6 +2,7 @@ package ffmpeg
2
2
3
3
import (
4
4
"slices"
5
+ "strings"
5
6
6
7
// Packages
7
8
media "github.com/mutablelogic/go-media"
@@ -69,9 +70,6 @@ func NewManager(opt ...Opt) (*Manager, error) {
69
70
return manager , nil
70
71
}
71
72
72
- ///////////////////////////////////////////////////////////////////////////////
73
- // PUBLIC METHODS
74
-
75
73
// Open a media file or device for reading, from a path or url.
76
74
// If a format is specified, then the format will be used to open
77
75
// the file. You can add additional options to the open call as
@@ -97,6 +95,194 @@ func (manager *Manager) NewReader(r io.Reader, format media.Format, opts ...stri
97
95
}
98
96
*/
99
97
98
+ ///////////////////////////////////////////////////////////////////////////////
99
+ // PUBLIC METHODS - FORMATS
100
+
101
+ func (manager * Manager ) Formats (t media.Type , name ... string ) []media.Format {
102
+ // Create filters
103
+ matchesInputFilter := func (demuxer * ff.AVInputFormat , filter string ) bool {
104
+ if strings .HasPrefix (filter , "." ) {
105
+ // By extension
106
+ ext := strings .Split (demuxer .Extensions (), "," )
107
+ for _ , ext := range ext {
108
+ if filter == "." + ext {
109
+ return true
110
+ }
111
+ }
112
+ } else if strings .Contains (filter , "/" ) {
113
+ // By mimetype
114
+ if slices .Contains (strings .Split (demuxer .MimeTypes (), "," ), filter ) {
115
+ return true
116
+ }
117
+ } else {
118
+ // By name
119
+ if slices .Contains (strings .Split (demuxer .Name (), "," ), filter ) {
120
+ return true
121
+ }
122
+ }
123
+ return false
124
+ }
125
+ matchesOutputFilter := func (muxer * ff.AVOutputFormat , filter string ) bool {
126
+ if strings .HasPrefix (filter , "." ) {
127
+ // By extension
128
+ ext := strings .Split (muxer .Extensions (), "," )
129
+ for _ , ext := range ext {
130
+ if filter == "." + ext {
131
+ return true
132
+ }
133
+ }
134
+ } else if strings .Contains (filter , "/" ) {
135
+ // By mimetype
136
+ if slices .Contains (strings .Split (muxer .MimeTypes (), "," ), filter ) {
137
+ return true
138
+ }
139
+ } else {
140
+ // By name
141
+ if slices .Contains (strings .Split (muxer .Name (), "," ), filter ) {
142
+ return true
143
+ }
144
+ }
145
+ return false
146
+ }
147
+ matchesInputFormat := func (demuxer * ff.AVInputFormat , t media.Type , filter ... string ) bool {
148
+ // Check for INPUT
149
+ if ! t .Is (media .INPUT ) && ! t .Is (media .ANY ) {
150
+ return false
151
+ }
152
+ if t .Is (media .DEVICE ) {
153
+ return false
154
+ }
155
+ if len (filter ) == 0 {
156
+ return true
157
+ }
158
+ for _ , filter := range filter {
159
+ if matchesInputFilter (demuxer , filter ) {
160
+ return true
161
+ }
162
+ }
163
+ return false
164
+ }
165
+ matchesOutputFormat := func (muxer * ff.AVOutputFormat , t media.Type , filter ... string ) bool {
166
+ // Check for OUTPUT
167
+ if ! t .Is (media .OUTPUT ) && ! t .Is (media .ANY ) {
168
+ return false
169
+ }
170
+ if t .Is (media .DEVICE ) {
171
+ return false
172
+ }
173
+ if len (filter ) == 0 {
174
+ return true
175
+ }
176
+ for _ , filter := range filter {
177
+ if matchesOutputFilter (muxer , filter ) {
178
+ return true
179
+ }
180
+ }
181
+ return false
182
+ }
183
+ matchesInputDevice := func (demuxer * ff.AVInputFormat , filter ... string ) bool {
184
+ if len (filter ) == 0 {
185
+ return true
186
+ }
187
+ for _ , filter := range filter {
188
+ if demuxer .Name () == filter {
189
+ return true
190
+ }
191
+ }
192
+ return false
193
+ }
194
+ matchesOutputDevice := func (muxer * ff.AVOutputFormat , filter ... string ) bool {
195
+ if len (filter ) == 0 {
196
+ return true
197
+ }
198
+ for _ , filter := range filter {
199
+ if muxer .Name () == filter {
200
+ return true
201
+ }
202
+ }
203
+ return false
204
+ }
205
+
206
+ // Iterate over all input formats
207
+ var opaque uintptr
208
+ result := []media.Format {}
209
+ for {
210
+ demuxer := ff .AVFormat_demuxer_iterate (& opaque )
211
+ if demuxer == nil {
212
+ break
213
+ }
214
+ if matchesInputFormat (demuxer , t , name ... ) {
215
+ result = append (result , newInputFormats (demuxer , media .INPUT )... )
216
+ }
217
+ }
218
+
219
+ // Iterate over all output formats
220
+ var opaque2 uintptr
221
+ for {
222
+ muxer := ff .AVFormat_muxer_iterate (& opaque2 )
223
+ if muxer == nil {
224
+ break
225
+ }
226
+ if matchesOutputFormat (muxer , t , name ... ) {
227
+ result = append (result , newOutputFormats (muxer , media .OUTPUT )... )
228
+ }
229
+ }
230
+
231
+ // Return if DEVICE is not requested
232
+ if ! t .Is (media .DEVICE ) && ! t .Is (media .ANY ) {
233
+ return result
234
+ }
235
+
236
+ // Iterate over all device inputs
237
+ audio_input := ff .AVDevice_input_audio_device_first ()
238
+ for {
239
+ if audio_input == nil {
240
+ break
241
+ }
242
+ if matchesInputDevice (audio_input , name ... ) {
243
+ result = append (result , newInputFormats (audio_input , media .INPUT | media .AUDIO | media .DEVICE )... )
244
+ }
245
+ audio_input = ff .AVDevice_input_audio_device_next (audio_input )
246
+ }
247
+
248
+ video_input := ff .AVDevice_input_video_device_first ()
249
+ for {
250
+ if video_input == nil {
251
+ break
252
+ }
253
+ if matchesInputDevice (video_input , name ... ) {
254
+ result = append (result , newInputFormats (video_input , media .INPUT | media .VIDEO | media .DEVICE )... )
255
+ }
256
+ video_input = ff .AVDevice_input_video_device_next (video_input )
257
+ }
258
+
259
+ // Iterate over all device outputs
260
+ audio_output := ff .AVDevice_output_audio_device_first ()
261
+ for {
262
+ if audio_output == nil {
263
+ break
264
+ }
265
+ if matchesOutputDevice (audio_output , name ... ) {
266
+ result = append (result , newOutputFormats (audio_output , media .OUTPUT | media .AUDIO | media .DEVICE )... )
267
+ }
268
+ audio_output = ff .AVDevice_output_audio_device_next (audio_output )
269
+ }
270
+
271
+ video_output := ff .AVDevice_output_video_device_first ()
272
+ for {
273
+ if video_output == nil {
274
+ break
275
+ }
276
+ if matchesOutputDevice (video_output , name ... ) {
277
+ result = append (result , newOutputFormats (video_output , media .OUTPUT | media .VIDEO | media .DEVICE )... )
278
+ }
279
+ video_output = ff .AVDevice_output_video_device_next (video_output )
280
+ }
281
+
282
+ // Return formats
283
+ return result
284
+ }
285
+
100
286
///////////////////////////////////////////////////////////////////////////////
101
287
// PUBLIC METHODS - CODECS, PIXEL FORMATS, SAMPLE FORMATS AND CHANNEL
102
288
// LAYOUTS
0 commit comments