Skip to content

Commit 934b7df

Browse files
author
vladimir.vyatkin
committed
Process HEVC in mpeg-ts container
1 parent bde084b commit 934b7df

File tree

7 files changed

+1003
-24
lines changed

7 files changed

+1003
-24
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ HLS.js is written in [ECMAScript6] (`*.js`) and [TypeScript] (`*.ts`) (strongly
3737
- Fragmented MP4 container
3838
- MPEG-2 TS container
3939
- ITU-T Rec. H.264 and ISO/IEC 14496-10 Elementary Stream
40+
- ITU-T Rec. H.265 and ISO/IEC 23008-2 Elementary Stream
4041
- ISO/IEC 13818-7 ADTS AAC Elementary Stream
4142
- ISO/IEC 11172-3 / ISO/IEC 13818-3 (MPEG-1/2 Audio Layer III) Elementary Stream
4243
- ATSC A/52 / AC-3 / Dolby Digital Elementary Stream

src/demux/tsdemuxer.ts

+50-20
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* highly optimized TS demuxer:
33
* parse PAT, PMT
44
* extract PES packet from audio and video PIDs
5-
* extract AVC/H264 NAL units and AAC/ADTS samples from PES packet
5+
* extract AVC/H264 (or HEVC/H265) NAL units and AAC/ADTS samples from PES packet
66
* trigger the remuxer upon parsing completion
77
* it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource.
88
* it also controls the remuxing process :
@@ -14,6 +14,7 @@ import * as MpegAudio from './audio/mpegaudio';
1414
import * as AC3 from './audio/ac3-demuxer';
1515
import BaseVideoParser from './video/base-video-parser';
1616
import AvcVideoParser from './video/avc-video-parser';
17+
import HevcVideoParser from './video/hevc-video-parser';
1718
import SampleAesDecrypter from './sample-aes';
1819
import { Events } from '../events';
1920
import { appendUint8Array, RemuxerTrackIdConfig } from '../utils/mp4-tools';
@@ -70,7 +71,7 @@ class TSDemuxer implements Demuxer {
7071
private _txtTrack?: DemuxedUserdataTrack;
7172
private aacOverFlow: AudioFrame | null = null;
7273
private remainderData: Uint8Array | null = null;
73-
private videoParser: BaseVideoParser;
74+
private videoParser: BaseVideoParser | null;
7475

7576
constructor(
7677
observer: HlsEventEmitter,
@@ -80,7 +81,7 @@ class TSDemuxer implements Demuxer {
8081
this.observer = observer;
8182
this.config = config;
8283
this.typeSupported = typeSupported;
83-
this.videoParser = new AvcVideoParser();
84+
this.videoParser = null;
8485
}
8586

8687
static probe(data: Uint8Array) {
@@ -288,13 +289,25 @@ class TSDemuxer implements Demuxer {
288289
case videoPid:
289290
if (stt) {
290291
if (videoData && (pes = parsePES(videoData))) {
291-
this.videoParser.parsePES(
292-
videoTrack,
293-
textTrack,
294-
pes,
295-
false,
296-
this._duration,
297-
);
292+
if (this.videoParser === null) {
293+
switch (videoTrack.segmentCodec) {
294+
case 'avc':
295+
this.videoParser = new AvcVideoParser();
296+
break;
297+
case 'hevc':
298+
this.videoParser = new HevcVideoParser();
299+
break;
300+
}
301+
}
302+
if (this.videoParser !== null) {
303+
this.videoParser.parsePES(
304+
videoTrack,
305+
textTrack,
306+
pes,
307+
false,
308+
this._duration,
309+
);
310+
}
298311
}
299312

300313
videoData = { data: [], size: 0 };
@@ -466,14 +479,26 @@ class TSDemuxer implements Demuxer {
466479
// try to parse last PES packets
467480
let pes: PES | null;
468481
if (videoData && (pes = parsePES(videoData))) {
469-
this.videoParser.parsePES(
470-
videoTrack as DemuxedVideoTrack,
471-
textTrack as DemuxedUserdataTrack,
472-
pes,
473-
true,
474-
this._duration,
475-
);
476-
videoTrack.pesData = null;
482+
if (this.videoParser === null) {
483+
switch (videoTrack.segmentCodec) {
484+
case 'avc':
485+
this.videoParser = new AvcVideoParser();
486+
break;
487+
case 'hevc':
488+
this.videoParser = new HevcVideoParser();
489+
break;
490+
}
491+
}
492+
if (this.videoParser !== null) {
493+
this.videoParser.parsePES(
494+
videoTrack as DemuxedVideoTrack,
495+
textTrack as DemuxedUserdataTrack,
496+
pes,
497+
true,
498+
this._duration,
499+
);
500+
videoTrack.pesData = null;
501+
}
477502
} else {
478503
// either avcData null or PES truncated, keep it for next frag parsing
479504
videoTrack.pesData = videoData;
@@ -870,8 +895,13 @@ function parsePMT(
870895
case 0x87:
871896
logger.warn('Unsupported EC-3 in M2TS found');
872897
break;
873-
case 0x24:
874-
logger.warn('Unsupported HEVC in M2TS found');
898+
899+
case 0x24: // ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
900+
if (result.videoPid === -1) {
901+
result.videoPid = pid;
902+
result.segmentVideoCodec = 'hevc';
903+
logger.log('HEVC in M2TS found');
904+
}
875905
break;
876906

877907
default:

0 commit comments

Comments
 (0)