bare-ffmpeg 1.0.0-10 → 1.0.0-12

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/binding.cc ADDED
@@ -0,0 +1,1771 @@
1
+ #include <assert.h>
2
+ #include <stddef.h>
3
+ #include <stdint.h>
4
+ #include <string.h>
5
+
6
+ #include <bare.h>
7
+ #include <js.h>
8
+ #include <jstl.h>
9
+
10
+ extern "C" {
11
+ #include <libavcodec/avcodec.h>
12
+ #include <libavcodec/codec.h>
13
+ #include <libavcodec/codec_id.h>
14
+ #include <libavcodec/codec_par.h>
15
+ #include <libavcodec/packet.h>
16
+ #include <libavdevice/avdevice.h>
17
+ #include <libavformat/avformat.h>
18
+ #include <libavformat/avio.h>
19
+ #include <libavutil/channel_layout.h>
20
+ #include <libavutil/dict.h>
21
+ #include <libavutil/error.h>
22
+ #include <libavutil/frame.h>
23
+ #include <libavutil/imgutils.h>
24
+ #include <libavutil/log.h>
25
+ #include <libavutil/mem.h>
26
+ #include <libavutil/pixfmt.h>
27
+ #include <libavutil/rational.h>
28
+ #include <libavutil/samplefmt.h>
29
+ #include <libswresample/swresample.h>
30
+ #include <libswscale/swscale.h>
31
+ }
32
+
33
+ typedef struct {
34
+ AVIOContext *handle;
35
+ } bare_ffmpeg_io_context_t;
36
+
37
+ typedef struct {
38
+ const AVOutputFormat *handle;
39
+ } bare_ffmpeg_output_format_t;
40
+
41
+ typedef struct {
42
+ const AVInputFormat *handle;
43
+ } bare_ffmpeg_input_format_t;
44
+
45
+ typedef struct {
46
+ AVFormatContext *handle;
47
+ } bare_ffmpeg_format_context_t;
48
+
49
+ typedef struct {
50
+ AVStream *handle;
51
+ } bare_ffmpeg_stream_t;
52
+
53
+ typedef struct {
54
+ const AVCodec *handle;
55
+ } bare_ffmpeg_codec_t;
56
+
57
+ typedef struct {
58
+ AVCodecParameters *handle;
59
+ } bare_ffmpeg_codec_parameters_t;
60
+
61
+ typedef struct {
62
+ AVCodecContext *handle;
63
+ } bare_ffmpeg_codec_context_t;
64
+
65
+ typedef struct {
66
+ AVChannelLayout handle;
67
+ } bare_ffmpeg_channel_layout_t;
68
+
69
+ typedef struct {
70
+ AVFrame *handle;
71
+ } bare_ffmpeg_frame_t;
72
+
73
+ typedef struct {
74
+ AVPacket *handle;
75
+ } bare_ffmpeg_packet_t;
76
+
77
+ typedef struct {
78
+ struct SwsContext *handle;
79
+ } bare_ffmpeg_scaler_t;
80
+
81
+ typedef struct {
82
+ struct AVDictionary *handle;
83
+ } bare_ffmpeg_dictionary_t;
84
+
85
+ typedef struct {
86
+ struct SwrContext *handle;
87
+ } bare_ffmpeg_resampler_t;
88
+
89
+ static uv_once_t bare_ffmpeg__init_guard = UV_ONCE_INIT;
90
+
91
+ static void
92
+ bare_ffmpeg__on_init(void) {
93
+ av_log_set_level(AV_LOG_ERROR);
94
+ avdevice_register_all();
95
+ }
96
+
97
+ static js_arraybuffer_t
98
+ bare_ffmpeg_io_context_init(
99
+ js_env_t *env,
100
+ js_receiver_t,
101
+ js_arraybuffer_span_t data,
102
+ uint64_t offset,
103
+ uint64_t len
104
+ ) {
105
+ int err;
106
+
107
+ js_arraybuffer_t handle;
108
+
109
+ bare_ffmpeg_io_context_t *context;
110
+ err = js_create_arraybuffer(env, context, handle);
111
+ assert(err == 0);
112
+
113
+ uint8_t *io;
114
+ size_t size = static_cast<size_t>(len);
115
+
116
+ if (len == 0) io = NULL;
117
+ else {
118
+ io = reinterpret_cast<uint8_t *>(av_malloc(size));
119
+
120
+ size_t off = static_cast<size_t>(offset);
121
+ memcpy(io, &data[off], size);
122
+ }
123
+
124
+ context->handle = avio_alloc_context(io, static_cast<int>(len), 0, NULL, NULL, NULL, NULL);
125
+ context->handle->opaque = (void *) context;
126
+
127
+ return handle;
128
+ }
129
+
130
+ static void
131
+ bare_ffmpeg_io_context_destroy(js_env_t *env, js_receiver_t, js_arraybuffer_span_of_t<bare_ffmpeg_io_context_t, 1> context) {
132
+ av_free(context->handle->buffer);
133
+ avio_context_free(&context->handle);
134
+ }
135
+
136
+ static js_arraybuffer_t
137
+ bare_ffmpeg_output_format_init(js_env_t *env, js_receiver_t, std::string name) {
138
+ int err;
139
+
140
+ const AVOutputFormat *format = av_guess_format(name.c_str(), NULL, NULL);
141
+
142
+ if (format == NULL) {
143
+ err = js_throw_errorf(env, NULL, "No output format found for name '%s'", name.c_str());
144
+ assert(err == 0);
145
+
146
+ throw js_pending_exception;
147
+ }
148
+
149
+ js_arraybuffer_t handle;
150
+ bare_ffmpeg_output_format_t *context;
151
+ err = js_create_arraybuffer(env, context, handle);
152
+ assert(err == 0);
153
+
154
+ context->handle = format;
155
+
156
+ return handle;
157
+ }
158
+
159
+ static js_arraybuffer_t
160
+ bare_ffmpeg_input_format_init(js_env_t *env, js_receiver_t, std::string name) {
161
+ int err;
162
+
163
+ const AVInputFormat *format = av_find_input_format(name.c_str());
164
+ if (format == NULL) {
165
+ err = js_throw_errorf(env, NULL, "No input format found for name '%s'", name.c_str());
166
+ assert(err == 0);
167
+
168
+ throw js_pending_exception;
169
+ }
170
+
171
+ js_arraybuffer_t handle;
172
+ bare_ffmpeg_input_format_t *context;
173
+ err = js_create_arraybuffer(env, context, handle);
174
+ assert(err == 0);
175
+
176
+ context->handle = format;
177
+
178
+ return handle;
179
+ }
180
+
181
+ static js_arraybuffer_t
182
+ bare_ffmpeg_format_context_open_input_with_io(
183
+ js_env_t *env,
184
+ js_receiver_t,
185
+ js_arraybuffer_span_of_t<bare_ffmpeg_io_context_t, 1> io
186
+ ) {
187
+ int err;
188
+
189
+ js_arraybuffer_t handle;
190
+
191
+ bare_ffmpeg_format_context_t *context;
192
+ err = js_create_arraybuffer(env, context, handle);
193
+ assert(err == 0);
194
+
195
+ context->handle = avformat_alloc_context();
196
+ context->handle->pb = io->handle;
197
+ context->handle->opaque = (void *) context;
198
+
199
+ err = avformat_open_input(&context->handle, NULL, NULL, NULL);
200
+ if (err < 0) {
201
+ avformat_free_context(context->handle);
202
+
203
+ err = js_throw_error(env, NULL, av_err2str(err));
204
+ assert(err == 0);
205
+
206
+ throw js_pending_exception;
207
+ }
208
+
209
+ err = avformat_find_stream_info(context->handle, NULL);
210
+ if (err < 0) {
211
+ avformat_close_input(&context->handle);
212
+
213
+ err = js_throw_error(env, NULL, av_err2str(err));
214
+ assert(err == 0);
215
+
216
+ throw js_pending_exception;
217
+ }
218
+
219
+ return handle;
220
+ }
221
+
222
+ static js_arraybuffer_t
223
+ bare_ffmpeg_format_context_open_input_with_format(
224
+ js_env_t *env,
225
+ js_receiver_t,
226
+ js_arraybuffer_span_of_t<bare_ffmpeg_input_format_t, 1> format,
227
+ js_arraybuffer_span_of_t<bare_ffmpeg_dictionary_t, 1> options,
228
+ std::string url
229
+ ) {
230
+ int err;
231
+
232
+ js_arraybuffer_t handle;
233
+
234
+ bare_ffmpeg_format_context_t *context;
235
+ err = js_create_arraybuffer(env, context, handle);
236
+ assert(err == 0);
237
+
238
+ context->handle = avformat_alloc_context();
239
+ context->handle->opaque = (void *) context;
240
+
241
+ err = avformat_open_input(&context->handle, url.c_str(), format->handle, &options->handle);
242
+ if (err < 0) {
243
+ avformat_free_context(context->handle);
244
+
245
+ err = js_throw_error(env, NULL, av_err2str(err));
246
+ assert(err == 0);
247
+
248
+ throw js_pending_exception;
249
+ }
250
+
251
+ err = avformat_find_stream_info(context->handle, NULL);
252
+ if (err < 0) {
253
+ avformat_close_input(&context->handle);
254
+
255
+ err = js_throw_error(env, NULL, av_err2str(err));
256
+ assert(err == 0);
257
+
258
+ throw js_pending_exception;
259
+ }
260
+
261
+ return handle;
262
+ }
263
+
264
+ static void
265
+ bare_ffmpeg_format_context_close_input(
266
+ js_env_t *env,
267
+ js_receiver_t,
268
+ js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context
269
+ ) {
270
+ avformat_close_input(&context->handle);
271
+ }
272
+
273
+ static js_arraybuffer_t
274
+ bare_ffmpeg_format_context_open_output(
275
+ js_env_t *env,
276
+ js_receiver_t,
277
+ js_arraybuffer_span_of_t<bare_ffmpeg_output_format_t, 1> format,
278
+ js_arraybuffer_span_of_t<bare_ffmpeg_io_context_t, 1> io
279
+ ) {
280
+ int err;
281
+
282
+ js_arraybuffer_t handle;
283
+ bare_ffmpeg_format_context_t *context;
284
+ err = js_create_arraybuffer(env, context, handle);
285
+ assert(err == 0);
286
+
287
+ err = avformat_alloc_output_context2(&context->handle, format->handle, NULL, NULL);
288
+ if (err < 0) {
289
+ err = js_throw_error(env, NULL, av_err2str(err));
290
+ assert(err == 0);
291
+
292
+ throw js_pending_exception;
293
+ }
294
+
295
+ context->handle->pb = io->handle;
296
+ context->handle->opaque = (void *) context;
297
+
298
+ return handle;
299
+ }
300
+
301
+ static void
302
+ bare_ffmpeg_format_context_close_output(
303
+ js_env_t *env,
304
+ js_receiver_t,
305
+ js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context
306
+ ) {
307
+ avformat_free_context(context->handle);
308
+ }
309
+
310
+ static js_array_t
311
+ bare_ffmpeg_format_context_get_streams(
312
+ js_env_t *env,
313
+ js_receiver_t,
314
+ js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context
315
+ ) {
316
+ int err;
317
+
318
+ uint32_t len = context->handle->nb_streams;
319
+
320
+ js_array_t result;
321
+ err = js_create_array(env, len, result);
322
+ assert(err == 0);
323
+
324
+ for (uint32_t i = 0; i < len; i++) {
325
+ js_arraybuffer_t handle;
326
+
327
+ bare_ffmpeg_stream_t *stream;
328
+ err = js_create_arraybuffer(env, stream, handle);
329
+ assert(err == 0);
330
+
331
+ stream->handle = context->handle->streams[i];
332
+
333
+ err = js_set_element(env, result, i, handle);
334
+ assert(err == 0);
335
+ }
336
+
337
+ return result;
338
+ }
339
+
340
+ static int
341
+ bare_ffmpeg_format_context_get_best_stream_index(
342
+ js_env_t *env,
343
+ js_receiver_t,
344
+ js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context,
345
+ int32_t type
346
+ ) {
347
+ int best_stream = av_find_best_stream(context->handle, static_cast<AVMediaType>(type), -1, -1, NULL, 0);
348
+
349
+ if (best_stream < 0) best_stream = -1;
350
+
351
+ return best_stream;
352
+ }
353
+
354
+ static js_arraybuffer_t
355
+ bare_ffmpeg_format_context_create_stream(
356
+ js_env_t *env,
357
+ js_receiver_t,
358
+ js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context,
359
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_t, 1> codec
360
+ ) {
361
+ int err;
362
+
363
+ js_arraybuffer_t handle;
364
+ bare_ffmpeg_stream_t *stream;
365
+ err = js_create_arraybuffer(env, stream, handle);
366
+ assert(err == 0);
367
+
368
+ stream->handle = avformat_new_stream(context->handle, codec->handle);
369
+
370
+ if (stream->handle == NULL) {
371
+ err = js_throw_error(env, NULL, av_err2str(err));
372
+ assert(err == 0);
373
+
374
+ throw js_pending_exception;
375
+ }
376
+
377
+ return handle;
378
+ }
379
+
380
+ static bool
381
+ bare_ffmpeg_format_context_read_frame(
382
+ js_env_t *env,
383
+ js_receiver_t,
384
+ js_arraybuffer_span_of_t<bare_ffmpeg_format_context_t, 1> context,
385
+ js_arraybuffer_span_of_t<bare_ffmpeg_packet_t, 1> packet
386
+ ) {
387
+ av_packet_unref(packet->handle);
388
+
389
+ int err = av_read_frame(context->handle, packet->handle);
390
+ if (err < 0 && err != AVERROR(EAGAIN) && err != AVERROR_EOF) {
391
+ err = js_throw_error(env, NULL, av_err2str(err));
392
+ assert(err == 0);
393
+
394
+ throw js_pending_exception;
395
+ }
396
+
397
+ return err == 0;
398
+ }
399
+
400
+ static int32_t
401
+ bare_ffmpeg_stream_get_codec(
402
+ js_env_t *env,
403
+ js_receiver_t,
404
+ js_arraybuffer_span_of_t<bare_ffmpeg_stream_t, 1> stream
405
+ ) {
406
+ return stream->handle->codecpar->codec_id;
407
+ }
408
+
409
+ static js_arraybuffer_t
410
+ bare_ffmpeg_stream_get_codec_parameters(
411
+ js_env_t *env,
412
+ js_receiver_t,
413
+ js_arraybuffer_span_of_t<bare_ffmpeg_stream_t, 1> stream
414
+ ) {
415
+ int err;
416
+
417
+ js_arraybuffer_t handle;
418
+
419
+ bare_ffmpeg_codec_parameters_t *parameters;
420
+ err = js_create_arraybuffer(env, parameters, handle);
421
+ assert(err == 0);
422
+
423
+ parameters->handle = stream->handle->codecpar;
424
+
425
+ return handle;
426
+ }
427
+
428
+ static js_arraybuffer_t
429
+ bare_ffmpeg_find_decoder_by_id(js_env_t *env, js_receiver_t, uint32_t id) {
430
+ int err;
431
+
432
+ const AVCodec *decoder = avcodec_find_decoder((enum AVCodecID) id);
433
+
434
+ if (decoder == NULL) {
435
+ err = js_throw_errorf(env, NULL, "No decoder found for codec '%d'", id);
436
+ assert(err == 0);
437
+
438
+ throw js_pending_exception;
439
+ }
440
+
441
+ js_arraybuffer_t handle;
442
+ bare_ffmpeg_codec_t *context;
443
+ err = js_create_arraybuffer(env, context, handle);
444
+ assert(err == 0);
445
+
446
+ context->handle = decoder;
447
+
448
+ return handle;
449
+ }
450
+
451
+ static js_arraybuffer_t
452
+ bare_ffmpeg_find_encoder_by_id(js_env_t *env, js_receiver_t, uint32_t id) {
453
+ int err;
454
+
455
+ const AVCodec *encoder = avcodec_find_encoder((enum AVCodecID) id);
456
+
457
+ if (encoder == NULL) {
458
+ err = js_throw_errorf(env, NULL, "No encoder found for codec '%d'", id);
459
+ assert(err == 0);
460
+
461
+ throw js_pending_exception;
462
+ }
463
+
464
+ js_arraybuffer_t handle;
465
+ bare_ffmpeg_codec_t *context;
466
+ err = js_create_arraybuffer(env, context, handle);
467
+ assert(err == 0);
468
+
469
+ context->handle = encoder;
470
+
471
+ return handle;
472
+ }
473
+
474
+ static js_arraybuffer_t
475
+ bare_ffmpeg_codec_context_init(
476
+ js_env_t *env,
477
+ js_receiver_t,
478
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_t, 1> codec
479
+ ) {
480
+ int err;
481
+
482
+ js_arraybuffer_t handle;
483
+
484
+ bare_ffmpeg_codec_context_t *context;
485
+ err = js_create_arraybuffer(env, context, handle);
486
+ assert(err == 0);
487
+
488
+ context->handle = avcodec_alloc_context3(codec->handle);
489
+ context->handle->opaque = (void *) context;
490
+
491
+ return handle;
492
+ }
493
+
494
+ static void
495
+ bare_ffmpeg_codec_context_destroy(
496
+ js_env_t *env,
497
+ js_receiver_t,
498
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
499
+ ) {
500
+ avcodec_free_context(&context->handle);
501
+ }
502
+
503
+ static bool
504
+ bare_ffmpeg_codec_context_open(
505
+ js_env_t *env,
506
+ js_receiver_t,
507
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
508
+ ) {
509
+ int err;
510
+
511
+ err = avcodec_open2(context->handle, context->handle->codec, NULL);
512
+ if (err < 0) {
513
+ err = js_throw_error(env, NULL, av_err2str(err));
514
+ assert(err == 0);
515
+
516
+ throw js_pending_exception;
517
+ }
518
+
519
+ return err == 0;
520
+ }
521
+
522
+ static int64_t
523
+ bare_ffmpeg_frame_get_format(
524
+ js_env_t *env,
525
+ js_receiver_t,
526
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
527
+ ) {
528
+ return frame->handle->format;
529
+ }
530
+
531
+ static void
532
+ bare_ffmpeg_frame_set_format(
533
+ js_env_t *env,
534
+ js_receiver_t,
535
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame,
536
+ int format
537
+ ) {
538
+ frame->handle->format = format;
539
+ }
540
+
541
+ static js_arraybuffer_t
542
+ bare_ffmpeg_frame_get_channel_layout(
543
+ js_env_t *env,
544
+ js_receiver_t,
545
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
546
+ ) {
547
+ int err;
548
+
549
+ js_arraybuffer_t result;
550
+
551
+ bare_ffmpeg_channel_layout_t *layout;
552
+ err = js_create_arraybuffer(env, layout, result);
553
+ assert(err == 0);
554
+
555
+ err = av_channel_layout_copy(&layout->handle, &frame->handle->ch_layout);
556
+ assert(err == 0);
557
+
558
+ return result;
559
+ }
560
+
561
+ static void
562
+ bare_ffmpeg_frame_set_channel_layout(
563
+ js_env_t *env,
564
+ js_receiver_t,
565
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame,
566
+ js_arraybuffer_span_of_t<bare_ffmpeg_channel_layout_t, 1> layout
567
+ ) {
568
+ int err;
569
+ err = av_channel_layout_copy(&frame->handle->ch_layout, &layout->handle);
570
+ assert(err == 0);
571
+ }
572
+
573
+ static bool
574
+ bare_ffmpeg_codec_context_open_with_options(
575
+ js_env_t *env,
576
+ js_receiver_t,
577
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
578
+ js_arraybuffer_span_of_t<bare_ffmpeg_dictionary_t, 1> options
579
+ ) {
580
+ int err;
581
+
582
+ err = avcodec_open2(context->handle, context->handle->codec, &options->handle);
583
+ if (err < 0) {
584
+ err = js_throw_error(env, NULL, av_err2str(err));
585
+ assert(err == 0);
586
+
587
+ throw js_pending_exception;
588
+ }
589
+
590
+ return err == 0;
591
+ }
592
+
593
+ static int64_t
594
+ bare_ffmpeg_codec_context_get_pixel_format(
595
+ js_env_t *env,
596
+ js_receiver_t,
597
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
598
+ ) {
599
+ return context->handle->pix_fmt;
600
+ }
601
+
602
+ static void
603
+ bare_ffmpeg_codec_context_set_pixel_format(
604
+ js_env_t *env,
605
+ js_receiver_t,
606
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
607
+ int32_t value
608
+ ) {
609
+ context->handle->pix_fmt = static_cast<AVPixelFormat>(value);
610
+ }
611
+
612
+ static int64_t
613
+ bare_ffmpeg_codec_context_get_width(
614
+ js_env_t *env,
615
+ js_receiver_t,
616
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
617
+ ) {
618
+ return context->handle->width;
619
+ }
620
+
621
+ static void
622
+ bare_ffmpeg_codec_context_set_width(
623
+ js_env_t *env,
624
+ js_receiver_t,
625
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
626
+ int value
627
+ ) {
628
+ context->handle->width = value;
629
+ }
630
+
631
+ static int64_t
632
+ bare_ffmpeg_codec_context_get_height(
633
+ js_env_t *env,
634
+ js_receiver_t,
635
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
636
+ ) {
637
+ return context->handle->height;
638
+ }
639
+
640
+ static void
641
+ bare_ffmpeg_codec_context_set_height(
642
+ js_env_t *env,
643
+ js_receiver_t,
644
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
645
+ int value
646
+ ) {
647
+ context->handle->height = value;
648
+ }
649
+
650
+ static int64_t
651
+ bare_ffmpeg_codec_context_get_sample_format(
652
+ js_env_t *env,
653
+ js_receiver_t,
654
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
655
+ ) {
656
+ return context->handle->sample_fmt;
657
+ }
658
+
659
+ static void
660
+ bare_ffmpeg_codec_context_set_sample_format(
661
+ js_env_t *env,
662
+ js_receiver_t,
663
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
664
+ int32_t value
665
+ ) {
666
+ context->handle->sample_fmt = static_cast<AVSampleFormat>(value);
667
+ }
668
+
669
+ static js_arraybuffer_t
670
+ bare_ffmpeg_codec_context_get_time_base(
671
+ js_env_t *env,
672
+ js_receiver_t,
673
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
674
+ ) {
675
+ js_arraybuffer_t result;
676
+ int32_t *data;
677
+
678
+ int err = js_create_arraybuffer(env, data, result);
679
+ assert(err == 0);
680
+
681
+ data[0] = context->handle->time_base.num;
682
+ data[1] = context->handle->time_base.den;
683
+
684
+ return result;
685
+ }
686
+
687
+ static void
688
+ bare_ffmpeg_codec_context_set_time_base(
689
+ js_env_t *env,
690
+ js_receiver_t,
691
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
692
+ int num,
693
+ int den
694
+ ) {
695
+ context->handle->time_base.num = num;
696
+ context->handle->time_base.den = den;
697
+ }
698
+
699
+ static js_arraybuffer_t
700
+ bare_ffmpeg_codec_context_get_channel_layout(
701
+ js_env_t *env,
702
+ js_receiver_t,
703
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
704
+ ) {
705
+ int err;
706
+
707
+ js_arraybuffer_t result;
708
+
709
+ bare_ffmpeg_channel_layout_t *layout;
710
+ err = js_create_arraybuffer(env, layout, result);
711
+ assert(err == 0);
712
+
713
+ err = av_channel_layout_copy(&layout->handle, &context->handle->ch_layout);
714
+ assert(err == 0);
715
+
716
+ return result;
717
+ }
718
+
719
+ static void
720
+ bare_ffmpeg_codec_context_set_channel_layout(
721
+ js_env_t *env,
722
+ js_receiver_t,
723
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
724
+ js_arraybuffer_span_of_t<bare_ffmpeg_channel_layout_t, 1> layout
725
+ ) {
726
+ int err;
727
+ err = av_channel_layout_copy(&context->handle->ch_layout, &layout->handle);
728
+ assert(err == 0);
729
+ }
730
+
731
+ static int
732
+ bare_ffmpeg_codec_context_get_sample_rate(
733
+ js_env_t *env,
734
+ js_receiver_t,
735
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
736
+ ) {
737
+ return context->handle->sample_rate;
738
+ }
739
+
740
+ static void
741
+ bare_ffmpeg_codec_context_set_sample_rate(
742
+ js_env_t *env,
743
+ js_receiver_t,
744
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
745
+ int32_t sample_rate
746
+ ) {
747
+ context->handle->sample_rate = sample_rate;
748
+ }
749
+
750
+ static bool
751
+ bare_ffmpeg_codec_context_send_packet(
752
+ js_env_t *env,
753
+ js_receiver_t,
754
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
755
+ js_arraybuffer_span_of_t<bare_ffmpeg_packet_t, 1> packet
756
+ ) {
757
+ int err;
758
+
759
+ err = avcodec_send_packet(context->handle, packet->handle);
760
+ if (err < 0 && err != AVERROR(EAGAIN) && err != AVERROR_EOF) {
761
+ err = js_throw_error(env, NULL, av_err2str(err));
762
+ assert(err == 0);
763
+
764
+ throw js_pending_exception;
765
+ }
766
+
767
+ return err == 0;
768
+ }
769
+
770
+ static bool
771
+ bare_ffmpeg_codec_context_receive_packet(
772
+ js_env_t *env,
773
+ js_receiver_t,
774
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
775
+ js_arraybuffer_span_of_t<bare_ffmpeg_packet_t, 1> packet
776
+ ) {
777
+ int err;
778
+
779
+ err = avcodec_receive_packet(context->handle, packet->handle);
780
+ if (err < 0 && err != AVERROR(EAGAIN) && err != AVERROR_EOF) {
781
+ err = js_throw_error(env, NULL, av_err2str(err));
782
+ assert(err == 0);
783
+
784
+ throw js_pending_exception;
785
+ }
786
+
787
+ return err == 0;
788
+ }
789
+
790
+ static bool
791
+ bare_ffmpeg_codec_context_send_frame(
792
+ js_env_t *env,
793
+ js_receiver_t,
794
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
795
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
796
+ ) {
797
+ int err;
798
+
799
+ err = avcodec_send_frame(context->handle, frame->handle);
800
+ if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) {
801
+ return false;
802
+ }
803
+
804
+ if (err < 0) {
805
+ err = js_throw_error(env, NULL, av_err2str(err));
806
+ assert(err == 0);
807
+
808
+ throw js_pending_exception;
809
+ }
810
+
811
+ return err == 0;
812
+ }
813
+
814
+ static bool
815
+ bare_ffmpeg_codec_context_receive_frame(
816
+ js_env_t *env,
817
+ js_receiver_t,
818
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
819
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
820
+ ) {
821
+ int err;
822
+
823
+ err = avcodec_receive_frame(context->handle, frame->handle);
824
+ if (err < 0 && err != AVERROR(EAGAIN) && err != AVERROR_EOF) {
825
+ err = js_throw_error(env, NULL, av_err2str(err));
826
+ assert(err == 0);
827
+
828
+ throw js_pending_exception;
829
+ }
830
+
831
+ return err == 0;
832
+ }
833
+
834
+ static void
835
+ bare_ffmpeg_codec_parameters_from_context(
836
+ js_env_t *env,
837
+ js_receiver_t,
838
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters,
839
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context
840
+ ) {
841
+ int err;
842
+
843
+ err = avcodec_parameters_from_context(parameters->handle, context->handle);
844
+ if (err < 0) {
845
+ err = js_throw_error(env, NULL, av_err2str(err));
846
+ assert(err == 0);
847
+
848
+ throw js_pending_exception;
849
+ }
850
+ }
851
+
852
+ static void
853
+ bare_ffmpeg_codec_parameters_to_context(
854
+ js_env_t *env,
855
+ js_receiver_t,
856
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_context_t, 1> context,
857
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
858
+ ) {
859
+ int err;
860
+
861
+ err = avcodec_parameters_to_context(context->handle, parameters->handle);
862
+ if (err < 0) {
863
+ err = js_throw_error(env, NULL, av_err2str(err));
864
+ assert(err == 0);
865
+
866
+ throw js_pending_exception;
867
+ }
868
+ }
869
+
870
+ static int64_t
871
+ bare_ffmpeg_codec_parameters_get_bit_rate(
872
+ js_env_t *env,
873
+ js_receiver_t,
874
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
875
+ ) {
876
+ return parameters->handle->bit_rate;
877
+ }
878
+
879
+ static int64_t
880
+ bare_ffmpeg_codec_parameters_get_bits_per_coded_sample(
881
+ js_env_t *env,
882
+ js_receiver_t,
883
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
884
+ ) {
885
+ return parameters->handle->bits_per_coded_sample;
886
+ }
887
+
888
+ static int64_t
889
+ bare_ffmpeg_codec_parameters_get_bits_per_raw_sample(
890
+ js_env_t *env,
891
+ js_receiver_t,
892
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
893
+ ) {
894
+ return parameters->handle->bits_per_raw_sample;
895
+ }
896
+
897
+ static int
898
+ bare_ffmpeg_codec_parameters_get_format(
899
+ js_env_t *env,
900
+ js_receiver_t,
901
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
902
+ ) {
903
+ return parameters->handle->format;
904
+ }
905
+
906
+ static int64_t
907
+ bare_ffmpeg_codec_parameters_get_sample_rate(
908
+ js_env_t *env,
909
+ js_receiver_t,
910
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
911
+ ) {
912
+ return parameters->handle->sample_rate;
913
+ }
914
+
915
+ static int64_t
916
+ bare_ffmpeg_codec_parameters_get_nb_channels(
917
+ js_env_t *env,
918
+ js_receiver_t,
919
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
920
+ ) {
921
+ return parameters->handle->ch_layout.nb_channels;
922
+ }
923
+
924
+ static int64_t
925
+ bare_ffmpeg_codec_parameters_get_codec_type(
926
+ js_env_t *env,
927
+ js_receiver_t,
928
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
929
+ ) {
930
+ return parameters->handle->codec_type;
931
+ }
932
+
933
+ static js_arraybuffer_t
934
+ bare_ffmpeg_codec_parameters_get_channel_layout(
935
+ js_env_t *env,
936
+ js_receiver_t,
937
+ js_arraybuffer_span_of_t<bare_ffmpeg_codec_parameters_t, 1> parameters
938
+ ) {
939
+ int err;
940
+
941
+ js_arraybuffer_t result;
942
+
943
+ bare_ffmpeg_channel_layout_t *layout;
944
+ err = js_create_arraybuffer(env, layout, result);
945
+ assert(err == 0);
946
+
947
+ err = av_channel_layout_copy(&layout->handle, &parameters->handle->ch_layout);
948
+ assert(err == 0);
949
+
950
+ return result;
951
+ }
952
+
953
+ static js_arraybuffer_t
954
+ bare_ffmpeg_frame_init(js_env_t *env, js_receiver_t) {
955
+ js_arraybuffer_t handle;
956
+
957
+ bare_ffmpeg_frame_t *frame;
958
+ int err = js_create_arraybuffer(env, frame, handle);
959
+ assert(err == 0);
960
+
961
+ frame->handle = av_frame_alloc();
962
+ frame->handle->opaque = (void *) frame;
963
+
964
+ return handle;
965
+ }
966
+
967
+ static void
968
+ bare_ffmpeg_frame_destroy(
969
+ js_env_t *env,
970
+ js_receiver_t,
971
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
972
+ ) {
973
+ av_frame_free(&frame->handle);
974
+ }
975
+
976
+ static int32_t
977
+ bare_ffmpeg_frame_get_width(
978
+ js_env_t *env,
979
+ js_receiver_t,
980
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
981
+ ) {
982
+ return frame->handle->width;
983
+ }
984
+
985
+ static void
986
+ bare_ffmpeg_frame_set_width(
987
+ js_env_t *env,
988
+ js_receiver_t,
989
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame,
990
+ int32_t width
991
+ ) {
992
+ frame->handle->width = width;
993
+ }
994
+
995
+ static int32_t
996
+ bare_ffmpeg_frame_get_height(
997
+ js_env_t *env,
998
+ js_receiver_t,
999
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
1000
+ ) {
1001
+ return frame->handle->height;
1002
+ }
1003
+
1004
+ static void
1005
+ bare_ffmpeg_frame_set_height(
1006
+ js_env_t *env,
1007
+ js_receiver_t,
1008
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame,
1009
+ int32_t height
1010
+ ) {
1011
+ frame->handle->height = height;
1012
+ }
1013
+
1014
+ static int64_t
1015
+ bare_ffmpeg_frame_get_pixel_format(
1016
+ js_env_t *env,
1017
+ js_receiver_t,
1018
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
1019
+ ) {
1020
+ return frame->handle->format;
1021
+ }
1022
+
1023
+ static void
1024
+ bare_ffmpeg_frame_set_pixel_format(
1025
+ js_env_t *env,
1026
+ js_receiver_t,
1027
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame,
1028
+ int32_t format
1029
+ ) {
1030
+ frame->handle->format = static_cast<AVPixelFormat>(format);
1031
+ }
1032
+
1033
+ static int32_t
1034
+ bare_ffmpeg_frame_get_nb_samples(
1035
+ js_env_t *env,
1036
+ js_receiver_t,
1037
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
1038
+ ) {
1039
+ return frame->handle->nb_samples;
1040
+ }
1041
+
1042
+ static void
1043
+ bare_ffmpeg_frame_set_nb_samples(
1044
+ js_env_t *env,
1045
+ js_receiver_t,
1046
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame,
1047
+ int32_t nb_samples
1048
+ ) {
1049
+ frame->handle->nb_samples = nb_samples;
1050
+ }
1051
+
1052
+ static void
1053
+ bare_ffmpeg_frame_alloc(
1054
+ js_env_t *env,
1055
+ js_receiver_t,
1056
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame,
1057
+ int align
1058
+ ) {
1059
+ int err;
1060
+
1061
+ err = av_frame_get_buffer(frame->handle, align);
1062
+ if (err < 0) {
1063
+ err = js_throw_error(env, NULL, av_err2str(err));
1064
+ assert(err == 0);
1065
+
1066
+ throw js_pending_exception;
1067
+ }
1068
+ }
1069
+
1070
+ static js_arraybuffer_t
1071
+ bare_ffmpeg_image_init(
1072
+ js_env_t *env,
1073
+ js_receiver_t,
1074
+ int32_t pixel_format,
1075
+ int32_t width,
1076
+ int32_t height,
1077
+ int32_t align
1078
+ ) {
1079
+ int err;
1080
+
1081
+ auto len = av_image_get_buffer_size(
1082
+ static_cast<AVPixelFormat>(pixel_format),
1083
+ width,
1084
+ height,
1085
+ align
1086
+ );
1087
+
1088
+ if (len < 0) {
1089
+ err = js_throw_error(env, NULL, av_err2str(len));
1090
+ assert(err == 0);
1091
+
1092
+ throw js_pending_exception;
1093
+ }
1094
+
1095
+ js_arraybuffer_t handle;
1096
+ err = js_create_arraybuffer(env, static_cast<size_t>(len), handle);
1097
+ assert(err == 0);
1098
+
1099
+ return handle;
1100
+ }
1101
+
1102
+ static void
1103
+ bare_ffmpeg_image_fill(
1104
+ js_env_t *env,
1105
+ js_receiver_t,
1106
+ int32_t pixel_format,
1107
+ int32_t width,
1108
+ int32_t height,
1109
+ int32_t align,
1110
+ js_arraybuffer_span_t data,
1111
+ uint64_t offset,
1112
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
1113
+ ) {
1114
+ int err;
1115
+
1116
+ err = av_image_fill_arrays(
1117
+ frame->handle->data,
1118
+ frame->handle->linesize,
1119
+ &data[static_cast<size_t>(offset)],
1120
+ static_cast<AVPixelFormat>(pixel_format),
1121
+ width,
1122
+ height,
1123
+ align
1124
+ );
1125
+
1126
+ if (err < 0) {
1127
+ err = js_throw_error(env, NULL, av_err2str(err));
1128
+ assert(err == 0);
1129
+
1130
+ throw js_pending_exception;
1131
+ }
1132
+ }
1133
+
1134
+ static int
1135
+ bare_ffmpeg_image_get_line_size(
1136
+ js_env_t *env,
1137
+ js_receiver_t,
1138
+ int32_t pixel_format,
1139
+ int32_t width,
1140
+ int32_t plane
1141
+ ) {
1142
+ return av_image_get_linesize(
1143
+ static_cast<AVPixelFormat>(pixel_format),
1144
+ width,
1145
+ plane
1146
+ );
1147
+ }
1148
+
1149
+ static js_arraybuffer_t
1150
+ bare_ffmpeg_samples_init(
1151
+ js_env_t *env,
1152
+ js_receiver_t,
1153
+ int32_t sample_format,
1154
+ int32_t nb_channels,
1155
+ int32_t nb_samples,
1156
+ int32_t align
1157
+ ) {
1158
+ int err;
1159
+
1160
+ auto len = av_samples_get_buffer_size(
1161
+ NULL,
1162
+ nb_channels,
1163
+ nb_samples,
1164
+ static_cast<AVSampleFormat>(sample_format),
1165
+ align
1166
+ );
1167
+
1168
+ if (len < 0) {
1169
+ err = js_throw_error(env, NULL, av_err2str(len));
1170
+ assert(err == 0);
1171
+
1172
+ throw js_pending_exception;
1173
+ }
1174
+
1175
+ js_arraybuffer_t handle;
1176
+ err = js_create_arraybuffer(env, static_cast<size_t>(len), handle);
1177
+ assert(err == 0);
1178
+
1179
+ return handle;
1180
+ }
1181
+
1182
+ static int
1183
+ bare_ffmpeg_samples_fill(
1184
+ js_env_t *env,
1185
+ js_receiver_t,
1186
+ int32_t sample_format,
1187
+ int32_t nb_channels,
1188
+ int32_t nb_samples,
1189
+ int32_t align,
1190
+ js_arraybuffer_span_t data,
1191
+ uint64_t offset,
1192
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> frame
1193
+ ) {
1194
+ int err;
1195
+
1196
+ auto len = av_samples_fill_arrays(
1197
+ frame->handle->data,
1198
+ frame->handle->linesize,
1199
+ &data[static_cast<size_t>(offset)],
1200
+ nb_channels,
1201
+ nb_samples,
1202
+ static_cast<AVSampleFormat>(sample_format),
1203
+ align
1204
+ );
1205
+
1206
+ if (len < 0) {
1207
+ err = js_throw_error(env, NULL, av_err2str(len));
1208
+ assert(err == 0);
1209
+
1210
+ throw js_pending_exception;
1211
+ }
1212
+
1213
+ return len;
1214
+ }
1215
+
1216
+ static js_arraybuffer_t
1217
+ bare_ffmpeg_packet_init(js_env_t *env, js_receiver_t) {
1218
+ int err;
1219
+
1220
+ js_arraybuffer_t handle;
1221
+ bare_ffmpeg_packet_t *packet;
1222
+ err = js_create_arraybuffer(env, packet, handle);
1223
+ assert(err == 0);
1224
+
1225
+ packet->handle = av_packet_alloc();
1226
+
1227
+ return handle;
1228
+ }
1229
+
1230
+ static js_arraybuffer_t
1231
+ bare_ffmpeg_packet_init_from_buffer(
1232
+ js_env_t *env,
1233
+ js_receiver_t,
1234
+ js_arraybuffer_span_t data,
1235
+ uint64_t offset,
1236
+ uint64_t len
1237
+ ) {
1238
+ int err;
1239
+
1240
+ AVPacket *pkt = av_packet_alloc();
1241
+ assert(pkt != NULL);
1242
+
1243
+ err = av_new_packet(pkt, static_cast<int>(len));
1244
+ assert(err == 0);
1245
+
1246
+ memcpy(pkt->data, &data[static_cast<size_t>(offset)], static_cast<size_t>(len));
1247
+
1248
+ js_arraybuffer_t handle;
1249
+ bare_ffmpeg_packet_t *packet;
1250
+ err = js_create_arraybuffer(env, packet, handle);
1251
+ assert(err == 0);
1252
+
1253
+ packet->handle = pkt;
1254
+
1255
+ return handle;
1256
+ }
1257
+
1258
+ static void
1259
+ bare_ffmpeg_packet_unref(
1260
+ js_env_t *env,
1261
+ js_receiver_t,
1262
+ js_arraybuffer_span_of_t<bare_ffmpeg_packet_t, 1> packet
1263
+ ) {
1264
+ av_packet_unref(packet->handle);
1265
+ }
1266
+
1267
+ static int32_t
1268
+ bare_ffmpeg_packet_get_stream_index(
1269
+ js_env_t *env,
1270
+ js_receiver_t,
1271
+ js_arraybuffer_span_of_t<bare_ffmpeg_packet_t, 1> packet
1272
+ ) {
1273
+ return packet->handle->stream_index;
1274
+ }
1275
+
1276
+ static js_arraybuffer_t
1277
+ bare_ffmpeg_packet_get_data(
1278
+ js_env_t *env,
1279
+ js_receiver_t,
1280
+ js_arraybuffer_span_of_t<bare_ffmpeg_packet_t, 1> packet
1281
+ ) {
1282
+ int err;
1283
+ size_t size = static_cast<size_t>(packet->handle->size);
1284
+
1285
+ js_arraybuffer_t handle;
1286
+ uint8_t *data;
1287
+ err = js_create_arraybuffer(env, size, data, handle);
1288
+ assert(err == 0);
1289
+
1290
+ memcpy(data, packet->handle->data, size);
1291
+
1292
+ return handle;
1293
+ }
1294
+
1295
+ static js_arraybuffer_t
1296
+ bare_ffmpeg_scaler_init(
1297
+ js_env_t *env,
1298
+ js_receiver_t,
1299
+ int64_t source_format,
1300
+ int32_t source_width,
1301
+ int32_t source_height,
1302
+ int64_t target_format,
1303
+ int32_t target_width,
1304
+ int32_t target_height
1305
+ ) {
1306
+ js_arraybuffer_t handle;
1307
+ bare_ffmpeg_scaler_t *scaler;
1308
+ int err = js_create_arraybuffer(env, scaler, handle);
1309
+ assert(err == 0);
1310
+
1311
+ scaler->handle = sws_getContext(
1312
+ source_width,
1313
+ source_height,
1314
+ (enum AVPixelFormat) source_format,
1315
+ target_width,
1316
+ target_height,
1317
+ (enum AVPixelFormat) target_format,
1318
+ SWS_BICUBIC,
1319
+ NULL,
1320
+ NULL,
1321
+ NULL
1322
+ );
1323
+
1324
+ return handle;
1325
+ }
1326
+
1327
+ static void
1328
+ bare_ffmpeg_scaler_destroy(
1329
+ js_env_t *env,
1330
+ js_receiver_t,
1331
+ js_arraybuffer_span_of_t<bare_ffmpeg_scaler_t, 1> scaler
1332
+ ) {
1333
+ sws_freeContext(scaler->handle);
1334
+ }
1335
+
1336
+ static int
1337
+ bare_ffmpeg_scaler_scale(
1338
+ js_env_t *env,
1339
+ js_receiver_t,
1340
+ js_arraybuffer_span_of_t<bare_ffmpeg_scaler_t, 1> scaler,
1341
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> source,
1342
+ int y,
1343
+ int height,
1344
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> target
1345
+ ) {
1346
+ return sws_scale(
1347
+ scaler->handle,
1348
+ (const uint8_t *const *) source->handle->data,
1349
+ source->handle->linesize,
1350
+ y,
1351
+ height,
1352
+ target->handle->data,
1353
+ target->handle->linesize
1354
+ );
1355
+ }
1356
+
1357
+ static js_arraybuffer_t
1358
+ bare_ffmpeg_dictionary_init(
1359
+ js_env_t *env,
1360
+ js_receiver_t
1361
+ ) {
1362
+ js_arraybuffer_t handle;
1363
+ bare_ffmpeg_dictionary_t *dict;
1364
+ int err = js_create_arraybuffer(env, dict, handle);
1365
+ assert(err == 0);
1366
+
1367
+ dict->handle = NULL;
1368
+
1369
+ return handle;
1370
+ }
1371
+
1372
+ static void
1373
+ bare_ffmpeg_dictionary_destroy(
1374
+ js_env_t *env,
1375
+ js_receiver_t,
1376
+ js_arraybuffer_span_of_t<bare_ffmpeg_dictionary_t, 1> dict
1377
+ ) {
1378
+ av_dict_free(&dict->handle);
1379
+ }
1380
+
1381
+ static void
1382
+ bare_ffmpeg_dictionary_set_entry(
1383
+ js_env_t *env,
1384
+ js_receiver_t,
1385
+ js_arraybuffer_span_of_t<bare_ffmpeg_dictionary_t, 1> dict,
1386
+ std::string key,
1387
+ std::string value
1388
+ ) {
1389
+ int err = av_dict_set(&dict->handle, key.c_str(), value.c_str(), 0);
1390
+ assert(err == 0);
1391
+ }
1392
+
1393
+ static std::optional<std::string>
1394
+ bare_ffmpeg_dictionary_get_entry(
1395
+ js_env_t *env,
1396
+ js_receiver_t,
1397
+ js_arraybuffer_span_of_t<bare_ffmpeg_dictionary_t, 1> dict,
1398
+ std::string key
1399
+ ) {
1400
+ AVDictionaryEntry *entry = av_dict_get(dict->handle, key.c_str(), NULL, 0);
1401
+
1402
+ if (entry == NULL) {
1403
+ return std::nullopt;
1404
+ }
1405
+
1406
+ return std::string{entry->value};
1407
+ }
1408
+
1409
+ static js_arraybuffer_t
1410
+ bare_ffmpeg_resampler_init(
1411
+ js_env_t *env,
1412
+ js_receiver_t,
1413
+ int32_t in_rate,
1414
+ int32_t in_fmt,
1415
+ js_arraybuffer_span_of_t<bare_ffmpeg_channel_layout_t, 1> in_layout,
1416
+ int32_t out_rate,
1417
+ int32_t out_fmt,
1418
+ js_arraybuffer_span_of_t<bare_ffmpeg_channel_layout_t, 1> out_layout
1419
+ ) {
1420
+ int err;
1421
+
1422
+ js_arraybuffer_t handle;
1423
+
1424
+ bare_ffmpeg_resampler_t *resampler;
1425
+ err = js_create_arraybuffer(env, resampler, handle);
1426
+ assert(err == 0);
1427
+
1428
+ resampler->handle = swr_alloc();
1429
+
1430
+ err = swr_alloc_set_opts2(
1431
+ &resampler->handle,
1432
+ &out_layout->handle,
1433
+ static_cast<AVSampleFormat>(out_fmt),
1434
+ out_rate,
1435
+ &in_layout->handle,
1436
+ static_cast<AVSampleFormat>(in_fmt),
1437
+ in_rate,
1438
+ 0,
1439
+ NULL
1440
+ );
1441
+
1442
+ if (err < 0) {
1443
+ swr_free(&resampler->handle);
1444
+
1445
+ err = js_throw_error(env, NULL, av_err2str(err));
1446
+ assert(err == 0);
1447
+
1448
+ throw js_pending_exception;
1449
+ }
1450
+
1451
+ err = swr_init(resampler->handle);
1452
+
1453
+ if (err < 0) {
1454
+ swr_free(&resampler->handle);
1455
+
1456
+ err = js_throw_error(env, NULL, av_err2str(err));
1457
+ assert(err == 0);
1458
+
1459
+ throw js_pending_exception;
1460
+ }
1461
+
1462
+ return handle;
1463
+ }
1464
+
1465
+ static int64_t
1466
+ bare_ffmpeg_resampler_convert_frames(
1467
+ js_env_t *env,
1468
+ js_receiver_t,
1469
+ js_arraybuffer_span_of_t<bare_ffmpeg_resampler_t, 1> resampler,
1470
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> in_frame,
1471
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> out_frame
1472
+ ) {
1473
+ int err;
1474
+
1475
+ int result = swr_convert(
1476
+ resampler->handle,
1477
+ (uint8_t **) out_frame->handle->data,
1478
+ out_frame->handle->nb_samples,
1479
+ (const uint8_t **) in_frame->handle->data,
1480
+ in_frame->handle->nb_samples
1481
+ );
1482
+
1483
+ if (result < 0) {
1484
+ err = js_throw_error(env, NULL, av_err2str(result));
1485
+ assert(err == 0);
1486
+ throw js_pending_exception;
1487
+ }
1488
+
1489
+ out_frame->handle->nb_samples = result;
1490
+
1491
+ return result;
1492
+ }
1493
+
1494
+ static int64_t
1495
+ bare_ffmpeg_resampler_get_delay(
1496
+ js_env_t *env,
1497
+ js_receiver_t,
1498
+ js_arraybuffer_span_of_t<bare_ffmpeg_resampler_t, 1> resampler,
1499
+ int64_t base
1500
+ ) {
1501
+ return swr_get_delay(resampler->handle, base);
1502
+ }
1503
+
1504
+ static int64_t
1505
+ bare_ffmpeg_resampler_flush(
1506
+ js_env_t *env,
1507
+ js_receiver_t,
1508
+ js_arraybuffer_span_of_t<bare_ffmpeg_resampler_t, 1> resampler,
1509
+ js_arraybuffer_span_of_t<bare_ffmpeg_frame_t, 1> out_frame
1510
+ ) {
1511
+ int err;
1512
+
1513
+ int result = swr_convert(
1514
+ resampler->handle,
1515
+ out_frame->handle->data,
1516
+ out_frame->handle->nb_samples,
1517
+ NULL,
1518
+ 0
1519
+ );
1520
+
1521
+ if (result < 0) {
1522
+ err = js_throw_error(env, NULL, av_err2str(result));
1523
+ assert(err == 0);
1524
+ throw js_pending_exception;
1525
+ }
1526
+
1527
+ out_frame->handle->nb_samples = result;
1528
+
1529
+ return result;
1530
+ }
1531
+
1532
+ static void
1533
+ bare_ffmpeg_resampler_destroy(
1534
+ js_env_t *env,
1535
+ js_receiver_t,
1536
+ js_arraybuffer_span_of_t<bare_ffmpeg_resampler_t, 1> resampler
1537
+ ) {
1538
+ swr_free(&resampler->handle);
1539
+ }
1540
+
1541
+ static void
1542
+ bare_ffmpeg_channel_layout_destroy(
1543
+ js_env_t *env,
1544
+ js_receiver_t,
1545
+ js_arraybuffer_span_of_t<bare_ffmpeg_channel_layout_t, 1> layout
1546
+ ) {
1547
+ av_channel_layout_uninit(&layout->handle);
1548
+ }
1549
+
1550
+ static js_arraybuffer_t
1551
+ bare_ffmpeg_channel_layout_copy(
1552
+ js_env_t *env,
1553
+ js_receiver_t,
1554
+ js_arraybuffer_span_of_t<bare_ffmpeg_channel_layout_t, 1> layout
1555
+ ) {
1556
+ int err;
1557
+
1558
+ js_arraybuffer_t result;
1559
+
1560
+ bare_ffmpeg_channel_layout_t *copy;
1561
+ err = js_create_arraybuffer(env, copy, result);
1562
+ assert(err == 0);
1563
+
1564
+ err = av_channel_layout_copy(&copy->handle, &layout->handle);
1565
+ assert(err == 0);
1566
+
1567
+ return result;
1568
+ }
1569
+
1570
+ static int
1571
+ bare_ffmpeg_channel_layout_get_nb_channels(
1572
+ js_env_t *env,
1573
+ js_receiver_t,
1574
+ js_arraybuffer_span_of_t<bare_ffmpeg_channel_layout_t, 1> layout
1575
+ ) {
1576
+ return layout->handle.nb_channels;
1577
+ }
1578
+
1579
+ static js_arraybuffer_t
1580
+ bare_ffmpeg_channel_layout_from_mask(
1581
+ js_env_t *env,
1582
+ js_receiver_t,
1583
+ uint64_t mask
1584
+ ) {
1585
+ int err;
1586
+
1587
+ js_arraybuffer_t result;
1588
+
1589
+ bare_ffmpeg_channel_layout_t *layout;
1590
+ err = js_create_arraybuffer(env, layout, result);
1591
+ assert(err == 0);
1592
+
1593
+ err = av_channel_layout_from_mask(&layout->handle, mask);
1594
+ assert(err == 0);
1595
+
1596
+ return result;
1597
+ }
1598
+
1599
+ static js_value_t *
1600
+ bare_ffmpeg_exports(js_env_t *env, js_value_t *exports) {
1601
+ uv_once(&bare_ffmpeg__init_guard, bare_ffmpeg__on_init);
1602
+
1603
+ int err;
1604
+
1605
+ #define V(name, fn) \
1606
+ err = js_set_property<fn>(env, exports, name); \
1607
+ assert(err == 0);
1608
+
1609
+ V("initIOContext", bare_ffmpeg_io_context_init)
1610
+ V("destroyIOContext", bare_ffmpeg_io_context_destroy)
1611
+
1612
+ V("initOutputFormat", bare_ffmpeg_output_format_init)
1613
+ V("initInputFormat", bare_ffmpeg_input_format_init)
1614
+
1615
+ V("openInputFormatContextWithIO", bare_ffmpeg_format_context_open_input_with_io)
1616
+ V("openInputFormatContextWithFormat", bare_ffmpeg_format_context_open_input_with_format)
1617
+ V("closeInputFormatContext", bare_ffmpeg_format_context_close_input)
1618
+ V("openOutputFormatContext", bare_ffmpeg_format_context_open_output)
1619
+ V("closeOutputFormatContext", bare_ffmpeg_format_context_close_output)
1620
+ V("getFormatContextStreams", bare_ffmpeg_format_context_get_streams)
1621
+ V("getFormatContextBestStreamIndex", bare_ffmpeg_format_context_get_best_stream_index)
1622
+ V("createFormatContextStream", bare_ffmpeg_format_context_create_stream)
1623
+ V("readFormatContextFrame", bare_ffmpeg_format_context_read_frame)
1624
+
1625
+ V("getStreamCodec", bare_ffmpeg_stream_get_codec)
1626
+ V("getStreamCodecParameters", bare_ffmpeg_stream_get_codec_parameters)
1627
+
1628
+ V("findDecoderByID", bare_ffmpeg_find_decoder_by_id)
1629
+ V("findEncoderByID", bare_ffmpeg_find_encoder_by_id)
1630
+
1631
+ V("initCodecContext", bare_ffmpeg_codec_context_init)
1632
+ V("destroyCodecContext", bare_ffmpeg_codec_context_destroy)
1633
+ V("openCodecContext", bare_ffmpeg_codec_context_open)
1634
+ V("openCodecContextWithOptions", bare_ffmpeg_codec_context_open_with_options)
1635
+ V("getCodecContextPixelFormat", bare_ffmpeg_codec_context_get_pixel_format)
1636
+ V("setCodecContextPixelFormat", bare_ffmpeg_codec_context_set_pixel_format)
1637
+ V("getCodecContextWidth", bare_ffmpeg_codec_context_get_width)
1638
+ V("setCodecContextWidth", bare_ffmpeg_codec_context_set_width)
1639
+ V("getCodecContextHeight", bare_ffmpeg_codec_context_get_height)
1640
+ V("setCodecContextHeight", bare_ffmpeg_codec_context_set_height)
1641
+ V("getCodecContextSampleFormat", bare_ffmpeg_codec_context_get_sample_format)
1642
+ V("setCodecContextSampleFormat", bare_ffmpeg_codec_context_set_sample_format)
1643
+ V("getCodecContextTimeBase", bare_ffmpeg_codec_context_get_time_base)
1644
+ V("setCodecContextTimeBase", bare_ffmpeg_codec_context_set_time_base)
1645
+ V("getCodecContextChannelLayout", bare_ffmpeg_codec_context_get_channel_layout);
1646
+ V("setCodecContextChannelLayout", bare_ffmpeg_codec_context_set_channel_layout);
1647
+ V("getCodecContextSampleRate", bare_ffmpeg_codec_context_get_sample_rate);
1648
+ V("setCodecContextSampleRate", bare_ffmpeg_codec_context_set_sample_rate);
1649
+ V("sendCodecContextPacket", bare_ffmpeg_codec_context_send_packet)
1650
+ V("receiveCodecContextPacket", bare_ffmpeg_codec_context_receive_packet)
1651
+ V("sendCodecContextFrame", bare_ffmpeg_codec_context_send_frame)
1652
+ V("receiveCodecContextFrame", bare_ffmpeg_codec_context_receive_frame)
1653
+
1654
+ V("codecParametersFromContext", bare_ffmpeg_codec_parameters_from_context)
1655
+ V("codecParametersToContext", bare_ffmpeg_codec_parameters_to_context)
1656
+ V("getCodecParametersBitRate", bare_ffmpeg_codec_parameters_get_bit_rate)
1657
+ V("getCodecParametersBitsPerCodedSample", bare_ffmpeg_codec_parameters_get_bits_per_coded_sample)
1658
+ V("getCodecParametersBitsPerRawSample", bare_ffmpeg_codec_parameters_get_bits_per_raw_sample)
1659
+ V("getCodecParametersFormat", bare_ffmpeg_codec_parameters_get_format)
1660
+ V("getCodecParametersSampleRate", bare_ffmpeg_codec_parameters_get_sample_rate)
1661
+ V("getCodecParametersNbChannels", bare_ffmpeg_codec_parameters_get_nb_channels)
1662
+ V("getCodecParametersCodecType", bare_ffmpeg_codec_parameters_get_codec_type)
1663
+ V("getCodecParametersChannelLayout", bare_ffmpeg_codec_parameters_get_channel_layout)
1664
+
1665
+ V("initFrame", bare_ffmpeg_frame_init)
1666
+ V("destroyFrame", bare_ffmpeg_frame_destroy)
1667
+ V("getFrameWidth", bare_ffmpeg_frame_get_width)
1668
+ V("setFrameWidth", bare_ffmpeg_frame_set_width)
1669
+ V("getFrameHeight", bare_ffmpeg_frame_get_height)
1670
+ V("setFrameHeight", bare_ffmpeg_frame_set_height)
1671
+ V("getFramePixelFormat", bare_ffmpeg_frame_get_pixel_format)
1672
+ V("setFramePixelFormat", bare_ffmpeg_frame_set_pixel_format)
1673
+ V("getFrameFormat", bare_ffmpeg_frame_get_format)
1674
+ V("setFrameFormat", bare_ffmpeg_frame_set_format)
1675
+ V("getFrameChannelLayout", bare_ffmpeg_frame_get_channel_layout)
1676
+ V("setFrameChannelLayout", bare_ffmpeg_frame_set_channel_layout)
1677
+ V("getFrameNbSamples", bare_ffmpeg_frame_get_nb_samples)
1678
+ V("setFrameNbSamples", bare_ffmpeg_frame_set_nb_samples)
1679
+ V("allocFrame", bare_ffmpeg_frame_alloc)
1680
+
1681
+ V("initImage", bare_ffmpeg_image_init)
1682
+ V("fillImage", bare_ffmpeg_image_fill)
1683
+ V("getImageLineSize", bare_ffmpeg_image_get_line_size)
1684
+
1685
+ V("initSamples", bare_ffmpeg_samples_init)
1686
+ V("fillSamples", bare_ffmpeg_samples_fill)
1687
+
1688
+ V("initPacket", bare_ffmpeg_packet_init)
1689
+ V("initPacketFromBuffer", bare_ffmpeg_packet_init_from_buffer)
1690
+ V("unrefPacket", bare_ffmpeg_packet_unref)
1691
+ V("getPacketStreamIndex", bare_ffmpeg_packet_get_stream_index)
1692
+ V("getPacketData", bare_ffmpeg_packet_get_data)
1693
+
1694
+ V("initScaler", bare_ffmpeg_scaler_init)
1695
+ V("destroyScaler", bare_ffmpeg_scaler_destroy)
1696
+ V("scaleScaler", bare_ffmpeg_scaler_scale)
1697
+
1698
+ V("initDictionary", bare_ffmpeg_dictionary_init)
1699
+ V("destroyDictionary", bare_ffmpeg_dictionary_destroy)
1700
+ V("getDictionaryEntry", bare_ffmpeg_dictionary_get_entry)
1701
+ V("setDictionaryEntry", bare_ffmpeg_dictionary_set_entry)
1702
+
1703
+ V("initResampler", bare_ffmpeg_resampler_init)
1704
+ V("destroyResampler", bare_ffmpeg_resampler_destroy)
1705
+ V("convertResampler", bare_ffmpeg_resampler_convert_frames)
1706
+ V("getResamplerDelay", bare_ffmpeg_resampler_get_delay)
1707
+ V("flushResampler", bare_ffmpeg_resampler_flush)
1708
+
1709
+ V("destroyChannelLayout", bare_ffmpeg_channel_layout_destroy)
1710
+ V("copyChannelLayout", bare_ffmpeg_channel_layout_copy)
1711
+ V("getChannelLayoutNbChannels", bare_ffmpeg_channel_layout_get_nb_channels)
1712
+ V("channelLayoutFromMask", bare_ffmpeg_channel_layout_from_mask)
1713
+ #undef V
1714
+
1715
+ #define V(name) \
1716
+ { \
1717
+ js_value_t *val; \
1718
+ err = js_create_int64(env, name, &val); \
1719
+ assert(err == 0); \
1720
+ err = js_set_named_property(env, exports, #name, val); \
1721
+ assert(err == 0); \
1722
+ }
1723
+
1724
+ V(AV_CODEC_ID_MJPEG)
1725
+ V(AV_CODEC_ID_H264)
1726
+ V(AV_CODEC_ID_AAC)
1727
+ V(AV_CODEC_ID_OPUS)
1728
+ V(AV_CODEC_ID_AV1)
1729
+
1730
+ V(AV_PIX_FMT_RGBA)
1731
+ V(AV_PIX_FMT_RGB24)
1732
+ V(AV_PIX_FMT_YUVJ420P)
1733
+ V(AV_PIX_FMT_YUV420P)
1734
+
1735
+ V(AVMEDIA_TYPE_UNKNOWN)
1736
+ V(AVMEDIA_TYPE_VIDEO)
1737
+ V(AVMEDIA_TYPE_AUDIO)
1738
+ V(AVMEDIA_TYPE_DATA)
1739
+ V(AVMEDIA_TYPE_SUBTITLE)
1740
+ V(AVMEDIA_TYPE_ATTACHMENT)
1741
+ V(AVMEDIA_TYPE_NB)
1742
+
1743
+ V(AV_SAMPLE_FMT_NONE)
1744
+ V(AV_SAMPLE_FMT_U8)
1745
+ V(AV_SAMPLE_FMT_S16)
1746
+ V(AV_SAMPLE_FMT_S32)
1747
+ V(AV_SAMPLE_FMT_FLT)
1748
+ V(AV_SAMPLE_FMT_DBL)
1749
+ V(AV_SAMPLE_FMT_U8P)
1750
+ V(AV_SAMPLE_FMT_S16P)
1751
+ V(AV_SAMPLE_FMT_S32P)
1752
+ V(AV_SAMPLE_FMT_FLTP)
1753
+ V(AV_SAMPLE_FMT_DBLP)
1754
+ V(AV_SAMPLE_FMT_S64)
1755
+ V(AV_SAMPLE_FMT_S64P)
1756
+ V(AV_SAMPLE_FMT_NB)
1757
+
1758
+ V(AV_CH_LAYOUT_MONO)
1759
+ V(AV_CH_LAYOUT_STEREO)
1760
+ V(AV_CH_LAYOUT_QUAD)
1761
+ V(AV_CH_LAYOUT_SURROUND)
1762
+ V(AV_CH_LAYOUT_2POINT1)
1763
+ V(AV_CH_LAYOUT_5POINT0)
1764
+ V(AV_CH_LAYOUT_5POINT1)
1765
+ V(AV_CH_LAYOUT_7POINT1)
1766
+ #undef V
1767
+
1768
+ return exports;
1769
+ }
1770
+
1771
+ BARE_MODULE(bare_ffmpeg, bare_ffmpeg_exports)