Skip to content

Commit

Permalink
Fix extraction of NALu overflowing PES packet (#6268)
Browse files Browse the repository at this point in the history
Co-authored-by: vladimir.vyatkin <vladimir.vyatkin@portal59.ru>
  • Loading branch information
devoldemar and vladimir.vyatkin committed Apr 11, 2024
1 parent 82c338c commit 0a49731
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/demux/video/avc-video-parser.ts
Expand Up @@ -17,7 +17,7 @@ class AvcVideoParser extends BaseVideoParser {
last: boolean,
duration: number,
) {
const units = this.parseNALu(track, pes.data);
const units = this.parseNALu(track, pes.data, last);
const debug = false;
let VideoSample = this.VideoSample;
let push: boolean;
Expand Down
43 changes: 20 additions & 23 deletions src/demux/video/base-video-parser.ts
Expand Up @@ -29,22 +29,6 @@ abstract class BaseVideoParser {
};
}

protected getLastNalUnit(
samples: VideoSample[],
): VideoSampleUnit | undefined {
let VideoSample = this.VideoSample;
let lastUnit: VideoSampleUnit | undefined;
// try to fallback to previous sample if current one is empty
if (!VideoSample || VideoSample.units.length === 0) {
VideoSample = samples[samples.length - 1];
}
if (VideoSample?.units) {
const units = VideoSample.units;
lastUnit = units[units.length - 1];
}
return lastUnit;
}

protected pushAccessUnit(
VideoSample: ParsedVideoSample,
videoTrack: DemuxedVideoTrack,
Expand Down Expand Up @@ -86,6 +70,7 @@ abstract class BaseVideoParser {
protected parseNALu(
track: DemuxedVideoTrack,
array: Uint8Array,
last: boolean,
): Array<{
data: Uint8Array;
type: number;
Expand Down Expand Up @@ -133,14 +118,18 @@ abstract class BaseVideoParser {
data: array.subarray(lastUnitStart, overflow),
type: lastUnitType,
};
if (track.lastNalu) {
units.push(track.lastNalu);
track.lastNalu = null;
}
// logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
units.push(unit);
} else {
// lastUnitStart is undefined => this is the first start code found in this PES packet
// first check if start code delimiter is overlapping between 2 PES packets,
// ie it started in last packet (lastState not zero)
// and ended at the beginning of this PES packet (i <= 4 - lastState)
const lastUnit = this.getLastNalUnit(track.samples);
const lastUnit = track.lastNalu;
if (lastUnit) {
if (lastState && i <= 4 - lastState) {
// start delimiter overlapping between PES packets
Expand All @@ -163,6 +152,8 @@ abstract class BaseVideoParser {
array.subarray(0, overflow),
);
lastUnit.state = 0;
units.push(lastUnit);
track.lastNalu = null;
}
}
}
Expand All @@ -187,15 +178,21 @@ abstract class BaseVideoParser {
type: lastUnitType,
state: state,
};
units.push(unit);
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
}
// no NALu found
if (units.length === 0) {
if (!last) {
track.lastNalu = unit;
// logger.log('store NALu to push it on next PES');
} else {
units.push(unit);
// logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
}
} else if (units.length === 0) {
// no NALu found
// append pes.data to previous NAL unit
const lastUnit = this.getLastNalUnit(track.samples);
const lastUnit = track.lastNalu;
if (lastUnit) {
lastUnit.data = appendUint8Array(lastUnit.data, array);
units.push(lastUnit);
track.lastNalu = null;
}
}
track.naluState = state;
Expand Down
2 changes: 1 addition & 1 deletion src/demux/video/hevc-video-parser.ts
Expand Up @@ -19,7 +19,7 @@ class HevcVideoParser extends BaseVideoParser {
last: boolean,
duration: number,
) {
const units = this.parseNALu(track, pes.data);
const units = this.parseNALu(track, pes.data, last);
const debug = false;
let VideoSample = this.VideoSample;
let push: boolean;
Expand Down
1 change: 1 addition & 0 deletions src/types/demuxer.ts
Expand Up @@ -77,6 +77,7 @@ export interface DemuxedVideoTrackBase extends DemuxedTrack {
pps?: Uint8Array[];
sps?: Uint8Array[];
naluState?: number;
lastNalu?: VideoSampleUnit | null;
segmentCodec?: string;
manifestCodec?: string;
samples: VideoSample[] | Uint8Array;
Expand Down
7 changes: 7 additions & 0 deletions tests/test-streams.js
Expand Up @@ -272,4 +272,11 @@ module.exports = {
description: 'Advanced stream (HEVC Main 10, MPEG-TS segments)',
skipFunctionalTests: true,
},
mpegTsBitmovinHevc: {
url: 'https://bitmovin-a.akamaihd.net/content/dataset/multi-codec/hevc/v720p_ts.m3u8',
description:
'HLS M2TS by Bitmovin (HEVC Main, many NALUs overflowing PESes, video only)',
abr: false,
skipFunctionalTests: true,
},
};

0 comments on commit 0a49731

Please sign in to comment.