@scrypted/libav 1.0.172 → 1.0.174
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/package.json +1 -1
- package/.vscode/launch.json +0 -23
- package/.vscode/settings.json +0 -32
- package/darwin.md +0 -24
- package/src/bsf.cpp +0 -213
- package/src/bsf.h +0 -35
- package/src/build-ffmpeg-darwin.sh +0 -13
- package/src/build-ffmpeg-linux.sh +0 -52
- package/src/build-ffmpeg-msys.sh +0 -41
- package/src/build-ffmpeg-windows.bat +0 -8
- package/src/codeccontext.cpp +0 -602
- package/src/codeccontext.h +0 -50
- package/src/error.cpp +0 -33
- package/src/error.h +0 -19
- package/src/ffmpeg-graphparser.cpp +0 -302
- package/src/filter.cpp +0 -487
- package/src/filter.h +0 -37
- package/src/flags.ts +0 -63
- package/src/formatcontext.cpp +0 -899
- package/src/formatcontext.h +0 -47
- package/src/frame.cpp +0 -667
- package/src/frame.h +0 -55
- package/src/index.ts +0 -356
- package/src/packet.cpp +0 -182
- package/src/packet.h +0 -42
- package/src/pkgconfig/glslang.pc +0 -10
- package/src/profiles.ts +0 -108
- package/src/tsconfig.json +0 -26
- package/tsconfig.json +0 -26
package/src/filter.cpp
DELETED
|
@@ -1,487 +0,0 @@
|
|
|
1
|
-
#include <napi.h>
|
|
2
|
-
|
|
3
|
-
extern "C"
|
|
4
|
-
{
|
|
5
|
-
#include <libavfilter/avfilter.h>
|
|
6
|
-
#include <libavfilter/buffersrc.h>
|
|
7
|
-
#include <libavfilter/buffersink.h>
|
|
8
|
-
#include <libavutil/opt.h>
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
#include "frame.h"
|
|
12
|
-
#include "error.h"
|
|
13
|
-
#include "filter.h"
|
|
14
|
-
|
|
15
|
-
#include "ffmpeg-graphparser.cpp"
|
|
16
|
-
|
|
17
|
-
Napi::FunctionReference AVFilterGraphObject::constructor;
|
|
18
|
-
|
|
19
|
-
Napi::Object AVFilterGraphObject::Init(Napi::Env env, Napi::Object exports)
|
|
20
|
-
{
|
|
21
|
-
Napi::HandleScope scope(env);
|
|
22
|
-
|
|
23
|
-
Napi::Function func = DefineClass(env, "AVFilterGraphObject", {
|
|
24
|
-
|
|
25
|
-
InstanceMethod(Napi::Symbol::WellKnown(env, "dispose"), &AVFilterGraphObject::Destroy),
|
|
26
|
-
|
|
27
|
-
InstanceMethod("destroy", &AVFilterGraphObject::Destroy),
|
|
28
|
-
|
|
29
|
-
InstanceMethod("addFrame", &AVFilterGraphObject::AddFrame),
|
|
30
|
-
|
|
31
|
-
InstanceMethod("getFrame", &AVFilterGraphObject::GetFrame),
|
|
32
|
-
|
|
33
|
-
InstanceMethod("sendCommand", &AVFilterGraphObject::SendCommand)});
|
|
34
|
-
|
|
35
|
-
constructor = Napi::Persistent(func);
|
|
36
|
-
constructor.SuppressDestruct();
|
|
37
|
-
|
|
38
|
-
exports.Set("AVFilter", func);
|
|
39
|
-
|
|
40
|
-
return exports;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
AVFilterGraphObject::AVFilterGraphObject(const Napi::CallbackInfo &info)
|
|
44
|
-
: Napi::ObjectWrap<AVFilterGraphObject>(info), filterGraph(nullptr)
|
|
45
|
-
{
|
|
46
|
-
filterGraph = nullptr;
|
|
47
|
-
|
|
48
|
-
Napi::Env env = info.Env();
|
|
49
|
-
|
|
50
|
-
if (info.Length() < 1 || !info[0].IsObject())
|
|
51
|
-
{
|
|
52
|
-
Napi::TypeError::New(env, "Object expected for argument 0: options").ThrowAsJavaScriptException();
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// need filter, frames
|
|
57
|
-
Napi::Object options = info[0].As<Napi::Object>();
|
|
58
|
-
|
|
59
|
-
Napi::Value filterValue = options.Get("filter");
|
|
60
|
-
if (!filterValue.IsString())
|
|
61
|
-
{
|
|
62
|
-
Napi::TypeError::New(env, "String expected for filter").ThrowAsJavaScriptException();
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
std::string hardwareDevice;
|
|
67
|
-
Napi::Value hardwareDeviceValue = options.Get("hardwareDevice");
|
|
68
|
-
if (hardwareDeviceValue.IsString())
|
|
69
|
-
{
|
|
70
|
-
hardwareDevice = hardwareDeviceValue.As<Napi::String>().Utf8Value();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
std::string hardwareDeviceName;
|
|
74
|
-
Napi::Value hardwareDeviceNameValue = options.Get("hardwareDeviceName");
|
|
75
|
-
if (hardwareDeviceNameValue.IsString())
|
|
76
|
-
{
|
|
77
|
-
if (!hardwareDevice.size())
|
|
78
|
-
{
|
|
79
|
-
Napi::TypeError::New(env, "hardwareDevice must be set if hardwareDeviceName is set").ThrowAsJavaScriptException();
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
hardwareDeviceName = hardwareDeviceNameValue.As<Napi::String>().Utf8Value();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
AVBufferRef *hw_device_ctx = NULL;
|
|
86
|
-
Napi::Value hardwareDeviceFrame = options.Get("hardwareDeviceFrame");
|
|
87
|
-
if (hardwareDeviceFrame.IsObject())
|
|
88
|
-
{
|
|
89
|
-
if (hardwareDevice.size())
|
|
90
|
-
{
|
|
91
|
-
Napi::TypeError::New(env, "hardwareDevice must not be set if hardwareDeviceFrame is set").ThrowAsJavaScriptException();
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
AVFrameObject *frameObject = Napi::ObjectWrap<AVFrameObject>::Unwrap(hardwareDeviceFrame.As<Napi::Object>());
|
|
96
|
-
AVFrame *frame = frameObject->frame_;
|
|
97
|
-
if (!frame || !frame->hw_frames_ctx)
|
|
98
|
-
{
|
|
99
|
-
Napi::TypeError::New(env, "Invalid hardwareDeviceFrame").ThrowAsJavaScriptException();
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
AVHWFramesContext *frames_ctx = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
|
|
104
|
-
hw_device_ctx = frames_ctx->device_ref;
|
|
105
|
-
}
|
|
106
|
-
else if (hardwareDevice.length())
|
|
107
|
-
{
|
|
108
|
-
// get hardware device type by string
|
|
109
|
-
enum AVHWDeviceType type = av_hwdevice_find_type_by_name(hardwareDevice.c_str());
|
|
110
|
-
if (type == AV_HWDEVICE_TYPE_NONE)
|
|
111
|
-
{
|
|
112
|
-
Napi::Error::New(env, "Failed to find hardware device type").ThrowAsJavaScriptException();
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const char *hardwareDeviceNameStr = hardwareDeviceName.length() ? hardwareDeviceName.c_str() : nullptr;
|
|
117
|
-
if (av_hwdevice_ctx_create(&hw_device_ctx, type, hardwareDeviceNameStr, NULL, 0) < 0)
|
|
118
|
-
{
|
|
119
|
-
Napi::Error::New(env, "Failed to create hardware device context").ThrowAsJavaScriptException();
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
Napi::Value framesValue = options.Get("frames");
|
|
125
|
-
if (!framesValue.IsArray())
|
|
126
|
-
{
|
|
127
|
-
Napi::TypeError::New(env, "Array expected for frames").ThrowAsJavaScriptException();
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
std::vector<AVFrame *> frames;
|
|
131
|
-
std::vector<Napi::Object> timeBases;
|
|
132
|
-
Napi::Array framesArray = framesValue.As<Napi::Array>();
|
|
133
|
-
for (unsigned int i = 0; i < framesArray.Length(); i++)
|
|
134
|
-
{
|
|
135
|
-
Napi::Value frameValue = framesArray.Get(i);
|
|
136
|
-
if (!frameValue.IsObject())
|
|
137
|
-
{
|
|
138
|
-
Napi::TypeError::New(env, "Object expected for frames").ThrowAsJavaScriptException();
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
Napi::Value timebaseValue = frameValue.As<Napi::Object>().Get("timeBase");
|
|
142
|
-
if (!timebaseValue.IsObject())
|
|
143
|
-
{
|
|
144
|
-
Napi::TypeError::New(env, "Object expected for timeBase").ThrowAsJavaScriptException();
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
Napi::Object timebaseObject = timebaseValue.As<Napi::Object>();
|
|
148
|
-
// validate the timebase object
|
|
149
|
-
if (!timebaseObject.Has("timeBaseNum") || !timebaseObject.Get("timeBaseNum").IsNumber() ||
|
|
150
|
-
!timebaseObject.Has("timeBaseDen") || !timebaseObject.Get("timeBaseDen").IsNumber())
|
|
151
|
-
{
|
|
152
|
-
Napi::TypeError::New(env, "invalid object for timeBase").ThrowAsJavaScriptException();
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
timeBases.push_back(timebaseObject);
|
|
157
|
-
|
|
158
|
-
Napi::Value frameFrameValue = frameValue.As<Napi::Object>().Get("frame");
|
|
159
|
-
if (!frameFrameValue.IsObject())
|
|
160
|
-
{
|
|
161
|
-
Napi::TypeError::New(env, "Object expected for frame").ThrowAsJavaScriptException();
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
AVFrameObject *frameObject = Napi::ObjectWrap<AVFrameObject>::Unwrap(frameFrameValue.As<Napi::Object>());
|
|
165
|
-
if (!frameObject->frame_)
|
|
166
|
-
{
|
|
167
|
-
Napi::Error::New(env, "Invalid frame").ThrowAsJavaScriptException();
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
frames.push_back(frameObject->frame_);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// outCount is the number of output frames
|
|
174
|
-
Napi::Value outCountValue = options.Get("outCount");
|
|
175
|
-
unsigned int outCount = 1;
|
|
176
|
-
if (outCountValue.IsNumber())
|
|
177
|
-
{
|
|
178
|
-
outCount = outCountValue.As<Napi::Number>().Int32Value();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// threadCount
|
|
182
|
-
Napi::Value threadCountValue = options.Get("threadCount");
|
|
183
|
-
int threadCount = -1;
|
|
184
|
-
if (threadCountValue.IsNumber())
|
|
185
|
-
{
|
|
186
|
-
threadCount = threadCountValue.As<Napi::Number>().Int32Value();
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
std::string filter_descr = filterValue.As<Napi::String>().Utf8Value();
|
|
190
|
-
|
|
191
|
-
char args[512];
|
|
192
|
-
int ret = 0;
|
|
193
|
-
const AVFilter *buffersrc = avfilter_get_by_name("buffer");
|
|
194
|
-
const AVFilter *buffersink = avfilter_get_by_name("buffersink");
|
|
195
|
-
AVFilterInOut *outputs = nullptr;
|
|
196
|
-
AVFilterInOut *inputs = nullptr;
|
|
197
|
-
|
|
198
|
-
struct AVFilterGraph *filter_graph = avfilter_graph_alloc();
|
|
199
|
-
if (threadCount > 0)
|
|
200
|
-
filter_graph->nb_threads = threadCount;
|
|
201
|
-
avfilter_graph_set_auto_convert(filter_graph, AVFILTER_AUTO_CONVERT_NONE);
|
|
202
|
-
if (!filter_graph)
|
|
203
|
-
{
|
|
204
|
-
Napi::Error::New(env, "filter graph creation failed").ThrowAsJavaScriptException();
|
|
205
|
-
goto end;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
for (unsigned int i = 0; i < frames.size(); i++)
|
|
209
|
-
{
|
|
210
|
-
AVFrame *frame_ = frames[i];
|
|
211
|
-
Napi::Object timeBase = timeBases[i];
|
|
212
|
-
int timeBaseNum = timeBase.Get("timeBaseNum").As<Napi::Number>().Int32Value();
|
|
213
|
-
int timeBaseDen = timeBase.Get("timeBaseDen").As<Napi::Number>().Int32Value();
|
|
214
|
-
|
|
215
|
-
snprintf(args, sizeof(args),
|
|
216
|
-
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
|
|
217
|
-
frame_->width, frame_->height, frame_->format,
|
|
218
|
-
timeBaseNum, timeBaseDen,
|
|
219
|
-
1, 1);
|
|
220
|
-
|
|
221
|
-
char name[512];
|
|
222
|
-
snprintf(name, sizeof(name), frames.size() == 1 ? "in" : "in%d", i);
|
|
223
|
-
AVFilterContext *buffersrc_ctx;
|
|
224
|
-
|
|
225
|
-
buffersrc_ctx = avfilter_graph_alloc_filter(filter_graph, buffersrc, name);
|
|
226
|
-
if (!buffersrc_ctx)
|
|
227
|
-
{
|
|
228
|
-
Napi::Error::New(env, "Cannot alloc buffer source").ThrowAsJavaScriptException();
|
|
229
|
-
goto end;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (frame_->hw_frames_ctx)
|
|
233
|
-
{
|
|
234
|
-
AVBufferSrcParameters *src_params = av_buffersrc_parameters_alloc();
|
|
235
|
-
if (!src_params)
|
|
236
|
-
{
|
|
237
|
-
Napi::Error::New(env, "Failed to allocate buffer source parameters").ThrowAsJavaScriptException();
|
|
238
|
-
goto end;
|
|
239
|
-
}
|
|
240
|
-
src_params->hw_frames_ctx = av_buffer_ref(frame_->hw_frames_ctx);
|
|
241
|
-
|
|
242
|
-
ret = av_buffersrc_parameters_set(buffersrc_ctx, src_params);
|
|
243
|
-
av_freep(&src_params);
|
|
244
|
-
|
|
245
|
-
if (ret < 0)
|
|
246
|
-
{
|
|
247
|
-
Napi::Error::New(env, "Failed to set buffer source parameters").ThrowAsJavaScriptException();
|
|
248
|
-
goto end;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
ret = avfilter_init_str(buffersrc_ctx, args);
|
|
253
|
-
if (ret < 0)
|
|
254
|
-
{
|
|
255
|
-
Napi::Error::New(env, "Cannot oimot buffer source").ThrowAsJavaScriptException();
|
|
256
|
-
goto end;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (ret < 0)
|
|
260
|
-
{
|
|
261
|
-
Napi::Error::New(env, "Cannot create buffer source").ThrowAsJavaScriptException();
|
|
262
|
-
goto end;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
buffersrc_ctxs.push_back(buffersrc_ctx);
|
|
266
|
-
|
|
267
|
-
AVFilterInOut *output = avfilter_inout_alloc();
|
|
268
|
-
if (!output)
|
|
269
|
-
{
|
|
270
|
-
Napi::Error::New(env, "Cannot allocate output").ThrowAsJavaScriptException();
|
|
271
|
-
goto end;
|
|
272
|
-
}
|
|
273
|
-
output->name = av_strdup(name);
|
|
274
|
-
output->filter_ctx = buffersrc_ctx;
|
|
275
|
-
output->pad_idx = 0;
|
|
276
|
-
output->next = NULL;
|
|
277
|
-
|
|
278
|
-
if (!outputs)
|
|
279
|
-
{
|
|
280
|
-
outputs = output;
|
|
281
|
-
}
|
|
282
|
-
else
|
|
283
|
-
{
|
|
284
|
-
AVFilterInOut *lastOutput = outputs;
|
|
285
|
-
while (lastOutput->next)
|
|
286
|
-
{
|
|
287
|
-
lastOutput = lastOutput->next;
|
|
288
|
-
}
|
|
289
|
-
lastOutput->next = output;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
for (unsigned int i = 0; i < outCount; i++)
|
|
294
|
-
{
|
|
295
|
-
char name[512];
|
|
296
|
-
snprintf(name, sizeof(name), outCount == 1 ? "out" : "out%d", i);
|
|
297
|
-
|
|
298
|
-
AVFilterContext *buffersink_ctx;
|
|
299
|
-
ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, name,
|
|
300
|
-
NULL, NULL, filter_graph);
|
|
301
|
-
if (ret < 0)
|
|
302
|
-
{
|
|
303
|
-
Napi::Error::New(env, "Cannot create buffer sink").ThrowAsJavaScriptException();
|
|
304
|
-
goto end;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
buffersink_ctxs.push_back(buffersink_ctx);
|
|
308
|
-
|
|
309
|
-
AVFilterInOut *input = avfilter_inout_alloc();
|
|
310
|
-
if (!input)
|
|
311
|
-
{
|
|
312
|
-
Napi::Error::New(env, "Cannot allocate input").ThrowAsJavaScriptException();
|
|
313
|
-
goto end;
|
|
314
|
-
}
|
|
315
|
-
input->name = av_strdup(name);
|
|
316
|
-
input->filter_ctx = buffersink_ctx;
|
|
317
|
-
input->pad_idx = 0;
|
|
318
|
-
input->next = NULL;
|
|
319
|
-
|
|
320
|
-
if (!inputs)
|
|
321
|
-
{
|
|
322
|
-
inputs = input;
|
|
323
|
-
}
|
|
324
|
-
else
|
|
325
|
-
{
|
|
326
|
-
AVFilterInOut *lastInput = inputs;
|
|
327
|
-
while (lastInput->next)
|
|
328
|
-
{
|
|
329
|
-
lastInput = lastInput->next;
|
|
330
|
-
}
|
|
331
|
-
lastInput->next = input;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if ((ret = avfilter_graph_parse_ptr2(filter_graph, filter_descr.c_str(),
|
|
336
|
-
&inputs, &outputs, hw_device_ctx)) < 0)
|
|
337
|
-
{
|
|
338
|
-
Napi::Error::New(env, "Cannot parse filter graph").ThrowAsJavaScriptException();
|
|
339
|
-
goto end;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
|
|
343
|
-
{
|
|
344
|
-
Napi::Error::New(env, "Cannot configure the filter graph").ThrowAsJavaScriptException();
|
|
345
|
-
goto end;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
avfilter_inout_free(&inputs);
|
|
349
|
-
avfilter_inout_free(&outputs);
|
|
350
|
-
filterGraph = filter_graph;
|
|
351
|
-
return;
|
|
352
|
-
|
|
353
|
-
end:
|
|
354
|
-
avfilter_graph_free(&filter_graph);
|
|
355
|
-
avfilter_inout_free(&inputs);
|
|
356
|
-
avfilter_inout_free(&outputs);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
AVFilterGraphObject::~AVFilterGraphObject()
|
|
360
|
-
{
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
Napi::Value AVFilterGraphObject::Destroy(const Napi::CallbackInfo &info)
|
|
364
|
-
{
|
|
365
|
-
if (filterGraph)
|
|
366
|
-
{
|
|
367
|
-
avfilter_graph_free(&filterGraph);
|
|
368
|
-
filterGraph = nullptr;
|
|
369
|
-
}
|
|
370
|
-
return info.Env().Undefined();
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
Napi::Value AVFilterGraphObject::SendCommand(const Napi::CallbackInfo &info)
|
|
374
|
-
{
|
|
375
|
-
// need four arguments
|
|
376
|
-
if (info.Length() < 3)
|
|
377
|
-
{
|
|
378
|
-
Napi::Error::New(info.Env(), "Expected 3 arguments to SendCommand").ThrowAsJavaScriptException();
|
|
379
|
-
return info.Env().Undefined();
|
|
380
|
-
}
|
|
381
|
-
// parse out left, top, width, and height arguments as strings
|
|
382
|
-
if (!info[0].IsString() || !info[1].IsString() || !info[2].IsString())
|
|
383
|
-
{
|
|
384
|
-
Napi::TypeError::New(info.Env(), "Strings expected").ThrowAsJavaScriptException();
|
|
385
|
-
return info.Env().Undefined();
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// get the strings from the arguments
|
|
389
|
-
std::string target = info[0].As<Napi::String>().Utf8Value();
|
|
390
|
-
std::string command = info[1].As<Napi::String>().Utf8Value();
|
|
391
|
-
std::string arg = info[2].As<Napi::String>().Utf8Value();
|
|
392
|
-
int ret;
|
|
393
|
-
|
|
394
|
-
// reset the x and y to zero so all widths and heights may be valid.
|
|
395
|
-
if ((ret = avfilter_graph_send_command(filterGraph, target.c_str(), command.c_str(), arg.c_str(), 0, 0, 0)) < 0)
|
|
396
|
-
{
|
|
397
|
-
av_log(NULL, AV_LOG_ERROR, "Error while sending command to target %s %s %s\n", target.c_str(), command.c_str(), arg.c_str());
|
|
398
|
-
Napi::Error::New(info.Env(), AVErrorString(ret)).ThrowAsJavaScriptException();
|
|
399
|
-
return info.Env().Undefined();
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
return info.Env().Undefined();
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
Napi::Value AVFilterGraphObject::AddFrame(const Napi::CallbackInfo &info)
|
|
406
|
-
{
|
|
407
|
-
if (info.Length() < 1 || !info[0].IsObject())
|
|
408
|
-
{
|
|
409
|
-
Napi::TypeError::New(info.Env(), "Frame object expected").ThrowAsJavaScriptException();
|
|
410
|
-
return info.Env().Undefined();
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
unsigned long index = 0;
|
|
414
|
-
if (info.Length() > 1 && info[1].IsNumber())
|
|
415
|
-
{
|
|
416
|
-
index = info[1].As<Napi::Number>().Int32Value();
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
AVFrameObject *frameObject = Napi::ObjectWrap<AVFrameObject>::Unwrap(info[0].As<Napi::Object>());
|
|
420
|
-
|
|
421
|
-
AVFrame *frame = frameObject->frame_;
|
|
422
|
-
|
|
423
|
-
if (!frame)
|
|
424
|
-
{
|
|
425
|
-
Napi::TypeError::New(info.Env(), "Frame object is null").ThrowAsJavaScriptException();
|
|
426
|
-
return info.Env().Undefined();
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (buffersrc_ctxs.size() <= index)
|
|
430
|
-
{
|
|
431
|
-
Napi::TypeError::New(info.Env(), "Buffersrc context is null").ThrowAsJavaScriptException();
|
|
432
|
-
return info.Env().Undefined();
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
AVFilterContext *buffersrc_ctx = buffersrc_ctxs[index];
|
|
436
|
-
|
|
437
|
-
// Feed the frame to the buffer source filter
|
|
438
|
-
int ret = av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF);
|
|
439
|
-
if (ret < 0)
|
|
440
|
-
{
|
|
441
|
-
Napi::Error::New(info.Env(), AVErrorString(ret)).ThrowAsJavaScriptException();
|
|
442
|
-
return info.Env().Undefined();
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
return info.Env().Undefined();
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
Napi::Value AVFilterGraphObject::GetFrame(const Napi::CallbackInfo &info)
|
|
449
|
-
{
|
|
450
|
-
unsigned long index = 0;
|
|
451
|
-
if (info.Length() && info[0].IsNumber())
|
|
452
|
-
{
|
|
453
|
-
index = info[0].As<Napi::Number>().Int32Value();
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
if (buffersink_ctxs.size() <= index)
|
|
457
|
-
{
|
|
458
|
-
Napi::TypeError::New(info.Env(), "Buffersink context is null").ThrowAsJavaScriptException();
|
|
459
|
-
return info.Env().Undefined();
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
AVFilterContext *buffersink_ctx = buffersink_ctxs[index];
|
|
463
|
-
|
|
464
|
-
AVFrame *filtered_frame = av_frame_alloc();
|
|
465
|
-
if (!filtered_frame)
|
|
466
|
-
{
|
|
467
|
-
Napi::Error::New(info.Env(), "Could not allocate filtered frame").ThrowAsJavaScriptException();
|
|
468
|
-
return info.Env().Undefined();
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// Get the filtered frame from the buffer sink filter
|
|
472
|
-
int ret = av_buffersink_get_frame(buffersink_ctx, filtered_frame);
|
|
473
|
-
// check for EAGAIN
|
|
474
|
-
if (ret == AVERROR(EAGAIN))
|
|
475
|
-
{
|
|
476
|
-
av_frame_free(&filtered_frame);
|
|
477
|
-
return info.Env().Undefined();
|
|
478
|
-
}
|
|
479
|
-
if (ret < 0)
|
|
480
|
-
{
|
|
481
|
-
av_frame_free(&filtered_frame);
|
|
482
|
-
Napi::Error::New(info.Env(), AVErrorString(ret)).ThrowAsJavaScriptException();
|
|
483
|
-
return info.Env().Undefined();
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
return AVFrameObject::NewInstance(info.Env(), filtered_frame);
|
|
487
|
-
}
|
package/src/filter.h
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include <napi.h>
|
|
4
|
-
|
|
5
|
-
extern "C"
|
|
6
|
-
{
|
|
7
|
-
#include <libavfilter/avfilter.h>
|
|
8
|
-
#include <libavfilter/buffersrc.h>
|
|
9
|
-
#include <libavfilter/buffersink.h>
|
|
10
|
-
#include <libavutil/opt.h>
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
#include "frame.h"
|
|
14
|
-
#include "error.h"
|
|
15
|
-
#include "filter.h"
|
|
16
|
-
|
|
17
|
-
class AVFilterGraphObject : public Napi::ObjectWrap<AVFilterGraphObject>
|
|
18
|
-
{
|
|
19
|
-
public:
|
|
20
|
-
static Napi::Object Init(Napi::Env env, Napi::Object exports);
|
|
21
|
-
|
|
22
|
-
AVFilterGraphObject(const Napi::CallbackInfo &info);
|
|
23
|
-
~AVFilterGraphObject();
|
|
24
|
-
|
|
25
|
-
std::vector<AVFilterContext*> buffersrc_ctxs;
|
|
26
|
-
std::vector<AVFilterContext*> buffersink_ctxs;
|
|
27
|
-
|
|
28
|
-
private:
|
|
29
|
-
static Napi::FunctionReference constructor;
|
|
30
|
-
|
|
31
|
-
Napi::Value Destroy(const Napi::CallbackInfo &info);
|
|
32
|
-
Napi::Value SendCommand(const Napi::CallbackInfo &info);
|
|
33
|
-
Napi::Value AddFrame(const Napi::CallbackInfo &info);
|
|
34
|
-
Napi::Value GetFrame(const Napi::CallbackInfo &info);
|
|
35
|
-
|
|
36
|
-
AVFilterGraph *filterGraph;
|
|
37
|
-
};
|
package/src/flags.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export enum AVPacketFlags {
|
|
2
|
-
AV_PKT_FLAG_KEY = 0x0001,
|
|
3
|
-
AV_PKT_FLAG_CORRUPT = 0x0002,
|
|
4
|
-
AV_PKT_FLAG_DISCARD = 0x0004,
|
|
5
|
-
AV_PKT_FLAG_TRUSTED = 0x0008,
|
|
6
|
-
AV_PKT_FLAG_DISPOSABLE = 0x0010,
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export enum AVFrameFlags {
|
|
10
|
-
AV_FRAME_FLAG_KEY = 0x0001,
|
|
11
|
-
AV_FRAME_FLAG_CORRUPT = 0x0002,
|
|
12
|
-
AV_FRAME_FLAG_DISCARD = 0x0004,
|
|
13
|
-
AV_FRAME_FLAG_TRUSTED = 0x0008,
|
|
14
|
-
AV_FRAME_FLAG_DISPOSABLE = 0x0010,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export enum AVPictureType {
|
|
18
|
-
AV_PICTURE_TYPE_NONE = 0, ///< Undefined
|
|
19
|
-
AV_PICTURE_TYPE_I, ///< Intra
|
|
20
|
-
AV_PICTURE_TYPE_P, ///< Predicted
|
|
21
|
-
AV_PICTURE_TYPE_B, ///< Bi-dir predicted
|
|
22
|
-
AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4
|
|
23
|
-
AV_PICTURE_TYPE_SI, ///< Switching Intra
|
|
24
|
-
AV_PICTURE_TYPE_SP, ///< Switching Predicted
|
|
25
|
-
AV_PICTURE_TYPE_BI ///< BI type
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export enum AVCodecFlags {
|
|
29
|
-
AV_CODEC_FLAG_UNALIGNED = 1 << 0,
|
|
30
|
-
AV_CODEC_FLAG_QSCALE = 1 << 1,
|
|
31
|
-
AV_CODEC_FLAG_4MV = 1 << 2,
|
|
32
|
-
AV_CODEC_FLAG_OUTPUT_CORRUPT = 1 << 3,
|
|
33
|
-
AV_CODEC_FLAG_QPEL = 1 << 4,
|
|
34
|
-
AV_CODEC_FLAG_DROPCHANGED = 1 << 5,
|
|
35
|
-
AV_CODEC_FLAG_RECON_FRAME = 1 << 6,
|
|
36
|
-
AV_CODEC_FLAG_COPY_OPAQUE = 1 << 7,
|
|
37
|
-
AV_CODEC_FLAG_FRAME_DURATION = 1 << 8,
|
|
38
|
-
AV_CODEC_FLAG_PASS1 = 1 << 9,
|
|
39
|
-
AV_CODEC_FLAG_PASS2 = 1 << 10,
|
|
40
|
-
AV_CODEC_FLAG_LOOP_FILTER = 1 << 11,
|
|
41
|
-
AV_CODEC_FLAG_GRAY = 1 << 13,
|
|
42
|
-
AV_CODEC_FLAG_PSNR = 1 << 15,
|
|
43
|
-
AV_CODEC_FLAG_INTERLACED_DCT = 1 << 18,
|
|
44
|
-
AV_CODEC_FLAG_LOW_DELAY = 1 << 19,
|
|
45
|
-
AV_CODEC_FLAG_GLOBAL_HEADER = 1 << 22,
|
|
46
|
-
AV_CODEC_FLAG_BITEXACT = 1 << 23,
|
|
47
|
-
AV_CODEC_FLAG_AC_PRED = 1 << 24,
|
|
48
|
-
AV_CODEC_FLAG_INTERLACED_ME = 1 << 29,
|
|
49
|
-
AV_CODEC_FLAG_CLOSED_GOP = 1 << 31,
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export enum AVCodecFlags2 {
|
|
53
|
-
AV_CODEC_FLAG2_FAST = 1 << 0,
|
|
54
|
-
AV_CODEC_FLAG2_NO_OUTPUT = 1 << 2,
|
|
55
|
-
AV_CODEC_FLAG2_LOCAL_HEADER = 1 << 3,
|
|
56
|
-
AV_CODEC_FLAG2_CHUNKS = 1 << 15,
|
|
57
|
-
AV_CODEC_FLAG2_IGNORE_CROP = 1 << 16,
|
|
58
|
-
AV_CODEC_FLAG2_SHOW_ALL = 1 << 22,
|
|
59
|
-
AV_CODEC_FLAG2_EXPORT_MVS = 1 << 28,
|
|
60
|
-
AV_CODEC_FLAG2_SKIP_MANUAL = 1 << 29,
|
|
61
|
-
AV_CODEC_FLAG2_RO_FLUSH_NOOP = 1 << 30,
|
|
62
|
-
AV_CODEC_FLAG2_ICC_PROFILES = 1 << 31,
|
|
63
|
-
}
|