File Coverage

blib/lib/Image/ExifTool/DJI.pm
Criterion Covered Total %
statement 21 47 44.6
branch 0 8 0.0
condition 0 11 0.0
subroutine 7 9 77.7
pod 0 2 0.0
total 28 77 36.3


line stmt bran cond sub pod time code
1             #------------------------------------------------------------------------------
2             # File: DJI.pm
3             #
4             # Description: DJI Phantom maker notes tags
5             #
6             # Revisions: 2016-07-25 - P. Harvey Created
7             # 2017-06-23 - PH Added XMP tags
8             # 2024-12-04 - PH Added protobuf tags
9             #------------------------------------------------------------------------------
10              
11             package Image::ExifTool::DJI;
12              
13 11     11   84 use strict;
  11         23  
  11         433  
14 11     11   56 use vars qw($VERSION %knownProtocol);
  11         17  
  11         592  
15 11     11   47 use Image::ExifTool qw(:DataAccess :Utils);
  11         18  
  11         2538  
16 11     11   62 use Image::ExifTool::Exif;
  11         20  
  11         256  
17 11     11   2067 use Image::ExifTool::XMP;
  11         31  
  11         728  
18 11     11   51 use Image::ExifTool::GPS;
  11         16  
  11         201  
19 11     11   6169 use Image::ExifTool::Protobuf;
  11         31  
  11         27064  
20              
21             $VERSION = '1.18';
22              
23             sub ProcessDJIInfo($$$);
24             sub ProcessSettings($$$);
25              
26             %knownProtocol = (
27             'dvtm_ac203.proto' => 1, # Osmo Action 4
28             'dvtm_ac204.proto' => 1, # Osmo Action 5
29             'dvtm_ac206.proto' => 1, # Osmo Action 6
30             'dvtm_AVATA2.proto' => 1, # Avata 2
31             'dvtm_wm265e.proto' => 1, # Mavic 3
32             'dvtm_pm320.proto' => 1, # Matrice 30
33             'dvtm_Mini4_Pro.proto' => 1, # Mini 4
34             'dvtm_dji_neo.proto' => 1, # Neo
35             'dvtm_Air3.proto' => 1, # Air 3
36             'dvtm_Air3s.proto' => 1, # Air 3s
37             'dvtm_PP-101.proto' => 1, # Osmo Pocket 3
38             'dvtm_oq101.proto' => 1, # Osmo 360
39             'dvtm_wa345e.proto' => 1, # Matrice 4E
40             'dvtm_wm261.proto' => 1, # Mavic 3 Pro
41             'dvtm_Mavic4.proto' => 1, # Mavic 4 Pro
42             'dvtm_Mini5Pro.proto' => 1, # Mini 5 Pro
43             # dvtm_wm169.proto seems to be DJI O3 but the structure is unknown
44             );
45              
46              
47             my %convFloat2 = (
48             PrintConv => 'sprintf("%+.2f", $val)',
49             PrintConvInv => '$val',
50             );
51              
52             # DJI maker notes (ref PH, mostly educated guesses based on DJI QuickTime::UserData tags)
53             %Image::ExifTool::DJI::Main = (
54             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
55             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
56             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
57             NOTES => q{
58             This table lists tags found in the maker notes of images from some DJI
59             Phantom drones.
60             },
61             0x01 => { Name => 'Make', Writable => 'string' },
62             # 0x02 - int8u[4]: "1 0 0 0", "1 1 0 0"
63             0x03 => { Name => 'SpeedX', Writable => 'float', %convFloat2 }, # (guess)
64             0x04 => { Name => 'SpeedY', Writable => 'float', %convFloat2 }, # (guess)
65             0x05 => { Name => 'SpeedZ', Writable => 'float', %convFloat2 }, # (guess)
66             0x06 => { Name => 'Pitch', Writable => 'float', %convFloat2 },
67             0x07 => { Name => 'Yaw', Writable => 'float', %convFloat2 },
68             0x08 => { Name => 'Roll', Writable => 'float', %convFloat2 },
69             0x09 => { Name => 'CameraPitch',Writable => 'float', %convFloat2 },
70             0x0a => { Name => 'CameraYaw', Writable => 'float', %convFloat2 },
71             0x0b => { Name => 'CameraRoll', Writable => 'float', %convFloat2 },
72             );
73              
74             # DJI debug maker notes
75             %Image::ExifTool::DJI::Info = (
76             PROCESS_PROC => \&ProcessDJIInfo,
77             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
78             NOTES => 'Tags written by some DJI drones.',
79             VARS => { LONG_TAGS => 2 },
80             ae_dbg_info => { Name => 'AEDebugInfo' },
81             ae_histogram_info => { Name => 'AEHistogramInfo' },
82             ae_local_histogram => { Name => 'AELocalHistogram' },
83             ae_liveview_histogram_info => { Name => 'AELiveViewHistogramInfo' },
84             ae_liveview_local_histogram => { Name => 'AELiveViewLocalHistogram' },
85             awb_dbg_info => { Name => 'AWBDebugInfo' },
86             af_dbg_info => { Name => 'AFDebugInfo' },
87             hiso => { Name => 'Histogram' },
88             xidiri => { Name => 'Xidiri' },
89             'GimbalDegree(Y,P,R)'=> { Name => 'GimbalDegree' },
90             'FlightDegree(Y,P,R)'=> { Name => 'FlightDegree' },
91             adj_dbg_info => { Name => 'ADJDebugInfo' },
92             sensor_id => { Name => 'SensorID' },
93             'FlightSpeed(X,Y,Z)' => { Name => 'FlightSpeed' },
94             hyperlapse_dbg_info => { Name => 'HyperlapsDebugInfo' },
95             );
96              
97             # thermal parameters in APP4 of DJI ZH20T images (ref forum11401)
98             %Image::ExifTool::DJI::ThermalParams = (
99             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
100             GROUPS => { 0 => 'APP4', 2 => 'Image' },
101             NOTES => 'Thermal parameters extracted from APP4 of DJI RJPEG files from the ZH20T.',
102             # 0x00 - 0xaa551206 - temperature header magic number
103             0x24 => { Name => 'K1', Format => 'float' },
104             0x28 => { Name => 'K2', Format => 'float' },
105             0x2c => { Name => 'K3', Format => 'float' },
106             0x30 => { Name => 'K4', Format => 'float' },
107             0x34 => { Name => 'KF', Format => 'float' },
108             0x38 => { Name => 'B1', Format => 'float' },
109             0x3c => { Name => 'B2', Format => 'float' },
110             0x44 => { Name => 'ObjectDistance', Format => 'int16u' },
111             0x46 => { Name => 'RelativeHumidity', Format => 'int16u' },
112             0x48 => { Name => 'Emissivity', Format => 'int16u' },
113             0x4a => { Name => 'Reflection', Format => 'int16u', },
114             0x4c => { Name => 'AmbientTemperature', Format => 'int16u' }, # (aka D1)
115             0x50 => { Name => 'D2', Format => 'int32s' },
116             0x54 => { Name => 'KJ', Format => 'int16u' },
117             0x56 => { Name => 'DB', Format => 'int16u' },
118             0x58 => { Name => 'KK', Format => 'int16u' },
119             # 0x500 - 0x55aa1206 - device header magic number
120             # (nothing yet decoded from device header)
121             );
122              
123             # thermal parameters in APP4 of DJI M3T, H20N, M2EA and some M30T images (ref PH/forum11401)
124             %Image::ExifTool::DJI::ThermalParams2 = (
125             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
126             GROUPS => { 0 => 'APP4', 2 => 'Image' },
127             NOTES => 'Thermal parameters extracted from APP4 of DJI M3T RJPEG files.',
128             0x00 => { Name => 'AmbientTemperature', Format => 'float', PrintConv => 'sprintf("%.1f C",$val)' }, # (NC)
129             0x04 => { Name => 'ObjectDistance', Format => 'float', PrintConv => 'sprintf("%.1f m",$val)' },
130             0x08 => { Name => 'Emissivity', Format => 'float', PrintConv => 'sprintf("%.2f",$val)' },
131             0x0c => { Name => 'RelativeHumidity', Format => 'float', PrintConv => 'sprintf("%g %%",$val*100)' },
132             0x10 => { Name => 'ReflectedTemperature',Format => 'float', PrintConv => 'sprintf("%.1f C",$val)' },
133             0x65 => { Name => 'IDString', Format => 'string[16]' }, # (NC)
134             );
135              
136             # thermal parameters in APP4 of some DJI M30T images (ref PH)
137             %Image::ExifTool::DJI::ThermalParams3 = (
138             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
139             GROUPS => { 0 => 'APP4', 2 => 'Image' },
140             NOTES => 'Thermal parameters extracted from APP4 of some DJI RJPEG files.',
141             # 0x00 - 0xaa553800 - params3 magic number
142             0x04 => { Name => 'RelativeHumidity', Format => 'int16u' },
143             0x06 => { Name => 'ObjectDistance', Format => 'int16u', ValueConv => '$val / 10' },
144             0x08 => { Name => 'Emissivity', Format => 'int16u', ValueConv => '$val / 100' },
145             0x0a => { Name => 'ReflectedTemperature',Format => 'int16u', ValueConv => '$val / 10' },
146             );
147              
148             %Image::ExifTool::DJI::XMP = (
149             %Image::ExifTool::XMP::xmpTableDefaults,
150             GROUPS => { 0 => 'XMP', 1 => 'XMP-drone-dji', 2 => 'Location' },
151             NAMESPACE => 'drone-dji',
152             TABLE_DESC => 'XMP DJI',
153             VARS => { ID_FMT => 'none' },
154             NOTES => 'XMP tags used by DJI for images from drones.',
155             AbsoluteAltitude => { Writable => 'real' },
156             RelativeAltitude => { Writable => 'real' },
157             GimbalRollDegree => { Writable => 'real' },
158             GimbalYawDegree => { Writable => 'real' },
159             GimbalPitchDegree => { Writable => 'real' },
160             FlightRollDegree => { Writable => 'real' },
161             FlightYawDegree => { Writable => 'real' },
162             FlightPitchDegree => { Writable => 'real' },
163             GpsLatitude => {
164             Name => 'GPSLatitude',
165             Writable => 'real',
166             Avoid => 1,
167             PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
168             PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1, "lat")',
169             },
170             GpsLongtitude => { # [sic] (misspelt in DJI original file)
171             Name => 'GPSLongtitude',
172             Writable => 'real',
173             Avoid => 1, # (in case someone tries to write "GPSLong*")
174             PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
175             PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1, "lon")',
176             },
177             GpsLongitude => { #PH (NC)
178             Name => 'GPSLongitude',
179             Writable => 'real',
180             Avoid => 1,
181             PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
182             PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1, "lon")',
183             },
184             FlightXSpeed => { Writable => 'real' },
185             FlightYSpeed => { Writable => 'real' },
186             FlightZSpeed => { Writable => 'real' },
187             CamReverse => { }, # integer?
188             GimbalReverse => { }, # integer?
189             SelfData => { Groups => { 2 => 'Image' } },
190             CalibratedFocalLength => { Writable => 'real', Groups => { 2 => 'Image' } },
191             CalibratedOpticalCenterX => { Writable => 'real', Groups => { 2 => 'Image' } },
192             CalibratedOpticalCenterY => { Writable => 'real', Groups => { 2 => 'Image' } },
193             RtkFlag => { }, # integer?
194             RtkStdLon => { Writable => 'real' },
195             RtkStdLat => { Writable => 'real' },
196             RtkStdHgt => { Writable => 'real' },
197             DewarpData => { Groups => { 2 => 'Image' } },
198             DewarpFlag => { Groups => { 2 => 'Image' } }, # integer?
199             Latitude => {
200             Name => 'Latitude',
201             Writable => 'real',
202             PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
203             PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1, "lat")',
204             },
205             Longitude => {
206             Name => 'Longitude',
207             Writable => 'real',
208             PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
209             PrintConvInv => 'Image::ExifTool::GPS::ToDegrees($val, 1, "lon")',
210             },
211             );
212              
213             %Image::ExifTool::DJI::Glamour = (
214             GROUPS => { 0 => 'QuickTime', 1 => 'DJI', 2 => 'Image' },
215             PROCESS_PROC => \&Image::ExifTool::DJI::ProcessSettings,
216             NOTES => 'Glamour settings used by some DJI models.',
217             beauty_enable => 'BeautyEnable',
218             smoother => 'Smoother',
219             whitening => 'Whitening',
220             face_slimming => 'FaceSlimming',
221             eye_enlarge => 'EyeEnlarge',
222             nose_slimming => 'NoseSlimming',
223             mouth_beautify => 'MouthModify',
224             teeth_whitening => 'TeethWhitening',
225             leg_longer => 'LegLonger',
226             head_shrinking => 'HeadShrinking',
227             lipstick => 'Lipstick',
228             blush => 'Blush',
229             dark_circle => 'DarkCircle',
230             acne_spot_removal=>'AcneSpotRemoval',
231             eyebrows => 'Eyebrows',
232             );
233              
234             # metadata in protobuf format (djmd and dbgi meta types, ref PH)
235             %Image::ExifTool::DJI::Protobuf = (
236             GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Camera' },
237             TAG_PREFIX => '',
238             PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
239             NOTES => q{
240             Tags found in protobuf-format DJI djmd and dbgi timed metadata. The known
241             tags listed below are extracted by default, but unknown djmd tags may be
242             extracted as well by setting the Unknown option to 1, or 2 to also extract
243             unknown dbgi debug tags. Tag ID's are composed of the corresponding .proto
244             file name combined with the hierarchical protobuf field numbers.
245              
246             ExifTool currently extracts timed GPS plus a few other tags from DJI devices
247             which use the following protocols: dvtm_AVATA2.proto (Avata 2),
248             dvtm_ac203.proto (Osmo Action 4), dvtm_ac204.proto (Osmo Action 5),
249             dvtm_ac206.proto (Osmo Action 6),dvtm_wm265e.proto (Mavic 3),
250             dvtm_pm320.proto (Matrice 30), dvtm_Mini4_Pro.proto (Mini 4 Pro),
251             dvtm_dji_neo.proto (DJI Neo), dvtm_Air3.proto (Air 3), dvtm_Air3s.proto (Air
252             3s), dvtm_PP-101.proto (Osmo Pocket 3), dvtm_oq101.proto (Osmo 360),
253             dvtm_wa345e.proto (Matrice 4E), dvtm_wm261.proto (Mavic 3 Pro),
254             dvtm_Mavic4.proto (Mavic 4 Pro) and dvtm_Mini5Pro.proto (Mini 5 Pro).
255              
256             Note that with the protobuf format, numerical tags missing from the output
257             for a given protocol should be considered to have the default value of 0.
258             },
259             Protocol => {
260             Notes => "typically protobuf field 1-1-1, but ExifTool doesn't rely on this",
261             RawConv => q{
262             unless ($Image::ExifTool::DJI::knownProtocol{$val} or $val =~ /^dbginfo/) {
263             $self->Warn("Unknown protocol $val (please submit sample for testing)");
264             }
265             return $val;
266             },
267             },
268             #
269             # Osmo Action 4
270             #
271             'dvtm_ac203_1-1-5' => { Name => 'SerialNumber', Notes => 'Osmo Action 4' }, # (NC)
272             # dvtm_ac203_1-1-6 - some version number
273             'dvtm_ac203_1-1-10' => 'Model',
274             'dvtm_ac203_2-3' => {
275             Name => 'FrameInfo',
276             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
277             },
278             'dvtm_ac203_3-2-2-1' => { Name => 'ISO', Format => 'float' },
279             'dvtm_ac203_3-2-4-1' => { # (NC)
280             Name => 'ShutterSpeed',
281             Format => 'rational',
282             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
283             },
284             'dvtm_ac203_3-2-6-1' => { Name => 'ColorTemperature', Format => 'unsigned' }, # (NC)
285             # dvtm_ac203_3-2-9-1 - looks like Z accerometer measurement, but 2 and 3 don't look like other components
286             'dvtm_ac203_3-2-10-2' => { Name => 'AccelerometerX', Format => 'float' } , # (NC) left/right
287             'dvtm_ac203_3-2-10-3' => { Name => 'AccelerometerY', Format => 'float' } , # (NC) front/back
288             'dvtm_ac203_3-2-10-4' => { Name => 'AccelerometerZ', Format => 'float' } , # (NC) up/down
289             # dvtm_ac203_3-4-1-4 - model code?
290             'dvtm_ac203_3-4-2-1' => {
291             Name => 'GPSInfo',
292             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
293             },
294             'dvtm_ac203_3-4-2-2' => {
295             Name => 'GPSAltitude',
296             Groups => { 2 => 'Location' },
297             Format => 'unsigned',
298             ValueConv => '$val / 1000',
299             },
300             'dvtm_ac203_3-4-2-6-1' => {
301             Name => 'GPSDateTime',
302             Format => 'string',
303             Groups => { 2 => 'Time' },
304             RawConv => '$$self{GPSDateTime} = $val',
305             ValueConv => '$val =~ tr/-/:/; $val',
306             PrintConv => '$self->ConvertDateTime($val)',
307             },
308             #
309             # Osmo Action 5
310             #
311             'dvtm_ac204_1-1-5' => { Name => 'SerialNumber', Notes => 'Osmo Action 5' }, # (NC)
312             # dvtm_ac204_1-1-6 - some version number
313             'dvtm_ac204_1-1-10' => 'Model',
314             'dvtm_ac204_2-3' => {
315             Name => 'FrameInfo',
316             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
317             },
318             'dvtm_ac204_3-2-4-1' => { # (NC)
319             Name => 'ShutterSpeed',
320             Format => 'rational',
321             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
322             },
323             'dvtm_ac204_3-2-6-1' => { Name => 'ColorTemperature', Format => 'unsigned' }, # (NC)
324             'dvtm_ac204_3-2-10-2' => { Name => 'AccelerometerX', Format => 'float' } , # (NC) left/right
325             'dvtm_ac204_3-2-10-3' => { Name => 'AccelerometerY', Format => 'float' } , # (NC) front/back
326             'dvtm_ac204_3-2-10-4' => { Name => 'AccelerometerZ', Format => 'float' } , # (NC) up/down
327             # dvtm_ac204_3-4-1-4 - model code?
328             'dvtm_ac204_3-4-2-1' => {
329             Name => 'GPSInfo',
330             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
331             },
332             'dvtm_ac204_3-4-2-2' => {
333             Name => 'GPSAltitude',
334             Groups => { 2 => 'Location' },
335             Format => 'unsigned',
336             ValueConv => '$val / 1000',
337             },
338             'dvtm_ac204_3-4-2-6-1' => {
339             Name => 'GPSDateTime',
340             Format => 'string',
341             Groups => { 2 => 'Time' },
342             RawConv => '$$self{GPSDateTime} = $val',
343             ValueConv => '$val =~ tr/-/:/; $val',
344             PrintConv => '$self->ConvertDateTime($val)',
345             },
346             #
347             # Osmo Action 6 (same as Action 5)
348             #
349             'dvtm_ac206_1-1-5' => { Name => 'SerialNumber', Notes => 'Osmo Action 6' }, # (NC)
350             # dvtm_ac206_1-1-6 - some version number
351             'dvtm_ac206_1-1-10' => 'Model',
352             # dvtm_ac206_2-1-3 - 'video'
353             'dvtm_ac206_2-3' => {
354             Name => 'FrameInfo',
355             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
356             },
357             'dvtm_ac206_3-2-4-1' => { # (NC)
358             Name => 'ShutterSpeed',
359             Format => 'rational',
360             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
361             },
362             'dvtm_ac206_3-2-6-1' => { Name => 'ColorTemperature', Format => 'unsigned' }, # (NC)
363             'dvtm_ac206_3-2-10-2' => { Name => 'AccelerometerX', Format => 'float' } , # (NC) left/right
364             'dvtm_ac206_3-2-10-3' => { Name => 'AccelerometerY', Format => 'float' } , # (NC) front/back
365             'dvtm_ac206_3-2-10-4' => { Name => 'AccelerometerZ', Format => 'float' } , # (NC) up/down
366             # dvtm_ac206_3-4-1-4 - model code?
367             'dvtm_ac206_3-4-2-1' => {
368             Name => 'GPSInfo',
369             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
370             },
371             'dvtm_ac206_3-4-2-2' => {
372             Name => 'GPSAltitude',
373             Groups => { 2 => 'Location' },
374             Format => 'unsigned',
375             ValueConv => '$val / 1000',
376             },
377             'dvtm_ac206_3-4-2-6-1' => {
378             Name => 'GPSDateTime',
379             Format => 'string',
380             Groups => { 2 => 'Time' },
381             RawConv => '$$self{GPSDateTime} = $val',
382             ValueConv => '$val =~ tr/-/:/; $val',
383             PrintConv => '$self->ConvertDateTime($val)',
384             },
385             #
386             # Avata 2
387             #
388             # dvtm_AVATA2_1-1-2 - some version number
389             # dvtm_AVATA2_1-1-3 - some version number
390             'dvtm_AVATA2_1-1-5' => { Name => 'SerialNumber', Notes => 'Avata 2' }, # (NC)
391             'dvtm_AVATA2_1-1-10' => 'Model',
392             # dvtm_AVATA2_2-2-1-4 - model code?
393             'dvtm_AVATA2_2-2-3-1' => 'SerialNumber2', # (NC)
394             'dvtm_AVATA2_2-3' => {
395             Name => 'FrameInfo',
396             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
397             },
398             # dvtm_AVATA2_3-1-1 - frame number (starting at 1)
399             'dvtm_AVATA2_3-1-2' => { # (also 3-2-1-6 and 3-4-1-6)
400             Name => 'TimeStamp',
401             Groups => { 2 => 'Time' },
402             Format => 'unsigned',
403             # milliseconds, but I don't know what the zero is
404             ValueConv => '$val / 1e6',
405             },
406             # dvtm_AVATA2_3-2-1-4 - model code?
407             # dvtm_AVATA2_3-2-1-5 - frame rate?
408             'dvtm_AVATA2_3-2-2-1' => { Name => 'ISO', Format => 'float' }, # (NC)
409             'dvtm_AVATA2_3-2-4-1' => {
410             Name => 'ShutterSpeed',
411             Format => 'rational',
412             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
413             },
414             'dvtm_AVATA2_3-2-6-1' => { Name => 'ColorTemperature', Format => 'unsigned' }, # (NC)
415             'dvtm_AVATA2_3-2-10-1' => { # (NC)
416             Name => 'FNumber',
417             Format => 'rational',
418             PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
419             },
420             # dvtm_AVATA2_3-4-1-4 - model code?
421             'dvtm_AVATA2_3-4-3' => { # (NC)
422             Name => 'DroneInfo',
423             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
424             },
425             'dvtm_AVATA2_3-4-4-1' => {
426             Name => 'GPSInfo',
427             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
428             },
429             'dvtm_AVATA2_3-4-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' }, # (NC)
430             'dvtm_AVATA2_3-4-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' }, # (NC)
431             #
432             # Mavic 3
433             #
434             'dvtm_wm265e_1-1-5' => { Name => 'SerialNumber', Notes => 'Mavic 3' }, # (confirmed)
435             'dvtm_wm265e_1-1-10' => 'Model',
436             'dvtm_wm265e_2-2' => {
437             Name => 'FrameInfo',
438             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
439             },
440             # dvtm_wm265e_3-2-1-4 - model code?
441             'dvtm_wm265e_3-2-2-1' => { Name => 'ISO', Format => 'float' },
442             'dvtm_wm265e_3-2-3-1' => {
443             Name => 'ShutterSpeed',
444             Format => 'rational',
445             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
446             },
447             # dvtm_wm265e_3-2-5-1 - unknown rational (xxxx / 1000)
448             'dvtm_wm265e_3-2-6-1' => { Name => 'DigitalZoom', Format => 'float' },
449             'dvtm_wm265e_3-3-4-1' => {
450             Name => 'GPSInfo',
451             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
452             },
453             'dvtm_wm265e_3-3-3' => {
454             Name => 'DroneInfo',
455             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
456             },
457             'dvtm_wm265e_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' },
458             'dvtm_wm265e_3-3-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' },
459             'dvtm_wm265e_3-4-3' => {
460             Name => 'GimbalInfo',
461             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GimbalInfo' },
462             },
463             #
464             # Matrice 30
465             #
466             'dvtm_pm320_1-1-5' => { Name => 'SerialNumber', Notes => 'Matrice 30' },
467             'dvtm_pm320_1-1-10' => 'Model',
468             'dvtm_pm320_2-2' => {
469             Name => 'FrameInfo',
470             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
471             },
472             'dvtm_pm320_3-2-2-1' => { Name => 'ISO', Format => 'float' },
473             'dvtm_pm320_3-2-3-1' => {
474             Name => 'ShutterSpeed',
475             Format => 'rational',
476             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
477             },
478             'dvtm_pm320_3-2-4-1' => { # (NC)
479             Name => 'FNumber',
480             Format => 'rational',
481             PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
482             },
483             'dvtm_pm320_3-2-6-1' => { Name => 'DigitalZoom', Format => 'float' },
484             'dvtm_pm320_3-3-4-1' => {
485             Name => 'GPSInfo',
486             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
487             },
488             'dvtm_pm320_3-3-3' => {
489             Name => 'DroneInfo',
490             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
491             },
492             'dvtm_pm320_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' },
493             'dvtm_pm320_3-3-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' },
494             'dvtm_pm320_3-4-3' => {
495             Name => 'GimbalInfo',
496             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GimbalInfo' },
497             },
498             #
499             # Mini 4 Pro
500             #
501             'dvtm_Mini4_Pro_1-1-5' => { Name => 'SerialNumber', Notes => 'Mini 4 Pro' },
502             'dvtm_Mini4_Pro_1-1-10' => 'Model',
503             'dvtm_Mini4_Pro_2-3' => {
504             Name => 'FrameInfo',
505             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
506             },
507             'dvtm_Mini4_Pro_3-2-7-1' => { Name => 'ISO', Format => 'float' },
508             'dvtm_Mini4_Pro_3-2-10-1' => {
509             Name => 'ShutterSpeed',
510             Format => 'rational',
511             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
512             },
513             'dvtm_Mini4_Pro_3-2-11-1' => {
514             Name => 'FNumber',
515             Format => 'rational',
516             PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
517             },
518             'dvtm_Mini4_Pro_3-2-32-1' => { Name => 'ColorTemperature', Format => 'unsigned' },
519             'dvtm_Mini4_Pro_3-2-37-1' => { Name => 'Temperature', Format => 'float' }, # (NC)
520             'dvtm_Mini4_Pro_3-3-4-1' => {
521             Name => 'GPSInfo',
522             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
523             },
524             'dvtm_Mini4_Pro_3-3-3' => {
525             Name => 'DroneInfo',
526             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
527             },
528             'dvtm_Mini4_Pro_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' },
529             'dvtm_Mini4_Pro_3-3-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' }, # (NC)
530             'dvtm_Mini4_Pro_3-4-3' => {
531             Name => 'GimbalInfo',
532             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GimbalInfo' },
533             },
534             #
535             # DJI Neo (very similar to AVATA2)
536             #
537             # dvtm_dji_neo_1-1-2 - some version number
538             # dvtm_dji_neo_1-1-3 - some version number
539             'dvtm_dji_neo_1-1-5' => { Name => 'SerialNumber', Notes => 'DJI Neo' }, # (NC)
540             'dvtm_dji_neo_1-1-10' => 'Model',
541             # dvtm_dji_neo_2-2-1-4 - model code?
542             # dvtm_dji_neo_2-2-2-1 - some firmware version?
543             # dvtm_dji_neo_2-2-2-2 - some version number?
544             'dvtm_dji_neo_2-2-3-1' => 'SerialNumber2', # (NC)
545             'dvtm_dji_neo_2-3' => {
546             Name => 'FrameInfo',
547             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
548             },
549             # dvtm_dji_neo_3-1-1 - frame number (starting at 1)
550             'dvtm_dji_neo_3-1-2' => { # (also 3-2-1-6 and 3-4-1-6)
551             Name => 'TimeStamp',
552             Groups => { 2 => 'Time' },
553             Format => 'unsigned',
554             # milliseconds, but I don't know what the zero is
555             ValueConv => '$val / 1e6',
556             },
557             # dvtm_dji_neo_3-2-1-4 - model code?
558             # dvtm_dji_neo_3-2-1-5 - frame rate?
559             'dvtm_dji_neo_3-2-2-1' => { Name => 'ISO', Format => 'float' }, # (NC)
560             'dvtm_dji_neo_3-2-4-1' => {
561             Name => 'ShutterSpeed',
562             Format => 'rational',
563             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
564             },
565             'dvtm_dji_neo_3-2-6-1' => { Name => 'ColorTemperature', Format => 'unsigned' }, # (NC)
566             'dvtm_dji_neo_3-2-10-1' => { # (NC)
567             Name => 'FNumber',
568             Format => 'rational',
569             PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
570             },
571             # dvtm_dji_neo_3-4-1-4 - model code?
572             'dvtm_dji_neo_3-4-3' => { # (NC)
573             Name => 'DroneInfo',
574             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
575             },
576             'dvtm_dji_neo_3-4-4-1' => {
577             Name => 'GPSInfo',
578             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
579             },
580             'dvtm_dji_neo_3-4-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' }, # (NC)
581             #
582             # Air 3
583             #
584             'dvtm_Air3_1-1-5' => { Name => 'SerialNumber', Notes => 'Air 3' },
585             'dvtm_Air3_2-3' => {
586             Name => 'FrameInfo',
587             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
588             },
589             'dvtm_Air3_3-1-2' => {
590             Name => 'TimeStamp',
591             Groups => { 2 => 'Time' },
592             Format => 'unsigned',
593             ValueConv => '$val / 1e6',
594             },
595             'dvtm_Air3_3-2-7-1' => { Name => 'ISO', Format => 'float' },
596             'dvtm_Air3_3-2-10-1' => {
597             Name => 'ShutterSpeed',
598             Format => 'rational',
599             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
600             },
601             'dvtm_Air3_3-2-32-1' => { Name => 'ColorTemperature', Format => 'unsigned' },
602             'dvtm_Air3_3-2-11-1' => {
603             Name => 'FNumber',
604             Format => 'rational',
605             PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
606             },
607             'dvtm_Air3_3-3-3' => {
608             Name => 'DroneInfo',
609             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
610             },
611             'dvtm_Air3_3-3-4-1' => {
612             Name => 'GPSInfo',
613             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
614             },
615             'dvtm_Air3_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' },
616             'dvtm_Air3_3-3-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' },
617             'dvtm_Air3_3-4-3' => {
618             Name => 'GimbalInfo',
619             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GimbalInfo' },
620             },
621             #
622             # Air 3s (same structure as Air 3)
623             #
624             'dvtm_Air3s_1-1-5' => { Name => 'SerialNumber', Notes => 'Air 3s' },
625             'dvtm_Air3s_2-3' => {
626             Name => 'FrameInfo',
627             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
628             },
629             'dvtm_Air3s_3-1-2' => {
630             Name => 'TimeStamp',
631             Groups => { 2 => 'Time' },
632             Format => 'unsigned',
633             ValueConv => '$val / 1e6',
634             },
635             'dvtm_Air3s_3-2-7-1' => { Name => 'ISO', Format => 'float' },
636             'dvtm_Air3s_3-2-10-1' => {
637             Name => 'ShutterSpeed',
638             Format => 'rational',
639             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
640             },
641             'dvtm_Air3s_3-2-32-1' => { Name => 'ColorTemperature', Format => 'unsigned' },
642             'dvtm_Air3s_3-2-11-1' => {
643             Name => 'FNumber',
644             Format => 'rational',
645             PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
646             },
647             'dvtm_Air3s_3-3-3' => {
648             Name => 'DroneInfo',
649             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
650             },
651             'dvtm_Air3s_3-3-4-1' => {
652             Name => 'GPSInfo',
653             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
654             },
655             'dvtm_Air3s_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' },
656             'dvtm_Air3s_3-3-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' },
657             'dvtm_Air3s_3-4-3' => {
658             Name => 'GimbalInfo',
659             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GimbalInfo' },
660             },
661             #
662             # Osmo 360 (similar to Action 4/5)
663             #
664             'dvtm_oq101_1-1-5' => { Name => 'SerialNumber', Notes => 'Osmo 360' },
665             'dvtm_oq101_1-1-10' => 'Model',
666             'dvtm_oq101_3-1-2' => {
667             Name => 'TimeStamp',
668             Groups => { 2 => 'Time' },
669             Format => 'unsigned',
670             ValueConv => '$val / 1e6',
671             },
672             'dvtm_oq101_3-2-3-1' => { Name => 'ISO', Format => 'float' },
673             'dvtm_oq101_3-2-4-1' => {
674             Name => 'ShutterSpeed',
675             Format => 'rational',
676             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
677             },
678             'dvtm_oq101_3-2-6-1' => { Name => 'ColorTemperature', Format => 'unsigned' },
679             'dvtm_oq101_1-14-1' => {
680             Name => 'FNumber',
681             Format => 'rational',
682             PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
683             },
684             'dvtm_oq101_3-4-2-1' => {
685             Name => 'GPSInfo',
686             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
687             },
688             'dvtm_oq101_3-4-2-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' },
689             'dvtm_oq101_3-4-2-6-1' => {
690             Name => 'GPSDateTime',
691             Format => 'string',
692             Groups => { 2 => 'Time' },
693             RawConv => '$$self{GPSDateTime} = $val',
694             ValueConv => '$val =~ tr/-/:/; $val',
695             PrintConv => '$self->ConvertDateTime($val)',
696             },
697             'dvtm_oq101_3-2-10-2' => { Name => 'AccelerometerX', Format => 'float' },
698             'dvtm_oq101_3-2-10-3' => { Name => 'AccelerometerY', Format => 'float' },
699             'dvtm_oq101_3-2-10-4' => { Name => 'AccelerometerZ', Format => 'float' },
700             #
701             # Osmo Pocket 3
702             #
703             'dvtm_PP-101_1-1-5' => { Name => 'SerialNumber', Notes => 'Osmo Pocket 3' },
704             'dvtm_PP-101_1-1-10' => 'Model',
705             'dvtm_PP-101_2-3' => {
706             Name => 'FrameInfo',
707             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
708             },
709             'dvtm_PP-101_3-1-2' => {
710             Name => 'TimeStamp',
711             Groups => { 2 => 'Time' },
712             Format => 'unsigned',
713             ValueConv => '$val / 1e6',
714             },
715             'dvtm_PP-101_3-2-9-1' => { Name => 'ISO', Format => 'float' },
716             'dvtm_PP-101_3-2-10-1' => {
717             Name => 'ShutterSpeed',
718             Format => 'rational',
719             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
720             },
721             'dvtm_PP-101_3-2-24-1' => { Name => 'ColorTemperature', Format => 'unsigned' },
722             #
723             # Matrice 4E
724             #
725             'dvtm_wa345e_1-1-5' => { Name => 'SerialNumber', Notes => 'Matrice 4E' },
726             'dvtm_wa345e_1-1-10' => 'Model',
727             'dvtm_wa345e_2-2' => {
728             Name => 'FrameInfo',
729             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
730             },
731             'dvtm_wa345e_3-1-2' => {
732             Name => 'TimeStamp',
733             Groups => { 2 => 'Time' },
734             Format => 'unsigned',
735             ValueConv => '$val / 1e6',
736             },
737             'dvtm_wa345e_3-3-3' => {
738             Name => 'DroneInfo',
739             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
740             },
741             'dvtm_wa345e_3-3-4-1' => {
742             Name => 'GPSInfo',
743             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
744             },
745             'dvtm_wa345e_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' },
746             'dvtm_wa345e_3-3-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' },
747             'dvtm_wa345e_3-4-3' => {
748             Name => 'GimbalInfo',
749             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GimbalInfo' },
750             },
751             'dvtm_wa345e_3-3-4-6-1' => {
752             Name => 'GPSDateTime',
753             Format => 'string',
754             Groups => { 2 => 'Time' },
755             RawConv => '$$self{GPSDateTime} = $val',
756             ValueConv => '$val =~ tr/-/:/; $val',
757             PrintConv => '$self->ConvertDateTime($val)',
758             },
759             #
760             # Mavic 3 Pro
761             #
762             'dvtm_wm261_1-1-5' => { Name => 'SerialNumber', Notes => 'Mavic 3 Pro' },
763             'dvtm_wm261_1-1-10' => 'Model',
764             'dvtm_wm261_2-3' => {
765             Name => 'FrameInfo',
766             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
767             },
768             'dvtm_wm261_3-1-2' => {
769             Name => 'TimeStamp',
770             Groups => { 2 => 'Time' },
771             Format => 'unsigned',
772             ValueConv => '$val / 1e6',
773             },
774             'dvtm_wm261_3-2-9-1' => { Name => 'ISO', Format => 'float' },
775             'dvtm_wm261_3-2-10-1' => {
776             Name => 'ShutterSpeed',
777             Format => 'rational',
778             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
779             },
780             'dvtm_wm261_3-2-11-1'=> {
781             Name => 'FNumber',
782             Format => 'rational',
783             PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
784             },
785             'dvtm_wm261_3-3-3' => {
786             Name => 'DroneInfo',
787             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
788             },
789             'dvtm_wm261_3-3-4-1' => {
790             Name => 'GPSInfo',
791             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
792             },
793             'dvtm_wm261_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' },
794             'dvtm_wm261_3-3-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' },
795             'dvtm_wm261_3-4-3' => {
796             Name => 'GimbalInfo',
797             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GimbalInfo' },
798             },
799             'dvtm_wm261_3-3-4-6-1' => {
800             Name => 'GPSDateTime',
801             Format => 'string',
802             Groups => { 2 => 'Time' },
803             RawConv => '$$self{GPSDateTime} = $val',
804             ValueConv => '$val =~ tr/-/:/; $val',
805             PrintConv => '$self->ConvertDateTime($val)',
806             },
807             #
808             # Mavic 4 Pro
809             #
810             'dvtm_Mavic4_1-1-5' => { Name => 'SerialNumber', Notes => 'Mavic 4 Pro' },
811             'dvtm_Mavic4_1-1-10' => 'Model',
812             # dvtm_Mavic4_2-2-1-4 - model code?
813             # dvtm_Mavic4_2-2-1-5 - frame rate again
814             'dvtm_Mavic4_2-3' => {
815             Name => 'FrameInfo',
816             SubDirectory => { TagTable => 'Image::ExifTool::DJI::FrameInfo' },
817             },
818             'dvtm_Mavic4_3-1-2' => {
819             Name => 'TimeStamp',
820             Groups => { 2 => 'Time' },
821             Format => 'unsigned',
822             ValueConv => '$val / 1e6',
823             },
824             # dvtm_Mavic4_3-2-1-4 - string: model code?
825             # dvtm_Mavic4_3-2-1-5 - float: frame rate again
826             'dvtm_Mavic4_3-2-9-1' => { Name => 'ISO', Format => 'float' },
827             'dvtm_Mavic4_3-2-10-1' => {
828             Name => 'ShutterSpeed',
829             Format => 'rational',
830             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
831             },
832             'dvtm_Mavic4_3-2-24-1' => { Name => 'ColorTemperature', Format => 'unsigned' },
833             # dvtm_Mavic4_3-2-32-1 - unsigned: color temperature again
834             'dvtm_Mavic4_3-2-37-1' => { Name => 'Temperature', Format => 'float' }, # (NC)
835             'dvtm_Mavic4_3-3-3' => { # (NC)
836             Name => 'DroneInfo',
837             SubDirectory => { TagTable => 'Image::ExifTool::DJI::DroneInfo' },
838             },
839             'dvtm_Mavic4_3-3-4-1' => {
840             Name => 'GPSInfo',
841             Condition => '$$self{CoordUnits} = 1', # (stores in degrees)
842             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
843             },
844             'dvtm_Mavic4_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' }, # (NC)
845             'dvtm_Mavic4_3-3-5-1' => { Name => 'RelativeAltitude', Format => 'float', ValueConv => '$val / 1000' }, # (NC)
846             # dvtm_Mavic4_3-4-1-4 - string: model code?
847             #
848             # Mini 5 Pro
849             #
850             'dvtm_Mini5Pro_1-1-5' => { Name => 'SerialNumber', Notes => 'Mini 5 Pro' }, # (NC)
851             'dvtm_Mini5Pro_1-1-10' => 'Model', # (NC)
852             'dvtm_Mini5Pro_3-2-37-1' => { Name => 'Temperature', Format => 'float' }, # (NC)
853             'dvtm_Mini5Pro_3-3-4-1' => {
854             Name => 'GPSInfo',
855             Condition => '$$self{CoordUnits} = 1', # (NC)
856             SubDirectory => { TagTable => 'Image::ExifTool::DJI::GPSInfo' },
857             },
858             'dvtm_Mini5Pro_3-3-4-2' => { Name => 'AbsoluteAltitude', Format => 'int64s', ValueConv => '$val / 1000' }, # (NC)
859             );
860              
861             # debug info (not yet extracted)
862             # Mavic 4 Pro (ref forum17855)
863             # dbginfo_wa341_2-1-29-12 - Absolute Altitude
864             # dbginfo_wa341_2-1-29-14 - Relative Altitude
865             # dbginfo_wa341_2-1-29-16 - VPS Height (Ultrasonic)
866             # dbginfo_wa341_2-1-4-200-198 - Sensor Temperature
867              
868             %Image::ExifTool::DJI::DroneInfo = (
869             GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Camera' },
870             PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
871             VARS => { ID_FMT => 'dec', ID_LABEL => 'Field #' },
872             1 => { Name => 'DroneRoll', Format => 'int64s', ValueConv => '$val / 10' },
873             2 => { Name => 'DronePitch', Format => 'int64s', ValueConv => '$val / 10' },
874             3 => { Name => 'DroneYaw', Format => 'int64s', ValueConv => '$val / 10' },
875             );
876              
877             %Image::ExifTool::DJI::GimbalInfo = (
878             GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Camera' },
879             PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
880             VARS => { ID_FMT => 'dec', ID_LABEL => 'Field #' },
881             1 => { Name => 'GimbalPitch',Format => 'int64s', ValueConv => '$val / 10' },
882             2 => { Name => 'GimbalRoll', Format => 'int64s', ValueConv => '$val / 10' }, # usually 0, so missing
883             3 => { Name => 'GimbalYaw', Format => 'int64s', ValueConv => '$val / 10' },
884             );
885              
886             %Image::ExifTool::DJI::FrameInfo = (
887             GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Video' },
888             PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
889             VARS => { ID_FMT => 'dec', ID_LABEL => 'Field #' },
890             1 => { Name => 'FrameWidth', Format => 'unsigned' },
891             2 => { Name => 'FrameHeight', Format => 'unsigned' },
892             3 => { Name => 'FrameRate', Format => 'float' },
893             # 4-8: seen these values respectively for DJI Neo: 1,8,4,1,4
894             );
895              
896             %Image::ExifTool::DJI::GPSInfo = (
897             GROUPS => { 0 => 'Protobuf', 1 => 'DJI', 2 => 'Location' },
898             PROCESS_PROC => \&Image::ExifTool::Protobuf::ProcessProtobuf,
899             VARS => { ID_FMT => 'dec', ID_LABEL => 'Field #' },
900             1 => {
901             Name => 'CoordinateUnits',
902             Format => 'unsigned',
903             Notes => 'not extracted, but used internally to convert coordinates to degrees',
904             # don't extract this -- just convert to degrees
905             RawConv => '$$self{CoordUnits} = $val; undef',
906             # PrintConv => { 0 => 'Radians', 1 => 'Degrees' },
907             },
908             2 => {
909             Name => 'GPSLatitude',
910             Format => 'double',
911             # set ExifTool GPSLatitude/GPSLongitude members so GPSDateTime will be generated if necessary
912             RawConv => '$$self{GPSLatitude} = $$self{CoordUnits} ? $val : $val * 180 / 3.141592653589793', # (NC)
913             PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
914             },
915             3 => {
916             Name => 'GPSLongitude',
917             Format => 'double',
918             RawConv => '$$self{GPSLongitude} = $$self{CoordUnits} ? $val : $val * 180 / 3.141592653589793', # (NC)
919             PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
920             },
921             );
922              
923             #------------------------------------------------------------------------------
924             # Process DJI beauty settings (ref PH)
925             # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
926             # Returns: 1 on success
927             sub ProcessSettings($$$)
928             {
929 0     0 0   my ($et, $dirInfo, $tagTbl) = @_;
930 0           $et->VerboseDir($$dirInfo{DirName}, undef, length(${$$dirInfo{DataPt}}));
  0            
931 0           foreach (split /;/, ${$$dirInfo{DataPt}}) {
  0            
932 0           my ($tag, $val) = split /=/;
933 0 0 0       next unless defined $tag and defined $val;
934 0           $et->HandleTag($tagTbl, $tag, $val, MakeTagInfo => 1);
935             }
936 0           return 1;
937             }
938              
939             #------------------------------------------------------------------------------
940             # Process DJI info (ref PH)
941             # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
942             # Returns: 1 on success
943             sub ProcessDJIInfo($$$)
944             {
945 0     0 0   my ($et, $dirInfo, $tagTbl) = @_;
946 0           my $dataPt = $$dirInfo{DataPt};
947 0   0       my $dirStart = $$dirInfo{DirStart} || 0;
948 0   0       my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart);
949 0 0         if ($dirStart) {
950 0           my $buff = substr($$dataPt, $dirStart, $dirLen);
951 0           $dataPt = \$buff;
952             }
953 0           $et->VerboseDir('DJIInfo', undef, length $$dataPt);
954 0           while ($$dataPt =~ /\G\[(.*?)\](?=(\[|$))/sg) {
955 0           my ($tag, $val) = split /:/, $1, 2;
956 0 0 0       next unless defined $tag and defined $val;
957 0 0         if ($val =~ /^([\x20-\x7e]+)\0*$/) {
958 0           $val = $1;
959             } else {
960 0           my $buff = $val;
961 0           $val = \$buff;
962             }
963 0           $et->HandleTag($tagTbl, $tag, $val, MakeTagInfo => 1);
964             }
965 0           return 1;
966             }
967              
968             __END__