Add error recovery to video, remove some dead code
parent
3464aec62c
commit
255a766e44
|
@ -14,7 +14,6 @@ export default class HLS extends Component {
|
||||||
onLoadEnd: PropTypes.func,
|
onLoadEnd: PropTypes.func,
|
||||||
onPlaySeek: PropTypes.func,
|
onPlaySeek: PropTypes.func,
|
||||||
segmentProgress: PropTypes.func,
|
segmentProgress: PropTypes.func,
|
||||||
shouldRestart: PropTypes.bool,
|
|
||||||
onRestart: PropTypes.func
|
onRestart: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,6 +40,26 @@ export default class HLS extends Component {
|
||||||
enableWorker: false,
|
enableWorker: false,
|
||||||
disablePtsDtsCorrectionInMp4Remux: true
|
disablePtsDtsCorrectionInMp4Remux: true
|
||||||
});
|
});
|
||||||
|
this.player.on(Hls.Events.ERROR, (event, data) => {
|
||||||
|
if (data.fatal) {
|
||||||
|
switch (data.type) {
|
||||||
|
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||||
|
// try to recover network error
|
||||||
|
console.log("fatal network error encountered, try to recover");
|
||||||
|
this.player.startLoad();
|
||||||
|
break;
|
||||||
|
case Hls.ErrorTypes.MEDIA_ERROR:
|
||||||
|
console.log("fatal media error encountered, try to recover");
|
||||||
|
this.player.recoverMediaError();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// cannot recover
|
||||||
|
this.player.destroy();
|
||||||
|
this.player = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
this.loadSource();
|
this.loadSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +97,7 @@ export default class HLS extends Component {
|
||||||
// destroy hls video source
|
// destroy hls video source
|
||||||
if (this.player) {
|
if (this.player) {
|
||||||
this.player.destroy();
|
this.player.destroy();
|
||||||
|
this.player = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { StyleSheet, css } from 'aphrodite/no-important';
|
import { StyleSheet, css } from 'aphrodite/no-important';
|
||||||
import { derived as RouteApi, video as VideoApi } from '@commaai/comma-api';
|
import { video as VideoApi } from '@commaai/comma-api';
|
||||||
|
|
||||||
import HLS from './HLS';
|
import HLS from './HLS';
|
||||||
import RouteSeeker from './RouteSeeker/RouteSeeker';
|
import RouteSeeker from './RouteSeeker/RouteSeeker';
|
||||||
|
@ -50,7 +50,6 @@ export default class RouteVideoSync extends Component {
|
||||||
shouldShowJpeg: true,
|
shouldShowJpeg: true,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
videoElement: null,
|
videoElement: null,
|
||||||
shouldRestartHls: false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onLoadStart = this.onLoadStart.bind(this);
|
this.onLoadStart = this.onLoadStart.bind(this);
|
||||||
|
@ -59,27 +58,12 @@ export default class RouteVideoSync extends Component {
|
||||||
this.onVideoElementAvailable = this.onVideoElementAvailable.bind(this);
|
this.onVideoElementAvailable = this.onVideoElementAvailable.bind(this);
|
||||||
this.onUserSeek = this.onUserSeek.bind(this);
|
this.onUserSeek = this.onUserSeek.bind(this);
|
||||||
this.onPlaySeek = this.onPlaySeek.bind(this);
|
this.onPlaySeek = this.onPlaySeek.bind(this);
|
||||||
this.onHlsRestart = this.onHlsRestart.bind(this);
|
|
||||||
this.ratioTime = this.ratioTime.bind(this);
|
this.ratioTime = this.ratioTime.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(nextProps) {
|
componentDidUpdate(nextProps) {
|
||||||
const {
|
const { userSeekTime } = this.props;
|
||||||
userSeekIndex,
|
|
||||||
message,
|
|
||||||
canFrameOffset,
|
|
||||||
userSeekTime
|
|
||||||
} = this.props;
|
|
||||||
const { videoElement } = this.state;
|
const { videoElement } = this.state;
|
||||||
if (
|
|
||||||
userSeekIndex !== nextProps.userSeekIndex
|
|
||||||
|| canFrameOffset !== nextProps.canFrameOffset
|
|
||||||
|| (message
|
|
||||||
&& nextProps.message
|
|
||||||
&& message.entries.length !== nextProps.message.entries.length)
|
|
||||||
) {
|
|
||||||
this.setState({ shouldRestartHls: true });
|
|
||||||
}
|
|
||||||
if (
|
if (
|
||||||
nextProps.userSeekTime
|
nextProps.userSeekTime
|
||||||
&& userSeekTime !== nextProps.userSeekTime
|
&& userSeekTime !== nextProps.userSeekTime
|
||||||
|
@ -103,22 +87,15 @@ export default class RouteVideoSync extends Component {
|
||||||
const funcSeekToRatio = () => onUserSeek(seekTime);
|
const funcSeekToRatio = () => onUserSeek(seekTime);
|
||||||
|
|
||||||
if (Number.isNaN(videoElement.duration)) {
|
if (Number.isNaN(videoElement.duration)) {
|
||||||
this.setState({ shouldRestartHls: true }, funcSeekToRatio);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
videoElement.currentTime = seekTime;
|
videoElement.currentTime = seekTime;
|
||||||
|
|
||||||
if (ratio === 0) {
|
if (ratio !== 0) {
|
||||||
this.setState({ shouldRestartHls: true }, funcSeekToRatio);
|
|
||||||
} else {
|
|
||||||
funcSeekToRatio();
|
funcSeekToRatio();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onHlsRestart() {
|
|
||||||
this.setState({ shouldRestartHls: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
onPlaySeek(offset) {
|
onPlaySeek(offset) {
|
||||||
const { onPlaySeek } = this.props;
|
const { onPlaySeek } = this.props;
|
||||||
this.seekTime = offset;
|
this.seekTime = offset;
|
||||||
|
@ -204,7 +181,6 @@ export default class RouteVideoSync extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
isLoading,
|
isLoading,
|
||||||
shouldRestartHls,
|
|
||||||
shouldShowJpeg,
|
shouldShowJpeg,
|
||||||
videoElement
|
videoElement
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
@ -244,8 +220,6 @@ export default class RouteVideoSync extends Component {
|
||||||
onUserSeek={this.onUserSeek}
|
onUserSeek={this.onUserSeek}
|
||||||
onPlaySeek={this.onPlaySeek}
|
onPlaySeek={this.onPlaySeek}
|
||||||
segmentProgress={this.segmentProgress}
|
segmentProgress={this.segmentProgress}
|
||||||
shouldRestart={shouldRestartHls}
|
|
||||||
onRestart={this.onHlsRestart}
|
|
||||||
/>
|
/>
|
||||||
<RouteSeeker
|
<RouteSeeker
|
||||||
className={css(Styles.seekBar)}
|
className={css(Styles.seekBar)}
|
||||||
|
@ -268,11 +242,8 @@ export default class RouteVideoSync extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
RouteVideoSync.propTypes = {
|
RouteVideoSync.propTypes = {
|
||||||
userSeekIndex: PropTypes.number.isRequired,
|
|
||||||
segment: PropTypes.array.isRequired,
|
segment: PropTypes.array.isRequired,
|
||||||
message: PropTypes.object,
|
|
||||||
thumbnails: PropTypes.array,
|
thumbnails: PropTypes.array,
|
||||||
canFrameOffset: PropTypes.number.isRequired,
|
|
||||||
url: PropTypes.string.isRequired,
|
url: PropTypes.string.isRequired,
|
||||||
playing: PropTypes.bool.isRequired,
|
playing: PropTypes.bool.isRequired,
|
||||||
onPlaySeek: PropTypes.func.isRequired,
|
onPlaySeek: PropTypes.func.isRequired,
|
||||||
|
|
Loading…
Reference in New Issue