Skip to content

Commit

Permalink
fix: CEA 608 captions not work with H.265 video streams (shaka-projec…
Browse files Browse the repository at this point in the history
…t#5252)

Fix parsing of CEA 608 captions in H.265 video streams by handling 2
byte nal unit header.

Fixes shaka-project#5251
  • Loading branch information
caridley committed May 31, 2023
1 parent 82e905b commit f0ee16b
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 2 deletions.
7 changes: 5 additions & 2 deletions lib/cea/mp4_cea_parser.js
Expand Up @@ -277,6 +277,7 @@ shaka.cea.Mp4CeaParser = class {
const naluHeader = reader.readUint8();
let naluType = null;
let isSeiMessage = false;
let naluHeaderSize = 1;

goog.asserts.assert(this.bitstreamFormat_ != BitstreamFormat.UNKNOWN,
'Bitstream format should have been checked before now!');
Expand All @@ -287,6 +288,8 @@ shaka.cea.Mp4CeaParser = class {
break;

case BitstreamFormat.H265:
naluHeaderSize = 2;
reader.skip(1);
naluType = (naluHeader >> 1) & 0x3f;
isSeiMessage =
naluType == CeaUtils.H265_PREFIX_NALU_TYPE_SEI ||
Expand All @@ -306,15 +309,15 @@ shaka.cea.Mp4CeaParser = class {

const pts = (time + timeOffset)/timescale;
for (const packet of this.seiProcessor_
.process(reader.readBytes(naluSize - 1))) {
.process(reader.readBytes(naluSize - naluHeaderSize))) {
captionPackets.push({
packet,
pts,
});
}
} else {
try {
reader.skip(naluSize - 1);
reader.skip(naluSize - naluHeaderSize);
} catch (e) {
// It is necessary to ignore this error because it can break the start
// of playback even if the user does not want to see the subtitles.
Expand Down
19 changes: 19 additions & 0 deletions test/cea/mp4_cea_parser_unit.js
Expand Up @@ -7,20 +7,30 @@
describe('Mp4CeaParser', () => {
const ceaInitSegmentUri = '/base/test/test/assets/cea-init.mp4';
const ceaSegmentUri = '/base/test/test/assets/cea-segment.mp4';
const h265ceaInitSegmentUri = '/base/test/test/assets/h265-cea-init.mp4';
const h265ceaSegmentUri = '/base/test/test/assets/h265-cea-segment.mp4';
const Util = shaka.test.Util;

/** @type {!ArrayBuffer} */
let ceaInitSegment;
/** @type {!ArrayBuffer} */
let ceaSegment;
/** @type {!ArrayBuffer} */
let h265ceaInitSegment;
/** @type {!ArrayBuffer} */
let h265ceaSegment;

beforeAll(async () => {
const responses = await Promise.all([
shaka.test.Util.fetch(ceaInitSegmentUri),
shaka.test.Util.fetch(ceaSegmentUri),
shaka.test.Util.fetch(h265ceaInitSegmentUri),
shaka.test.Util.fetch(h265ceaSegmentUri),
]);
ceaInitSegment = responses[0];
ceaSegment = responses[1];
h265ceaInitSegment = responses[2];
h265ceaSegment = responses[3];
});

/**
Expand Down Expand Up @@ -70,6 +80,15 @@ describe('Mp4CeaParser', () => {
.toEqual(expectedCea708Packet);
});

it('parses cea data from an h265 mp4 stream', () => {
const ceaParser = new shaka.cea.Mp4CeaParser();

ceaParser.init(h265ceaInitSegment);
const ceaPackets = ceaParser.parse(h265ceaSegment);
expect(ceaPackets).toBeDefined();
expect(ceaPackets.length).toBe(60);
});

it('parses an invalid init segment', () => {
const cea708Parser = new shaka.cea.Mp4CeaParser();

Expand Down
Binary file added test/test/assets/h265-cea-init.mp4
Binary file not shown.
Binary file added test/test/assets/h265-cea-segment.mp4
Binary file not shown.

0 comments on commit f0ee16b

Please sign in to comment.