Skip to content

Commit 626282e

Browse files
authored
feat(hw-frames-context): expose constraints (#192)
Signed-off-by: Tony Gorez <gorez.tony@gmail.com>
1 parent a01691d commit 626282e

7 files changed

Lines changed: 329 additions & 53 deletions

File tree

binding.cc

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ typedef struct {
143143
AVBufferRef *handle;
144144
} bare_ffmpeg_hw_frames_context_t;
145145

146+
typedef struct {
147+
AVHWFramesConstraints *handle;
148+
} bare_ffmpeg_hw_frames_constraints_t;
149+
146150
static uv_once_t bare_ffmpeg__init_guard = UV_ONCE_INIT;
147151

148152
static void
@@ -2718,6 +2722,113 @@ bare_ffmpeg_hw_frames_context_get_buffer(
27182722
}
27192723
}
27202724

2725+
static js_arraybuffer_t
2726+
bare_ffmpeg_hw_frames_context_get_constraints(
2727+
js_env_t *env,
2728+
js_receiver_t,
2729+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_context_t, 1> hw_frames_ctx
2730+
) {
2731+
int err;
2732+
2733+
AVHWFramesContext *frames_ctx = reinterpret_cast<AVHWFramesContext *>(hw_frames_ctx->handle->data);
2734+
2735+
AVHWFramesConstraints *constraints = av_hwdevice_get_hwframe_constraints(frames_ctx->device_ref, NULL);
2736+
if (!constraints) {
2737+
err = js_throw_error(env, NULL, "Failed to get hardware frame constraints");
2738+
assert(err == 0);
2739+
throw js_pending_exception;
2740+
}
2741+
2742+
js_arraybuffer_t handle;
2743+
bare_ffmpeg_hw_frames_constraints_t *hw_frames_constraints;
2744+
2745+
err = js_create_arraybuffer(env, hw_frames_constraints, handle);
2746+
assert(err == 0);
2747+
2748+
hw_frames_constraints->handle = constraints;
2749+
2750+
return handle;
2751+
}
2752+
2753+
static void
2754+
bare_ffmpeg_hw_frames_constraints_destroy(
2755+
js_env_t *env,
2756+
js_receiver_t,
2757+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_constraints_t, 1> hw_frames_constraints
2758+
) {
2759+
av_hwframe_constraints_free(&hw_frames_constraints->handle);
2760+
}
2761+
2762+
static std::vector<int32_t>
2763+
bare_ffmpeg_hw_frames_constraints_get_valid_sw_formats(
2764+
js_env_t *env,
2765+
js_receiver_t,
2766+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_constraints_t, 1> hw_frames_constraints
2767+
) {
2768+
std::vector<int32_t> formats;
2769+
2770+
if (hw_frames_constraints->handle->valid_sw_formats) {
2771+
for (int i = 0; hw_frames_constraints->handle->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
2772+
formats.push_back(hw_frames_constraints->handle->valid_sw_formats[i]);
2773+
}
2774+
}
2775+
2776+
return formats;
2777+
}
2778+
2779+
static std::vector<int32_t>
2780+
bare_ffmpeg_hw_frames_constraints_get_valid_hw_formats(
2781+
js_env_t *env,
2782+
js_receiver_t,
2783+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_constraints_t, 1> hw_frames_constraints
2784+
) {
2785+
std::vector<int32_t> formats;
2786+
2787+
if (hw_frames_constraints->handle->valid_hw_formats) {
2788+
for (int i = 0; hw_frames_constraints->handle->valid_hw_formats[i] != AV_PIX_FMT_NONE; i++) {
2789+
formats.push_back(hw_frames_constraints->handle->valid_hw_formats[i]);
2790+
}
2791+
}
2792+
2793+
return formats;
2794+
}
2795+
2796+
static int32_t
2797+
bare_ffmpeg_hw_frames_constraints_get_min_width(
2798+
js_env_t *env,
2799+
js_receiver_t,
2800+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_constraints_t, 1> hw_frames_constraints
2801+
) {
2802+
return hw_frames_constraints->handle->min_width;
2803+
}
2804+
2805+
static int32_t
2806+
bare_ffmpeg_hw_frames_constraints_get_max_width(
2807+
js_env_t *env,
2808+
js_receiver_t,
2809+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_constraints_t, 1> hw_frames_constraints
2810+
) {
2811+
return hw_frames_constraints->handle->max_width;
2812+
}
2813+
2814+
static int32_t
2815+
bare_ffmpeg_hw_frames_constraints_get_min_height(
2816+
js_env_t *env,
2817+
js_receiver_t,
2818+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_constraints_t, 1> hw_frames_constraints
2819+
) {
2820+
return hw_frames_constraints->handle->min_height;
2821+
}
2822+
2823+
static int32_t
2824+
bare_ffmpeg_hw_frames_constraints_get_max_height(
2825+
js_env_t *env,
2826+
js_receiver_t,
2827+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_constraints_t, 1> hw_frames_constraints
2828+
) {
2829+
return hw_frames_constraints->handle->max_height;
2830+
}
2831+
27212832
static int32_t
27222833
bare_ffmpeg_hw_frames_context_get_format(
27232834
js_env_t *env,
@@ -2802,6 +2913,27 @@ bare_ffmpeg_hw_frames_context_set_height(
28022913
ctx->height = height;
28032914
}
28042915

2916+
static int32_t
2917+
bare_ffmpeg_hw_frames_context_get_initial_pool_size(
2918+
js_env_t *env,
2919+
js_receiver_t,
2920+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_context_t, 1> hw_frames_ctx
2921+
) {
2922+
AVHWFramesContext *ctx = reinterpret_cast<AVHWFramesContext *>(hw_frames_ctx->handle->data);
2923+
return ctx->initial_pool_size;
2924+
}
2925+
2926+
static void
2927+
bare_ffmpeg_hw_frames_context_set_initial_pool_size(
2928+
js_env_t *env,
2929+
js_receiver_t,
2930+
js_arraybuffer_span_of_t<bare_ffmpeg_hw_frames_context_t, 1> hw_frames_ctx,
2931+
int32_t initial_pool_size
2932+
) {
2933+
AVHWFramesContext *ctx = reinterpret_cast<AVHWFramesContext *>(hw_frames_ctx->handle->data);
2934+
ctx->initial_pool_size = initial_pool_size;
2935+
}
2936+
28052937
static js_arraybuffer_t
28062938
bare_ffmpeg_image_init(
28072939
js_env_t *env,
@@ -4559,7 +4691,18 @@ bare_ffmpeg_exports(js_env_t *env, js_value_t *exports) {
45594691
V("setHWFramesContextWidth", bare_ffmpeg_hw_frames_context_set_width)
45604692
V("getHWFramesContextHeight", bare_ffmpeg_hw_frames_context_get_height)
45614693
V("setHWFramesContextHeight", bare_ffmpeg_hw_frames_context_set_height)
4694+
V("getHWFramesContextInitialPoolSize", bare_ffmpeg_hw_frames_context_get_initial_pool_size)
4695+
V("setHWFramesContextInitialPoolSize", bare_ffmpeg_hw_frames_context_set_initial_pool_size)
45624696
V("getHWFramesContextBuffer", bare_ffmpeg_hw_frames_context_get_buffer)
4697+
V("getHWFramesContextConstraints", bare_ffmpeg_hw_frames_context_get_constraints)
4698+
4699+
V("destroyHWFramesConstraints", bare_ffmpeg_hw_frames_constraints_destroy)
4700+
V("getHWFramesConstraintsValidSwFormats", bare_ffmpeg_hw_frames_constraints_get_valid_sw_formats)
4701+
V("getHWFramesConstraintsValidHwFormats", bare_ffmpeg_hw_frames_constraints_get_valid_hw_formats)
4702+
V("getHWFramesConstraintsMinWidth", bare_ffmpeg_hw_frames_constraints_get_min_width)
4703+
V("getHWFramesConstraintsMaxWidth", bare_ffmpeg_hw_frames_constraints_get_max_width)
4704+
V("getHWFramesConstraintsMinHeight", bare_ffmpeg_hw_frames_constraints_get_min_height)
4705+
V("getHWFramesConstraintsMaxHeight", bare_ffmpeg_hw_frames_constraints_get_max_height)
45634706

45644707
V("initImage", bare_ffmpeg_image_init)
45654708
V("fillImage", bare_ffmpeg_image_fill)

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const FilterInOut = require('./lib/filter-inout')
1414
const Frame = require('./lib/frame')
1515
const HWDeviceContext = require('./lib/hw-device-context')
1616
const HWFramesContext = require('./lib/hw-frames-context')
17+
const HWFramesConstraints = require('./lib/hw-frames-constraints')
1718
const IOContext = require('./lib/io-context')
1819
const Image = require('./lib/image')
1920
const InputFormat = require('./lib/input-format')
@@ -41,6 +42,7 @@ exports.FilterInOut = FilterInOut
4142
exports.Frame = Frame
4243
exports.HWDeviceContext = HWDeviceContext
4344
exports.HWFramesContext = HWFramesContext
45+
exports.HWFramesConstraints = HWFramesConstraints
4446
exports.IOContext = IOContext
4547
exports.Image = Image
4648
exports.InputFormat = InputFormat

lib/hw-frames-constraints.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const binding = require('../binding')
2+
3+
module.exports = class HWFramesConstraints {
4+
constructor(handle) {
5+
this._handle = handle
6+
}
7+
8+
get validSwFormats() {
9+
return binding.getHWFramesConstraintsValidSwFormats(this._handle)
10+
}
11+
12+
get validHwFormats() {
13+
return binding.getHWFramesConstraintsValidHwFormats(this._handle)
14+
}
15+
16+
get minWidth() {
17+
return binding.getHWFramesConstraintsMinWidth(this._handle)
18+
}
19+
20+
get maxWidth() {
21+
return binding.getHWFramesConstraintsMaxWidth(this._handle)
22+
}
23+
24+
get minHeight() {
25+
return binding.getHWFramesConstraintsMinHeight(this._handle)
26+
}
27+
28+
get maxHeight() {
29+
return binding.getHWFramesConstraintsMaxHeight(this._handle)
30+
}
31+
32+
// Note: HWFramesConstraints is independently allocated by FFmpeg and must be
33+
// explicitly freed. It is not owned by HWFramesContext.
34+
destroy() {
35+
binding.destroyHWFramesConstraints(this._handle)
36+
this._handle = null
37+
}
38+
39+
[Symbol.dispose]() {
40+
this.destroy()
41+
}
42+
43+
[Symbol.for('bare.inspect')]() {
44+
return {
45+
__proto__: { constructor: HWFramesConstraints },
46+
validSwFormats: this.validSwFormats,
47+
validHwFormats: this.validHwFormats,
48+
minWidth: this.minWidth,
49+
maxWidth: this.maxWidth,
50+
minHeight: this.minHeight,
51+
maxHeight: this.maxHeight
52+
}
53+
}
54+
}

lib/hw-frames-context.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const binding = require('../binding')
2+
const HWFramesConstraints = require('./hw-frames-constraints')
23

34
module.exports = class HWFramesContext {
45
constructor(hwDeviceContext, format, swFormat, width, height, handle = undefined) {
@@ -53,10 +54,23 @@ module.exports = class HWFramesContext {
5354
binding.setHWFramesContextHeight(this._handle, value)
5455
}
5556

57+
get initialPoolSize() {
58+
return binding.getHWFramesContextInitialPoolSize(this._handle)
59+
}
60+
61+
set initialPoolSize(value) {
62+
binding.setHWFramesContextInitialPoolSize(this._handle, value)
63+
}
64+
5665
getBuffer(frame) {
5766
binding.getHWFramesContextBuffer(this._handle, frame._handle)
5867
}
5968

69+
getConstraints() {
70+
const handle = binding.getHWFramesContextConstraints(this._handle)
71+
return new HWFramesConstraints(handle)
72+
}
73+
6074
destroy() {
6175
binding.destroyHWFramesContext(this._handle)
6276
this._handle = null

test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require('./test/filter-inout')
1414
require('./test/frame')
1515
require('./test/hw-device-context')
1616
require('./test/hw-frames-context')
17+
require('./test/hw-frames-constraints')
1718
require('./test/image')
1819
require('./test/input-format')
1920
require('./test/packet')

test/hw-frames-constraints.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
const test = require('brittle')
2+
const ffmpeg = require('..')
3+
const os = require('bare-os')
4+
5+
const darwinFilter = os.platform() !== 'darwin'
6+
7+
let hwDevice
8+
let hwFrames
9+
let constraints
10+
11+
test.hook('setup', { skip: darwinFilter }, () => {
12+
hwDevice = new ffmpeg.HWDeviceContext(ffmpeg.constants.hwDeviceTypes.VIDEOTOOLBOX)
13+
hwFrames = new ffmpeg.HWFramesContext(
14+
hwDevice,
15+
ffmpeg.constants.pixelFormats.VIDEOTOOLBOX,
16+
ffmpeg.constants.pixelFormats.NV12,
17+
640,
18+
480
19+
)
20+
constraints = hwFrames.getConstraints()
21+
})
22+
23+
test(
24+
'HWFramesConstraints should expose validSwFormats getter (darwin)',
25+
{ skip: darwinFilter },
26+
(t) => {
27+
t.ok(Array.isArray(constraints.validSwFormats))
28+
t.ok(constraints.validSwFormats.length > 0)
29+
}
30+
)
31+
32+
test(
33+
'HWFramesConstraints should expose validHwFormats getter (darwin)',
34+
{ skip: darwinFilter },
35+
(t) => {
36+
t.ok(Array.isArray(constraints.validHwFormats))
37+
t.ok(constraints.validHwFormats.length > 0)
38+
}
39+
)
40+
41+
test('HWFramesConstraints should expose minWidth getter (darwin)', { skip: darwinFilter }, (t) => {
42+
t.is(typeof constraints.minWidth, 'number')
43+
t.ok(constraints.minWidth >= 0)
44+
})
45+
46+
test('HWFramesConstraints should expose maxWidth getter (darwin)', { skip: darwinFilter }, (t) => {
47+
t.is(typeof constraints.maxWidth, 'number')
48+
t.ok(constraints.maxWidth >= 0)
49+
})
50+
51+
test('HWFramesConstraints should expose minHeight getter (darwin)', { skip: darwinFilter }, (t) => {
52+
t.is(typeof constraints.minHeight, 'number')
53+
t.ok(constraints.minHeight >= 0)
54+
})
55+
56+
test('HWFramesConstraints should expose maxHeight getter (darwin)', { skip: darwinFilter }, (t) => {
57+
t.is(typeof constraints.maxHeight, 'number')
58+
t.ok(constraints.maxHeight >= 0)
59+
})
60+
61+
test('HWFramesConstraints should have destroy method (darwin)', { skip: darwinFilter }, (t) => {
62+
t.ok(typeof constraints.destroy === 'function')
63+
})
64+
65+
test.hook('teardown', { skip: darwinFilter }, () => {
66+
constraints.destroy()
67+
hwFrames.destroy()
68+
hwDevice.destroy()
69+
})

0 commit comments

Comments
 (0)