Skip to content

Commit

Permalink
optimize NAL unit parsing
Browse files Browse the repository at this point in the history
use a state machine and byte read instead of word read and jump backwards in the array in case start code not found
related to #162
  • Loading branch information
mangui committed Jul 1, 2015
1 parent 1115c04 commit 9fbd025
Showing 1 changed file with 58 additions and 51 deletions.
109 changes: 58 additions & 51 deletions src/org/mangui/hls/demux/Nalu.as
Original file line number Diff line number Diff line change
Expand Up @@ -24,62 +24,69 @@

/** 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>();
var unit_start : int;
var unit_type : int;
var unit_header : int;
var aud_found : Boolean = false;
// Loop through data to find NAL startcodes.
var window : uint = 0;
nalu.position = position;
while (nalu.bytesAvailable > 4) {
window = nalu.readUnsignedInt();
// Match four-byte startcodes
if ((window & 0xFFFFFFFF) == 0x01) {
// push previous NAL unit if new start delimiter found, dont push unit with type = 0
if (unit_start && unit_type) {
units.push(new VideoFrame(unit_header, nalu.position - 4 - unit_start, unit_start, unit_type));
}
unit_header = 4;
unit_start = nalu.position;
unit_type = nalu.readByte() & 0x1F;
if(unit_type ==9) {
aud_found = true;
}
/* if AUD already found and newly found unit is NDR or IDR,
stop parsing here and consider that this IDR/NDR is the last NAL unit
breaking the loop here is done for optimization purpose, as NAL parsing is time consuming ...
*/
if (aud_found && (unit_type == 1 || unit_type == 5)) {
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;
}
// Match three-byte startcodes
} else if ((window & 0xFFFFFF00) == 0x100) {
// push previous NAL unit if new start delimiter found, dont push unit with type = 0
if (unit_start && unit_type) {
units.push(new VideoFrame(unit_header, nalu.position - 4 - unit_start, unit_start, unit_type));
}
nalu.position--;
unit_header = 3;
unit_start = nalu.position;
unit_type = nalu.readByte() & 0x1F;
if(unit_type ==9) {
aud_found = true;
}
/* if AUD already found and newly found unit is NDR or IDR,
stop parsing here and consider that this IDR/NDR is the last NAL unit
breaking the loop here is done for optimization purpose, as NAL parsing is time consuming ...
*/
if (aud_found && (unit_type == 1 || unit_type == 5)) {
case 1:
if(value) {
state = 0;
} else {
state = 2;
}
break;
case 2:
case 3:
if(value) {
if(value === 1) {
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;
}
} else {
nalu.position -= 3;
}
}
// Append the last NAL to the array.
if (unit_start) {
units.push(new VideoFrame(unit_header, nalu.length - unit_start, unit_start, unit_type));
//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 {
Expand All @@ -101,7 +108,7 @@
];
if (units.length) {
var txt : String = "AVC: ";
for (var i : int = 0; i < units.length; i++) {
for (i = 0; i < units.length; i++) {
txt += NAMES[units[i].type] + ","; //+ ":" + units[i].length
}
Log.debug2(txt.substr(0,txt.length-1) + " slices");
Expand Down

0 comments on commit 9fbd025

Please sign in to comment.