cabana: fix bugs and refactor a bit of can-frame offset code, improving experience for panda users.

main
Andy Haden 2017-07-11 18:10:31 -07:00
parent 023736c5ad
commit 4939892761
7 changed files with 66 additions and 51 deletions

View File

@ -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
}); });
} }

View File

@ -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() {

View File

@ -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;

View File

@ -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;

View File

@ -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}

View File

@ -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}

View File

@ -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) {