-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] - Multicam Display Support #1183
Conversation
I need to update the resizing of the windows based on the control size modification. Currently it is using a number from a frame behind. You can see this by collapsing/expanding the timeline area. If you collapse it and resize the window slightly you'll see it resize properly. The resize Observer is not calculating the proper height it is using the height before the timeline panel collapses down. |
* WIP * Doneish * WIP
630989f
to
910b53e
Compare
Through TrackStore development found another issue: |
List of changes since the merge:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if some of this is supposed to work, so I'm just noting it here:
- Continuous mode seems broken. When you start in continuous, then move into another camera, the "empty" annotation that gets created isn't removed, so if you're doing continuous, you end up with a bunch of detections with no geometry.
- Pressing
r
to recenter is broken
I ignored the trackstore.
export interface ImageDataItem { | ||
url: string; | ||
filename: string; | ||
} | ||
|
||
function loadImageFunc(imageDataItem: ImageDataItem, img: HTMLImageElement) { | ||
// eslint-disable-next-line no-param-reassign | ||
img.src = imageDataItem.url; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is identical to the default prop value. Why is it specified here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it's a remnant of the refactor, I'll remove it.
const defaultCamera = ref('default'); | ||
const selectedCamera = ref('default'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to do with with something other than strings. Using the reserved keyword "default" to name a camera causes the viewer to break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would the suggestion be to use a combined type for the camera references? null | string
where null is used in the case of a single camera? Then strings are used for multicameras.
const datasetType: Ref<DatasetType> = ref('image-sequence'); | ||
const datasetName = ref(''); | ||
const saveInProgress = ref(false); | ||
const videoUrl = ref(undefined as undefined | string); | ||
const videoUrl = ref({ default: null } as Record<string, null | string>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's subtle, but there are two empty conditions here when there should only be one.
Either the key is missing, or the key is set to null. So you have to compare against both null and undefined. It would be more strict to choose a single empty condition, which is that if no videourl exists for a camera, its key is not in the map at all, so you only have to compare against undefined.
let track = trackMap.get(selectedTrackId.value); | ||
if (selectedCamera.value !== 'default') { | ||
track = camTrackMap[selectedCamera.value].get(selectedTrackId.value); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like having consumers responsible for all this logic, it's just more for bugs.
Possibly not part of this PR, but i think we need to
- Get rid of
trackMap
and replace it withcamTrackMap
- Replace everywhere that access the trackMap with a
getTrack(map, id, camera)
call that properly throws an error if either the camera or id don't exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done this in the trackStore modification branch. There really is no longer a trackMap, it's all camMap
used in conjunction with different getTrack
functions. Except it's a little more complicated than a single getTrack
function, because getTrack(map, id, camera)
doesn't cover all needs, sometimes you just need the first trackId that's available and don't care what camera is selected, other times you need a conglomerate of all tracks across all cameras to display (in the case of the event Viewer for a selected track). Finally you need a list of all available tracks to iterate over (For setting confidence pairs on all tracks regardless of camera, or setting track wide attributes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, I remember talking about this now. If we need some new functions or a more complicated getTrack
that makes sense. I just don't want each function that needs to get a track to have to implement its own error handling / null checking.
if (!track) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this doing? We're inside an if (track)
block already.
FWIW, that if (track)
is also probably wrong because it implies that the else case is a valid execution path when it should probably be a runtime error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a typescript oddity that it believes that track can be undefined even though the forEach is inside of an if (track)
. I'll see what I can do about it. If not in this PR it should be resolved in the next when there is better way to get the track from the camMap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a typescript oddity
This would go beyond "oddity"--either there's some weird dynamics in this code that we're missing (perhaps due to lexical scoping of the forEach()
callback?), or there's a typescript bug. What error do you get when you omit the if block? You can also use this technique (https://stackoverflow.com/a/66124742/1886928) to force the compiler to tell you what it thinks the type of track
is at that point in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It believes that within the forEach that track can be Track | undefined
and doesn't want to use it as an argument to recipe.update
Update: Found an issue related exactly to this, marked as a duplicate to an issue that's still open:
microsoft/TypeScript#29916
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And how about outside of the forEach callback (3 lines up, on the track.canInterpolate()
invocation)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine there and is known as a track. I've updated my last comment and it might have been too late. But there is an issue exactly like this and has a simplistic demo showing the problem. I think I've seen this before as well.
microsoft/TypeScript#29916
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for looking into this.
I know this is nitpicky, but it happens from time to time. When typescript misbehaves, I think it would be better to put in a // @ts-ignore
than to insert code that handles what we know to be an invalid execution path. That return
should be unreachable, and I wouldn't blame a reasonable developer for seeing that in the future and ripping it out because it looks like it shouldn't be there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And because you don't want to disable type checks for that whole line, you can probably add something like this:
// @ts-ignore
const _track: Track = track;
const changes = recipe.update(eventType, frameNum, _track, [data], key);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also use a type assertion here ("casting" with the as
operator) to avoid having to disable the ts-lint rules.
trackMap: Map<TrackId, Track>; | ||
mediaController: Ref<MediaController>; | ||
camTrackMap: Record<string, Map<TrackId, Track>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should have trackMap
anymore.
watch(controlsRef, (previous) => { | ||
if (previous) observer.unobserve(previous.$el); | ||
if (controlsRef.value) observer.observe(controlsRef.value.$el); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment about what causes this watch to fire? I think it's shadowing the value of the wrapping v-if="progress.loaded"
, and I'm fine with doing it like this, I just want to make sure that's what's happening.
Maybe do the easy stuff and let's resolve the harder stuff later?
|
I've switch to The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wooo
Restructured the PRs for multicam into different feature branches. Renamed a branch and modified some stuff to make it a bit more clear what is happening.
Closes #1094.