exiftool_vendored 10.65.0 → 11.41.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of exiftool_vendored might be problematic. Click here for more details.

Files changed (205) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +818 -19
  3. data/bin/MANIFEST +38 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +48 -44
  7. data/bin/arg_files/exif2xmp.args +4 -1
  8. data/bin/arg_files/gps2xmp.args +4 -1
  9. data/bin/arg_files/iptcCore.args +8 -0
  10. data/bin/arg_files/xmp2exif.args +4 -1
  11. data/bin/arg_files/xmp2gps.args +4 -1
  12. data/bin/config_files/dji.config +131 -0
  13. data/bin/config_files/example.config +6 -2
  14. data/bin/config_files/gps2utm.config +256 -256
  15. data/bin/config_files/nksc.config +146 -0
  16. data/bin/config_files/picasa_faces.config +382 -382
  17. data/bin/exiftool +688 -408
  18. data/bin/fmt_files/gpx.fmt +10 -6
  19. data/bin/fmt_files/gpx_wpt.fmt +10 -6
  20. data/bin/fmt_files/kml.fmt +8 -5
  21. data/bin/lib/File/RandomAccess.pm +48 -8
  22. data/bin/lib/File/RandomAccess.pod +21 -2
  23. data/bin/lib/Image/ExifTool.pm +645 -256
  24. data/bin/lib/Image/ExifTool.pod +219 -164
  25. data/bin/lib/Image/ExifTool/AES.pm +1 -1
  26. data/bin/lib/Image/ExifTool/AFCP.pm +3 -8
  27. data/bin/lib/Image/ExifTool/AIFF.pm +12 -4
  28. data/bin/lib/Image/ExifTool/APE.pm +1 -1
  29. data/bin/lib/Image/ExifTool/APP12.pm +1 -1
  30. data/bin/lib/Image/ExifTool/ASF.pm +19 -6
  31. data/bin/lib/Image/ExifTool/Apple.pm +13 -5
  32. data/bin/lib/Image/ExifTool/Audible.pm +1 -1
  33. data/bin/lib/Image/ExifTool/BMP.pm +1 -1
  34. data/bin/lib/Image/ExifTool/BPG.pm +17 -15
  35. data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
  36. data/bin/lib/Image/ExifTool/BigTIFF.pm +30 -15
  37. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +103 -52
  38. data/bin/lib/Image/ExifTool/Canon.pm +684 -112
  39. data/bin/lib/Image/ExifTool/CanonCustom.pm +119 -9
  40. data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
  41. data/bin/lib/Image/ExifTool/CanonVRD.pm +13 -26
  42. data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
  43. data/bin/lib/Image/ExifTool/Casio.pm +1 -1
  44. data/bin/lib/Image/ExifTool/Charset.pm +1 -1
  45. data/bin/lib/Image/ExifTool/DICOM.pm +12 -5
  46. data/bin/lib/Image/ExifTool/DJI.pm +51 -3
  47. data/bin/lib/Image/ExifTool/DNG.pm +15 -8
  48. data/bin/lib/Image/ExifTool/DPX.pm +1 -1
  49. data/bin/lib/Image/ExifTool/DV.pm +1 -1
  50. data/bin/lib/Image/ExifTool/DarwinCore.pm +63 -23
  51. data/bin/lib/Image/ExifTool/DjVu.pm +4 -2
  52. data/bin/lib/Image/ExifTool/EXE.pm +30 -6
  53. data/bin/lib/Image/ExifTool/Exif.pm +351 -109
  54. data/bin/lib/Image/ExifTool/FITS.pm +148 -0
  55. data/bin/lib/Image/ExifTool/FLAC.pm +2 -2
  56. data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
  57. data/bin/lib/Image/ExifTool/FLIR.pm +109 -13
  58. data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
  59. data/bin/lib/Image/ExifTool/Flash.pm +3 -3
  60. data/bin/lib/Image/ExifTool/FlashPix.pm +433 -9
  61. data/bin/lib/Image/ExifTool/Font.pm +2 -2
  62. data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
  63. data/bin/lib/Image/ExifTool/FujiFilm.pm +336 -16
  64. data/bin/lib/Image/ExifTool/GE.pm +1 -1
  65. data/bin/lib/Image/ExifTool/GIF.pm +5 -7
  66. data/bin/lib/Image/ExifTool/GIMP.pm +39 -3
  67. data/bin/lib/Image/ExifTool/GPS.pm +48 -22
  68. data/bin/lib/Image/ExifTool/GeoTiff.pm +23 -23
  69. data/bin/lib/Image/ExifTool/Geotag.pm +80 -45
  70. data/bin/lib/Image/ExifTool/GoPro.pm +709 -0
  71. data/bin/lib/Image/ExifTool/H264.pm +40 -18
  72. data/bin/lib/Image/ExifTool/HP.pm +1 -1
  73. data/bin/lib/Image/ExifTool/HTML.pm +19 -12
  74. data/bin/lib/Image/ExifTool/HtmlDump.pm +37 -26
  75. data/bin/lib/Image/ExifTool/ICC_Profile.pm +297 -23
  76. data/bin/lib/Image/ExifTool/ID3.pm +12 -7
  77. data/bin/lib/Image/ExifTool/IPTC.pm +48 -19
  78. data/bin/lib/Image/ExifTool/ISO.pm +1 -1
  79. data/bin/lib/Image/ExifTool/ITC.pm +1 -1
  80. data/bin/lib/Image/ExifTool/Import.pm +13 -9
  81. data/bin/lib/Image/ExifTool/InDesign.pm +3 -5
  82. data/bin/lib/Image/ExifTool/JPEG.pm +22 -11
  83. data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
  84. data/bin/lib/Image/ExifTool/JSON.pm +3 -3
  85. data/bin/lib/Image/ExifTool/JVC.pm +1 -1
  86. data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -2
  87. data/bin/lib/Image/ExifTool/Kodak.pm +1233 -58
  88. data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
  89. data/bin/lib/Image/ExifTool/LNK.pm +1 -1
  90. data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
  91. data/bin/lib/Image/ExifTool/Lang/de.pm +33 -24
  92. data/bin/lib/Image/ExifTool/Lang/en_ca.pm +64 -2
  93. data/bin/lib/Image/ExifTool/Lang/en_gb.pm +64 -2
  94. data/bin/lib/Image/ExifTool/Lang/es.pm +8 -4
  95. data/bin/lib/Image/ExifTool/Lang/fi.pm +46 -4
  96. data/bin/lib/Image/ExifTool/Lang/fr.pm +5 -3
  97. data/bin/lib/Image/ExifTool/Lang/it.pm +6 -3
  98. data/bin/lib/Image/ExifTool/Lang/ja.pm +15 -3
  99. data/bin/lib/Image/ExifTool/Lang/ko.pm +5 -2
  100. data/bin/lib/Image/ExifTool/Lang/nl.pm +6 -3
  101. data/bin/lib/Image/ExifTool/Lang/pl.pm +2 -2
  102. data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
  103. data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
  104. data/bin/lib/Image/ExifTool/Lang/tr.pm +4 -2
  105. data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
  106. data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
  107. data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
  108. data/bin/lib/Image/ExifTool/Lytro.pm +4 -8
  109. data/bin/lib/Image/ExifTool/M2TS.pm +10 -9
  110. data/bin/lib/Image/ExifTool/MIE.pm +12 -8
  111. data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
  112. data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
  113. data/bin/lib/Image/ExifTool/MNG.pm +1 -1
  114. data/bin/lib/Image/ExifTool/MOI.pm +1 -1
  115. data/bin/lib/Image/ExifTool/MPC.pm +1 -1
  116. data/bin/lib/Image/ExifTool/MPEG.pm +2 -3
  117. data/bin/lib/Image/ExifTool/MPF.pm +6 -6
  118. data/bin/lib/Image/ExifTool/MWG.pm +4 -4
  119. data/bin/lib/Image/ExifTool/MXF.pm +2 -2
  120. data/bin/lib/Image/ExifTool/MacOS.pm +184 -34
  121. data/bin/lib/Image/ExifTool/MakerNotes.pm +101 -18
  122. data/bin/lib/Image/ExifTool/Matroska.pm +1 -1
  123. data/bin/lib/Image/ExifTool/Microsoft.pm +5 -3
  124. data/bin/lib/Image/ExifTool/Minolta.pm +89 -62
  125. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
  126. data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
  127. data/bin/lib/Image/ExifTool/Nikon.pm +1511 -380
  128. data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
  129. data/bin/lib/Image/ExifTool/NikonCustom.pm +2758 -2935
  130. data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
  131. data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
  132. data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
  133. data/bin/lib/Image/ExifTool/Olympus.pm +47 -8
  134. data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
  135. data/bin/lib/Image/ExifTool/Opus.pm +1 -1
  136. data/bin/lib/Image/ExifTool/PCX.pm +138 -0
  137. data/bin/lib/Image/ExifTool/PDF.pm +58 -42
  138. data/bin/lib/Image/ExifTool/PGF.pm +1 -1
  139. data/bin/lib/Image/ExifTool/PICT.pm +1 -1
  140. data/bin/lib/Image/ExifTool/PLIST.pm +12 -5
  141. data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
  142. data/bin/lib/Image/ExifTool/PNG.pm +108 -10
  143. data/bin/lib/Image/ExifTool/PPM.pm +3 -3
  144. data/bin/lib/Image/ExifTool/PSP.pm +1 -1
  145. data/bin/lib/Image/ExifTool/Palm.pm +1 -1
  146. data/bin/lib/Image/ExifTool/Panasonic.pm +299 -31
  147. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +201 -19
  148. data/bin/lib/Image/ExifTool/Pentax.pm +164 -143
  149. data/bin/lib/Image/ExifTool/PhaseOne.pm +12 -5
  150. data/bin/lib/Image/ExifTool/PhotoCD.pm +9 -10
  151. data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
  152. data/bin/lib/Image/ExifTool/Photoshop.pm +230 -60
  153. data/bin/lib/Image/ExifTool/PostScript.pm +29 -4
  154. data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
  155. data/bin/lib/Image/ExifTool/Qualcomm.pm +2 -2
  156. data/bin/lib/Image/ExifTool/QuickTime.pm +1539 -279
  157. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +1857 -0
  158. data/bin/lib/Image/ExifTool/README +84 -46
  159. data/bin/lib/Image/ExifTool/RIFF.pm +116 -23
  160. data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
  161. data/bin/lib/Image/ExifTool/RTF.pm +6 -4
  162. data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
  163. data/bin/lib/Image/ExifTool/Rawzor.pm +3 -2
  164. data/bin/lib/Image/ExifTool/Real.pm +1 -1
  165. data/bin/lib/Image/ExifTool/Reconyx.pm +261 -7
  166. data/bin/lib/Image/ExifTool/Red.pm +325 -0
  167. data/bin/lib/Image/ExifTool/Ricoh.pm +3 -7
  168. data/bin/lib/Image/ExifTool/Samsung.pm +95 -25
  169. data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
  170. data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
  171. data/bin/lib/Image/ExifTool/Shift.pl +26 -12
  172. data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -2
  173. data/bin/lib/Image/ExifTool/Sigma.pm +36 -30
  174. data/bin/lib/Image/ExifTool/SigmaRaw.pm +3 -8
  175. data/bin/lib/Image/ExifTool/Sony.pm +531 -177
  176. data/bin/lib/Image/ExifTool/SonyIDC.pm +63 -3
  177. data/bin/lib/Image/ExifTool/Stim.pm +2 -2
  178. data/bin/lib/Image/ExifTool/TagInfoXML.pm +23 -23
  179. data/bin/lib/Image/ExifTool/TagLookup.pm +6352 -5062
  180. data/bin/lib/Image/ExifTool/TagNames.pod +3024 -565
  181. data/bin/lib/Image/ExifTool/Theora.pm +1 -1
  182. data/bin/lib/Image/ExifTool/Torrent.pm +2 -2
  183. data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
  184. data/bin/lib/Image/ExifTool/VCard.pm +47 -9
  185. data/bin/lib/Image/ExifTool/Validate.pm +391 -99
  186. data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
  187. data/bin/lib/Image/ExifTool/WTV.pm +319 -0
  188. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  189. data/bin/lib/Image/ExifTool/WriteExif.pl +91 -18
  190. data/bin/lib/Image/ExifTool/WriteIPTC.pl +6 -6
  191. data/bin/lib/Image/ExifTool/WritePDF.pl +13 -12
  192. data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
  193. data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
  194. data/bin/lib/Image/ExifTool/WritePostScript.pl +2 -2
  195. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +764 -121
  196. data/bin/lib/Image/ExifTool/WriteXMP.pl +176 -67
  197. data/bin/lib/Image/ExifTool/Writer.pl +490 -246
  198. data/bin/lib/Image/ExifTool/XMP.pm +216 -76
  199. data/bin/lib/Image/ExifTool/XMP2.pl +54 -10
  200. data/bin/lib/Image/ExifTool/XMPStruct.pl +14 -11
  201. data/bin/lib/Image/ExifTool/ZIP.pm +60 -15
  202. data/bin/lib/Image/ExifTool/iWork.pm +12 -5
  203. data/bin/perl-Image-ExifTool.spec +46 -44
  204. data/lib/exiftool_vendored/version.rb +1 -1
  205. metadata +14 -4
@@ -0,0 +1,709 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: GoPro.pm
3
+ #
4
+ # Description: Read information from GoPro videos
5
+ #
6
+ # Revisions: 2018/01/12 - P. Harvey Created
7
+ #
8
+ # References: 1) https://github.com/gopro/gpmf-parser
9
+ # 2) https://github.com/stilldavid/gopro-utils
10
+ #------------------------------------------------------------------------------
11
+
12
+ package Image::ExifTool::GoPro;
13
+
14
+ use strict;
15
+ use vars qw($VERSION);
16
+ use Image::ExifTool qw(:DataAccess :Utils);
17
+ use Image::ExifTool::QuickTime;
18
+
19
+ $VERSION = '1.02';
20
+
21
+ sub ProcessGoPro($$$);
22
+ sub ProcessString($$$);
23
+ sub ScaleValues($$);
24
+ sub AddUnits($$$);
25
+ sub ConvertSystemTime($$);
26
+
27
+ # GoPro data types that have ExifTool equivalents (ref 1)
28
+ my %goProFmt = ( # format codes
29
+ # 0x00 - container (subdirectory)
30
+ 0x62 => 'int8s', # 'b'
31
+ 0x42 => 'int8u', # 'B'
32
+ 0x63 => 'string', # 'c' (possibly null terminated)
33
+ 0x73 => 'int16s', # 's'
34
+ 0x53 => 'int16u', # 'S'
35
+ 0x6c => 'int32s', # 'l'
36
+ 0x4c => 'int32u', # 'L'
37
+ 0x66 => 'float', # 'f'
38
+ 0x64 => 'double', # 'd'
39
+ 0x46 => 'undef', # 'F' (4-char ID)
40
+ 0x47 => 'undef', # 'G' (16-byte uuid)
41
+ 0x6a => 'int64s', # 'j'
42
+ 0x4a => 'int64u', # 'J'
43
+ 0x71 => 'fixed32s', # 'q'
44
+ 0x51 => 'fixed64s', # 'Q'
45
+ 0x55 => 'undef', # 'U' (16-byte date)
46
+ 0x3f => 'undef', # '?' (complex structure)
47
+ );
48
+
49
+ # sizes of format codes if different than what FormatSize() would return
50
+ my %goProSize = (
51
+ 0x46 => 4,
52
+ 0x47 => 16,
53
+ 0x55 => 16,
54
+ );
55
+
56
+ # tagInfo elements to add units to PrintConv value
57
+ my %addUnits = (
58
+ AddUnits => 1,
59
+ PrintConv => 'Image::ExifTool::GoPro::AddUnits($self, $val, $tag)',
60
+ );
61
+
62
+ # Tags found in the GPMF box of Hero6 mp4 videos (ref PH), and
63
+ # the gpmd-format timed metadata of Hero5 and Hero6 videos (ref 1)
64
+ %Image::ExifTool::GoPro::GPMF = (
65
+ PROCESS_PROC => \&ProcessGoPro,
66
+ GROUPS => { 2 => 'Camera' },
67
+ NOTES => q{
68
+ Tags extracted from the GPMF box of GoPro MP4 videos, the APP6 "GoPro" segment
69
+ of JPEG files, and from the "gpmd" timed metadata if the ExtractEmbedded option
70
+ is enabled. Many more tags exist, but are currently unknown and extracted only
71
+ with the -u option. Please let me know if you discover the meaning of any of
72
+ these unknown tags. See L<https://github.com/gopro/gpmf-parser> for details
73
+ about this format.
74
+ },
75
+ ACCL => { #2 (gpmd)
76
+ Name => 'Accelerometer',
77
+ Notes => 'accelerator readings in m/s2',
78
+ Binary => 1,
79
+ },
80
+ ALLD => 'AutoLowLightDuration', #1 (gpmd) (untested)
81
+ # APTO (GPMF) - seen: 'RAW' (fmt c)
82
+ ATTD => { #PH (Karma)
83
+ Name => 'Attitude',
84
+ # UNIT=s,rad,rad,rad,rad/s,rad/s,rad/s,
85
+ # TYPE=LffffffB
86
+ # SCAL=1000 1 1 1 1 1 1 1
87
+ Binary => 1,
88
+ },
89
+ ATTR => { #PH (Karma)
90
+ Name => 'AttitudeTarget',
91
+ # UNIT=s,rad,rad,rad,
92
+ # TYPE=Jffff
93
+ # SCAL=1000 1 1 1 1
94
+ Binary => 1,
95
+ },
96
+ AUDO => 'AudioSetting', #PH (GPMF - seen: 'WIND', fmt c)
97
+ # AUPT (GPMF) - seen: 'N' (fmt c)
98
+ BPOS => { #PH (Karma)
99
+ Name => 'Controller',
100
+ Unknown => 1,
101
+ # UNIT=deg,deg,m,deg,deg,m,m,m
102
+ # TYPE=lllfffff
103
+ # SCAL=10000000 10000000 1000 1 1 1 1 1
104
+ %addUnits,
105
+ },
106
+ # BRID (GPMF) - seen: 0 (fmt B)
107
+ # BROD (GPMF) - seen: 'ASK' (fmt c)
108
+ CASN => 'CameraSerialNumber', #PH (GPMF - seen: 'C3221324545448', fmt c)
109
+ # CINF (GPMF) - seen: 0x67376be7709bc8876a8baf3940908618 (fmt B)
110
+ # CMOD (GPMF) - seen: 12,13,17 [13 time-laps video, 17 JPEG] (fmt B)
111
+ CYTS => { #PH (Karma)
112
+ Name => 'CoyoteStatus',
113
+ # UNIT=s,,,,,rad,rad,rad,,
114
+ # TYPE=LLLLLfffBB
115
+ # SCAL=1000 1 1 1 1 1 1 1 1 1
116
+ Binary => 1,
117
+ },
118
+ CSEN => { #PH (Karma)
119
+ Name => 'CoyoteSense',
120
+ # UNIT=s,rad/s,rad/s,rad/s,g,g,g,,,,
121
+ # TYPE=LffffffLLLL
122
+ # SCAL=1000 1 1 1 1 1 1 1 1 1 1
123
+ Binary => 1,
124
+ },
125
+ DEVC => { #PH (gpmd,GPMF, fmt \0)
126
+ Name => 'DeviceContainer',
127
+ SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
128
+ },
129
+ # DVID (GPMF) - DeviceID; seen: 1 (fmt L), HLMT (fmt F)
130
+ DVID => { Name => 'DeviceID', Unknown => 1 }, #2 (gpmd)
131
+ # DVNM (GPMF) seen: 'Video Global Settings' (fmt c), 'Highlights' (fmt c)
132
+ # DVNM (gpmd) seen: 'Camera' (Hero5), 'Hero6 Black' (Hero6), 'GoPro Karma v1.0' (Karma)
133
+ DVNM => 'DeviceName', #PH
134
+ DZOM => { #PH (GPMF - seen: 'Y', fmt c)
135
+ Name => 'DigitalZoom',
136
+ PrintConv => { N => 'No', Y => 'Yes' },
137
+ },
138
+ # DZST (GPMF) - seen: 0 (fmt L) (something to do with digital zoom maybe?)
139
+ # EISA (GPMF) - seen: 'Y','N' [N was for a time-lapse video] (fmt c)
140
+ # EISE (GPMF) - seen: 'Y' (fmt c)
141
+ EMPT => { Name => 'Empty', Unknown => 1 }, #2 (gpmd)
142
+ ESCS => { #PH (Karma)
143
+ Name => 'EscapeStatus',
144
+ # UNIT=s,rpm,rpm,rpm,rpm,rpm,rpm,rpm,rpm,degC,degC,degC,degC,V,V,V,V,A,A,A,A,,,,,,,,,
145
+ # TYPE=JSSSSSSSSssssSSSSSSSSSSSSSSSSB
146
+ # (no SCAL!)
147
+ Unknown => 1,
148
+ %addUnits,
149
+ },
150
+ # EXPT (GPMF) - seen: '' (fmt c)
151
+ FACE => 'FaceDetected', #PH (gpmd)
152
+ FCNM => 'FaceNumbers', #PH (gpmd) (faces counted per frame, ref 1)
153
+ FMWR => 'FirmwareVersion', #PH (GPMF - seen: HD6.01.01.51.00, fmt c)
154
+ FWVS => 'OtherFirmware', #PH (NC) (gpmd - seen: '1.1.11.0', Karma)
155
+ GLPI => { #PH (gpmd, Karma)
156
+ Name => 'GPSPos',
157
+ # UNIT=s,deg,deg,m,m,m/s,m/s,m/s,deg
158
+ # TYPE=LllllsssS
159
+ # SCAL=1000 10000000 10000000 1000 1000 100 100 100 100
160
+ RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
161
+ SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GLPI' },
162
+ },
163
+ GPRI => { #PH (gpmd, Karma)
164
+ Name => 'GPSRaw',
165
+ # UNIT=s,deg,deg,m,m,m,m/s,deg,,
166
+ # TYPE=JlllSSSSBB
167
+ # SCAL=1000000,10000000,10000000,1000,100,100,100,100,1,1
168
+ Unknown => 1,
169
+ RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
170
+ SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPRI' },
171
+ },
172
+ GPS5 => { #2 (gpmd)
173
+ Name => 'GPSInfo',
174
+ # SCAL=10000000,10000000,1000,1000,100
175
+ RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
176
+ SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPS5' },
177
+ },
178
+ GPSF => { #2 (gpmd)
179
+ Name => 'GPSMeasureMode',
180
+ PrintConv => {
181
+ 2 => '2-Dimensional Measurement',
182
+ 3 => '3-Dimensional Measurement',
183
+ },
184
+ },
185
+ GPSP => { #2 (gpmd)
186
+ Name => 'GPSHPositioningError',
187
+ Description => 'GPS Horizontal Positioning Error',
188
+ ValueConv => '$val / 100', # convert from cm to m
189
+ },
190
+ GPSU => { #2 (gpmd)
191
+ Name => 'GPSDateTime',
192
+ Groups => { 2 => 'Time' },
193
+ # (HERO5 writes this in 'c' format, HERO6 writes 'U')
194
+ ValueConv => '$val =~ s/^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/20$1:$2:$3 $4:$5:/; $val',
195
+ PrintConv => '$self->ConvertDateTime($val)',
196
+ },
197
+ GYRO => { #2 (gpmd)
198
+ Name => 'Gyroscope',
199
+ Notes => 'gyroscope readings in rad/s',
200
+ Binary => 1,
201
+ },
202
+ # HFLG (APP6) - seen: 0
203
+ ISOE => 'ISOSpeeds', #PH (gpmd)
204
+ ISOG => { #2 (gpmd)
205
+ Name => 'ImageSensorGain',
206
+ Binary => 1,
207
+ },
208
+ KBAT => { #PH (gpmd) (Karma)
209
+ Name => 'BatteryStatus',
210
+ # UNIT=A,Ah,J,degC,V,V,V,V,s,%,,,,,%
211
+ # TYPE=lLlsSSSSSSSBBBb
212
+ # SCAL=1000,1000,0.00999999977648258,100,1000,1000,1000,1000,0.0166666675359011,1,1,1,1,1,1
213
+ RawConv => '$val', # necessary to use scaled value instead of raw data as subdir data
214
+ SubDirectory => { TagTable => 'Image::ExifTool::GoPro::KBAT' },
215
+ },
216
+ # LINF (GPMF) - seen: LAJ7061916601668 (fmt c)
217
+ LNED => { #PH (Karma)
218
+ Name => 'LocalPositionNED',
219
+ # UNIT=s,m,m,m,m/s,m/s,m/s
220
+ # TYPE=Lffffff
221
+ # SCAL=1000 1 1 1 1 1 1
222
+ Binary => 1,
223
+ },
224
+ MAGN => 'Magnetometer', #1 (gpmd) (units of uT)
225
+ MINF => { #PH (GPMF - seen: HERO6 Black, fmt c)
226
+ Name => 'Model',
227
+ Groups => { 2 => 'Camera' },
228
+ Description => 'Camera Model Name',
229
+ },
230
+ # MTYP (GPMF) - seen: 0,1,11 [1 for time-lapse video, 11 for JPEG] (fmt B)
231
+ # MUID (GPMF) - seen: 3882563431 2278071152 967805802 411471936 0 0 0 0 (fmt L)
232
+ OREN => { #PH (GPMF - seen: 'U', fmt c)
233
+ Name => 'AutoRotation',
234
+ PrintConv => {
235
+ U => 'Up',
236
+ D => 'Down', # (NC)
237
+ A => 'Auto', # (NC)
238
+ },
239
+ },
240
+ # (most of the "P" tags are ProTune settings - PH)
241
+ PHDR => 'HDRSetting', #PH (APP6 - seen: 0)
242
+ PIMN => 'AutoISOMin', #PH (GPMF - seen: 100, fmt L)
243
+ PIMX => 'AutoISOMax', #PH (GPMF - seen: 1600, fmt L)
244
+ # PRAW (APP6) - seen: 0
245
+ PRES => 'PhotoResolution', #PH (APP6 - seen: '12MP_W')
246
+ PRTN => { #PH (GPMF - seen: 'N', fmt c)
247
+ Name => 'ProTune',
248
+ PrintConv => {
249
+ N => 'Off',
250
+ Y => 'On', # (NC)
251
+ },
252
+ },
253
+ PTCL => 'ColorMode', #PH (GPMF - seen: 'GOPRO', fmt c' APP6: 'FLAT')
254
+ PTEV => 'ExposureCompensation', #PH (GPMF - seen: '0.0', fmt c)
255
+ PTSH => 'Sharpness', #PH (GPMF - seen: 'HIGH', fmt c)
256
+ PTWB => 'WhiteBalance', #PH (GPMF - seen: 'AUTO', fmt c)
257
+ RATE => 'Rate', #PH (GPMF - seen: '0_5SEC', fmt c; APP6 - seen: '4_1SEC')
258
+ RMRK => { #2 (gpmd)
259
+ Name => 'Comments',
260
+ ValueConv => '$self->Decode($val, "Latin")',
261
+ },
262
+ SCAL => { #2 (gpmd) scale factor for subsequent data
263
+ Name => 'ScaleFactor',
264
+ Unknown => 1,
265
+ },
266
+ SCPR => { #PH (Karma) [stream was empty]
267
+ Name => 'ScaledPressure',
268
+ # UNIT=s,Pa,Pa,degC
269
+ # TYPE=Lffs
270
+ # SCAL=1000 0.00999999977648258 0.00999999977648258 100
271
+ %addUnits,
272
+ },
273
+ SHUT => { #2 (gpmd)
274
+ Name => 'ExposureTimes',
275
+ PrintConv => q{
276
+ my @a = split ' ', $val;
277
+ $_ = Image::ExifTool::Exif::PrintExposureTime($_) foreach @a;
278
+ return join ' ', @a;
279
+ },
280
+ },
281
+ SIMU => { #PH (Karma)
282
+ Name => 'ScaledIMU',
283
+ # UNIT=s,g,g,g,rad/s,rad/s,rad/s,T,T,T
284
+ # TYPE=Lsssssssss
285
+ # SCAL=1000 1000 1000 1000 1000 1000 1000 1000 1000 1000
286
+ %addUnits,
287
+ },
288
+ SIUN => { #2 (gpmd - seen : 'm/s2','rad/s')
289
+ Name => 'SIUnits',
290
+ Unknown => 1,
291
+ ValueConv => '$self->Decode($val, "Latin")',
292
+ },
293
+ # SMTR (GPMF) - seen: 'N' (fmt c)
294
+ STMP => { #1 (gpmd)
295
+ Name => 'TimeStamp',
296
+ ValueConv => '$val / 1e6',
297
+ },
298
+ STRM => { #2 (gpmd,GPMF, fmt \0)
299
+ Name => 'NestedSignalStream',
300
+ SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
301
+ },
302
+ STNM => { #2 (gpmd)
303
+ Name => 'StreamName',
304
+ Unknown => 1,
305
+ ValueConv => '$self->Decode($val, "Latin")',
306
+ },
307
+ SYST => { #PH (Karma)
308
+ Name => 'SystemTime',
309
+ # UNIT=s,s
310
+ # TYPE=JJ
311
+ # SCAL=1000000 1000
312
+ # save system time calibrations for later
313
+ RawConv => q{
314
+ my @v = split ' ', $val;
315
+ if (@v == 2) {
316
+ my $s = $$self{SystemTimeList};
317
+ $s or $s = $$self{SystemTimeList} = [ ];
318
+ push @$s, \@v;
319
+ }
320
+ return $val;
321
+ },
322
+ },
323
+ # TICK => { Name => 'InTime', Unknown => 1, ValueConv => '$val/1000' }, #1 (gpmd)
324
+ TMPC => { #2 (gpmd)
325
+ Name => 'CameraTemperature',
326
+ PrintConv => '"$val C"',
327
+ },
328
+ # TOCK => { Name => 'OutTime', Unknown => 1, ValueConv => '$val/1000' }, #1 (gpmd)
329
+ TSMP => { Name => 'TotalSamples', Unknown => 1 }, #2 (gpmd)
330
+ TYPE => { Name => 'StructureType', Unknown => 1 }, #2 (gpmd,GPMF - eg 'LLLllfFff', fmt c)
331
+ UNIT => { #2 (gpmd) alternative units
332
+ Name => 'Units',
333
+ Unknown => 1,
334
+ ValueConv => '$self->Decode($val, "Latin")',
335
+ },
336
+ VFOV => { #PH (GPMF - seen: 'W', fmt c)
337
+ Name => 'FieldOfView',
338
+ PrintConv => {
339
+ W => 'Wide',
340
+ S => 'Super View', # (NC, not seen)
341
+ L => 'Linear', # (NC, not seen)
342
+ },
343
+ },
344
+ # VLTA (GPMF) - seen: 78 ('N') (fmt B -- wrong format?)
345
+ VFRH => { #PH (Karma)
346
+ Name => 'VisualFlightRulesHUD',
347
+ BinaryData => 1,
348
+ # UNIT=m/s,m/s,m,m/s,deg,%
349
+ # TYPE=ffffsS
350
+ },
351
+ # VLTE (GPMF) - seen: 'Y' (fmt c)
352
+ WBAL => 'ColorTemperatures', #PH (gpmd)
353
+ WRGB => { #PH (gpmd)
354
+ Name => 'WhiteBalanceRGB',
355
+ Binary => 1,
356
+ },
357
+ );
358
+
359
+ # GoPro GPS5 tags (ref 2) (Hero5,Hero6)
360
+ %Image::ExifTool::GoPro::GPS5 = (
361
+ PROCESS_PROC => \&ProcessString,
362
+ GROUPS => { 1 => 'GoPro', 2 => 'Location' },
363
+ VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
364
+ 0 => { # (unit='deg')
365
+ Name => 'GPSLatitude',
366
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
367
+ },
368
+ 1 => { # (unit='deg')
369
+ Name => 'GPSLongitude',
370
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
371
+ },
372
+ 2 => { # (unit='m')
373
+ Name => 'GPSAltitude',
374
+ PrintConv => '"$val m"',
375
+ },
376
+ 3 => 'GPSSpeed', # (unit='m/s')
377
+ 4 => 'GPSSpeed3D', # (unit='m/s')
378
+ );
379
+
380
+ # GoPro GPRI tags (ref PH) (Karma)
381
+ %Image::ExifTool::GoPro::GPRI = (
382
+ PROCESS_PROC => \&ProcessString,
383
+ GROUPS => { 1 => 'GoPro', 2 => 'Location' },
384
+ VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
385
+ 0 => { # (unit='s')
386
+ Name => 'GPSDateTimeRaw',
387
+ Groups => { 2 => 'Time' },
388
+ ValueConv => \&ConvertSystemTime, # convert to date/time based on SystemTime clock
389
+ PrintConv => '$self->ConvertDateTime($val)',
390
+ },
391
+ 1 => { # (unit='deg')
392
+ Name => 'GPSLatitudeRaw',
393
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
394
+ },
395
+ 2 => { # (unit='deg')
396
+ Name => 'GPSLongitudeRaw',
397
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
398
+ },
399
+ 3 => {
400
+ Name => 'GPSAltitudeRaw', # (NC)
401
+ PrintConv => '"$val m"',
402
+ },
403
+ # (unknown tags must be defined so that ProcessString() will iterate through all values)
404
+ 4 => { Name => 'GPRI_Unknown4', Unknown => 1, Hidden => 1, PrintConv => '"$val m"' },
405
+ 5 => { Name => 'GPRI_Unknown5', Unknown => 1, Hidden => 1, PrintConv => '"$val m"' },
406
+ 6 => 'GPSSpeedRaw', # (NC) # (unit='m/s' -- should convert to other units?)
407
+ 7 => 'GPSTrackRaw', # (NC) # (unit='deg')
408
+ 8 => { Name => 'GPRI_Unknown8', Unknown => 1, Hidden => 1 }, # (no units)
409
+ 9 => { Name => 'GPRI_Unknown9', Unknown => 1, Hidden => 1 }, # (no units)
410
+ );
411
+
412
+ # GoPro GLPI tags (ref PH) (Karma)
413
+ %Image::ExifTool::GoPro::GLPI = (
414
+ PROCESS_PROC => \&ProcessString,
415
+ GROUPS => { 1 => 'GoPro', 2 => 'Location' },
416
+ VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
417
+ 0 => { # (unit='s')
418
+ Name => 'GPSDateTime',
419
+ Groups => { 2 => 'Time' },
420
+ ValueConv => \&ConvertSystemTime, # convert to date/time based on SystemTime clock
421
+ PrintConv => '$self->ConvertDateTime($val)',
422
+ },
423
+ 1 => { # (unit='deg')
424
+ Name => 'GPSLatitude',
425
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
426
+ },
427
+ 2 => { # (unit='deg')
428
+ Name => 'GPSLongitude',
429
+ PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
430
+ },
431
+ 3 => { # (unit='m')
432
+ Name => 'GPSAltitude', # (NC)
433
+ PrintConv => '"$val m"',
434
+ },
435
+ # (unknown tags must be defined so that ProcessString() will iterate through all values)
436
+ 4 => { Name => 'GLPI_Unknown4', Unknown => 1, Hidden => 1, PrintConv => '"$val m"' },
437
+ 5 => { Name => 'GPSSpeedX', PrintConv => '"$val m/s"' }, # (NC)
438
+ 6 => { Name => 'GPSSpeedY', PrintConv => '"$val m/s"' }, # (NC)
439
+ 7 => { Name => 'GPSSpeedZ', PrintConv => '"$val m/s"' }, # (NC)
440
+ 8 => { Name => 'GPSTrack' }, # (unit='deg')
441
+ );
442
+
443
+ # GoPro KBAT tags (ref PH)
444
+ %Image::ExifTool::GoPro::KBAT = (
445
+ PROCESS_PROC => \&ProcessString,
446
+ GROUPS => { 1 => 'GoPro', 2 => 'Camera' },
447
+ VARS => { HEX_ID => 0, ID_LABEL => 'Index' },
448
+ NOTES => 'Battery status information found in GoPro Karma videos.',
449
+ 0 => { Name => 'BatteryCurrent', PrintConv => '"$val A"' },
450
+ 1 => { Name => 'BatteryCapacity', PrintConv => '"$val Ah"' },
451
+ 2 => { Name => 'KBAT_Unknown2', PrintConv => '"$val J"', Unknown => 1, Hidden => 1 },
452
+ 3 => { Name => 'BatteryTemperature', PrintConv => '"$val C"' },
453
+ 4 => { Name => 'BatteryVoltage1', PrintConv => '"$val V"' },
454
+ 5 => { Name => 'BatteryVoltage2', PrintConv => '"$val V"' },
455
+ 6 => { Name => 'BatteryVoltage3', PrintConv => '"$val V"' },
456
+ 7 => { Name => 'BatteryVoltage4', PrintConv => '"$val V"' },
457
+ 8 => { Name => 'BatteryTime', PrintConv => 'ConvertDuration(int($val + 0.5))' }, # (NC)
458
+ 9 => { Name => 'KBAT_Unknown9', PrintConv => '"$val %"', Unknown => 1, Hidden => 1, },
459
+ 10 => { Name => 'KBAT_Unknown10', Unknown => 1, Hidden => 1 }, # (no units)
460
+ 11 => { Name => 'KBAT_Unknown11', Unknown => 1, Hidden => 1 }, # (no units)
461
+ 12 => { Name => 'KBAT_Unknown12', Unknown => 1, Hidden => 1 }, # (no units)
462
+ 13 => { Name => 'KBAT_Unknown13', Unknown => 1, Hidden => 1 }, # (no units)
463
+ 14 => { Name => 'BatteryLevel', PrintConv => '"$val %"' },
464
+ );
465
+
466
+ # GoPro fdsc tags written by the Hero5 and Hero6 (ref PH)
467
+ %Image::ExifTool::GoPro::fdsc = (
468
+ GROUPS => { 2 => 'Camera' },
469
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
470
+ NOTES => q{
471
+ Tags extracted from the MP4 "fdsc" timed metadata when the ExtractEmbedded
472
+ option is used.
473
+ },
474
+ 0x08 => { Name => 'FirmwareVersion', Format => 'string[15]' },
475
+ 0x17 => { Name => 'SerialNumber', Format => 'string[16]' },
476
+ 0x57 => { Name => 'OtherSerialNumber', Format => 'string[15]' }, # (NC)
477
+ 0x66 => {
478
+ Name => 'Model',
479
+ Description => 'Camera Model Name',
480
+ Format => 'string[16]',
481
+ },
482
+ # ...
483
+ # after this there are lots of interesting values also found in the GPMF box,
484
+ # but this block is lacking tag ID's and any directory structure, so the
485
+ # value offsets are therefore presumably firmware dependent :(
486
+ );
487
+
488
+ #------------------------------------------------------------------------------
489
+ # Convert system time to date/time string
490
+ # Inputs: 0) system time value, 1) ExifTool ref
491
+ # Returns: EXIF-format date/time string with milliseconds
492
+ sub ConvertSystemTime($$)
493
+ {
494
+ my ($val, $et) = @_;
495
+ my $s = $$et{SystemTimeList} or return '<uncalibrated>';
496
+ unless ($$et{SystemTimeListSorted}) {
497
+ $s = $$et{SystemTimeList} = [ sort { $$a[0] <=> $$b[0] } @$s ];
498
+ $$et{SystemTimeListSorted} = 1;
499
+ }
500
+ my ($i, $j) = (0, $#$s);
501
+ # perform binary search to find this system time value
502
+ while ($j - $i > 1) {
503
+ my $t = int(($i + $j) / 2);
504
+ ($val < $$s[$t][0] ? $j : $i) = $t;
505
+ }
506
+ if ($i == $j or $$s[$j][0] == $$s[$i][0]) {
507
+ $val = $$s[$i][1];
508
+ } else {
509
+ # interpolate between values
510
+ $val = $$s[$i][1] + ($$s[$j][1] - $$s[$i][1]) * ($val - $$s[$i][0]) / ($$s[$j][0] - $$s[$i][0]);
511
+ }
512
+ # (a bit tricky to remove fractional seconds then add them back again after
513
+ # the date/time conversion while avoiding round-off errors which could
514
+ # put the seconds out by 1...)
515
+ my ($t, $f) = ("$val" =~ /^(\d+)(\.\d+)/);
516
+ return Image::ExifTool::ConvertUnixTime($t, $$et{OPTIONS}{QuickTimeUTC}) . $f;
517
+ }
518
+
519
+ #------------------------------------------------------------------------------
520
+ # Scale values by last 'SCAL' constants
521
+ # Inputs: 0) value or list of values, 1) string of scale factors
522
+ # Returns: nothing, but updates values
523
+ sub ScaleValues($$)
524
+ {
525
+ my ($val, $scl) = @_;
526
+ return unless $val and $scl;
527
+ my @scl = split ' ', $scl or return;
528
+ my @scaled;
529
+ my $v = (ref $val eq 'ARRAY') ? $val : [ $val ];
530
+ foreach $val (@$v) {
531
+ my @a = split ' ', $val;
532
+ $a[$_] /= $scl[$_ % @scl] foreach 0..$#a;
533
+ push @scaled, join(' ', @a);
534
+ }
535
+ $_[0] = @scaled > 1 ? \@scaled : $scaled[0];
536
+ }
537
+
538
+ #------------------------------------------------------------------------------
539
+ # Add units to values for human-readable output
540
+ # Inputs: 0) ExifTool ref, 1) value, 2) tag key
541
+ # Returns: converted value
542
+ sub AddUnits($$$)
543
+ {
544
+ my ($et, $val, $tag) = @_;
545
+ if ($et and $$et{TAG_EXTRA}{$tag} and $$et{TAG_EXTRA}{$tag}{Units}) {
546
+ my $u = $$et{TAG_EXTRA}{$tag}{Units};
547
+ $u = [ $u ] unless ref $u eq 'ARRAY';
548
+ my @a = split ' ', $val;
549
+ if (@$u == @a) {
550
+ my $i;
551
+ for ($i=0; $i<@a; ++$i) {
552
+ $a[$i] .= ' ' . $$u[$i] if $$u[$i];
553
+ }
554
+ $val = join ' ', @a;
555
+ }
556
+ }
557
+ return $val;
558
+ }
559
+
560
+ #------------------------------------------------------------------------------
561
+ # Process string of values (or array of strings) to extract as separate tags
562
+ # Inputs: 0) ExifTool object ref, 1) directory information ref, 2) tag table ref
563
+ # Returns: 1 on success
564
+ sub ProcessString($$$)
565
+ {
566
+ my ($et, $dirInfo, $tagTablePtr) = @_;
567
+ my $dataPt = $$dirInfo{DataPt};
568
+ my @list = ref $$dataPt eq 'ARRAY' ? @{$$dataPt} : ( $$dataPt );
569
+ my ($string, $val);
570
+ $et->VerboseDir('GoPro structure');
571
+ foreach $string (@list) {
572
+ my @val = split ' ', $string;
573
+ my $i = 0;
574
+ foreach $val (@val) {
575
+ $et->HandleTag($tagTablePtr, $i, $val);
576
+ $$tagTablePtr{++$i} or $i = 0;
577
+ }
578
+ }
579
+ return 1;
580
+ }
581
+
582
+ #------------------------------------------------------------------------------
583
+ # Process GoPro metadata (gpmd samples, GPMF box, or APP6) (ref PH/1/2)
584
+ # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
585
+ # Returns: 1 on success
586
+ sub ProcessGoPro($$$)
587
+ {
588
+ my ($et, $dirInfo, $tagTablePtr) = @_;
589
+ my $dataPt = $$dirInfo{DataPt};
590
+ my $base = $$dirInfo{Base};
591
+ my $pos = $$dirInfo{DirStart} || 0;
592
+ my $dirEnd = $pos + ($$dirInfo{DirLen} || (length($$dataPt) - $pos));
593
+ my $verbose = $et->Options('Verbose');
594
+ my $unknown = $verbose || $et->Options('Unknown');
595
+ my ($size, $type, $unit, $scal, $setGroup0);
596
+
597
+ $et->VerboseDir($$dirInfo{DirName} || 'GPMF', undef, $dirEnd-$pos) if $verbose;
598
+ if ($pos) {
599
+ my $parent = $$dirInfo{Parent};
600
+ $setGroup0 = $$et{SET_GROUP0} = 'APP6' if $parent and $parent eq 'APP6';
601
+ } else {
602
+ # set group0 to "QuickTime" unless group1 is being changed (to Track#)
603
+ $setGroup0 = $$et{SET_GROUP0} = 'QuickTime' unless $$et{SET_GROUP1};
604
+ }
605
+
606
+ for (; $pos+8<=$dirEnd; $pos+=($size+3)&0xfffffffc) {
607
+ my ($tag,$fmt,$len,$count) = unpack("x${pos}a4CCn", $$dataPt);
608
+ $size = $len * $count;
609
+ $pos += 8;
610
+ last if $pos + $size > $dirEnd;
611
+ my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
612
+ last if $tag eq "\0\0\0\0"; # stop at null tag
613
+ next unless $size or $verbose; # don't save empty values unless verbose
614
+ my $format = $goProFmt{$fmt} || 'undef';
615
+ my ($val, $i, $j, $p, @v);
616
+ if ($fmt eq 0x3f and defined $type) {
617
+ # decode structure with format given by previous 'TYPE'
618
+ for ($i=0; $i<$count; ++$i) {
619
+ my (@s, $l);
620
+ for ($j=0, $p=0; $j<length($type); ++$j, $p+=$l) {
621
+ my $b = Get8u(\$type, $j);
622
+ my $f = $goProFmt{$b} or last;
623
+ $l = $goProSize{$b} || Image::ExifTool::FormatSize($f) or last;
624
+ last if $p + $l > $len;
625
+ my $s = ReadValue($dataPt, $pos+$i*$len+$p, $f, undef, $l);
626
+ last unless defined $s;
627
+ push @s, $s;
628
+ }
629
+ push @v, join ' ', @s if @s;
630
+ }
631
+ $val = @v > 1 ? \@v : $v[0];
632
+ } elsif (($format eq 'undef' or $format eq 'string') and $count > 1 and $len > 1) {
633
+ # unpack multiple undef/string values as a list
634
+ my $a = $format eq 'undef' ? 'a' : 'A';
635
+ $val = [ unpack("x${pos}".("$a$len" x $count), $$dataPt) ];
636
+ } else {
637
+ $val = ReadValue($dataPt, $pos, $format, undef, $size);
638
+ }
639
+ # save TYPE, UNIT/SIUN and SCAL values for later
640
+ $type = $val if $tag eq 'TYPE';
641
+ $unit = $val if $tag eq 'UNIT' or $tag eq 'SIUN';
642
+ $scal = $val if $tag eq 'SCAL';
643
+
644
+ unless ($tagInfo) {
645
+ next unless $unknown;
646
+ my $name = Image::ExifTool::QuickTime::PrintableTagID($tag);
647
+ $tagInfo = { Name => "GoPro_$name", Description => "GoPro $name", Unknown => 1 };
648
+ $$tagInfo{SubDirectory} = { TagTable => 'Image::ExifTool::GoPro::GPMF' } if not $fmt;
649
+ AddTagToTable($tagTablePtr, $tag, $tagInfo);
650
+ }
651
+ # apply scaling if available to last tag in this container
652
+ ScaleValues($val, $scal) if $scal and $tag ne 'SCAL' and $pos+$size+3>=$dirEnd;
653
+ my $key = $et->HandleTag($tagTablePtr, $tag, $val,
654
+ DataPt => $dataPt,
655
+ Base => $base,
656
+ Start => $pos,
657
+ Size => $size,
658
+ TagInfo => $tagInfo,
659
+ Format => $format,
660
+ Extra => $verbose ? ", type='".($fmt ? chr($fmt) : '\0')."' size=$len count=$count" : undef,
661
+ );
662
+ # save units for adding in print conversion if specified
663
+ $$et{TAG_EXTRA}{$key}{Units} = $unit if $$tagInfo{AddUnits} and $key;
664
+ }
665
+ delete $$et{SET_GROUP0} if $setGroup0;
666
+ return 1;
667
+ }
668
+
669
+ 1; # end
670
+
671
+ __END__
672
+
673
+ =head1 NAME
674
+
675
+ Image::ExifTool::GoPro - Read information from GoPro videos
676
+
677
+ =head1 SYNOPSIS
678
+
679
+ This module is used by Image::ExifTool
680
+
681
+ =head1 DESCRIPTION
682
+
683
+ This module contains definitions required by Image::ExifTool to decode
684
+ metadata from GoPro MP4 videos.
685
+
686
+ =head1 AUTHOR
687
+
688
+ Copyright 2003-2019, Phil Harvey (phil at owl.phy.queensu.ca)
689
+
690
+ This library is free software; you can redistribute it and/or modify it
691
+ under the same terms as Perl itself.
692
+
693
+ =head1 REFERENCES
694
+
695
+ =over 4
696
+
697
+ =item L<https://github.com/gopro/gpmf-parser>
698
+
699
+ =item L<https://github.com/stilldavid/gopro-utils>
700
+
701
+ =back
702
+
703
+ =head1 SEE ALSO
704
+
705
+ L<Image::ExifTool::TagNames/GoPro Tags>,
706
+ L<Image::ExifTool(3pm)|Image::ExifTool>
707
+
708
+ =cut
709
+