mapillary-tools 0.12.1__py3-none-any.whl → 0.13.1__py3-none-any.whl

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 (59) hide show
  1. mapillary_tools/__init__.py +1 -1
  2. mapillary_tools/api_v4.py +94 -4
  3. mapillary_tools/{geotag → camm}/camm_builder.py +73 -61
  4. mapillary_tools/camm/camm_parser.py +561 -0
  5. mapillary_tools/commands/__init__.py +0 -1
  6. mapillary_tools/commands/__main__.py +0 -6
  7. mapillary_tools/commands/process.py +0 -50
  8. mapillary_tools/commands/upload.py +1 -26
  9. mapillary_tools/constants.py +2 -2
  10. mapillary_tools/exiftool_read_video.py +13 -11
  11. mapillary_tools/ffmpeg.py +2 -2
  12. mapillary_tools/geo.py +0 -54
  13. mapillary_tools/geotag/blackvue_parser.py +4 -4
  14. mapillary_tools/geotag/geotag_images_from_exif.py +2 -1
  15. mapillary_tools/geotag/geotag_images_from_exiftool_both_image_and_video.py +0 -1
  16. mapillary_tools/geotag/geotag_images_from_gpx_file.py +7 -1
  17. mapillary_tools/geotag/geotag_videos_from_exiftool_video.py +5 -3
  18. mapillary_tools/geotag/geotag_videos_from_video.py +13 -14
  19. mapillary_tools/geotag/gpmf_gps_filter.py +9 -10
  20. mapillary_tools/geotag/gpmf_parser.py +346 -83
  21. mapillary_tools/mp4/__init__.py +0 -0
  22. mapillary_tools/{geotag → mp4}/construct_mp4_parser.py +32 -16
  23. mapillary_tools/mp4/mp4_sample_parser.py +322 -0
  24. mapillary_tools/{geotag → mp4}/simple_mp4_builder.py +64 -38
  25. mapillary_tools/process_geotag_properties.py +25 -19
  26. mapillary_tools/process_sequence_properties.py +6 -6
  27. mapillary_tools/sample_video.py +17 -16
  28. mapillary_tools/telemetry.py +71 -0
  29. mapillary_tools/types.py +18 -0
  30. mapillary_tools/upload.py +74 -233
  31. mapillary_tools/upload_api_v4.py +8 -9
  32. mapillary_tools/utils.py +9 -16
  33. mapillary_tools/video_data_extraction/cli_options.py +0 -1
  34. mapillary_tools/video_data_extraction/extract_video_data.py +13 -31
  35. mapillary_tools/video_data_extraction/extractors/base_parser.py +13 -11
  36. mapillary_tools/video_data_extraction/extractors/blackvue_parser.py +5 -4
  37. mapillary_tools/video_data_extraction/extractors/camm_parser.py +13 -16
  38. mapillary_tools/video_data_extraction/extractors/exiftool_runtime_parser.py +4 -9
  39. mapillary_tools/video_data_extraction/extractors/exiftool_xml_parser.py +9 -11
  40. mapillary_tools/video_data_extraction/extractors/generic_video_parser.py +6 -11
  41. mapillary_tools/video_data_extraction/extractors/gopro_parser.py +11 -4
  42. mapillary_tools/video_data_extraction/extractors/gpx_parser.py +90 -11
  43. mapillary_tools/video_data_extraction/extractors/nmea_parser.py +3 -3
  44. mapillary_tools/video_data_extraction/video_data_parser_factory.py +13 -20
  45. {mapillary_tools-0.12.1.dist-info → mapillary_tools-0.13.1.dist-info}/METADATA +10 -3
  46. mapillary_tools-0.13.1.dist-info/RECORD +75 -0
  47. {mapillary_tools-0.12.1.dist-info → mapillary_tools-0.13.1.dist-info}/WHEEL +1 -1
  48. mapillary_tools/commands/upload_blackvue.py +0 -33
  49. mapillary_tools/commands/upload_camm.py +0 -33
  50. mapillary_tools/commands/upload_zip.py +0 -33
  51. mapillary_tools/geotag/camm_parser.py +0 -306
  52. mapillary_tools/geotag/mp4_sample_parser.py +0 -426
  53. mapillary_tools/process_import_meta_properties.py +0 -76
  54. mapillary_tools-0.12.1.dist-info/RECORD +0 -77
  55. /mapillary_tools/{geotag → mp4}/io_utils.py +0 -0
  56. /mapillary_tools/{geotag → mp4}/simple_mp4_parser.py +0 -0
  57. {mapillary_tools-0.12.1.dist-info → mapillary_tools-0.13.1.dist-info}/LICENSE +0 -0
  58. {mapillary_tools-0.12.1.dist-info → mapillary_tools-0.13.1.dist-info}/entry_points.txt +0 -0
  59. {mapillary_tools-0.12.1.dist-info → mapillary_tools-0.13.1.dist-info}/top_level.txt +0 -0
@@ -1,426 +0,0 @@
1
- import datetime
2
- import io
3
- import typing as T
4
- from pathlib import Path
5
-
6
- from . import construct_mp4_parser as cparser, simple_mp4_parser as parser
7
-
8
-
9
- class RawSample(T.NamedTuple):
10
- # 1-based index
11
- description_idx: int
12
- # sample offset
13
- offset: int
14
- # sample size
15
- size: int
16
- # sample_delta read from stts entries,
17
- # i.e. STTS(n) in the forumula DT(n+1) = DT(n) + STTS(n)
18
- timedelta: int
19
- # sample composition offset,
20
- # i.e. CTTS(n) in the forumula CT(n) = DT(n) + CTTS(n).
21
- composition_offset: int
22
- # if it is a sync sample
23
- is_sync: bool
24
-
25
-
26
- # TODO: can not inherit RawSample?
27
- class Sample(T.NamedTuple):
28
- # copied from RawSample
29
-
30
- # 1-based index
31
- description_idx: int
32
- # sample offset
33
- offset: int
34
- # sample size
35
- size: int
36
- # sample delta in seconds read from stts entries,
37
- # i.e. (STTS(n) / timescale) in the forumula DT(n+1) = DT(n) + STTS(n)
38
- timedelta: float
39
- # sample composition offset in seconds,
40
- # i.e. (CTTS(n) / timescale) in the forumula CT(n) = DT(n) + CTTS(n).
41
- composition_offset: float
42
- # if it is a sync sample
43
- is_sync: bool
44
-
45
- # extended fields below
46
-
47
- # accumulated sample_delta in seconds,
48
- # i.e. (DT(n) / timescale) in the forumula DT(n+1) = DT(n) + STTS(n)
49
- time_offset: T.Union[int, float]
50
- # accumulated composition offset in seconds,
51
- # i.e. (CT(n) / timescale) in the forumula CT(n) = DT(n) + CTTS(n).
52
- composition_time_offset: T.Union[int, float]
53
- # reference to the sample description
54
- description: T.Dict
55
-
56
-
57
- def _extract_raw_samples(
58
- sizes: T.Sequence[int],
59
- chunk_entries: T.Sequence[T.Dict],
60
- chunk_offsets: T.Sequence[int],
61
- timedeltas: T.Sequence[int],
62
- composition_offsets: T.Optional[T.Sequence[int]],
63
- syncs: T.Optional[T.Set[int]],
64
- ) -> T.Generator[RawSample, None, None]:
65
- if not sizes:
66
- return
67
-
68
- if not chunk_entries:
69
- return
70
-
71
- assert len(sizes) <= len(
72
- timedeltas
73
- ), f"got less ({len(timedeltas)}) sample time deltas (stts) than expected ({len(sizes)})"
74
-
75
- sample_idx = 0
76
- chunk_idx = 0
77
-
78
- # iterate compressed chunks
79
- for entry_idx, entry in enumerate(chunk_entries):
80
- if entry_idx + 1 < len(chunk_entries):
81
- nbr_chunks = (
82
- chunk_entries[entry_idx + 1]["first_chunk"] - entry["first_chunk"]
83
- )
84
- else:
85
- nbr_chunks = 1
86
-
87
- # iterate chunks
88
- for _ in range(nbr_chunks):
89
- sample_offset = chunk_offsets[chunk_idx]
90
- # iterate samples in this chunk
91
- for _ in range(entry["samples_per_chunk"]):
92
- is_sync = syncs is None or (sample_idx + 1) in syncs
93
- composition_offset = (
94
- composition_offsets[sample_idx]
95
- if composition_offsets is not None
96
- else 0
97
- )
98
- yield RawSample(
99
- description_idx=entry["sample_description_index"],
100
- offset=sample_offset,
101
- size=sizes[sample_idx],
102
- timedelta=timedeltas[sample_idx],
103
- composition_offset=composition_offset,
104
- is_sync=is_sync,
105
- )
106
- sample_offset += sizes[sample_idx]
107
- sample_idx += 1
108
- chunk_idx += 1
109
-
110
- # below handles the single-entry case:
111
- # If all the chunks have the same number of samples per chunk
112
- # and use the same sample description, this table has one entry.
113
-
114
- # iterate chunks
115
- while sample_idx < len(sizes):
116
- sample_offset = chunk_offsets[chunk_idx]
117
- # iterate samples in this chunk
118
- for _ in range(chunk_entries[-1]["samples_per_chunk"]):
119
- is_sync = syncs is None or (sample_idx + 1) in syncs
120
- composition_offset = (
121
- composition_offsets[sample_idx]
122
- if composition_offsets is not None
123
- else 0
124
- )
125
- yield RawSample(
126
- description_idx=chunk_entries[-1]["sample_description_index"],
127
- offset=sample_offset,
128
- size=sizes[sample_idx],
129
- timedelta=timedeltas[sample_idx],
130
- composition_offset=composition_offset,
131
- is_sync=is_sync,
132
- )
133
- sample_offset += sizes[sample_idx]
134
- sample_idx += 1
135
- chunk_idx += 1
136
-
137
-
138
- def _extract_samples(
139
- raw_samples: T.Iterator[RawSample],
140
- descriptions: T.List,
141
- ) -> T.Generator[Sample, None, None]:
142
- acc_delta = 0
143
- for raw_sample in raw_samples:
144
- yield Sample(
145
- description_idx=raw_sample.description_idx,
146
- offset=raw_sample.offset,
147
- size=raw_sample.size,
148
- timedelta=raw_sample.timedelta,
149
- composition_offset=raw_sample.composition_offset,
150
- is_sync=raw_sample.is_sync,
151
- description=descriptions[raw_sample.description_idx - 1],
152
- time_offset=acc_delta,
153
- # CT(n) = DT(n) + CTTS(n)
154
- composition_time_offset=(acc_delta + raw_sample.composition_offset),
155
- )
156
- acc_delta += raw_sample.timedelta
157
-
158
-
159
- def _apply_timescale(sample: Sample, media_timescale: int) -> Sample:
160
- return Sample(
161
- description_idx=sample.description_idx,
162
- offset=sample.offset,
163
- size=sample.size,
164
- timedelta=sample.timedelta / media_timescale,
165
- composition_offset=sample.composition_offset / media_timescale,
166
- is_sync=sample.is_sync,
167
- description=sample.description,
168
- time_offset=sample.time_offset / media_timescale,
169
- composition_time_offset=sample.composition_time_offset / media_timescale,
170
- )
171
-
172
-
173
- def parse_raw_samples_from_stbl(
174
- stbl: T.BinaryIO,
175
- maxsize: int = -1,
176
- ) -> T.Tuple[T.List[T.Dict], T.Generator[RawSample, None, None]]:
177
- """
178
- DEPRECATED: use parse_raw_samples_from_stbl_bytes instead
179
- """
180
-
181
- descriptions = []
182
- sizes = []
183
- chunk_offsets = []
184
- chunk_entries = []
185
- timedeltas: T.List[int] = []
186
- composition_offsets: T.Optional[T.List[int]] = None
187
- syncs: T.Optional[T.Set[int]] = None
188
-
189
- for h, s in parser.parse_boxes(stbl, maxsize=maxsize, extend_eof=False):
190
- if h.type == b"stsd":
191
- box = cparser.SampleDescriptionBox.parse(s.read(h.maxsize))
192
- descriptions = list(box.entries)
193
- elif h.type == b"stsz":
194
- box = cparser.SampleSizeBox.parse(s.read(h.maxsize))
195
- if box.sample_size == 0:
196
- sizes = list(box.entries)
197
- else:
198
- sizes = [box.sample_size for _ in range(box.sample_count)]
199
- elif h.type == b"stco":
200
- box = cparser.ChunkOffsetBox.parse(s.read(h.maxsize))
201
- chunk_offsets = list(box.entries)
202
- elif h.type == b"co64":
203
- box = cparser.ChunkLargeOffsetBox.parse(s.read(h.maxsize))
204
- chunk_offsets = list(box.entries)
205
- elif h.type == b"stsc":
206
- box = cparser.SampleToChunkBox.parse(s.read(h.maxsize))
207
- chunk_entries = list(box.entries)
208
- elif h.type == b"stts":
209
- timedeltas = []
210
- box = cparser.TimeToSampleBox.parse(s.read(h.maxsize))
211
- for entry in box.entries:
212
- for _ in range(entry.sample_count):
213
- timedeltas.append(entry.sample_delta)
214
- elif h.type == b"ctts":
215
- composition_offsets = []
216
- box = cparser.CompositionTimeToSampleBox.parse(s.read(h.maxsize))
217
- for entry in box.entries:
218
- for _ in range(entry.sample_count):
219
- composition_offsets.append(entry.sample_offset)
220
- elif h.type == b"stss":
221
- box = cparser.SyncSampleBox.parse(s.read(h.maxsize))
222
- syncs = set(box.entries)
223
-
224
- # some stbl have less timedeltas than the sample count i.e. len(sizes),
225
- # in this case append 0's to timedeltas
226
- while len(timedeltas) < len(sizes):
227
- timedeltas.append(0)
228
- if composition_offsets is not None:
229
- while len(composition_offsets) < len(sizes):
230
- composition_offsets.append(0)
231
-
232
- raw_samples = _extract_raw_samples(
233
- sizes, chunk_entries, chunk_offsets, timedeltas, composition_offsets, syncs
234
- )
235
- return descriptions, raw_samples
236
-
237
-
238
- STBLBoxlistConstruct = cparser.Box64ConstructBuilder(
239
- T.cast(cparser.SwitchMapType, cparser.CMAP[b"stbl"])
240
- ).BoxList
241
-
242
-
243
- def parse_raw_samples_from_stbl_bytes(
244
- stbl: bytes,
245
- ) -> T.Tuple[T.List[T.Dict], T.Generator[RawSample, None, None]]:
246
- descriptions = []
247
- sizes = []
248
- chunk_offsets = []
249
- chunk_entries = []
250
- timedeltas: T.List[int] = []
251
- composition_offsets: T.Optional[T.List[int]] = None
252
- syncs: T.Optional[T.Set[int]] = None
253
-
254
- stbl_boxes = T.cast(T.Sequence[cparser.BoxDict], STBLBoxlistConstruct.parse(stbl))
255
-
256
- for box in stbl_boxes:
257
- data: T.Dict = T.cast(T.Dict, box["data"])
258
-
259
- if box["type"] == b"stsd":
260
- descriptions = list(data["entries"])
261
- elif box["type"] == b"stsz":
262
- if data["sample_size"] == 0:
263
- sizes = list(data["entries"])
264
- else:
265
- sizes = [data["sample_size"] for _ in range(data["sample_count"])]
266
- elif box["type"] == b"stco":
267
- chunk_offsets = list(data["entries"])
268
- elif box["type"] == b"co64":
269
- chunk_offsets = list(data["entries"])
270
- elif box["type"] == b"stsc":
271
- chunk_entries = list(data["entries"])
272
- elif box["type"] == b"stts":
273
- timedeltas = []
274
- for entry in data["entries"]:
275
- for _ in range(entry["sample_count"]):
276
- timedeltas.append(entry["sample_delta"])
277
- elif box["type"] == b"ctts":
278
- composition_offsets = []
279
- for entry in data["entries"]:
280
- for _ in range(entry["sample_count"]):
281
- composition_offsets.append(entry["sample_offset"])
282
- elif box["type"] == b"stss":
283
- syncs = set(data["entries"])
284
-
285
- # some stbl have less timedeltas than the sample count i.e. len(sizes),
286
- # in this case append 0's to timedeltas
287
- while len(timedeltas) < len(sizes):
288
- timedeltas.append(0)
289
- if composition_offsets is not None:
290
- while len(composition_offsets) < len(sizes):
291
- composition_offsets.append(0)
292
-
293
- raw_samples = _extract_raw_samples(
294
- sizes, chunk_entries, chunk_offsets, timedeltas, composition_offsets, syncs
295
- )
296
- return descriptions, raw_samples
297
-
298
-
299
- def parse_descriptions_from_trak(trak: T.BinaryIO, maxsize: int = -1) -> T.List[T.Dict]:
300
- data = parser.parse_box_data_first(
301
- trak, [b"mdia", b"minf", b"stbl", b"stsd"], maxsize=maxsize
302
- )
303
- if data is None:
304
- return []
305
- box = cparser.SampleDescriptionBox.parse(data)
306
- return list(box.entries)
307
-
308
-
309
- def parse_samples_from_trak(
310
- trak: T.BinaryIO,
311
- maxsize: int = -1,
312
- ) -> T.Generator[Sample, None, None]:
313
- trak_start_offset = trak.tell()
314
-
315
- trak.seek(trak_start_offset, io.SEEK_SET)
316
- mdhd_box = parser.parse_box_data_firstx(trak, [b"mdia", b"mdhd"], maxsize=maxsize)
317
- mdhd = T.cast(T.Dict, cparser.MediaHeaderBox.parse(mdhd_box))
318
-
319
- trak.seek(trak_start_offset, io.SEEK_SET)
320
- h, s = parser.parse_box_path_firstx(
321
- trak, [b"mdia", b"minf", b"stbl"], maxsize=maxsize
322
- )
323
- descriptions, raw_samples = parse_raw_samples_from_stbl(s, maxsize=h.maxsize)
324
-
325
- yield from (
326
- _apply_timescale(s, mdhd["timescale"])
327
- for s in _extract_samples(raw_samples, descriptions)
328
- )
329
-
330
-
331
- STSDBoxListConstruct = cparser.Box64ConstructBuilder(
332
- # pyre-ignore[6]: pyre does not support recursive type SwitchMapType
333
- {b"stsd": cparser.CMAP[b"stsd"]}
334
- ).BoxList
335
-
336
-
337
- class TrackBoxParser:
338
- trak_boxes: T.Sequence[cparser.BoxDict]
339
- stbl_data: bytes
340
-
341
- def __init__(self, trak_boxes: T.Sequence[cparser.BoxDict]):
342
- self.trak_boxes = trak_boxes
343
- stbl = cparser.find_box_at_pathx(self.trak_boxes, [b"mdia", b"minf", b"stbl"])
344
- self.stbl_data = T.cast(bytes, stbl["data"])
345
-
346
- def tkhd(self) -> T.Dict:
347
- return T.cast(
348
- T.Dict, cparser.find_box_at_pathx(self.trak_boxes, [b"tkhd"])["data"]
349
- )
350
-
351
- def is_video_track(self) -> bool:
352
- hdlr = cparser.find_box_at_pathx(self.trak_boxes, [b"mdia", b"hdlr"])
353
- return T.cast(T.Dict[str, T.Any], hdlr["data"])["handler_type"] == b"vide"
354
-
355
- def parse_sample_description(self) -> T.Dict:
356
- boxes = STSDBoxListConstruct.parse(self.stbl_data)
357
- stsd = cparser.find_box_at_pathx(
358
- T.cast(T.Sequence[cparser.BoxDict], boxes), [b"stsd"]
359
- )
360
- return T.cast(T.Dict, stsd["data"])
361
-
362
- def parse_raw_samples(self) -> T.Generator[RawSample, None, None]:
363
- _, raw_samples = parse_raw_samples_from_stbl_bytes(self.stbl_data)
364
- yield from raw_samples
365
-
366
- def parse_samples(self) -> T.Generator[Sample, None, None]:
367
- descriptions, raw_samples = parse_raw_samples_from_stbl_bytes(self.stbl_data)
368
- mdhd = T.cast(
369
- T.Dict,
370
- cparser.find_box_at_pathx(self.trak_boxes, [b"mdia", b"mdhd"])["data"],
371
- )
372
- yield from (
373
- _apply_timescale(s, mdhd["timescale"])
374
- for s in _extract_samples(raw_samples, descriptions)
375
- )
376
-
377
-
378
- class MovieBoxParser:
379
- moov_boxes: T.Sequence[cparser.BoxDict]
380
-
381
- def __init__(self, moov: bytes):
382
- self.moov_boxes = T.cast(
383
- T.Sequence[cparser.BoxDict],
384
- cparser.MOOVWithoutSTBLBuilderConstruct.BoxList.parse(moov),
385
- )
386
-
387
- @classmethod
388
- def parse_file(cls, video_path: Path) -> "MovieBoxParser":
389
- with video_path.open("rb") as fp:
390
- moov = parser.parse_box_data_firstx(fp, [b"moov"])
391
- return MovieBoxParser(moov)
392
-
393
- def mvhd(self):
394
- mvhd = cparser.find_box_at_pathx(self.moov_boxes, [b"mvhd"])
395
- return mvhd["data"]
396
-
397
- def parse_tracks(self) -> T.Generator[TrackBoxParser, None, None]:
398
- for box in self.moov_boxes:
399
- if box["type"] == b"trak":
400
- yield TrackBoxParser(T.cast(T.Sequence[cparser.BoxDict], box["data"]))
401
-
402
- def parse_track_at(self, stream_idx: int) -> TrackBoxParser:
403
- """
404
- stream_idx should be the stream_index specifier. See http://ffmpeg.org/ffmpeg.html#Stream-specifiers-1
405
- > Stream numbering is based on the order of the streams as detected by libavformat
406
- """
407
- trak_boxes = [box for box in self.moov_boxes if box["type"] == b"trak"]
408
- if not (0 <= stream_idx < len(trak_boxes)):
409
- raise IndexError(
410
- "unable to read stream at %d from the track list (length %d)",
411
- stream_idx,
412
- len(trak_boxes),
413
- )
414
- return TrackBoxParser(
415
- T.cast(T.Sequence[cparser.BoxDict], trak_boxes[stream_idx]["data"])
416
- )
417
-
418
-
419
- _DT_1904 = datetime.datetime.utcfromtimestamp(0).replace(year=1904)
420
-
421
-
422
- def to_datetime(seconds_since_1904: int) -> datetime.datetime:
423
- """
424
- Convert seconds since midnight, Jan. 1, 1904, in UTC time
425
- """
426
- return _DT_1904 + datetime.timedelta(seconds=seconds_since_1904)
@@ -1,76 +0,0 @@
1
- import logging
2
- import typing as T
3
-
4
- from . import types
5
-
6
-
7
- LOG = logging.getLogger(__name__)
8
-
9
-
10
- def format_orientation(orientation: int) -> int:
11
- """
12
- Convert orientation from clockwise degrees to exif tag
13
-
14
- # see http://sylvana.net/jpegcrop/exif_orientation.html
15
- """
16
- mapping: T.Mapping[int, int] = {
17
- 0: 1,
18
- 90: 8,
19
- 180: 3,
20
- 270: 6,
21
- }
22
- if orientation not in mapping:
23
- raise ValueError("Orientation value has to be 0, 90, 180, or 270")
24
-
25
- return mapping[orientation]
26
-
27
-
28
- def process_import_meta_properties(
29
- metadatas: T.List[types.MetadataOrError],
30
- orientation=None,
31
- device_make=None,
32
- device_model=None,
33
- GPS_accuracy=None,
34
- add_file_name=False,
35
- add_import_date=False,
36
- custom_meta_data=None,
37
- camera_uuid=None,
38
- ) -> T.List[types.MetadataOrError]:
39
- if add_file_name:
40
- LOG.warning("The option --add_file_name is not needed any more since v0.10.0")
41
-
42
- if add_import_date:
43
- LOG.warning("The option --add_import_date is not needed any more since v0.10.0")
44
-
45
- if custom_meta_data:
46
- LOG.warning(
47
- "The option --custom_meta_data is not needed any more since v0.10.0"
48
- )
49
-
50
- for metadata in metadatas:
51
- if isinstance(metadata, types.ErrorMetadata):
52
- continue
53
-
54
- if device_make is not None:
55
- if isinstance(metadata, types.VideoMetadata):
56
- metadata.make = device_make
57
- else:
58
- metadata.MAPDeviceMake = device_make
59
-
60
- if device_model is not None:
61
- if isinstance(metadata, types.VideoMetadata):
62
- metadata.model = device_model
63
- elif isinstance(metadata, types.ImageMetadata):
64
- metadata.MAPDeviceModel = device_model
65
-
66
- if isinstance(metadata, types.ImageMetadata):
67
- if orientation is not None:
68
- metadata.MAPOrientation = format_orientation(orientation)
69
-
70
- if GPS_accuracy is not None:
71
- metadata.MAPGPSAccuracyMeters = float(GPS_accuracy)
72
-
73
- if camera_uuid is not None:
74
- metadata.MAPCameraUUID = camera_uuid
75
-
76
- return metadatas
@@ -1,77 +0,0 @@
1
- mapillary_tools/__init__.py,sha256=Y_EQVeH08TULmSWJnga0Czi_46VOIkJR_BSsDzpxqNo,19
2
- mapillary_tools/api_v4.py,sha256=EX0x-mGjKJIM3KYHsrMo5ZcGVb1_1A2j01eP7gc17vo,1685
3
- mapillary_tools/authenticate.py,sha256=LCFcs6LqZmXaYkTUEKgGfmqytWdh5v_L3KXB48ojOZ4,3090
4
- mapillary_tools/config.py,sha256=jCjaK4jJaTY4AV4qf_b_tcxn5LA_uPsEWlGIdm2zw6g,2103
5
- mapillary_tools/constants.py,sha256=q5-4LG35aIrdUTaBh8v5WDGVR4o4fHYPCv0WFnKJLLg,2450
6
- mapillary_tools/exceptions.py,sha256=Mh1tgVEFTSMnYEzrl9x7b95fW9Z3SPVD_YMEl7r8I0I,2693
7
- mapillary_tools/exif_read.py,sha256=F60A0-T8XSBHvFKgVIrUz_ZWKQrTFWrtj3c6siB0IMg,28707
8
- mapillary_tools/exif_write.py,sha256=3PawLnBOY8Z86TYiA_F4LxRhe5Ui6CTNhxYm9yeJNX8,8786
9
- mapillary_tools/exiftool_read.py,sha256=Mg027me1IzblKb9IyGaLgU6goFqk_QiOt0Ppq-CeECg,16288
10
- mapillary_tools/exiftool_read_video.py,sha256=BA4Mo0rdC-mM9jIAtFQbNJ2v4TkDqDiZzKfh5DcnwDE,14430
11
- mapillary_tools/ffmpeg.py,sha256=M56MrJSbwf5SJs15KwHZC8moxjx6SrB6gM0h-JMPq1U,15788
12
- mapillary_tools/geo.py,sha256=yAopdbA20R9RpG6hfyrXo6qP09Xpb915f8-BtYAgoiA,11211
13
- mapillary_tools/history.py,sha256=l2z3YdYRyBGEOvcqcLExTV-0LUAX3iBq2OdBzLNMHLM,1766
14
- mapillary_tools/ipc.py,sha256=DwWQb9hNshx0bg0Fo5NjY0mXjs-FkbR6tIQmjMgMtmg,1089
15
- mapillary_tools/process_geotag_properties.py,sha256=39gpT96Rzfu9hH1uGKDsYrFR8MLU1PNX_ytdlsL7yvI,22813
16
- mapillary_tools/process_import_meta_properties.py,sha256=pEqUp1pLzSNUoSEkxRGk1RVTtkE7FMagPo-yEagS3bk,2166
17
- mapillary_tools/process_sequence_properties.py,sha256=PLCSYJDNwr3rpUfh8kLNtUrUozYbRByR1g3xh3GCVCY,11559
18
- mapillary_tools/sample_video.py,sha256=3zji4zHt4hT_iWP0sV1XpNikFLfC-OGpk_p1NpSMPec,14385
19
- mapillary_tools/types.py,sha256=wNdb516UR039voIMN8_MtNPEyLWgzCb8dGj-nR74Pds,21490
20
- mapillary_tools/upload.py,sha256=Lm7juEYnMmpDLarTU-QGoxMvet1sS3eM3PqTE956LnY,29727
21
- mapillary_tools/upload_api_v4.py,sha256=-JlrPg5lCAo959jAbL8lYl72gTgQ3o-MawFuAQJ8Uj0,8596
22
- mapillary_tools/uploader.py,sha256=VieDKi51wdXTIhN7x_mcuQeHESUyFlF5cgB-TAnF4g0,14093
23
- mapillary_tools/utils.py,sha256=eg0TdJNjOJSYMB0NCxzOzDAbQc67NFOT919ZJxvSNRs,6257
24
- mapillary_tools/commands/__init__.py,sha256=wz89o8syKkWwoOCp3WBgnFWc41TBQRzRi62TlOTmVNQ,188
25
- mapillary_tools/commands/__main__.py,sha256=m9MRLyQJfgiki3eRBaagWUwNBKEbEiYtAaf2K3JsQmM,4940
26
- mapillary_tools/commands/authenticate.py,sha256=4aVvAQal_mqtm2NEMBt5aKLahi0iRdO8b7WSBf6jokA,1136
27
- mapillary_tools/commands/process.py,sha256=PyfIcpsS7vnLElr02ol1sQ_9Ma6J6uLusIuiyrAiF-c,12808
28
- mapillary_tools/commands/process_and_upload.py,sha256=osJv1TVHYAG5E-EsA0nB1F3RkKXMadLR2t1EGK0Ifqw,654
29
- mapillary_tools/commands/sample_video.py,sha256=bTJmlDsajkC-QJ_ZO_scdD4R664zs-r_dh-x2PlOgyY,3281
30
- mapillary_tools/commands/upload.py,sha256=GyLJ0wa2OO6fxr-8MoEelZsb2sOv3B2B2OhYtwFjzQc,2663
31
- mapillary_tools/commands/upload_blackvue.py,sha256=9RbCbz0-BquOIcp5JycnVbIAPUIqctwAm50LcLZw3N8,923
32
- mapillary_tools/commands/upload_camm.py,sha256=2zlBkZYbR2Hi4P02cHtBIymrqkudn5RrhFWwsCG7lG8,907
33
- mapillary_tools/commands/upload_zip.py,sha256=p8EZZktXLm8IipAbxrmz7E0RcfcLcxeGhEtxZzq5rSw,897
34
- mapillary_tools/commands/video_process.py,sha256=-wQeeIwWXPmy81HQHam5A0huMLRHknkEFa_V1OwElU4,890
35
- mapillary_tools/commands/video_process_and_upload.py,sha256=llV0dHBS31qPZp-Fs1GCM0yYezEA_VF_tfYcp-Z8NkY,701
36
- mapillary_tools/commands/zip.py,sha256=DVQuMLpbstwiy5o4pU_fBvM6eORuFjLeySd80AhHKU0,991
37
- mapillary_tools/geotag/__init__.py,sha256=ohud7lLsqO1b9ddCF0SjrNOcUcRdQzNVR43RkcVVLAc,33
38
- mapillary_tools/geotag/blackvue_parser.py,sha256=1yrIs9Hp_-tNrClLQn2gxzCVWpkWTa6OlpLXgI4it70,2983
39
- mapillary_tools/geotag/camm_builder.py,sha256=AgY-LuuZy2w0Ni_GKI7Z_39Q19BfcghzfuHa5CSOK8o,8224
40
- mapillary_tools/geotag/camm_parser.py,sha256=zRQcPNgD_oibLp06aW_cwk4H3MvWqHDg-RiKVFiftTA,8830
41
- mapillary_tools/geotag/construct_mp4_parser.py,sha256=waaJl1wtQ2gbd6nIl9dj3V2nxiPYOn7bU8vopYeIWwE,16713
42
- mapillary_tools/geotag/geotag_from_generic.py,sha256=bCYfIbkv4qIlkKttAjSGl9t4i_QAtzIiCZoth1hMVI4,480
43
- mapillary_tools/geotag/geotag_images_from_exif.py,sha256=Wslwj3oNJdJjpSPV5JZ_aHEGF8O62LNQO7CBPczBOs0,4762
44
- mapillary_tools/geotag/geotag_images_from_exiftool.py,sha256=a-c4H8VIyPdJkfUIvJho0phR0QU0zN8-lSyiCz0wc4s,3981
45
- mapillary_tools/geotag/geotag_images_from_exiftool_both_image_and_video.py,sha256=GbNtPxE-FanzrPUI3FS-dadT5d0lyH_AcAAr4H6GL-o,3386
46
- mapillary_tools/geotag/geotag_images_from_gpx.py,sha256=S9Pw6FvP5kRSpHUnKUYKXmw0CHa9V92UmrS_MJfbjS4,9053
47
- mapillary_tools/geotag/geotag_images_from_gpx_file.py,sha256=zEbC0kVf_iw9ioIyJLL-gYN_QvAOEdAoEczCBkizl38,5122
48
- mapillary_tools/geotag/geotag_images_from_nmea_file.py,sha256=dDdHnJInQ_WN3ZRf-w44NSBElDLPs7XYBiimvE2iCNo,1651
49
- mapillary_tools/geotag/geotag_images_from_video.py,sha256=XsaWOFChGItl-j1UbKM4hNjUqN29pVNbMpGT_BvI-o8,3306
50
- mapillary_tools/geotag/geotag_videos_from_exiftool_video.py,sha256=5ezj-9uZszJiI9XZqW9b_XDYfX5RjlXnOyf7atCh47o,5143
51
- mapillary_tools/geotag/geotag_videos_from_video.py,sha256=HPVJqFeFDvvrFD0vfCimeaOyHHddcWlneAT0LjLUnZo,7098
52
- mapillary_tools/geotag/gpmf_gps_filter.py,sha256=7GHr05CLLF6lDGpMS3yAbZENh_vEfS0ezrfd_VFg3-c,2800
53
- mapillary_tools/geotag/gpmf_parser.py,sha256=GDV2yFhmsII4RdzbnPCQwd-Quk6NdMTJ0BcM0QH8ERU,15284
54
- mapillary_tools/geotag/gps_filter.py,sha256=4CPL8glxdzPWIbfGPPgyqMLyiZFt-djce5vhiFPuZB8,3766
55
- mapillary_tools/geotag/io_utils.py,sha256=wc3-F1TnxZjTwB7-oea5yRmRQ_0T3Zbz8oBkW9JL8d4,5454
56
- mapillary_tools/geotag/mp4_sample_parser.py,sha256=UxBqs0vFTA4qVth1ELkeBGElmW465_Vn2vKNApHmp7M,15141
57
- mapillary_tools/geotag/simple_mp4_builder.py,sha256=-0ZFe0rnFYNcRxxBLrrqytl5GPnKToUH8TPEYjZkjZs,11981
58
- mapillary_tools/geotag/simple_mp4_parser.py,sha256=eji6JZa497wK8CY8hQt21fjgtnd0nzuyBx7MPEKST74,6671
59
- mapillary_tools/geotag/utils.py,sha256=Orl35Df4ypxj4v6Lu1Mhk9d2XZxa8yNffz1s1C0JZsQ,651
60
- mapillary_tools/video_data_extraction/cli_options.py,sha256=g5kqzvkGJm6f5T4Vhum4JLL5qS6vE4iagQbEPtGJcug,563
61
- mapillary_tools/video_data_extraction/extract_video_data.py,sha256=2MJk4ekb3fhRLRThCrUsPOuTvHkPzyTTMTzlnfvuGD8,6603
62
- mapillary_tools/video_data_extraction/video_data_parser_factory.py,sha256=EDl4x_M0HvE4Pgwas679w70udLgeKuz6u-4Gv1BZQgE,1539
63
- mapillary_tools/video_data_extraction/extractors/base_parser.py,sha256=qNjS4LRDekD1E2Guqb2J5XstGVV9X2eN54CDlzXQGCw,1996
64
- mapillary_tools/video_data_extraction/extractors/blackvue_parser.py,sha256=zro4SUgqnVgEIrkjDf5yb6MJKOfl6ayPrr3FLoVBWO0,1143
65
- mapillary_tools/video_data_extraction/extractors/camm_parser.py,sha256=u7Yp7CYM0zdcRlpgkHQSB72x_uL2j-_AmwnGSREJPv0,1368
66
- mapillary_tools/video_data_extraction/extractors/exiftool_runtime_parser.py,sha256=mtdsoncnsspCtt5rMET2gxcEzvyOCyNv754RNhMEUNQ,2436
67
- mapillary_tools/video_data_extraction/extractors/exiftool_xml_parser.py,sha256=unLa5uZB1N5Vtl8bk19hayphRhXzHlSKgBYjVUv1hlQ,1848
68
- mapillary_tools/video_data_extraction/extractors/generic_video_parser.py,sha256=mw_byv66za_5Mb5TrWbD5UU2Ts6mAMZqLgKB9umWGsY,1955
69
- mapillary_tools/video_data_extraction/extractors/gopro_parser.py,sha256=xNXGuR7a-oDaE_WB2xK7sDpAGFwyWIsBUC8fSMKtfgM,1214
70
- mapillary_tools/video_data_extraction/extractors/gpx_parser.py,sha256=cqNGtlWFuuxBTf5BliCuJ14avxu-8Pz5LvXnTpTum60,815
71
- mapillary_tools/video_data_extraction/extractors/nmea_parser.py,sha256=QFMw_yf4uNP8z7tTybHMKHHMG6cS92bae-MJPHq6EJk,731
72
- mapillary_tools-0.12.1.dist-info/LICENSE,sha256=l2D8cKfFmmJq_wcVq_JElPJrlvWQOzNWx7gMLINucxc,1292
73
- mapillary_tools-0.12.1.dist-info/METADATA,sha256=nlA9PJrgEzB0LxKovlrER7YD-arXOyo7P6Zzr8PWt1Y,19638
74
- mapillary_tools-0.12.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
75
- mapillary_tools-0.12.1.dist-info/entry_points.txt,sha256=A3f3LP-BO_P-U8Y29QfpT4jx6Mjk3sXjTi2Yew4bvj8,75
76
- mapillary_tools-0.12.1.dist-info/top_level.txt,sha256=FbDkMgOrt1S70ho1WSBrOwzKOSkJFDwwqFOoY5-527s,16
77
- mapillary_tools-0.12.1.dist-info/RECORD,,
File without changes
File without changes