@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
package/src/packet.cc ADDED
@@ -0,0 +1,762 @@
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
+ #include "packet.h"
23
+
24
+ napi_value getPacketPts(napi_env env, napi_callback_info info) {
25
+ napi_status status;
26
+ napi_value result;
27
+ packetData* p;
28
+
29
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
30
+ CHECK_STATUS;
31
+
32
+ if (p->packet->pts == AV_NOPTS_VALUE) {
33
+ status = napi_get_null(env, &result);
34
+ } else {
35
+ status = napi_create_int64(env, p->packet->pts, &result);
36
+ }
37
+ CHECK_STATUS;
38
+ return result;
39
+ }
40
+
41
+ napi_value setPacketPts(napi_env env, napi_callback_info info) {
42
+ napi_status status;
43
+ napi_value result;
44
+ napi_valuetype type;
45
+ packetData* p;
46
+
47
+ size_t argc = 1;
48
+ napi_value args[1];
49
+
50
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
51
+ CHECK_STATUS;
52
+ if (argc < 1) {
53
+ NAPI_THROW_ERROR("Set packet PTS must be provided with a value.");
54
+ }
55
+ status = napi_typeof(env, args[0], &type);
56
+ CHECK_STATUS;
57
+ switch (type) {
58
+ case napi_null:
59
+ p->packet->pts = AV_NOPTS_VALUE;
60
+ break;
61
+ case napi_number:
62
+ status = napi_get_value_int64(env, args[0], &p->packet->pts);
63
+ CHECK_STATUS;
64
+ break;
65
+ default:
66
+ NAPI_THROW_ERROR("Packet PTS property must be set with a number.");
67
+ break;
68
+ }
69
+
70
+ status = napi_get_undefined(env, &result);
71
+ CHECK_STATUS;
72
+ return result;
73
+ }
74
+
75
+ napi_value getPacketDts(napi_env env, napi_callback_info info) {
76
+ napi_status status;
77
+ napi_value result;
78
+ packetData* p;
79
+
80
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
81
+ CHECK_STATUS;
82
+
83
+ if (p->packet->dts == AV_NOPTS_VALUE) {
84
+ status = napi_get_null(env, &result);
85
+ } else {
86
+ status = napi_create_int64(env, p->packet->dts, &result);
87
+ }
88
+
89
+ CHECK_STATUS;
90
+ return result;
91
+ }
92
+
93
+ napi_value setPacketDts(napi_env env, napi_callback_info info) {
94
+ napi_status status;
95
+ napi_value result;
96
+ napi_valuetype type;
97
+ packetData* p;
98
+
99
+ size_t argc = 1;
100
+ napi_value args[1];
101
+
102
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
103
+ CHECK_STATUS;
104
+ if (argc < 1) {
105
+ NAPI_THROW_ERROR("Set packet DTS must be provided with a value.");
106
+ }
107
+ status = napi_typeof(env, args[0], &type);
108
+ CHECK_STATUS;
109
+ if ((type == napi_undefined) || (type == napi_null)) {
110
+ p->packet->dts = AV_NOPTS_VALUE;
111
+ goto done;
112
+ }
113
+ if (type != napi_number) {
114
+ NAPI_THROW_ERROR("Packet DTS property must be set with a number.");
115
+ }
116
+ status = napi_get_value_int64(env, args[0], &p->packet->dts);
117
+ CHECK_STATUS;
118
+
119
+ done:
120
+ status = napi_get_undefined(env, &result);
121
+ CHECK_STATUS;
122
+ return result;
123
+ }
124
+
125
+ napi_value getPacketData(napi_env env, napi_callback_info info) {
126
+ napi_status status;
127
+ napi_value result;
128
+ packetData* p;
129
+ AVBufferRef* hintRef;
130
+
131
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
132
+ CHECK_STATUS;
133
+
134
+ if (p->packet->buf == nullptr) {
135
+ status = napi_get_null(env, &result);
136
+ } else {
137
+ hintRef = av_buffer_ref(p->packet->buf);
138
+ status = napi_create_external_buffer(env, hintRef->size, hintRef->data,
139
+ packetBufferFinalizer, hintRef, &result);
140
+ CHECK_STATUS;
141
+ }
142
+
143
+ CHECK_STATUS;
144
+ return result;
145
+ }
146
+
147
+ napi_value setPacketData(napi_env env, napi_callback_info info) {
148
+ napi_status status;
149
+ napi_value result;
150
+ napi_valuetype type;
151
+ bool isBuffer;
152
+ packetData* p;
153
+ uint8_t* data;
154
+ size_t length;
155
+ avBufRef* avr = new avBufRef;
156
+
157
+ size_t argc = 1;
158
+ napi_value args[1];
159
+
160
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
161
+ CHECK_STATUS;
162
+ if (argc < 1) {
163
+ NAPI_THROW_ERROR("Set packet data must be provided with a buffer value.");
164
+ }
165
+ status = napi_typeof(env, args[0], &type);
166
+ CHECK_STATUS;
167
+ if ((type == napi_null) || (type == napi_undefined)) {
168
+ if (p->dataRef != nullptr) {
169
+ status = napi_delete_reference(env, p->dataRef);
170
+ CHECK_STATUS;
171
+ p->dataRef = nullptr;
172
+ }
173
+ if (p->packet->buf != nullptr) {
174
+ av_buffer_unref(&p->packet->buf); // sets it to null
175
+ }
176
+ p->packet->data = nullptr;
177
+ goto done;
178
+ }
179
+ status = napi_is_buffer(env, args[0], &isBuffer);
180
+ CHECK_STATUS;
181
+ if (!isBuffer) {
182
+ NAPI_THROW_ERROR("Packet data property must be set with a buffer.");
183
+ }
184
+
185
+ if (p->dataRef != nullptr) {
186
+ status = napi_delete_reference(env, p->dataRef);
187
+ CHECK_STATUS;
188
+ p->dataRef = nullptr;
189
+ }
190
+ status = napi_create_reference(env, args[0], 1, &p->dataRef);
191
+ CHECK_STATUS;
192
+ status = napi_create_reference(env, args[0], 1, &avr->ref);
193
+ CHECK_STATUS;
194
+ avr->env = env;
195
+ status = napi_get_buffer_info(env, args[0], (void**) &data, &length);
196
+ CHECK_STATUS;
197
+ if (p->packet->buf != nullptr) {
198
+ av_buffer_unref(&p->packet->buf);
199
+ }
200
+ p->packet->buf = av_buffer_create(data, length, packetBufferFree, avr, 0);
201
+ CHECK_STATUS;
202
+ p->packet->data = data;
203
+
204
+ done:
205
+ status = napi_get_undefined(env, &result);
206
+ CHECK_STATUS;
207
+ return result;
208
+ }
209
+
210
+ // TODO is this a smell? Can this actually run from a separate thread?
211
+ void packetBufferFree(void* opaque, uint8_t* data) {
212
+ napi_status status;
213
+ avBufRef* avr = (avBufRef*) opaque;
214
+ status = napi_delete_reference(avr->env, (napi_ref) avr->ref);
215
+ if (status != napi_ok)
216
+ printf("DEBUG: Failed to delete buffer reference associated with an AVBufferRef.");
217
+ delete avr;
218
+ }
219
+
220
+ napi_value getPacketSize(napi_env env, napi_callback_info info) {
221
+ napi_status status;
222
+ napi_value result;
223
+ packetData *p;
224
+
225
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
226
+ CHECK_STATUS;
227
+
228
+ status = napi_create_int32(env, p->packet->size, &result);
229
+ CHECK_STATUS;
230
+
231
+ return result;
232
+ }
233
+
234
+ napi_value setPacketSize(napi_env env, napi_callback_info info) {
235
+ napi_status status;
236
+ napi_value result;
237
+ napi_valuetype type;
238
+ packetData* p;
239
+
240
+ size_t argc = 1;
241
+ napi_value args[1];
242
+
243
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
244
+ CHECK_STATUS;
245
+ if (argc < 1) {
246
+ NAPI_THROW_ERROR("Set packet size must be provided with a value.");
247
+ }
248
+ status = napi_typeof(env, args[0], &type);
249
+ CHECK_STATUS;
250
+ if (type != napi_number) {
251
+ NAPI_THROW_ERROR("Packet size property must be set with a number.");
252
+ }
253
+ status = napi_get_value_int32(env, args[0], &p->packet->size);
254
+ CHECK_STATUS;
255
+
256
+ status = napi_get_undefined(env, &result);
257
+ CHECK_STATUS;
258
+
259
+ return result;
260
+ }
261
+
262
+ napi_value getPacketStreamIndex(napi_env env, napi_callback_info info) {
263
+ napi_status status;
264
+ napi_value result;
265
+ packetData* p;
266
+
267
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
268
+ CHECK_STATUS;
269
+
270
+ status = napi_create_int32(env, p->packet->stream_index, &result);
271
+ CHECK_STATUS;
272
+ return result;
273
+ }
274
+
275
+ napi_value setPacketStreamIndex(napi_env env, napi_callback_info info) {
276
+ napi_status status;
277
+ napi_value result;
278
+ napi_valuetype type;
279
+ packetData* p;
280
+
281
+ size_t argc = 1;
282
+ napi_value args[1];
283
+
284
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
285
+ CHECK_STATUS;
286
+ if (argc < 1) {
287
+ NAPI_THROW_ERROR("Set packet stream_index must be provided with a value.");
288
+ }
289
+ status = napi_typeof(env, args[0], &type);
290
+ CHECK_STATUS;
291
+ if (type != napi_number) {
292
+ NAPI_THROW_ERROR("Packet stream_index property must be set with a number.");
293
+ }
294
+ status = napi_get_value_int32(env, args[0], &p->packet->stream_index);
295
+ CHECK_STATUS;
296
+
297
+ status = napi_get_undefined(env, &result);
298
+ CHECK_STATUS;
299
+ return result;
300
+ }
301
+
302
+ napi_value getPacketFlags(napi_env env, napi_callback_info info) {
303
+ napi_status status;
304
+ napi_value result;
305
+ packetData* p;
306
+
307
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
308
+ CHECK_STATUS;
309
+
310
+ status = napi_create_object(env, &result);
311
+ CHECK_STATUS;
312
+ status = beam_set_bool(env, result, "KEY", (p->packet->flags & AV_PKT_FLAG_KEY) != 0);
313
+ CHECK_STATUS;
314
+ status = beam_set_bool(env, result, "CORRUPT", (p->packet->flags & AV_PKT_FLAG_CORRUPT) != 0);
315
+ CHECK_STATUS;
316
+ status = beam_set_bool(env, result, "DISCARD", (p->packet->flags & AV_PKT_FLAG_DISCARD) != 0);
317
+ CHECK_STATUS;
318
+ status = beam_set_bool(env, result, "TRUSTED", (p->packet->flags & AV_PKT_FLAG_TRUSTED) != 0);
319
+ CHECK_STATUS;
320
+ status = beam_set_bool(env, result, "DISPOSABLE", (p->packet->flags & AV_PKT_FLAG_DISPOSABLE) != 0);
321
+ CHECK_STATUS;
322
+
323
+ return result;
324
+ }
325
+
326
+ napi_value setPacketFlags(napi_env env, napi_callback_info info) {
327
+ napi_status status;
328
+ napi_value result;
329
+ napi_valuetype type;
330
+ packetData* p;
331
+ bool present, flag;
332
+
333
+ size_t argc = 1;
334
+ napi_value args[1];
335
+
336
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
337
+ CHECK_STATUS;
338
+ if (argc < 1) {
339
+ NAPI_THROW_ERROR("Set frame flags must be provided with a value.");
340
+ }
341
+ status = napi_typeof(env, args[0], &type);
342
+ CHECK_STATUS;
343
+ if (type != napi_object) {
344
+ NAPI_THROW_ERROR("Frame sample_rate property must be set with a number.");
345
+ }
346
+ status = beam_get_bool(env, args[0], "KEY", &present, &flag);
347
+ CHECK_STATUS;
348
+ if (present) { p->packet->flags = (flag) ?
349
+ p->packet->flags | AV_PKT_FLAG_KEY :
350
+ p->packet->flags & ~AV_PKT_FLAG_KEY; }
351
+ status = beam_get_bool(env, args[0], "CORRUPT", &present, &flag);
352
+ CHECK_STATUS;
353
+ if (present) { p->packet->flags = (flag) ?
354
+ p->packet->flags | AV_PKT_FLAG_CORRUPT :
355
+ p->packet->flags & ~AV_PKT_FLAG_CORRUPT; }
356
+ status = beam_get_bool(env, args[0], "DISCARD", &present, &flag);
357
+ CHECK_STATUS;
358
+ if (present) { p->packet->flags = (flag) ?
359
+ p->packet->flags | AV_PKT_FLAG_DISCARD :
360
+ p->packet->flags & ~AV_PKT_FLAG_DISCARD; }
361
+ status = beam_get_bool(env, args[0], "TRUSTED", &present, &flag);
362
+ CHECK_STATUS;
363
+ if (present) { p->packet->flags = (flag) ?
364
+ p->packet->flags | AV_PKT_FLAG_TRUSTED :
365
+ p->packet->flags & ~AV_PKT_FLAG_TRUSTED; }
366
+ status = beam_get_bool(env, args[0], "DISPOSABLE", &present, &flag);
367
+ CHECK_STATUS;
368
+ if (present) { p->packet->flags = (flag) ?
369
+ p->packet->flags | AV_PKT_FLAG_DISPOSABLE :
370
+ p->packet->flags & ~AV_PKT_FLAG_DISPOSABLE; }
371
+
372
+ status = napi_get_undefined(env, &result);
373
+ CHECK_STATUS;
374
+ return result;
375
+ }
376
+
377
+ napi_value getPacketSideData(napi_env env, napi_callback_info info) {
378
+ napi_status status;
379
+ napi_value result, element;
380
+ packetData* p;
381
+ void* resultData;
382
+
383
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
384
+ CHECK_STATUS;
385
+
386
+ if (p->packet->side_data_elems <= 0) {
387
+ status = napi_get_null(env, &result);
388
+ CHECK_STATUS;
389
+ } else {
390
+ status = napi_create_object(env, &result);
391
+ CHECK_STATUS;
392
+ status = beam_set_string_utf8(env, result, "type", "PacketSideData");
393
+ for ( int x = 0 ; x < p->packet->side_data_elems ; x++ ) {
394
+ status = napi_create_buffer_copy(env, p->packet->side_data[x].size,
395
+ p->packet->side_data[x].data, &resultData, &element);
396
+ CHECK_STATUS;
397
+ status = napi_set_named_property(env, result,
398
+ beam_lookup_name(beam_packet_side_data_type->forward,
399
+ p->packet->side_data[x].type), element);
400
+ CHECK_STATUS;
401
+ }
402
+ }
403
+
404
+ return result;
405
+ }
406
+
407
+ napi_value setPacketSideData(napi_env env, napi_callback_info info) {
408
+ napi_status status;
409
+ napi_value result, global, jsBuffer, jsBufferFrom, name, names, element, arrayData;
410
+ napi_valuetype type;
411
+ bool isArray, isBuffer;
412
+ uint32_t sdCount;
413
+ packetData* p;
414
+ char* typeName;
415
+ size_t strLen;
416
+ int psdt;
417
+ void* rawdata;
418
+ size_t rawdataSize;
419
+
420
+ size_t argc = 1;
421
+ napi_value args[1];
422
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
423
+ CHECK_STATUS;
424
+ if (argc < 1) {
425
+ NAPI_THROW_ERROR("A value is required to set side_data property.");
426
+ }
427
+
428
+ status = napi_get_global(env, &global);
429
+ CHECK_STATUS;
430
+ status = napi_get_named_property(env, global, "Buffer", &jsBuffer);
431
+ CHECK_STATUS;
432
+ status = napi_get_named_property(env, jsBuffer, "from", &jsBufferFrom);
433
+ CHECK_STATUS;
434
+
435
+ status = napi_typeof(env, args[0], &type);
436
+ CHECK_STATUS;
437
+ status = napi_is_array(env, args[0], &isArray);
438
+ CHECK_STATUS;
439
+
440
+ switch (type) {
441
+ case napi_object:
442
+ case napi_null:
443
+ case napi_undefined:
444
+ av_packet_free_side_data(p->packet);
445
+ if (type != napi_object) { goto done; };
446
+ break;
447
+ default:
448
+ NAPI_THROW_ERROR("Packet side_data property requires an object with Buffer-valued properties.");
449
+ }
450
+
451
+ status = napi_get_property_names(env, args[0], &names);
452
+ CHECK_STATUS;
453
+ status = napi_get_array_length(env, names, &sdCount);
454
+ CHECK_STATUS;
455
+
456
+ for ( uint32_t x = 0 ; x < sdCount ; x++ ) {
457
+ status = napi_get_element(env, names, x, &name);
458
+ CHECK_STATUS;
459
+ status = napi_get_property(env, args[0], name, &element);
460
+ CHECK_STATUS;
461
+ status = napi_is_buffer(env, element, &isBuffer);
462
+ CHECK_STATUS;
463
+ if (!isBuffer) {
464
+ status = napi_get_named_property(env, element, "data", &arrayData);
465
+ CHECK_STATUS;
466
+ // TODO more checks that this is a buffer from JSON?
467
+ status = napi_is_array(env, arrayData, &isArray);
468
+ CHECK_STATUS;
469
+ if (isArray) {
470
+ const napi_value fargs[] = { arrayData };
471
+ status = napi_call_function(env, element, jsBufferFrom, 1, fargs, &element);
472
+ CHECK_STATUS;
473
+ } else {
474
+ continue;
475
+ }
476
+ }
477
+ status = napi_get_value_string_utf8(env, name, nullptr, 0, &strLen);
478
+ CHECK_STATUS;
479
+ typeName = (char*) malloc(sizeof(char) * (strLen + 1));
480
+ status = napi_get_value_string_utf8(env, name, typeName, strLen + 1, &strLen);
481
+ CHECK_STATUS;
482
+
483
+ psdt = beam_lookup_enum(beam_packet_side_data_type->inverse, typeName);
484
+ free(typeName);
485
+ if (psdt == BEAM_ENUM_UNKNOWN) {
486
+ continue;
487
+ } else {
488
+ status = napi_get_buffer_info(env, element, &rawdata, &rawdataSize);
489
+ CHECK_STATUS;
490
+ uint8_t* pktdata = av_packet_new_side_data(p->packet,
491
+ (AVPacketSideDataType) psdt, rawdataSize);
492
+ if (pktdata != nullptr) {
493
+ memcpy(pktdata, rawdata, rawdataSize);
494
+ }
495
+ }
496
+ }
497
+
498
+ done:
499
+ status = napi_get_undefined(env, &result);
500
+ CHECK_STATUS;
501
+ return result;
502
+ }
503
+
504
+ napi_value getPacketDuration(napi_env env, napi_callback_info info) {
505
+ napi_status status;
506
+ napi_value result;
507
+ packetData* p;
508
+
509
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
510
+ CHECK_STATUS;
511
+
512
+ status = napi_create_int64(env, p->packet->duration, &result);
513
+ CHECK_STATUS;
514
+ return result;
515
+ }
516
+
517
+ napi_value setPacketDuration(napi_env env, napi_callback_info info) {
518
+ napi_status status;
519
+ napi_value result;
520
+ napi_valuetype type;
521
+ packetData* p;
522
+
523
+ size_t argc = 1;
524
+ napi_value args[1];
525
+
526
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
527
+ CHECK_STATUS;
528
+ if (argc < 1) {
529
+ NAPI_THROW_ERROR("Set packet duration must be provided with a value.");
530
+ }
531
+ status = napi_typeof(env, args[0], &type);
532
+ CHECK_STATUS;
533
+ if (type != napi_number) {
534
+ NAPI_THROW_ERROR("Packet duration property must be set with a number.");
535
+ }
536
+ status = napi_get_value_int64(env, args[0], &p->packet->duration);
537
+ CHECK_STATUS;
538
+
539
+ status = napi_get_undefined(env, &result);
540
+ CHECK_STATUS;
541
+ return result;
542
+ }
543
+
544
+ napi_value getPacketPos(napi_env env, napi_callback_info info) {
545
+ napi_status status;
546
+ napi_value result;
547
+ packetData* p;
548
+
549
+ status = napi_get_cb_info(env, info, 0, nullptr, nullptr, (void**) &p);
550
+ CHECK_STATUS;
551
+
552
+ status = napi_create_int64(env, p->packet->pos, &result);
553
+ CHECK_STATUS;
554
+ return result;
555
+ }
556
+
557
+ napi_value setPacketPos(napi_env env, napi_callback_info info) {
558
+ napi_status status;
559
+ napi_value result;
560
+ napi_valuetype type;
561
+ packetData* p;
562
+
563
+ size_t argc = 1;
564
+ napi_value args[1];
565
+
566
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, (void**) &p);
567
+ CHECK_STATUS;
568
+ if (argc < 1) {
569
+ NAPI_THROW_ERROR("Set packet pos must be provided with a value.");
570
+ }
571
+ status = napi_typeof(env, args[0], &type);
572
+ CHECK_STATUS;
573
+ if (type != napi_number) {
574
+ NAPI_THROW_ERROR("Packet pos property must be set with a number.");
575
+ }
576
+ status = napi_get_value_int64(env, args[0], &p->packet->pos);
577
+ CHECK_STATUS;
578
+
579
+ status = napi_get_undefined(env, &result);
580
+ CHECK_STATUS;
581
+ return result;
582
+ }
583
+
584
+ napi_value makePacket(napi_env env, napi_callback_info info) {
585
+ napi_status status;
586
+ napi_value result, global, jsObject, assign, jsJSON, jsParse;
587
+ napi_valuetype type;
588
+ bool isArray, deleted;
589
+ packetData* p = new packetData;
590
+ p->packet = av_packet_alloc();
591
+
592
+ status = napi_get_global(env, &global);
593
+ CHECK_STATUS;
594
+
595
+ size_t argc = 1;
596
+ napi_value args[1];
597
+
598
+ status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
599
+ CHECK_STATUS;
600
+ if (argc > 1) {
601
+ NAPI_THROW_ERROR("Packet may be created with zero or one options object argument.");
602
+ }
603
+ if (argc == 1) {
604
+ status = napi_typeof(env, args[0], &type);
605
+ CHECK_STATUS;
606
+ if (type == napi_string) {
607
+ status = napi_get_named_property(env, global, "JSON", &jsJSON);
608
+ CHECK_STATUS;
609
+ status = napi_get_named_property(env, jsJSON, "parse", &jsParse);
610
+ CHECK_STATUS;
611
+ const napi_value pargs[] = { args[0] };
612
+ status = napi_call_function(env, args[0], jsParse, 1, pargs, &args[0]);
613
+ CHECK_STATUS;
614
+ status = napi_typeof(env, args[0], &type);
615
+ CHECK_STATUS;
616
+ if (type == napi_object) {
617
+ status = beam_delete_named_property(env, args[0], "type", &deleted);
618
+ CHECK_STATUS;
619
+ }
620
+ }
621
+ status = napi_is_array(env, args[0], &isArray);
622
+ CHECK_STATUS;
623
+ if (isArray || (type != napi_object)) {
624
+ NAPI_THROW_ERROR("Cannot create a packet unless argument is an object.");
625
+ }
626
+ }
627
+
628
+ status = fromAVPacket(env, p, &result);
629
+ CHECK_STATUS;
630
+
631
+ if (argc == 1) {
632
+ status = napi_get_named_property(env, global, "Object", &jsObject);
633
+ CHECK_STATUS;
634
+ status = napi_get_named_property(env, jsObject, "assign", &assign);
635
+ CHECK_STATUS;
636
+ const napi_value fargs[] = { result, args[0] };
637
+ status = napi_call_function(env, result, assign, 2, fargs, &result);
638
+ CHECK_STATUS;
639
+ }
640
+
641
+ return result;
642
+ }
643
+
644
+ napi_value getPacketTypeName(napi_env env, napi_callback_info info) {
645
+ napi_status status;
646
+ napi_value result;
647
+
648
+ status = napi_create_string_utf8(env, "Packet", NAPI_AUTO_LENGTH, &result);
649
+ CHECK_STATUS;
650
+
651
+ return result;
652
+ }
653
+
654
+ napi_value packetToJSON(napi_env env, napi_callback_info info) {
655
+ napi_status status;
656
+ napi_value result, base;
657
+ packetData* p;
658
+ int count = 0;
659
+
660
+ size_t argc = 0;
661
+ status = napi_get_cb_info(env, info, &argc, nullptr, &base, (void**) &p);
662
+ CHECK_STATUS;
663
+
664
+ status = napi_create_object(env, &result);
665
+ CHECK_STATUS;
666
+
667
+ napi_property_descriptor desc[10];
668
+ DECLARE_GETTER3("type", true, getPacketTypeName, p);
669
+ DECLARE_GETTER3("pts", p->packet->pts != AV_NOPTS_VALUE, getPacketPts, p);
670
+ DECLARE_GETTER3("dts", p->packet->dts != AV_NOPTS_VALUE, getPacketDts, p);
671
+ DECLARE_GETTER3("size", p->packet->size > 0, getPacketSize, p);
672
+ DECLARE_GETTER3("stream_index", true, getPacketStreamIndex, p);
673
+ DECLARE_GETTER3("flags", p->packet->flags > 0, getPacketFlags, p);
674
+ DECLARE_GETTER3("side_data", p->packet->side_data != nullptr, getPacketSideData, p);
675
+ DECLARE_GETTER3("duration", p->packet->duration > 0, getPacketDuration, p);
676
+ DECLARE_GETTER3("pos", p->packet->pos > 0, getPacketPos, p);
677
+
678
+ status = napi_define_properties(env, result, count, desc);
679
+ CHECK_STATUS;
680
+
681
+ return result;
682
+ }
683
+
684
+ napi_status fromAVPacket(napi_env env, packetData* p, napi_value* result) {
685
+ napi_status status;
686
+ napi_value jsPacket, extPacket, typeName;
687
+ int64_t externalMemory;
688
+
689
+ status = napi_create_object(env, &jsPacket);
690
+ PASS_STATUS;
691
+ status = napi_create_string_utf8(env, "Packet", NAPI_AUTO_LENGTH, &typeName);
692
+ PASS_STATUS;
693
+ status = napi_create_external(env, p, packetDataFinalizer, nullptr, &extPacket);
694
+ PASS_STATUS;
695
+
696
+ napi_property_descriptor desc[] = {
697
+ { "type", nullptr, nullptr, getPacketTypeName, nop, nullptr,
698
+ (napi_property_attributes) (napi_writable | napi_enumerable), nullptr },
699
+ { "pts", nullptr, nullptr, getPacketPts, setPacketPts, nullptr,
700
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
701
+ { "dts", nullptr, nullptr, getPacketDts, setPacketDts, nullptr,
702
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
703
+ { "data", nullptr, nullptr, getPacketData, setPacketData, nullptr,
704
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
705
+ { "size", nullptr, nullptr, getPacketSize, setPacketSize, nullptr,
706
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
707
+ { "stream_index", nullptr, nullptr, getPacketStreamIndex, setPacketStreamIndex, nullptr,
708
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
709
+ { "flags", nullptr, nullptr, getPacketFlags, setPacketFlags, nullptr,
710
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
711
+ { "side_data", nullptr, nullptr, getPacketSideData, setPacketSideData, nullptr,
712
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
713
+ { "duration", nullptr, nullptr, getPacketDuration, setPacketDuration, nullptr,
714
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
715
+ // 10
716
+ { "pos", nullptr, nullptr, getPacketPos, setPacketPos, nullptr,
717
+ (napi_property_attributes) (napi_writable | napi_enumerable), p },
718
+ { "toJSON", nullptr, packetToJSON, nullptr, nullptr, nullptr, napi_default, p },
719
+ { "_packet", nullptr, nullptr, nullptr, nullptr, extPacket, napi_default, nullptr }
720
+ };
721
+ status = napi_define_properties(env, jsPacket, 12, desc);
722
+ PASS_STATUS;
723
+
724
+ if (p->packet->buf != nullptr) {
725
+ p->extSize = p->packet->buf->size;
726
+ // printf("Size of buffer is %i\n", p->extSize);
727
+ status = napi_adjust_external_memory(env, p->extSize, &externalMemory);
728
+ PASS_STATUS;
729
+ }
730
+
731
+ *result = jsPacket;
732
+ return napi_ok;
733
+ }
734
+
735
+ void packetFinalizer(napi_env env, void* data, void* hint) {
736
+ AVPacket* pkt = (AVPacket*) data;
737
+ av_packet_free(&pkt);
738
+ }
739
+
740
+ void packetDataFinalizer(napi_env env, void* data, void* hint) {
741
+ napi_status status;
742
+ napi_ref dataRef;
743
+ int64_t externalMemory;
744
+ packetData* p = (packetData*) data;
745
+ dataRef = p->dataRef;
746
+ status = napi_adjust_external_memory(env, -p->extSize, &externalMemory);
747
+ if (status != napi_ok) {
748
+ printf("DEBUG: Failed to adjust external memory downwards on packet delete.\n");
749
+ }
750
+ delete p;
751
+ if (dataRef != nullptr) {
752
+ status = napi_delete_reference(env, dataRef);
753
+ if (status != napi_ok) {
754
+ printf("DEBUG: Failed to delete data reference for packet data, status %i.\n", status);
755
+ }
756
+ }
757
+ }
758
+
759
+ void packetBufferFinalizer(napi_env env, void* data, void* hint) {
760
+ AVBufferRef* hintRef = (AVBufferRef*) hint;
761
+ av_buffer_unref(&hintRef);
762
+ };