no commit message

This commit is contained in:
niandeng
2020-09-17 18:40:01 +08:00
parent 4382915d09
commit d957abceaa
283 changed files with 86935 additions and 63 deletions
+172
View File
@@ -0,0 +1,172 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mangui.hls.demux {
import flash.utils.ByteArray;
CONFIG::LOGGING {
import org.mangui.hls.HLSSettings;
import org.mangui.hls.utils.Log;
}
/** Constants and utilities for the H264 video format. **/
public class Nalu {
private static var _audNalu : ByteArray;
// static initializer
{
_audNalu = new ByteArray();
_audNalu.length = 2;
_audNalu.writeByte(0x09);
_audNalu.writeByte(0xF0);
};
/** Return an array with NAL delimiter indexes. **/
public static function getNALU(nalu : ByteArray, position : uint) : Vector.<VideoFrame> {
var len : uint = nalu.length,i : uint = position;
var unitHeader : int,lastUnitHeader : int = 0;
var unitStart : int,lastUnitStart : int = 0;
var unitType : int,lastUnitType : int = 0;
var audFound : Boolean = false;
var value : uint,state : uint = 0;
var units : Vector.<VideoFrame> = new Vector.<VideoFrame>();
// Loop through data to find NAL startcodes.
while (i < len) {
// finding 3 or 4-byte start codes (00 00 01 OR 00 00 00 01)
value = nalu[i++];
switch(state)
{
case 0:
if(!value) {
state = 1;
// unitHeader is NAL header offset
unitHeader=i-1;
}
break;
case 1:
if(value) {
state = 0;
} else {
state = 2;
}
break;
case 2:
case 3:
if(value) {
if(value === 1 && i < len) {
unitType = nalu[i] & 0x1f;
if(unitType == 9) {
audFound = true;
}
if(lastUnitStart) {
// use Math.min(4,...) as max header size is 4.
// in case there are any leading zeros
// such as 00 00 00 00 00 00 01
// ^^
// we need to ignore them as they are part of previous NAL unit
units.push(new VideoFrame(Math.min(4,lastUnitStart-lastUnitHeader), i-state-1-lastUnitStart, lastUnitStart, lastUnitType));
}
lastUnitStart = i;
lastUnitType = unitType;
lastUnitHeader = unitHeader;
if(audFound == true && (unitType === 1 || unitType === 5)) {
// OPTI !!! if AUD unit already parsed and if IDR/NDR unit, consider it is last NALu
i = len;
}
}
state = 0;
} else {
state = 3;
}
break;
default:
break;
}
}
//push last unit
if(lastUnitStart) {
units.push(new VideoFrame(Math.min(4,lastUnitStart-lastUnitHeader), len-lastUnitStart, lastUnitStart, lastUnitType));
}
// Reset position and return results.
CONFIG::LOGGING {
if (HLSSettings.logDebug2) {
/** H264 NAL unit names. **/
const NAMES : Array = ['Unspecified',// 0
'NDR', // 1
'Partition A', // 2
'Partition B', // 3
'Partition C', // 4
'IDR', // 5
'SEI', // 6
'SPS', // 7
'PPS', // 8
'AUD', // 9
'End of Sequence', // 10
'End of Stream', // 11
'Filler Data'// 12
];
if (units.length) {
var txt : String = "AVC: ";
for (i = 0; i < units.length; i++) {
txt += NAMES[units[i].type] + ","; //+ ":" + units[i].length
}
Log.debug2(txt.substr(0,txt.length-1) + " slices");
} else {
Log.debug2('AVC: no NALU slices found');
}
}
}
nalu.position = position;
return units;
};
public static function get AUD():ByteArray {
return _audNalu;
}
/**
* remove Emulation Prevention bytes from a RBSP
*/
public static function unescapeStream(data : ByteArray):ByteArray {
var length : uint = data.length;
var EPBPositions : Vector.<uint> = new Vector.<uint>();
var i : uint = 1;
var newLength : uint;
var newData : ByteArray;
// Find all `Emulation Prevention Bytes`
while (i < length - 2) {
if (data[i] === 0 &&
data[i + 1] === 0 &&
data[i + 2] === 0x03) {
EPBPositions.push(i + 2);
i += 2;
} else {
i++;
}
}
// If no Emulation Prevention Bytes were found just return the original
// array
if (EPBPositions.length === 0) {
return data;
}
// Create a new array to hold the NAL unit data
newLength = length - EPBPositions.length;
newData = new ByteArray();
newData.length = newLength;
var sourceIndex : uint = 0;
for (i = 0; i < newLength; sourceIndex++, i++) {
if (EPBPositions.length && sourceIndex === EPBPositions[0]) {
// Skip this byte
sourceIndex++;
// Remove this position index
EPBPositions.shift();
}
newData[i] = data[sourceIndex];
}
return newData;
}
}
}