[34921] | 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 |
|
---|
| 11 | package Image::ExifTool::Parrot;
|
---|
| 12 |
|
---|
| 13 | use strict;
|
---|
| 14 | use vars qw($VERSION);
|
---|
| 15 |
|
---|
| 16 | $VERSION = '1.01';
|
---|
| 17 |
|
---|
| 18 | sub 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
|
---|
| 664 | Image::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)
|
---|
| 672 | sub 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 |
|
---|
| 715 | 1; # end
|
---|
| 716 |
|
---|
| 717 | __END__
|
---|
| 718 |
|
---|
| 719 | =head1 NAME
|
---|
| 720 |
|
---|
| 721 | Image::ExifTool::Parrot - Read timed metadata from Parrot drone videos
|
---|
| 722 |
|
---|
| 723 | =head1 SYNOPSIS
|
---|
| 724 |
|
---|
| 725 | This module is loaded automatically by Image::ExifTool when required.
|
---|
| 726 |
|
---|
| 727 | =head1 DESCRIPTION
|
---|
| 728 |
|
---|
| 729 | This module contains definitions required by Image::ExifTool to interpret
|
---|
| 730 | timed metadata from the 'mett' frame found in Parrot drone MP4 videos.
|
---|
| 731 |
|
---|
| 732 | =head1 AUTHOR
|
---|
| 733 |
|
---|
| 734 | Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
|
---|
| 735 |
|
---|
| 736 | This library is free software; you can redistribute it and/or modify it
|
---|
| 737 | under 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 |
|
---|
| 749 | L<Image::ExifTool::TagNames/Parrot Tags>,
|
---|
| 750 | L<Image::ExifTool(3pm)|Image::ExifTool>
|
---|
| 751 |
|
---|
| 752 | =cut
|
---|