exiftool-vendored.pl 12.45.0 → 12.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/bin/Changes +122 -6
  2. package/bin/MANIFEST +12 -0
  3. package/bin/META.json +1 -1
  4. package/bin/META.yml +1 -1
  5. package/bin/README +45 -44
  6. package/bin/config_files/acdsee.config +2 -1
  7. package/bin/config_files/frameCount.config +56 -0
  8. package/bin/config_files/tiff_version.config +1 -1
  9. package/bin/exiftool +89 -75
  10. package/bin/lib/Image/ExifTool/Apple.pm +6 -2
  11. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +17 -9
  12. package/bin/lib/Image/ExifTool/Canon.pm +31 -14
  13. package/bin/lib/Image/ExifTool/CanonRaw.pm +8 -1
  14. package/bin/lib/Image/ExifTool/Exif.pm +13 -8
  15. package/bin/lib/Image/ExifTool/FLAC.pm +17 -3
  16. package/bin/lib/Image/ExifTool/FlashPix.pm +4 -2
  17. package/bin/lib/Image/ExifTool/FujiFilm.pm +31 -5
  18. package/bin/lib/Image/ExifTool/Geotag.pm +1 -1
  19. package/bin/lib/Image/ExifTool/ICC_Profile.pm +1 -1
  20. package/bin/lib/Image/ExifTool/ICO.pm +143 -0
  21. package/bin/lib/Image/ExifTool/ID3.pm +5 -5
  22. package/bin/lib/Image/ExifTool/IPTC.pm +5 -1
  23. package/bin/lib/Image/ExifTool/M2TS.pm +98 -8
  24. package/bin/lib/Image/ExifTool/MIE.pm +9 -3
  25. package/bin/lib/Image/ExifTool/MISB.pm +494 -0
  26. package/bin/lib/Image/ExifTool/MakerNotes.pm +3 -1
  27. package/bin/lib/Image/ExifTool/Nikon.pm +220 -109
  28. package/bin/lib/Image/ExifTool/NikonSettings.pm +5 -3
  29. package/bin/lib/Image/ExifTool/Olympus.pm +2 -1
  30. package/bin/lib/Image/ExifTool/Panasonic.pm +21 -4
  31. package/bin/lib/Image/ExifTool/PanasonicRaw.pm +12 -5
  32. package/bin/lib/Image/ExifTool/Pentax.pm +7 -2
  33. package/bin/lib/Image/ExifTool/Photoshop.pm +29 -3
  34. package/bin/lib/Image/ExifTool/QuickTime.pm +78 -10
  35. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +76 -5
  36. package/bin/lib/Image/ExifTool/README +5 -1
  37. package/bin/lib/Image/ExifTool/RIFF.pm +106 -9
  38. package/bin/lib/Image/ExifTool/Samsung.pm +2 -2
  39. package/bin/lib/Image/ExifTool/Sigma.pm +27 -1
  40. package/bin/lib/Image/ExifTool/SigmaRaw.pm +37 -13
  41. package/bin/lib/Image/ExifTool/Sony.pm +35 -16
  42. package/bin/lib/Image/ExifTool/TagInfoXML.pm +3 -1
  43. package/bin/lib/Image/ExifTool/TagLookup.pm +4700 -4520
  44. package/bin/lib/Image/ExifTool/TagNames.pod +4796 -4463
  45. package/bin/lib/Image/ExifTool/Text.pm +3 -4
  46. package/bin/lib/Image/ExifTool/Torrent.pm +2 -3
  47. package/bin/lib/Image/ExifTool/WriteCanonRaw.pl +7 -0
  48. package/bin/lib/Image/ExifTool/WriteExif.pl +19 -1
  49. package/bin/lib/Image/ExifTool/WriteRIFF.pl +359 -0
  50. package/bin/lib/Image/ExifTool/Writer.pl +6 -2
  51. package/bin/lib/Image/ExifTool/XMP.pm +72 -57
  52. package/bin/lib/Image/ExifTool/XMP2.pl +9 -1
  53. package/bin/lib/Image/ExifTool.pm +81 -18
  54. package/bin/lib/Image/ExifTool.pod +64 -60
  55. package/bin/perl-Image-ExifTool.spec +43 -43
  56. package/bin/pp_build_exe.args +7 -4
  57. package/package.json +2 -2
@@ -21,7 +21,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
21
21
  use Image::ExifTool::Exif;
22
22
  use Image::ExifTool::ASF; # for GetGUID()
23
23
 
24
- $VERSION = '1.40';
24
+ $VERSION = '1.41';
25
25
 
26
26
  sub ProcessFPX($$);
27
27
  sub ProcessFPXR($$$);
@@ -1338,7 +1338,9 @@ sub ConvertDTTM($)
1338
1338
  my $hr = ($val >> 6) & 0x1f;
1339
1339
  my $min = ($val & 0x3f);
1340
1340
  $yr += 1900 if $val;
1341
- return sprintf("%.4d:%.2d:%.2d %.2d:%.2d:00%s",$yr,$mon,$day,$hr,$min,$val ? 'Z' : '');
1341
+ # ExifTool 12.48 dropped the "Z" on the time here because a test .doc
1342
+ # file written by Word 2011 on Mac certainly used local time here
1343
+ return sprintf("%.4d:%.2d:%.2d %.2d:%.2d:00",$yr,$mon,$day,$hr,$min);
1342
1344
  }
1343
1345
 
1344
1346
  #------------------------------------------------------------------------------
@@ -31,7 +31,7 @@ use vars qw($VERSION);
31
31
  use Image::ExifTool qw(:DataAccess :Utils);
32
32
  use Image::ExifTool::Exif;
33
33
 
34
- $VERSION = '1.82';
34
+ $VERSION = '1.84';
35
35
 
36
36
  sub ProcessFujiDir($$$);
37
37
  sub ProcessFaceRec($$$);
@@ -254,6 +254,23 @@ my %faceCategories = (
254
254
  0x2e0 => '-4 (weakest)', #10 (-4)
255
255
  },
256
256
  },
257
+ 0x100f => { #PR158
258
+ Name => 'Clarity',
259
+ Writable => 'int32s', #PH
260
+ PrintConv => {
261
+ -5000 => '-5',
262
+ -4000 => '-4',
263
+ -3000 => '-3',
264
+ -2000 => '-2',
265
+ -1000 => '-1',
266
+ 0 => '0',
267
+ 1000 => '1',
268
+ 2000 => '2',
269
+ 3000 => '3',
270
+ 4000 => '4',
271
+ 5000 => '5',
272
+ },
273
+ },
257
274
  0x1010 => {
258
275
  Name => 'FujiFlashMode',
259
276
  Writable => 'int16u',
@@ -444,7 +461,7 @@ my %faceCategories = (
444
461
  PrintConv => { 0 => 'Off', 1 => 'On' },
445
462
  },
446
463
  0x1047 => { #12
447
- Name => 'GrainEffect',
464
+ Name => 'GrainEffectRoughness',
448
465
  Writable => 'int32s',
449
466
  PrintConv => {
450
467
  0 => 'Off',
@@ -469,6 +486,15 @@ my %faceCategories = (
469
486
  PrintConvInv => '$val + 0',
470
487
  },
471
488
  # 0x104b - BWAdjustment for Green->Magenta (forum10800)
489
+ 0x104c => { #PR158
490
+ Name => "GrainEffectSize",
491
+ Writable => 'int16u', #PH
492
+ PrintConv => {
493
+ 0 => 'Off',
494
+ 16 => 'Small',
495
+ 32 => 'Large',
496
+ },
497
+ },
472
498
  0x104d => { #forum9634
473
499
  Name => 'CropMode',
474
500
  Writable => 'int16u',
@@ -763,8 +789,8 @@ my %faceCategories = (
763
789
  },
764
790
  PrintConvInv => '$val=~/(0x[0-9a-f]+)/i; hex $1',
765
791
  },
766
- 0x1447 => { Name => 'FirmwareVersion', Writable => 'string' },
767
- 0x1448 => { Name => 'FirmwareVersion2', Writable => 'string' },
792
+ 0x1447 => { Name => 'FujiModel', Writable => 'string' },
793
+ 0x1448 => { Name => 'FujiModel2', Writable => 'string' },
768
794
  0x3803 => { #forum10037
769
795
  Name => 'VideoRecordingMode',
770
796
  Groups => { 2 => 'Video' },
@@ -1046,7 +1072,7 @@ my %faceCategories = (
1046
1072
  Mask => 0x000000ff,
1047
1073
  PrintConv => {
1048
1074
  0 => 'Single',
1049
- 1 => 'Continuous Low',
1075
+ 1 => 'Continuous Low', # not used by X-H2S? (see forum13777)
1050
1076
  2 => 'Continuous High',
1051
1077
  },
1052
1078
  },
@@ -558,7 +558,7 @@ DoneFix: $isDate = 1;
558
558
  } elsif ($nmea eq 'RMC') {
559
559
  # $GPRMC,092204.999,A,4250.5589,S,14718.5084,E,0.00,89.68,211200,,*25
560
560
  # $GPRMC,093657.007,,3652.835020,N,01053.104094,E,1.642,,290913,,,A*0F
561
- # $GPRMC,hhmmss.sss,A/V,ddmm.mmmm,N/S,ddmmm.mmmm,E/W,spd(knots),dir(deg),DDMMYY,,*cs
561
+ # $GPRMC,hhmmss.sss,A/V,ddmm.mmmm,N/S,dddmm.mmmm,E/W,spd(knots),dir(deg),DDMMYY,,*cs
562
562
  /^\$[A-Z]{2}RMC,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(\d*?)(\d{1,2}\.\d+),([NS]),(\d*?)(\d{1,2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/ or next;
563
563
  next if $13 > 31 or $14 > 12 or $15 > 99; # validate day/month/year
564
564
  $fix{lat} = (($5 || 0) + $6/60) * ($7 eq 'N' ? 1 : -1);
@@ -627,7 +627,7 @@ my %manuSig = ( #6
627
627
  swpt => 'SpectralWhitePoint',
628
628
  s2cp => 'StandardToCustomPcc',
629
629
  smap => 'SurfaceMap',
630
- # smwp ? (seen in some v5 samples)
630
+ # smwp ? (seen in some v5 samples [was a mistake in sample production])
631
631
 
632
632
  # the following entry represents the ICC profile header, and doesn't
633
633
  # exist as a tag in the directory. It is only in this table to provide
@@ -0,0 +1,143 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: ICO.pm
3
+ #
4
+ # Description: Read Windows ICO and CUR files
5
+ #
6
+ # Revisions: 2020-10-18 - P. Harvey Created
7
+ #
8
+ # References: 1) https://docs.fileformat.com/image/ico/
9
+ #------------------------------------------------------------------------------
10
+
11
+ package Image::ExifTool::ICO;
12
+
13
+ use strict;
14
+ use vars qw($VERSION);
15
+ use Image::ExifTool qw(:DataAccess :Utils);
16
+
17
+ $VERSION = '1.00';
18
+
19
+ %Image::ExifTool::ICO::Main = (
20
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
21
+ GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' },
22
+ NOTES => 'Information extracted from Windows ICO (icon) and CUR (cursor) files.',
23
+ 2 => {
24
+ Name => 'ImageType',
25
+ Format => 'int16u',
26
+ PrintConv => { 1 => 'Icon', 2 => 'Cursor' },
27
+ },
28
+ 4 => {
29
+ Name => 'ImageCount',
30
+ Format => 'int16u',
31
+ RawConv => '$$self{ImageCount} = $val',
32
+ },
33
+ 6 => {
34
+ Name => 'IconDir',
35
+ SubDirectory => { TagTable => 'Image::ExifTool::ICO::IconDir' },
36
+ },
37
+ );
38
+
39
+ %Image::ExifTool::ICO::IconDir = (
40
+ PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
41
+ GROUPS => { 0 => 'File', 1 => 'File', 2 => 'Image' },
42
+ 0 => {
43
+ Name => 'ImageWidth',
44
+ ValueConv => '$val or $val + 256',
45
+ },
46
+ 1 => {
47
+ Name => 'ImageHeight',
48
+ ValueConv => '$val or $val + 256',
49
+ },
50
+ 2 => 'NumColors',
51
+ 4 => [{
52
+ Name => 'ColorPlanes',
53
+ Condition => '$$self{FileType} eq "ICO"',
54
+ Format => 'int16u',
55
+ Notes => 'ICO files',
56
+ },{
57
+ Name => 'HotspotX',
58
+ Format => 'int16u',
59
+ Notes => 'CUR files',
60
+ }],
61
+ 6 => [{
62
+ Name => 'BitsPerPixel',
63
+ Condition => '$$self{FileType} eq "ICO"',
64
+ Format => 'int16u',
65
+ Notes => 'ICO files',
66
+ },{
67
+ Name => 'HotspotY',
68
+ Format => 'int16u',
69
+ Notes => 'CUR files',
70
+ }],
71
+ 8 => {
72
+ Name => 'ImageLength',
73
+ Format => 'int32u',
74
+ },
75
+ );
76
+
77
+ #------------------------------------------------------------------------------
78
+ # Process ICO/CUR file
79
+ # Inputs: 0) ExifTool ref, 1) dirInfo ref
80
+ # Returns: 1 on success, 0 if this wasn't a valid ICO/CUR file
81
+ sub ProcessICO($$$)
82
+ {
83
+ my ($et, $dirInfo) = @_;
84
+ my $raf = $$dirInfo{RAF};
85
+ my ($i, $buff);
86
+ # verify this is a valid ICO/CUR file
87
+ return 0 unless $raf->Read($buff, 6) == 6;
88
+ return 0 unless $buff =~ /^\0\0([\x01\x02])\0[^0]\0/s;
89
+ # (note: have seen cursor files in the wild with an 0x01 here,
90
+ # but SetFileType will use the .cur extension to identify these)
91
+ $et->SetFileType($1 eq "\x01" ? 'ICO' : 'CUR');
92
+ SetByteOrder('II');
93
+ my $tagTbl = GetTagTable('Image::ExifTool::ICO::Main');
94
+ my $num = Get16u(\$buff, 4);
95
+ $et->HandleTag($tagTbl, 4, $num);
96
+ for ($i=0; $i<$num; ++$i) {
97
+ $raf->Read($buff, 16) == 16 or $et->Warn('Truncated file'), last;
98
+ $$et{DOC_NUM} = ++$$et{DOC_COUNT} if $i;
99
+ $et->HandleTag($tagTbl, 6, $buff);
100
+ }
101
+ delete $$et{DOC_NUM};
102
+ return 1;
103
+ }
104
+
105
+ 1; # end
106
+
107
+ __END__
108
+
109
+ =head1 NAME
110
+
111
+ Image::ExifTool::ICO - Read ICO meta information
112
+
113
+ =head1 SYNOPSIS
114
+
115
+ This module is used by Image::ExifTool
116
+
117
+ =head1 DESCRIPTION
118
+
119
+ This module contains definitions required by Image::ExifTool to read
120
+ information from Windows ICO (icon) and CUR (cursor) files.
121
+
122
+ =head1 AUTHOR
123
+
124
+ Copyright 2003-2022, Phil Harvey (philharvey66 at gmail.com)
125
+
126
+ This library is free software; you can redistribute it and/or modify it
127
+ under the same terms as Perl itself.
128
+
129
+ =head1 REFERENCES
130
+
131
+ =over 4
132
+
133
+ =item L<https://docs.fileformat.com/image/ico/>
134
+
135
+ =back
136
+
137
+ =head1 SEE ALSO
138
+
139
+ L<Image::ExifTool::TagNames/ICO Tags>,
140
+ L<Image::ExifTool(3pm)|Image::ExifTool>
141
+
142
+ =cut
143
+
@@ -18,7 +18,7 @@ use strict;
18
18
  use vars qw($VERSION);
19
19
  use Image::ExifTool qw(:DataAccess :Utils);
20
20
 
21
- $VERSION = '1.57';
21
+ $VERSION = '1.58';
22
22
 
23
23
  sub ProcessID3v2($$$);
24
24
  sub ProcessPrivate($$$);
@@ -1414,13 +1414,13 @@ sub ProcessID3($$)
1414
1414
  if ($flags & 0x40) {
1415
1415
  # skip the extended header
1416
1416
  $size >= 4 or $et->Warn('Bad ID3 extended header'), last;
1417
- my $len = unpack('N', $hBuff);
1418
- if ($len > length($hBuff) - 4) {
1417
+ my $len = UnSyncSafe(unpack('N', $hBuff));
1418
+ if ($len > length($hBuff)) {
1419
1419
  $et->Warn('Truncated ID3 extended header');
1420
1420
  last;
1421
1421
  }
1422
- $hBuff = substr($hBuff, $len + 4);
1423
- $pos += $len + 4;
1422
+ $hBuff = substr($hBuff, $len);
1423
+ $pos += $len;
1424
1424
  }
1425
1425
  if ($flags & 0x10) {
1426
1426
  # ignore v2.4 footer (10 bytes long)
@@ -15,7 +15,7 @@ use strict;
15
15
  use vars qw($VERSION $AUTOLOAD %iptcCharset);
16
16
  use Image::ExifTool qw(:DataAccess :Utils);
17
17
 
18
- $VERSION = '1.57';
18
+ $VERSION = '1.58';
19
19
 
20
20
  %iptcCharset = (
21
21
  "\x1b%G" => 'UTF8',
@@ -411,6 +411,7 @@ my %fileFormat = (
411
411
  Shift => 'Time',
412
412
  ValueConv => 'Image::ExifTool::Exif::ExifDate($val)',
413
413
  ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)',
414
+ PrintConv => '$self->Options("DateFormat") ? $self->ConvertDateTime("$val 00:00:00") : $val',
414
415
  PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)',
415
416
  },
416
417
  60 => {
@@ -420,6 +421,7 @@ my %fileFormat = (
420
421
  Shift => 'Time',
421
422
  ValueConv => 'Image::ExifTool::Exif::ExifTime($val)',
422
423
  ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)',
424
+ PrintConv => '$self->Options("DateFormat") ? $self->ConvertDateTime("1970:01:01 $val") : $val',
423
425
  PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)',
424
426
  },
425
427
  62 => {
@@ -429,6 +431,7 @@ my %fileFormat = (
429
431
  Shift => 'Time',
430
432
  ValueConv => 'Image::ExifTool::Exif::ExifDate($val)',
431
433
  ValueConvInv => 'Image::ExifTool::IPTC::IptcDate($val)',
434
+ PrintConv => '$self->Options("DateFormat") ? $self->ConvertDateTime("$val 00:00:00") : $val',
432
435
  PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)',
433
436
  },
434
437
  63 => {
@@ -438,6 +441,7 @@ my %fileFormat = (
438
441
  Shift => 'Time',
439
442
  ValueConv => 'Image::ExifTool::Exif::ExifTime($val)',
440
443
  ValueConvInv => 'Image::ExifTool::IPTC::IptcTime($val)',
444
+ PrintConv => '$self->Options("DateFormat") ? $self->ConvertDateTime("1970:01:01 $val") : $val',
441
445
  PrintConvInv => 'Image::ExifTool::IPTC::InverseDateOrTime($self,$val)',
442
446
  },
443
447
  65 => {
@@ -13,6 +13,7 @@
13
13
  # 6) http://trac.handbrake.fr/browser/trunk/libhb/stream.c
14
14
  # 7) http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=04560141
15
15
  # 8) http://www.w6rz.net/xport.zip
16
+ # 9) https://en.wikipedia.org/wiki/Program-specific_information
16
17
  #
17
18
  # Notes: Variable names containing underlines are the same as in ref 1.
18
19
  #
@@ -31,9 +32,9 @@ use strict;
31
32
  use vars qw($VERSION);
32
33
  use Image::ExifTool qw(:DataAccess :Utils);
33
34
 
34
- $VERSION = '1.21';
35
+ $VERSION = '1.23';
35
36
 
36
- # program map table "stream_type" lookup (ref 6/1)
37
+ # program map table "stream_type" lookup (ref 6/1/9)
37
38
  my %streamType = (
38
39
  0x00 => 'Reserved',
39
40
  0x01 => 'MPEG-1 Video',
@@ -56,9 +57,22 @@ my %streamType = (
56
57
  0x12 => 'MPEG-4 generic',
57
58
  0x13 => 'ISO 14496-1 SL-packetized',
58
59
  0x14 => 'ISO 13818-6 Synchronized Download Protocol',
59
- # 0x15-0x7F => 'ISO 13818-1 Reserved',
60
+ 0x15 => 'Packetized metadata',
61
+ 0x16 => 'Sectioned metadata',
62
+ 0x17 => 'ISO/IEC 13818-6 DSM CC Data Carousel metadata',
63
+ 0x18 => 'ISO/IEC 13818-6 DSM CC Object Carousel metadata',
64
+ 0x19 => 'ISO/IEC 13818-6 Synchronized Download Protocol metadata',
65
+ 0x1a => 'ISO/IEC 13818-11 IPMP',
60
66
  0x1b => 'H.264 (AVC) Video',
67
+ 0x1c => 'ISO/IEC 14496-3 (MPEG-4 raw audio)',
68
+ 0x1d => 'ISO/IEC 14496-17 (MPEG-4 text)',
69
+ 0x1e => 'ISO/IEC 23002-3 (MPEG-4 auxiliary video)',
70
+ 0x1f => 'ISO/IEC 14496-10 SVC (MPEG-4 AVC sub-bitstream)',
71
+ 0x20 => 'ISO/IEC 14496-10 MVC (MPEG-4 AVC sub-bitstream)',
72
+ 0x21 => 'ITU-T Rec. T.800 and ISO/IEC 15444 (JPEG 2000 video)',
61
73
  0x24 => 'H.265 (HEVC) Video', #PH
74
+ 0x42 => 'Chinese Video Standard',
75
+ 0x7f => 'ISO/IEC 13818-11 IPMP (DRM)',
62
76
  0x80 => 'DigiCipher II Video',
63
77
  0x81 => 'A52/AC-3 Audio',
64
78
  0x82 => 'HDMV DTS Audio',
@@ -145,6 +159,7 @@ my $knotsToKph = 1.852; # knots --> km/h
145
159
  # the following tags are for documentation purposes only
146
160
  _AC3 => { SubDirectory => { TagTable => 'Image::ExifTool::M2TS::AC3' } },
147
161
  _H264 => { SubDirectory => { TagTable => 'Image::ExifTool::H264::Main' } },
162
+ _MISB => { SubDirectory => { TagTable => 'Image::ExifTool::MISB::Main' } },
148
163
  );
149
164
 
150
165
  # information extracted from AC-3 audio streams
@@ -278,7 +293,7 @@ sub ParsePID($$$$$)
278
293
  my $verbose = $et->Options('Verbose');
279
294
  if ($verbose > 1) {
280
295
  my $out = $et->Options('TextOut');
281
- printf $out "Parsing stream 0x%.4x (%s)\n", $pid, $pidName;
296
+ printf $out "Parsing stream 0x%.4x (%s) %d bytes\n", $pid, $pidName, length($$dataPt);
282
297
  $et->VerboseDump($dataPt);
283
298
  }
284
299
  my $more = 0;
@@ -303,6 +318,16 @@ sub ParsePID($$$$$)
303
318
  } elsif ($type == 0x81 or $type == 0x87 or $type == 0x91) {
304
319
  # AC-3 audio
305
320
  ParseAC3Audio($et, $dataPt);
321
+ } elsif ($type == 0x15) {
322
+ # packetized metadata (look for MISB code starting after 5-byte header)
323
+ if ($$dataPt =~ /^.{5}\x06\x0e\x2b\x34/s) {
324
+ $more = Image::ExifTool::MISB::ParseMISB($et, $dataPt, GetTagTable('Image::ExifTool::MISB::Main'));
325
+ if (not $$et{OPTIONS}{ExtractEmbedded}) {
326
+ $more = 0; # extract from only the first packet unless ExtractEmbedded is used
327
+ } elsif ($$et{OPTIONS}{ExtractEmbedded} > 2) {
328
+ $more = 1; # read past unknown 0x15 packets if ExtractEmbedded > 2
329
+ }
330
+ }
306
331
  } elsif ($type < 0) {
307
332
  if ($$dataPt =~ /^(.{164})?(.{24})A[NS][EW]/s) {
308
333
  # (Blueskysea B4K, Novatek NT96670)
@@ -390,6 +415,48 @@ sub ParsePID($$$$$)
390
415
  }
391
416
  }
392
417
  $more = 1;
418
+ } elsif ($$dataPt =~ /\$GPRMC,/) {
419
+ # Jomise T860S-GM dashcam
420
+ # $GPRMC,hhmmss.ss,A,ddmm.mmmmm,N,dddmm.mmmmm,W,spd-kts,dir-dg,DDMMYY,,*cs
421
+ # $GPRMC,172255.00,A,:985.95194,N,17170.14674,W,029.678,170.68,240822,,,D*7B
422
+ # $GPRMC,172355.00,A,:984.76779,N,17170.00473,W,032.219,172.04,240822,,,D*7B
423
+ # ddmm.mmmm: from 4742.2568 12209.2028 (should be)
424
+ # to 4741.7696 12209.1056
425
+ # stamped on video: 47.70428N, 122.15338W, 35mph (dd.ddddd)
426
+ # to 47.69616N, 122.15176W, 37mph
427
+ my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
428
+ while ($$dataPt =~ /\$[A-Z]{2}RMC,(\d{2})(\d{2})(\d+(\.\d*)?),A?,(.{2})(\d{2}\.\d+),([NS]),(.{3})(\d{2}\.\d+),([EW]),(\d*\.?\d*),(\d*\.?\d*),(\d{2})(\d{2})(\d+)/g and
429
+ # do some basic sanity checks on the date
430
+ $13 <= 31 and $14 <= 12 and $15 <= 99)
431
+ {
432
+ $$et{DOC_NUM} = ++$$et{DOC_COUNT};
433
+ my $year = $15 + ($15 >= 70 ? 1900 : 2000);
434
+ $et->HandleTag($tagTbl, GPSDateTime => sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2dZ', $year, $14, $13, $1, $2, $3));
435
+ #(not this simple)
436
+ #$et->HandleTag($tagTbl, GPSLatitude => (($5 || 0) + $6/60) * ($7 eq 'N' ? 1 : -1));
437
+ #$et->HandleTag($tagTbl, GPSLongitude => (($8 || 0) + $9/60) * ($10 eq 'E' ? 1 : -1));
438
+ $et->HandleTag($tagTbl, GPSSpeed => $11 * $knotsToKph) if length $11;
439
+ $et->HandleTag($tagTbl, GPSTrack => $12) if length $12;
440
+ # it looks like maybe the degrees are xor-ed with something,
441
+ # and the minutes have some scaling factor and offset?
442
+ # (the code below is approximately correct for my only sample)
443
+ my @chars = unpack('C*', $5 . $8);
444
+ my @xor = (0x0e,0x0e,0x00,0x05,0x03); # (empirical based on 1 sample; may be completely off base)
445
+ my $bad;
446
+ foreach (@chars) {
447
+ $_ ^= shift(@xor);
448
+ $bad = 1 if $_ < 0x30 or $_ > 0x39;
449
+ }
450
+ if ($bad) {
451
+ $et->WarnOnce('Error decrypting GPS degrees');
452
+ } else {
453
+ my $la = pack('C*', @chars[0,1]);
454
+ my $lo = pack('C*', @chars[2,3,4]);
455
+ $et->WarnOnce('Decryption of this GPS is highly experimental. More testing samples are required');
456
+ $et->HandleTag($tagTbl, GPSLatitude => (($la || 0) + (($6-85.95194)/2.43051724137931+42.2568)/60) * ($7 eq 'N' ? 1 : -1));
457
+ $et->HandleTag($tagTbl, GPSLongitude => (($lo || 0) + (($9-70.14674)/1.460987654320988+9.2028)/60) * ($10 eq 'E' ? 1 : -1));
458
+ }
459
+ }
393
460
  } elsif ($$dataPt =~ /^.{44}A\0{3}.{4}([NS])\0{3}.{4}([EW])\0{3}/s and length($$dataPt) >= 84) {
394
461
  #forum11320
395
462
  SetByteOrder('II');
@@ -426,7 +493,7 @@ sub ProcessM2TS($$)
426
493
  my ($et, $dirInfo) = @_;
427
494
  my $raf = $$dirInfo{RAF};
428
495
  my ($buff, $pLen, $upkPrefix, $j, $fileType, $eof);
429
- my (%pmt, %pidType, %data, %sectLen);
496
+ my (%pmt, %pidType, %data, %sectLen, %packLen, %fromStart);
430
497
  my ($startTime, $endTime, $fwdTime, $backScan, $maxBack);
431
498
  my $verbose = $et->Options('Verbose');
432
499
  my $out = $et->Options('TextOut');
@@ -468,6 +535,7 @@ sub ProcessM2TS($$)
468
535
  my %gpsPID = (
469
536
  0x0300 => 1, # Novatek INNOVV
470
537
  0x01e4 => 1, # vsys a6l dashcam
538
+ 0x0e1b => 1, # Jomise T860S-GM dashcam
471
539
  );
472
540
  my $pEnd = 0;
473
541
 
@@ -610,6 +678,7 @@ sub ProcessM2TS($$)
610
678
  $buf2 = $data{$pid};
611
679
  $pos = 0;
612
680
  delete $data{$pid};
681
+ delete $fromStart{$pid};
613
682
  delete $sectLen{$pid};
614
683
  }
615
684
  my $slen = length($buf2); # section length
@@ -736,6 +805,7 @@ sub ProcessM2TS($$)
736
805
  my $more = ParsePID($et, $pid, $pidType{$pid}, $pidName{$pid}, \$data{$pid});
737
806
  # start fresh even if we couldn't process this PID yet
738
807
  delete $data{$pid};
808
+ delete $fromStart{$pid};
739
809
  unless ($more) {
740
810
  delete $needPID{$pid};
741
811
  $didPID{$pid} = 1;
@@ -749,8 +819,8 @@ sub ProcessM2TS($$)
749
819
  my $start_code = Get32u(\$buff, $pos);
750
820
  next unless ($start_code & 0xffffff00) == 0x00000100;
751
821
  my $stream_id = $start_code & 0xff;
822
+ my $pes_packet_length = Get16u(\$buff, $pos + 4);
752
823
  if ($verbose > 1) {
753
- my $pes_packet_length = Get16u(\$buff, $pos + 4);
754
824
  printf $out " Stream ID: 0x%.2x\n", $stream_id;
755
825
  print $out " Packet Len: $pes_packet_length\n";
756
826
  }
@@ -766,6 +836,14 @@ sub ProcessM2TS($$)
766
836
  next if $pos >= $pEnd;
767
837
  }
768
838
  $data{$pid} = substr($buff, $pos, $pEnd-$pos);
839
+ # set flag that we read this payload from the start
840
+ $fromStart{$pid} = 1;
841
+ # save the packet length
842
+ if ($pes_packet_length > 8) {
843
+ $packLen{$pid} = $pes_packet_length - 8; # (where are the 8 extra bytes? - PH)
844
+ } else {
845
+ delete $packLen{$pid};
846
+ }
769
847
  } else {
770
848
  unless (defined $data{$pid}) {
771
849
  # (vsys a6l dashcam GPS record doesn't have a start indicator)
@@ -776,12 +854,24 @@ sub ProcessM2TS($$)
776
854
  $data{$pid} .= substr($buff, $pos, $pEnd-$pos);
777
855
  }
778
856
  # save only the first 256 bytes of most streams, except for
779
- # unknown or H.264 streams where we save 1 kB
780
- my $saveLen = (not $pidType{$pid} or $pidType{$pid} == 0x1b) ? 1024 : 256;
857
+ # unknown, H.264 or metadata streams where we save up to 1 kB
858
+ my $saveLen;
859
+ if (not $pidType{$pid} or $pidType{$pid} == 0x1b) {
860
+ $saveLen = 1024;
861
+ } elsif ($pidType{$pid} == 0x15) {
862
+ # use 1024 or actual size of metadata packet if smaller
863
+ $saveLen = 1024;
864
+ $saveLen = $packLen{$pid} if defined $packLen{$pid} and $saveLen > $packLen{$pid};
865
+ } else {
866
+ $saveLen = 256;
867
+ }
781
868
  if (length($data{$pid}) >= $saveLen) {
782
869
  my $more = ParsePID($et, $pid, $pidType{$pid}, $pidName{$pid}, \$data{$pid});
783
870
  next if $more < 0; # wait for program map table (hopefully not too long)
871
+ # don't stop parsing if we weren't successful and may have missed the start
872
+ $more = 1 if not $more and not $fromStart{$pid};
784
873
  delete $data{$pid};
874
+ delete $fromStart{$pid};
785
875
  $more and $needPID{$pid} = -1, next; # parse more of these
786
876
  delete $needPID{$pid};
787
877
  $didPID{$pid} = 1;
@@ -14,7 +14,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
14
14
  use Image::ExifTool::Exif;
15
15
  use Image::ExifTool::GPS;
16
16
 
17
- $VERSION = '1.49';
17
+ $VERSION = '1.50';
18
18
 
19
19
  sub ProcessMIE($$);
20
20
  sub ProcessMIEGroup($$$);
@@ -448,6 +448,13 @@ my %offOn = ( 0 => 'Off', 1 => 'On' );
448
448
  Notes => 'string composed of R, G, B, Y, Cb and Cr',
449
449
  },
450
450
  Compression => { Name => 'CompressionRatio', Writable => 'rational32u' },
451
+ OriginalImageSize => { # PH added 2022-09-28
452
+ Writable => 'int16u',
453
+ Count => -1,
454
+ Notes => 'size of original image before cropping',
455
+ PrintConv => '$val=~tr/ /x/;$val',
456
+ PrintConvInv => '$val=~tr/x/ /;$val',
457
+ },
451
458
  ImageSize => {
452
459
  Writable => 'int16u',
453
460
  Count => -1,
@@ -1253,8 +1260,7 @@ sub WriteMIEGroup($$$)
1253
1260
  # join multiple values into a single string
1254
1261
  $newVal = join "\0", @newVals;
1255
1262
  # write string as UTF-8,16 or 32 if value contains valid UTF-8 codes
1256
- require Image::ExifTool::XMP;
1257
- my $isUTF8 = Image::ExifTool::XMP::IsUTF8(\$newVal);
1263
+ my $isUTF8 = Image::ExifTool::IsUTF8(\$newVal);
1258
1264
  if ($isUTF8 > 0) {
1259
1265
  $writable = 'utf8';
1260
1266
  # write UTF-16 or UTF-32 if it is more compact