bare-ffmpeg 1.0.0-2 → 1.0.0-21

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 (47) hide show
  1. package/CMakeLists.txt +10 -3
  2. package/README.md +1097 -0
  3. package/binding.cc +3330 -0
  4. package/cmake/ports/ffmpeg/port.cmake +513 -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 +14 -4
  11. package/lib/audio-fifo.js +47 -0
  12. package/lib/channel-layout.js +35 -0
  13. package/lib/codec-context.js +92 -15
  14. package/lib/codec-parameters.js +230 -8
  15. package/lib/codec.js +19 -0
  16. package/lib/constants.js +163 -8
  17. package/lib/dictionary.js +18 -15
  18. package/lib/errors.js +38 -0
  19. package/lib/format-context.js +62 -31
  20. package/lib/frame.js +87 -16
  21. package/lib/image.js +22 -0
  22. package/lib/input-format.js +8 -3
  23. package/lib/io-context.js +29 -6
  24. package/lib/log.js +16 -0
  25. package/lib/output-format.js +4 -0
  26. package/lib/packet.js +88 -13
  27. package/lib/rational.js +35 -1
  28. package/lib/resampler.js +63 -0
  29. package/lib/samples.js +49 -0
  30. package/lib/scaler.js +8 -7
  31. package/lib/stream.js +37 -12
  32. package/package.json +7 -4
  33. package/prebuilds/android-arm/bare-ffmpeg.bare +0 -0
  34. package/prebuilds/android-arm64/bare-ffmpeg.bare +0 -0
  35. package/prebuilds/android-ia32/bare-ffmpeg.bare +0 -0
  36. package/prebuilds/android-x64/bare-ffmpeg.bare +0 -0
  37. package/prebuilds/darwin-arm64/bare-ffmpeg.bare +0 -0
  38. package/prebuilds/darwin-x64/bare-ffmpeg.bare +0 -0
  39. package/prebuilds/ios-arm64/bare-ffmpeg.bare +0 -0
  40. package/prebuilds/ios-arm64-simulator/bare-ffmpeg.bare +0 -0
  41. package/prebuilds/ios-x64-simulator/bare-ffmpeg.bare +0 -0
  42. package/prebuilds/linux-arm64/bare-ffmpeg.bare +0 -0
  43. package/prebuilds/linux-x64/bare-ffmpeg.bare +0 -0
  44. package/prebuilds/win32-arm64/bare-ffmpeg.bare +0 -0
  45. package/prebuilds/win32-x64/bare-ffmpeg.bare +0 -0
  46. package/binding.c +0 -2128
  47. package/lib/reference-counted.js +0 -39
package/lib/io-context.js CHANGED
@@ -1,15 +1,38 @@
1
1
  const binding = require('../binding')
2
- const ReferenceCounted = require('./reference-counted')
3
2
 
4
- module.exports = class FFmpegIOContext extends ReferenceCounted {
5
- constructor(buffer = Buffer.alloc(0)) {
6
- super()
3
+ module.exports = class FFmpegIOContext {
4
+ constructor(buffer, opts = {}) {
5
+ let offset = 0
6
+ let len = 0
7
7
 
8
- this._handle = binding.initIOContext(buffer)
8
+ if (typeof buffer === 'number') {
9
+ len = buffer
10
+ buffer = undefined
11
+ } else if (buffer) {
12
+ offset = buffer.byteOffset
13
+ len = buffer.byteLength
14
+ buffer = buffer.buffer
15
+ } else {
16
+ buffer = Buffer.alloc(0)
17
+ }
18
+
19
+ let onwrite
20
+
21
+ if (typeof opts.onwrite === 'function') {
22
+ onwrite = function (chunk) {
23
+ opts.onwrite(Buffer.from(chunk))
24
+ }
25
+ }
26
+
27
+ this._handle = binding.initIOContext(buffer, offset, len, onwrite)
9
28
  }
10
29
 
11
- _destroy() {
30
+ destroy() {
12
31
  binding.destroyIOContext(this._handle)
13
32
  this._handle = null
14
33
  }
34
+
35
+ [Symbol.dispose]() {
36
+ this.destroy()
37
+ }
15
38
  }
package/lib/log.js ADDED
@@ -0,0 +1,16 @@
1
+ const binding = require('../binding')
2
+ const constants = require('./constants')
3
+
4
+ module.exports = {
5
+ ...constants.logLevels
6
+ }
7
+
8
+ Object.defineProperty(module.exports, 'level', {
9
+ get() {
10
+ return binding.getLogLevel()
11
+ },
12
+
13
+ set(level) {
14
+ return binding.setLogLevel(level)
15
+ }
16
+ })
@@ -4,4 +4,8 @@ module.exports = class FFmpegOutputFormat {
4
4
  constructor(name) {
5
5
  this._handle = binding.initOutputFormat(name)
6
6
  }
7
+
8
+ get flags() {
9
+ return binding.getOutputFormatFlags(this._handle)
10
+ }
7
11
  }
package/lib/packet.js CHANGED
@@ -1,17 +1,9 @@
1
1
  const binding = require('../binding')
2
- const ReferenceCounted = require('./reference-counted')
2
+ const Rational = require('./rational')
3
3
 
4
- module.exports = class FFmpegPacket extends ReferenceCounted {
4
+ module.exports = class FFmpegPacket {
5
5
  constructor(buffer) {
6
- super()
7
-
8
6
  if (buffer) {
9
- if (!Buffer.isBuffer(buffer)) {
10
- throw TypeError(
11
- `Buffer parameter should be of type Buffer but got: ${typeof buffer}`
12
- )
13
- }
14
-
15
7
  this._handle = binding.initPacketFromBuffer(
16
8
  buffer.buffer,
17
9
  buffer.byteOffset,
@@ -22,13 +14,12 @@ module.exports = class FFmpegPacket extends ReferenceCounted {
22
14
  }
23
15
  }
24
16
 
25
- _destroy() {
26
- binding.destroyPacket(this._handle)
17
+ destroy() {
18
+ binding.unrefPacket(this._handle)
27
19
  this._handle = null
28
20
  }
29
21
 
30
22
  unref() {
31
- this._unref()
32
23
  binding.unrefPacket(this._handle)
33
24
  }
34
25
 
@@ -36,7 +27,91 @@ module.exports = class FFmpegPacket extends ReferenceCounted {
36
27
  return binding.getPacketStreamIndex(this._handle)
37
28
  }
38
29
 
30
+ set streamIndex(value) {
31
+ return binding.setPacketStreamIndex(this._handle, value)
32
+ }
33
+
39
34
  get data() {
40
35
  return Buffer.from(binding.getPacketData(this._handle))
41
36
  }
37
+
38
+ set data(value) {
39
+ binding.setPacketData(
40
+ this._handle,
41
+ value.buffer,
42
+ value.byteOffset,
43
+ value.byteLength
44
+ )
45
+ }
46
+
47
+ get isKeyframe() {
48
+ return binding.isPacketKeyframe(this._handle)
49
+ }
50
+
51
+ get dts() {
52
+ return binding.getPacketDTS(this._handle)
53
+ }
54
+
55
+ set dts(value) {
56
+ return binding.setPacketDTS(this._handle, value)
57
+ }
58
+
59
+ get pts() {
60
+ return binding.getPacketPTS(this._handle)
61
+ }
62
+
63
+ set pts(value) {
64
+ return binding.setPacketPTS(this._handle, value)
65
+ }
66
+
67
+ get timeBase() {
68
+ const view = new Int32Array(binding.getPacketTimeBase(this._handle))
69
+ return new Rational(view[0], view[1])
70
+ }
71
+
72
+ set timeBase(value) {
73
+ binding.setPacketTimeBase(this._handle, value.numerator, value.denominator)
74
+ }
75
+
76
+ rescaleTimestamps(rational) {
77
+ return binding.rescalePacketTimestamps(
78
+ this._handle,
79
+ rational.numerator,
80
+ rational.denominator
81
+ )
82
+ }
83
+
84
+ get duration() {
85
+ return binding.getPacketDuration(this._handle)
86
+ }
87
+
88
+ set duration(value) {
89
+ return binding.setPacketDuration(this._handle, value)
90
+ }
91
+
92
+ get flags() {
93
+ return binding.getPacketFlags(this._handle)
94
+ }
95
+
96
+ set flags(value) {
97
+ return binding.setPacketFlags(this._handle, value)
98
+ }
99
+
100
+ [Symbol.for('bare.inspect')]() {
101
+ return {
102
+ __proto__: { constructor: FFmpegPacket },
103
+ streamIndex: this.streamIndex,
104
+ flags: this.flags,
105
+ isKeyframe: this.isKeyframe,
106
+ timeBase: this.timeBase,
107
+ dts: this.dts,
108
+ pts: this.pts,
109
+ duration: this.duration,
110
+ data: this.data
111
+ }
112
+ }
113
+
114
+ [Symbol.dispose]() {
115
+ this.destroy()
116
+ }
42
117
  }
package/lib/rational.js CHANGED
@@ -1,6 +1,40 @@
1
+ const binding = require('../binding')
2
+
1
3
  module.exports = class FFmpegRational {
2
- constructor(numerator, denominator) {
4
+ constructor(numerator = 0, denominator = 1) {
3
5
  this.numerator = numerator
4
6
  this.denominator = denominator
5
7
  }
8
+
9
+ get valid() {
10
+ // don't support negative denominators for now
11
+ if (this.denominator < 0) return false
12
+
13
+ const n = this.toNumber()
14
+
15
+ if (Number.isNaN(n) || n === 0) return false
16
+
17
+ return true
18
+ }
19
+
20
+ get uninitialized() {
21
+ // common initial value for AVRational(0, 1)
22
+ return this.numerator === 0 && this.denominator === 1
23
+ }
24
+
25
+ toNumber() {
26
+ return this.numerator / this.denominator
27
+ }
28
+
29
+ static from(num) {
30
+ const view = new Int32Array(binding.rationalD2Q(num))
31
+ return new FFmpegRational(view[0], view[1])
32
+ }
33
+
34
+ static rescaleQ(n, src, dst) {
35
+ return (
36
+ (n * (src.numerator / src.denominator)) /
37
+ (dst.numerator / dst.denominator)
38
+ )
39
+ }
6
40
  }
@@ -0,0 +1,63 @@
1
+ const binding = require('../binding')
2
+ const ChannelLayout = require('./channel-layout')
3
+
4
+ class FFmpegResampler {
5
+ constructor(
6
+ inputSampleRate,
7
+ inputChannelLayout,
8
+ inputFormat,
9
+ outputSampleRate,
10
+ outputChannelLayout,
11
+ outputFormat
12
+ ) {
13
+ inputChannelLayout = ChannelLayout.from(inputChannelLayout)
14
+ outputChannelLayout = ChannelLayout.from(outputChannelLayout)
15
+
16
+ this._inputSampleRate = inputSampleRate
17
+ this._outputSampleRate = outputSampleRate
18
+
19
+ this._handle = binding.initResampler(
20
+ inputSampleRate,
21
+ inputFormat,
22
+ inputChannelLayout._handle,
23
+ outputSampleRate,
24
+ outputFormat,
25
+ outputChannelLayout._handle
26
+ )
27
+ }
28
+
29
+ get inputSampleRate() {
30
+ return this._inputSampleRate
31
+ }
32
+
33
+ get outputSampleRate() {
34
+ return this._outputSampleRate
35
+ }
36
+
37
+ get delay() {
38
+ return binding.getResamplerDelay(this._handle, this._inputSampleRate)
39
+ }
40
+
41
+ convert(inputFrame, outputFrame) {
42
+ return binding.convertResampler(
43
+ this._handle,
44
+ inputFrame._handle,
45
+ outputFrame._handle
46
+ )
47
+ }
48
+
49
+ flush(outputFrame) {
50
+ return binding.flushResampler(this._handle, outputFrame._handle)
51
+ }
52
+
53
+ destroy() {
54
+ binding.destroyResampler(this._handle)
55
+ this._handle = null
56
+ }
57
+
58
+ [Symbol.dispose]() {
59
+ this.destroy()
60
+ }
61
+ }
62
+
63
+ module.exports = FFmpegResampler
package/lib/samples.js ADDED
@@ -0,0 +1,49 @@
1
+ const binding = require('../binding')
2
+ const constants = require('./constants.js')
3
+
4
+ module.exports = class FFmpegSamples {
5
+ constructor(sampleFormat, nbChannels, nbSamples, align = 0) {
6
+ sampleFormat = constants.toSampleFormat(sampleFormat)
7
+
8
+ this._sampleFormat = sampleFormat
9
+ this._nbChannels = nbChannels
10
+ this._nbSamples = nbSamples
11
+ this._align = align
12
+
13
+ this._data = Buffer.from(
14
+ binding.initSamples(sampleFormat, nbChannels, nbSamples, align)
15
+ )
16
+ }
17
+
18
+ get sampleFormat() {
19
+ return this._sampleFormat
20
+ }
21
+
22
+ get nbChannels() {
23
+ return this._nbChannels
24
+ }
25
+
26
+ get nbSamples() {
27
+ return this._nbSamples
28
+ }
29
+
30
+ get align() {
31
+ return this._align
32
+ }
33
+
34
+ get data() {
35
+ return this._data
36
+ }
37
+
38
+ fill(frame) {
39
+ binding.fillSamples(
40
+ this._sampleFormat,
41
+ this._nbChannels,
42
+ this._nbSamples,
43
+ this._align,
44
+ this._data.buffer,
45
+ this._data.byteOffset,
46
+ frame._handle
47
+ )
48
+ }
49
+ }
package/lib/scaler.js CHANGED
@@ -1,8 +1,7 @@
1
1
  const binding = require('../binding')
2
2
  const constants = require('./constants')
3
- const ReferenceCounted = require('./reference-counted')
4
3
 
5
- module.exports = class FFmpegScaler extends ReferenceCounted {
4
+ module.exports = class FFmpegScaler {
6
5
  constructor(
7
6
  sourcePixelFormat,
8
7
  sourceWidth,
@@ -11,8 +10,6 @@ module.exports = class FFmpegScaler extends ReferenceCounted {
11
10
  targetWidth,
12
11
  targetHeight
13
12
  ) {
14
- super()
15
-
16
13
  sourcePixelFormat = constants.toPixelFormat(sourcePixelFormat)
17
14
  targetPixelFormat = constants.toPixelFormat(targetPixelFormat)
18
15
 
@@ -33,7 +30,7 @@ module.exports = class FFmpegScaler extends ReferenceCounted {
33
30
  )
34
31
  }
35
32
 
36
- _destroy() {
33
+ destroy() {
37
34
  binding.destroyScaler(this._handle)
38
35
  this._handle = null
39
36
  }
@@ -42,10 +39,10 @@ module.exports = class FFmpegScaler extends ReferenceCounted {
42
39
  if (typeof y !== 'number') {
43
40
  target = y
44
41
  y = 0
45
- height = this._targetHeight
42
+ height = source.height
46
43
  } else if (typeof height !== 'number') {
47
44
  target = height
48
- height = this._targetHeight
45
+ height = source.height
49
46
  }
50
47
 
51
48
  return binding.scaleScaler(
@@ -56,4 +53,8 @@ module.exports = class FFmpegScaler extends ReferenceCounted {
56
53
  target._handle
57
54
  )
58
55
  }
56
+
57
+ [Symbol.dispose]() {
58
+ this.destroy()
59
+ }
59
60
  }
package/lib/stream.js CHANGED
@@ -2,42 +2,67 @@ const binding = require('../binding')
2
2
  const Codec = require('./codec')
3
3
  const CodecContext = require('./codec-context')
4
4
  const CodecParameters = require('./codec-parameters')
5
- const ReferenceCounted = require('./reference-counted')
5
+ const Rational = require('./rational')
6
6
 
7
- module.exports = class FFmpegStream extends ReferenceCounted {
7
+ module.exports = class FFmpegStream {
8
8
  constructor(handle) {
9
- super()
10
-
11
9
  this._handle = handle
12
10
 
13
- this._codec = Codec.for(binding.getStreamCodec(this._handle))
14
-
15
11
  this._codecParameters = new CodecParameters(
16
12
  binding.getStreamCodecParameters(this._handle)
17
13
  )
18
14
  }
19
15
 
20
- _destroy() {
21
- this._codecParameters.destroy()
22
- this._codecParameters = null
16
+ get id() {
17
+ return binding.getStreamId(this._handle)
18
+ }
19
+
20
+ set id(value) {
21
+ binding.setStreamId(this._handle, value)
22
+ }
23
+
24
+ get index() {
25
+ return binding.getStreamIndex(this._handle)
23
26
  }
24
27
 
25
28
  get codec() {
26
- return this._codec
29
+ return Codec.for(this.codecParameters.id)
27
30
  }
28
31
 
29
32
  get codecParameters() {
30
33
  return this._codecParameters
31
34
  }
32
35
 
36
+ get timeBase() {
37
+ const view = new Int32Array(binding.getStreamTimeBase(this._handle))
38
+ return new Rational(view[0], view[1])
39
+ }
40
+
41
+ set timeBase(value) {
42
+ binding.setStreamTimeBase(this._handle, value.numerator, value.denominator)
43
+ }
44
+
45
+ get avgFramerate() {
46
+ const view = new Int32Array(binding.getStreamAverageFramerate(this._handle))
47
+ return new Rational(view[0], view[1])
48
+ }
49
+
50
+ set avgFramerate(value) {
51
+ binding.setStreamAverageFramerate(
52
+ this._handle,
53
+ value.numerator,
54
+ value.denominator
55
+ )
56
+ }
57
+
33
58
  decoder() {
34
- const context = new CodecContext(this._codec.decoder)
59
+ const context = new CodecContext(this.codec.decoder)
35
60
  this._codecParameters.toContext(context)
36
61
  return context.open()
37
62
  }
38
63
 
39
64
  encoder() {
40
- const context = new CodecContext(this._codec.encoder)
65
+ const context = new CodecContext(this.codec.encoder)
41
66
  this._codecParameters.toContext(context)
42
67
  return context.open()
43
68
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-ffmpeg",
3
- "version": "1.0.0-2",
3
+ "version": "1.0.0-21",
4
4
  "description": "Low-level FFmpeg bindings for Bare",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -8,15 +8,17 @@
8
8
  },
9
9
  "files": [
10
10
  "index.js",
11
- "binding.c",
11
+ "binding.cc",
12
12
  "binding.js",
13
13
  "CMakeLists.txt",
14
14
  "lib",
15
- "prebuilds"
15
+ "prebuilds",
16
+ "cmake"
16
17
  ],
17
18
  "addon": true,
18
19
  "scripts": {
19
- "test": "prettier . --check && bare test.js"
20
+ "test": "prettier . --check && bare test.js",
21
+ "format": "prettier . --write && clang-format -i binding.cc"
20
22
  },
21
23
  "repository": {
22
24
  "type": "git",
@@ -31,6 +33,7 @@
31
33
  "devDependencies": {
32
34
  "brittle": "^3.4.0",
33
35
  "cmake-bare": "^1.1.2",
36
+ "cmake-harden": "^1.0.2",
34
37
  "cmake-ports": "^1.5.0",
35
38
  "prettier": "^3.3.3",
36
39
  "prettier-config-standard": "^7.0.0"