Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow generate muxed content with Mp4Generator #5555

Merged
merged 2 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/mss/mss_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,8 @@ shaka.mss.MssParser = class {
}
/** @type {shaka.util.Mp4Generator.StreamInfo} */
const streamInfo = {
id: stream.id,
type: stream.type,
encrypted: stream.encrypted,
timescale: stream.mssPrivateData.timescale,
duration: stream.mssPrivateData.duration,
Expand All @@ -642,7 +644,7 @@ shaka.mss.MssParser = class {
data: null, // Data is not necessary for init segement.
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator(streamInfo);
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
initSegmentData = mp4Generator.initSegment();
this.initSegmentDataByStreamId_.set(stream.id, initSegmentData);
}
Expand Down
5 changes: 3 additions & 2 deletions lib/transmuxer/aac_transmuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ shaka.transmuxer.AacTransmuxer = class {
stream.audioSamplingRate = info.sampleRate;
stream.channelsCount = info.channelCount;
stream.codecs = info.codec;
stream.type = 'audio';

/** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
const samples = [];
Expand Down Expand Up @@ -188,6 +187,8 @@ shaka.transmuxer.AacTransmuxer = class {

/** @type {shaka.util.Mp4Generator.StreamInfo} */
const streamInfo = {
id: stream.id,
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: sampleRate,
duration: duration,
Expand All @@ -201,7 +202,7 @@ shaka.transmuxer.AacTransmuxer = class {
},
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator(streamInfo);
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
let initSegment;
if (!this.initSegments.has(stream.id)) {
initSegment = mp4Generator.initSegment();
Expand Down
4 changes: 3 additions & 1 deletion lib/transmuxer/ac3_transmuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ shaka.transmuxer.Ac3Transmuxer = class {

/** @type {shaka.util.Mp4Generator.StreamInfo} */
const streamInfo = {
id: stream.id,
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: sampleRate,
duration: duration,
Expand All @@ -188,7 +190,7 @@ shaka.transmuxer.Ac3Transmuxer = class {
},
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator(streamInfo);
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
let initSegment;
if (!this.initSegments.has(stream.id)) {
initSegment = mp4Generator.initSegment();
Expand Down
4 changes: 3 additions & 1 deletion lib/transmuxer/ec3_transmuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ shaka.transmuxer.Ec3Transmuxer = class {

/** @type {shaka.util.Mp4Generator.StreamInfo} */
const streamInfo = {
id: stream.id,
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: sampleRate,
duration: duration,
Expand All @@ -188,7 +190,7 @@ shaka.transmuxer.Ec3Transmuxer = class {
},
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator(streamInfo);
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
let initSegment;
if (!this.initSegments.has(stream.id)) {
initSegment = mp4Generator.initSegment();
Expand Down
4 changes: 3 additions & 1 deletion lib/transmuxer/mp3_transmuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ shaka.transmuxer.Mp3Transmuxer = class {

/** @type {shaka.util.Mp4Generator.StreamInfo} */
const streamInfo = {
id: stream.id,
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: sampleRate,
duration: duration,
Expand All @@ -180,7 +182,7 @@ shaka.transmuxer.Mp3Transmuxer = class {
},
stream: stream,
};
const mp4Generator = new shaka.util.Mp4Generator(streamInfo);
const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
let initSegment;
if (!this.initSegments.has(stream.id)) {
initSegment = mp4Generator.initSegment();
Expand Down
83 changes: 66 additions & 17 deletions lib/transmuxer/ts_transmuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,45 +180,59 @@ shaka.transmuxer.TsTransmuxer = class {
if (startTime.video != null) {
timestamp = startTime.video;
}
let streamInfo;
const streamInfos = [];
const codecs = tsParser.getCodecs();
try {
let streamInfo = null;
switch (codecs.video) {
case 'avc':
streamInfo =
this.getAvcStreamInfo_(tsParser, timestamp, stream, duration);
break;
}
if (streamInfo) {
streamInfos.push(streamInfo);
streamInfo = null;
}
const isMuxed = !!(codecs.video && codecs.audio);
switch (codecs.audio) {
case 'aac':
streamInfo =
this.getAacStreamInfo_(tsParser, timestamp, stream, duration);
this.getAacStreamInfo_(
tsParser, timestamp, stream, duration, isMuxed);
break;
case 'ac3':
streamInfo =
this.getAc3StreamInfo_(tsParser, timestamp, stream, duration);
this.getAc3StreamInfo_(
tsParser, timestamp, stream, duration, isMuxed);
break;
case 'ec3':
streamInfo =
this.getEc3StreamInfo_(tsParser, timestamp, stream, duration);
this.getEc3StreamInfo_(
tsParser, timestamp, stream, duration, isMuxed);
break;
case 'mp3':
streamInfo =
this.getMp3StreamInfo_(tsParser, timestamp, stream, duration);
this.getMp3StreamInfo_(
tsParser, timestamp, stream, duration, isMuxed);
break;
}
switch (codecs.video) {
case 'avc':
streamInfo =
this.getAvcStreamInfo_(tsParser, timestamp, stream, duration);
break;
if (streamInfo) {
streamInfos.push(streamInfo);
streamInfo = null;
}
} catch (e) {
return Promise.reject(e);
}

if (!streamInfo) {
if (!streamInfos.length) {
return Promise.reject(new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.MEDIA,
shaka.util.Error.Code.TRANSMUXING_FAILED));
}

const mp4Generator = new shaka.util.Mp4Generator(streamInfo);
const mp4Generator = new shaka.util.Mp4Generator(streamInfos);
let initSegment;
if (!this.initSegments.has(stream.id)) {
initSegment = mp4Generator.initSegment();
Expand All @@ -239,10 +253,11 @@ shaka.transmuxer.TsTransmuxer = class {
* @param {number} timestamp
* @param {shaka.extern.Stream} stream
* @param {number} duration
* @param {boolean} isMuxed
* @return {shaka.util.Mp4Generator.StreamInfo}
* @private
*/
getAacStreamInfo_(tsParser, timestamp, stream, duration) {
getAacStreamInfo_(tsParser, timestamp, stream, duration, isMuxed) {
const ADTS = shaka.transmuxer.ADTS;

/** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
Expand All @@ -266,7 +281,6 @@ shaka.transmuxer.TsTransmuxer = class {
stream.audioSamplingRate = info.sampleRate;
stream.channelsCount = info.channelCount;
stream.codecs = info.codec;
stream.type = 'audio';

while (offset < data.length) {
const header = ADTS.parseHeader(data, offset);
Expand Down Expand Up @@ -311,7 +325,13 @@ shaka.transmuxer.TsTransmuxer = class {
/** @type {number} */
const baseMediaDecodeTime = Math.floor(timestamp * sampleRate / 1000);

let id = stream.id;
if (isMuxed) {
id += shaka.transmuxer.TsTransmuxer.START_ID_FOR_MUXED_CONTENT_;
}
return {
id: id,
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: sampleRate,
duration: duration,
Expand All @@ -333,10 +353,11 @@ shaka.transmuxer.TsTransmuxer = class {
* @param {number} timestamp
* @param {shaka.extern.Stream} stream
* @param {number} duration
* @param {boolean} isMuxed
* @return {shaka.util.Mp4Generator.StreamInfo}
* @private
*/
getAc3StreamInfo_(tsParser, timestamp, stream, duration) {
getAc3StreamInfo_(tsParser, timestamp, stream, duration, isMuxed) {
const Ac3 = shaka.transmuxer.Ac3;

/** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
Expand Down Expand Up @@ -394,7 +415,13 @@ shaka.transmuxer.TsTransmuxer = class {
/** @type {number} */
const baseMediaDecodeTime = Math.floor(timestamp * sampleRate / 1000);

let id = stream.id;
if (isMuxed) {
id += shaka.transmuxer.TsTransmuxer.START_ID_FOR_MUXED_CONTENT_;
}
return {
id: id,
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: sampleRate,
duration: duration,
Expand All @@ -416,10 +443,11 @@ shaka.transmuxer.TsTransmuxer = class {
* @param {number} timestamp
* @param {shaka.extern.Stream} stream
* @param {number} duration
* @param {boolean} isMuxed
* @return {shaka.util.Mp4Generator.StreamInfo}
* @private
*/
getEc3StreamInfo_(tsParser, timestamp, stream, duration) {
getEc3StreamInfo_(tsParser, timestamp, stream, duration, isMuxed) {
const Ec3 = shaka.transmuxer.Ec3;

/** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
Expand Down Expand Up @@ -477,7 +505,13 @@ shaka.transmuxer.TsTransmuxer = class {
/** @type {number} */
const baseMediaDecodeTime = Math.floor(timestamp * sampleRate / 1000);

let id = stream.id;
if (isMuxed) {
id += shaka.transmuxer.TsTransmuxer.START_ID_FOR_MUXED_CONTENT_;
}
return {
id: id,
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: sampleRate,
duration: duration,
Expand All @@ -499,10 +533,11 @@ shaka.transmuxer.TsTransmuxer = class {
* @param {number} timestamp
* @param {shaka.extern.Stream} stream
* @param {number} duration
* @param {boolean} isMuxed
* @return {shaka.util.Mp4Generator.StreamInfo}
* @private
*/
getMp3StreamInfo_(tsParser, timestamp, stream, duration) {
getMp3StreamInfo_(tsParser, timestamp, stream, duration, isMuxed) {
const MpegAudio = shaka.transmuxer.MpegAudio;

/** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
Expand Down Expand Up @@ -555,7 +590,13 @@ shaka.transmuxer.TsTransmuxer = class {
/** @type {number} */
const baseMediaDecodeTime = Math.floor(timestamp * sampleRate / 1000);

let id = stream.id;
if (isMuxed) {
id += shaka.transmuxer.TsTransmuxer.START_ID_FOR_MUXED_CONTENT_;
}
return {
id: id,
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: sampleRate,
duration: duration,
Expand Down Expand Up @@ -643,6 +684,8 @@ shaka.transmuxer.TsTransmuxer = class {
stream.width = info.width;

return {
id: stream.id,
type: shaka.util.ManifestParserUtils.ContentType.VIDEO,
encrypted: stream.encrypted && stream.drmInfos.length > 0,
timescale: timescale,
duration: duration,
Expand Down Expand Up @@ -682,6 +725,12 @@ shaka.transmuxer.TsTransmuxer.SUPPORTED_VIDEO_CODECS_ = [
'avc',
];

/**
* @private
* @const {number}
*/
shaka.transmuxer.TsTransmuxer.START_ID_FOR_MUXED_CONTENT_ = 128;


shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
'video/mp2t',
Expand Down
Loading