bare-ffmpeg 1.0.0-26 → 1.0.0-28

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.
package/index.js CHANGED
@@ -10,6 +10,10 @@ const {
10
10
  InputFormatContext,
11
11
  OutputFormatContext
12
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')
13
17
  const Frame = require('./lib/frame')
14
18
  const IOContext = require('./lib/io-context')
15
19
  const Image = require('./lib/image')
@@ -31,6 +35,10 @@ exports.CodecParameters = CodecParameters
31
35
  exports.Decoder = Decoder
32
36
  exports.Dictionary = Dictionary
33
37
  exports.Encoder = Encoder
38
+ exports.Filter = Filter
39
+ exports.FilterContext = FilterContext
40
+ exports.FilterGraph = FilterGraph
41
+ exports.FilterInOut = FilterInOut
34
42
  exports.Frame = Frame
35
43
  exports.IOContext = IOContext
36
44
  exports.Image = Image
@@ -1,6 +1,7 @@
1
1
  const binding = require('../binding')
2
2
  const Rational = require('./rational')
3
3
  const ChannelLayout = require('./channel-layout')
4
+ const { codecConfig } = require('./constants')
4
5
 
5
6
  module.exports = class FFmpegCodecContext {
6
7
  constructor(codec) {
@@ -120,6 +121,14 @@ module.exports = class FFmpegCodecContext {
120
121
  )
121
122
  }
122
123
 
124
+ get frameSize() {
125
+ return binding.getCodecContextFrameSize(this._handle)
126
+ }
127
+
128
+ get frameNum() {
129
+ return binding.getCodecContextFrameNum(this._handle)
130
+ }
131
+
123
132
  open(options) {
124
133
  if (this._opened) return
125
134
  this._opened = true
@@ -151,6 +160,45 @@ module.exports = class FFmpegCodecContext {
151
160
  return binding.receiveCodecContextFrame(this._handle, frame._handle)
152
161
  }
153
162
 
163
+ getSupportedConfig(config) {
164
+ if (config === codecConfig.FRAME_RATE) {
165
+ const data = binding.getSupportedFrameRates(
166
+ this._handle,
167
+ this._codec._handle
168
+ )
169
+ if (!data || data.length === 0) return null
170
+
171
+ const view = new Int32Array(data)
172
+ const rates = []
173
+ for (let i = 0; i < view.length; i += 2) {
174
+ rates.push(new Rational(view[i], view[i + 1]))
175
+ }
176
+ return rates
177
+ }
178
+
179
+ if (config === codecConfig.CHANNEL_LAYOUT) {
180
+ const handles = binding.getSupportedChannelLayouts(
181
+ this._handle,
182
+ this._codec._handle
183
+ )
184
+ if (!handles || handles.length === 0) return null
185
+
186
+ return handles.map((handle) => new ChannelLayout(handle))
187
+ }
188
+
189
+ const data = binding.getSupportedConfig(
190
+ this._handle,
191
+ this._codec._handle,
192
+ config
193
+ )
194
+
195
+ if (config === codecConfig.SAMPLE_RATE && !data) {
196
+ return null
197
+ }
198
+
199
+ return new Int32Array(data)
200
+ }
201
+
154
202
  [Symbol.dispose]() {
155
203
  this.destroy()
156
204
  }
@@ -243,22 +243,26 @@ module.exports = class FFmpegCodecParameters {
243
243
  type: this.type,
244
244
  id: this.id,
245
245
  format: this.format,
246
+ tag: this.tag,
247
+ frameRate: this.frameRate,
248
+ videoDelay: this.videoDelay,
246
249
  profile: this.profile,
247
250
  level: this.level,
248
251
  width: this.width,
249
252
  height: this.height,
253
+ sampleAsectRatio: this.sampleAspectRatio,
250
254
  bitRate: this.bitRate,
251
255
  bitsPerCodedSample: this.bitsPerCodedSample,
252
256
  bitsPerRawSample: this.bitsPerRawSample,
253
257
  sampleRate: this.sampleRate,
254
258
  nbChannels: this.nbChannels,
255
259
  channelLayout: this.channelLayout,
256
- frameRate: this.frameRate,
257
260
  extraData: this.extraData,
258
261
  blockAlign: this.blockAlign,
259
262
  initialPadding: this.initialPadding,
260
263
  trailingPadding: this.trailingPadding,
261
- seekPreroll: this.seekPreroll
264
+ seekPreroll: this.seekPreroll,
265
+ frameSize: this.frameSize
262
266
  }
263
267
  }
264
268
 
package/lib/constants.js CHANGED
@@ -184,6 +184,15 @@ module.exports = exports = {
184
184
  '3D_REFERENCE_DISPLAYS': binding.AV_PKT_DATA_3D_REFERENCE_DISPLAYS,
185
185
  RTCP_SR: binding.AV_PKT_DATA_RTCP_SR,
186
186
  NB: binding.AV_PKT_DATA_NB
187
+ },
188
+ codecConfig: {
189
+ PIX_FORMAT: binding.AV_CODEC_CONFIG_PIX_FORMAT,
190
+ FRAME_RATE: binding.AV_CODEC_CONFIG_FRAME_RATE,
191
+ SAMPLE_RATE: binding.AV_CODEC_CONFIG_SAMPLE_RATE,
192
+ SAMPLE_FORMAT: binding.AV_CODEC_CONFIG_SAMPLE_FORMAT,
193
+ CHANNEL_LAYOUT: binding.AV_CODEC_CONFIG_CHANNEL_LAYOUT,
194
+ COLOR_RANGE: binding.AV_CODEC_CONFIG_COLOR_RANGE,
195
+ COLOR_SPACE: binding.AV_CODEC_CONFIG_COLOR_SPACE
187
196
  }
188
197
  }
189
198
 
@@ -0,0 +1,7 @@
1
+ const binding = require('../binding')
2
+
3
+ module.exports = class FilterContext {
4
+ constructor() {
5
+ this._handle = binding.initFilterContext()
6
+ }
7
+ }
@@ -0,0 +1,54 @@
1
+ const binding = require('../binding')
2
+
3
+ module.exports = class FilterGraph {
4
+ constructor() {
5
+ this._handle = binding.initFilterGraph()
6
+ }
7
+
8
+ destroy() {
9
+ binding.destroyFilterGraph(this._handle)
10
+ this._handle = null
11
+ }
12
+
13
+ createFilter(context, filter, name, args) {
14
+ const argumentsString =
15
+ args &&
16
+ `video_size=${args.width}x${args.height}` +
17
+ `:pix_fmt=${args.pixelFormat}` +
18
+ `:time_base=${args.timeBase.numerator}/${args.timeBase.denominator}` +
19
+ `:pixel_aspect=${args.aspectRatio.numerator}/${args.aspectRatio.denominator}`
20
+
21
+ return binding.createFilterGraphFilter(
22
+ this._handle,
23
+ context._handle,
24
+ filter._handle,
25
+ name,
26
+ argumentsString
27
+ )
28
+ }
29
+
30
+ parse(filterDescription, inputs, outputs) {
31
+ binding.parseFilterGraph(
32
+ this._handle,
33
+ inputs._handle,
34
+ outputs._handle,
35
+ filterDescription
36
+ )
37
+ }
38
+
39
+ configure() {
40
+ binding.configureFilterGraph(this._handle)
41
+ }
42
+
43
+ pushFrame(ctx, frame) {
44
+ return binding.pushFilterGraphFrame(ctx._handle, frame._handle)
45
+ }
46
+
47
+ pullFrame(ctx, frame) {
48
+ return binding.pullFilterGraphFrame(ctx._handle, frame._handle)
49
+ }
50
+
51
+ [Symbol.dispose]() {
52
+ this.destroy()
53
+ }
54
+ }
@@ -0,0 +1,55 @@
1
+ const binding = require('../binding')
2
+
3
+ module.exports = class FilterInOut {
4
+ constructor(handle = binding.initFilterInout()) {
5
+ this._handle = handle
6
+ this._next = null
7
+ this._filterContext = null
8
+ }
9
+
10
+ destroy() {
11
+ binding.destroyFilterInOut(this._handle)
12
+ this._handle = null
13
+ }
14
+
15
+ get name() {
16
+ return binding.getFilterInOutName(this._handle)
17
+ }
18
+
19
+ set name(value) {
20
+ return binding.setFilterInOutName(this._handle, value)
21
+ }
22
+
23
+ get filterContext() {
24
+ return this._filterContext
25
+ }
26
+
27
+ set filterContext(value) {
28
+ this._filterContext = value
29
+ return binding.setFilterInOutFilterContext(
30
+ this._handle,
31
+ this._filterContext._handle
32
+ )
33
+ }
34
+
35
+ get padIdx() {
36
+ return binding.getFilterInOutPadIdx(this._handle)
37
+ }
38
+
39
+ set padIdx(value) {
40
+ return binding.setFilterInOutPadIdx(this._handle, value)
41
+ }
42
+
43
+ get next() {
44
+ return this._next
45
+ }
46
+
47
+ set next(value) {
48
+ this._next = value
49
+ return binding.setFilterInOutNext(this._handle, this._next._handle)
50
+ }
51
+
52
+ [Symbol.dispose]() {
53
+ this.destroy()
54
+ }
55
+ }
package/lib/filter.js ADDED
@@ -0,0 +1,7 @@
1
+ const binding = require('../binding')
2
+
3
+ module.exports = class Filter {
4
+ constructor(name) {
5
+ this._handle = binding.getFilterByName(name)
6
+ }
7
+ }
package/lib/frame.js CHANGED
@@ -88,6 +88,10 @@ module.exports = class FFmpegFrame {
88
88
  binding.setFrameTimeBase(this._handle, value.numerator, value.denominator)
89
89
  }
90
90
 
91
+ copyProperties(source) {
92
+ binding.copyFrameProperties(this._handle, source._handle)
93
+ }
94
+
91
95
  alloc() {
92
96
  binding.allocFrame(this._handle, 32)
93
97
  }
@@ -26,4 +26,12 @@ module.exports = class FFmpegInputFormat {
26
26
  get flags() {
27
27
  return binding.getInputFormatFlags(this._handle)
28
28
  }
29
+
30
+ get extensions() {
31
+ return binding.getInputFormatExtensions(this._handle)
32
+ }
33
+
34
+ get mimeType() {
35
+ return binding.getInputFormatMimeType(this._handle)
36
+ }
29
37
  }
@@ -8,4 +8,12 @@ module.exports = class FFmpegOutputFormat {
8
8
  get flags() {
9
9
  return binding.getOutputFormatFlags(this._handle)
10
10
  }
11
+
12
+ get extensions() {
13
+ return binding.getOutputFormatExtensions(this._handle)
14
+ }
15
+
16
+ get mimeType() {
17
+ return binding.getOutputFormatMimeType(this._handle)
18
+ }
11
19
  }
package/lib/packet.js CHANGED
@@ -138,6 +138,10 @@ module.exports = class FFmpegPacket {
138
138
  )
139
139
  }
140
140
 
141
+ copyPropsFrom(sourcePacket) {
142
+ binding.copyPacketProps(this._handle, sourcePacket._handle)
143
+ }
144
+
141
145
  get duration() {
142
146
  return binding.getPacketDuration(this._handle)
143
147
  }
@@ -164,7 +168,8 @@ module.exports = class FFmpegPacket {
164
168
  dts: this.dts,
165
169
  pts: this.pts,
166
170
  duration: this.duration,
167
- data: this.data
171
+ data: this.data,
172
+ sideData: this.sideData
168
173
  }
169
174
  }
170
175
 
package/lib/rational.js CHANGED
@@ -26,15 +26,27 @@ module.exports = class FFmpegRational {
26
26
  return this.numerator / this.denominator
27
27
  }
28
28
 
29
+ equals(other) {
30
+ return (
31
+ this.numerator === other.numerator &&
32
+ this.denominator === other.denominator
33
+ )
34
+ }
35
+
29
36
  static from(num) {
30
37
  const view = new Int32Array(binding.rationalD2Q(num))
31
38
  return new FFmpegRational(view[0], view[1])
32
39
  }
33
40
 
34
41
  static rescaleQ(n, src, dst) {
35
- return (
36
- (n * (src.numerator / src.denominator)) /
37
- (dst.numerator / dst.denominator)
42
+ if (src.equals(dst)) return n
43
+
44
+ return binding.rationalRescaleQ(
45
+ n,
46
+ src.numerator,
47
+ src.denominator,
48
+ dst.numerator,
49
+ dst.denominator
38
50
  )
39
51
  }
40
52
  }
package/lib/samples.js CHANGED
@@ -1,49 +1,64 @@
1
1
  const binding = require('../binding')
2
- const constants = require('./constants.js')
3
2
 
4
3
  module.exports = class FFmpegSamples {
5
- constructor(sampleFormat, nbChannels, nbSamples, align = 0) {
6
- sampleFormat = constants.toSampleFormat(sampleFormat)
4
+ _data
5
+ _frame
7
6
 
8
- this._sampleFormat = sampleFormat
9
- this._nbChannels = nbChannels
10
- this._nbSamples = nbSamples
11
- this._align = align
7
+ constructor({ noAlignment = false } = {}) {
8
+ this._noAlignment = noAlignment
9
+ }
12
10
 
13
- this._data = Buffer.from(
14
- binding.initSamples(sampleFormat, nbChannels, nbSamples, align)
15
- )
11
+ get data() {
12
+ return this._data
16
13
  }
17
14
 
18
- get sampleFormat() {
19
- return this._sampleFormat
15
+ get format() {
16
+ return this._frame.format
20
17
  }
21
18
 
22
- get nbChannels() {
23
- return this._nbChannels
19
+ get channelLayout() {
20
+ return this._frame.channelLayout
24
21
  }
25
22
 
26
23
  get nbSamples() {
27
- return this._nbSamples
24
+ return this._frame.nbSamples
28
25
  }
29
26
 
30
- get align() {
31
- return this._align
27
+ get nbChannels() {
28
+ return this.channelLayout && this.channelLayout.nbChannels
32
29
  }
33
30
 
34
- get data() {
35
- return this._data
31
+ get pts() {
32
+ return this._frame.pts
36
33
  }
37
34
 
38
35
  fill(frame) {
39
- binding.fillSamples(
40
- this._sampleFormat,
41
- this._nbChannels,
42
- this._nbSamples,
43
- this._align,
36
+ const { format, channelLayout, nbSamples } = frame
37
+
38
+ const len = FFmpegSamples.bufferSize(
39
+ format,
40
+ channelLayout.nbChannels,
41
+ nbSamples,
42
+ this._noAlignment
43
+ )
44
+
45
+ if (!this._data || len !== this._data.length) {
46
+ this._data = Buffer.allocUnsafe(len)
47
+ }
48
+
49
+ const res = binding.fillSamples(
50
+ frame._handle,
44
51
  this._data.buffer,
45
52
  this._data.byteOffset,
46
- frame._handle
53
+ this._noAlignment
47
54
  )
55
+
56
+ this._frame = frame
57
+
58
+ return res
59
+ }
60
+
61
+ static bufferSize(format, nbChannels, nbSamples, noAlignment = false) {
62
+ return binding.samplesBufferSize(format, nbChannels, nbSamples, noAlignment)
48
63
  }
49
64
  }
package/lib/stream.js CHANGED
@@ -66,4 +66,15 @@ module.exports = class FFmpegStream {
66
66
  this._codecParameters.toContext(context)
67
67
  return context.open()
68
68
  }
69
+
70
+ [Symbol.for('bare.inspect')]() {
71
+ return {
72
+ __proto__: { constructor: FFmpegStream },
73
+ id: this.id,
74
+ index: this.index,
75
+ timeBase: this.timeBase,
76
+ avgFramerate: this.avgFramerate,
77
+ codecParameters: this.codecParameters
78
+ }
79
+ }
69
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-ffmpeg",
3
- "version": "1.0.0-26",
3
+ "version": "1.0.0-28",
4
4
  "description": "Low-level FFmpeg bindings for Bare",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -18,7 +18,8 @@
18
18
  "addon": true,
19
19
  "scripts": {
20
20
  "test": "prettier . --check && bare test.js",
21
- "format": "prettier . --write && clang-format -i binding.cc"
21
+ "format": "prettier . --write && clang-format -i binding.cc",
22
+ "example": "bare ./examples/index.js"
22
23
  },
23
24
  "repository": {
24
25
  "type": "git",
@@ -31,6 +32,7 @@
31
32
  },
32
33
  "homepage": "https://github.com/holepunchto/bare-ffmpeg#readme",
33
34
  "devDependencies": {
35
+ "bare-assert": "^1.1.0",
34
36
  "brittle": "^3.4.0",
35
37
  "cmake-bare": "^1.1.2",
36
38
  "cmake-harden": "^1.0.2",