bare-ffmpeg 1.0.0-3 → 1.0.0-31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CMakeLists.txt +10 -3
  2. package/README.md +1811 -0
  3. package/binding.cc +4638 -0
  4. package/cmake/ports/ffmpeg/port.cmake +514 -0
  5. package/cmake/ports/opus/patches/01-windows-clang.patch +52 -0
  6. package/cmake/ports/opus/port.cmake +42 -0
  7. package/cmake/ports/svt-av1/port.cmake +42 -0
  8. package/cmake/ports/x264/patches/01-windows-clang.patch +33 -0
  9. package/cmake/ports/x264/port.cmake +157 -0
  10. package/index.js +22 -4
  11. package/lib/audio-fifo.js +47 -0
  12. package/lib/channel-layout.js +35 -0
  13. package/lib/codec-context.js +210 -16
  14. package/lib/codec-parameters.js +242 -8
  15. package/lib/codec.js +19 -1
  16. package/lib/constants.js +245 -9
  17. package/lib/dictionary.js +28 -15
  18. package/lib/errors.js +38 -0
  19. package/lib/filter-context.js +7 -0
  20. package/lib/filter-graph.js +47 -0
  21. package/lib/filter-inout.js +55 -0
  22. package/lib/filter.js +7 -0
  23. package/lib/format-context.js +72 -31
  24. package/lib/frame.js +88 -22
  25. package/lib/image.js +22 -0
  26. package/lib/input-format.js +36 -4
  27. package/lib/io-context.js +36 -6
  28. package/lib/log.js +16 -0
  29. package/lib/output-format.js +33 -2
  30. package/lib/packet.js +153 -12
  31. package/lib/rational.js +49 -1
  32. package/lib/resampler.js +63 -0
  33. package/lib/samples.js +96 -0
  34. package/lib/scaler.js +8 -7
  35. package/lib/stream.js +58 -14
  36. package/package.json +9 -4
  37. package/prebuilds/android-arm/bare-ffmpeg.bare +0 -0
  38. package/prebuilds/android-arm64/bare-ffmpeg.bare +0 -0
  39. package/prebuilds/android-ia32/bare-ffmpeg.bare +0 -0
  40. package/prebuilds/android-x64/bare-ffmpeg.bare +0 -0
  41. package/prebuilds/darwin-arm64/bare-ffmpeg.bare +0 -0
  42. package/prebuilds/darwin-x64/bare-ffmpeg.bare +0 -0
  43. package/prebuilds/ios-arm64/bare-ffmpeg.bare +0 -0
  44. package/prebuilds/ios-arm64-simulator/bare-ffmpeg.bare +0 -0
  45. package/prebuilds/ios-x64-simulator/bare-ffmpeg.bare +0 -0
  46. package/prebuilds/linux-arm64/bare-ffmpeg.bare +0 -0
  47. package/prebuilds/linux-x64/bare-ffmpeg.bare +0 -0
  48. package/prebuilds/win32-arm64/bare-ffmpeg.bare +0 -0
  49. package/prebuilds/win32-x64/bare-ffmpeg.bare +0 -0
  50. package/binding.c +0 -2203
  51. package/lib/reference-counted.js +0 -39
@@ -0,0 +1,157 @@
1
+ include_guard(GLOBAL)
2
+
3
+ if(WIN32)
4
+ set(lib x264.lib)
5
+ else()
6
+ set(lib libx264.a)
7
+ endif()
8
+
9
+ set(env)
10
+
11
+ set(args
12
+ --disable-cli
13
+
14
+ --enable-static
15
+ --enable-strip
16
+ --enable-pic
17
+ )
18
+
19
+ if(CMAKE_BUILD_TYPE MATCHES "Debug|RelWithDebInfo")
20
+ list(APPEND args --enable-debug)
21
+ endif()
22
+
23
+ if(CMAKE_SYSTEM_NAME)
24
+ set(platform ${CMAKE_SYSTEM_NAME})
25
+ else()
26
+ set(platform ${CMAKE_HOST_SYSTEM_NAME})
27
+ endif()
28
+
29
+ string(TOLOWER "${platform}" platform)
30
+
31
+ if(platform MATCHES "darwin|ios")
32
+ set(platform "darwin")
33
+ elseif(platform MATCHES "linux|android")
34
+ set(platform "linux")
35
+ elseif(platform MATCHES "windows")
36
+ set(platform "msys")
37
+ else()
38
+ message(FATAL_ERROR "Unsupported platform '${platform}'")
39
+ endif()
40
+
41
+ if(APPLE AND CMAKE_OSX_ARCHITECTURES)
42
+ set(arch ${CMAKE_OSX_ARCHITECTURES})
43
+ elseif(MSVC AND CMAKE_GENERATOR_PLATFORM)
44
+ set(arch ${CMAKE_GENERATOR_PLATFORM})
45
+ elseif(ANDROID AND CMAKE_ANDROID_ARCH_ABI)
46
+ set(arch ${CMAKE_ANDROID_ARCH_ABI})
47
+ elseif(CMAKE_SYSTEM_PROCESSOR)
48
+ set(arch ${CMAKE_SYSTEM_PROCESSOR})
49
+ else()
50
+ set(arch ${CMAKE_HOST_SYSTEM_PROCESSOR})
51
+ endif()
52
+
53
+ string(TOLOWER "${arch}" arch)
54
+
55
+ if(arch MATCHES "arm64|aarch64")
56
+ set(arch "aarch64")
57
+ elseif(arch MATCHES "armv7-a|armeabi-v7a")
58
+ set(arch "arm")
59
+ elseif(arch MATCHES "x64|x86_64|amd64")
60
+ set(arch "x86_64")
61
+ elseif(arch MATCHES "x86|i386|i486|i586|i686")
62
+ set(arch "i686")
63
+ else()
64
+ message(FATAL_ERROR "Unsupported architecture '${arch}'")
65
+ endif()
66
+
67
+ list(APPEND args --host=${arch}-${platform})
68
+
69
+ if(APPLE)
70
+ list(APPEND args --sysroot=${CMAKE_OSX_SYSROOT})
71
+ elseif(ANDROID)
72
+ list(APPEND args --sysroot=${CMAKE_SYSROOT} --disable-asm)
73
+ elseif(WIN32)
74
+ list(APPEND args --disable-asm)
75
+ endif()
76
+
77
+ if(CMAKE_C_COMPILER)
78
+ cmake_path(GET CMAKE_C_COMPILER PARENT_PATH CC_path)
79
+ cmake_path(GET CMAKE_C_COMPILER FILENAME CC_filename)
80
+
81
+ list(APPEND env "CC=${CC_filename}")
82
+
83
+ list(APPEND args
84
+ --extra-cflags=--target=${CMAKE_C_COMPILER_TARGET}
85
+ --extra-ldflags=--target=${CMAKE_C_COMPILER_TARGET}
86
+ )
87
+
88
+ if(CMAKE_LINKER_TYPE MATCHES "LLD")
89
+ list(APPEND args --extra-ldflags=-fuse-ld=lld)
90
+ endif()
91
+
92
+ list(APPEND env --modify "PATH=path_list_prepend:${CC_path}")
93
+ endif()
94
+
95
+ if(CMAKE_ASM_NASM_COMPILER)
96
+ cmake_path(GET CMAKE_ASM_NASM_COMPILER PARENT_PATH AS_path)
97
+ cmake_path(GET CMAKE_ASM_NASM_COMPILER FILENAME AS_filename)
98
+
99
+ list(APPEND env "AS=${AS_filename}")
100
+
101
+ list(APPEND env --modify "PATH=path_list_prepend:${AS_path}")
102
+ elseif(CMAKE_ASM_COMPILER)
103
+ cmake_path(GET CMAKE_ASM_COMPILER PARENT_PATH AS_path)
104
+ cmake_path(GET CMAKE_ASM_COMPILER FILENAME AS_filename)
105
+
106
+ list(APPEND env "AS=${AS_filename}")
107
+
108
+ list(APPEND args --extra-asflags=--target=${CMAKE_ASM_COMPILER_TARGET})
109
+
110
+ list(APPEND env --modify "PATH=path_list_prepend:${AS_path}")
111
+ endif()
112
+
113
+ if(CMAKE_RC_COMPILER)
114
+ cmake_path(GET CMAKE_RC_COMPILER PARENT_PATH RC_path)
115
+ cmake_path(GET CMAKE_RC_COMPILER FILENAME RC_filename)
116
+
117
+ list(APPEND env "RC=${RC_filename}")
118
+
119
+ list(APPEND env --modify "PATH=path_list_prepend:${RC_path}")
120
+ endif()
121
+
122
+ if(CMAKE_AR)
123
+ cmake_path(GET CMAKE_AR PARENT_PATH AR_path)
124
+ cmake_path(GET CMAKE_AR FILENAME AR_filename)
125
+
126
+ list(APPEND env "AR=${AR_filename}")
127
+
128
+ list(APPEND env --modify "PATH=path_list_prepend:${AR_path}")
129
+ endif()
130
+
131
+ declare_port(
132
+ "git:code.videolan.org/videolan/x264#stable"
133
+ x264
134
+ AUTOTOOLS
135
+ BYPRODUCTS lib/${lib}
136
+ ARGS ${args}
137
+ ENV ${env}
138
+ PATCHES
139
+ patches/01-windows-clang.patch
140
+ )
141
+
142
+ add_library(x264 STATIC IMPORTED GLOBAL)
143
+
144
+ add_dependencies(x264 ${x264})
145
+
146
+ set_target_properties(
147
+ x264
148
+ PROPERTIES
149
+ IMPORTED_LOCATION "${x264_PREFIX}/lib/${lib}"
150
+ )
151
+
152
+ file(MAKE_DIRECTORY "${x264_PREFIX}/include")
153
+
154
+ target_include_directories(
155
+ x264
156
+ INTERFACE "${x264_PREFIX}/include"
157
+ )
package/index.js CHANGED
@@ -1,28 +1,44 @@
1
+ const AudioFIFO = require('./lib/audio-fifo')
2
+ const ChannelLayout = require('./lib/channel-layout')
1
3
  const Codec = require('./lib/codec')
2
4
  const CodecContext = require('./lib/codec-context')
3
5
  const CodecParameters = require('./lib/codec-parameters')
4
6
  const Decoder = require('./lib/decoder')
7
+ const Dictionary = require('./lib/dictionary')
5
8
  const Encoder = require('./lib/encoder')
6
9
  const {
7
10
  InputFormatContext,
8
11
  OutputFormatContext
9
12
  } = require('./lib/format-context')
13
+ const Filter = require('./lib/filter')
14
+ const FilterContext = require('./lib/filter-context')
15
+ const FilterGraph = require('./lib/filter-graph')
16
+ const FilterInOut = require('./lib/filter-inout')
10
17
  const Frame = require('./lib/frame')
11
- const Image = require('./lib/image')
12
18
  const IOContext = require('./lib/io-context')
19
+ const Image = require('./lib/image')
13
20
  const InputFormat = require('./lib/input-format')
14
21
  const OutputFormat = require('./lib/output-format')
15
22
  const Packet = require('./lib/packet')
23
+ const Rational = require('./lib/rational')
24
+ const Resampler = require('./lib/resampler')
25
+ const Samples = require('./lib/samples')
16
26
  const Scaler = require('./lib/scaler')
17
27
  const Stream = require('./lib/stream')
18
- const Rational = require('./lib/rational')
19
- const Dictionary = require('./lib/dictionary')
28
+ const log = require('./lib/log')
20
29
 
30
+ exports.AudioFIFO = AudioFIFO
31
+ exports.ChannelLayout = ChannelLayout
21
32
  exports.Codec = Codec
22
33
  exports.CodecContext = CodecContext
23
34
  exports.CodecParameters = CodecParameters
24
35
  exports.Decoder = Decoder
36
+ exports.Dictionary = Dictionary
25
37
  exports.Encoder = Encoder
38
+ exports.Filter = Filter
39
+ exports.FilterContext = FilterContext
40
+ exports.FilterGraph = FilterGraph
41
+ exports.FilterInOut = FilterInOut
26
42
  exports.Frame = Frame
27
43
  exports.IOContext = IOContext
28
44
  exports.Image = Image
@@ -31,9 +47,11 @@ exports.InputFormatContext = InputFormatContext
31
47
  exports.OutputFormat = OutputFormat
32
48
  exports.OutputFormatContext = OutputFormatContext
33
49
  exports.Packet = Packet
50
+ exports.Samples = Samples
34
51
  exports.Scaler = Scaler
35
52
  exports.Stream = Stream
36
53
  exports.Rational = Rational
37
- exports.Dictionary = Dictionary
54
+ exports.Resampler = Resampler
55
+ exports.log = log
38
56
 
39
57
  exports.constants = require('./lib/constants')
@@ -0,0 +1,47 @@
1
+ const binding = require('../binding')
2
+ const constants = require('./constants')
3
+
4
+ module.exports = class FFmpegAudioFIFO {
5
+ constructor(sampleFormat, channels, nbSamples) {
6
+ sampleFormat = constants.toSampleFormat(sampleFormat)
7
+
8
+ this._handle = binding.initAudioFifo(sampleFormat, channels, nbSamples)
9
+ }
10
+
11
+ destroy() {
12
+ binding.destroyAudioFifo(this._handle)
13
+ this._handle = null
14
+ }
15
+
16
+ write(frame) {
17
+ return binding.writeAudioFifo(this._handle, frame._handle)
18
+ }
19
+
20
+ read(frame, nbSamples) {
21
+ return binding.readAudioFifo(this._handle, frame._handle, nbSamples)
22
+ }
23
+
24
+ peek(frame, nbSamples) {
25
+ return binding.peekAudioFifo(this._handle, frame._handle, nbSamples)
26
+ }
27
+
28
+ drain(nbSamples) {
29
+ return binding.drainAudioFifo(this._handle, nbSamples)
30
+ }
31
+
32
+ reset() {
33
+ binding.resetAudioFifo(this._handle)
34
+ }
35
+
36
+ get size() {
37
+ return binding.getAudioFifoSize(this._handle)
38
+ }
39
+
40
+ get space() {
41
+ return binding.getAudioFifoSpace(this._handle)
42
+ }
43
+
44
+ [Symbol.dispose]() {
45
+ this.destroy()
46
+ }
47
+ }
@@ -0,0 +1,35 @@
1
+ const binding = require('../binding')
2
+ const constants = require('./constants')
3
+
4
+ module.exports = class FFmpegChannelLayout {
5
+ constructor(handle) {
6
+ this._handle = handle
7
+ }
8
+
9
+ get nbChannels() {
10
+ return binding.getChannelLayoutNbChannels(this._handle)
11
+ }
12
+
13
+ get mask() {
14
+ return binding.getChannelLayoutMask(this._handle)
15
+ }
16
+
17
+ static from(value) {
18
+ if (typeof value === 'string') value = constants.toChannelLayout(value)
19
+
20
+ if (typeof value === 'number') {
21
+ value = binding.channelLayoutFromMask(value)
22
+ } else if (typeof value === 'object' && value !== null) {
23
+ value = binding.copyChannelLayout(value._handle)
24
+ }
25
+
26
+ return new this(value)
27
+ }
28
+
29
+ [Symbol.for('bare.inspect')]() {
30
+ return {
31
+ __proto__: { constructor: FFmpegChannelLayout },
32
+ nbChannels: this.nbChannels
33
+ }
34
+ }
35
+ }
@@ -1,17 +1,16 @@
1
1
  const binding = require('../binding')
2
- const ReferenceCounted = require('./reference-counted')
3
2
  const Rational = require('./rational')
3
+ const ChannelLayout = require('./channel-layout')
4
+ const { codecConfig, optionFlags } = require('./constants')
4
5
 
5
- module.exports = class FFmpegCodecContext extends ReferenceCounted {
6
+ module.exports = class FFmpegCodecContext {
6
7
  constructor(codec) {
7
- super()
8
-
9
8
  this._codec = codec
10
9
  this._opened = false
11
10
  this._handle = binding.initCodecContext(codec._handle)
12
11
  }
13
12
 
14
- _destroy() {
13
+ destroy() {
15
14
  binding.destroyCodecContext(this._handle)
16
15
  this._handle = null
17
16
  }
@@ -40,16 +39,109 @@ module.exports = class FFmpegCodecContext extends ReferenceCounted {
40
39
  binding.setCodecContextHeight(this._handle, value)
41
40
  }
42
41
 
42
+ get sampleFormat() {
43
+ return binding.getCodecContextSampleFormat(this._handle)
44
+ }
45
+
46
+ set sampleFormat(value) {
47
+ return binding.setCodecContextSampleFormat(this._handle, value)
48
+ }
49
+
50
+ get sampleRate() {
51
+ return binding.getCodecContextSampleRate(this._handle)
52
+ }
53
+
54
+ set sampleRate(value) {
55
+ binding.setCodecContextSampleRate(this._handle, value)
56
+ }
57
+
43
58
  get timeBase() {
44
59
  const view = new Int32Array(binding.getCodecContextTimeBase(this._handle))
45
60
  return new Rational(view[0], view[1])
46
61
  }
47
62
 
48
63
  set timeBase(value) {
49
- const view = new Int32Array(2)
50
- view[0] = value.numerator
51
- view[1] = value.denominator
52
- binding.setCodecContextTimeBase(this._handle, view.buffer)
64
+ binding.setCodecContextTimeBase(
65
+ this._handle,
66
+ value.numerator,
67
+ value.denominator
68
+ )
69
+ }
70
+
71
+ get frameRate() {
72
+ const view = new Int32Array(binding.getCodecContextFramerate(this._handle))
73
+ return new Rational(view[0], view[1])
74
+ }
75
+
76
+ set frameRate(value) {
77
+ binding.setCodecContextFramerate(
78
+ this._handle,
79
+ value.numerator,
80
+ value.denominator
81
+ )
82
+ }
83
+
84
+ get channelLayout() {
85
+ return new ChannelLayout(binding.getCodecContextChannelLayout(this._handle))
86
+ }
87
+
88
+ set channelLayout(value) {
89
+ binding.setCodecContextChannelLayout(
90
+ this._handle,
91
+ ChannelLayout.from(value)._handle
92
+ )
93
+ }
94
+
95
+ get gopSize() {
96
+ return binding.getCodecContextGOPSize(this._handle)
97
+ }
98
+
99
+ set gopSize(value) {
100
+ binding.setCodecContextGOPSize(this._handle, value)
101
+ }
102
+
103
+ get flags() {
104
+ return binding.getCodecContextFlags(this._handle)
105
+ }
106
+
107
+ set flags(value) {
108
+ binding.setCodecContextFlags(this._handle, value)
109
+ }
110
+
111
+ get extraData() {
112
+ return Buffer.from(binding.getCodecContextExtraData(this._handle))
113
+ }
114
+
115
+ set extraData(value) {
116
+ binding.setCodecContextExtraData(
117
+ this._handle,
118
+ value.buffer,
119
+ value.byteOffset,
120
+ value.byteLength
121
+ )
122
+ }
123
+
124
+ get frameSize() {
125
+ return binding.getCodecContextFrameSize(this._handle)
126
+ }
127
+
128
+ get frameNum() {
129
+ return binding.getCodecContextFrameNum(this._handle)
130
+ }
131
+
132
+ get requestSampleFormat() {
133
+ return binding.getCodecContextRequestSampleFormat(this._handle)
134
+ }
135
+
136
+ set requestSampleFormat(sampleFormat) {
137
+ binding.setCodecContextRequestSampleFormat(this._handle, sampleFormat)
138
+ }
139
+
140
+ set getFormat(callback) {
141
+ const wrap = (pixelFormats) => {
142
+ return callback(this, pixelFormats)
143
+ }
144
+ binding.setCodecContextGetFormat(this._handle, wrap)
53
145
  }
54
146
 
55
147
  open(options) {
@@ -60,25 +152,127 @@ module.exports = class FFmpegCodecContext extends ReferenceCounted {
60
152
  } else {
61
153
  binding.openCodecContext(this._handle)
62
154
  }
63
- return this
64
155
  }
65
156
 
66
157
  sendPacket(packet) {
67
- binding.sendCodecContextPacket(this._handle, packet._handle)
68
- return this
158
+ return binding.sendCodecContextPacket(this._handle, packet._handle)
69
159
  }
70
160
 
71
161
  receivePacket(packet) {
72
- const res = binding.receiveCodecContextPacket(this._handle, packet._handle)
73
- if (res) packet._ref()
74
- return res
162
+ return binding.receiveCodecContextPacket(this._handle, packet._handle)
75
163
  }
76
164
 
77
165
  sendFrame(frame) {
78
- return binding.sendCodecContextFrame(this._handle, frame._handle)
166
+ let frameHandle = undefined
167
+
168
+ if (frame) frameHandle = frame._handle
169
+
170
+ return binding.sendCodecContextFrame(this._handle, frameHandle)
79
171
  }
80
172
 
81
173
  receiveFrame(frame) {
82
174
  return binding.receiveCodecContextFrame(this._handle, frame._handle)
83
175
  }
176
+
177
+ getSupportedConfig(config) {
178
+ if (config === codecConfig.FRAME_RATE) {
179
+ const data = binding.getSupportedFrameRates(
180
+ this._handle,
181
+ this._codec._handle
182
+ )
183
+ if (!data || data.length === 0) return null
184
+
185
+ const view = new Int32Array(data)
186
+ const rates = []
187
+ for (let i = 0; i < view.length; i += 2) {
188
+ rates.push(new Rational(view[i], view[i + 1]))
189
+ }
190
+ return rates
191
+ }
192
+
193
+ if (config === codecConfig.CHANNEL_LAYOUT) {
194
+ const handles = binding.getSupportedChannelLayouts(
195
+ this._handle,
196
+ this._codec._handle
197
+ )
198
+ if (!handles || handles.length === 0) return null
199
+
200
+ return handles.map((handle) => new ChannelLayout(handle))
201
+ }
202
+
203
+ const data = binding.getSupportedConfig(
204
+ this._handle,
205
+ this._codec._handle,
206
+ config
207
+ )
208
+
209
+ if (config === codecConfig.SAMPLE_RATE && !data) {
210
+ return null
211
+ }
212
+
213
+ return new Int32Array(data)
214
+ }
215
+
216
+ getOption(name, flags = optionFlags.SEARCH_CHILDREN) {
217
+ return binding.getOption(this._handle, name, flags)
218
+ }
219
+
220
+ setOption(name, value, flags = optionFlags.SEARCH_CHILDREN) {
221
+ return binding.setOption(this._handle, name, value, flags)
222
+ }
223
+
224
+ setOptionDictionary(dictionary, flags = optionFlags.SEARCH_CHILDREN) {
225
+ return binding.setOptionDictionary(this._handle, dictionary._handle, flags)
226
+ }
227
+
228
+ setOptionDefaults() {
229
+ return binding.setOptionDefaults(this._handle)
230
+ }
231
+
232
+ listOptionNames(flags = optionFlags.SEARCH_CHILDREN) {
233
+ return binding.listOptionNames(this._handle, flags)
234
+ }
235
+
236
+ getOptions(flags) {
237
+ const options = {}
238
+
239
+ for (const name of this.listOptionNames(flags)) {
240
+ try {
241
+ options[name] = this.getOption(name, flags)
242
+ } catch (error) {
243
+ // TODO: handle binary and other non-string types
244
+ }
245
+ }
246
+
247
+ return options
248
+ }
249
+
250
+ copyOptionsFrom(codecContext) {
251
+ binding.copyOptions(this._handle, codecContext._handle)
252
+ }
253
+
254
+ [Symbol.dispose]() {
255
+ this.destroy()
256
+ }
257
+
258
+ [Symbol.for('bare.inspect')]() {
259
+ return {
260
+ __proto__: { constructor: FFmpegCodecContext },
261
+ _codec: this._codec,
262
+ _opened: this._opened,
263
+ flags: this.flags,
264
+ pixelFormat: this.pixelFormat,
265
+ width: this.width,
266
+ height: this.height,
267
+ sampleFormat: this.sampleFormat,
268
+ sampleRate: this.sampleRate,
269
+ timeBase: this.timeBase,
270
+ channelLayout: this.channelLayout,
271
+ gopSize: this.gopSize,
272
+ extraData: this.extraData,
273
+ frameRate: this.frameRate,
274
+ frameSize: this.frameSize,
275
+ frameNum: this.frameNum
276
+ }
277
+ }
84
278
  }