diff --git a/src/misc/coders/Encoders/index.js b/src/misc/coders/Encoders/index.js index c7c33e0..ec5380b 100644 --- a/src/misc/coders/Encoders/index.js +++ b/src/misc/coders/Encoders/index.js @@ -16,6 +16,7 @@ import * as H264OMX from './video/H264OMX'; import * as H264V4L2M2M from './video/H264V4L2M2M'; import * as H264VAAPI from './video/H264VAAPI'; import * as HEVCVAAPI from './video/HEVCVAAPI'; +import * as HEVCVideoToolbox from './video/HEVCVideoToolbox'; import * as VP9VAAPI from './video/VP9VAAPI'; import * as VideoCopy from './video/Copy'; import * as VideoNone from './video/None'; @@ -130,6 +131,7 @@ videoRegistry.Register(H264OMX); videoRegistry.Register(H264V4L2M2M); videoRegistry.Register(H264VAAPI); videoRegistry.Register(HEVCVAAPI); +videoRegistry.Register(HEVCVideoToolbox); videoRegistry.Register(VP9VAAPI); videoRegistry.Register(VP9); videoRegistry.Register(VideoRaw); diff --git a/src/misc/coders/Encoders/video/HEVCVideoToolbox.js b/src/misc/coders/Encoders/video/HEVCVideoToolbox.js new file mode 100644 index 0000000..d8cd20f --- /dev/null +++ b/src/misc/coders/Encoders/video/HEVCVideoToolbox.js @@ -0,0 +1,149 @@ +import React from 'react'; + +import Grid from '@mui/material/Grid'; +import MenuItem from '@mui/material/MenuItem'; + +import { Trans } from '@lingui/macro'; + +import Select from '../../../Select'; +import Video from '../../settings/Video'; +import Helper from '../../helper'; + +function init(initialState) { + const state = { + bitrate: '4096', + fps: '25', + gop: '2', + profile: 'auto', + ...initialState, + }; + + return state; +} + +function createMapping(settings, stream, skills) { + stream = Helper.InitStream(stream); + skills = Helper.InitSkills(skills); + + const local = [ + '-codec:v', + 'hevc_videotoolbox', + '-b:v', + `${settings.bitrate}k`, + '-maxrate:v', + `${settings.bitrate}k`, + '-bufsize:v', + `${settings.bitrate}k`, + '-r', + `${settings.fps}`, + '-pix_fmt', + 'yuv420p', + '-realtime', + 'true', + ]; + + if (settings.gop !== 'auto') { + local.push('-g', `${Math.round(parseInt(settings.fps) * parseInt(settings.gop)).toFixed(0)}`); + } + + if (settings.profile !== 'auto') { + local.push('-profile:v', `${settings.profile}`); + } + + const mapping = { + global: [], + local: local, + }; + + return mapping; +} + +function Profile(props) { + return ( + + ); +} + +Profile.defaultProps = { + value: '', + onChange: function (event) {}, +}; + +function Coder(props) { + const settings = init(props.settings); + const stream = Helper.InitStream(props.stream); + const skills = Helper.InitSkills(props.skills); + + const handleChange = (newSettings) => { + let automatic = false; + if (!newSettings) { + newSettings = settings; + automatic = true; + } + + props.onChange(newSettings, createMapping(newSettings, stream, skills), automatic); + }; + + const update = (what) => (event) => { + const newSettings = { + ...settings, + [what]: event.target.value, + }; + + handleChange(newSettings); + }; + + React.useEffect(() => { + handleChange(null); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + + + + + + + + + + + + + + + ); +} + +Coder.defaultProps = { + stream: {}, + settings: {}, + skills: {}, + onChange: function (settings, mapping) {}, +}; + +const coder = 'hevc_videotoolbox'; +const name = 'HEVC (VideoToolbox)'; +const codec = 'hevc'; +const type = 'video'; +const hwaccel = true; + +function summarize(settings) { + return `${name}, ${settings.bitrate} kbit/s, ${settings.fps} FPS, Profile: ${settings.profile}`; +} + +function defaults(stream, skills) { + const settings = init({}); + + return { + settings: settings, + mapping: createMapping(settings, stream, skills), + }; +} + +export { coder, name, codec, type, hwaccel, summarize, defaults, Coder as component };