Conversation
Distance sampling reads GPS only through the native extractors (GoPro, CAMM, BlackVue). Novatek based dashcams -- Viofo A129/A139, Rove R2-4K Pro, AZDome GS63H, Vantrue N4, Anker Roav C1 Pro -- store GPS in "freeGPS " blocks indexed by a moov/"gps " box, which none of them parse. So `video_process --video_sample_distance` finds no GPS in these videos, even though `process` geotags them fine through the ExifTool fallback. Add novatek_parser, tried last by NativeVideoExtractor. ExifTool tells the vendor layouts apart by probing each block in a fixed order (ProcessFreeGPS). The parser probes in the same order and decodes only the three layouts these cameras use, ExifTool GPSType 1, 3 and 15. The points are the ones the ExifTool fallback produces: same date handling, same dedupe/sort/rebase as _aggregate_gps_track, and numbers rounded to the 15 significant digits ExifTool prints. Anything the parser is not certain about returns None and still falls through to ExifTool as before: other layouts, blocks that also parse as Nextbase records, videos mixing layouts, type 3 timestamps that ExifTool converts from the time zone of the machine it runs on, and non-finite numbers. Failure raises MapillaryVideoGPSNotFoundError, which the geotag factory treats as reprocessable, so the ExifTool fallback in `process` is unchanged. Checked against ExifTool 13.40 on 669 dashcam and action camera videos: the 27 Novatek videos ExifTool reads now extract natively with points identical to ExifTool's, no other video changes, and `process` writes identical descriptions for all 35 videos that have a "gps " box.
The first version rebased point times on the first fix, as the ExifTool fallback does. Distance sampling interpolates the track at frame times, so that shifts the track whenever the camera gets its first fix after it starts recording. In timelapse videos, where GPS time runs faster than the video, it also leaves most of the track past the end of the video. The camera writes one freeGPS block per second of video, right after the frames of that second, whether it has a fix or not. So the position of the block in the index is its time in the video. Use that as the point time, and keep the GPS time in epoch_time as before. Since the timing relies on one block per second, leave the video to ExifTool if the block count doesn't match the duration in mvhd. Positions and GPS times still match ExifTool's on all 27 Novatek videos it reads. Times change on the four of them that get their first fix 17 to 35 seconds in, or are timelapse.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Distance sampling reads GPS only through the native extractors (GoPro, CAMM, BlackVue). Novatek based dashcams store GPS in
freeGPSblocks indexed by amoov/gpsbox, which none of them parse, so distance sampling finds no GPS in these videos:processgeotags the same videos fine, because it falls back to ExifTool. Affected: Viofo A129 and A139, Rove R2-4K Pro, AZDome GS63H, Vantrue N4, Anker Roav C1 Pro. With #839, this becomes a hard sampling failure instead of a silent one.Fix
Add
novatek_parser, tried last byNativeVideoExtractor.ExifTool tells the vendor layouts apart by probing each block in a fixed order (
ProcessFreeGPSinQuickTimeStream.pl) and numbers them with its GPSType. The parser probes in the same order and decodes only the three layouts these cameras use:Positions, headings and GPS times (
epoch_time) are the ones the ExifTool fallback produces for the same video: same date handling, same dedupe of repeated fixes, and numbers rounded to the 15 significant digits ExifTool prints.Point times
Point times are deliberately not ExifTool's. ExifTool's times count from the first fix, which is fine for geotagging the whole video but wrong for distance sampling, which interpolates the track at frame times.
The camera writes one block per second of video, right after the frames of that second, whether it has a fix or not, and in timelapse too. In all 35 videos I have with a
gpsbox, block i follows the frames of video second i: the frame before it is at i + 0.93 to 0.98 s. So the parser uses the position of the block in the index as the point time. Counting from the first fix instead would:Since the timing relies on one block per second, a video whose block count differs from its
mvhdduration by more than 1.5 is left to ExifTool.Left to ExifTool
Anything the parser is not certain about returns
Noneand falls through to ExifTool exactly as before:_aggregate_gps_trackwould align by position;Failure raises
MapillaryVideoGPSNotFoundError, which the geotag factory treats as reprocessable, soprocessstill falls back to ExifTool.Behaviour changes worth flagging
processpoint times. For these videos,processnow takes the points from the native extractor instead of ExifTool. The descriptions are byte-identical before and after for 31 of the 35 videos with agpsbox. The other 4 differ only in point times: the three late-first-fix clips (+17, +22 and +35 s) and the Rove timelapse. Positions, headings and all other fields are unchanged.--video_geotag_source gpx, native GPS used to be missing for these videos, sosyncaligned the GPX start with the video start andstrict_syncfailed. Both now sync by GPS time. That is exact when the first fix is in the first second of the video. When the first fix comes later, the track ends up early by that many seconds, becauseGPXVideoExtractor._gpx_offsetassumes the first native point is at video time 0. Fix CAMM GPS epoch follow-ups from #828 #842 rewrites_gpx_offset, so I left gpx.py alone here. The fix is to anchor onvideo_gps_points[0].get_unix_time() - video_gps_points[0].time.Verification
Checked against ExifTool 13.40 on 669 dashcam and action camera videos:
process: as described above: 31 identical, 4 differing only in point times.Distance sampling on one real clip per camera, which previously produced no frames:
The 21 new unit tests build synthetic videos for each layout and cover late first fix, timelapse, skipped blocks, the fall-through cases, the block count check and GPX sync. Their expected positions and GPS times are what ExifTool 13.40 extracts from the same videos.
773 unit + integration tests pass on Python 3.9 and 3.14.
ruff check,ruff format --check,usort diffandmypyare clean on 3.9.Scope
Independent of #839 and #841: branches off
main, with no file overlap. #842 touchesnative.py(CAMM part only) andgpx.py; see GPX sync above.