mirror of
https://github.com/viarotel-org/escrcpy.git
synced 2024-11-14 18:57:40 +01:00
perf: ♻️ optimize Codec
This commit is contained in:
parent
5331eb1396
commit
6154ffcfae
@ -11,5 +11,6 @@ module.exports = {
|
||||
'import/default': 'off',
|
||||
|
||||
'vue/no-mutating-props': 'off',
|
||||
'vue/no-use-v-if-with-v-for': 'off',
|
||||
},
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { spawn } from 'node:child_process'
|
||||
import util from 'node:util'
|
||||
import { exec as _exec, spawn } from 'node:child_process'
|
||||
import appStore from '@electron/helpers/store.js'
|
||||
import { adbPath, scrcpyPath } from '@electron/configs/index.js'
|
||||
|
||||
const exec = util.promisify(_exec)
|
||||
|
||||
const shell = async (command, { stdout, stderr } = {}) => {
|
||||
const spawnPath = appStore.get('common.scrcpyPath') || scrcpyPath
|
||||
const ADB = appStore.get('common.adbPath') || adbPath
|
||||
@ -9,6 +12,7 @@ const shell = async (command, { stdout, stderr } = {}) => {
|
||||
|
||||
console.log('scrcpy.shell.spawnPath', spawnPath)
|
||||
console.log('scrcpy.shell.ADB', ADB)
|
||||
console.log('scrcpy.shell.args', args)
|
||||
|
||||
const scrcpyProcess = spawn(`"${spawnPath}"`, args, {
|
||||
env: { ...process.env, ADB },
|
||||
@ -52,6 +56,54 @@ const shell = async (command, { stdout, stderr } = {}) => {
|
||||
})
|
||||
}
|
||||
|
||||
const execShell = async (command) => {
|
||||
const spawnPath = appStore.get('common.scrcpyPath') || scrcpyPath
|
||||
const ADB = appStore.get('common.adbPath') || adbPath
|
||||
|
||||
console.log('scrcpy.execShell.spawnPath', spawnPath)
|
||||
console.log('scrcpy.execShell.ADB', ADB)
|
||||
console.log('scrcpy.shell.command', command)
|
||||
|
||||
const res = exec(`"${spawnPath}" ${command}`, {
|
||||
env: { ...process.env, ADB },
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
})
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
const getEncoders = async (serial) => {
|
||||
const res = await execShell(`--serial="${serial}" --list-encoders`)
|
||||
// console.log('getEncoders.res', res)
|
||||
const stdout = res.stdout
|
||||
|
||||
// 提取视频编码器列表
|
||||
const videoEncoderRegex
|
||||
= /--video-codec=([\w-]+)\s+--video-encoder='([^']+)'/g
|
||||
const videoEncoders = [...stdout.matchAll(videoEncoderRegex)].map(
|
||||
([, codec, encoder]) => ({ decoder: codec, encoder }),
|
||||
)
|
||||
|
||||
// 提取音频编码器列表
|
||||
const audioEncoderRegex
|
||||
= /--audio-codec=([\w-]+)\s+--audio-encoder='([^']+)'/g
|
||||
const audioEncoders = [...stdout.matchAll(audioEncoderRegex)].map(
|
||||
([, codec, encoder]) => ({ decoder: codec, encoder }),
|
||||
)
|
||||
|
||||
const value = {
|
||||
audio: audioEncoders,
|
||||
video: videoEncoders,
|
||||
}
|
||||
|
||||
console.log('getEncoders.value', value)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
export default () => ({
|
||||
shell,
|
||||
execShell,
|
||||
getEncoders,
|
||||
})
|
||||
|
89
src/components/Preference/AudioCodecSelect/index.vue
Normal file
89
src/components/Preference/AudioCodecSelect/index.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-bind="data.props || {}"
|
||||
:model-value="modelValue"
|
||||
class="!w-full"
|
||||
:title="$t(data.placeholder)"
|
||||
:placeholder="$t(data.placeholder)"
|
||||
@change="onChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in options"
|
||||
:key="index"
|
||||
:label="$t(item.label)"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
deviceScope: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
preferenceData: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
emits: ['update:model-value'],
|
||||
data() {
|
||||
return {
|
||||
deviceOptions: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
options() {
|
||||
return this.deviceOptions.length ? this.deviceOptions : this.data.options
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
deviceScope: {
|
||||
handler(value) {
|
||||
if (value === 'global') {
|
||||
this.deviceOptions = []
|
||||
return
|
||||
}
|
||||
|
||||
this.getDeviceOptions()
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async getDeviceOptions() {
|
||||
const res = await this.$scrcpy.getEncoders(this.deviceScope)
|
||||
|
||||
this.deviceOptions = res?.audio?.map((item) => {
|
||||
const value = `${item.decoder} & ${item.encoder}`
|
||||
return {
|
||||
label: value,
|
||||
value,
|
||||
}
|
||||
})
|
||||
|
||||
console.log('deviceOptions', this.deviceOptions)
|
||||
},
|
||||
onChange(value) {
|
||||
// console.log('value', value)
|
||||
this.$emit('update:model-value', value)
|
||||
|
||||
const [decoder, encoder] = value.split(' & ')
|
||||
this.preferenceData['--audio-codec'] = decoder
|
||||
this.preferenceData['--audio-encoder'] = encoder
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
89
src/components/Preference/VideoCodecSelect/index.vue
Normal file
89
src/components/Preference/VideoCodecSelect/index.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<el-select
|
||||
v-bind="data.props || {}"
|
||||
:model-value="modelValue"
|
||||
class="!w-full"
|
||||
:title="$t(data.placeholder)"
|
||||
:placeholder="$t(data.placeholder)"
|
||||
@change="onChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in options"
|
||||
:key="index"
|
||||
:label="$t(item.label)"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
deviceScope: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
preferenceData: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
emits: ['update:model-value'],
|
||||
data() {
|
||||
return {
|
||||
deviceOptions: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
options() {
|
||||
return this.deviceOptions.length ? this.deviceOptions : this.data.options
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
deviceScope: {
|
||||
handler(value) {
|
||||
if (value === 'global') {
|
||||
this.deviceOptions = []
|
||||
return
|
||||
}
|
||||
|
||||
this.getDeviceOptions()
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async getDeviceOptions() {
|
||||
const res = await this.$scrcpy.getEncoders(this.deviceScope)
|
||||
|
||||
this.deviceOptions = res?.video?.map((item) => {
|
||||
const value = `${item.decoder} & ${item.encoder}`
|
||||
return {
|
||||
label: value,
|
||||
value,
|
||||
}
|
||||
})
|
||||
|
||||
console.log('deviceOptions', this.deviceOptions)
|
||||
},
|
||||
onChange(value) {
|
||||
// console.log('value', value)
|
||||
this.$emit('update:model-value', value)
|
||||
|
||||
const [decoder, encoder] = value.split(' & ')
|
||||
this.preferenceData['--video-codec'] = decoder
|
||||
this.preferenceData['--video-encoder'] = encoder
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
@ -1,6 +1,6 @@
|
||||
import { watchEffect } from 'vue'
|
||||
|
||||
export function useOTG(data) {
|
||||
export function useOtg(data) {
|
||||
watchEffect(() => {
|
||||
if (data.value['--hid-keyboard'] || data.value['--hid-mouse']) {
|
||||
data.value['--otg'] = true
|
||||
|
@ -83,7 +83,7 @@
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col
|
||||
v-for="(item_1, index_1) of item?.children || {}"
|
||||
v-for="(item_1, index_1) of subModel(item)"
|
||||
:key="index_1"
|
||||
:span="12"
|
||||
:offset="0"
|
||||
@ -170,6 +170,8 @@
|
||||
v-else
|
||||
v-model="preferenceData[item_1.field]"
|
||||
:data="item_1"
|
||||
:device-scope="deviceScope"
|
||||
:preference-data="preferenceData"
|
||||
></component>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -184,9 +186,11 @@
|
||||
<script>
|
||||
import { debounce } from 'lodash-es'
|
||||
import { ref } from 'vue'
|
||||
import { useOTG } from './__composables__/OTG/index.js'
|
||||
import { useOtg } from './__composables__/otg/index.js'
|
||||
import LanguageSelect from './LanguageSelect/index.vue'
|
||||
import PathInput from './PathInput/index.vue'
|
||||
import VideoCodecSelect from './VideoCodecSelect/index.vue'
|
||||
import AudioCodecSelect from './AudioCodecSelect/index.vue'
|
||||
import LoadingIcon from '@/components/Device/ControlBar/LoadingIcon/index.vue'
|
||||
import { usePreferenceStore } from '@/store/index.js'
|
||||
|
||||
@ -194,6 +198,8 @@ export default {
|
||||
components: {
|
||||
LanguageSelect,
|
||||
PathInput,
|
||||
VideoCodecSelect,
|
||||
AudioCodecSelect,
|
||||
},
|
||||
setup() {
|
||||
const preferenceStore = usePreferenceStore()
|
||||
@ -201,7 +207,7 @@ export default {
|
||||
const preferenceData = ref(preferenceStore.data)
|
||||
const deviceScope = ref(preferenceStore.deviceScope)
|
||||
|
||||
useOTG(preferenceData)
|
||||
useOtg(preferenceData)
|
||||
|
||||
return {
|
||||
preferenceData,
|
||||
@ -218,7 +224,6 @@ export default {
|
||||
label: `${item.id}(${item.$name}${
|
||||
item.$remark ? `,${item.$remark}` : ''
|
||||
})`,
|
||||
|
||||
value: item.id,
|
||||
}))
|
||||
|
||||
@ -269,6 +274,16 @@ export default {
|
||||
this.getDisplay()
|
||||
},
|
||||
methods: {
|
||||
subModel(item) {
|
||||
const children = item?.children || {}
|
||||
const value = {}
|
||||
Object.entries(children).forEach(([key, data]) => {
|
||||
if (!data.hidden) {
|
||||
value[key] = data
|
||||
}
|
||||
})
|
||||
return value
|
||||
},
|
||||
handleResetAll() {
|
||||
this.$store.preference.reset(this.deviceScope)
|
||||
this.preferenceData = this.$store.preference.data
|
||||
|
@ -138,10 +138,8 @@
|
||||
"preferences.video.bit.placeholder": "Default 4M, equal to 4000000",
|
||||
"preferences.video.refresh-rate.name": "Frame Rate",
|
||||
"preferences.video.refresh-rate.placeholder": "Default 60",
|
||||
"preferences.video.decoder.name": "Video Decoder",
|
||||
"preferences.video.decoder.placeholder": "Default h264",
|
||||
"preferences.video.encoder.name": "Video Encoder",
|
||||
"preferences.video.encoder.placeholder": "Default device encoder",
|
||||
"preferences.video.codec.name": "Video Codec",
|
||||
"preferences.video.codec.placeholder": "Default H.264",
|
||||
"preferences.video.screen-rotation.name": "Rotation",
|
||||
"preferences.video.screen-rotation.placeholder": "Default device rotation",
|
||||
"preferences.video.screen-cropping.name": "Crop",
|
||||
|
@ -4,6 +4,7 @@
|
||||
"common.cancel": "取消",
|
||||
"common.confirm": "确认",
|
||||
"common.restart": "重启",
|
||||
"common.default": "默认",
|
||||
"common.tips": "提示",
|
||||
"common.open": "打开",
|
||||
"common.input.placeholder": "请填写",
|
||||
@ -138,10 +139,8 @@
|
||||
"preferences.video.bit.placeholder": "默认值为 4M,等同于 4000000",
|
||||
"preferences.video.refresh-rate.name": "刷新率",
|
||||
"preferences.video.refresh-rate.placeholder": "默认值为 60",
|
||||
"preferences.video.decoder.name": "视频解码器",
|
||||
"preferences.video.decoder.placeholder": "默认值为 h264",
|
||||
"preferences.video.encoder.name": "视频编码器",
|
||||
"preferences.video.encoder.placeholder": "默认值为设备默认编码器",
|
||||
"preferences.video.codec.name": "视频编码",
|
||||
"preferences.video.codec.placeholder": "默认为 H.264",
|
||||
"preferences.video.screen-rotation.name": "屏幕旋转",
|
||||
"preferences.video.screen-rotation.placeholder": "默认值为设备屏幕旋转角度",
|
||||
"preferences.video.screen-cropping.name": "屏幕裁剪",
|
||||
@ -181,12 +180,21 @@
|
||||
"preferences.record.format.name": "录制视频格式",
|
||||
"preferences.record.format.placeholder": "默认为 *.mp4 格式",
|
||||
"preferences.audio.name": "音频控制",
|
||||
"preferences.audio.disable.name": "禁用音频",
|
||||
"preferences.audio.disable.placeholder": "开启后将禁用音频功能",
|
||||
"preferences.audio.audio-source.name": "音频源",
|
||||
"preferences.audio.audio-source.placeholder": "默认为设备音频输出",
|
||||
"preferences.audio.audio-source.tips": "技巧:如果将来源设为麦克风将可以在录制时将声音录制下来",
|
||||
"preferences.audio.audio-source.mic": "麦克风",
|
||||
"preferences.audio.audio-codec.name": "音频编解码器",
|
||||
"preferences.audio.audio-codec.placeholder": "默认为 Opus",
|
||||
"preferences.audio.audio-bit-rate.name": "音频比特率",
|
||||
"preferences.audio.audio-bit-rate.placeholder": "默认为 128000bps",
|
||||
"preferences.audio.audio-bit-rate.tips": "注意:此选项不适用于 RAW 音频编解码器",
|
||||
"preferences.audio.audio-buffer.name": "音频缓冲",
|
||||
"preferences.audio.audio-buffer.placeholder": "默认值为 0ms",
|
||||
"preferences.audio.audio-output-buffer.name": "音频输出缓冲",
|
||||
"preferences.audio.audio-output-buffer.placeholder": "默认值为 5ms",
|
||||
"preferences.audio.disable.name": "禁用音频",
|
||||
"preferences.audio.disable.placeholder": "开启后将禁用音频功能",
|
||||
"preferences.otg.name": "OTG 控制",
|
||||
"preferences.otg.enable.name": "启用 OTG",
|
||||
"preferences.otg.enable.placeholder": "开启或关闭 OTG 功能",
|
||||
|
@ -10,7 +10,7 @@ import icons from './icons/index.js'
|
||||
|
||||
import { i18n, t } from './locales/index.js'
|
||||
|
||||
import { replaceIP } from '@/utils/index.js'
|
||||
import { replaceIP, restoreIP } from '@/utils/index.js'
|
||||
|
||||
import 'virtual:uno.css'
|
||||
import './styles/index.js'
|
||||
@ -36,6 +36,7 @@ app.config.globalProperties.$scrcpy = window.scrcpy
|
||||
app.config.globalProperties.$gnirehtet = window.gnirehtet
|
||||
|
||||
app.config.globalProperties.$replaceIP = replaceIP
|
||||
app.config.globalProperties.$restoreIP = restoreIP
|
||||
|
||||
app.mount('#app').$nextTick(() => {
|
||||
// Remove Preload scripts loading
|
||||
|
@ -11,19 +11,27 @@ import {
|
||||
setStoreData,
|
||||
} from './helpers/index.js'
|
||||
|
||||
import { replaceIP } from '@/utils/index.js'
|
||||
import { replaceIP, restoreIP } from '@/utils/index.js'
|
||||
|
||||
const { adbPath, scrcpyPath } = window.electron?.configs || {}
|
||||
|
||||
export const usePreferenceStore = defineStore({
|
||||
id: 'app-preference',
|
||||
state() {
|
||||
const deviceScope = restoreIP(
|
||||
window.appStore.get('scrcpy.deviceScope') || 'global',
|
||||
)
|
||||
|
||||
return {
|
||||
model: cloneDeep(model),
|
||||
data: { ...getDefaultData() },
|
||||
deviceScope: window.appStore.get('scrcpy.deviceScope') || 'global',
|
||||
|
||||
scrcpyExcludeKeys: ['--record-format', ...getOtherFields('scrcpy')],
|
||||
deviceScope,
|
||||
scrcpyExcludeKeys: [
|
||||
'--record-format',
|
||||
'--video-code',
|
||||
'--audio-code',
|
||||
...getOtherFields('scrcpy'),
|
||||
],
|
||||
}
|
||||
},
|
||||
getters: {},
|
||||
@ -114,7 +122,7 @@ export const usePreferenceStore = defineStore({
|
||||
return ''
|
||||
}
|
||||
|
||||
const value = Object.entries(data).reduce((arr, [key, value]) => {
|
||||
const valueList = Object.entries(data).reduce((arr, [key, value]) => {
|
||||
if (!value) {
|
||||
return arr
|
||||
}
|
||||
@ -133,11 +141,11 @@ export const usePreferenceStore = defineStore({
|
||||
return arr
|
||||
}, [])
|
||||
|
||||
const joinValue = value.join(' ')
|
||||
const value = valueList.join(' ')
|
||||
|
||||
console.log('getScrcpyData.joinValue', joinValue)
|
||||
console.log('getScrcpyData.value', value)
|
||||
|
||||
return joinValue
|
||||
return value
|
||||
},
|
||||
getModel(path) {
|
||||
const value = get(this.model, path)
|
||||
|
@ -3,6 +3,58 @@ export default {
|
||||
field: 'scrcpy',
|
||||
|
||||
children: {
|
||||
audioSource: {
|
||||
label: 'preferences.audio.audio-source.name',
|
||||
field: '--audio-source',
|
||||
type: 'Select',
|
||||
value: '',
|
||||
placeholder: 'preferences.audio.audio-source.placeholder',
|
||||
tips: 'preferences.audio.audio-source.tips',
|
||||
options: [
|
||||
{ label: 'common.default', value: '' },
|
||||
{ label: '麦克风', value: 'mic' },
|
||||
],
|
||||
},
|
||||
audioCode: {
|
||||
label: 'preferences.audio.audio-codec.name',
|
||||
field: '--audio-code',
|
||||
type: 'AudioCodecSelect',
|
||||
value: '',
|
||||
placeholder: 'preferences.audio.audio-codec.placeholder',
|
||||
options: [
|
||||
{
|
||||
label: 'opus & c2.android.opus.encoder',
|
||||
value: 'opus & c2.android.opus.encoder',
|
||||
},
|
||||
{
|
||||
label: 'aac & c2.android.aac.encoder',
|
||||
value: 'aac & c2.android.aac.encoder',
|
||||
},
|
||||
{
|
||||
label: 'aac & OMX.google.aac.encoder',
|
||||
value: 'aac & OMX.google.aac.encoder',
|
||||
},
|
||||
{ label: 'raw', value: 'raw' },
|
||||
],
|
||||
},
|
||||
audioCodec: {
|
||||
hidden: true,
|
||||
field: '--audio-codec',
|
||||
value: '',
|
||||
},
|
||||
audioEncoder: {
|
||||
hidden: true,
|
||||
field: '--audio-encoder',
|
||||
value: '',
|
||||
},
|
||||
audioBitRate: {
|
||||
label: 'preferences.audio.audio-bit-rate.name',
|
||||
field: '--audio-bit-rate',
|
||||
type: 'Input.number',
|
||||
value: '',
|
||||
placeholder: 'preferences.audio.audio-bit-rate.placeholder',
|
||||
append: 'bps',
|
||||
},
|
||||
audioBuffer: {
|
||||
label: 'preferences.audio.audio-buffer.name',
|
||||
field: '--audio-buffer',
|
||||
|
@ -25,61 +25,44 @@ export default {
|
||||
placeholder: 'preferences.video.refresh-rate.placeholder',
|
||||
append: 'fps',
|
||||
},
|
||||
videoCodec: {
|
||||
label: 'preferences.video.decoder.name',
|
||||
field: '--video-codec',
|
||||
type: 'Select',
|
||||
videoCode: {
|
||||
label: 'preferences.video.codec.name',
|
||||
field: '--video-code',
|
||||
type: 'VideoCodecSelect',
|
||||
value: '',
|
||||
placeholder: 'preferences.video.decoder.placeholder',
|
||||
placeholder: 'preferences.video.codec.placeholder',
|
||||
options: [
|
||||
{
|
||||
label: 'h264',
|
||||
value: 'h264',
|
||||
label: 'h265 & OMX.qcom.video.encoder.avc',
|
||||
value: 'h265 & OMX.qcom.video.encoder.avc',
|
||||
},
|
||||
{
|
||||
label: 'h265',
|
||||
value: 'h265',
|
||||
label: 'h265 & c2.android.avc.encoder',
|
||||
value: 'h265 & c2.android.avc.encoder',
|
||||
},
|
||||
{
|
||||
label: 'av1',
|
||||
value: 'av1',
|
||||
label: 'h264 & OMX.google.h264.encoder',
|
||||
value: 'h264 & OMX.google.h264.encoder',
|
||||
},
|
||||
{
|
||||
label: 'h264 & OMX.qcom.video.encoder.hevc',
|
||||
value: 'h264 & OMX.qcom.video.encoder.hevc',
|
||||
},
|
||||
{
|
||||
label: 'h264 & c2.android.hevc.encoder',
|
||||
value: 'h264 & c2.android.hevc.encoder',
|
||||
},
|
||||
],
|
||||
},
|
||||
videoEncoder: {
|
||||
label: 'preferences.video.encoder.name',
|
||||
field: '--video-encoder',
|
||||
type: 'Select',
|
||||
videoCodec: {
|
||||
hidden: true,
|
||||
field: '--video-codec',
|
||||
value: '',
|
||||
},
|
||||
videoEncoder: {
|
||||
hidden: true,
|
||||
field: '--video-encoder',
|
||||
value: '',
|
||||
placeholder: 'preferences.video.encoder.placeholder',
|
||||
// "[server] INFO: List of video encoders:"
|
||||
// "--video-codec=h264 --video-encoder='OMX.qcom.video.encoder.avc'"
|
||||
// "--video-codec=h264 --video-encoder='c2.android.avc.encoder'"
|
||||
// "--video-codec=h264 --video-encoder='OMX.google.h264.encoder'"
|
||||
// "--video-codec=h265 --video-encoder='OMX.qcom.video.encoder.hevc'"
|
||||
// "--video-codec=h265 --video-encoder='c2.android.hevc.encoder'"
|
||||
options: [
|
||||
{
|
||||
label: 'Android HEVC(H.265) ',
|
||||
value: 'OMX.qcom.video.encoder.avc',
|
||||
},
|
||||
{
|
||||
label: 'Qualcomm HEVC(H.265) ',
|
||||
value: 'c2.android.avc.encoder',
|
||||
},
|
||||
{
|
||||
label: 'Google H.264(AVC)',
|
||||
value: 'OMX.google.h264.encoder',
|
||||
},
|
||||
{
|
||||
label: 'Android AVC(H.264) ',
|
||||
value: 'OMX.qcom.video.encoder.hevc',
|
||||
},
|
||||
{
|
||||
label: 'Qualcomm AVC(H.264)',
|
||||
value: 'c2.android.hevc.encoder',
|
||||
},
|
||||
],
|
||||
},
|
||||
rotation: {
|
||||
label: 'preferences.video.screen-rotation.name',
|
||||
|
@ -17,8 +17,12 @@ export function isIPWithPort(ip) {
|
||||
return regex.test(ip)
|
||||
}
|
||||
|
||||
export function replaceIP(value, to = '_') {
|
||||
return value.replaceAll('.', to).replaceAll(':', to)
|
||||
export function replaceIP(value) {
|
||||
return value.replaceAll('.', '_').replaceAll(':', '-')
|
||||
}
|
||||
|
||||
export function restoreIP(value) {
|
||||
return value.replaceAll('_', '.').replaceAll('-', ':')
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user