优化amf解析

This commit is contained in:
Harvey Zack committed 2018-12-21 14:30:38 +08:00
1 parent 3afe2e1640
commit 32b2f4792a
9 files changed
+190 -119

No files matched your search

@@ -36,7 +36,7 @@ export default function fetchStream(flv, url) {
read();
})
.catch(error => {
flv.emit('flvFetchError', error);
throw error;
});
})();
},
@@ -1,14 +1,18 @@
import { getUint8Sum, readUint8, bin2String, bin2Boolean, bin2Float } from '../utils';
import { getUint8Sum, readUint8, bin2String, bin2Boolean, bin2Float, errorHandle } from '../utils';
export default function getMetaData(scripTag) {
const readScripTag = readUint8(scripTag.body);
const metadata = Object.create(null);
const amf1 = Object.create(null);
const amf2 = Object.create(null);
[amf1.type] = readScripTag(1);
errorHandle(amf1.type === 2, `AMF: [amf1] type expect 2, but got ${amf1.type}`);
amf1.size = getUint8Sum(readScripTag(2));
amf1.string = bin2String(readScripTag(amf1.size));
[amf2.type] = readScripTag(1);
errorHandle(amf2.type === 8, `AMF: [amf1] type expect 8, but got ${amf2.type}`);
amf2.size = getUint8Sum(readScripTag(4));
amf2.metaData = Object.create(null);
@@ -45,8 +49,8 @@ export default function getMetaData(scripTag) {
}
case 8: {
value = Object.create(null);
let endObject = false;
while (!endObject && readScripTag.index < scripTag.body.length) {
let endArray = false;
while (!endArray && readScripTag.index < scripTag.body.length) {
const nameLength = getUint8Sum(readScripTag(2));
const name = bin2String(readScripTag(nameLength));
const type = readScripTag(1)[0];
@@ -54,7 +58,7 @@ export default function getMetaData(scripTag) {
value[name] = getValue(type);
}
if (type === 9) {
endObject = true;
endArray = true;
}
}
break;
@@ -74,7 +78,7 @@ export default function getMetaData(scripTag) {
break;
}
default:
console.warn(`AMF: Unknown metaData type: ${type} in ${readScripTag.index - 1}`);
errorHandle(false, `AMF: Unknown metaData type: ${type}`);
break;
}
}
@@ -90,6 +94,9 @@ export default function getMetaData(scripTag) {
}
}
errorHandle(readScripTag.index === scripTag.body.length, 'AMF: Seems to be incompletely parsed');
errorHandle(amf2.size === Object.keys(amf2.metaData).length, 'AMF: [amf2] length does not match');
metadata.amf1 = amf1;
metadata.amf2 = amf2;
return metadata;
@@ -1,12 +1,12 @@
import fetchStream from './fetchStream';
import readFile from './readFile';
import getMetaData from './getMetaData';
import { mergeTypedArrays, getUint8Sum } from '../utils';
import { mergeTypedArrays, getUint8Sum, bin2String } from '../utils';
export default class FlvParse {
constructor(flv) {
this.flv = flv;
const { url } = flv.options;
const { url, debug } = flv.options;
this.uint8 = new Uint8Array(0);
this.index = 0;
this.header = null;
@@ -15,15 +15,15 @@ export default class FlvParse {
this.done = false;
flv.on('flvFetchStart', () => {
console.log('[flv-fetch-start]');
if (debug) {
console.log('[flv-fetch-start]', url);
}
});
flv.on('flvFetchCancel', () => {
console.log('[flv-fetch-cancel]');
});
flv.on('flvFetchError', error => {
console.log('[flv-fetch-error]', error);
if (debug) {
console.log('[flv-fetch-cancel]');
}
});
flv.on('flvFetching', uint8 => {
@@ -32,7 +32,9 @@ export default class FlvParse {
});
flv.on('flvFetchEnd', uint8 => {
console.log('[flv-fetch-end]');
if (debug) {
console.log('[flv-fetch-end]');
}
this.done = true;
if (uint8) {
this.uint8 = uint8;
@@ -42,7 +44,10 @@ export default class FlvParse {
this.tags = [];
this.parse();
}
flv.emit('parseDone');
flv.emit('flvParseDone');
if (debug) {
console.log('[flv-parse-done]');
}
});
if (typeof url === 'string') {
@@ -53,41 +58,48 @@ export default class FlvParse {
}
parse() {
const { debug } = this.flv.options;
if (this.uint8.length >= 13 && !this.header) {
const header = Object.create(null);
header.signature = this.read(3);
header.version = this.read(1);
header.flags = this.read(1);
header.headersize = this.read(4);
header.signature = bin2String(this.read(3));
[header.version] = this.read(1);
[header.flags] = this.read(1);
header.headersize = getUint8Sum(this.read(4));
this.header = header;
this.read(4);
this.flv.emit('parseHeader', this.header);
console.log(this.header);
this.flv.emit('flvParseHeader', this.header);
if (debug) {
console.log('[flv-parse-header]', this.header);
}
}
while (this.index < this.uint8.length) {
const tag = Object.create(null);
tag.tagType = this.read(1);
tag.dataSize = this.read(3);
[tag.tagType] = this.read(1);
tag.dataSize = getUint8Sum(this.read(3));
tag.timestamp = this.read(4);
tag.streamID = this.read(3);
tag.body = this.read(getUint8Sum(tag.dataSize));
tag.body = this.read(tag.dataSize);
this.tags.push(tag);
this.read(4);
this.flv.emit('parseTag', tag);
this.flv.emit('flvParseTag', tag);
}
if (this.tags.length > 1 && this.tags[0].tagType[0] === 18 && !this.metadata) {
this.flv.emit('flvParseTags', this.tags);
if (this.tags.length > 1 && this.tags[0].tagType === 18 && !this.metadata) {
this.metadata = getMetaData(this.tags[0]);
this.flv.emit('parseMetadata', this.metadata);
console.log(this.metadata);
if (debug) {
console.log('[flv-parse-metadata]', this.metadata);
}
}
}
read(length) {
const tempUint8 = [];
const tempUint8 = new Uint8Array(length);
for (let i = 0; i < length; i += 1) {
tempUint8.push(this.uint8[this.index]);
tempUint8[i] = this.uint8[this.index];
this.index += 1;
}
return tempUint8;
@@ -26,6 +26,7 @@ class Flv extends Emitter {
return {
mediaElement: '',
url: '',
debug: false,
};
}
@@ -53,15 +53,19 @@ export function bin2Boolean(bin) {
return bin === 1;
}
export function log(name, msg = '') {
console.log(`[${name}] ${msg}`);
}
export function readUint8(uint8) {
let index = 0;
return function read(length) {
const result = [];
const tempUint8 = new Uint8Array(length);
for (let i = 0; i < length; i += 1) {
result.push(uint8[index]);
tempUint8[i] = uint8[index];
index += 1;
}
read.index = index;
return result;
return tempUint8;
};
}