Skip to content

Commit

Permalink
Merge branch 'dev-mp3-audio-support'
Browse files Browse the repository at this point in the history
Add mp3 audio codec playback support (pull request #112)
  • Loading branch information
xqq committed Mar 20, 2017
2 parents 7197ebb + 183e9db commit e11cf53
Show file tree
Hide file tree
Showing 6 changed files with 360 additions and 101 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ flv.js is written in [ECMAScript 6][], transpiled into ECMAScript 5 by [Babel Co
[Browserify]: http://browserify.org/

## Features
- FLV container with H.264 + AAC codec playback
- FLV container with H.264 + AAC / MP3 codec playback
- Multipart segmented video playback
- HTTP FLV low latency live stream playback
- FLV over WebSocket live stream playback
Expand Down Expand Up @@ -61,6 +61,10 @@ See [cors.md](docs/cors.md) for more details.
</script>
```

## Limitations
- MP3 audio codec is currently not working on IE11 / Edge
- HTTP FLV live stream is not currently working on all browsers, see [livestream.md](docs/livestream.md)

## Multipart playback
You only have to provide a playlist for `MediaDataSource`. See [multipart.md](docs/multipart.md)

Expand Down
62 changes: 60 additions & 2 deletions src/core/mse-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class MSEController {
this._isBufferFull = false;
this._hasPendingEos = false;

this._requireSetMediaDuration = false;
this._pendingMediaDuration = 0;

this._pendingSourceBufferInit = [];
this._mimeTypes = {
video: null,
Expand Down Expand Up @@ -162,7 +165,11 @@ class MSEController {
}

let is = initSegment;
let mimeType = `${is.container};codecs=${is.codec}`;
let mimeType = `${is.container}`;
if (is.codec && is.codec.length > 0) {
mimeType += `;codecs=${is.codec}`;
}

let firstInitSegment = false;

Log.v(this.TAG, 'Received Initialization Segment, mimeType: ' + mimeType);
Expand Down Expand Up @@ -195,6 +202,13 @@ class MSEController {
this._doAppendSegments();
}
}
if (Browser.safari && is.container === 'audio/mpeg' && is.mediaDuration > 0) {
// 'audio/mpeg' track under Safari may cause MediaElement's duration to be NaN
// Manually correct MediaSource.duration to make progress bar seekable, and report right duration
this._requireSetMediaDuration = true;
this._pendingMediaDuration = is.mediaDuration / 1000; // in seconds
this._updateMediaSourceDuration();
}
}

appendMediaSegment(mediaSegment) {
Expand Down Expand Up @@ -293,6 +307,27 @@ class MSEController {
return this._idrList.getLastSyncPointBeforeDts(dts);
}

_updateMediaSourceDuration() {
let sb = this._sourceBuffers;
if (this._mediaElement.readyState === 0 || this._mediaSource.readyState !== 'open') {
return;
}
if ((sb.video && sb.video.updating) || (sb.audio && sb.audio.updating)) {
return;
}

let current = this._mediaSource.duration;
let target = this._pendingMediaDuration;

if (target > 0 && (isNaN(current) || target > current)) {
Log.v(this.TAG, `Update MediaSource duration from ${current} to ${target}`);
this._mediaSource.duration = target;
}

this._requireSetMediaDuration = false;
this._pendingMediaDuration = 0;
}

_doRemoveRanges() {
for (let type in this._pendingRemoveRanges) {
if (!this._sourceBuffers[type] || this._sourceBuffers[type].updating) {
Expand All @@ -314,8 +349,29 @@ class MSEController {
if (!this._sourceBuffers[type] || this._sourceBuffers[type].updating) {
continue;
}

if (pendingSegments[type].length > 0) {
let segment = pendingSegments[type].shift();

if (segment.timestampOffset) {
// For MPEG audio stream in MSE, if unbuffered-seeking occurred
// We need explicitly set timestampOffset to the desired point in timeline for mpeg SourceBuffer.
let currentOffset = this._sourceBuffers[type].timestampOffset;
let targetOffset = segment.timestampOffset / 1000; // in seconds

let delta = Math.abs(currentOffset - targetOffset);
if (delta > 0.1) { // If time delta > 100ms
Log.v(this.TAG, `Update MPEG audio timestampOffset from ${currentOffset} to ${targetOffset}`);
this._sourceBuffers[type].timestampOffset = targetOffset;
}
delete segment.timestampOffset;
}

if (!segment.data || segment.data.byteLength === 0) {
// Ignore empty buffer
continue;
}

try {
this._sourceBuffers[type].appendBuffer(segment.data);
this._isBufferFull = false;
Expand Down Expand Up @@ -392,7 +448,9 @@ class MSEController {
}

_onSourceBufferUpdateEnd() {
if (this._hasPendingRemoveRanges()) {
if (this._requireSetMediaDuration) {
this._updateMediaSourceDuration();
} else if (this._hasPendingRemoveRanges()) {
this._doRemoveRanges();
} else if (this._hasPendingSegments()) {
this._doAppendSegments();
Expand Down
Loading

0 comments on commit e11cf53

Please sign in to comment.