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.
- checksums.yaml +4 -4
- data/bin/Changes +818 -19
- data/bin/MANIFEST +38 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +48 -44
- data/bin/arg_files/exif2xmp.args +4 -1
- data/bin/arg_files/gps2xmp.args +4 -1
- data/bin/arg_files/iptcCore.args +8 -0
- data/bin/arg_files/xmp2exif.args +4 -1
- data/bin/arg_files/xmp2gps.args +4 -1
- data/bin/config_files/dji.config +131 -0
- data/bin/config_files/example.config +6 -2
- data/bin/config_files/gps2utm.config +256 -256
- data/bin/config_files/nksc.config +146 -0
- data/bin/config_files/picasa_faces.config +382 -382
- data/bin/exiftool +688 -408
- data/bin/fmt_files/gpx.fmt +10 -6
- data/bin/fmt_files/gpx_wpt.fmt +10 -6
- data/bin/fmt_files/kml.fmt +8 -5
- data/bin/lib/File/RandomAccess.pm +48 -8
- data/bin/lib/File/RandomAccess.pod +21 -2
- data/bin/lib/Image/ExifTool.pm +645 -256
- data/bin/lib/Image/ExifTool.pod +219 -164
- data/bin/lib/Image/ExifTool/AES.pm +1 -1
- data/bin/lib/Image/ExifTool/AFCP.pm +3 -8
- data/bin/lib/Image/ExifTool/AIFF.pm +12 -4
- data/bin/lib/Image/ExifTool/APE.pm +1 -1
- data/bin/lib/Image/ExifTool/APP12.pm +1 -1
- data/bin/lib/Image/ExifTool/ASF.pm +19 -6
- data/bin/lib/Image/ExifTool/Apple.pm +13 -5
- data/bin/lib/Image/ExifTool/Audible.pm +1 -1
- data/bin/lib/Image/ExifTool/BMP.pm +1 -1
- data/bin/lib/Image/ExifTool/BPG.pm +17 -15
- data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
- data/bin/lib/Image/ExifTool/BigTIFF.pm +30 -15
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +103 -52
- data/bin/lib/Image/ExifTool/Canon.pm +684 -112
- data/bin/lib/Image/ExifTool/CanonCustom.pm +119 -9
- data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/CanonVRD.pm +13 -26
- data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
- data/bin/lib/Image/ExifTool/Casio.pm +1 -1
- data/bin/lib/Image/ExifTool/Charset.pm +1 -1
- data/bin/lib/Image/ExifTool/DICOM.pm +12 -5
- data/bin/lib/Image/ExifTool/DJI.pm +51 -3
- data/bin/lib/Image/ExifTool/DNG.pm +15 -8
- data/bin/lib/Image/ExifTool/DPX.pm +1 -1
- data/bin/lib/Image/ExifTool/DV.pm +1 -1
- data/bin/lib/Image/ExifTool/DarwinCore.pm +63 -23
- data/bin/lib/Image/ExifTool/DjVu.pm +4 -2
- data/bin/lib/Image/ExifTool/EXE.pm +30 -6
- data/bin/lib/Image/ExifTool/Exif.pm +351 -109
- data/bin/lib/Image/ExifTool/FITS.pm +148 -0
- data/bin/lib/Image/ExifTool/FLAC.pm +2 -2
- data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
- data/bin/lib/Image/ExifTool/FLIR.pm +109 -13
- data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
- data/bin/lib/Image/ExifTool/Flash.pm +3 -3
- data/bin/lib/Image/ExifTool/FlashPix.pm +433 -9
- data/bin/lib/Image/ExifTool/Font.pm +2 -2
- data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
- data/bin/lib/Image/ExifTool/FujiFilm.pm +336 -16
- data/bin/lib/Image/ExifTool/GE.pm +1 -1
- data/bin/lib/Image/ExifTool/GIF.pm +5 -7
- data/bin/lib/Image/ExifTool/GIMP.pm +39 -3
- data/bin/lib/Image/ExifTool/GPS.pm +48 -22
- data/bin/lib/Image/ExifTool/GeoTiff.pm +23 -23
- data/bin/lib/Image/ExifTool/Geotag.pm +80 -45
- data/bin/lib/Image/ExifTool/GoPro.pm +709 -0
- data/bin/lib/Image/ExifTool/H264.pm +40 -18
- data/bin/lib/Image/ExifTool/HP.pm +1 -1
- data/bin/lib/Image/ExifTool/HTML.pm +19 -12
- data/bin/lib/Image/ExifTool/HtmlDump.pm +37 -26
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +297 -23
- data/bin/lib/Image/ExifTool/ID3.pm +12 -7
- data/bin/lib/Image/ExifTool/IPTC.pm +48 -19
- data/bin/lib/Image/ExifTool/ISO.pm +1 -1
- data/bin/lib/Image/ExifTool/ITC.pm +1 -1
- data/bin/lib/Image/ExifTool/Import.pm +13 -9
- data/bin/lib/Image/ExifTool/InDesign.pm +3 -5
- data/bin/lib/Image/ExifTool/JPEG.pm +22 -11
- data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
- data/bin/lib/Image/ExifTool/JSON.pm +3 -3
- data/bin/lib/Image/ExifTool/JVC.pm +1 -1
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -2
- data/bin/lib/Image/ExifTool/Kodak.pm +1233 -58
- data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/LNK.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/de.pm +33 -24
- data/bin/lib/Image/ExifTool/Lang/en_ca.pm +64 -2
- data/bin/lib/Image/ExifTool/Lang/en_gb.pm +64 -2
- data/bin/lib/Image/ExifTool/Lang/es.pm +8 -4
- data/bin/lib/Image/ExifTool/Lang/fi.pm +46 -4
- data/bin/lib/Image/ExifTool/Lang/fr.pm +5 -3
- data/bin/lib/Image/ExifTool/Lang/it.pm +6 -3
- data/bin/lib/Image/ExifTool/Lang/ja.pm +15 -3
- data/bin/lib/Image/ExifTool/Lang/ko.pm +5 -2
- data/bin/lib/Image/ExifTool/Lang/nl.pm +6 -3
- data/bin/lib/Image/ExifTool/Lang/pl.pm +2 -2
- data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/tr.pm +4 -2
- data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
- data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
- data/bin/lib/Image/ExifTool/Lytro.pm +4 -8
- data/bin/lib/Image/ExifTool/M2TS.pm +10 -9
- data/bin/lib/Image/ExifTool/MIE.pm +12 -8
- data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
- data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
- data/bin/lib/Image/ExifTool/MNG.pm +1 -1
- data/bin/lib/Image/ExifTool/MOI.pm +1 -1
- data/bin/lib/Image/ExifTool/MPC.pm +1 -1
- data/bin/lib/Image/ExifTool/MPEG.pm +2 -3
- data/bin/lib/Image/ExifTool/MPF.pm +6 -6
- data/bin/lib/Image/ExifTool/MWG.pm +4 -4
- data/bin/lib/Image/ExifTool/MXF.pm +2 -2
- data/bin/lib/Image/ExifTool/MacOS.pm +184 -34
- data/bin/lib/Image/ExifTool/MakerNotes.pm +101 -18
- data/bin/lib/Image/ExifTool/Matroska.pm +1 -1
- data/bin/lib/Image/ExifTool/Microsoft.pm +5 -3
- data/bin/lib/Image/ExifTool/Minolta.pm +89 -62
- data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +1511 -380
- data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
- data/bin/lib/Image/ExifTool/NikonCustom.pm +2758 -2935
- data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
- data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
- data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
- data/bin/lib/Image/ExifTool/Olympus.pm +47 -8
- data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
- data/bin/lib/Image/ExifTool/Opus.pm +1 -1
- data/bin/lib/Image/ExifTool/PCX.pm +138 -0
- data/bin/lib/Image/ExifTool/PDF.pm +58 -42
- data/bin/lib/Image/ExifTool/PGF.pm +1 -1
- data/bin/lib/Image/ExifTool/PICT.pm +1 -1
- data/bin/lib/Image/ExifTool/PLIST.pm +12 -5
- data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
- data/bin/lib/Image/ExifTool/PNG.pm +108 -10
- data/bin/lib/Image/ExifTool/PPM.pm +3 -3
- data/bin/lib/Image/ExifTool/PSP.pm +1 -1
- data/bin/lib/Image/ExifTool/Palm.pm +1 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +299 -31
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +201 -19
- data/bin/lib/Image/ExifTool/Pentax.pm +164 -143
- data/bin/lib/Image/ExifTool/PhaseOne.pm +12 -5
- data/bin/lib/Image/ExifTool/PhotoCD.pm +9 -10
- data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
- data/bin/lib/Image/ExifTool/Photoshop.pm +230 -60
- data/bin/lib/Image/ExifTool/PostScript.pm +29 -4
- data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
- data/bin/lib/Image/ExifTool/Qualcomm.pm +2 -2
- data/bin/lib/Image/ExifTool/QuickTime.pm +1539 -279
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +1857 -0
- data/bin/lib/Image/ExifTool/README +84 -46
- data/bin/lib/Image/ExifTool/RIFF.pm +116 -23
- data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
- data/bin/lib/Image/ExifTool/RTF.pm +6 -4
- data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
- data/bin/lib/Image/ExifTool/Rawzor.pm +3 -2
- data/bin/lib/Image/ExifTool/Real.pm +1 -1
- data/bin/lib/Image/ExifTool/Reconyx.pm +261 -7
- data/bin/lib/Image/ExifTool/Red.pm +325 -0
- data/bin/lib/Image/ExifTool/Ricoh.pm +3 -7
- data/bin/lib/Image/ExifTool/Samsung.pm +95 -25
- data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
- data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
- data/bin/lib/Image/ExifTool/Shift.pl +26 -12
- data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -2
- data/bin/lib/Image/ExifTool/Sigma.pm +36 -30
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +3 -8
- data/bin/lib/Image/ExifTool/Sony.pm +531 -177
- data/bin/lib/Image/ExifTool/SonyIDC.pm +63 -3
- data/bin/lib/Image/ExifTool/Stim.pm +2 -2
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +23 -23
- data/bin/lib/Image/ExifTool/TagLookup.pm +6352 -5062
- data/bin/lib/Image/ExifTool/TagNames.pod +3024 -565
- data/bin/lib/Image/ExifTool/Theora.pm +1 -1
- data/bin/lib/Image/ExifTool/Torrent.pm +2 -2
- data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
- data/bin/lib/Image/ExifTool/VCard.pm +47 -9
- data/bin/lib/Image/ExifTool/Validate.pm +391 -99
- data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
- data/bin/lib/Image/ExifTool/WTV.pm +319 -0
- data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteExif.pl +91 -18
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +6 -6
- data/bin/lib/Image/ExifTool/WritePDF.pl +13 -12
- data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePostScript.pl +2 -2
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +764 -121
- data/bin/lib/Image/ExifTool/WriteXMP.pl +176 -67
- data/bin/lib/Image/ExifTool/Writer.pl +490 -246
- data/bin/lib/Image/ExifTool/XMP.pm +216 -76
- data/bin/lib/Image/ExifTool/XMP2.pl +54 -10
- data/bin/lib/Image/ExifTool/XMPStruct.pl +14 -11
- data/bin/lib/Image/ExifTool/ZIP.pm +60 -15
- data/bin/lib/Image/ExifTool/iWork.pm +12 -5
- data/bin/perl-Image-ExifTool.spec +46 -44
- data/lib/exiftool_vendored/version.rb +1 -1
- 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
|
+
|