Skip to content

Commit

Permalink
fix: Fix NALU parsing in some HLS muxed live streams (#5688)
Browse files Browse the repository at this point in the history
Related to #5666
  • Loading branch information
avelad committed Sep 27, 2023
1 parent caef5a4 commit 756a576
Showing 1 changed file with 35 additions and 34 deletions.
69 changes: 35 additions & 34 deletions lib/util/ts_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -441,14 +441,15 @@ shaka.util.TsParser = class {
*
* @param {shaka.extern.MPEG_PES} pes
* @param {?shaka.extern.MPEG_PES=} nextPes
* @param {?shaka.extern.VideoNalu=} lastNalu
* @return {!Array.<shaka.extern.VideoNalu>}
* @export
*/
parseNalus(pes, nextPes) {
parseNalus(pes, nextPes, lastNalu) {
const timescale = shaka.util.TsParser.Timescale;
const time = pes.pts ? pes.pts / timescale : null;
let data = pes.data;
let len = data.byteLength;
const data = pes.data;
const len = data.byteLength;

let naluHeaderSize = 1;
if (this.videoCodec_ == 'hvc') {
Expand All @@ -471,29 +472,27 @@ shaka.util.TsParser = class {
// Extracted from the first byte.
let lastNaluType = 0;

let tryToFinishLastNalu = false;

/** @type {?shaka.extern.VideoNalu} */
let infoOfLastNalu;

for (let i = 0; i < len; ++i) {
const value = data[i];
if (!value) {
numZeros++;
} else if (numZeros >= 2 && value == 1 && tryToFinishLastNalu) {
} else if (numZeros >= 2 && value == 1 && lastNalu) {
// If we are scanning the next PES, we need append the data to the
// previous Nalu and don't scan for more nalus.
const startCodeSize = numZeros > 3 ? 3 : numZeros;
const lastByteToKeep = i - startCodeSize;
// Optimization
if (lastByteToKeep == 0) {
break;
return [];
}
infoOfLastNalu.data = shaka.util.Uint8ArrayUtils.concat(
infoOfLastNalu.data, data.subarray(0, lastByteToKeep));
infoOfLastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
infoOfLastNalu.fullData, data.subarray(0, lastByteToKeep));
break;
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
lastNalu.data, data.subarray(0, lastByteToKeep));
lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
lastNalu.fullData, data.subarray(0, lastByteToKeep));
return [];
} else if (numZeros >= 2 && value == 1) {
// We just read a start code. Consume the NALU we passed, if any.
if (lastNaluStart >= 0) {
Expand All @@ -514,11 +513,17 @@ shaka.util.TsParser = class {
time: time,
};
nalus.push(nalu);
} else if (lastNalu) {
const overflow = i - numZeros;
if (overflow > 0) {
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
lastNalu.data, data.subarray(0, overflow));
}
}

// We just read a start code, so there should be another byte here, at
// least, for the NALU type. Check just in case.
if (i >= len - 1) {
if (i >= len - naluHeaderSize) {
shaka.log.warning('Malformed TS, incomplete NALU, ignoring.');
return nalus;
}
Expand All @@ -539,34 +544,30 @@ shaka.util.TsParser = class {
// unfinished Nalu, we will try to use the next PES to complete the
// unfinished Nalu.
if (i >= (len - 1) && lastNaluStart >= 0 && numZeros >= 0) {
if (tryToFinishLastNalu) {
infoOfLastNalu.data = shaka.util.Uint8ArrayUtils.concat(
infoOfLastNalu.data, data);
infoOfLastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
infoOfLastNalu.fullData, data);
} else {
tryToFinishLastNalu = true;
// The rest of the buffer was a NALU.
// Because the start position includes the header size.
const firstByteToKeep = lastNaluStart + naluHeaderSize;
infoOfLastNalu = {
data: data.subarray(firstByteToKeep, len),
fullData: data.subarray(lastNaluStart, len),
type: lastNaluType,
time: time,
};
if (nextPes && pes.packetLength == 0) {
data = nextPes.data;
len = data.byteLength;
i = -1;
}
// The rest of the buffer was a NALU.
// Because the start position includes the header size.
const firstByteToKeep = lastNaluStart + naluHeaderSize;
infoOfLastNalu = {
data: data.subarray(firstByteToKeep, len),
fullData: data.subarray(lastNaluStart, len),
type: lastNaluType,
time: time,
};
if (nextPes) {
this.parseNalus(nextPes, /* nextPes= */ null, infoOfLastNalu);
}
}
}

if (infoOfLastNalu) {
nalus.push(infoOfLastNalu);
}
if (!nalus.length && lastNalu) {
lastNalu.data = shaka.util.Uint8ArrayUtils.concat(
lastNalu.data, data);
lastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
lastNalu.fullData, data);
}
return nalus;
}

Expand Down

0 comments on commit 756a576

Please sign in to comment.