Skip to content

Commit

Permalink
feat(CEA): Parse CEA from TS with H.265 (#5610)
Browse files Browse the repository at this point in the history
  • Loading branch information
avelad committed Sep 7, 2023
1 parent fc93292 commit 54eaf63
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 12 deletions.
17 changes: 15 additions & 2 deletions lib/cea/ts_cea_parser.js
Expand Up @@ -49,10 +49,23 @@ shaka.cea.TsCeaParser = class {
return captionPackets;
}
const tsParser = new shaka.util.TsParser().parse(uint8ArrayData);
const codecs = tsParser.getCodecs();
const videoNalus = tsParser.getVideoNalus();
const validNaluTypes = [];
switch (codecs.video) {
case 'avc':
validNaluTypes.push(CeaUtils.H264_NALU_TYPE_SEI);
break;
case 'hvc':
validNaluTypes.push(CeaUtils.H265_PREFIX_NALU_TYPE_SEI);
validNaluTypes.push(CeaUtils.H265_SUFFIX_NALU_TYPE_SEI);
break;
}
if (!validNaluTypes.length) {
return captionPackets;
}
for (const nalu of videoNalus) {
if (nalu.type == CeaUtils.H264_NALU_TYPE_SEI &&
nalu.time != null) {
if (validNaluTypes.includes(nalu.type) && nalu.time != null) {
for (const packet of this.seiProcessor_.process(nalu.data)) {
captionPackets.push({
packet: packet,
Expand Down
2 changes: 1 addition & 1 deletion lib/transmuxer/ts_transmuxer.js
Expand Up @@ -632,7 +632,7 @@ shaka.transmuxer.TsTransmuxer = class {
if (i + 1 < videoData.length) {
nextPes = videoData[i + 1];
}
const dataNalus = tsParser.parseAvcNalus(pes, nextPes);
const dataNalus = tsParser.parseNalus(pes, nextPes);
nalus = nalus.concat(dataNalus);
const frame = H264.parseFrame(dataNalus);
if (!frame) {
Expand Down
45 changes: 36 additions & 9 deletions lib/util/ts_parser.js
Expand Up @@ -416,11 +416,34 @@ shaka.util.TsParser = class {
* @export
*/
parseAvcNalus(pes, nextPes) {
shaka.Deprecate.deprecateFeature(5,
'TsParser',
'Please use parseNalus function instead.');
return this.parseNalus(pes, nextPes);
}

/**
* Parse AVC and HVC Nalus
*
* The code is based on hls.js
* Credit to https://github.com/video-dev/hls.js/blob/master/src/demux/tsdemuxer.ts
*
* @param {shaka.extern.MPEG_PES} pes
* @param {?shaka.extern.MPEG_PES=} nextPes
* @return {!Array.<shaka.extern.VideoNalu>}
* @export
*/
parseNalus(pes, nextPes) {
const timescale = shaka.util.TsParser.Timescale;
const time = pes.pts ? pes.pts / timescale : null;
let data = pes.data;
let len = data.byteLength;

let naluHeaderSize = 1;
if (this.videoCodec_ == 'hvc') {
naluHeaderSize = 2;
}

// A NALU does not contain is its size.
// The Annex B specification solves this by requiring ‘Start Codes’ to
// precede each NALU. A start code is 2 or 3 0x00 bytes followed with a
Expand Down Expand Up @@ -459,8 +482,8 @@ shaka.util.TsParser = class {
} else if (numZeros >= 2 && value == 1) {
// We just read a start code. Consume the NALU we passed, if any.
if (lastNaluStart >= 0) {
// Because the start position includes the type, skip the first byte.
const firstByteToKeep = lastNaluStart + 1;
// Because the start position includes the header size.
const firstByteToKeep = lastNaluStart + naluHeaderSize;

// Compute the last byte to keep. The start code is at most 3 zeros.
// Any earlier zeros are not part of the start code.
Expand Down Expand Up @@ -488,7 +511,11 @@ shaka.util.TsParser = class {
// Advance and read the type of the next NALU.
i++;
lastNaluStart = i;
lastNaluType = data[i] & 0x1f;
if (this.videoCodec_ == 'hvc') {
lastNaluType = (data[i] >> 1) & 0x3f;
} else {
lastNaluType = data[i] & 0x1f;
}
numZeros = 0;
} else {
numZeros = 0;
Expand All @@ -505,8 +532,8 @@ shaka.util.TsParser = class {
} else {
tryToFinishLastNalu = true;
// The rest of the buffer was a NALU.
// Because the start position includes the type, skip the first byte.
const firstByteToKeep = lastNaluStart + 1;
// Because the start position includes the header size.
const firstByteToKeep = lastNaluStart + naluHeaderSize;
infoOfLastNalu = {
data: data.subarray(firstByteToKeep, len),
fullData: data.subarray(lastNaluStart, len),
Expand Down Expand Up @@ -639,17 +666,14 @@ shaka.util.TsParser = class {
*/
getVideoNalus() {
const nalus = [];
if (this.videoCodec_ != 'avc') {
return nalus;
}
const videoData = this.getVideoData();
for (let i = 0; i < videoData.length; i++) {
const pes = videoData[i];
let nextPes;
if (i + 1 < videoData.length) {
nextPes = videoData[i + 1];
}
nalus.push(...this.parseAvcNalus(pes, nextPes));
nalus.push(...this.parseNalus(pes, nextPes));
}
return nalus;
}
Expand Down Expand Up @@ -684,6 +708,9 @@ shaka.util.TsParser = class {
width: null,
codec: null,
};
if (this.videoCodec_ != 'avc') {
return videoInfo;
}
const videoNalus = this.getVideoNalus();
if (!videoNalus.length) {
return videoInfo;
Expand Down

0 comments on commit 54eaf63

Please sign in to comment.