83 lines
2.4 KiB
JavaScript
83 lines
2.4 KiB
JavaScript
// composables/useStreams.js
|
|
import { nextTick } from 'vue'
|
|
|
|
export function useStreams({ instanceList, videoElement, wslist, openStr, VideoConverter }) {
|
|
// 用 Map 做延迟队列,避免固定 8 个的限制
|
|
const feedState = new Map()
|
|
|
|
function ensureState(index) {
|
|
if (!feedState.has(index)) {
|
|
feedState.set(index, { processing: false, pending: null })
|
|
}
|
|
return feedState.get(index)
|
|
}
|
|
|
|
function pushFrame(index, buf) {
|
|
const st = ensureState(index)
|
|
if (st.processing) {
|
|
// 覆盖旧的等待帧,保留最新
|
|
st.pending = buf
|
|
return
|
|
}
|
|
st.processing = true
|
|
try {
|
|
instanceList[index].converter.appendRawData(new Uint8Array(buf))
|
|
} finally {
|
|
st.processing = false
|
|
if (st.pending) {
|
|
const next = st.pending
|
|
st.pending = null
|
|
queueMicrotask(() => pushFrame(index, next))
|
|
}
|
|
}
|
|
}
|
|
|
|
function resetFeedState(index) {
|
|
const st = feedState.get(index)
|
|
if (!st) return
|
|
st.processing = false
|
|
st.pending = null
|
|
}
|
|
|
|
async function waitForVideoEl(udid, tries = 20, delay = 16) {
|
|
for (let i = 0; i < tries; i++) {
|
|
const el = videoElement.value?.[udid]
|
|
if (el) return el
|
|
await nextTick()
|
|
await new Promise(r => setTimeout(r, delay))
|
|
}
|
|
return null
|
|
}
|
|
|
|
function refreshStream(index, hard = true) {
|
|
const devices = Object.keys(videoElement.value || {})
|
|
const udid = devices[index]
|
|
const video = videoElement.value?.[udid]
|
|
if (!video || !instanceList[index]) return
|
|
|
|
resetFeedState(index)
|
|
try { instanceList[index].converter?.destroy?.() } catch { }
|
|
instanceList[index].converter = null
|
|
|
|
if (hard) {
|
|
try { video.pause?.() } catch { }
|
|
try { video.removeAttribute?.('src') } catch { }
|
|
try { video.load?.() } catch { }
|
|
}
|
|
|
|
// 重新挂新的 converter
|
|
instanceList[index].converter = new VideoConverter(video, 60, 1)
|
|
|
|
// 让后端尽快推关键帧
|
|
try { wslist[index]?.send?.(openStr) } catch { }
|
|
}
|
|
|
|
return {
|
|
feedState,
|
|
pushFrame,
|
|
resetFeedState,
|
|
waitForVideoEl,
|
|
refreshStream,
|
|
}
|
|
}
|