bare-ffmpeg 1.0.0-0 → 1.0.0-1

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
@@ -1,14 +1,39 @@
1
- exports.Codec = require('./lib/codec')
2
- exports.CodecContext = require('./lib/codec-context')
3
- exports.CodecParameters = require('./lib/codec-parameters')
4
- exports.Decoder = require('./lib/decoder')
5
- exports.Encoder = require('./lib/encoder')
6
- exports.FormatContext = require('./lib/format-context')
7
- exports.Frame = require('./lib/frame')
8
- exports.Image = require('./lib/image')
9
- exports.IOContext = require('./lib/io-context')
10
- exports.Packet = require('./lib/packet')
11
- exports.Scaler = require('./lib/scaler')
12
- exports.Stream = require('./lib/stream')
1
+ const Codec = require('./lib/codec')
2
+ const CodecContext = require('./lib/codec-context')
3
+ const CodecParameters = require('./lib/codec-parameters')
4
+ const Decoder = require('./lib/decoder')
5
+ const Encoder = require('./lib/encoder')
6
+ const {
7
+ InputFormatContext,
8
+ OutputFormatContext
9
+ } = require('./lib/format-context')
10
+ const Frame = require('./lib/frame')
11
+ const Image = require('./lib/image')
12
+ const IOContext = require('./lib/io-context')
13
+ const InputFormat = require('./lib/input-format')
14
+ const OutputFormat = require('./lib/output-format')
15
+ const Packet = require('./lib/packet')
16
+ const Scaler = require('./lib/scaler')
17
+ const Stream = require('./lib/stream')
18
+ const Rational = require('./lib/rational')
19
+ const Dictionary = require('./lib/dictionary')
20
+
21
+ exports.Codec = Codec
22
+ exports.CodecContext = CodecContext
23
+ exports.CodecParameters = CodecParameters
24
+ exports.Decoder = Decoder
25
+ exports.Encoder = Encoder
26
+ exports.Frame = Frame
27
+ exports.IOContext = IOContext
28
+ exports.Image = Image
29
+ exports.InputFormat = InputFormat
30
+ exports.InputFormatContext = InputFormatContext
31
+ exports.OutputFormat = OutputFormat
32
+ exports.OutputFormatContext = OutputFormatContext
33
+ exports.Packet = Packet
34
+ exports.Scaler = Scaler
35
+ exports.Stream = Stream
36
+ exports.Rational = Rational
37
+ exports.Dictionary = Dictionary
13
38
 
14
39
  exports.constants = require('./lib/constants')
@@ -1,38 +1,70 @@
1
1
  const binding = require('../binding')
2
+ const ReferenceCounted = require('./reference-counted')
3
+ const Rational = require('./rational')
4
+
5
+ module.exports = class FFmpegCodecContext extends ReferenceCounted {
6
+ constructor(codec) {
7
+ super()
2
8
 
3
- module.exports = class FFmpegCodecContext {
4
- constructor(codec, parameters) {
5
9
  this._codec = codec
6
- this._handle = binding.initCodecContext(codec._handle, parameters._handle)
10
+ this._opened = false
11
+ this._handle = binding.initCodecContext(codec._handle)
12
+ }
13
+
14
+ _destroy() {
15
+ binding.destroyCodecContext(this._handle)
16
+ this._handle = null
7
17
  }
8
18
 
9
19
  get pixelFormat() {
10
20
  return binding.getCodecContextPixelFormat(this._handle)
11
21
  }
12
22
 
23
+ set pixelFormat(value) {
24
+ binding.setCodecContextPixelFormat(this._handle, value)
25
+ }
26
+
13
27
  get width() {
14
28
  return binding.getCodecContextWidth(this._handle)
15
29
  }
16
30
 
31
+ set width(value) {
32
+ binding.setCodecContextWidth(this._handle, value)
33
+ }
34
+
17
35
  get height() {
18
36
  return binding.getCodecContextHeight(this._handle)
19
37
  }
20
38
 
21
- destroy() {
22
- if (this._handle === null) return
23
- binding.destroyCodecContext(this._handle)
24
- this._handle = null
39
+ set height(value) {
40
+ binding.setCodecContextHeight(this._handle, value)
41
+ }
42
+
43
+ get timeBase() {
44
+ const view = new Int32Array(binding.getCodecContextTimeBase(this._handle))
45
+ return new Rational(view[0], view[1])
46
+ }
47
+
48
+ 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)
25
53
  }
26
54
 
27
- [Symbol.dispose]() {
28
- this.destroy()
55
+ open() {
56
+ if (this._opened) return
57
+ this._opened = true
58
+ binding.openCodecContext(this._handle)
59
+ return this
29
60
  }
30
61
 
31
62
  sendPacket(packet) {
32
63
  binding.sendCodecContextPacket(this._handle, packet._handle)
64
+ return this
33
65
  }
34
66
 
35
67
  receiveFrame(frame) {
36
- binding.receiveCodecContextFrame(this._handle, frame._handle)
68
+ return binding.receiveCodecContextFrame(this._handle, frame._handle)
37
69
  }
38
70
  }
@@ -1,5 +1,38 @@
1
- module.exports = class FFmpegCodecParameters {
1
+ const binding = require('../binding')
2
+ const ReferenceCounted = require('./reference-counted')
3
+
4
+ module.exports = class FFmpegCodecParameters extends ReferenceCounted {
2
5
  constructor(handle) {
6
+ super()
7
+
3
8
  this._handle = handle
4
9
  }
10
+
11
+ _destroy() {
12
+ this._handle = null
13
+ }
14
+
15
+ get bitRate() {
16
+ return binding.getCodecParametersBitRate(this._handle)
17
+ }
18
+
19
+ get bitsPerCodedSample() {
20
+ return binding.getCodecParametersBitsPerCodedSample(this._handle)
21
+ }
22
+
23
+ get bitsPerRawSample() {
24
+ return binding.getCodecParametersBitsPerRawSample(this._handle)
25
+ }
26
+
27
+ get sampleRate() {
28
+ return binding.getCodecParametersSampleRate(this._handle)
29
+ }
30
+
31
+ fromContext(context) {
32
+ binding.codecParametersFromContext(this._handle, context._handle)
33
+ }
34
+
35
+ toContext(context) {
36
+ binding.codecParametersToContext(context._handle, this._handle)
37
+ }
5
38
  }
package/lib/codec.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const Decoder = require('./decoder')
2
2
  const Encoder = require('./encoder')
3
+ const constants = require('./constants')
3
4
 
4
5
  const codecs = new Map()
5
6
 
@@ -32,4 +33,6 @@ module.exports = class FFmpegCodec {
32
33
  }
33
34
  return codec
34
35
  }
36
+
37
+ static MJPEG = this.for(constants.codecs.MJPEG)
35
38
  }
package/lib/constants.js CHANGED
@@ -1,8 +1,13 @@
1
1
  const binding = require('../binding')
2
2
 
3
3
  module.exports = exports = {
4
+ codecs: {
5
+ MJPEG: binding.AV_CODEC_ID_MJPEG
6
+ },
4
7
  pixelFormats: {
5
- RGBA: binding.AV_PIX_FMT_RGBA
8
+ RGBA: binding.AV_PIX_FMT_RGBA,
9
+ YUVJ420P: binding.AV_PIX_FMT_YUVJ420P,
10
+ YUV420P: binding.AV_PIX_FMT_YUV420P
6
11
  }
7
12
  }
8
13
 
@@ -0,0 +1,33 @@
1
+ const binding = require('../binding')
2
+ const ReferenceCounted = require('./reference-counted')
3
+
4
+ module.exports = class FFmpegDictionary extends ReferenceCounted {
5
+ constructor() {
6
+ super()
7
+
8
+ this._handle = binding.initDictionary()
9
+ }
10
+
11
+ _destroy() {
12
+ binding.destroyDictionary(this._handle)
13
+ this._handle = null
14
+ }
15
+
16
+ get(key) {
17
+ if (typeof key !== 'string' || key.length < 1) {
18
+ throw new TypeError(`Key should be a non empty string`)
19
+ }
20
+ return binding.getDictionaryEntry(this._handle, key)
21
+ }
22
+
23
+ set(key, value) {
24
+ if (typeof key !== 'string' || key.length < 1) {
25
+ throw new TypeError(`Key should be a non empty string`)
26
+ }
27
+
28
+ if (typeof value !== 'string' || value.length < 1) {
29
+ throw new TypeError(`Value should be a non empty string`)
30
+ }
31
+ binding.setDictionaryEntry(this._handle, key, value)
32
+ }
33
+ }
@@ -1,15 +1,22 @@
1
1
  const binding = require('../binding')
2
2
  const Stream = require('./stream.js')
3
+ const ReferenceCounted = require('./reference-counted')
4
+ const OutputFormat = require('./output-format')
3
5
 
4
- module.exports = class FFmpegFormatContext {
6
+ class FFmpegFormatContext extends ReferenceCounted {
5
7
  constructor(io) {
6
- this._io = io
8
+ super()
9
+
10
+ this._io = io._ref()
7
11
  this._streams = []
8
- this._handle = binding.initFormatContext(io._handle)
12
+ }
9
13
 
10
- for (const handle of binding.getFormatContextStreams(this._handle)) {
11
- this._streams.push(new Stream(handle))
12
- }
14
+ _destroy() {
15
+ this._io._unref()
16
+ this._io = null
17
+
18
+ for (const stream of this._streams) stream.destroy()
19
+ this._streams = []
13
20
  }
14
21
 
15
22
  get io() {
@@ -20,18 +27,63 @@ module.exports = class FFmpegFormatContext {
20
27
  return this._streams
21
28
  }
22
29
 
23
- destroy() {
24
- if (this._handle === null) return
25
- binding.destroyFormatContext(this._handle)
26
- this._io = null
30
+ readFrame(packet) {
31
+ if (packet._refs !== 0) {
32
+ throw new Error('Cannot read into packet with active references')
33
+ }
34
+
35
+ const result = binding.readFormatContextFrame(this._handle, packet._handle)
36
+ if (result) packet._ref()
37
+ return result
38
+ }
39
+ }
40
+
41
+ exports.InputFormatContext = class FFmpegInputFormatContext extends (
42
+ FFmpegFormatContext
43
+ ) {
44
+ constructor(io) {
45
+ super(io)
46
+
47
+ this._handle = binding.openInputFormatContext(io._handle)
48
+
49
+ for (const handle of binding.getFormatContextStreams(this._handle)) {
50
+ this._streams.push(new Stream(handle))
51
+ }
52
+ }
53
+
54
+ _destroy() {
55
+ super._destroy()
56
+
57
+ binding.closeInputFormatContext(this._handle)
27
58
  this._handle = null
28
59
  }
60
+ }
61
+
62
+ exports.OutputFormatContext = class FFmpegOutputFormatContext extends (
63
+ FFmpegFormatContext
64
+ ) {
65
+ constructor(format, io) {
66
+ super(io)
29
67
 
30
- [Symbol.dispose]() {
31
- this.destroy()
68
+ if (typeof format === 'string') format = new OutputFormat(format)
69
+
70
+ this._handle = binding.openOutputFormatContext(format._handle, io._handle)
32
71
  }
33
72
 
34
- readFrame(packet) {
35
- binding.readFormatContextFrame(this._handle, packet._handle)
73
+ _destroy() {
74
+ super._destroy()
75
+
76
+ binding.closeOutputFormatContext(this._handle)
77
+ this._handle = null
78
+ }
79
+
80
+ createStream(codec) {
81
+ const stream = new Stream(
82
+ binding.createFormatContextStream(this._handle, codec._handle)
83
+ )
84
+
85
+ this._streams.push(stream)
86
+
87
+ return stream
36
88
  }
37
89
  }
package/lib/frame.js CHANGED
@@ -1,17 +1,51 @@
1
1
  const binding = require('../binding')
2
+ const ReferenceCounted = require('./reference-counted')
2
3
 
3
- module.exports = class FFmpegFrame {
4
+ module.exports = class FFmpegFrame extends ReferenceCounted {
4
5
  constructor() {
6
+ super()
7
+
5
8
  this._handle = binding.initFrame()
6
9
  }
7
10
 
8
- destroy() {
9
- if (this._handle === null) return
11
+ _destroy() {
10
12
  binding.destroyFrame(this._handle)
11
13
  this._handle = null
12
14
  }
13
15
 
14
- [Symbol.dispose]() {
15
- this.destroy()
16
+ channel(i) {
17
+ if (i < 0 || i > 7) {
18
+ throw new RangeError(`Channel index must be between 0 and 7`)
19
+ }
20
+
21
+ return Buffer.from(binding.getFrameChannel(this._handle, i))
22
+ }
23
+
24
+ set width(value) {
25
+ binding.setFrameWidth(this._handle, value)
26
+ }
27
+
28
+ get width() {
29
+ return binding.getFrameWidth(this._handle)
30
+ }
31
+
32
+ set height(value) {
33
+ binding.setFrameHeight(this._handle, value)
34
+ }
35
+
36
+ get height() {
37
+ return binding.getFrameHeight(this._handle)
38
+ }
39
+
40
+ set pixelFormat(value) {
41
+ binding.setFramePixelFormat(this._handle, value)
42
+ }
43
+
44
+ get pixelFormat() {
45
+ return binding.getFramePixelFormat(this._handle)
46
+ }
47
+
48
+ alloc() {
49
+ binding.allocFrame(this._handle, 32)
16
50
  }
17
51
  }
@@ -0,0 +1,24 @@
1
+ const binding = require('../binding')
2
+
3
+ let defaultName = null
4
+
5
+ switch (Bare.platform) {
6
+ case 'darwin':
7
+ defaultName = 'avfoundation'
8
+ break
9
+ case 'linux':
10
+ defaultName = 'v4l2'
11
+ break
12
+ case 'win32':
13
+ defaultName = 'dshow'
14
+ break
15
+ }
16
+
17
+ module.exports = class FFmpegInputFormat {
18
+ constructor(name = defaultName) {
19
+ if (typeof name !== 'string' || name.length < 1) {
20
+ throw new TypeError('Input format name should be a non empty string')
21
+ }
22
+ this._handle = binding.initInputFormat(name)
23
+ }
24
+ }
package/lib/io-context.js CHANGED
@@ -1,17 +1,15 @@
1
1
  const binding = require('../binding')
2
+ const ReferenceCounted = require('./reference-counted')
3
+
4
+ module.exports = class FFmpegIOContext extends ReferenceCounted {
5
+ constructor(buffer = Buffer.alloc(0)) {
6
+ super()
2
7
 
3
- module.exports = class FFmpegIOContext {
4
- constructor(buffer) {
5
8
  this._handle = binding.initIOContext(buffer)
6
9
  }
7
10
 
8
- destroy() {
9
- if (this._handle === null) return
11
+ _destroy() {
10
12
  binding.destroyIOContext(this._handle)
11
13
  this._handle = null
12
14
  }
13
-
14
- [Symbol.dispose]() {
15
- this.destroy()
16
- }
17
15
  }
@@ -0,0 +1,7 @@
1
+ const binding = require('../binding')
2
+
3
+ module.exports = class FFmpegOutputFormat {
4
+ constructor(name) {
5
+ this._handle = binding.initOutputFormat(name)
6
+ }
7
+ }
package/lib/packet.js CHANGED
@@ -1,21 +1,20 @@
1
1
  const binding = require('../binding')
2
+ const ReferenceCounted = require('./reference-counted')
2
3
 
3
- module.exports = class FFmpegPacket {
4
+ module.exports = class FFmpegPacket extends ReferenceCounted {
4
5
  constructor() {
5
- this._handle = binding.initPacket()
6
- }
6
+ super()
7
7
 
8
- unref() {
9
- binding.unrefPacket(this._handle)
8
+ this._handle = binding.initPacket()
10
9
  }
11
10
 
12
- destroy() {
13
- if (this._handle === null) return
11
+ _destroy() {
14
12
  binding.destroyPacket(this._handle)
15
13
  this._handle = null
16
14
  }
17
15
 
18
- [Symbol.dispose]() {
19
- this.destroy()
16
+ unref() {
17
+ this._unref()
18
+ binding.unrefPacket(this._handle)
20
19
  }
21
20
  }
@@ -0,0 +1,6 @@
1
+ module.exports = class FFmpegRational {
2
+ constructor(numerator, denominator) {
3
+ this.numerator = numerator
4
+ this.denominator = denominator
5
+ }
6
+ }
@@ -0,0 +1,39 @@
1
+ module.exports = class FFmpegReferenceCounted {
2
+ constructor() {
3
+ this._refs = 0
4
+ this._destroyed = false
5
+ }
6
+
7
+ _ref() {
8
+ if (this._destroyed === false) this._refs++
9
+ return this
10
+ }
11
+
12
+ _unref() {
13
+ if (this._refs === 0) {
14
+ throw new Error('Cannot unreference object with no active references')
15
+ }
16
+
17
+ if (--this._refs === 0 && this._destroyed === true) this._destroy()
18
+ return this
19
+ }
20
+
21
+ _destroy() {}
22
+
23
+ destroy() {
24
+ if (this._refs !== 0) {
25
+ throw new Error('Cannot destroy object with active references')
26
+ }
27
+
28
+ if (this._destroyed === true) {
29
+ throw new Error('Object has already been destroyed')
30
+ }
31
+
32
+ this._destroyed = true
33
+ this._destroy()
34
+ }
35
+
36
+ [Symbol.dispose]() {
37
+ this.destroy()
38
+ }
39
+ }
package/lib/scaler.js CHANGED
@@ -1,7 +1,8 @@
1
1
  const binding = require('../binding')
2
2
  const constants = require('./constants')
3
+ const ReferenceCounted = require('./reference-counted')
3
4
 
4
- module.exports = class FFmpegScaler {
5
+ module.exports = class FFmpegScaler extends ReferenceCounted {
5
6
  constructor(
6
7
  sourcePixelFormat,
7
8
  sourceWidth,
@@ -10,6 +11,8 @@ module.exports = class FFmpegScaler {
10
11
  targetWidth,
11
12
  targetHeight
12
13
  ) {
14
+ super()
15
+
13
16
  sourcePixelFormat = constants.toPixelFormat(sourcePixelFormat)
14
17
  targetPixelFormat = constants.toPixelFormat(targetPixelFormat)
15
18
 
@@ -30,16 +33,11 @@ module.exports = class FFmpegScaler {
30
33
  )
31
34
  }
32
35
 
33
- destroy() {
34
- if (this._handle === null) return
36
+ _destroy() {
35
37
  binding.destroyScaler(this._handle)
36
38
  this._handle = null
37
39
  }
38
40
 
39
- [Symbol.dispose]() {
40
- this.destroy()
41
- }
42
-
43
41
  scale(source, y, height, target) {
44
42
  if (typeof y !== 'number') {
45
43
  target = y
package/lib/stream.js CHANGED
@@ -2,9 +2,12 @@ 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
6
 
6
- module.exports = class FFmpegStream {
7
+ module.exports = class FFmpegStream extends ReferenceCounted {
7
8
  constructor(handle) {
9
+ super()
10
+
8
11
  this._handle = handle
9
12
 
10
13
  this._codec = Codec.for(binding.getStreamCodec(this._handle))
@@ -14,6 +17,11 @@ module.exports = class FFmpegStream {
14
17
  )
15
18
  }
16
19
 
20
+ _destroy() {
21
+ this._codecParameters.destroy()
22
+ this._codecParameters = null
23
+ }
24
+
17
25
  get codec() {
18
26
  return this._codec
19
27
  }
@@ -23,10 +31,14 @@ module.exports = class FFmpegStream {
23
31
  }
24
32
 
25
33
  decoder() {
26
- return new CodecContext(this._codec.decoder, this._codecParameters)
34
+ const context = new CodecContext(this._codec.decoder)
35
+ this._codecParameters.toContext(context)
36
+ return context.open()
27
37
  }
28
38
 
29
39
  encoder() {
30
- return new CodecContext(this._codec.encoder, this._codecParameters)
40
+ const context = new CodecContext(this._codec.encoder)
41
+ this._codecParameters.toContext(context)
42
+ return context.open()
31
43
  }
32
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-ffmpeg",
3
- "version": "1.0.0-0",
3
+ "version": "1.0.0-1",
4
4
  "description": "Low-level FFmpeg bindings for Bare",
5
5
  "exports": {
6
6
  ".": "./index.js",