bare-ffmpeg 1.0.0-11 → 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 +1771 -0
- package/cmake/ports/ffmpeg/port.cmake +513 -0
- package/cmake/ports/opus/patches/01-windows-clang.patch +52 -0
- package/cmake/ports/opus/port.cmake +38 -0
- package/cmake/ports/svt-av1/port.cmake +42 -0
- package/cmake/ports/x264/patches/01-windows-clang.patch +33 -0
- package/cmake/ports/x264/port.cmake +157 -0
- package/package.json +4 -3
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, ¶meters->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(©->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)
|