bare-ffmpeg 1.0.0-21 → 1.0.0-23

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 CHANGED
@@ -8,7 +8,7 @@ project(bare_ffmpeg C CXX)
8
8
 
9
9
  fetch_package("github:holepunchto/libjstl#5b85a24")
10
10
 
11
- find_port(ffmpeg FEATURES gpl dav1d svt-av1 x264 opus)
11
+ find_port(ffmpeg FEATURES dav1d svt-av1 opus)
12
12
 
13
13
  add_bare_module(bare_ffmpeg)
14
14
 
package/README.md CHANGED
@@ -108,6 +108,21 @@ for (const [key, value] of dict) {
108
108
  }
109
109
  ```
110
110
 
111
+ #### Static methods
112
+
113
+ ##### `Dictionary.from(object)`
114
+
115
+ A helper to create a `Dictionary` instance from an object.
116
+
117
+ ```js
118
+ const dict = ffmpeg.Dictionary.from({
119
+ foo: 'bar',
120
+ baz: 'qux'
121
+ })
122
+ ```
123
+
124
+ **Returns**: A new `Dictionary` instance
125
+
111
126
  ### `FormatContext`
112
127
 
113
128
  The `FormatContext` API provides the base functionality for reading and writing media files.
@@ -600,15 +615,9 @@ Gets or sets the frame height.
600
615
 
601
616
  **Returns**: `number`
602
617
 
603
- ##### `Frame.pixelFormat`
604
-
605
- Gets or sets the pixel format.
606
-
607
- **Returns**: `number` (pixel format constant)
608
-
609
618
  ##### `Frame.format`
610
619
 
611
- Gets or sets the sample format for audio frames.
620
+ Gets or sets the format of the frame, `-1` if unknown or unset.
612
621
 
613
622
  **Returns**: `number` (sample format constant)
614
623
 
@@ -852,17 +861,47 @@ Parameters:
852
861
 
853
862
  #### Properties
854
863
 
864
+ ##### `Stream.id`
865
+
866
+ Gets or sets the stream ID.
867
+
868
+ **Returns**: `number`
869
+
870
+ ##### `Stream.index`
871
+
872
+ Gets the stream index.
873
+
874
+ **Returns**: `number`
875
+
876
+ ##### `Stream.codec`
877
+
878
+ Gets the codec for this stream.
879
+
880
+ **Returns**: `Codec` instance
881
+
855
882
  ##### `Stream.codecParameters`
856
883
 
857
884
  Gets the codec parameters for this stream.
858
885
 
859
886
  **Returns**: `CodecParameters` instance
860
887
 
861
- ##### `Stream.codec`
888
+ ##### `Stream.timeBase`
862
889
 
863
- Gets the codec for this stream
890
+ Gets or sets the time base for the stream.
864
891
 
865
- **Returns**: `Codec` instance
892
+ **Returns**: `Rational` instance
893
+
894
+ ##### `Stream.avgFramerate`
895
+
896
+ Gets or sets the average framerate for video streams.
897
+
898
+ **Returns**: `Rational` instance
899
+
900
+ Example:
901
+
902
+ ```js
903
+ const fps = stream.avgFramerate.toNumber()
904
+ ```
866
905
 
867
906
  #### Methods
868
907
 
package/binding.cc CHANGED
@@ -1,14 +1,13 @@
1
- #include <assert.h>
2
- #include <cstdint>
3
- #include <stddef.h>
4
- #include <stdint.h>
5
- #include <string.h>
6
1
  #include <tuple>
7
2
  #include <vector>
8
3
 
4
+ #include <assert.h>
9
5
  #include <bare.h>
10
6
  #include <js.h>
11
7
  #include <jstl.h>
8
+ #include <stddef.h>
9
+ #include <stdint.h>
10
+ #include <string.h>
12
11
 
13
12
  extern "C" {
14
13
  #include <libavcodec/avcodec.h>
@@ -34,13 +33,18 @@ extern "C" {
34
33
  #include <libswscale/swscale.h>
35
34
  }
36
35
 
37
- using bare_ffmpeg_io_context_on_write_cb_t = js_function_t<void, js_arraybuffer_t>;
36
+ using bare_ffmpeg_io_context_write_cb_t = js_function_t<void, js_typedarray_t<uint8_t>>;
37
+ using bare_ffmpeg_io_context_read_cb_t = js_function_t<int32_t, js_typedarray_t<uint8_t>, int32_t>;
38
+ using bare_ffmpeg_io_context_seek_cb_t = js_function_t<int64_t, int64_t, std::string>;
38
39
 
39
40
  typedef struct {
40
41
  AVIOContext *handle;
41
42
 
42
43
  js_env_t *env;
43
- js_persistent_t<bare_ffmpeg_io_context_on_write_cb_t> on_write;
44
+
45
+ js_persistent_t<bare_ffmpeg_io_context_write_cb_t> on_write;
46
+ js_persistent_t<bare_ffmpeg_io_context_read_cb_t> on_read;
47
+ js_persistent_t<bare_ffmpeg_io_context_seek_cb_t> on_seek;
44
48
  } bare_ffmpeg_io_context_t;
45
49
 
46
50
  typedef struct {
@@ -102,9 +106,9 @@ typedef struct {
102
106
  static uv_once_t bare_ffmpeg__init_guard = UV_ONCE_INIT;
103
107
 
104
108
  static inline bool
105
- bad_timebase(const AVRational r) {
106
- return r.den < 1 || // invalid denominator
107
- av_q2d(r) == 0; // detect initial state: (0 / 1)
109
+ bare_ffmpeg__bad_timebase(const AVRational r) {
110
+ return r.den < 1 || // Invalid denominator
111
+ av_q2d(r) == 0; // Initial state (0 / 1)
108
112
  }
109
113
 
110
114
  static void
@@ -125,24 +129,107 @@ bare_ffmpeg_log_set_level(js_env_t *, int32_t level) {
125
129
  }
126
130
 
127
131
  static int
128
- io_context_write_packet(void *opaque, const uint8_t *chunk, int len) {
132
+ bare_ffmpeg__on_io_context_write(void *opaque, const uint8_t *buf, int len) {
133
+ int err;
134
+
135
+ auto context = static_cast<bare_ffmpeg_io_context_t *>(opaque);
136
+
137
+ auto env = context->env;
138
+
139
+ bare_ffmpeg_io_context_write_cb_t callback;
140
+ err = js_get_reference_value(env, context->on_write, callback);
141
+ assert(err == 0);
142
+
143
+ js_arraybuffer_t data;
144
+ err = js_create_arraybuffer(env, buf, static_cast<size_t>(len), data);
145
+ assert(err == 0);
146
+
147
+ js_typedarray_t<uint8_t> view;
148
+ err = js_create_typedarray(env, static_cast<size_t>(len), data, view);
149
+ assert(err == 0);
150
+
151
+
152
+ err = js_call_function(env, callback, view);
153
+ assert(err == 0);
154
+
155
+ return 0;
156
+ }
157
+
158
+ static int
159
+ bare_ffmpeg__on_io_context_read(void *opaque, uint8_t *buf, int len) {
160
+ int err;
161
+
129
162
  auto context = reinterpret_cast<bare_ffmpeg_io_context_t *>(opaque);
163
+
130
164
  auto env = context->env;
131
165
 
132
- bare_ffmpeg_io_context_on_write_cb_t callback;
166
+ bare_ffmpeg_io_context_read_cb_t callback;
167
+ err = js_get_reference_value(env, context->on_read, callback);
168
+ assert(err == 0);
133
169
 
134
- int err = js_get_reference_value(env, context->on_write, callback);
170
+ js_arraybuffer_t arraybuffer;
171
+ err = js_create_external_arraybuffer(env, buf, static_cast<size_t>(len), arraybuffer);
135
172
  assert(err == 0);
136
173
 
137
- js_arraybuffer_t data;
138
- err = js_create_arraybuffer(env, chunk, static_cast<size_t>(len), data);
174
+ js_typedarray_t<uint8_t> view;
175
+ err = js_create_typedarray(env, static_cast<size_t>(len), arraybuffer, view);
176
+ assert(err == 0);
177
+
178
+ int32_t result;
179
+ int call_status = js_call_function<js_type_options_t{}, int32_t, js_typedarray_t<uint8_t>, int32_t>(env, callback, view, len, result);
139
180
 
181
+ err = js_detach_arraybuffer(env, arraybuffer);
140
182
  assert(err == 0);
141
183
 
142
- // TODO: running on js-stack during avformat_write_header()
143
- // trace other invocations, pray singlethread.
144
- err = js_call_function(env, callback, data);
145
- return err;
184
+ if (call_status < 0) return AVERROR(EIO);
185
+
186
+ if (result == 0) return AVERROR_EOF;
187
+
188
+ return result;
189
+ }
190
+
191
+ static int64_t
192
+ bare_ffmpeg__on_io_context_seek(void *opaque, int64_t offset, int whence) {
193
+ int err;
194
+
195
+ auto context = reinterpret_cast<bare_ffmpeg_io_context_t *>(opaque);
196
+
197
+ auto env = context->env;
198
+
199
+ int64_t result;
200
+ std::string whence_str;
201
+ switch (whence) {
202
+ case AVSEEK_SIZE:
203
+ whence_str = "avseek_size";
204
+ break;
205
+ case AVSEEK_FORCE:
206
+ whence_str = "avseek_force";
207
+ break;
208
+ case SEEK_SET:
209
+ whence_str = "seek_set";
210
+ break;
211
+ case SEEK_CUR:
212
+ whence_str = "seek_cur";
213
+ break;
214
+ case SEEK_END:
215
+ whence_str = "seek_end";
216
+ break;
217
+ default:
218
+ whence_str = "unknown:" + std::to_string(whence);
219
+ }
220
+
221
+ bare_ffmpeg_io_context_seek_cb_t callback;
222
+ err = js_get_reference_value(env, context->on_seek, callback);
223
+ assert(err == 0);
224
+
225
+ err = js_call_function<js_type_options_t{}, int64_t, int64_t, std::string>(env, callback, offset, whence_str, result);
226
+ if (err < 0) return AVERROR(EIO); // read-error
227
+
228
+ if (result == -1) {
229
+ return AVERROR(ENOSYS); // seek-op not supported by IO
230
+ }
231
+
232
+ return result;
146
233
  }
147
234
 
148
235
  static js_arraybuffer_t
@@ -152,7 +239,9 @@ bare_ffmpeg_io_context_init(
152
239
  std::optional<js_arraybuffer_span_t> data,
153
240
  uint64_t offset,
154
241
  uint64_t len,
155
- std::optional<bare_ffmpeg_io_context_on_write_cb_t> on_write
242
+ std::optional<bare_ffmpeg_io_context_write_cb_t> on_write,
243
+ std::optional<bare_ffmpeg_io_context_read_cb_t> on_read,
244
+ std::optional<bare_ffmpeg_io_context_seek_cb_t> on_seek
156
245
  ) {
157
246
  int err;
158
247
 
@@ -164,37 +253,46 @@ bare_ffmpeg_io_context_init(
164
253
 
165
254
  context->env = env;
166
255
 
167
- int write_flag = 0;
256
+ int writable = 0;
257
+
168
258
  if (on_write) {
169
- write_flag = 1;
259
+ writable = 1;
260
+
170
261
  err = js_create_reference(env, *on_write, context->on_write);
171
262
  assert(err == 0);
172
263
  }
173
264
 
174
- size_t size = static_cast<size_t>(len);
175
-
176
- uint8_t *io = NULL;
265
+ if (on_read) {
266
+ err = js_create_reference(env, *on_read, context->on_read);
267
+ assert(err == 0);
268
+ }
177
269
 
178
- if (size) {
179
- io = reinterpret_cast<uint8_t *>(av_malloc(size));
270
+ if (on_seek) {
271
+ err = js_create_reference(env, *on_seek, context->on_seek);
272
+ assert(err == 0);
180
273
  }
181
274
 
275
+ auto size = static_cast<size_t>(len);
276
+
277
+ auto io = reinterpret_cast<uint8_t *>(av_malloc(size));
278
+
182
279
  if (data) {
183
280
  memcpy(io, &data.value()[static_cast<size_t>(offset)], size);
184
281
  }
185
282
 
186
- // TODO: for stream read support provide read/seek callbacks
187
-
188
283
  context->handle = avio_alloc_context(
189
284
  io,
190
285
  static_cast<int>(len),
191
- write_flag,
286
+ writable,
192
287
  context,
193
- NULL, // io_context_read_packet
194
- io_context_write_packet,
195
- NULL // io_context_seek
288
+ on_read ? bare_ffmpeg__on_io_context_read : nullptr,
289
+ on_write ? bare_ffmpeg__on_io_context_write : nullptr,
290
+ on_seek ? bare_ffmpeg__on_io_context_seek : nullptr
196
291
  );
197
- assert(context->handle->opaque == context);
292
+
293
+ if (!on_seek) {
294
+ context->handle->seekable = 0;
295
+ }
198
296
 
199
297
  return handle;
200
298
  }
@@ -208,7 +306,10 @@ bare_ffmpeg_io_context_destroy(
208
306
  av_free(context->handle->buffer);
209
307
 
210
308
  avio_context_free(&context->handle);
309
+
211
310
  context->on_write.reset();
311
+ context->on_read.reset();
312
+ context->on_seek.reset();
212
313
  }
213
314
 
214
315
  static js_arraybuffer_t
@@ -415,7 +516,7 @@ bare_ffmpeg_format_context_get_streams(
415
516
  ) {
416
517
  int err;
417
518
 
418
- uint32_t len = context->handle->nb_streams;
519
+ auto len = context->handle->nb_streams;
419
520
 
420
521
  js_array_t result;
421
522
  err = js_create_array(env, len, result);
@@ -497,15 +598,14 @@ bare_ffmpeg_format_context_write_header(
497
598
  js_env_t *env,
498
599
  js_receiver_t,
499
600
  js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context,
500
- std::optional<js_arraybuffer_span_of_t<bare_ffmpeg_dictionary_t, 1>> muxer_options
601
+ std::optional<js_arraybuffer_span_of_t<bare_ffmpeg_dictionary_t, 1>> options
501
602
  ) {
502
603
  int err;
503
604
 
504
- if (!muxer_options) {
505
- err = avformat_write_header(context->handle, NULL);
605
+ if (options) {
606
+ err = avformat_write_header(context->handle, &options.value()->handle);
506
607
  } else {
507
- auto dict = *muxer_options;
508
- err = avformat_write_header(context->handle, &dict->handle);
608
+ err = avformat_write_header(context->handle, NULL);
509
609
  }
510
610
 
511
611
  if (err < 0) {
@@ -517,6 +617,7 @@ bare_ffmpeg_format_context_write_header(
517
617
 
518
618
  return err;
519
619
  }
620
+
520
621
  static void
521
622
  bare_ffmpeg_format_context_write_frame(
522
623
  js_env_t *env,
@@ -524,8 +625,9 @@ bare_ffmpeg_format_context_write_frame(
524
625
  js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context,
525
626
  js_arraybuffer_span_of_t<bare_ffmpeg_packet_t, 1> packet
526
627
  ) {
527
- int err = av_interleaved_write_frame(context->handle, packet->handle);
628
+ int err;
528
629
 
630
+ err = av_interleaved_write_frame(context->handle, packet->handle);
529
631
  if (err < 0) {
530
632
  err = js_throw_error(env, NULL, av_err2str(err));
531
633
  assert(err == 0);
@@ -540,7 +642,9 @@ bare_ffmpeg_format_context_write_trailer(
540
642
  js_receiver_t,
541
643
  js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context
542
644
  ) {
543
- int err = av_write_trailer(context->handle);
645
+ int err;
646
+
647
+ err = av_write_trailer(context->handle);
544
648
  if (err < 0) {
545
649
  err = js_throw_error(env, NULL, av_err2str(err));
546
650
  assert(err == 0);
@@ -562,6 +666,7 @@ bare_ffmpeg_format_context_dump(
562
666
 
563
667
  for (int i = 0; i < context->handle->nb_streams; i++) {
564
668
  auto stream = context->handle->streams[i];
669
+
565
670
  av_log(NULL, AV_LOG_INFO, " - stream=%i timebase=(%i / %i)\n", i, stream->time_base.num, stream->time_base.den);
566
671
  }
567
672
  }
@@ -770,7 +875,6 @@ bare_ffmpeg_codec_context_open(
770
875
  int err;
771
876
 
772
877
  err = avcodec_open2(context->handle, context->handle->codec, NULL);
773
-
774
878
  if (err < 0) {
775
879
  err = js_throw_error(env, NULL, av_err2str(err));
776
880
  assert(err == 0);
@@ -800,7 +904,7 @@ bare_ffmpeg_codec_context_set_flags(
800
904
  context->handle->flags = value;
801
905
  }
802
906
 
803
- static int64_t
907
+ static int
804
908
  bare_ffmpeg_frame_get_format(
805
909
  js_env_t *env,
806
910
  js_receiver_t,
@@ -1133,7 +1237,7 @@ bare_ffmpeg_codec_context_send_frame(
1133
1237
  int err;
1134
1238
 
1135
1239
  if (frame) {
1136
- err = avcodec_send_frame(context->handle, (*frame)->handle);
1240
+ err = avcodec_send_frame(context->handle, frame.value()->handle);
1137
1241
  } else {
1138
1242
  err = avcodec_send_frame(context->handle, NULL); // End of stream
1139
1243
  }
@@ -1178,7 +1282,6 @@ bare_ffmpeg_codec_parameters_from_context(
1178
1282
  int err;
1179
1283
 
1180
1284
  err = avcodec_parameters_from_context(parameters->handle, context->handle);
1181
-
1182
1285
  if (err < 0) {
1183
1286
  err = js_throw_error(env, NULL, av_err2str(err));
1184
1287
  assert(err == 0);
@@ -1213,6 +1316,7 @@ bare_ffmpeg_codec_parameters_alloc(
1213
1316
  int err;
1214
1317
 
1215
1318
  js_arraybuffer_t handle;
1319
+
1216
1320
  bare_ffmpeg_codec_parameters_t *parameters;
1217
1321
  err = js_create_arraybuffer(env, parameters, handle);
1218
1322
  assert(err == 0);
@@ -1578,7 +1682,6 @@ bare_ffmpeg_codec_parameters_set_extra_data(
1578
1682
  int err;
1579
1683
 
1580
1684
  std::span<uint8_t> view;
1581
-
1582
1685
  err = js_get_arraybuffer_info(env, buffer, view);
1583
1686
  assert(err == 0);
1584
1687
 
@@ -1592,6 +1695,7 @@ bare_ffmpeg_codec_parameters_set_extra_data(
1592
1695
  size_t min_size = len + AV_INPUT_BUFFER_PADDING_SIZE;
1593
1696
 
1594
1697
  parameters->handle->extradata = reinterpret_cast<uint8_t *>(av_malloc(min_size));
1698
+
1595
1699
  memset(&parameters->handle->extradata[len], 0, AV_INPUT_BUFFER_PADDING_SIZE);
1596
1700
 
1597
1701
  memcpy(parameters->handle->extradata, &view[offset], len);
@@ -1797,25 +1901,6 @@ bare_ffmpeg_frame_set_height(
1797
1901
  frame->handle->height = height;
1798
1902
  }
1799
1903
 
1800
- static int64_t
1801
- bare_ffmpeg_frame_get_pixel_format(
1802
- js_env_t *env,
1803
- js_receiver_t,
1804
- js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
1805
- ) {
1806
- return frame->handle->format;
1807
- }
1808
-
1809
- static void
1810
- bare_ffmpeg_frame_set_pixel_format(
1811
- js_env_t *env,
1812
- js_receiver_t,
1813
- js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame,
1814
- int32_t format
1815
- ) {
1816
- frame->handle->format = static_cast<AVPixelFormat>(format);
1817
- }
1818
-
1819
1904
  static int32_t
1820
1905
  bare_ffmpeg_frame_get_nb_samples(
1821
1906
  js_env_t *env,
@@ -1909,6 +1994,7 @@ bare_ffmpeg_frame_get_time_base(
1909
1994
 
1910
1995
  return result;
1911
1996
  }
1997
+
1912
1998
  static void
1913
1999
  bare_ffmpeg_frame_set_time_base(
1914
2000
  js_env_t *env,
@@ -2015,10 +2101,12 @@ bare_ffmpeg_image_read(
2015
2101
  uint64_t offset,
2016
2102
  js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
2017
2103
  ) {
2104
+ int err;
2105
+
2018
2106
  uint8_t *dst_data[4];
2019
2107
  int dst_linesize[4];
2020
2108
 
2021
- int err = av_image_fill_arrays(
2109
+ auto len = av_image_fill_arrays(
2022
2110
  dst_data,
2023
2111
  dst_linesize,
2024
2112
  &data[offset],
@@ -2027,7 +2115,13 @@ bare_ffmpeg_image_read(
2027
2115
  height,
2028
2116
  align
2029
2117
  );
2030
- assert(err >= 0);
2118
+
2119
+ if (len < 0) {
2120
+ err = js_throw_error(env, NULL, av_err2str(len));
2121
+ assert(err == 0);
2122
+
2123
+ throw js_pending_exception;
2124
+ }
2031
2125
 
2032
2126
  av_image_copy(
2033
2127
  dst_data,
@@ -2174,6 +2268,15 @@ bare_ffmpeg_packet_unref(
2174
2268
  av_packet_unref(packet->handle);
2175
2269
  }
2176
2270
 
2271
+ static void
2272
+ bare_ffmpeg_packet_destroy(
2273
+ js_env_t *env,
2274
+ js_receiver_t,
2275
+ js_arraybuffer_span_of_t<bare_ffmpeg_packet_t, 1> packet
2276
+ ) {
2277
+ av_packet_free(&packet->handle);
2278
+ }
2279
+
2177
2280
  static int32_t
2178
2281
  bare_ffmpeg_packet_get_stream_index(
2179
2282
  js_env_t *env,
@@ -2224,6 +2327,7 @@ bare_ffmpeg_packet_set_data(
2224
2327
  uint32_t len
2225
2328
  ) {
2226
2329
  int err;
2330
+
2227
2331
  assert(offset + len <= data.size());
2228
2332
 
2229
2333
  av_packet_unref(packet->handle);
@@ -2329,11 +2433,11 @@ bare_ffmpeg_packet_rescale_ts(
2329
2433
  int32_t den
2330
2434
  ) {
2331
2435
  AVRational src = packet->handle->time_base;
2332
- AVRational dst = {.num = num, .den = den};
2436
+ AVRational dst = {num, den};
2333
2437
 
2334
2438
  if (
2335
- bad_timebase(src) ||
2336
- bad_timebase(dst) ||
2439
+ bare_ffmpeg__bad_timebase(src) ||
2440
+ bare_ffmpeg__bad_timebase(dst) ||
2337
2441
  packet->handle->dts == AV_NOPTS_VALUE ||
2338
2442
  packet->handle->pts == AV_NOPTS_VALUE
2339
2443
  ) {
@@ -2439,7 +2543,9 @@ bare_ffmpeg_scaler_scale(
2439
2543
  int height,
2440
2544
  js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> target
2441
2545
  ) {
2442
- int err = av_frame_copy_props(target->handle, source->handle);
2546
+ int err;
2547
+
2548
+ err = av_frame_copy_props(target->handle, source->handle);
2443
2549
  assert(err == 0);
2444
2550
 
2445
2551
  return sws_scale(
@@ -2503,6 +2609,7 @@ bare_ffmpeg_dictionary_get_entries(
2503
2609
  std::vector<std::tuple<const char *, const char *>> entries{};
2504
2610
 
2505
2611
  const AVDictionaryEntry *entry = nullptr;
2612
+
2506
2613
  while ((entry = av_dict_iterate(dict->handle, entry))) {
2507
2614
  entries.emplace_back(entry->key, entry->value);
2508
2615
  }
@@ -2760,11 +2867,12 @@ bare_ffmpeg_audio_fifo_write(
2760
2867
  ) {
2761
2868
  int err;
2762
2869
 
2763
- int len = av_audio_fifo_write(fifo->handle, (void **) frame->handle->data, frame->handle->nb_samples);
2870
+ auto len = av_audio_fifo_write(fifo->handle, (void **) frame->handle->data, frame->handle->nb_samples);
2764
2871
 
2765
2872
  if (len < 0) {
2766
2873
  err = js_throw_error(env, NULL, av_err2str(len));
2767
2874
  assert(err == 0);
2875
+
2768
2876
  throw js_pending_exception;
2769
2877
  }
2770
2878
 
@@ -2781,11 +2889,12 @@ bare_ffmpeg_audio_fifo_read(
2781
2889
  ) {
2782
2890
  int err;
2783
2891
 
2784
- int len = av_audio_fifo_read(fifo->handle, (void **) frame->handle->data, nb_samples);
2892
+ auto len = av_audio_fifo_read(fifo->handle, (void **) frame->handle->data, nb_samples);
2785
2893
 
2786
2894
  if (len < 0) {
2787
2895
  err = js_throw_error(env, NULL, av_err2str(len));
2788
2896
  assert(err == 0);
2897
+
2789
2898
  throw js_pending_exception;
2790
2899
  }
2791
2900
 
@@ -2802,11 +2911,12 @@ bare_ffmpeg_audio_fifo_peek(
2802
2911
  ) {
2803
2912
  int err;
2804
2913
 
2805
- int len = av_audio_fifo_peek(fifo->handle, (void **) frame->handle->data, nb_samples);
2914
+ auto len = av_audio_fifo_peek(fifo->handle, (void **) frame->handle->data, nb_samples);
2806
2915
 
2807
2916
  if (len < 0) {
2808
2917
  err = js_throw_error(env, NULL, av_err2str(len));
2809
2918
  assert(err == 0);
2919
+
2810
2920
  throw js_pending_exception;
2811
2921
  }
2812
2922
 
@@ -2822,11 +2932,12 @@ bare_ffmpeg_audio_fifo_drain(
2822
2932
  ) {
2823
2933
  int err;
2824
2934
 
2825
- int len = av_audio_fifo_drain(fifo->handle, nb_samples);
2935
+ auto len = av_audio_fifo_drain(fifo->handle, nb_samples);
2826
2936
 
2827
2937
  if (len < 0) {
2828
2938
  err = js_throw_error(env, NULL, av_err2str(len));
2829
2939
  assert(err == 0);
2940
+
2830
2941
  throw js_pending_exception;
2831
2942
  }
2832
2943
 
@@ -2866,12 +2977,10 @@ bare_ffmpeg_rational_d2q(
2866
2977
  js_receiver_t,
2867
2978
  double num
2868
2979
  ) {
2869
- constexpr int safe_max = 1 << 26;
2870
-
2871
- auto rational = av_d2q(num, safe_max);
2872
-
2873
2980
  int err;
2874
2981
 
2982
+ auto rational = av_d2q(num, 1 << 26);
2983
+
2875
2984
  js_arraybuffer_t result;
2876
2985
 
2877
2986
  int32_t *data;
@@ -3018,8 +3127,6 @@ bare_ffmpeg_exports(js_env_t *env, js_value_t *exports) {
3018
3127
  V("setFrameWidth", bare_ffmpeg_frame_set_width)
3019
3128
  V("getFrameHeight", bare_ffmpeg_frame_get_height)
3020
3129
  V("setFrameHeight", bare_ffmpeg_frame_set_height)
3021
- V("getFramePixelFormat", bare_ffmpeg_frame_get_pixel_format)
3022
- V("setFramePixelFormat", bare_ffmpeg_frame_set_pixel_format)
3023
3130
  V("getFrameFormat", bare_ffmpeg_frame_get_format)
3024
3131
  V("setFrameFormat", bare_ffmpeg_frame_set_format)
3025
3132
  V("getFrameChannelLayout", bare_ffmpeg_frame_get_channel_layout)
@@ -3045,6 +3152,7 @@ bare_ffmpeg_exports(js_env_t *env, js_value_t *exports) {
3045
3152
 
3046
3153
  V("initPacket", bare_ffmpeg_packet_init)
3047
3154
  V("initPacketFromBuffer", bare_ffmpeg_packet_init_from_buffer)
3155
+ V("destroyPacket", bare_ffmpeg_packet_destroy)
3048
3156
  V("unrefPacket", bare_ffmpeg_packet_unref)
3049
3157
  V("getPacketStreamIndex", bare_ffmpeg_packet_get_stream_index)
3050
3158
  V("setPacketStreamIndex", bare_ffmpeg_packet_set_stream_index)
@@ -285,6 +285,7 @@ if(CMAKE_HOST_WIN32)
285
285
  find_path(
286
286
  msys2
287
287
  NAMES msys2.exe
288
+ PATHS "C:/tools/msys64"
288
289
  REQUIRED
289
290
  )
290
291
 
package/lib/codec.js CHANGED
@@ -51,7 +51,6 @@ module.exports = class FFmpegCodec {
51
51
  }
52
52
 
53
53
  static MJPEG = this.for(constants.codecs.MJPEG)
54
- static H264 = this.for(constants.codecs.H264)
55
54
  static AAC = this.for(constants.codecs.AAC)
56
55
  static OPUS = this.for(constants.codecs.OPUS)
57
56
  static AV1 = this.for(constants.codecs.AV1)
package/lib/constants.js CHANGED
@@ -1,7 +1,6 @@
1
1
  const binding = require('../binding')
2
2
  const errors = require('./errors')
3
3
 
4
- // Helpers
5
4
  function makeTag(a, b, c, d) {
6
5
  return (
7
6
  a.charCodeAt(0) |
@@ -14,7 +13,6 @@ function makeTag(a, b, c, d) {
14
13
  module.exports = exports = {
15
14
  codecs: {
16
15
  MJPEG: binding.AV_CODEC_ID_MJPEG,
17
- H264: binding.AV_CODEC_ID_H264,
18
16
  AAC: binding.AV_CODEC_ID_AAC,
19
17
  OPUS: binding.AV_CODEC_ID_OPUS,
20
18
  AV1: binding.AV_CODEC_ID_AV1,
@@ -22,11 +20,7 @@ module.exports = exports = {
22
20
  MP3: binding.AV_CODEC_ID_MP3
23
21
  },
24
22
  tags: {
25
- // Source Ref:
26
- // https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/riff.c#L36
27
- // https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/riff.c#L530
28
23
  MJPEG: makeTag('M', 'J', 'P', 'G'),
29
- H264: makeTag('H', '2', '6', '4'),
30
24
  AV1: makeTag('A', 'V', '0', '1'),
31
25
  AAC: 0x00ff,
32
26
  FLAC: 0xf1ac,
package/lib/dictionary.js CHANGED
@@ -1,6 +1,16 @@
1
1
  const binding = require('../binding')
2
2
 
3
3
  module.exports = class FFmpegDictionary {
4
+ static from(obj) {
5
+ const dictionary = new FFmpegDictionary()
6
+
7
+ for (const [key, value] of Object.entries(obj)) {
8
+ dictionary.set(key, value)
9
+ }
10
+
11
+ return dictionary
12
+ }
13
+
4
14
  constructor() {
5
15
  this._handle = binding.initDictionary()
6
16
  }
package/lib/frame.js CHANGED
@@ -32,14 +32,6 @@ module.exports = class FFmpegFrame {
32
32
  binding.setFrameHeight(this._handle, value)
33
33
  }
34
34
 
35
- get pixelFormat() {
36
- return binding.getFramePixelFormat(this._handle)
37
- }
38
-
39
- set pixelFormat(value) {
40
- binding.setFramePixelFormat(this._handle, value)
41
- }
42
-
43
35
  get format() {
44
36
  return binding.getFrameFormat(this._handle)
45
37
  }
@@ -109,7 +101,6 @@ module.exports = class FFmpegFrame {
109
101
  __proto__: { constructor: FFmpegFrame },
110
102
  width: this.width,
111
103
  height: this.height,
112
- pixelFormat: this.pixelFormat,
113
104
  format: this.format,
114
105
  channelLayout: this.channelLayout,
115
106
  nbSamples: this.nbSamples,
package/lib/io-context.js CHANGED
@@ -16,15 +16,14 @@ module.exports = class FFmpegIOContext {
16
16
  buffer = Buffer.alloc(0)
17
17
  }
18
18
 
19
- let onwrite
20
-
21
- if (typeof opts.onwrite === 'function') {
22
- onwrite = function (chunk) {
23
- opts.onwrite(Buffer.from(chunk))
24
- }
25
- }
26
-
27
- this._handle = binding.initIOContext(buffer, offset, len, onwrite)
19
+ this._handle = binding.initIOContext(
20
+ buffer,
21
+ offset,
22
+ len,
23
+ opts.onwrite,
24
+ opts.onread,
25
+ opts.onseek
26
+ )
28
27
  }
29
28
 
30
29
  destroy() {
package/lib/packet.js CHANGED
@@ -15,7 +15,7 @@ module.exports = class FFmpegPacket {
15
15
  }
16
16
 
17
17
  destroy() {
18
- binding.unrefPacket(this._handle)
18
+ binding.destroyPacket(this._handle)
19
19
  this._handle = null
20
20
  }
21
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-ffmpeg",
3
- "version": "1.0.0-21",
3
+ "version": "1.0.0-23",
4
4
  "description": "Low-level FFmpeg bindings for Bare",
5
5
  "exports": {
6
6
  ".": "./index.js",