cabana: fix bugs and refactor a bit of can-frame offset code, improving experience for panda users.
parent
023736c5ad
commit
4939892761
|
@ -146,7 +146,7 @@ export default class CanExplorer extends Component {
|
||||||
prevMsgEntries = {};
|
prevMsgEntries = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const {dbc, dbcFilename, route, firstCanTime} = this.state;
|
const {dbc, dbcFilename, route, firstCanTime, canFrameOffset} = this.state;
|
||||||
var worker = new CanFetcher();
|
var worker = new CanFetcher();
|
||||||
|
|
||||||
worker.onmessage = (e) => {
|
worker.onmessage = (e) => {
|
||||||
|
@ -196,7 +196,7 @@ export default class CanExplorer extends Component {
|
||||||
worker.postMessage({dbcText: dbc.text(),
|
worker.postMessage({dbcText: dbc.text(),
|
||||||
base: route.url,
|
base: route.url,
|
||||||
num: part,
|
num: part,
|
||||||
canStartTime: firstCanTime,
|
canStartTime: firstCanTime - canFrameOffset,
|
||||||
prevMsgEntries
|
prevMsgEntries
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,29 @@ const DEMO_ROUTES = {
|
||||||
"start_lng": -122.465,
|
"start_lng": -122.465,
|
||||||
"start_time": "2017-06-30T17:37:49",
|
"start_time": "2017-06-30T17:37:49",
|
||||||
"url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/b67ff0c1d78774da/c130d5eaf04518c4d08ede29efbd519b_2017-06-30--17-37-49"
|
"url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/b67ff0c1d78774da/c130d5eaf04518c4d08ede29efbd519b_2017-06-30--17-37-49"
|
||||||
}
|
},
|
||||||
|
"2017-07-10--19-11-08": { // elikorh panda route with bad offset
|
||||||
|
"can": true,
|
||||||
|
"device_type": 2,
|
||||||
|
"end_geocode": "Fargo",
|
||||||
|
"end_lat": 46.9041,
|
||||||
|
"end_lng": -96.8059,
|
||||||
|
"end_time": "2017-07-10T19:19:34",
|
||||||
|
"fullname": "03ad84b839400fdb|2017-07-10--19-11-08",
|
||||||
|
"len": 5.4562,
|
||||||
|
"maxcamera": 8,
|
||||||
|
"maxlog": 8,
|
||||||
|
"movie": true,
|
||||||
|
"piececount": 8,
|
||||||
|
"proccamera": 8,
|
||||||
|
"proclog": 8,
|
||||||
|
"sig_path": "03ad84b839400fdb/29176323acf8f30b6a09c188d8a3edb9_2017-07-10--19-11-08",
|
||||||
|
"start_geocode": "Fargo",
|
||||||
|
"start_lat": 46.8565,
|
||||||
|
"start_lng": -96.8426,
|
||||||
|
"start_time": "2017-07-10T19:11:08",
|
||||||
|
"url": "https://chffrprivate.blob.core.windows.net/chffrprivate3/v2/03ad84b839400fdb/29176323acf8f30b6a09c188d8a3edb9_2017-07-10--19-11-08"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function getCommaAccessToken() {
|
function getCommaAccessToken() {
|
||||||
|
|
|
@ -44,8 +44,7 @@ export default class HLS extends Component {
|
||||||
this.videoElement.addEventListener('seeking', () => {
|
this.videoElement.addEventListener('seeking', () => {
|
||||||
if(!this.props.playing) {
|
if(!this.props.playing) {
|
||||||
this.props.onLoadStart();
|
this.props.onLoadStart();
|
||||||
const progress = this.props.segmentProgress(this.videoElement.currentTime);
|
this.props.onPlaySeek(this.videoElement.currentTime);
|
||||||
this.props.onPlaySeek(progress);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let shouldInitVideoTime = true;
|
let shouldInitVideoTime = true;
|
||||||
|
|
|
@ -156,7 +156,7 @@ export default class RouteSeeker extends Component {
|
||||||
|
|
||||||
if(newRatio >= 0) {
|
if(newRatio >= 0) {
|
||||||
this.updateSeekedBar(newRatio);
|
this.updateSeekedBar(newRatio);
|
||||||
this.props.onPlaySeek(newRatio);
|
this.props.onPlaySeek(currentTime);
|
||||||
}
|
}
|
||||||
}, 30);
|
}, 30);
|
||||||
let {ratio} = this.state;
|
let {ratio} = this.state;
|
||||||
|
|
|
@ -22,7 +22,7 @@ export default class RouteVideoSync extends Component {
|
||||||
onUserSeek: PropTypes.func.isRequired,
|
onUserSeek: PropTypes.func.isRequired,
|
||||||
onPlay: PropTypes.func.isRequired,
|
onPlay: PropTypes.func.isRequired,
|
||||||
onPause: PropTypes.func.isRequired,
|
onPause: PropTypes.func.isRequired,
|
||||||
userSeekRatio: PropTypes.number.isRequired
|
userSeekTime: PropTypes.number.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -53,17 +53,9 @@ export default class RouteVideoSync extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nearestFrameTime() {
|
|
||||||
const {userSeekTime, message, canFrameOffset, firstCanTime} = this.props;
|
|
||||||
if(!message) {
|
|
||||||
return this.ratioTime(this.props.userSeekRatio);
|
|
||||||
}
|
|
||||||
return canFrameOffset + this.props.userSeekTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
nearestFrameUrl() {
|
nearestFrameUrl() {
|
||||||
const {url} = this.props;
|
const {url} = this.props;
|
||||||
const sec = Math.round(this.nearestFrameTime());
|
const sec = Math.round(this.props.userSeekTime);
|
||||||
return cameraPath(url, sec);
|
return cameraPath(url, sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +99,7 @@ export default class RouteVideoSync extends Component {
|
||||||
onUserSeek(ratio) {
|
onUserSeek(ratio) {
|
||||||
/* ratio in [0,1] */
|
/* ratio in [0,1] */
|
||||||
|
|
||||||
const funcSeekToRatio = () => this.props.onUserSeek(ratio);
|
const funcSeekToRatio = () => this.props.onUserSeek(this.ratioTime(ratio));
|
||||||
if(ratio == 0) {
|
if(ratio == 0) {
|
||||||
this.setState({shouldRestartHls: true},
|
this.setState({shouldRestartHls: true},
|
||||||
funcSeekToRatio);
|
funcSeekToRatio);
|
||||||
|
@ -130,7 +122,7 @@ export default class RouteVideoSync extends Component {
|
||||||
<HLS
|
<HLS
|
||||||
className={css(Styles.hls)}
|
className={css(Styles.hls)}
|
||||||
source={Video.videoUrlForRouteUrl(this.props.url)}
|
source={Video.videoUrlForRouteUrl(this.props.url)}
|
||||||
startTime={this.nearestFrameTime()}
|
startTime={this.props.userSeekTime}
|
||||||
playbackSpeed={1}
|
playbackSpeed={1}
|
||||||
onVideoElementAvailable={this.onVideoElementAvailable}
|
onVideoElementAvailable={this.onVideoElementAvailable}
|
||||||
playing={this.props.playing}
|
playing={this.props.playing}
|
||||||
|
@ -144,7 +136,7 @@ export default class RouteVideoSync extends Component {
|
||||||
onRestart={this.onHlsRestart} />
|
onRestart={this.onHlsRestart} />
|
||||||
<RouteSeeker
|
<RouteSeeker
|
||||||
className={css(Styles.seekBar)}
|
className={css(Styles.seekBar)}
|
||||||
nearestFrameTime={this.nearestFrameTime()}
|
nearestFrameTime={this.props.userSeekTime}
|
||||||
segmentProgress={this.segmentProgress}
|
segmentProgress={this.segmentProgress}
|
||||||
secondsLoaded={this.props.secondsLoaded}
|
secondsLoaded={this.props.secondsLoaded}
|
||||||
segmentIndices={this.props.segmentIndices}
|
segmentIndices={this.props.segmentIndices}
|
||||||
|
|
|
@ -41,9 +41,8 @@ export default class Explorer extends Component {
|
||||||
segmentIndices: [],
|
segmentIndices: [],
|
||||||
shouldShowAddSignal: true,
|
shouldShowAddSignal: true,
|
||||||
userSeekIndex: 0,
|
userSeekIndex: 0,
|
||||||
userSeekRatio: 0,
|
userSeekTime: props.currentParts[0] * 60,
|
||||||
userSeekTime: 0,
|
playing: props.autoplay,
|
||||||
playing: this.props.autoplay,
|
|
||||||
signals: {}
|
signals: {}
|
||||||
};
|
};
|
||||||
this.onSignalPlotPressed = this.onSignalPlotPressed.bind(this);
|
this.onSignalPlotPressed = this.onSignalPlotPressed.bind(this);
|
||||||
|
@ -185,13 +184,10 @@ export default class Explorer extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nextProps.partsLoaded !== this.props.partsLoaded && !nextMessage) {
|
if(JSON.stringify(nextProps.currentParts) !== JSON.stringify(this.props.currentParts)) {
|
||||||
let userSeekRatio = this.state.userSeekRatio;
|
const {userSeekTime} = this.state;
|
||||||
const nextSecondsLoaded = this.secondsLoadedRouteRelative(nextProps.currentParts);
|
const nextSeekTime = (userSeekTime - this.props.currentParts[0] * 60) + nextProps.currentParts[0] * 60;
|
||||||
userSeekRatio = (userSeekRatio * this.secondsLoaded()) / nextSecondsLoaded;
|
this.setState({userSeekTime: nextSeekTime});
|
||||||
|
|
||||||
|
|
||||||
this.setState({userSeekRatio});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,42 +247,50 @@ export default class Explorer extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
resetSegment() {
|
resetSegment() {
|
||||||
this.setState({segment: [], segmentIndices: [], userSeekIndex: 0, userSeekTime: 0})
|
const {segment, segmentIndices} = this.state;
|
||||||
|
if(segment.length > 0 || segmentIndices.length > 0) {
|
||||||
|
this.setState({segment: [], segmentIndices: [], userSeekIndex: 0, userSeekTime: 0})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showAddSignal() {
|
showAddSignal() {
|
||||||
this.setState({shouldShowAddSignal: true})
|
this.setState({shouldShowAddSignal: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
indexFromSeekRatio(ratio) {
|
indexFromSeekTime(time) {
|
||||||
// returns index guaranteed to be in [0, entries.length - 1]
|
// returns index guaranteed to be in [0, entries.length - 1]
|
||||||
|
|
||||||
const {entries} = this.props.messages[this.props.selectedMessage];
|
const {entries} = this.props.messages[this.props.selectedMessage];
|
||||||
const {segmentIndices} = this.state;
|
const {segmentIndices} = this.state;
|
||||||
let segmentLength, offset;
|
let segmentLength, offset;
|
||||||
if(segmentIndices.length === 2) {
|
if(segmentIndices.length === 2) {
|
||||||
offset = segmentIndices[0];
|
for(let i = segmentIndices[0]; i <= segmentIndices[1]; i++) {
|
||||||
segmentLength = segmentIndices[1] - segmentIndices[0];
|
if(entries[i].relTime >= time) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segmentIndices[1];
|
||||||
} else {
|
} else {
|
||||||
offset = 0;
|
for(let i = 0; i < entries.length; i++) {
|
||||||
segmentLength = entries.length;
|
if(entries[i].relTime >= time) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entries.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.min(entries.length - 1, offset + Math.round(ratio * (segmentLength - 1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onUserSeek(ratio) {
|
onUserSeek(time) {
|
||||||
this.setState({userSeekRatio: ratio});
|
this.setState({userSeekTime: time});
|
||||||
const message = this.props.messages[this.props.selectedMessage];
|
const message = this.props.messages[this.props.selectedMessage];
|
||||||
if(!message) {
|
if(!message) {
|
||||||
const seekTime = ratio * this.secondsLoaded() + this.startOffset();
|
this.props.onUserSeek(time);
|
||||||
this.props.onUserSeek(seekTime);
|
this.props.onSeek(0, time);
|
||||||
this.props.onSeek(0, ratio * this.secondsLoaded() + this.startOffset());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {entries} = message;
|
const {entries} = message;
|
||||||
const userSeekIndex = this.indexFromSeekRatio(ratio);
|
const userSeekIndex = this.indexFromSeekTime(time);
|
||||||
const seekTime = entries[userSeekIndex].relTime;
|
const seekTime = entries[userSeekIndex].relTime;
|
||||||
|
|
||||||
this.setState({userSeekIndex, userSeekTime: seekTime});
|
this.setState({userSeekIndex, userSeekTime: seekTime});
|
||||||
|
@ -294,16 +298,16 @@ export default class Explorer extends Component {
|
||||||
this.props.onSeek(userSeekIndex, seekTime);
|
this.props.onSeek(userSeekIndex, seekTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPlaySeek(ratio) {
|
onPlaySeek(time) {
|
||||||
const message = this.props.messages[this.props.selectedMessage];
|
const message = this.props.messages[this.props.selectedMessage];
|
||||||
if(!message) {
|
if(!message) {
|
||||||
this.props.onSeek(0, ratio * this.secondsLoaded() + this.startOffset());
|
this.props.onSeek(0, time);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {entries} = message
|
const {entries} = message
|
||||||
|
|
||||||
const seekIndex = this.indexFromSeekRatio(ratio);
|
const seekIndex = this.indexFromSeekTime(time);
|
||||||
const seekTime = entries[seekIndex].relTime;
|
const seekTime = entries[seekIndex].relTime;
|
||||||
|
|
||||||
this.props.onSeek(seekIndex, seekTime);
|
this.props.onSeek(seekIndex, seekTime);
|
||||||
|
@ -320,7 +324,6 @@ export default class Explorer extends Component {
|
||||||
this.props.onUserSeek(time);
|
this.props.onUserSeek(time);
|
||||||
|
|
||||||
this.setState({userSeekIndex,
|
this.setState({userSeekIndex,
|
||||||
userSeekRatio: (userSeekIndex) / entries.length,
|
|
||||||
userSeekTime: time});
|
userSeekTime: time});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +371,7 @@ export default class Explorer extends Component {
|
||||||
startTime = entries[0].relTime;
|
startTime = entries[0].relTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
return canFrameOffset + startTime;
|
return startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
onVideoClick() {
|
onVideoClick() {
|
||||||
|
@ -459,12 +462,11 @@ export default class Explorer extends Component {
|
||||||
onUserSeek={this.onUserSeek}
|
onUserSeek={this.onUserSeek}
|
||||||
onPlay={this.onPlay}
|
onPlay={this.onPlay}
|
||||||
onPause={this.onPause}
|
onPause={this.onPause}
|
||||||
userSeekRatio={this.state.userSeekRatio}
|
|
||||||
userSeekTime={this.state.userSeekTime} />
|
userSeekTime={this.state.userSeekTime} />
|
||||||
|
|
||||||
{this.state.segment.length > 0 ?
|
{this.state.segment.length > 0 ?
|
||||||
<div className={css(CommonStyles.button, Styles.resetSegment)}
|
<div className={css(CommonStyles.button, Styles.resetSegment)}
|
||||||
onClick={() => this.resetSegment()}>
|
onClick={() => {this.resetSegment()}}>
|
||||||
<p>Reset Segment</p>
|
<p>Reset Segment</p>
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
|
|
|
@ -9,7 +9,7 @@ function calcCanFrameOffset(firstCanPart, partCanTimes) {
|
||||||
const firstPartLastCanTime = partCanTimes[partCanTimes.length - 1];
|
const firstPartLastCanTime = partCanTimes[partCanTimes.length - 1];
|
||||||
|
|
||||||
return (60 * firstCanPart
|
return (60 * firstCanPart
|
||||||
- (60 - (firstPartLastCanTime - firstCanTime)));
|
+ (60 - (firstPartLastCanTime - firstCanTime)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchCanTimes(base, part) {
|
async function fetchCanTimes(base, part) {
|
||||||
|
|
Loading…
Reference in New Issue