import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { StyleSheet, css } from 'aphrodite/no-important'; import { derived as RouteApi, video as VideoApi } from '@commaai/comma-api'; import HLS from './HLS'; import RouteSeeker from './RouteSeeker/RouteSeeker'; const Styles = StyleSheet.create({ loadingOverlay: { position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: 3 }, loadingSpinner: { width: '25%', height: '25%', display: 'block' }, img: { height: 480, display: 'block', position: 'absolute', zIndex: 2 }, hls: { zIndex: 1, height: 480, backgroundColor: 'rgba(0,0,0,0.9)' }, seekBar: { position: 'absolute', bottom: 0, left: 0, width: '100%', zIndex: 4 } }); export default class RouteVideoSync extends Component { static propTypes = { userSeekIndex: PropTypes.number.isRequired, segment: PropTypes.array.isRequired, message: PropTypes.object, canFrameOffset: PropTypes.number.isRequired, url: PropTypes.string.isRequired, playing: PropTypes.bool.isRequired, onPlaySeek: PropTypes.func.isRequired, onUserSeek: PropTypes.func.isRequired, onPlay: PropTypes.func.isRequired, onPause: PropTypes.func.isRequired, userSeekTime: PropTypes.number.isRequired, playSpeed: PropTypes.number.isRequired }; constructor(props) { super(props); this.state = { shouldShowJpeg: true, isLoading: true, videoElement: null, shouldRestartHls: false }; this.onLoadStart = this.onLoadStart.bind(this); this.onLoadEnd = this.onLoadEnd.bind(this); this.segmentProgress = this.segmentProgress.bind(this); this.onVideoElementAvailable = this.onVideoElementAvailable.bind(this); this.onUserSeek = this.onUserSeek.bind(this); this.onHlsRestart = this.onHlsRestart.bind(this); this.ratioTime = this.ratioTime.bind(this); } componentWillReceiveProps(nextProps) { if ( this.props.userSeekIndex !== nextProps.userSeekIndex || this.props.canFrameOffset !== nextProps.canFrameOffset || (this.props.message && nextProps.message && this.props.message.entries.length !== nextProps.message.entries.length) ) { this.setState({ shouldRestartHls: true }); } if ( nextProps.userSeekTime && this.props.userSeekTime !== nextProps.userSeekTime ) { if (this.state.videoElement) { this.state.videoElement.currentTime = nextProps.userSeekTime; } } } nearestFrameUrl() { const { url } = this.props; const sec = Math.round(this.props.userSeekTime); if (isNaN(sec)) { debugger; } return RouteApi(url).getJpegUrl(sec); } loadingOverlay() { return (