1#------------------------------------------------------------------------------
2# File:         Parrot.pm
3#
4# Description:  Read timed metadata from Parrot drone videos
5#
6# Revisions:    2019-10-23 - P. Harvey Created
7#
8# References:   1) https://developer.parrot.com/docs/pdraw/metadata.html
9#------------------------------------------------------------------------------
10
11package Image::ExifTool::Parrot;
12
13use strict;
14use vars qw($VERSION);
15
16$VERSION = '1.01';
17
18sub Process_mett($$$);
19
20# tags found in Parrot 'mett' timed metadata (ref 1)
21%Image::ExifTool::Parrot::mett = (
22    PROCESS_PROC => \&Process_mett,
23    # put the 'P' records first in the documentation
24    VARS => { SORT_PROC => sub { my ($a,$b)=@_; $a=~s/P/A/; $b=~s/P/A/; $a cmp $b } },
25    NOTES => q{
26        Streaming metadata found in Parrot drone videos. See
27        L<https://developer.parrot.com/docs/pdraw/metadata.html> for the
28        specification.
29    },
30    P1 => {
31        Name => 'ParrotV1',
32        SubDirectory => { TagTable => 'Image::ExifTool::Parrot::V1' },
33    },
34    P2 => {
35        Name => 'ParrotV2',
36        SubDirectory => { TagTable => 'Image::ExifTool::Parrot::V2' },
37    },
38    P3 => {
39        Name => 'ParrotV3',
40        SubDirectory => { TagTable => 'Image::ExifTool::Parrot::V3' },
41    },
42    E1 => {
43        Name => 'ParrotTimeStamp',
44        SubDirectory => { TagTable => 'Image::ExifTool::Parrot::TimeStamp' },
45    },
46    E2 => {
47        Name => 'ParrotFollowMe',
48        SubDirectory => { TagTable => 'Image::ExifTool::Parrot::FollowMe' },
49    },
50    E3 => {
51        Name => 'ParrotAutomation',
52        SubDirectory => { TagTable => 'Image::ExifTool::Parrot::Automation' },
53    },
54);
55
56# tags found in the Parrot 'mett' V1 timed metadata (ref 1) [untested]
57%Image::ExifTool::Parrot::V1 = (
58    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
59    NOTES => 'Parrot version 1 streaming metadata.',
60    GROUPS => { 2 => 'Location' },
61    4 => {
62        Name => 'DroneYaw',
63        Format => 'int16s',
64        ValueConv => '$val / 0x1000 * 180 / 3.14159', # convert from rad to deg
65    },
66    6 => {
67        Name => 'DronePitch',
68        Format => 'int16s',
69        ValueConv => '$val / 0x1000 * 180 / 3.14159',
70    },
71    8 => {
72        Name => 'DroneRoll',
73        Format => 'int16s',
74        ValueConv => '$val / 0x1000 * 180 / 3.14159',
75    },
76    10 => {
77        Name => 'CameraPan',
78        Format => 'int16s',
79        ValueConv => '$val / 0x1000 * 180 / 3.14159',
80    },
81    12 => {
82        Name => 'CameraTilt',
83        Format => 'int16s',
84        ValueConv => '$val / 0x1000 * 180 / 3.14159',
85    },
86    14 => {
87        Name => 'FrameView',        # (W,X,Y,Z)
88        Format => 'int16s[4]',
89        ValueConv => 'my @a = split " ",$val; $_ /= 0x1000 foreach @a; "@a"',
90    },
91    22 => {
92        Name => 'ExposureTime',
93        Groups => { 2 => 'Camera' },
94        Format => 'int16s',
95        ValueConv => '$val / 0x100 / 1000',
96        PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
97    },
98    24 => {
99        Name => 'ISO',
100        Groups => { 2 => 'Camera' },
101        Format => 'int16s',
102    },
103    26 => {
104        Name => 'WifiRSSI',
105        Groups => { 2 => 'Device' },
106        Format => 'int8s',
107        PrintConv => '"$val dBm"',
108    },
109    27 => {
110        Name => 'Battery',
111        Groups => { 2 => 'Device' },
112        PrintConv => '"$val %"',
113    },
114    28 => {
115        Name => 'GPSLatitude',
116        Format => 'int32s',
117        ValueConv => '$val / 0x100000',
118        PrintConv    => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
119    },
120    32 => {
121        Name => 'GPSLongitude',
122        Format => 'int32s',
123        ValueConv => '$val / 0x100000',
124        PrintConv    => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
125    },
126    36 => {
127        Name => 'GPSAltitude',
128        Format => 'int32s',
129        Mask => 0xffffff00,
130        ValueConv => '$val / 0x100',
131        PrintConv => 'sprintf("%.3f m", $val)',
132    },
133    36.1 => {
134        Name => 'GPSSatellites',    # (SV count)
135        Format => 'int32s',
136        Mask => 0xff,
137    },
138    40 => {
139        Name => 'AltitudeFromTakeOff',
140        Format => 'int32s',
141        ValueConv => '$val / 0x10000',
142        PrintConv => 'sprintf("%.3f m", $val)',
143    },
144    44 => {
145        Name => 'DistanceFromHome',
146        Format => 'int32u',
147        ValueConv => '$val / 0x10000',
148    },
149    48 => {
150        Name => 'SpeedX',
151        Format => 'int16s',
152        ValueConv => '$val / 0x100',
153    },
154    50 => {
155        Name => 'SpeedY',
156        Format => 'int16s',
157        ValueConv => '$val / 0x100',
158    },
159    52 => {
160        Name => 'SpeedZ',
161        Format => 'int16s',
162        ValueConv => '$val / 0x100',
163    },
164    54 => {
165        Name => 'Binning',
166        Groups => { 2 => 'Device' },
167        Mask => 0x80,
168    },
169    54.1 => {
170        Name => 'FlyingState',
171        Groups => { 2 => 'Device' },
172        Mask => 0x7f,
173        PrintConv => {
174            0 => 'Landed',
175            1 => 'Taking Off',
176            2 => 'Hovering',
177            3 => 'Flying',
178            4 => 'Landing',
179            5 => 'Emergency',
180        },
181    },
182    55 => {
183        Name => 'Animation',
184        Groups => { 2 => 'Device' },
185        Mask => 0x80,
186    },
187    55.1 => {
188        Name => 'PilotingMode',
189        Groups => { 2 => 'Device' },
190        Mask => 0x7f,
191        PrintConv => {
192            0 => 'Manual',
193            1 => 'Return Home',
194            2 => 'Flight Plan',
195            3 => 'Follow Me',
196        },
197    },
198);
199
200# tags found in the Parrot 'mett' V2 timed metadata (ref 1) [untested]
201%Image::ExifTool::Parrot::V2 = (
202    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
203    Groups => { 2 => 'Location' },
204    NOTES => 'Parrot version 2 basic streaming metadata.',
205    4 => {
206        Name => 'Elevation',
207        Notes => 'estimated distance from ground',
208        Format => 'int32s',
209        ValueConv => '$val / 0x10000',
210        PrintConv => 'sprintf("%.3f m", $val)',
211    },
212    8 => {
213        Name => 'GPSLatitude',
214        Format => 'int32s',
215        ValueConv => '$val / 0x400000',
216        PrintConv    => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
217    },
218    12 => {
219        Name => 'GPSLongitude',
220        Format => 'int32s',
221        ValueConv => '$val / 0x400000',
222        PrintConv    => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
223    },
224    16 => {
225        Name => 'GPSAltitude',
226        Format => 'int32s',
227        Mask => 0xffffff00,
228        ValueConv => '$val / 0x100',
229        PrintConv => 'sprintf("%.3f m", $val)',
230    },
231    16.1 => {
232        Name => 'GPSSatellites',    # (SV count)
233        Format => 'int32s',
234        Mask => 0xff,
235    },
236    20 => {
237        Name => 'GPSVelocityNorth', # (m/s)
238        Format => 'int16s',
239        ValueConv => '$val / 0x100',
240    },
241    22 => {
242        Name => 'GPSVelocityEast',  # (m/s)
243        Format => 'int16s',
244        ValueConv => '$val / 0x100',
245    },
246    24 => {
247        Name => 'GPSVelocityDown',  # (m/s)
248        Format => 'int16s',
249        ValueConv => '$val / 0x100',
250    },
251    26 => {
252        Name => 'AirSpeed',         # (m/s)
253        Format => 'int16s',
254        RawConv => '$val < 0 ? undef : $val',
255        ValueConv => '$val / 0x100',
256    },
257    28 => {
258        Name => 'DroneQuaternion',  # (W,X,Y,Z)
259        Format => 'int16s[4]',
260        ValueConv => 'my @a = split " ",$val; $_ /= 0x4000 foreach @a; "@a"',
261    },
262    36 => {
263        Name => 'FrameView',        # (W,X,Y,Z)
264        Format => 'int16s[4]',
265        ValueConv => 'my @a = split " ",$val; $_ /= 0x4000 foreach @a; "@a"',
266    },
267    44 => {
268        Name => 'CameraPan',
269        Format => 'int16s',
270        ValueConv => '$val / 0x1000 * 180 / 3.14159', # convert from rad to deg
271    },
272    46 => {
273        Name => 'CameraTilt',
274        Format => 'int16s',
275        ValueConv => '$val / 0x1000 * 180 / 3.14159',
276    },
277    48 => {
278        Name => 'ExposureTime',
279        Groups => { 2 => 'Camera' },
280        Format => 'int16u',
281        ValueConv => '$val / 0x100 / 1000',
282        PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
283    },
284    50 => {
285        Name => 'ISO',
286        Groups => { 2 => 'Camera' },
287        Format => 'int16u',
288    },
289    52 => {
290        Name => 'Binning',
291        Groups => { 2 => 'Device' },
292        Mask => 0x80,
293    },
294    52.1 => {
295        Name => 'FlyingState',
296        Groups => { 2 => 'Device' },
297        Mask => 0x7f,
298        PrintConv => {
299            0 => 'Landed',
300            1 => 'Taking Off',
301            2 => 'Hovering',
302            3 => 'Flying',
303            4 => 'Landing',
304            5 => 'Emergency',
305            6 => 'User Takeoff',
306            7 => 'Motor Ramping',
307            8 => 'Emergency Landing',
308        },
309    },
310    53 => {
311        Name => 'Animation',
312        Groups => { 2 => 'Device' },
313        Mask => 0x80,
314    },
315    53.1 => {
316        Name => 'PilotingMode',
317        Groups => { 2 => 'Device' },
318        Mask => 0x7f,
319        PrintConv => {
320            0 => 'Manual',
321            1 => 'Return Home',
322            2 => 'Flight Plan',
323            3 => 'Follow Me / Tracking', # (same as 'Tracking')
324            4 => 'Magic Carpet',
325            5 => 'Move To',
326        },
327    },
328    54 => {
329        Name => 'WifiRSSI',
330        Groups => { 2 => 'Device' },
331        Format => 'int8s',
332        PrintConv => '"$val dBm"',
333    },
334    55 => {
335        Name => 'Battery',
336        Groups => { 2 => 'Device' },
337        PrintConv => '"$val %"',
338    },
339);
340
341# tags found in the Parrot 'mett' V3 timed metadata (ref 1)
342%Image::ExifTool::Parrot::V3 = (
343    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
344    GROUPS => { 2 => 'Location' },
345    NOTES => 'Parrot version 3 basic streaming metadata.',
346    4 => {
347        Name => 'Elevation',
348        Notes => 'estimated distance from ground',
349        Format => 'int32s',
350        ValueConv => '$val / 0x10000',
351        PrintConv => 'sprintf("%.3f m", $val)',
352    },
353    8 => {
354        Name => 'GPSLatitude',
355        Format => 'int32s',
356        ValueConv => '$val / 0x400000',
357        PrintConv    => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
358    },
359    12 => {
360        Name => 'GPSLongitude',
361        Format => 'int32s',
362        ValueConv => '$val / 0x400000',
363        PrintConv    => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
364    },
365    16 => {
366        Name => 'GPSAltitude',
367        Format => 'int32s',
368        Mask => 0xffffff00,
369        ValueConv => '$val / 0x100',
370        PrintConv => 'sprintf("%.3f m", $val)',
371    },
372    16.1 => {
373        Name => 'GPSSatellites',    # (SV count)
374        Format => 'int32s',
375        Mask => 0xff,
376    },
377    20 => {
378        Name => 'GPSVelocityNorth', # (m/s)
379        Format => 'int16s',
380        ValueConv => '$val / 0x100',
381    },
382    22 => {
383        Name => 'GPSVelocityEast',  # (m/s)
384        Format => 'int16s',
385        ValueConv => '$val / 0x100',
386    },
387    24 => {
388        Name => 'GPSVelocityDown',  # (m/s)
389        Format => 'int16s',
390        ValueConv => '$val / 0x100',
391    },
392    26 => {
393        Name => 'AirSpeed',         # (m/s)
394        Format => 'int16s',
395        RawConv => '$val < 0 ? undef : $val',
396        ValueConv => '$val / 0x100',
397    },
398    28 => {
399        Name => 'DroneQuaternion',  # (W,X,Y,Z)
400        Format => 'int16s[4]',
401        ValueConv => 'my @a = split " ",$val; $_ /= 0x4000 foreach @a; "@a"',
402    },
403    36 => {
404        Name => 'FrameBaseView',    # (W,X,Y,Z without pan/tilt)
405        Format => 'int16s[4]',
406        ValueConv => 'my @a = split " ",$val; $_ /= 0x4000 foreach @a; "@a"',
407    },
408    44 => {
409        Name => 'FrameView',        # (W,X,Y,Z)
410        Format => 'int16s[4]',
411        ValueConv => 'my @a = split " ",$val; $_ /= 0x4000 foreach @a; "@a"',
412    },
413    52 => {
414        Name => 'ExposureTime',
415        Groups => { 2 => 'Camera' },
416        Format => 'int16u',
417        ValueConv => '$val / 0x100 / 1000',
418        PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
419    },
420    54 => {
421        Name => 'ISO',
422        Groups => { 2 => 'Camera' },
423        Format => 'int16u',
424    },
425    56 => {
426        Name => 'RedBalance',
427        Groups => { 2 => 'Camera' },
428        Format => 'int16u',
429        ValueConv => '$val / 0x4000',
430    },
431    58 => {
432        Name => 'BlueBalance',
433        Groups => { 2 => 'Camera' },
434        Format => 'int16u',
435        ValueConv => '$val / 0x4000',
436    },
437    60 => {
438        Name => 'FOV',              # (degrees)
439        Description => 'Field Of View',
440        Notes => 'horizontal and vertical field of view in degrees',
441        Groups => { 2 => 'Image' },
442        Format => 'int16u[2]',
443        ValueConv => 'my @a = split " ",$val; $_ /= 0x100 foreach @a; "@a"',
444    },
445    64 => {
446        Name => 'LinkGoodput',
447        Groups => { 2 => 'Device' },
448        Format => 'int32u',
449        Mask => 0xffffff00,
450        PrintConv => '"$val kbit/s"',
451    },
452    64.1 => {
453        Name => 'LinkQuality',
454        Groups => { 2 => 'Device' },
455        Format => 'int32u',
456        Notes => '0-5',
457        Mask => 0xff,
458    },
459    68 => {
460        Name => 'WifiRSSI',
461        Groups => { 2 => 'Device' },
462        Format => 'int8s',
463        PrintConv => '"$val dBm"',
464    },
465    69 => {
466        Name => 'Battery',
467        Groups => { 2 => 'Device' },
468        PrintConv => '"$val %"',
469    },
470    70 => {
471        Name => 'Binning',
472        Groups => { 2 => 'Device' },
473        Mask => 0x80,
474    },
475    70.1 => {
476        Name => 'FlyingState',
477        Groups => { 2 => 'Device' },
478        Mask => 0x7f,
479        PrintConv => {
480            0 => 'Landed',
481            1 => 'Taking Off',
482            2 => 'Hovering',
483            3 => 'Flying',
484            4 => 'Landing',
485            5 => 'Emergency',
486            6 => 'User Takeoff',
487            7 => 'Motor Ramping',
488            8 => 'Emergency Landing',
489        },
490    },
491    71 => {
492        Name => 'Animation',
493        Groups => { 2 => 'Device' },
494        Mask => 0x80,
495    },
496    71.1 => {
497        Name => 'PilotingMode',
498        Groups => { 2 => 'Device' },
499        Mask => 0x7f,
500        PrintConv => {
501            0 => 'Manual',
502            1 => 'Return Home',
503            2 => 'Flight Plan',
504            3 => 'Follow Me / Tracking', # (same as 'Tracking')
505            4 => 'Magic Carpet',
506            5 => 'Move To',
507        },
508    },
509);
510
511# tags found in the Parrot 'mett' E1 timestamp timed metadata (ref 1)
512%Image::ExifTool::Parrot::TimeStamp = (
513    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
514    NOTES => 'Parrot streaming metadata timestamp extension.',
515    GROUPS => { 2 => 'Time' },
516    4 => {
517        Name => 'TimeStamp',
518        Format => 'int64u',
519        ValueConv => '$val / 1e6',
520    },
521);
522
523# tags found in the Parrot 'mett' E2 follow-me timed metadata (ref 1) [untested]
524%Image::ExifTool::Parrot::FollowMe = (
525    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
526    GROUPS => { 2 => 'Location' },
527    NOTES => 'Parrot streaming metadata follow-me extension.',
528    4 => {
529        Name => 'GPSTargetLatitude',
530        Format => 'int32s',
531        ValueConv => '$val / 0x400000',
532    },
533    8 => {
534        Name => 'GPSTargetLongitude',
535        Format => 'int32s',
536        ValueConv => '$val / 0x400000',
537    },
538    12 => {
539        Name => 'GPSTargetAltitude',
540        Format => 'int32s',
541        ValueConv => '$val / 0x10000',
542    },
543    16 => {
544        Name => 'Follow-meMode',
545        Groups => { 2 => 'Device' },
546        PrintConv => { BITMASK => {
547            0 => 'Follow-me enabled',
548            1 => 'Follow-me',           # (0=Look-at-me! auggh. see AutomationFlags below)
549            2 => 'Angle locked',
550        }},
551    },
552    17 => {
553        Name => 'Follow-meAnimation',
554        Groups => { 2 => 'Device' },
555        PrintConv => {
556            0 => 'None',
557            1 => 'Orbit',
558            2 => 'Boomerang',
559            3 => 'Parabola',
560            4 => 'Zenith',
561        },
562    },
563);
564
565# tags found in the Parrot 'mett' E3 automation timed metadata (ref 1)
566%Image::ExifTool::Parrot::Automation = (
567    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
568    GROUPS => { 2 => 'Location' },
569    NOTES => 'Parrot streaming metadata automation extension.',
570    4 => {
571        Name => 'GPSFramingLatitude',
572        Format => 'int32s',
573        ValueConv => '$val / 0x400000',
574    },
575    8 => {
576        Name => 'GPSFramingLongitude',
577        Format => 'int32s',
578        ValueConv => '$val / 0x400000',
579    },
580    12 => {
581        Name => 'GPSFramingAltitude',
582        Format => 'int32s',
583        ValueConv => '$val / 0x10000',
584    },
585    16 => {
586        Name => 'GPSDestLatitude',
587        Format => 'int32s',
588        ValueConv => '$val / 0x400000',
589    },
590    20 => {
591        Name => 'GPSDestLongitude',
592        Format => 'int32s',
593        ValueConv => '$val / 0x400000',
594    },
595    24 => {
596        Name => 'GPSDestAltitude',
597        Format => 'int32s',
598        ValueConv => '$val / 0x10000',
599    },
600    28 => {
601        Name => 'AutomationAnimation',
602        Groups => { 2 => 'Device' },
603        PrintConv => {
604            0 => 'None',
605            1 => 'Orbit',
606            2 => 'Boomerang',
607            3 => 'Parabola',
608            4 => 'Dolly Slide',
609            5 => 'Dolly Zoom',
610            6 => 'Reveal Vertical',
611            7 => 'Reveal Horizontal',
612            8 => 'Candle',
613            9 => 'Flip Front',
614            10 => 'Flip Back',
615            11 => 'Flip Left',
616            12 => 'Flip Right',
617            13 => 'Twist Up',
618            14 => 'Position Twist Up',
619        },
620    },
621    29 => {
622        Name => 'AutomationFlags',
623        Groups => { 2 => 'Device' },
624        PrintConv => { BITMASK => {
625            0 => 'Follow-me enabled',
626            1 => 'Look-at-me enabled',  # (really? opposite sense to Follow-meMode above!)
627            2 => 'Angle locked',
628        }},
629    },
630);
631
632%Image::ExifTool::Parrot::Composite = (
633    GPSDateTime => {
634        Description => 'GPS Date/Time',
635        Groups => { 2 => 'Time' },
636        SubDoc => 1,
637        Require => {
638            0 => 'Parrot:GPSLatitude',  # (avoids creating this tag for other videos)
639            1 => 'Main:CreateDate',
640            2 => 'SampleTime',
641        },
642        ValueConv => q{
643            my $time = $val[1];
644            my $diff = $val[2];
645            # handle time zone and shift to UTC
646            if ($time =~ s/([-+])(\d{1,2}):?(\d{2})$//) {
647                my $secs = (($2 * 60) + $3) * 60;
648                $secs *= -1 if $1 eq '+';
649                $diff += $secs;
650            } elsif ($time !~ s/Z$//) {
651                # shift from local time
652                $diff += GetUnixTime($time, 1) - GetUnixTime($time);
653            }
654            my $sign = ($diff =~ s/^-// ? '-' : '');
655            $time .= '.000';    # add decimal seconds
656            ShiftTime($time, "${sign}0:0:$diff");
657            return $time . 'Z';
658        },
659        PrintConv => '$self->ConvertDateTime($val)',
660    },
661);
662
663# add our composite tags
664Image::ExifTool::AddCompositeTags('Image::ExifTool::Parrot');
665
666
667#------------------------------------------------------------------------------
668# Parse Parrot 'mett' timed metadata
669# Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
670# Returns: 1 on success
671# (this metadata design is really stupid -- you need to know the size of the base structures)
672sub Process_mett($$$)
673{
674    my ($et, $dirInfo, $tagTbl) = @_;
675    my $dataPt = $$dirInfo{DataPt};
676    my $dataPos = $$dirInfo{DataPos};
677    my $dirEnd = length $$dataPt;
678    my $pos = $$dirInfo{DirStart} || 0;
679
680    $et->VerboseDir('Parrot mett', undef, $dirEnd);
681
682    while ($pos + 4 < $dirEnd) {
683        my ($id, $nwords) = unpack("x${pos}a2n", $$dataPt);
684        my $size;
685        if ($id !~ /^[EP]\d/) {
686            # no ID so this should be a 60-byte V1 recording record, otherwise give up
687            last unless $dirEnd == 60;
688            $id = 'P1'; # generate a fake ID
689            # ignore the first 4 of the record so the fields will align with
690            # the other V1 records (unfortunately, this means that we won't
691            # decode the V1 recording frame timestamp, but oh well)
692            $pos += 4;
693            $size = $dirEnd - $pos;
694        # must override size for P3 and P3 records since it includes the extensions (augh!)
695        } elsif ($id eq 'P2') {
696            $size = 56;
697        } elsif ($id eq 'P3') {
698            $size = 72;
699        } else {
700            $size = $nwords * 4 + 4;
701        }
702        last if $pos + $size > $dirEnd;
703        $et->HandleTag($tagTbl, $id, undef,
704            DataPt  => $dataPt,
705            DataPos => $dataPos,
706            Base    => $$dirInfo{Base},
707            Start   => $pos,
708            Size    => $size,
709        );
710        $pos += $size;
711    }
712    return 1;
713}
714
7151;  # end
716
717__END__
718
719=head1 NAME
720
721Image::ExifTool::Parrot - Read timed metadata from Parrot drone videos
722
723=head1 SYNOPSIS
724
725This module is loaded automatically by Image::ExifTool when required.
726
727=head1 DESCRIPTION
728
729This module contains definitions required by Image::ExifTool to interpret
730timed metadata from the 'mett' frame found in Parrot drone MP4 videos.
731
732=head1 AUTHOR
733
734Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
735
736This library is free software; you can redistribute it and/or modify it
737under the same terms as Perl itself.
738
739=head1 REFERENCES
740
741=over 4
742
743=item L<https://developer.parrot.com/docs/pdraw/metadata.html>
744
745=back
746
747=head1 SEE ALSO
748
749L<Image::ExifTool::TagNames/Parrot Tags>,
750L<Image::ExifTool(3pm)|Image::ExifTool>
751
752=cut
753