I have a server that can http video-stream (send the parts of a video to the http get request with "Range" header). This streaming works properly on Chrome if just putting the link to a video tag. However, I need to take some specific config;s raw data from these mp4 chunks before playing them on the page (specifically moov -> trak -> mdia -> esds). How do I find those configs?
The following code is what I have
For parsing numbers and changing from Little-Endian to Big-Endian:
function parseNumber(data: Uint8Array, offset: number, size: number) {
let result: number = 0
for(let i = offset; i < size; i++) {
result += data[i] * 256 ^ (i - offset)
}
return result
}
For parsing strings:
function parseString(data: Uint8Array, offset: number, size: number) {
return String.fromCharCode(...data.slice(offset, offset + size));
}
For searching for an atom inside of body of another atom:
function lookForChildAtom(data: Uint8Array, offset: number, size: number, lookFor: string | string[]) {
while(offset < size) {
let [childAtomSize, childAtomName] = parseAtomSizeAndName(data, offset)
if(childAtomSize === 1 && childAtomName === 'mdat') {
childAtomSize = parseNumber(data, offset + 8, 16)
}
if(childAtomSize < (MIN_SIZES[childAtomName] ?? 8)) {
throw Error('The file is invalid: ' + childAtomName + ' atom < ' + MIN_SIZES[childAtomName] ?? '8')
}
if(lookFor instanceof Array && lookFor.includes(childAtomName) || childAtomName === lookFor) {
return [offset, childAtomSize]
}
offset += childAtomSize
}
return [offset, 0]
}
And, eventually for searching the config I need:
export default function parseMp4ForESDSData(data: Uint8Array) : string {
let offset = 0;
let size: number = data.length;
[offset, size] = lookForChildAtom(data, offset, size, ['moov', 'moof']);
while(true) {
const [trakOffset, trakSize] = lookForChildAtom(data, offset, size, 'trak');
const [mdiaOffset, mdiaSize] = lookForChildAtom(data, trakOffset, trakSize, 'mdia');
const [hdlrOffset, hdlrSize] = lookForChildAtom(data, mdiaOffset, mdiaSize, 'hdlr');
const hdlrSubtype = parseString(data, hdlrOffset + HDLRSubtypeStart, HDLRSubtypeSize)
if(hdlrSubtype === 'soun') {
[offset, size] = [mdiaOffset, mdiaSize]
break
}
const trackEnd = trakOffset + trakSize
offset += trackEnd
size -= trackEnd
if(size <= 0) {
throw Error('No sound track in the file')
}
}
[offset, size] = lookForChildAtom(data, offset, size, 'minf');
[offset, size] = lookForChildAtom(data, offset, size, 'mp4a');
[offset, size] = lookForChildAtom(data, offset, size, 'esds');
offset += ESDSElementaryStreamDescriptorStart
size -= ESDSElementaryStreamDescriptorStart
return parseString(data, offset, offset + size)
}