mapillary-tools 0.11.2__tar.gz → 0.12.0__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.
Files changed (86) hide show
  1. {mapillary_tools-0.11.2/mapillary_tools.egg-info → mapillary_tools-0.12.0}/PKG-INFO +2 -2
  2. mapillary_tools-0.12.0/mapillary_tools/__init__.py +1 -0
  3. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/exif_write.py +8 -0
  4. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/ffmpeg.py +13 -1
  5. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/gpmf_parser.py +128 -75
  6. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0/mapillary_tools.egg-info}/PKG-INFO +2 -2
  7. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools.egg-info/requires.txt +1 -1
  8. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/requirements.txt +1 -1
  9. mapillary_tools-0.11.2/mapillary_tools/__init__.py +0 -1
  10. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/LICENSE +0 -0
  11. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/MANIFEST.in +0 -0
  12. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/README.md +0 -0
  13. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/api_v4.py +0 -0
  14. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/authenticate.py +0 -0
  15. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/__init__.py +0 -0
  16. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/__main__.py +0 -0
  17. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/authenticate.py +0 -0
  18. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/process.py +0 -0
  19. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/process_and_upload.py +0 -0
  20. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/sample_video.py +0 -0
  21. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/upload.py +0 -0
  22. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/upload_blackvue.py +0 -0
  23. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/upload_camm.py +0 -0
  24. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/upload_zip.py +0 -0
  25. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/video_process.py +0 -0
  26. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/video_process_and_upload.py +0 -0
  27. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/commands/zip.py +0 -0
  28. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/config.py +0 -0
  29. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/constants.py +0 -0
  30. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/exceptions.py +0 -0
  31. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/exif_read.py +0 -0
  32. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/exiftool_read.py +0 -0
  33. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/exiftool_read_video.py +0 -0
  34. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geo.py +0 -0
  35. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/__init__.py +0 -0
  36. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/blackvue_parser.py +0 -0
  37. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/camm_builder.py +0 -0
  38. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/camm_parser.py +0 -0
  39. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/construct_mp4_parser.py +0 -0
  40. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_from_generic.py +0 -0
  41. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_images_from_exif.py +0 -0
  42. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_images_from_exiftool.py +0 -0
  43. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_images_from_exiftool_both_image_and_video.py +0 -0
  44. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_images_from_gpx.py +0 -0
  45. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_images_from_gpx_file.py +0 -0
  46. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_images_from_nmea_file.py +0 -0
  47. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_images_from_video.py +0 -0
  48. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_videos_from_exiftool_video.py +0 -0
  49. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/geotag_videos_from_video.py +0 -0
  50. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/gpmf_gps_filter.py +0 -0
  51. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/gps_filter.py +0 -0
  52. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/io_utils.py +0 -0
  53. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/mp4_sample_parser.py +0 -0
  54. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/simple_mp4_builder.py +0 -0
  55. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/simple_mp4_parser.py +0 -0
  56. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/geotag/utils.py +0 -0
  57. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/history.py +0 -0
  58. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/ipc.py +0 -0
  59. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/process_geotag_properties.py +0 -0
  60. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/process_import_meta_properties.py +0 -0
  61. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/process_sequence_properties.py +0 -0
  62. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/sample_video.py +0 -0
  63. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/types.py +0 -0
  64. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/upload.py +0 -0
  65. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/upload_api_v4.py +0 -0
  66. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/uploader.py +0 -0
  67. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/utils.py +0 -0
  68. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/cli_options.py +0 -0
  69. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extract_video_data.py +0 -0
  70. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/base_parser.py +0 -0
  71. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/blackvue_parser.py +0 -0
  72. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/camm_parser.py +0 -0
  73. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/exiftool_runtime_parser.py +0 -0
  74. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/exiftool_xml_parser.py +0 -0
  75. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/generic_video_parser.py +0 -0
  76. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/gopro_parser.py +0 -0
  77. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/gpx_parser.py +0 -0
  78. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/extractors/nmea_parser.py +0 -0
  79. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools/video_data_extraction/video_data_parser_factory.py +0 -0
  80. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools.egg-info/SOURCES.txt +0 -0
  81. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools.egg-info/dependency_links.txt +0 -0
  82. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools.egg-info/entry_points.txt +0 -0
  83. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/mapillary_tools.egg-info/top_level.txt +0 -0
  84. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/schema/image_description_schema.json +0 -0
  85. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/setup.cfg +0 -0
  86. {mapillary_tools-0.11.2 → mapillary_tools-0.12.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mapillary_tools
3
- Version: 0.11.2
3
+ Version: 0.12.0
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
@@ -0,0 +1 @@
1
+ VERSION = "0.12.0"
@@ -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 = "+".join(f"eq(n\\,{idx})" for idx in sorted(frame_indices))
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 gps_from_stream(
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(gps_from_stream(klv["data"]))
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mapillary_tools
3
- Version: 0.11.2
3
+ Version: 0.12.0
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
@@ -4,7 +4,7 @@ exifread==2.3.2
4
4
  piexif==1.1.3
5
5
  gpxpy<1.6.0,>=1.5.0
6
6
  pynmea2<2.0.0,>=1.12.0
7
- requests<3.0.0,>=2.20.0
7
+ requests[socks]<3.0.0,>=2.20.0
8
8
  tqdm<5.0,>=4.0
9
9
  typing_extensions
10
10
  jsonschema~=4.17.3
@@ -4,7 +4,7 @@ exifread==2.3.2
4
4
  piexif==1.1.3
5
5
  gpxpy>=1.5.0,<1.6.0
6
6
  pynmea2>=1.12.0,<2.0.0
7
- requests>=2.20.0,<3.0.0
7
+ requests[socks]>=2.20.0,<3.0.0
8
8
  tqdm>=4.0,<5.0
9
9
  typing_extensions
10
10
  jsonschema~=4.17.3
@@ -1 +0,0 @@
1
- VERSION = "0.11.2"