mapillary-tools 0.11.2__tar.gz → 0.12.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mapillary_tools-0.11.2/mapillary_tools.egg-info → mapillary_tools-0.12.1}/PKG-INFO +3 -3
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/README.md +1 -1
- mapillary_tools-0.12.1/mapillary_tools/__init__.py +1 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/api_v4.py +0 -7
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/exif_write.py +8 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/ffmpeg.py +13 -1
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/gpmf_parser.py +128 -75
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/upload_api_v4.py +0 -7
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1/mapillary_tools.egg-info}/PKG-INFO +3 -3
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools.egg-info/requires.txt +1 -1
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/requirements.txt +1 -1
- mapillary_tools-0.11.2/mapillary_tools/__init__.py +0 -1
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/LICENSE +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/MANIFEST.in +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/authenticate.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/__init__.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/__main__.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/authenticate.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/process.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/process_and_upload.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/sample_video.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/upload.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/upload_blackvue.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/upload_camm.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/upload_zip.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/video_process.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/video_process_and_upload.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/zip.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/config.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/constants.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/exceptions.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/exif_read.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/exiftool_read.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/exiftool_read_video.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geo.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/__init__.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/blackvue_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/camm_builder.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/camm_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/construct_mp4_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_from_generic.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_exif.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_exiftool.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_exiftool_both_image_and_video.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_gpx.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_gpx_file.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_nmea_file.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_video.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_videos_from_exiftool_video.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_videos_from_video.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/gpmf_gps_filter.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/gps_filter.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/io_utils.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/mp4_sample_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/simple_mp4_builder.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/simple_mp4_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/utils.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/history.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/ipc.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/process_geotag_properties.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/process_import_meta_properties.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/process_sequence_properties.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/sample_video.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/types.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/upload.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/uploader.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/utils.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/cli_options.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extract_video_data.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/base_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/blackvue_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/camm_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/exiftool_runtime_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/exiftool_xml_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/generic_video_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/gopro_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/gpx_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/extractors/nmea_parser.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/video_data_extraction/video_data_parser_factory.py +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools.egg-info/SOURCES.txt +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools.egg-info/dependency_links.txt +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools.egg-info/entry_points.txt +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools.egg-info/top_level.txt +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/schema/image_description_schema.json +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/setup.cfg +0 -0
- {mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mapillary_tools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.1
|
|
4
4
|
Summary: Mapillary Image/Video Import Pipeline
|
|
5
5
|
Home-page: https://github.com/mapillary/mapillary_tools
|
|
6
6
|
Author: Mapillary
|
|
@@ -14,7 +14,7 @@ Requires-Dist: exifread==2.3.2
|
|
|
14
14
|
Requires-Dist: piexif==1.1.3
|
|
15
15
|
Requires-Dist: gpxpy<1.6.0,>=1.5.0
|
|
16
16
|
Requires-Dist: pynmea2<2.0.0,>=1.12.0
|
|
17
|
-
Requires-Dist: requests<3.0.0,>=2.20.0
|
|
17
|
+
Requires-Dist: requests[socks]<3.0.0,>=2.20.0
|
|
18
18
|
Requires-Dist: tqdm<5.0,>=4.0
|
|
19
19
|
Requires-Dist: typing_extensions
|
|
20
20
|
Requires-Dist: jsonschema~=4.17.3
|
|
@@ -82,7 +82,7 @@ mapillary_tools supports JPG/JEPG images (.jpg, .jpeg), with the following EXIF
|
|
|
82
82
|
mapillary_tools supports videos (.mp4, .360) that contain any of the following telemetry structures:
|
|
83
83
|
|
|
84
84
|
- [GPMF](https://github.com/gopro/gpmf-parser): mostly GoPro videos
|
|
85
|
-
- [GoPro HERO series](https://gopro.com/en/us/shop/cameras/hero11-black/CHDHX-111-master.html) (from 5 to
|
|
85
|
+
- [GoPro HERO series](https://gopro.com/en/us/shop/cameras/hero11-black/CHDHX-111-master.html) (from 5 to 13)
|
|
86
86
|
- [GoPro MAX](https://gopro.com/en/us/shop/cameras/max/CHDHZ-202-master.html)
|
|
87
87
|
- [CAMM](https://developers.google.com/streetview/publish/camm-spec): an open-standard telemetry spec supported by a number of cameras
|
|
88
88
|
- [Insta360 Pro2](https://www.insta360.com/product/insta360-pro2/)
|
|
@@ -60,7 +60,7 @@ mapillary_tools supports JPG/JEPG images (.jpg, .jpeg), with the following EXIF
|
|
|
60
60
|
mapillary_tools supports videos (.mp4, .360) that contain any of the following telemetry structures:
|
|
61
61
|
|
|
62
62
|
- [GPMF](https://github.com/gopro/gpmf-parser): mostly GoPro videos
|
|
63
|
-
- [GoPro HERO series](https://gopro.com/en/us/shop/cameras/hero11-black/CHDHX-111-master.html) (from 5 to
|
|
63
|
+
- [GoPro HERO series](https://gopro.com/en/us/shop/cameras/hero11-black/CHDHX-111-master.html) (from 5 to 13)
|
|
64
64
|
- [GoPro MAX](https://gopro.com/en/us/shop/cameras/max/CHDHZ-202-master.html)
|
|
65
65
|
- [CAMM](https://developers.google.com/streetview/publish/camm-spec): an open-standard telemetry spec supported by a number of cameras
|
|
66
66
|
- [Insta360 Pro2](https://www.insta360.com/product/insta360-pro2/)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.12.1"
|
|
@@ -9,10 +9,6 @@ MAPILLARY_CLIENT_TOKEN = os.getenv(
|
|
|
9
9
|
MAPILLARY_GRAPH_API_ENDPOINT = os.getenv(
|
|
10
10
|
"MAPILLARY_GRAPH_API_ENDPOINT", "https://graph.mapillary.com"
|
|
11
11
|
)
|
|
12
|
-
# https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification
|
|
13
|
-
MAPILLARY__DISABLE_VERIFYING_SSL = (
|
|
14
|
-
os.getenv("MAPILLARY__DISABLE_VERIFYING_SSL") == "TRUE"
|
|
15
|
-
)
|
|
16
12
|
REQUESTS_TIMEOUT = 60 # 1 minutes
|
|
17
13
|
|
|
18
14
|
|
|
@@ -22,7 +18,6 @@ def get_upload_token(email: str, password: str) -> requests.Response:
|
|
|
22
18
|
params={"access_token": MAPILLARY_CLIENT_TOKEN},
|
|
23
19
|
json={"email": email, "password": password, "locale": "en_US"},
|
|
24
20
|
timeout=REQUESTS_TIMEOUT,
|
|
25
|
-
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
26
21
|
)
|
|
27
22
|
resp.raise_for_status()
|
|
28
23
|
return resp
|
|
@@ -40,7 +35,6 @@ def fetch_organization(
|
|
|
40
35
|
"Authorization": f"OAuth {user_access_token}",
|
|
41
36
|
},
|
|
42
37
|
timeout=REQUESTS_TIMEOUT,
|
|
43
|
-
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
44
38
|
)
|
|
45
39
|
resp.raise_for_status()
|
|
46
40
|
return resp
|
|
@@ -62,7 +56,6 @@ def logging(action_type: ActionType, properties: T.Dict) -> requests.Response:
|
|
|
62
56
|
"Authorization": f"OAuth {MAPILLARY_CLIENT_TOKEN}",
|
|
63
57
|
},
|
|
64
58
|
timeout=REQUESTS_TIMEOUT,
|
|
65
|
-
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
66
59
|
)
|
|
67
60
|
resp.raise_for_status()
|
|
68
61
|
return resp
|
|
@@ -182,6 +182,14 @@ class ExifEdit:
|
|
|
182
182
|
# retry later
|
|
183
183
|
else:
|
|
184
184
|
raise exc
|
|
185
|
+
except Exception as exc:
|
|
186
|
+
zeroth_ifd = self._ef.get("0th", {})
|
|
187
|
+
# workaround: https://github.com/mapillary/mapillary_tools/issues/662
|
|
188
|
+
if piexif.ImageIFD.AsShotNeutral in zeroth_ifd:
|
|
189
|
+
del zeroth_ifd[piexif.ImageIFD.AsShotNeutral]
|
|
190
|
+
assert piexif.ImageIFD.AsShotNeutral not in zeroth_ifd
|
|
191
|
+
else:
|
|
192
|
+
raise exc
|
|
185
193
|
else:
|
|
186
194
|
break
|
|
187
195
|
|
|
@@ -195,6 +195,18 @@ class FFMPEG:
|
|
|
195
195
|
|
|
196
196
|
self._run_ffmpeg(cmd)
|
|
197
197
|
|
|
198
|
+
def generate_binary_search(self, sorted_frame_indices: T.Sequence[int]) -> str:
|
|
199
|
+
length = len(sorted_frame_indices)
|
|
200
|
+
|
|
201
|
+
if length == 0:
|
|
202
|
+
return "0"
|
|
203
|
+
|
|
204
|
+
if length == 1:
|
|
205
|
+
return f"eq(n\\,{ sorted_frame_indices[0] })"
|
|
206
|
+
|
|
207
|
+
middle = length // 2
|
|
208
|
+
return f"if(lt(n\\,{ sorted_frame_indices[middle] })\\,{ self.generate_binary_search(sorted_frame_indices[:middle]) }\\,{ self.generate_binary_search(sorted_frame_indices[middle:]) })"
|
|
209
|
+
|
|
198
210
|
def extract_specified_frames(
|
|
199
211
|
self,
|
|
200
212
|
video_path: Path,
|
|
@@ -226,7 +238,7 @@ class FFMPEG:
|
|
|
226
238
|
# the maximum command line length for the CreateProcess function is 32767 characters
|
|
227
239
|
# https://devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553
|
|
228
240
|
|
|
229
|
-
eqs =
|
|
241
|
+
eqs = self.generate_binary_search(sorted(frame_indices))
|
|
230
242
|
|
|
231
243
|
# https://github.com/mapillary/mapillary_tools/issues/503
|
|
232
244
|
if sys.platform in ["win32"]:
|
|
@@ -15,15 +15,16 @@ A GPS GPMF sample has the following structure:
|
|
|
15
15
|
- DVID: Auto generated unique-ID for managing a large number of connect devices
|
|
16
16
|
- STRM: Metadata streams are each nested with STRM
|
|
17
17
|
- GPS5: latitude, longitude, altitude (WGS 84), 2D ground speed, and 3D speed
|
|
18
|
+
- GPS9: lat, long, alt, 2D speed, 3D speed, days since 2000, secs since midnight (ms precision), DOP, fix (0, 2D or 3D)
|
|
18
19
|
- GPSA: not documented in the spec
|
|
19
20
|
- GPSF: Within the GPS stream: 0 - no lock, 2 or 3 - 2D or 3D Lock.
|
|
20
21
|
- GPSP: GPS Precision - Dilution of Precision (DOP x100). Under 500 is good.
|
|
21
22
|
- GPSU: UTC time and data from GPS. The time is read from from another clock so it is not in use.
|
|
22
|
-
- SCAL: Scaling factor (divisor) for GPS5
|
|
23
|
+
- SCAL: Scaling factor (divisor) for GPS5 and GPS9
|
|
23
24
|
|
|
24
25
|
NOTE:
|
|
25
26
|
- There might be multiple DEVC streams.
|
|
26
|
-
- Only GPS5 and SCAL are required. The others are optional.
|
|
27
|
+
- Only GPS5, GPS9, and SCAL are required. The others are optional.
|
|
27
28
|
- GPSU is not in use. We use the video clock to make sure frames and GPS are in sync.
|
|
28
29
|
- We should skip samples with GPSF==0 or GPSP > 500
|
|
29
30
|
"""
|
|
@@ -40,6 +41,66 @@ class KLVDict(T.TypedDict):
|
|
|
40
41
|
GPMFSampleData: C.GreedyRange
|
|
41
42
|
|
|
42
43
|
|
|
44
|
+
# type char: (construct type, size in bytes)
|
|
45
|
+
_type_mapping = {
|
|
46
|
+
# b single byte signed integer int8_t -128 to 127
|
|
47
|
+
b"b": (C.Int8sb, 1),
|
|
48
|
+
# B single byte unsigned integer uint8_t 0 to 255
|
|
49
|
+
b"B": (C.Int8ub, 1),
|
|
50
|
+
# c single byte 'c' style ASCII character string char Optionally NULL terminated - size/repeat sets the length
|
|
51
|
+
b"c": (C.Bytes(1), 1),
|
|
52
|
+
# d 64-bit double precision (IEEE 754) double
|
|
53
|
+
b"d": (C.Float64b, 8),
|
|
54
|
+
# f 32-bit float (IEEE 754) float
|
|
55
|
+
b"f": (C.Float32b, 4),
|
|
56
|
+
# F 32-bit four character key -- FourCC char fourcc[4]
|
|
57
|
+
b"F": (C.Bytes(4), 4),
|
|
58
|
+
# G 128-bit ID (like UUID) uint8_t guid[16]
|
|
59
|
+
b"G": (C.Bytes(16), 16),
|
|
60
|
+
# j 64-bit signed long number int64_t
|
|
61
|
+
b"j": (C.Int64sb, 8),
|
|
62
|
+
# J 64-bit unsigned long number uint64_t
|
|
63
|
+
b"J": (C.Int64ub, 8),
|
|
64
|
+
# l 32-bit signed integer int32_t
|
|
65
|
+
b"l": (C.Int32sb, 4),
|
|
66
|
+
# L 32-bit unsigned integer uint32_t
|
|
67
|
+
b"L": (C.Int32ub, 4),
|
|
68
|
+
# q 32-bit Q Number Q15.16 uint32_t 16-bit integer (A) with 16-bit fixed point (B) for A.B value (range -32768.0 to 32767.99998)
|
|
69
|
+
b"q": (C.Int32ub, 4),
|
|
70
|
+
# Q 64-bit Q Number Q31.32 uint64_t 32-bit integer (A) with 32-bit fixed point (B) for A.B value.
|
|
71
|
+
b"Q": (C.Int64ub, 8),
|
|
72
|
+
# s 16-bit signed integer int16_t -32768 to 32768
|
|
73
|
+
b"s": (C.Int16sb, 2),
|
|
74
|
+
# S 16-bit unsigned integer uint16_t 0 to 65536
|
|
75
|
+
b"S": (C.Int16ub, 2),
|
|
76
|
+
# U UTC Date and Time string char utcdate[16] Date + UTC Time format yymmddhhmmss.sss - (years 20xx covered)
|
|
77
|
+
b"U": (C.Bytes(16), 16),
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
_klv_data_switch = C.Switch(
|
|
82
|
+
C.this.type,
|
|
83
|
+
{
|
|
84
|
+
**{
|
|
85
|
+
type_char: C.Array(
|
|
86
|
+
C.this.repeat, C.Array(C.this.structure_size // size, ctype)
|
|
87
|
+
)
|
|
88
|
+
for type_char, (ctype, size) in _type_mapping.items()
|
|
89
|
+
},
|
|
90
|
+
# c single byte 'c' style ASCII character string char Optionally NULL terminated - size/repeat sets the length
|
|
91
|
+
b"c": C.Array(
|
|
92
|
+
C.this.repeat, C.Bytes(C.this.structure_size)
|
|
93
|
+
), # overwrite the one in _type_mapping to make sure it returns bytes instead of a list of bytes
|
|
94
|
+
# null Nested metadata uint32_t The data within is GPMF structured KLV data
|
|
95
|
+
b"\x00": C.FixedSized(
|
|
96
|
+
(C.this.repeat * C.this.structure_size),
|
|
97
|
+
C.LazyBound(lambda: GPMFSampleData),
|
|
98
|
+
),
|
|
99
|
+
},
|
|
100
|
+
C.Array(C.this.repeat, C.Bytes(C.this.structure_size)),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
43
104
|
KLV = C.Struct(
|
|
44
105
|
# FourCC
|
|
45
106
|
"key" / C.Bytes(4),
|
|
@@ -52,77 +113,7 @@ KLV = C.Struct(
|
|
|
52
113
|
# this is the Repeat field. Struct Size and the Repeat allow for up to
|
|
53
114
|
# 16.7MB of data in a single KLV GPMF payload.
|
|
54
115
|
"repeat" / C.Int16ub,
|
|
55
|
-
"data"
|
|
56
|
-
/ C.Switch(
|
|
57
|
-
C.this.type,
|
|
58
|
-
{
|
|
59
|
-
# b single byte signed integer int8_t -128 to 127
|
|
60
|
-
b"b": C.Array(C.this.repeat, C.Array(C.this.structure_size, C.Int8sb)),
|
|
61
|
-
# B single byte unsigned integer uint8_t 0 to 255
|
|
62
|
-
b"B": C.Array(C.this.repeat, C.Array(C.this.structure_size, C.Int8ub)),
|
|
63
|
-
# c single byte 'c' style ASCII character string char Optionally NULL terminated - size/repeat sets the length
|
|
64
|
-
b"c": C.Array(C.this.repeat, C.Bytes(C.this.structure_size)),
|
|
65
|
-
# d 64-bit double precision (IEEE 754) double
|
|
66
|
-
b"d": C.Array(
|
|
67
|
-
C.this.repeat, C.Array(C.this.structure_size // 8, C.Float64b)
|
|
68
|
-
),
|
|
69
|
-
# f 32-bit float (IEEE 754) float
|
|
70
|
-
b"f": C.Array(
|
|
71
|
-
C.this.repeat, C.Array(C.this.structure_size // 4, C.Float32b)
|
|
72
|
-
),
|
|
73
|
-
# F 32-bit four character key -- FourCC char fourcc[4]
|
|
74
|
-
b"F": C.Array(
|
|
75
|
-
C.this.repeat, C.Array(C.this.structure_size // 4, C.Bytes(4))
|
|
76
|
-
),
|
|
77
|
-
# G 128-bit ID (like UUID) uint8_t guid[16]
|
|
78
|
-
b"G": C.Array(
|
|
79
|
-
C.this.repeat, C.Array(C.this.structure_size // 16, C.Bytes(16))
|
|
80
|
-
),
|
|
81
|
-
# j 64-bit signed unsigned number int64_t
|
|
82
|
-
b"j": C.Array(
|
|
83
|
-
C.this.repeat, C.Array(C.this.structure_size // 8, C.Int64sb)
|
|
84
|
-
),
|
|
85
|
-
# J 64-bit unsigned unsigned number uint64_t
|
|
86
|
-
b"J": C.Array(
|
|
87
|
-
C.this.repeat, C.Array(C.this.structure_size // 8, C.Int64ub)
|
|
88
|
-
),
|
|
89
|
-
# l 32-bit signed integer int32_t
|
|
90
|
-
b"l": C.Array(
|
|
91
|
-
C.this.repeat, C.Array(C.this.structure_size // 4, C.Int32sb)
|
|
92
|
-
),
|
|
93
|
-
# L 32-bit unsigned integer uint32_t
|
|
94
|
-
b"L": C.Array(
|
|
95
|
-
C.this.repeat, C.Array(C.this.structure_size // 4, C.Int32ub)
|
|
96
|
-
),
|
|
97
|
-
# q 32-bit Q Number Q15.16 uint32_t 16-bit integer (A) with 16-bit fixed point (B) for A.B value (range -32768.0 to 32767.99998)
|
|
98
|
-
b"q": C.Array(
|
|
99
|
-
C.this.repeat, C.Array(C.this.structure_size // 4, C.Int32ub)
|
|
100
|
-
),
|
|
101
|
-
# Q 64-bit Q Number Q31.32 uint64_t 32-bit integer (A) with 32-bit fixed point (B) for A.B value.
|
|
102
|
-
b"Q": C.Array(
|
|
103
|
-
C.this.repeat, C.Array(C.this.structure_size // 8, C.Int64ub)
|
|
104
|
-
),
|
|
105
|
-
# s 16-bit signed integer int16_t -32768 to 32768
|
|
106
|
-
b"s": C.Array(
|
|
107
|
-
C.this.repeat, C.Array(C.this.structure_size // 2, C.Int16sb)
|
|
108
|
-
),
|
|
109
|
-
# S 16-bit unsigned integer uint16_t 0 to 65536
|
|
110
|
-
b"S": C.Array(
|
|
111
|
-
C.this.repeat, C.Array(C.this.structure_size // 2, C.Int16ub)
|
|
112
|
-
),
|
|
113
|
-
# U UTC Date and Time string char utcdate[16] Date + UTC Time format yymmddhhmmss.sss - (years 20xx covered)
|
|
114
|
-
b"U": C.Array(
|
|
115
|
-
C.this.repeat, C.Array(C.this.structure_size // 16, C.Bytes(16))
|
|
116
|
-
),
|
|
117
|
-
# ? data structure is complex TYPE Structure is defined with a preceding TYPE
|
|
118
|
-
# null Nested metadata uint32_t The data within is GPMF structured KLV data
|
|
119
|
-
b"\x00": C.FixedSized(
|
|
120
|
-
(C.this.repeat * C.this.structure_size),
|
|
121
|
-
C.LazyBound(lambda: GPMFSampleData),
|
|
122
|
-
),
|
|
123
|
-
},
|
|
124
|
-
C.Array(C.this.repeat, C.Bytes(C.this.structure_size)),
|
|
125
|
-
),
|
|
116
|
+
"data" / _klv_data_switch,
|
|
126
117
|
C.IfThenElse(
|
|
127
118
|
(C.this.repeat * C.this.structure_size) % 4 == 0,
|
|
128
119
|
C.Padding(0),
|
|
@@ -170,7 +161,7 @@ GPMFSampleData = C.GreedyRange(KLV)
|
|
|
170
161
|
# [378081666, -1224280064, 9621, 1492, 138],
|
|
171
162
|
# [378081662, -1224280049, 9592, 1476, 150],
|
|
172
163
|
# ]
|
|
173
|
-
def
|
|
164
|
+
def gps5_from_stream(
|
|
174
165
|
stream: T.Sequence[KLVDict],
|
|
175
166
|
) -> T.Generator[geo.PointWithFix, None, None]:
|
|
176
167
|
indexed: T.Dict[bytes, T.List[T.List[T.Any]]] = {
|
|
@@ -217,6 +208,64 @@ def gps_from_stream(
|
|
|
217
208
|
)
|
|
218
209
|
|
|
219
210
|
|
|
211
|
+
def gps9_from_stream(
|
|
212
|
+
stream: T.Sequence[KLVDict],
|
|
213
|
+
) -> T.Generator[geo.PointWithFix, None, None]:
|
|
214
|
+
indexed: T.Dict[bytes, T.List[T.List[T.Any]]] = {
|
|
215
|
+
klv["key"]: klv["data"] for klv in stream
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
gps9 = indexed.get(b"GPS9")
|
|
219
|
+
if gps9 is None:
|
|
220
|
+
return
|
|
221
|
+
|
|
222
|
+
scal = indexed.get(b"SCAL")
|
|
223
|
+
if scal is None:
|
|
224
|
+
return
|
|
225
|
+
scal_values = [s[0] for s in scal]
|
|
226
|
+
if any(s == 0 for s in scal_values):
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
type = indexed.get(b"TYPE")
|
|
230
|
+
if type is None:
|
|
231
|
+
return
|
|
232
|
+
gps_value_types = type[0]
|
|
233
|
+
|
|
234
|
+
try:
|
|
235
|
+
sample_parser = C.Sequence(
|
|
236
|
+
*[_type_mapping[t.to_bytes()][0] for t in gps_value_types]
|
|
237
|
+
)
|
|
238
|
+
except Exception as ex:
|
|
239
|
+
raise ValueError(f"Error parsing the complex type {gps_value_types}: {ex}")
|
|
240
|
+
|
|
241
|
+
for sample_data_bytes in gps9:
|
|
242
|
+
sample_data = sample_parser.parse(sample_data_bytes)
|
|
243
|
+
|
|
244
|
+
(
|
|
245
|
+
lat,
|
|
246
|
+
lon,
|
|
247
|
+
alt,
|
|
248
|
+
speed_2d,
|
|
249
|
+
_speed_3d,
|
|
250
|
+
_days_since_2000,
|
|
251
|
+
_secs_since_midnight,
|
|
252
|
+
dop,
|
|
253
|
+
gps_fix,
|
|
254
|
+
) = [v / s for v, s in zip(sample_data, scal_values)]
|
|
255
|
+
|
|
256
|
+
yield geo.PointWithFix(
|
|
257
|
+
# will figure out the actual timestamp later
|
|
258
|
+
time=0,
|
|
259
|
+
lat=lat,
|
|
260
|
+
lon=lon,
|
|
261
|
+
alt=alt,
|
|
262
|
+
gps_fix=geo.GPSFix(gps_fix),
|
|
263
|
+
gps_precision=dop * 100,
|
|
264
|
+
gps_ground_speed=speed_2d,
|
|
265
|
+
angle=None,
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
|
|
220
269
|
def _find_first_device_id(stream: T.Sequence[KLVDict]) -> int:
|
|
221
270
|
device_id = None
|
|
222
271
|
|
|
@@ -238,7 +287,11 @@ def _find_first_gps_stream(stream: T.Sequence[KLVDict]) -> T.List[geo.PointWithF
|
|
|
238
287
|
|
|
239
288
|
for klv in stream:
|
|
240
289
|
if klv["key"] == b"STRM":
|
|
241
|
-
sample_points = list(
|
|
290
|
+
sample_points = list(gps9_from_stream(klv["data"]))
|
|
291
|
+
if sample_points:
|
|
292
|
+
break
|
|
293
|
+
|
|
294
|
+
sample_points = list(gps5_from_stream(klv["data"]))
|
|
242
295
|
if sample_points:
|
|
243
296
|
break
|
|
244
297
|
|
|
@@ -15,10 +15,6 @@ MAPILLARY_UPLOAD_ENDPOINT = os.getenv(
|
|
|
15
15
|
MAPILLARY_GRAPH_API_ENDPOINT = os.getenv(
|
|
16
16
|
"MAPILLARY_GRAPH_API_ENDPOINT", "https://graph.mapillary.com"
|
|
17
17
|
)
|
|
18
|
-
# https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification
|
|
19
|
-
MAPILLARY__DISABLE_VERIFYING_SSL = (
|
|
20
|
-
os.getenv("MAPILLARY__DISABLE_VERIFYING_SSL") == "TRUE"
|
|
21
|
-
)
|
|
22
18
|
DEFAULT_CHUNK_SIZE = 1024 * 1024 * 16 # 16MB
|
|
23
19
|
# According to the docs, UPLOAD_REQUESTS_TIMEOUT can be a tuple of
|
|
24
20
|
# (connection_timeout, read_timeout): https://requests.readthedocs.io/en/latest/user/advanced/#timeouts
|
|
@@ -101,7 +97,6 @@ class UploadService:
|
|
|
101
97
|
url,
|
|
102
98
|
headers=headers,
|
|
103
99
|
timeout=REQUESTS_TIMEOUT,
|
|
104
|
-
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
105
100
|
)
|
|
106
101
|
LOG.debug("HTTP response %s: %s", resp.status_code, resp.content)
|
|
107
102
|
resp.raise_for_status()
|
|
@@ -144,7 +139,6 @@ class UploadService:
|
|
|
144
139
|
headers=headers,
|
|
145
140
|
data=chunk,
|
|
146
141
|
timeout=UPLOAD_REQUESTS_TIMEOUT,
|
|
147
|
-
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
148
142
|
)
|
|
149
143
|
LOG.debug(
|
|
150
144
|
"HTTP response %s: %s", resp.status_code, _truncate_end(resp.content)
|
|
@@ -191,7 +185,6 @@ class UploadService:
|
|
|
191
185
|
headers=headers,
|
|
192
186
|
json=data,
|
|
193
187
|
timeout=REQUESTS_TIMEOUT,
|
|
194
|
-
verify=not MAPILLARY__DISABLE_VERIFYING_SSL,
|
|
195
188
|
)
|
|
196
189
|
LOG.debug("HTTP response %s: %s", resp.status_code, _truncate_end(resp.content))
|
|
197
190
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mapillary_tools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.1
|
|
4
4
|
Summary: Mapillary Image/Video Import Pipeline
|
|
5
5
|
Home-page: https://github.com/mapillary/mapillary_tools
|
|
6
6
|
Author: Mapillary
|
|
@@ -14,7 +14,7 @@ Requires-Dist: exifread==2.3.2
|
|
|
14
14
|
Requires-Dist: piexif==1.1.3
|
|
15
15
|
Requires-Dist: gpxpy<1.6.0,>=1.5.0
|
|
16
16
|
Requires-Dist: pynmea2<2.0.0,>=1.12.0
|
|
17
|
-
Requires-Dist: requests<3.0.0,>=2.20.0
|
|
17
|
+
Requires-Dist: requests[socks]<3.0.0,>=2.20.0
|
|
18
18
|
Requires-Dist: tqdm<5.0,>=4.0
|
|
19
19
|
Requires-Dist: typing_extensions
|
|
20
20
|
Requires-Dist: jsonschema~=4.17.3
|
|
@@ -82,7 +82,7 @@ mapillary_tools supports JPG/JEPG images (.jpg, .jpeg), with the following EXIF
|
|
|
82
82
|
mapillary_tools supports videos (.mp4, .360) that contain any of the following telemetry structures:
|
|
83
83
|
|
|
84
84
|
- [GPMF](https://github.com/gopro/gpmf-parser): mostly GoPro videos
|
|
85
|
-
- [GoPro HERO series](https://gopro.com/en/us/shop/cameras/hero11-black/CHDHX-111-master.html) (from 5 to
|
|
85
|
+
- [GoPro HERO series](https://gopro.com/en/us/shop/cameras/hero11-black/CHDHX-111-master.html) (from 5 to 13)
|
|
86
86
|
- [GoPro MAX](https://gopro.com/en/us/shop/cameras/max/CHDHZ-202-master.html)
|
|
87
87
|
- [CAMM](https://developers.google.com/streetview/publish/camm-spec): an open-standard telemetry spec supported by a number of cameras
|
|
88
88
|
- [Insta360 Pro2](https://www.insta360.com/product/insta360-pro2/)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "0.11.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/process_and_upload.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/commands/upload_blackvue.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/construct_mp4_parser.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_from_generic.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_exif.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_gpx.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_images_from_video.py
RENAMED
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/geotag_videos_from_video.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/mp4_sample_parser.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/simple_mp4_builder.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/geotag/simple_mp4_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/process_geotag_properties.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/process_import_meta_properties.py
RENAMED
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools/process_sequence_properties.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mapillary_tools-0.11.2 → mapillary_tools-0.12.1}/mapillary_tools.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|