cat / goq
clone

turns a linux box into a private steam streaming appliance: plug in, tap your key, play from another computer

fix/docs-activation-truth
goq / portal / codecs.js
codecs.js 2.6K
1// ─── H.264 Annex B → AVCC conversion ──────────────────────────────────────2// Sigil's negotiated media contract is H.264-only. The encoder emits Annex B3// start codes; WebCodecs expects length-prefixed NALs plus an AVC description.45export function parseAnnexBNals(data) {6 const nals = [];7 let i = 0;8 while (i < data.length) {9 let scl = 0;10 if (i + 3 < data.length && data[i] === 0 && data[i+1] === 0 && data[i+2] === 0 && data[i+3] === 1) {11 scl = 4;12 } else if (i + 2 < data.length && data[i] === 0 && data[i+1] === 0 && data[i+2] === 1) {13 scl = 3;14 } else {15 i++; continue;16 }17 const nalStart = i + scl;18 let j = nalStart + 1;19 while (j < data.length) {20 if (j + 3 < data.length && data[j] === 0 && data[j+1] === 0 && data[j+2] === 0 && data[j+3] === 1) break;21 if (j + 2 < data.length && data[j] === 0 && data[j+1] === 0 && data[j+2] === 1) break;22 j++;23 }24 nals.push(data.subarray(nalStart, j));25 i = j;26 }27 return nals;28}2930export function nalsToLengthPrefixed(nals) {31 let total = 0;32 for (const nal of nals) total += 4 + nal.length;33 const result = new Uint8Array(total);34 let off = 0;35 for (const nal of nals) {36 const dv = new DataView(result.buffer, off, 4);37 dv.setUint32(0, nal.length, false);38 result.set(nal, off + 4);39 off += 4 + nal.length;40 }41 return result;42}4344// ─── H.264 ─────────────────────────────────────────────────────────────────4546export function h264NalType(nal) { return nal[0] & 0x1f; }4748export function buildAvcDescription(sps, pps) {49 const buf = new Uint8Array(11 + sps.length + pps.length);50 let off = 0;51 buf[off++] = 1; // configurationVersion52 buf[off++] = sps[1]; // profile_idc53 buf[off++] = sps[2]; // constraint_flags54 buf[off++] = sps[3]; // level_idc55 buf[off++] = 0xFF; // lengthSizeMinusOne = 356 buf[off++] = 0xE1; // numOfSPS = 157 buf[off++] = (sps.length >> 8) & 0xFF;58 buf[off++] = sps.length & 0xFF;59 buf.set(sps, off); off += sps.length;60 buf[off++] = 1; // numOfPPS = 161 buf[off++] = (pps.length >> 8) & 0xFF;62 buf[off++] = pps.length & 0xFF;63 buf.set(pps, off);64 return buf.buffer;65}6667export function avcCodecStr(sps) {68 const p = sps[1].toString(16).padStart(2, '0');69 const c = sps[2].toString(16).padStart(2, '0');70 const l = sps[3].toString(16).padStart(2, '0');71 return `avc1.${p}${c}${l}`;72}