From 25ca9bc1f664a429a43e3c9c28fc6a81cd053672 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 27 Nov 2024 14:57:21 +0200 Subject: [PATCH 1/6] Fixed issue: player navigates to removed frames when playing --- .../annotation-page/top-bar/top-bar.tsx | 61 +++++++------------ 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx index e9d2785faf10..dd5f13ee806c 100644 --- a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx +++ b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx @@ -28,7 +28,7 @@ import { import AnnotationTopBarComponent from 'components/annotation-page/top-bar/top-bar'; import { Canvas } from 'cvat-canvas-wrapper'; import { Canvas3d } from 'cvat-canvas3d-wrapper'; -import { DimensionType, Job, JobType } from 'cvat-core-wrapper'; +import { Job } from 'cvat-core-wrapper'; import { CombinedState, FrameSpeed, @@ -225,10 +225,12 @@ type Props = StateToProps & DispatchToProps & RouteComponentProps; class AnnotationTopBarContainer extends React.PureComponent { private inputFrameRef: React.RefObject; private autoSaveInterval: number | undefined; + private lockedPlayTimeout: boolean; private unblock: any; constructor(props: Props) { super(props); + this.lockedPlayTimeout = false; this.inputFrameRef = React.createRef(); } @@ -572,7 +574,6 @@ class AnnotationTopBarContainer extends React.PureComponent { private play(): void { const { jobInstance, - frameSpeed, frameNumber, frameDelay, frameFetching, @@ -582,44 +583,26 @@ class AnnotationTopBarContainer extends React.PureComponent { onChangeFrame, } = this.props; - if (playing && canvasIsReady && !frameFetching) { - if (frameNumber < jobInstance.stopFrame) { - let framesSkipped = 0; - if (frameSpeed === FrameSpeed.Fast && frameNumber + 1 < jobInstance.stopFrame) { - framesSkipped = 1; - } - if (frameSpeed === FrameSpeed.Fastest && frameNumber + 2 < jobInstance.stopFrame) { - framesSkipped = 2; - } - - setTimeout(async () => { - const { playing: stillPlaying } = this.props; - if (stillPlaying) { - if (isAbleToChangeFrame()) { - if (jobInstance.type === JobType.GROUND_TRUTH) { - const newFrame = await jobInstance.frames.search( - { notDeleted: true }, - frameNumber + 1, - jobInstance.stopFrame, - ); - if (newFrame !== null) { - onChangeFrame(newFrame, stillPlaying); - } else { - onSwitchPlay(false); - } - } else { - onChangeFrame(frameNumber + 1 + framesSkipped, stillPlaying, framesSkipped + 1); - } - } else if (jobInstance.dimension === DimensionType.DIMENSION_2D) { - onSwitchPlay(false); - } else { - setTimeout(() => this.play(), frameDelay); - } + if (playing && canvasIsReady && !frameFetching && !this.lockedPlayTimeout) { + this.lockedPlayTimeout = true; + setTimeout(async () => { + const { playing: stillPlaying } = this.props; + this.lockedPlayTimeout = false; + + if (stillPlaying) { + const newFrame = await jobInstance.frames.search( + { notDeleted: true }, + frameNumber + 1, + jobInstance.stopFrame, + ); + + if (newFrame !== null && isAbleToChangeFrame(newFrame)) { + onChangeFrame(newFrame, stillPlaying); + } else { + onSwitchPlay(false); } - }, frameDelay); - } else { - onSwitchPlay(false); - } + } + }, frameDelay); } } From a540d0179fc6263379ad81cbd3281a1bf03f4cc0 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 27 Nov 2024 14:58:12 +0200 Subject: [PATCH 2/6] Added changelog fragment --- .../20241127_145739_sekachev.bs_simplified_navigation.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog.d/20241127_145739_sekachev.bs_simplified_navigation.md diff --git a/changelog.d/20241127_145739_sekachev.bs_simplified_navigation.md b/changelog.d/20241127_145739_sekachev.bs_simplified_navigation.md new file mode 100644 index 000000000000..55ba97093598 --- /dev/null +++ b/changelog.d/20241127_145739_sekachev.bs_simplified_navigation.md @@ -0,0 +1,4 @@ +### Fixed + +- Player may navigate to removed frames when playing + () From c17eb3578e48c9286df85490f0f721c5354ce621 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 27 Nov 2024 14:59:02 +0200 Subject: [PATCH 3/6] Update 20241127_145739_sekachev.bs_simplified_navigation.md --- .../20241127_145739_sekachev.bs_simplified_navigation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/20241127_145739_sekachev.bs_simplified_navigation.md b/changelog.d/20241127_145739_sekachev.bs_simplified_navigation.md index 55ba97093598..4fb6385e1d21 100644 --- a/changelog.d/20241127_145739_sekachev.bs_simplified_navigation.md +++ b/changelog.d/20241127_145739_sekachev.bs_simplified_navigation.md @@ -1,4 +1,4 @@ ### Fixed - Player may navigate to removed frames when playing - () + () From b197f1807375d99eab39569cd689012e2bd94e47 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 27 Nov 2024 16:17:35 +0200 Subject: [PATCH 4/6] Fixed minor issue --- .../annotation-page/top-bar/top-bar.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx index dd5f13ee806c..b301fc1d6e85 100644 --- a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx +++ b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx @@ -583,21 +583,24 @@ class AnnotationTopBarContainer extends React.PureComponent { onChangeFrame, } = this.props; + const { stopFrame } = jobInstance; + if (playing && canvasIsReady && !frameFetching && !this.lockedPlayTimeout) { this.lockedPlayTimeout = true; setTimeout(async () => { - const { playing: stillPlaying } = this.props; + const { playing: currentPlaying } = this.props; this.lockedPlayTimeout = false; - if (stillPlaying) { - const newFrame = await jobInstance.frames.search( - { notDeleted: true }, - frameNumber + 1, - jobInstance.stopFrame, - ); + if (currentPlaying) { + const nextCandidate = frameNumber + 1; + if (nextCandidate > stopFrame) { + onSwitchPlay(false); + return; + } - if (newFrame !== null && isAbleToChangeFrame(newFrame)) { - onChangeFrame(newFrame, stillPlaying); + const next = await jobInstance.frames.search({ notDeleted: true }, nextCandidate, stopFrame); + if (next !== null && isAbleToChangeFrame(next)) { + onChangeFrame(next, currentPlaying); } else { onSwitchPlay(false); } From 0bc26d33f6272d15c0649dee0e83aff459df7cdd Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 27 Nov 2024 16:27:33 +0200 Subject: [PATCH 5/6] Changed func to async --- .../annotation-page/top-bar/top-bar.tsx | 87 ++++++++++--------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx index b301fc1d6e85..15dc1d116f29 100644 --- a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx +++ b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx @@ -225,12 +225,12 @@ type Props = StateToProps & DispatchToProps & RouteComponentProps; class AnnotationTopBarContainer extends React.PureComponent { private inputFrameRef: React.RefObject; private autoSaveInterval: number | undefined; - private lockedPlayTimeout: boolean; + private isWaitingForPlayDelay: boolean; private unblock: any; constructor(props: Props) { super(props); - this.lockedPlayTimeout = false; + this.isWaitingForPlayDelay = false; this.inputFrameRef = React.createRef(); } @@ -272,7 +272,7 @@ class AnnotationTopBarContainer extends React.PureComponent { if (this.autoSaveInterval) window.clearInterval(this.autoSaveInterval); this.autoSaveInterval = window.setInterval(this.autoSave.bind(this), autoSaveInterval); } - this.play(); + this.handlePlayIfNecessary(); } public componentWillUnmount(): void { @@ -281,6 +281,49 @@ class AnnotationTopBarContainer extends React.PureComponent { this.unblock(); } + private async handlePlayIfNecessary(): Promise { + const { + jobInstance, + frameNumber, + frameDelay, + frameFetching, + playing, + canvasIsReady, + onSwitchPlay, + onChangeFrame, + } = this.props; + + const { stopFrame } = jobInstance; + + if (playing && canvasIsReady && !frameFetching && !this.isWaitingForPlayDelay) { + this.isWaitingForPlayDelay = true; + try { + await new Promise((resolve) => { + setTimeout(resolve, frameDelay); + }); + + const { playing: currentPlaying } = this.props; + + if (currentPlaying) { + const nextCandidate = frameNumber + 1; + if (nextCandidate > stopFrame) { + onSwitchPlay(false); + return; + } + + const next = await jobInstance.frames.search({ notDeleted: true }, nextCandidate, stopFrame); + if (next !== null && isAbleToChangeFrame(next)) { + onChangeFrame(next, currentPlaying); + } else { + onSwitchPlay(false); + } + } + } finally { + this.isWaitingForPlayDelay = false; + } + } + } + private undo = (): void => { const { undo, undoAction } = this.props; @@ -571,44 +614,6 @@ class AnnotationTopBarContainer extends React.PureComponent { return undefined; }; - private play(): void { - const { - jobInstance, - frameNumber, - frameDelay, - frameFetching, - playing, - canvasIsReady, - onSwitchPlay, - onChangeFrame, - } = this.props; - - const { stopFrame } = jobInstance; - - if (playing && canvasIsReady && !frameFetching && !this.lockedPlayTimeout) { - this.lockedPlayTimeout = true; - setTimeout(async () => { - const { playing: currentPlaying } = this.props; - this.lockedPlayTimeout = false; - - if (currentPlaying) { - const nextCandidate = frameNumber + 1; - if (nextCandidate > stopFrame) { - onSwitchPlay(false); - return; - } - - const next = await jobInstance.frames.search({ notDeleted: true }, nextCandidate, stopFrame); - if (next !== null && isAbleToChangeFrame(next)) { - onChangeFrame(next, currentPlaying); - } else { - onSwitchPlay(false); - } - } - }, frameDelay); - } - } - private autoSave(): void { const { autoSave, saving, onSaveAnnotation } = this.props; From baac19d510e3071f9f8cdf343c048ffef5ac5da8 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Thu, 28 Nov 2024 12:48:18 +0200 Subject: [PATCH 6/6] Applied comment --- cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx index 15dc1d116f29..7185106e05d8 100644 --- a/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx +++ b/cvat-ui/src/containers/annotation-page/top-bar/top-bar.tsx @@ -302,7 +302,7 @@ class AnnotationTopBarContainer extends React.PureComponent { setTimeout(resolve, frameDelay); }); - const { playing: currentPlaying } = this.props; + const { playing: currentPlaying, showDeletedFrames } = this.props; if (currentPlaying) { const nextCandidate = frameNumber + 1; @@ -311,7 +311,8 @@ class AnnotationTopBarContainer extends React.PureComponent { return; } - const next = await jobInstance.frames.search({ notDeleted: true }, nextCandidate, stopFrame); + const next = await jobInstance.frames + .search({ notDeleted: !showDeletedFrames }, nextCandidate, stopFrame); if (next !== null && isAbleToChangeFrame(next)) { onChangeFrame(next, currentPlaying); } else {