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: multiple sourcebuffer #49

Merged
merged 2 commits into from
Mar 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ describe('fmp4Generator', () => {
]))
})

it('should generator moov buffer size', () => {
expect(FMP4.moov(audioData).length).toBe(1154)
it('should generator audio moov buffer size', () => {
expect(FMP4.moov(audioData, 'audio').length).toBe(652)
})

it('should generator video moov buffer size', () => {
expect(FMP4.moov(audioData, 'video').length).toBe(718)
})

it('should generator moof buffer size', () => {
Expand Down
8 changes: 6 additions & 2 deletions packages/griffith-mp4/src/fmp4/boxes/__tests__/moov.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import moov from '../moov'
import {audioData} from './__mocks__/data'

describe('moov', () => {
it('should get moov box size', () => {
expect(moov(audioData).length).toBe(1154)
it('should get audio moov box size', () => {
expect(moov(audioData, 'audio').length).toBe(652)
})

it('should get video moov box size', () => {
expect(moov(audioData, 'video').length).toBe(718)
})
})
5 changes: 2 additions & 3 deletions packages/griffith-mp4/src/fmp4/boxes/moov.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import mvhd from './mvhd'
import trak from './trak'
import mvex from './mvex'

export default function moov(data) {
export default function moov(data, type) {
const content = concatTypedArray(
mvhd(data),
trak({...data, type: 'video'}),
trak({...data, type: 'audio'}),
trak({...data, type}),
mvex(data)
)
return generateBox('moov', content)
Expand Down
4 changes: 2 additions & 2 deletions packages/griffith-mp4/src/fmp4/fmp4Generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export default class FMP4Generator {
return ftyp()
}

static moov(data) {
return moov(data)
static moov(data, type) {
return moov(data, type)
}

static moof(trackInfo, baseMediaDecodeTime) {
Expand Down
7 changes: 6 additions & 1 deletion packages/griffith-mp4/src/mp4/boxes/elst.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ export default function elst(buffer) {

for (let i = 0; i < entryCount; ++i) {
const segmentDuration = stream.readByte(4)
const mediaTime = stream.readByte(4)
let mediaTime = stream.readByte(4)

// 0xffffffff -> -1
if (mediaTime === 4294967295) {
mediaTime = -1
}
const mediaRateInteger = stream.readByte(2)
const mediaRateFraction = stream.readByte(2)

Expand Down
8 changes: 8 additions & 0 deletions packages/griffith-mp4/src/mp4/utils/__tests__/findBox.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,12 @@ describe('findBox', () => {
it('find empty', () => {
expect(findBox(mp4BoxTree)).toEqual({})
})

it('find audio elst', () => {
expect(findBox(mp4BoxTree, 'audioElst').entries[0].mediaTime).toBe(2048)
})

it('find video elst', () => {
expect(findBox(mp4BoxTree, 'videoElst').entries[0].mediaTime).toBe(2048)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('getSamplesInterval', () => {
})
).toEqual({
offsetInterVal: [0, 395],
timeInterVal: [0, 404480],
timeInterVal: [2048, 404480],
})
})

Expand Down
12 changes: 12 additions & 0 deletions packages/griffith-mp4/src/mp4/utils/findBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ export default function findBox(mp4BoxTree, type) {
return findAudioStszBox(mp4BoxTree)
case 'mp4a':
return findMp4aBox(mp4BoxTree)
case 'audioElst':
return findAudioElstBox(mp4BoxTree)
case 'videoElst':
return findVideoElstBox(mp4BoxTree)

default:
return {}
Expand Down Expand Up @@ -143,3 +147,11 @@ function findAudioStszBox(mp4BoxTree) {
function findVideoCttsBox(mp4BoxTree) {
return findVideoStblBox(mp4BoxTree)['ctts']
}

function findAudioElstBox(mp4BoxTree) {
return findAudioTrakBox(mp4BoxTree)['edts']['elst']
}

function findVideoElstBox(mp4BoxTree) {
return findAudioTrakBox(mp4BoxTree)['edts']['elst']
}
5 changes: 4 additions & 1 deletion packages/griffith-mp4/src/mp4/utils/getSamplesInterval.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,16 @@ export function getAudioSamplesInterval(mp4BoxTree, videoInterval) {
const {timescale: videoTimescale} = findBox(mp4BoxTree, 'videoMdhd')
const videoStszBox = findBox(mp4BoxTree, 'videoStsz')
const audioStszBox = findBox(mp4BoxTree, 'audioStsz')
const audioElstBox = findBox(mp4BoxTree, 'audioElst')

const audioStartTime = (startTime / videoTimescale) * audioTimescale
const audioEndTime = (endTime / videoTimescale) * audioTimescale

let start = 0
let end = 0
let startDuration = 0

const {mediaTime} = audioElstBox.entries[0]
let startDuration = mediaTime || 0
let endDuration = 0
for (let i = 0; i < sttsBox.samples.length; i++) {
const {sampleCount, sampleDelta} = sttsBox.samples[i]
Expand Down
46 changes: 32 additions & 14 deletions packages/griffith-mp4/src/mse/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ export default class MSE {
constructor(video, src) {
this.video = video
this.src = src
this.sourceBuffers = {
video: null,
audio: null,
}
this.mimeTypes = {
video: 'video/mp4; codecs="avc1.42E01E"',
audio: 'audio/mp4; codecs="mp4a.40.2"',
}
this.installSrc()
}

Expand All @@ -20,9 +28,13 @@ export default class MSE {
}

handleSourceOpen = () => {
const mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
this.sourceBuffer = this.mediaSource.addSourceBuffer(mime)
this.sourceBuffer.addEventListener('updateend', () => {
this.sourceBuffers.video = this.mediaSource.addSourceBuffer(
this.mimeTypes.video
)
this.sourceBuffers.audio = this.mediaSource.addSourceBuffer(
this.mimeTypes.audio
)
this.sourceBuffers.video.addEventListener('updateend', () => {
this.mseUpdating = false

if (this.needUpdateTime) {
Expand Down Expand Up @@ -73,13 +85,19 @@ export default class MSE {
this.mp4Probe = new MP4Probe(mp4BoxTreeObject)
this.mp4BoxTreeObject = mp4BoxTreeObject

const rawData = concatTypedArray(
const videoRawData = concatTypedArray(
FMP4.ftyp(),
FMP4.moov(this.mp4Probe.mp4Data, 'video')
)

const audioRawData = concatTypedArray(
FMP4.ftyp(),
FMP4.moov(this.mp4Probe.mp4Data)
FMP4.moov(this.mp4Probe.mp4Data, 'audio')
)

this.mediaSource.addEventListener('sourceopen', () => {
this.appendBuffer(rawData)
this.sourceBuffers.video.appendBuffer(videoRawData)
this.sourceBuffers.audio.appendBuffer(audioRawData)
})
})
}
Expand Down Expand Up @@ -121,23 +139,24 @@ export default class MSE {
const {videoInterval, audioInterval} = this.mp4Probe
const videoBaseMediaDecodeTime = videoInterval.timeInterVal[0]
const audioBaseMediaDecodeTime = audioInterval.timeInterVal[0]
const rawData = concatTypedArray(
const videoRawData = concatTypedArray(
FMP4.moof(videoTrackInfo, videoBaseMediaDecodeTime),
FMP4.mdat(videoTrackInfo),
FMP4.mdat(videoTrackInfo)
)

const audioRawData = concatTypedArray(
FMP4.moof(audioTrackInfo, audioBaseMediaDecodeTime),
FMP4.mdat(audioTrackInfo)
)
this.appendBuffer(rawData)

this.sourceBuffers.video.appendBuffer(videoRawData)
this.sourceBuffers.audio.appendBuffer(audioRawData)
if (time) {
this.needUpdateTime = true
}
})
}

appendBuffer(buffer) {
this.sourceBuffer.appendBuffer(buffer)
}

loadData(start = 0, end = MAGIC_NUMBER) {
return new Promise(resolve => {
new FragmentFetch(this.src, start, end, resolve)
Expand All @@ -154,7 +173,6 @@ export default class MSE {
videoInterval: {offsetInterVal = []} = [],
mp4Data: {videoSamplesLength},
} = this.mp4Probe

if (this.mediaSource.readyState === 'open') {
if (offsetInterVal[1] === videoSamplesLength && !this.mseUpdating) {
this.destroy()
Expand Down