@lumen5/beamcoder 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.
Files changed (88) hide show
  1. package/.circleci/config.yml +41 -0
  2. package/.circleci/images/testbeam10-4.1/Dockerfile +12 -0
  3. package/.circleci/test_image/Dockerfile +14 -0
  4. package/.circleci/test_image/build.md +13 -0
  5. package/.eslintrc.js +27 -0
  6. package/.github/workflows/publish-npm.yml +33 -0
  7. package/LICENSE +674 -0
  8. package/README.md +1221 -0
  9. package/beamstreams.js +692 -0
  10. package/binding.gyp +103 -0
  11. package/examples/encode_h264.js +92 -0
  12. package/examples/jpeg_app.js +55 -0
  13. package/examples/jpeg_filter_app.js +101 -0
  14. package/examples/make_mp4.js +123 -0
  15. package/images/beamcoder_small.jpg +0 -0
  16. package/index.d.ts +83 -0
  17. package/index.js +44 -0
  18. package/install_ffmpeg.js +240 -0
  19. package/package.json +45 -0
  20. package/scratch/decode_aac.js +38 -0
  21. package/scratch/decode_avci.js +50 -0
  22. package/scratch/decode_hevc.js +38 -0
  23. package/scratch/decode_pcm.js +39 -0
  24. package/scratch/make_a_mux.js +68 -0
  25. package/scratch/muxer.js +74 -0
  26. package/scratch/read_wav.js +35 -0
  27. package/scratch/simple_mux.js +39 -0
  28. package/scratch/stream_avci.js +127 -0
  29. package/scratch/stream_mp4.js +78 -0
  30. package/scratch/stream_mux.js +47 -0
  31. package/scratch/stream_pcm.js +82 -0
  32. package/scratch/stream_wav.js +62 -0
  33. package/scripts/install_beamcoder_dependencies.sh +25 -0
  34. package/src/adaptor.h +202 -0
  35. package/src/beamcoder.cc +937 -0
  36. package/src/beamcoder_util.cc +1129 -0
  37. package/src/beamcoder_util.h +206 -0
  38. package/src/codec.cc +7386 -0
  39. package/src/codec.h +44 -0
  40. package/src/codec_par.cc +1818 -0
  41. package/src/codec_par.h +40 -0
  42. package/src/decode.cc +569 -0
  43. package/src/decode.h +75 -0
  44. package/src/demux.cc +584 -0
  45. package/src/demux.h +88 -0
  46. package/src/encode.cc +496 -0
  47. package/src/encode.h +72 -0
  48. package/src/filter.cc +1888 -0
  49. package/src/filter.h +30 -0
  50. package/src/format.cc +5287 -0
  51. package/src/format.h +77 -0
  52. package/src/frame.cc +2681 -0
  53. package/src/frame.h +52 -0
  54. package/src/governor.cc +286 -0
  55. package/src/governor.h +30 -0
  56. package/src/hwcontext.cc +378 -0
  57. package/src/hwcontext.h +35 -0
  58. package/src/log.cc +186 -0
  59. package/src/log.h +20 -0
  60. package/src/mux.cc +834 -0
  61. package/src/mux.h +106 -0
  62. package/src/packet.cc +762 -0
  63. package/src/packet.h +49 -0
  64. package/test/codecParamsSpec.js +148 -0
  65. package/test/decoderSpec.js +56 -0
  66. package/test/demuxerSpec.js +41 -0
  67. package/test/encoderSpec.js +69 -0
  68. package/test/filtererSpec.js +47 -0
  69. package/test/formatSpec.js +343 -0
  70. package/test/frameSpec.js +145 -0
  71. package/test/introspectionSpec.js +73 -0
  72. package/test/muxerSpec.js +34 -0
  73. package/test/packetSpec.js +122 -0
  74. package/types/Beamstreams.d.ts +98 -0
  75. package/types/Codec.d.ts +123 -0
  76. package/types/CodecContext.d.ts +555 -0
  77. package/types/CodecPar.d.ts +108 -0
  78. package/types/Decoder.d.ts +137 -0
  79. package/types/Demuxer.d.ts +113 -0
  80. package/types/Encoder.d.ts +94 -0
  81. package/types/Filter.d.ts +324 -0
  82. package/types/FormatContext.d.ts +380 -0
  83. package/types/Frame.d.ts +295 -0
  84. package/types/HWContext.d.ts +62 -0
  85. package/types/Muxer.d.ts +121 -0
  86. package/types/Packet.d.ts +82 -0
  87. package/types/PrivClass.d.ts +25 -0
  88. package/types/Stream.d.ts +165 -0
@@ -0,0 +1,122 @@
1
+ /*
2
+ Aerostat Beam Coder - Node.js native bindings for FFmpeg.
3
+ Copyright (C) 2019 Streampunk Media Ltd.
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ https://www.streampunk.media/ mailto:furnace@streampunk.media
19
+ 14 Ormiscaig, Aultbea, Achnasheen, IV22 2JJ U.K.
20
+ */
21
+
22
+ const test = require('tape');
23
+ const beamcoder = require('../index.js');
24
+
25
+ test('Create a packet', t => {
26
+ let pkt = beamcoder.packet();
27
+ t.ok(pkt, 'is truthy.');
28
+ t.equal(typeof pkt._packet, 'object', 'external value present.');
29
+ t.deepEqual(pkt, { type: 'Packet',
30
+ pts: null,
31
+ dts: null,
32
+ data: null,
33
+ size: 0,
34
+ stream_index: 0,
35
+ flags:
36
+ { KEY: false,
37
+ CORRUPT: false,
38
+ DISCARD: false,
39
+ TRUSTED: false,
40
+ DISPOSABLE: false },
41
+ side_data: null,
42
+ duration: 0,
43
+ pos: -1 }, 'has expected minimal value.');
44
+ t.end();
45
+ });
46
+
47
+ test('Minimal JSON serialization', t => {
48
+ let pkt = beamcoder.packet();
49
+ t.equal(typeof pkt.toJSON, 'function', 'has hidden toJSON function.');
50
+ let ps = JSON.stringify(pkt);
51
+ t.equal(typeof ps, 'string', 'stringify created a string.');
52
+ let pps = JSON.parse(ps);
53
+ t.deepEqual(pps, { type: 'Packet', stream_index: 0 }, 'made minimal value.');
54
+ let rpkt = beamcoder.packet(ps);
55
+ t.ok(rpkt, 'roundtrip packet is truthy.');
56
+ t.deepEqual(rpkt, { type: 'Packet',
57
+ pts: null,
58
+ dts: null,
59
+ data: null,
60
+ size: 0,
61
+ stream_index: 0,
62
+ flags:
63
+ { KEY: false,
64
+ CORRUPT: false,
65
+ DISCARD: false,
66
+ TRUSTED: false,
67
+ DISPOSABLE: false },
68
+ side_data: null,
69
+ duration: 0,
70
+ pos: -1 }, 'has expected minimal value.');
71
+ t.end();
72
+ });
73
+
74
+ test('Maximal JSON serialization', t => {
75
+ let pkt = beamcoder.packet({ type: 'Packet',
76
+ pts: 42,
77
+ dts: 43,
78
+ data: Buffer.from('wibble'),
79
+ stream_index: 7,
80
+ flags:
81
+ { KEY: true,
82
+ CORRUPT: false,
83
+ DISCARD: false,
84
+ TRUSTED: true,
85
+ DISPOSABLE: false },
86
+ side_data: { replaygain: Buffer.from('wobble') },
87
+ duration: 44,
88
+ pos: 45 });
89
+ let ps = JSON.stringify(pkt);
90
+ t.equal(typeof ps, 'string', 'stringify created a string.');
91
+ let rpkt = beamcoder.packet(ps);
92
+ t.ok(rpkt, 'roundtrip packet is truthy.');
93
+ t.deepEqual(rpkt, { type: 'Packet',
94
+ pts: 42,
95
+ dts: 43,
96
+ data: null,
97
+ size: 0,
98
+ stream_index: 7,
99
+ flags:
100
+ { KEY: true,
101
+ CORRUPT: false,
102
+ DISCARD: false,
103
+ TRUSTED: true,
104
+ DISPOSABLE: false },
105
+ side_data:
106
+ { type: 'PacketSideData',
107
+ replaygain: Buffer.from([0x77, 0x6f, 0x62, 0x62, 0x6c, 0x65]) },
108
+ duration: 44,
109
+ pos: 45 }, 'roundtrips expected values.');
110
+ t.end();
111
+ });
112
+
113
+ test('Reset packet data', t => {
114
+ let p = beamcoder.packet({ pts: 42, size: 4321, data: Buffer.alloc(4321 + beamcoder.AV_INPUT_BUFFER_PADDING_SIZE) });
115
+ t.ok(Buffer.isBuffer(p.data), 'data is a buffer.');
116
+ t.notEqual(p.data.length, p.size, 'data length is greater than the packet size.');
117
+ t.equal(p.data.length, 4321 + beamcoder.AV_INPUT_BUFFER_PADDING_SIZE, 'length is as expected.');
118
+ p.data = null;
119
+ t.equal(p.data, null, 'after reset, packet data is set to null.');
120
+ t.equal(p.size, 4321, 'after reset, size remains at original value.');
121
+ t.end();
122
+ });
@@ -0,0 +1,98 @@
1
+ import { Demuxer, DemuxerCreateOptions } from "./Demuxer"
2
+ import { Muxer, MuxerCreateOptions } from "./Muxer"
3
+ import { InputFormat } from "./FormatContext"
4
+
5
+ /**
6
+ * A [Node.js Writable stream](https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_writable_streams)
7
+ * allowing source data to be streamed to the demuxer from a file or other stream source such as a network connection
8
+ */
9
+ export interface WritableDemuxerStream extends NodeJS.WritableStream {
10
+ /**
11
+ * Create a demuxer for this source
12
+ * @param options a DemuxerCreateOptions object
13
+ * @returns a promise that resolves to a Demuxer when it has determined sufficient
14
+ * format details by consuming data from the source. The promise will wait indefinitely
15
+ * until sufficient source data has been read.
16
+ */
17
+ demuxer(options: DemuxerCreateOptions): Promise<Demuxer>
18
+ }
19
+ /**
20
+ * Create a WritableDemuxerStream to allow streaming to a Demuxer
21
+ * @param options.highwaterMark Buffer level when `stream.write()` starts returng false.
22
+ * @returns A WritableDemuxerStream that can be streamed to.
23
+ */
24
+ export function demuxerStream(options: { highwaterMark?: number }): WritableDemuxerStream
25
+
26
+ /**
27
+ * A [Node.js Readable stream](https://nodejs.org/docs/latest-v12.x/api/stream.html#stream_readable_streams)
28
+ * allowing data to be streamed from the muxer to a file or other stream destination such as a network connection
29
+ */
30
+ export interface ReadableMuxerStream extends NodeJS.ReadableStream {
31
+ /**
32
+ * Create a muxer for this source
33
+ * @param options a MuxerCreateOptions object
34
+ * @returns A Muxer object
35
+ */
36
+ muxer(options: MuxerCreateOptions): Muxer
37
+ }
38
+ /**
39
+ * Create a ReadableMuxerStream to allow streaming from a Muxer
40
+ * @param options.highwaterMark The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource.
41
+ * @returns A ReadableMuxerStream that can be streamed from.
42
+ */
43
+ export function muxerStream(options: { highwaterMark?: number }): ReadableMuxerStream
44
+
45
+ /** Create object for AVIOContext based buffered I/O */
46
+ export function governor(options: { highWaterMark: number }): {
47
+ read(len: number): Promise<Buffer>
48
+ write(data: Buffer): Promise<null>
49
+ finish(): undefined
50
+ }
51
+
52
+ /** Source definition for a beamstream channel, from either a file or NodeJS ReadableStream */
53
+ export interface BeamstreamSource {
54
+ url?: string
55
+ input_stream?: NodeJS.ReadableStream
56
+ ms?: { start: number, end: number }
57
+ streamIndex?: number
58
+ iformat?: InputFormat
59
+ options?: { [key: string]: any }
60
+ }
61
+ /** Codec definition for the destination channel */
62
+ export interface BeamstreamStream {
63
+ name: string
64
+ time_base: Array<number>
65
+ codecpar: { [key: string]: any }
66
+ }
67
+ /** Definition for a channel of beamstream processing */
68
+ export interface BeamstreamChannel {
69
+ sources: Array<BeamstreamSource>
70
+ filterSpec: string
71
+ streams: Array<BeamstreamStream>
72
+ }
73
+ /**
74
+ * Definition for a beamstream process consisting of a number of audio and video sources
75
+ * that are to be processed and multiplexed into an output file or stream
76
+ */
77
+ export interface BeamstreamParams {
78
+ video?: Array<BeamstreamChannel>
79
+ audio?: Array<BeamstreamChannel>
80
+ /** Destination definition for the beamstream process, to either a file or NodeJS WritableStream */
81
+ out: {
82
+ formatName: string
83
+ url?: string
84
+ output_stream?: NodeJS.WritableStream
85
+ }
86
+ }
87
+ /**
88
+ * Initialise the sources for the beamstream process.
89
+ * Note - the params object is updated by the function.
90
+ */
91
+ export function makeSources(params: BeamstreamParams): Promise<null>
92
+ /**
93
+ * Initialise the output streams for the beamstream process.
94
+ * Note - the params object is updated by the function.
95
+ * @returns Promise which resolves to an object with a run function that starts the processing
96
+ */
97
+ export function makeStreams(params: BeamstreamParams): Promise<{ run(): Promise<null>} >
98
+
@@ -0,0 +1,123 @@
1
+ import { PrivClass } from "./PrivClass"
2
+
3
+ export interface Codec {
4
+ /** Object name. */
5
+ readonly type: 'Codec'
6
+ /**
7
+ * Name of the codec implementation.
8
+ * The name is globally unique among encoders and among decoders (but an
9
+ * encoder and a decoder can share the same name).
10
+ * This is the primary way to find a codec from the user perspective.
11
+ */
12
+ readonly name: string
13
+ /** Descriptive name for the codec, meant to be more human readable than name. */
14
+ readonly long_name: string
15
+ /** String describing the media type */
16
+ readonly codec_type: 'unknown' | 'video' | 'audio' | 'data' | 'subtitle' | 'attachment' | 'nb'
17
+ /** Number that identifies the syntax and semantics of the bitstream. */
18
+ readonly id: number
19
+ /** true if codec is an decoder */
20
+ readonly decoder: boolean
21
+ /** true if codec is an encoder */
22
+ readonly encoder: boolean
23
+ /** Codec capabilities - see AV_CODEC_CAP_* */
24
+ readonly capabilities: {
25
+ /** Decoder can use draw_horiz_band callback. */
26
+ DRAW_HORIZ_BAND: boolean
27
+ /** Codec uses get_buffer() for allocating buffers and supports custom allocators. */
28
+ DR1: boolean
29
+ TRUNCATED: boolean
30
+ /**
31
+ * Decoder requires flushing with NULL input at the end in order to
32
+ * give the complete and correct output.
33
+
34
+ * NOTE: If this flag is not set, the codec is guaranteed to never be fed with
35
+ * with NULL data. The user can still send NULL data to the decode function,
36
+ * but it will not be passed along to the codec unless this flag is set.
37
+ *
38
+ * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL,
39
+ * avpkt->size=0 at the end to get the delayed data until the decoder no longer
40
+ * returns frames.
41
+ */
42
+ DELAY: boolean
43
+ /** Codec can be fed a final frame with a smaller size. This can be used to prevent truncation of the last audio samples. */
44
+ SMALL_LAST_FRAME: boolean
45
+ /**
46
+ * Codec can output multiple frames per APacket
47
+ * Normally demuxers return one frame at a time, demuxers which do not do
48
+ * are connected to a parser to split what they return into proper frames.
49
+ * This flag is reserved to the very rare category of codecs which have a
50
+ * bitstream that cannot be split into frames without timeconsuming
51
+ * operations like full decoding. Demuxers carrying such bitstreams thus
52
+ * may return multiple frames in a packet. This has many disadvantages like
53
+ * prohibiting stream copy in many cases thus it should only be considered
54
+ * as a last resort.
55
+ */
56
+ SUBFRAMES: boolean
57
+ /** Codec is experimental and is thus avoided in favor of non experimental codecs */
58
+ EXPERIMENTAL: boolean
59
+ /** Codec should fill in channel configuration and samplerate instead of container */
60
+ CHANNEL_CONF: boolean
61
+ /** Codec supports frame-level multithreading. */
62
+ FRAME_THREADS: boolean
63
+ /** Codec supports slice-based (or partition-based) multithreading. */
64
+ SLICE_THREADS: boolean
65
+ /** Codec supports changed parameters at any point. */
66
+ PARAM_CHANGE: boolean
67
+ /** Codec supports avctx->thread_count == 0 (auto). */
68
+ AUTO_THREADS: boolean
69
+ /** Audio encoder supports receiving a different number of samples in each call. */
70
+ VARIABLE_FRAME_SIZE: boolean
71
+ /**
72
+ * Decoder is not a preferred choice for probing.
73
+ * This indicates that the decoder is not a good choice for probing.
74
+ * It could for example be an expensive to spin up hardware decoder,
75
+ * or it could simply not provide a lot of useful information about
76
+ * the stream.
77
+ * A decoder marked with this flag should only be used as last resort
78
+ * choice for probing.
79
+ */
80
+ AVOID_PROBING: boolean
81
+ /** Codec is intra only. */
82
+ INTRA_ONLY: boolean
83
+ /** Codec is lossless. */
84
+ LOSSLESS: boolean
85
+ /** Codec is backed by a hardware implementation. Typically used to identify a non-hwaccel hardware decoder. */
86
+ HARDWARE: boolean
87
+ /**
88
+ * Codec is potentially backed by a hardware implementation, but not necessarily.
89
+ * This is used instead of the HARDWARE flag if the implementation provides some sort of internal fallback.
90
+ */
91
+ HYBRID: boolean
92
+ }
93
+ /** Array of supported framerates (as a rational [num, den]), or null if unknown. */
94
+ readonly supported_framerates: ReadonlyArray<ReadonlyArray<number>> | null
95
+ /** Array of supported pixel formats, or null if unknown. */
96
+ readonly pix_fmts: ReadonlyArray<string> | null
97
+ /** Array of supported audio samplerates, or null if unknown */
98
+ readonly supported_samplerates: ReadonlyArray<number> | null
99
+ /** Array of supported sample formats, or NULL if unknown, */
100
+ readonly sample_fmts: ReadonlyArray<string>
101
+ /** */
102
+ readonly channel_layouts: ReadonlyArray<string>
103
+ /** */
104
+ readonly max_lowres: number
105
+ /** Class for private context */
106
+ readonly priv_class: PrivClass
107
+ /** */
108
+ readonly profiles: ReadonlyArray<string> | null
109
+ /** */
110
+ readonly wrapper_name?: string
111
+ /** */
112
+ readonly descriptor: {
113
+ INTRA_ONLY: boolean
114
+ LOSSY: boolean
115
+ LOSSLESS: boolean
116
+ REORDER: boolean
117
+ BITMAP_SUB: boolean
118
+ TEXT_SUB: boolean
119
+ }
120
+ }
121
+
122
+ /** List the available codecs */
123
+ export function codecs(): { [key: string]: { encoder?: Codec, decoder?: Codec }}