bare-ffmpeg 1.0.0-0 → 1.0.0-10
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/CMakeLists.txt +11 -3
- package/README.md +809 -0
- package/index.js +43 -12
- package/lib/channel-layout.js +33 -0
- package/lib/codec-context.js +63 -10
- package/lib/codec-parameters.js +53 -0
- package/lib/codec.js +7 -0
- package/lib/constants.js +96 -7
- package/lib/dictionary.js +26 -0
- package/lib/errors.js +38 -0
- package/lib/format-context.js +124 -11
- package/lib/frame.js +55 -1
- package/lib/image.js +10 -0
- package/lib/input-format.js +22 -0
- package/lib/io-context.js +6 -3
- package/lib/output-format.js +7 -0
- package/lib/packet.js +21 -6
- package/lib/rational.js +6 -0
- package/lib/resampler.js +63 -0
- package/lib/samples.js +49 -0
- package/lib/scaler.js +4 -5
- package/lib/stream.js +15 -2
- package/package.json +3 -2
- package/prebuilds/android-arm/bare-ffmpeg.bare +0 -0
- package/prebuilds/android-arm64/bare-ffmpeg.bare +0 -0
- package/prebuilds/android-ia32/bare-ffmpeg.bare +0 -0
- package/prebuilds/android-x64/bare-ffmpeg.bare +0 -0
- package/prebuilds/darwin-arm64/bare-ffmpeg.bare +0 -0
- package/prebuilds/darwin-x64/bare-ffmpeg.bare +0 -0
- package/prebuilds/ios-arm64/bare-ffmpeg.bare +0 -0
- package/prebuilds/ios-arm64-simulator/bare-ffmpeg.bare +0 -0
- package/prebuilds/ios-x64-simulator/bare-ffmpeg.bare +0 -0
- package/prebuilds/linux-arm64/bare-ffmpeg.bare +0 -0
- package/prebuilds/linux-x64/bare-ffmpeg.bare +0 -0
- package/prebuilds/win32-arm64/bare-ffmpeg.bare +0 -0
- package/prebuilds/win32-x64/bare-ffmpeg.bare +0 -0
- package/binding.c +0 -962
package/index.js
CHANGED
|
@@ -1,14 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
const ChannelLayout = require('./lib/channel-layout')
|
|
2
|
+
const Codec = require('./lib/codec')
|
|
3
|
+
const CodecContext = require('./lib/codec-context')
|
|
4
|
+
const CodecParameters = require('./lib/codec-parameters')
|
|
5
|
+
const Decoder = require('./lib/decoder')
|
|
6
|
+
const Dictionary = require('./lib/dictionary')
|
|
7
|
+
const Encoder = require('./lib/encoder')
|
|
8
|
+
const {
|
|
9
|
+
InputFormatContext,
|
|
10
|
+
OutputFormatContext
|
|
11
|
+
} = require('./lib/format-context')
|
|
12
|
+
const Frame = require('./lib/frame')
|
|
13
|
+
const Image = require('./lib/image')
|
|
14
|
+
const IOContext = require('./lib/io-context')
|
|
15
|
+
const InputFormat = require('./lib/input-format')
|
|
16
|
+
const OutputFormat = require('./lib/output-format')
|
|
17
|
+
const Packet = require('./lib/packet')
|
|
18
|
+
const Samples = require('./lib/samples')
|
|
19
|
+
const Scaler = require('./lib/scaler')
|
|
20
|
+
const Stream = require('./lib/stream')
|
|
21
|
+
const Rational = require('./lib/rational')
|
|
22
|
+
const Resampler = require('./lib/resampler')
|
|
23
|
+
|
|
24
|
+
exports.ChannelLayout = ChannelLayout
|
|
25
|
+
exports.Codec = Codec
|
|
26
|
+
exports.CodecContext = CodecContext
|
|
27
|
+
exports.CodecParameters = CodecParameters
|
|
28
|
+
exports.Decoder = Decoder
|
|
29
|
+
exports.Dictionary = Dictionary
|
|
30
|
+
exports.Encoder = Encoder
|
|
31
|
+
exports.Frame = Frame
|
|
32
|
+
exports.IOContext = IOContext
|
|
33
|
+
exports.Image = Image
|
|
34
|
+
exports.InputFormat = InputFormat
|
|
35
|
+
exports.InputFormatContext = InputFormatContext
|
|
36
|
+
exports.OutputFormat = OutputFormat
|
|
37
|
+
exports.OutputFormatContext = OutputFormatContext
|
|
38
|
+
exports.Packet = Packet
|
|
39
|
+
exports.Samples = Samples
|
|
40
|
+
exports.Scaler = Scaler
|
|
41
|
+
exports.Stream = Stream
|
|
42
|
+
exports.Rational = Rational
|
|
43
|
+
exports.Resampler = Resampler
|
|
13
44
|
|
|
14
45
|
exports.constants = require('./lib/constants')
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
destroy() {
|
|
14
|
+
binding.destroyChannelLayout(this._handle)
|
|
15
|
+
this._handle = null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
[Symbol.dispose]() {
|
|
19
|
+
this.destroy()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static from(value) {
|
|
23
|
+
if (typeof value === 'string') value = constants.toChannelLayout(value)
|
|
24
|
+
|
|
25
|
+
if (typeof value === 'number') {
|
|
26
|
+
value = binding.channelLayoutFromMask(value)
|
|
27
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
28
|
+
value = binding.copyChannelLayout(value._handle)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return new this(value)
|
|
32
|
+
}
|
|
33
|
+
}
|
package/lib/codec-context.js
CHANGED
|
@@ -1,38 +1,91 @@
|
|
|
1
1
|
const binding = require('../binding')
|
|
2
|
+
const Rational = require('./rational')
|
|
2
3
|
|
|
3
4
|
module.exports = class FFmpegCodecContext {
|
|
4
|
-
constructor(codec
|
|
5
|
+
constructor(codec) {
|
|
5
6
|
this._codec = codec
|
|
6
|
-
this.
|
|
7
|
+
this._opened = false
|
|
8
|
+
this._handle = binding.initCodecContext(codec._handle)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
destroy() {
|
|
12
|
+
binding.destroyCodecContext(this._handle)
|
|
13
|
+
this._handle = null
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
get pixelFormat() {
|
|
10
17
|
return binding.getCodecContextPixelFormat(this._handle)
|
|
11
18
|
}
|
|
12
19
|
|
|
20
|
+
set pixelFormat(value) {
|
|
21
|
+
binding.setCodecContextPixelFormat(this._handle, value)
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
get width() {
|
|
14
25
|
return binding.getCodecContextWidth(this._handle)
|
|
15
26
|
}
|
|
16
27
|
|
|
28
|
+
set width(value) {
|
|
29
|
+
binding.setCodecContextWidth(this._handle, value)
|
|
30
|
+
}
|
|
31
|
+
|
|
17
32
|
get height() {
|
|
18
33
|
return binding.getCodecContextHeight(this._handle)
|
|
19
34
|
}
|
|
20
35
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
binding.destroyCodecContext(this._handle)
|
|
24
|
-
this._handle = null
|
|
36
|
+
set height(value) {
|
|
37
|
+
binding.setCodecContextHeight(this._handle, value)
|
|
25
38
|
}
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
this.
|
|
40
|
+
get sampleFormat() {
|
|
41
|
+
return binding.getCodecContextSampleFormat(this._handle)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
set sampleFormat(value) {
|
|
45
|
+
return binding.setCodecContextSampleFormat(this._handle, value)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get timeBase() {
|
|
49
|
+
const view = new Int32Array(binding.getCodecContextTimeBase(this._handle))
|
|
50
|
+
return new Rational(view[0], view[1])
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
set timeBase(value) {
|
|
54
|
+
binding.setCodecContextTimeBase(
|
|
55
|
+
this._handle,
|
|
56
|
+
value.numerator,
|
|
57
|
+
value.denominator
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
open(options) {
|
|
62
|
+
if (this._opened) return
|
|
63
|
+
this._opened = true
|
|
64
|
+
if (options) {
|
|
65
|
+
binding.openCodecContextWithOptions(this._handle, options._handle)
|
|
66
|
+
} else {
|
|
67
|
+
binding.openCodecContext(this._handle)
|
|
68
|
+
}
|
|
69
|
+
return this
|
|
29
70
|
}
|
|
30
71
|
|
|
31
72
|
sendPacket(packet) {
|
|
32
|
-
binding.sendCodecContextPacket(this._handle, packet._handle)
|
|
73
|
+
return binding.sendCodecContextPacket(this._handle, packet._handle)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
receivePacket(packet) {
|
|
77
|
+
return binding.receiveCodecContextPacket(this._handle, packet._handle)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
sendFrame(frame) {
|
|
81
|
+
return binding.sendCodecContextFrame(this._handle, frame._handle)
|
|
33
82
|
}
|
|
34
83
|
|
|
35
84
|
receiveFrame(frame) {
|
|
36
|
-
binding.receiveCodecContextFrame(this._handle, frame._handle)
|
|
85
|
+
return binding.receiveCodecContextFrame(this._handle, frame._handle)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
[Symbol.dispose]() {
|
|
89
|
+
this.destroy()
|
|
37
90
|
}
|
|
38
91
|
}
|
package/lib/codec-parameters.js
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
|
+
const binding = require('../binding')
|
|
2
|
+
const ChannelLayout = require('./channel-layout')
|
|
3
|
+
|
|
1
4
|
module.exports = class FFmpegCodecParameters {
|
|
2
5
|
constructor(handle) {
|
|
3
6
|
this._handle = handle
|
|
4
7
|
}
|
|
8
|
+
|
|
9
|
+
destroy() {
|
|
10
|
+
this._handle = null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get bitRate() {
|
|
14
|
+
return binding.getCodecParametersBitRate(this._handle)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get bitsPerCodedSample() {
|
|
18
|
+
return binding.getCodecParametersBitsPerCodedSample(this._handle)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get bitsPerRawSample() {
|
|
22
|
+
return binding.getCodecParametersBitsPerRawSample(this._handle)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get format() {
|
|
26
|
+
return binding.getCodecParametersFormat(this._handle)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get sampleRate() {
|
|
30
|
+
return binding.getCodecParametersSampleRate(this._handle)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get nbChannels() {
|
|
34
|
+
return binding.getCodecParametersNbChannels(this._handle)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get codecType() {
|
|
38
|
+
return binding.getCodecParametersCodecType(this._handle)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get channelLayout() {
|
|
42
|
+
return new ChannelLayout(
|
|
43
|
+
binding.getCodecParametersChannelLayout(this._handle)
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fromContext(context) {
|
|
48
|
+
binding.codecParametersFromContext(this._handle, context._handle)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
toContext(context) {
|
|
52
|
+
binding.codecParametersToContext(context._handle, this._handle)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
[Symbol.dispose]() {
|
|
56
|
+
this.destroy()
|
|
57
|
+
}
|
|
5
58
|
}
|
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,10 @@ module.exports = class FFmpegCodec {
|
|
|
32
33
|
}
|
|
33
34
|
return codec
|
|
34
35
|
}
|
|
36
|
+
|
|
37
|
+
static MJPEG = this.for(constants.codecs.MJPEG)
|
|
38
|
+
static H264 = this.for(constants.codecs.H264)
|
|
39
|
+
static AAC = this.for(constants.codecs.AAC)
|
|
40
|
+
static OPUS = this.for(constants.codecs.OPUS)
|
|
41
|
+
static AV1 = this.for(constants.codecs.AV1)
|
|
35
42
|
}
|
package/lib/constants.js
CHANGED
|
@@ -1,19 +1,108 @@
|
|
|
1
1
|
const binding = require('../binding')
|
|
2
|
+
const errors = require('./errors')
|
|
3
|
+
const ChannelLayout = require('./channel-layout')
|
|
2
4
|
|
|
3
5
|
module.exports = exports = {
|
|
6
|
+
codecs: {
|
|
7
|
+
MJPEG: binding.AV_CODEC_ID_MJPEG,
|
|
8
|
+
H264: binding.AV_CODEC_ID_H264,
|
|
9
|
+
AAC: binding.AV_CODEC_ID_AAC,
|
|
10
|
+
OPUS: binding.AV_CODEC_ID_OPUS,
|
|
11
|
+
AV1: binding.AV_CODEC_ID_AV1
|
|
12
|
+
},
|
|
4
13
|
pixelFormats: {
|
|
5
|
-
RGBA: binding.AV_PIX_FMT_RGBA
|
|
14
|
+
RGBA: binding.AV_PIX_FMT_RGBA,
|
|
15
|
+
RGB24: binding.AV_PIX_FMT_RGB24,
|
|
16
|
+
YUVJ420P: binding.AV_PIX_FMT_YUVJ420P,
|
|
17
|
+
UYVY422: binding.AV_PIX_FMT_UYVY422,
|
|
18
|
+
YUV420P: binding.AV_PIX_FMT_YUV420P
|
|
19
|
+
},
|
|
20
|
+
mediaTypes: {
|
|
21
|
+
UNKNOWN: binding.AVMEDIA_TYPE_UNKNOWN,
|
|
22
|
+
VIDEO: binding.AVMEDIA_TYPE_VIDEO,
|
|
23
|
+
AUDIO: binding.AVMEDIA_TYPE_AUDIO,
|
|
24
|
+
DATA: binding.AVMEDIA_TYPE_DATA,
|
|
25
|
+
SUBTITLE: binding.AVMEDIA_TYPE_SUBTITLE,
|
|
26
|
+
ATTACHEMENT: binding.AVMEDIA_TYPE_ATTACHMENT,
|
|
27
|
+
NB: binding.AVMEDIA_TYPE_NB
|
|
28
|
+
},
|
|
29
|
+
sampleFormats: {
|
|
30
|
+
NONE: binding.AV_SAMPLE_FMT_NONE,
|
|
31
|
+
U8: binding.AV_SAMPLE_FMT_U8,
|
|
32
|
+
S16: binding.AV_SAMPLE_FMT_S16,
|
|
33
|
+
S32: binding.AV_SAMPLE_FMT_S32,
|
|
34
|
+
S64: binding.AV_SAMPLE_FMT_S64,
|
|
35
|
+
FLT: binding.AV_SAMPLE_FMT_FLT,
|
|
36
|
+
DBL: binding.AV_SAMPLE_FMT_DBL,
|
|
37
|
+
U8P: binding.AV_SAMPLE_FMT_U8P,
|
|
38
|
+
S16P: binding.AV_SAMPLE_FMT_S16P,
|
|
39
|
+
S32P: binding.AV_SAMPLE_FMT_S32P,
|
|
40
|
+
S64P: binding.AV_SAMPLE_FMT_S64P,
|
|
41
|
+
FLTP: binding.AV_SAMPLE_FMT_FLTP,
|
|
42
|
+
DBLP: binding.AV_SAMPLE_FMT_DBLP,
|
|
43
|
+
NB: binding.AV_SAMPLE_FMT_NB
|
|
44
|
+
},
|
|
45
|
+
channelLayouts: {
|
|
46
|
+
MONO: binding.AV_CH_LAYOUT_MONO,
|
|
47
|
+
STEREO: binding.AV_CH_LAYOUT_STEREO,
|
|
48
|
+
QUAD: binding.AV_CH_LAYOUT_QUAD,
|
|
49
|
+
SURROUND: binding.AV_CH_LAYOUT_SURROUND,
|
|
50
|
+
2_1: binding.AV_CH_LAYOUT_2POINT1,
|
|
51
|
+
5_0: binding.AV_CH_LAYOUT_5POINT0,
|
|
52
|
+
5_1: binding.AV_CH_LAYOUT_5POINT1,
|
|
53
|
+
7_1: binding.AV_CH_LAYOUT_7POINT1,
|
|
54
|
+
// Aliases
|
|
55
|
+
2.1: binding.AV_CH_LAYOUT_2POINT1,
|
|
56
|
+
'5.0': binding.AV_CH_LAYOUT_5POINT0,
|
|
57
|
+
5.1: binding.AV_CH_LAYOUT_5POINT1,
|
|
58
|
+
7.1: binding.AV_CH_LAYOUT_7POINT1
|
|
6
59
|
}
|
|
7
60
|
}
|
|
8
61
|
|
|
9
|
-
exports.toPixelFormat = function toPixelFormat(
|
|
10
|
-
if (typeof
|
|
62
|
+
exports.toPixelFormat = function toPixelFormat(format) {
|
|
63
|
+
if (typeof format === 'number') return format
|
|
11
64
|
|
|
12
|
-
if (typeof
|
|
13
|
-
if (
|
|
14
|
-
throw errors.UNKNOWN_PIXEL_FORMAT(`Unknown pixel format '${
|
|
65
|
+
if (typeof format === 'string') {
|
|
66
|
+
if (format in exports.pixelFormats === false) {
|
|
67
|
+
throw errors.UNKNOWN_PIXEL_FORMAT(`Unknown pixel format '${format}'`)
|
|
15
68
|
}
|
|
16
69
|
|
|
17
|
-
return exports.pixelFormats[
|
|
70
|
+
return exports.pixelFormats[format]
|
|
18
71
|
}
|
|
72
|
+
|
|
73
|
+
throw new TypeError(
|
|
74
|
+
`Pixel format must be a number or string. Received ${typeof format} (${format})`
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
exports.toSampleFormat = function toSampleFormat(format) {
|
|
79
|
+
if (typeof format === 'number') return format
|
|
80
|
+
|
|
81
|
+
if (typeof format === 'string') {
|
|
82
|
+
if (format in exports.sampleFormats === false) {
|
|
83
|
+
throw errors.UNKNOWN_SAMPLE_FORMAT(`Unknown sample format '${format}'`)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return exports.sampleFormats[format]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
throw new TypeError(
|
|
90
|
+
`Sample format must be a number or string. Received ${typeof format} (${format})`
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
exports.toChannelLayout = function toChannelLayout(layout) {
|
|
95
|
+
if (typeof layout === 'number') return layout
|
|
96
|
+
|
|
97
|
+
if (typeof layout === 'string') {
|
|
98
|
+
if (layout in exports.channelLayouts === false) {
|
|
99
|
+
throw errors.UNKNOWN_CHANNEL_LAYOUT(`Unknown channel layout '${layout}'`)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return exports.channelLayouts[layout]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
throw new TypeError(
|
|
106
|
+
`Channel layout must be a number or string. Received ${typeof layout} (${layout})`
|
|
107
|
+
)
|
|
19
108
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const binding = require('../binding')
|
|
2
|
+
|
|
3
|
+
module.exports = class FFmpegDictionary {
|
|
4
|
+
constructor() {
|
|
5
|
+
this._handle = binding.initDictionary()
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
destroy() {
|
|
9
|
+
binding.destroyDictionary(this._handle)
|
|
10
|
+
this._handle = null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get(key) {
|
|
14
|
+
const value = binding.getDictionaryEntry(this._handle, key)
|
|
15
|
+
if (value === undefined) return null
|
|
16
|
+
return value
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
set(key, value) {
|
|
20
|
+
binding.setDictionaryEntry(this._handle, key, value)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
[Symbol.dispose]() {
|
|
24
|
+
this.destroy()
|
|
25
|
+
}
|
|
26
|
+
}
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module.exports = class FFmpegError extends Error {
|
|
2
|
+
constructor(msg, code, fn = FFmpegError) {
|
|
3
|
+
super(`${code}: ${msg}`)
|
|
4
|
+
this.code = code
|
|
5
|
+
|
|
6
|
+
if (Error.captureStackTrace) {
|
|
7
|
+
Error.captureStackTrace(this, fn)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get name() {
|
|
12
|
+
return 'FFmpegError'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static UNKNOWN_PIXEL_FORMAT(msg) {
|
|
16
|
+
return new FFmpegError(
|
|
17
|
+
msg,
|
|
18
|
+
'UNKNOWN_PIXEL_FORMAT',
|
|
19
|
+
FFmpegError.UNKNOWN_PIXEL_FORMAT
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static UNKNOWN_SAMPLE_FORMAT(msg) {
|
|
24
|
+
return new FFmpegError(
|
|
25
|
+
msg,
|
|
26
|
+
'UNKNOWN_SAMPLE_FORMAT',
|
|
27
|
+
FFmpegError.UNKNOWN_SAMPLE_FORMAT
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static UNKNOWN_CHANNEL_LAYOUT(msg) {
|
|
32
|
+
return new FFmpegError(
|
|
33
|
+
msg,
|
|
34
|
+
'UNKNOWN_CHANNEL_LAYOUT',
|
|
35
|
+
FFmpegError.UNKNOWN_CHANNEL_LAYOUT
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
}
|
package/lib/format-context.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
const binding = require('../binding')
|
|
2
2
|
const Stream = require('./stream.js')
|
|
3
|
+
const OutputFormat = require('./output-format')
|
|
4
|
+
const IOContext = require('./io-context')
|
|
5
|
+
const InputFormat = require('./input-format')
|
|
6
|
+
const Dictionary = require('./dictionary')
|
|
3
7
|
|
|
4
|
-
|
|
8
|
+
class FFmpegFormatContext {
|
|
5
9
|
constructor(io) {
|
|
6
10
|
this._io = io
|
|
7
11
|
this._streams = []
|
|
8
|
-
|
|
12
|
+
}
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
destroy() {
|
|
15
|
+
if (this._io) {
|
|
16
|
+
this._io.destroy()
|
|
17
|
+
this._io = null
|
|
12
18
|
}
|
|
19
|
+
|
|
20
|
+
for (const stream of this._streams) stream.destroy()
|
|
21
|
+
this._streams = []
|
|
13
22
|
}
|
|
14
23
|
|
|
15
24
|
get io() {
|
|
@@ -20,18 +29,122 @@ module.exports = class FFmpegFormatContext {
|
|
|
20
29
|
return this._streams
|
|
21
30
|
}
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
readFrame(packet) {
|
|
33
|
+
return binding.readFormatContextFrame(this._handle, packet._handle)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getBestStreamIndex(type) {
|
|
37
|
+
return binding.getFormatContextBestStreamIndex(this._handle, type)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getStream(index) {
|
|
41
|
+
if (index < 0 || index >= this._streams.length) {
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return this._streams[index]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getBestStream(type) {
|
|
49
|
+
if (this._streams.length == 0) {
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const bestIndex = binding.getFormatContextBestStreamIndex(
|
|
54
|
+
this._handle,
|
|
55
|
+
type
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
if (bestIndex < 0 || bestIndex >= this._streams.length) {
|
|
59
|
+
return null
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return this._streams[bestIndex]
|
|
28
63
|
}
|
|
29
64
|
|
|
30
65
|
[Symbol.dispose]() {
|
|
31
66
|
this.destroy()
|
|
32
67
|
}
|
|
68
|
+
}
|
|
33
69
|
|
|
34
|
-
|
|
35
|
-
|
|
70
|
+
let defaultURL = null
|
|
71
|
+
|
|
72
|
+
switch (Bare.platform) {
|
|
73
|
+
case 'darwin':
|
|
74
|
+
case 'ios':
|
|
75
|
+
defaultURL = '0:0'
|
|
76
|
+
break
|
|
77
|
+
case 'linux':
|
|
78
|
+
// TODO: test on real machine
|
|
79
|
+
// we might need separate contexts for linux
|
|
80
|
+
// video: V4L2 and audio: ALSA/PulseAudio
|
|
81
|
+
defaultURL = '/dev/video0'
|
|
82
|
+
break
|
|
83
|
+
case 'win32':
|
|
84
|
+
defaultURL = 'video=Integrated Camera'
|
|
85
|
+
break
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
exports.InputFormatContext = class FFmpegInputFormatContext extends (
|
|
89
|
+
FFmpegFormatContext
|
|
90
|
+
) {
|
|
91
|
+
constructor(io, options, url = defaultURL) {
|
|
92
|
+
if (io instanceof IOContext) {
|
|
93
|
+
super(io)
|
|
94
|
+
|
|
95
|
+
this._handle = binding.openInputFormatContextWithIO(io._handle)
|
|
96
|
+
} else if (io instanceof InputFormat) {
|
|
97
|
+
super()
|
|
98
|
+
|
|
99
|
+
options = options || new Dictionary()
|
|
100
|
+
|
|
101
|
+
this._handle = binding.openInputFormatContextWithFormat(
|
|
102
|
+
io._handle,
|
|
103
|
+
options._handle,
|
|
104
|
+
url
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
options.destroy()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
for (const handle of binding.getFormatContextStreams(this._handle)) {
|
|
111
|
+
this._streams.push(new Stream(handle))
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
destroy() {
|
|
116
|
+
super.destroy()
|
|
117
|
+
|
|
118
|
+
binding.closeInputFormatContext(this._handle)
|
|
119
|
+
this._handle = null
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
exports.OutputFormatContext = class FFmpegOutputFormatContext extends (
|
|
124
|
+
FFmpegFormatContext
|
|
125
|
+
) {
|
|
126
|
+
constructor(format, io) {
|
|
127
|
+
super(io)
|
|
128
|
+
|
|
129
|
+
if (typeof format === 'string') format = new OutputFormat(format)
|
|
130
|
+
|
|
131
|
+
this._handle = binding.openOutputFormatContext(format._handle, io._handle)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
destroy() {
|
|
135
|
+
super.destroy()
|
|
136
|
+
|
|
137
|
+
binding.closeOutputFormatContext(this._handle)
|
|
138
|
+
this._handle = null
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
createStream(codec) {
|
|
142
|
+
const stream = new Stream(
|
|
143
|
+
binding.createFormatContextStream(this._handle, codec._handle)
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
this._streams.push(stream)
|
|
147
|
+
|
|
148
|
+
return stream
|
|
36
149
|
}
|
|
37
150
|
}
|
package/lib/frame.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const binding = require('../binding')
|
|
2
|
+
const ChannelLayout = require('./channel-layout')
|
|
2
3
|
|
|
3
4
|
module.exports = class FFmpegFrame {
|
|
4
5
|
constructor() {
|
|
@@ -6,11 +7,64 @@ module.exports = class FFmpegFrame {
|
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
destroy() {
|
|
9
|
-
if (this._handle === null) return
|
|
10
10
|
binding.destroyFrame(this._handle)
|
|
11
11
|
this._handle = null
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
get width() {
|
|
15
|
+
return binding.getFrameWidth(this._handle)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
set width(value) {
|
|
19
|
+
binding.setFrameWidth(this._handle, value)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get height() {
|
|
23
|
+
return binding.getFrameHeight(this._handle)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
set height(value) {
|
|
27
|
+
binding.setFrameHeight(this._handle, value)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get pixelFormat() {
|
|
31
|
+
return binding.getFramePixelFormat(this._handle)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
set pixelFormat(value) {
|
|
35
|
+
binding.setFramePixelFormat(this._handle, value)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get format() {
|
|
39
|
+
return binding.getFrameFormat(this._handle)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
set format(value) {
|
|
43
|
+
binding.setFrameFormat(this._handle, value)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get channelLayout() {
|
|
47
|
+
return new ChannelLayout(binding.getFrameChannelLayout(this._handle))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
set channelLayout(value) {
|
|
51
|
+
using copy = ChannelLayout.from(value)
|
|
52
|
+
|
|
53
|
+
binding.setFrameChannelLayout(this._handle, copy._handle)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get nbSamples() {
|
|
57
|
+
return binding.getFrameNbSamples(this._handle)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
set nbSamples(value) {
|
|
61
|
+
binding.setFrameNbSamples(this._handle, value)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
alloc() {
|
|
65
|
+
binding.allocFrame(this._handle, 32)
|
|
66
|
+
}
|
|
67
|
+
|
|
14
68
|
[Symbol.dispose]() {
|
|
15
69
|
this.destroy()
|
|
16
70
|
}
|
package/lib/image.js
CHANGED
|
@@ -40,8 +40,18 @@ module.exports = class FFmpegImage {
|
|
|
40
40
|
this._pixelFormat,
|
|
41
41
|
this._width,
|
|
42
42
|
this._height,
|
|
43
|
+
this._align,
|
|
43
44
|
this._data.buffer,
|
|
45
|
+
this._data.byteOffset,
|
|
44
46
|
frame._handle
|
|
45
47
|
)
|
|
46
48
|
}
|
|
49
|
+
|
|
50
|
+
lineSize(plane = 0) {
|
|
51
|
+
return binding.getImageLineSize(this._pixelFormat, this._width, plane)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static lineSize(pixelFormat, width, plane = 0) {
|
|
55
|
+
return binding.getImageLineSize(pixelFormat, width, plane)
|
|
56
|
+
}
|
|
47
57
|
}
|