exiftool_vendored 12.16.0 → 12.25.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +137 -1
  3. data/bin/MANIFEST +12 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +44 -43
  7. data/bin/config_files/acdsee.config +193 -6
  8. data/bin/config_files/cuepointlist.config +70 -0
  9. data/bin/config_files/example.config +1 -8
  10. data/bin/exiftool +139 -98
  11. data/bin/fmt_files/gpx.fmt +1 -1
  12. data/bin/fmt_files/gpx_wpt.fmt +1 -1
  13. data/bin/fmt_files/kml.fmt +1 -1
  14. data/bin/fmt_files/kml_track.fmt +1 -1
  15. data/bin/lib/Image/ExifTool.pm +158 -49
  16. data/bin/lib/Image/ExifTool.pod +94 -75
  17. data/bin/lib/Image/ExifTool/Apple.pm +3 -2
  18. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +25 -14
  19. data/bin/lib/Image/ExifTool/Canon.pm +28 -3
  20. data/bin/lib/Image/ExifTool/CanonCustom.pm +19 -1
  21. data/bin/lib/Image/ExifTool/DJI.pm +6 -6
  22. data/bin/lib/Image/ExifTool/DjVu.pm +6 -5
  23. data/bin/lib/Image/ExifTool/Exif.pm +50 -22
  24. data/bin/lib/Image/ExifTool/FITS.pm +13 -2
  25. data/bin/lib/Image/ExifTool/FujiFilm.pm +19 -8
  26. data/bin/lib/Image/ExifTool/GPS.pm +24 -13
  27. data/bin/lib/Image/ExifTool/H264.pm +20 -5
  28. data/bin/lib/Image/ExifTool/ICC_Profile.pm +2 -2
  29. data/bin/lib/Image/ExifTool/JPEG.pm +6 -2
  30. data/bin/lib/Image/ExifTool/JSON.pm +24 -3
  31. data/bin/lib/Image/ExifTool/Jpeg2000.pm +361 -16
  32. data/bin/lib/Image/ExifTool/M2TS.pm +40 -4
  33. data/bin/lib/Image/ExifTool/MIE.pm +2 -2
  34. data/bin/lib/Image/ExifTool/MRC.pm +341 -0
  35. data/bin/lib/Image/ExifTool/MWG.pm +3 -3
  36. data/bin/lib/Image/ExifTool/MXF.pm +1 -1
  37. data/bin/lib/Image/ExifTool/MacOS.pm +1 -1
  38. data/bin/lib/Image/ExifTool/Microsoft.pm +298 -82
  39. data/bin/lib/Image/ExifTool/Nikon.pm +5 -5
  40. data/bin/lib/Image/ExifTool/NikonSettings.pm +25 -16
  41. data/bin/lib/Image/ExifTool/Olympus.pm +2 -2
  42. data/bin/lib/Image/ExifTool/PNG.pm +2 -2
  43. data/bin/lib/Image/ExifTool/Panasonic.pm +14 -1
  44. data/bin/lib/Image/ExifTool/PhaseOne.pm +4 -3
  45. data/bin/lib/Image/ExifTool/QuickTime.pm +148 -68
  46. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +94 -34
  47. data/bin/lib/Image/ExifTool/README +5 -4
  48. data/bin/lib/Image/ExifTool/RIFF.pm +84 -12
  49. data/bin/lib/Image/ExifTool/Samsung.pm +2 -1
  50. data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -0
  51. data/bin/lib/Image/ExifTool/Sony.pm +157 -49
  52. data/bin/lib/Image/ExifTool/TagInfoXML.pm +1 -0
  53. data/bin/lib/Image/ExifTool/TagLookup.pm +4079 -3987
  54. data/bin/lib/Image/ExifTool/TagNames.pod +642 -273
  55. data/bin/lib/Image/ExifTool/WriteExif.pl +1 -1
  56. data/bin/lib/Image/ExifTool/WritePostScript.pl +1 -0
  57. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +44 -17
  58. data/bin/lib/Image/ExifTool/WriteXMP.pl +15 -8
  59. data/bin/lib/Image/ExifTool/Writer.pl +50 -14
  60. data/bin/lib/Image/ExifTool/XMP.pm +50 -11
  61. data/bin/perl-Image-ExifTool.spec +42 -42
  62. data/lib/exiftool_vendored/version.rb +1 -1
  63. metadata +52 -12
@@ -62,7 +62,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
62
62
  use Image::ExifTool::Exif;
63
63
  use Image::ExifTool::GPS;
64
64
 
65
- $VERSION = '3.92';
65
+ $VERSION = '3.95';
66
66
 
67
67
  sub LensIDConv($$$);
68
68
  sub ProcessNikonAVI($$$);
@@ -563,7 +563,7 @@ sub GetAFPointGrid($$;$);
563
563
  'F0 3F 2D 8A 2C 40 DF 0E' => 'Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD (B008)',
564
564
  'E0 40 2D 98 2C 41 DF 4E' => 'Tamron 18-400mm f/3.5-6.3 Di II VC HLD (B028)', # (removed AF designation, ref 37)
565
565
  '07 40 2F 44 2C 34 03 02' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
566
- '07 40 30 45 2D 35 03 02' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
566
+ '07 40 30 45 2D 35 03 02.1' => 'Tamron AF 19-35mm f/3.5-4.5 (A10)',
567
567
  '00 49 30 48 22 2B 00 02' => 'Tamron SP AF 20-40mm f/2.7-3.5 (166D)',
568
568
  '0E 4A 31 48 23 2D 0E 02' => 'Tamron SP AF 20-40mm f/2.7-3.5 (166D)',
569
569
  'FE 48 37 5C 24 24 DF 0E' => 'Tamron SP 24-70mm f/2.8 Di VC USD (A007)', #24
@@ -640,6 +640,7 @@ sub GetAFPointGrid($$;$);
640
640
  '24 44 60 98 34 3C 1A 02' => 'Tokina AT-X 840 AF-II (AF 80-400mm f/4.5-5.6)',
641
641
  '00 44 60 98 34 3C 00 02' => 'Tokina AT-X 840 D (AF 80-400mm f/4.5-5.6)',
642
642
  '14 48 68 8E 30 30 0B 00' => 'Tokina AT-X 340 AF (AF 100-300mm f/4)',
643
+ '8C 48 29 3C 24 24 86 06' => 'Tokina opera 16-28mm F2.8 FF', #30
643
644
  #
644
645
  '06 3F 68 68 2C 2C 06 00' => 'Cosina AF 100mm F3.5 Macro',
645
646
  '07 36 3D 5F 2C 3C 03 00' => 'Cosina AF Zoom 28-80mm F3.5-5.6 MC Macro',
@@ -655,6 +656,7 @@ sub GetAFPointGrid($$;$);
655
656
  '00 54 48 48 18 18 00 00' => 'Voigtlander Ultron 40mm F2 SLII Aspherical',
656
657
  '00 54 55 55 0C 0C 00 00' => 'Voigtlander Nokton 58mm F1.4 SLII',
657
658
  '00 40 64 64 2C 2C 00 00' => 'Voigtlander APO-Lanthar 90mm F3.5 SLII Close Focus',
659
+ '07 40 30 45 2D 35 03 02.2' => 'Voigtlander Ultragon 19-35mm F3.5-4.5 VMV', #NJ
658
660
  #
659
661
  '00 40 2D 2D 2C 2C 00 00' => 'Carl Zeiss Distagon T* 3.5/18 ZF.2',
660
662
  '00 48 27 27 24 24 00 00' => 'Carl Zeiss Distagon T* 2.8/15 ZF.2', #MykytaKozlov
@@ -9945,12 +9947,10 @@ sub PrescanExif($$$)
9945
9947
  $dataLen = length $data;
9946
9948
  $dirStart = 0;
9947
9949
  }
9948
- # loop through necessary IFD entries
9949
- my ($lastTag) = sort { $b <=> $a } keys %$tagHash; # (reverse sort)
9950
+ # loop through Nikon MakerNote IFD entries
9950
9951
  for ($index=0; $index<$numEntries; ++$index) {
9951
9952
  my $entry = $dirStart + 2 + 12 * $index;
9952
9953
  my $tagID = Get16u($dataPt, $entry);
9953
- last if $tagID > $lastTag; # (assuming tags are in order)
9954
9954
  next unless exists $$tagHash{$tagID}; # only extract required tags
9955
9955
  my $format = Get16u($dataPt, $entry+2);
9956
9956
  next if $format < 1 or $format > 13;
@@ -17,7 +17,7 @@ use strict;
17
17
  use vars qw($VERSION);
18
18
  use Image::ExifTool qw(:DataAccess :Utils);
19
19
 
20
- $VERSION = '1.00';
20
+ $VERSION = '1.03';
21
21
 
22
22
  sub ProcessNikonSettings($$$);
23
23
 
@@ -911,14 +911,14 @@ my %infoD6 = (
911
911
  },
912
912
  0x05a => [{ # CSf6-b-1 and CSf6-b-2 (D6), CSf5-b-1 and CSf5-b-2 (Z7_2), (continued from above)
913
913
  Name => 'CmdDialsChangeMainSub',
914
- Condition => '$$self{CmdDialsChangeMainSubExposure} == 1',
914
+ Condition => '$$self{CmdDialsChangeMainSubExposure} and $$self{CmdDialsChangeMainSubExposure} == 1',
915
915
  PrintConv => {
916
916
  1 => 'Autofocus On, Exposure On',
917
917
  2 => 'Autofocus Off, Exposure On',
918
918
  },
919
919
  },{
920
920
  Name => 'CmdDialsChangeMainSub',
921
- Condition => '$$self{CmdDialsChangeMainSubExposure} == 2',
921
+ Condition => '$$self{CmdDialsChangeMainSubExposure} and $$self{CmdDialsChangeMainSubExposure} == 2',
922
922
  PrintConv => {
923
923
  1 => 'Autofocus On, Exposure On (Mode A)',
924
924
  2 => 'Autofocus Off, Exposure On (Mode A)',
@@ -1014,7 +1014,7 @@ my %infoD6 = (
1014
1014
  }],
1015
1015
  0x08b => [{ # CSf6-a-1 and CSf6-a-2 (D6), CSf5-a-1 and CSf5-a-2 (Z7_2), (continued from above)
1016
1016
  Name => 'CmdDialsReverseRotation',
1017
- Condition => '$$self{CmdDialsReverseRotExposureComp} == 1',
1017
+ Condition => '$$self{CmdDialsReverseRotExposureComp} and $$self{CmdDialsReverseRotExposureComp} == 1',
1018
1018
  PrintConv => {
1019
1019
  1 => 'No',
1020
1020
  2 => 'Shutter Speed & Aperture',
@@ -1283,7 +1283,7 @@ my %infoD6 = (
1283
1283
  PrintConv => {
1284
1284
  1 => 'Enable',
1285
1285
  2 => 'Enable (Standby Timer Active)',
1286
- 3 => 'Diaable',
1286
+ 3 => 'Disable',
1287
1287
  },
1288
1288
  },
1289
1289
  0x0ab => { # CSf11 (D6)
@@ -1313,7 +1313,7 @@ my %infoD6 = (
1313
1313
  1 => 'Power Aperture (Open)',
1314
1314
  2 => 'Exposure Compensation',
1315
1315
  3 => 'Subject Tracking',
1316
- 4 => 'LiveView Info Display On/Off)',
1316
+ 4 => 'LiveView Info Display On/Off',
1317
1317
  5 => 'Grid Display',
1318
1318
  6 => 'Zoom (Low)',
1319
1319
  7 => 'Zoom (1:1)',
@@ -1357,7 +1357,7 @@ my %infoD6 = (
1357
1357
  1 => 'Power Aperture (Close)',
1358
1358
  2 => 'Exposure Compensation',
1359
1359
  3 => 'Subject Tracking',
1360
- 4 => 'LiveView Info Display On/Off)',
1360
+ 4 => 'LiveView Info Display On/Off',
1361
1361
  5 => 'Grid Display',
1362
1362
  6 => 'Zoom (Low)',
1363
1363
  7 => 'Zoom (1:1)',
@@ -1545,10 +1545,10 @@ my %infoD6 = (
1545
1545
  12 => 'None',
1546
1546
  },
1547
1547
  },
1548
- 0x0fb => { Name => 'SecondarySlotFunction', PrintConv => \%tagSecondarySlotFunction }, # tag name selected to maintain compatibility with older cameras # (Z7_2)
1549
- 0x0fb => { Name => 'SecondarySlotFunction', PrintConv => \%tagSecondarySlotFunction }, # (D6)
1550
- 0x0fc => { Name => 'SilentPhotography', PrintConv => \%onOff }, # (D6,Z7_2) # tag is associated with Silent LiveView Photography (as distinguisehed from Silent Interval or Silent Focus Shift)
1551
- 0x0fd => { Name => 'ExtendedShuttterSpeeds', PrintConv => \%onOff }, # CSd7 (D6), CSd6 (Z7_2)
1548
+ 0x0fb => { Name => 'SecondarySlotFunction', PrintConv => \%tagSecondarySlotFunction }, # tag name selected to maintain compatibility with older cameras # (Z7_2)
1549
+ 0x0fb => { Name => 'SecondarySlotFunction', PrintConv => \%tagSecondarySlotFunction }, # (D6)
1550
+ 0x0fc => { Name => 'SilentPhotography', PrintConv => \%onOff }, # (D6,Z7_2) # tag is associated with Silent LiveView Photography (as distinguisehed from Silent Interval or Silent Focus Shift)
1551
+ 0x0fd => { Name => 'ExtendedShutterSpeeds', PrintConv => \%onOff }, # CSd7 (D6), CSd6 (Z7_2)
1552
1552
  0x109 => { # (D6,Z7_2)
1553
1553
  Name => 'BracketSet',
1554
1554
  RawConv => '$$self{BracketSet} = $val',
@@ -1578,7 +1578,7 @@ my %infoD6 = (
1578
1578
  },
1579
1579
  },{
1580
1580
  Name => 'BracketProgram',
1581
- Condition => '$$self{BracketSet} == 4',
1581
+ Condition => '$$self{BracketSet} and $$self{BracketSet} == 4',
1582
1582
  Notes => 'White Balance Bracketing',
1583
1583
  RawConv => '$$self{BracketProgram} = $val',
1584
1584
  PrintConv => {
@@ -1595,7 +1595,7 @@ my %infoD6 = (
1595
1595
  },
1596
1596
  },{
1597
1597
  Name => 'BracketProgram',
1598
- Condition => '$$self{BracketSet} == 5',
1598
+ Condition => '$$self{BracketSet} and $$self{BracketSet} == 5',
1599
1599
  Notes => 'Active-D Bracketing',
1600
1600
  RawConv => '$$self{BracketProgram} = $val',
1601
1601
  Mask => 0x0f,
@@ -1802,9 +1802,9 @@ my %infoD6 = (
1802
1802
  },
1803
1803
  },
1804
1804
  0x139 => { Name => 'PlaybackFlickUp', RawConv => '$$self{PlaybackFlickUp} = $val', PrintConv => \%flickUpDownD6 }, # CSf12-1-a # (D6)
1805
- 0x13a => { Name => 'PlaybackFlickUpRating', Condition => '$$self{PlaybackFlickUp} == 1', Notes => 'Meaningful only when PlaybackFlickUp is Rating', PrintConv => \%flickUpDownRatingD6 }, # CSf12-1-b # (D6)
1805
+ 0x13a => { Name => 'PlaybackFlickUpRating', Condition => '$$self{PlaybackFlickUp} and $$self{PlaybackFlickUp} == 1', Notes => 'Meaningful only when PlaybackFlickUp is Rating', PrintConv => \%flickUpDownRatingD6 }, # CSf12-1-b # (D6)
1806
1806
  0x13b => { Name => 'PlaybackFlickDown', RawConv => '$$self{PlaybackFlickDown} = $val', PrintConv => \%flickUpDownD6 }, # CSf12-2-a # (D6)
1807
- 0x13c => { Name => 'PlaybackFlickDownRating', Condition => '$$self{PlaybackFlickDown} == 1', Notes => 'Meaningful only when PlaybackFlickDown is Rating', PrintConv => \%flickUpDownRatingD6 }, # CSf12-2-b # (D6)
1807
+ 0x13c => { Name => 'PlaybackFlickDownRating', Condition => '$$self{PlaybackFlickDown} and $$self{PlaybackFlickDown} == 1', Notes => 'Meaningful only when PlaybackFlickDown is Rating', PrintConv => \%flickUpDownRatingD6 }, # CSf12-2-b # (D6)
1808
1808
  0x13d => { # CSg2-d (D6)
1809
1809
  Name => 'MovieFunc3Button',
1810
1810
  PrintConv => {
@@ -1875,7 +1875,7 @@ my %infoD6 = (
1875
1875
  0x164 => { # CSg7-a (Z7_2)
1876
1876
  Name => 'VerticalMovieFuncButton',
1877
1877
  PrintConv => {
1878
- 1 => 'LiveView Info Display On/Off)',
1878
+ 1 => 'LiveView Info Display On/Off',
1879
1879
  2 => 'Record Movies',
1880
1880
  3 => 'Exposure Compensation',
1881
1881
  4 => 'ISO',
@@ -1919,6 +1919,15 @@ my %infoD6 = (
1919
1919
  10 => 'Auto (Animals)',
1920
1920
  },
1921
1921
  },
1922
+ 0x170 => { Name => 'PreferSubSelectorCenter', PrintConv => \%offOn }, # CSf13 (D6 firmware v1.2.0)
1923
+ 0x174 => { # CSa17-d (D6 firmware v1.2.0)
1924
+ Name => 'FocusPointSelectionSpeed',
1925
+ PrintConv => {
1926
+ 1 => 'Normal',
1927
+ 2 => 'High',
1928
+ 3 => 'Very High',
1929
+ },
1930
+ },
1922
1931
  );
1923
1932
 
1924
1933
  #------------------------------------------------------------------------------
@@ -40,7 +40,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
40
40
  use Image::ExifTool::Exif;
41
41
  use Image::ExifTool::APP12;
42
42
 
43
- $VERSION = '2.70';
43
+ $VERSION = '2.71';
44
44
 
45
45
  sub PrintLensInfo($$$);
46
46
 
@@ -3952,7 +3952,7 @@ my %indexInfo = (
3952
3952
  1 => 'LensTypeModel',
3953
3953
  },
3954
3954
  Notes => 'based on tags found in some Panasonic RW2 images',
3955
- SeparateTable => 'LensType',
3955
+ SeparateTable => 'Olympus LensType',
3956
3956
  ValueConv => '"$val[0] $val[1]"',
3957
3957
  PrintConv => \%olympusLensTypes,
3958
3958
  },
@@ -36,7 +36,7 @@ use strict;
36
36
  use vars qw($VERSION $AUTOLOAD %stdCase);
37
37
  use Image::ExifTool qw(:DataAccess :Utils);
38
38
 
39
- $VERSION = '1.56';
39
+ $VERSION = '1.57';
40
40
 
41
41
  sub ProcessPNG_tEXt($$$);
42
42
  sub ProcessPNG_iTXt($$$);
@@ -975,7 +975,7 @@ sub FoundPNG($$$$;$$$$)
975
975
  $$tagInfo{LangCode} = $lang if $lang;
976
976
  # make unknown profiles binary data type
977
977
  $$tagInfo{Binary} = 1 if $tag =~ /^Raw profile type /;
978
- $verbose and $et->VPrint(0, " | [adding $tag]\n");
978
+ $verbose and $et->VPrint(0, " [adding $tag]\n");
979
979
  AddTagToTable($tagTablePtr, $tag, $tagInfo);
980
980
  }
981
981
  #
@@ -2118,6 +2118,7 @@ my %shootingMode = (
2118
2118
  Name => 'UserProfile',
2119
2119
  Writable => 'string',
2120
2120
  },
2121
+ # 0x357 int32u - 0=DNG, 3162=JPG (ref 23)
2121
2122
  0x359 => { #23
2122
2123
  Name => 'ISOSelected',
2123
2124
  Writable => 'int32s',
@@ -2134,7 +2135,19 @@ my %shootingMode = (
2134
2135
  PrintConv => 'sprintf("%.1f", $val)',
2135
2136
  PrintConvInv => '$val',
2136
2137
  },
2137
- # 0x357 int32u - 0=DNG, 3162=JPG (ref 23)
2138
+ 0x035b => { #IB
2139
+ Name => 'CorrelatedColorTemp', # (in Kelvin)
2140
+ Writable => 'int16u',
2141
+ },
2142
+ 0x035c => { #IB
2143
+ Name => 'ColorTint', # (same units as Adobe is using)
2144
+ Writable => 'int16s',
2145
+ },
2146
+ 0x035d => { #IB
2147
+ Name => 'WhitePoint', # (x/y)
2148
+ Writable => 'rational64u',
2149
+ Count => 2,
2150
+ },
2138
2151
  );
2139
2152
 
2140
2153
  # Type 2 tags (ref PH)
@@ -15,7 +15,7 @@ use vars qw($VERSION);
15
15
  use Image::ExifTool qw(:DataAccess :Utils);
16
16
  use Image::ExifTool::Exif;
17
17
 
18
- $VERSION = '1.06';
18
+ $VERSION = '1.07';
19
19
 
20
20
  sub WritePhaseOne($$$);
21
21
  sub ProcessPhaseOne($$$);
@@ -73,10 +73,11 @@ my @formatName = ( undef, 'string', 'int16s', undef, 'int32s' );
73
73
  PrintConv => { #PH
74
74
  1 => 'RAW 1', #? (encrypted)
75
75
  2 => 'RAW 2', #? (encrypted)
76
- 3 => 'IIQ L',
76
+ 3 => 'IIQ L', # (now "L14", ref IB)
77
77
  # 4?
78
78
  5 => 'IIQ S',
79
- 6 => 'IIQ Sv2',
79
+ 6 => 'IIQ Sv2', # (now "S14" for "IIQ 14 Smart" and "IIQ 14 Sensor+", ref IB)
80
+ 8 => 'IIQ L16', #IB ("IIQ 16 Extended" and "IIQ 16 Large")
80
81
  },
81
82
  },
82
83
  0x010f => {
@@ -47,7 +47,7 @@ use Image::ExifTool qw(:DataAccess :Utils);
47
47
  use Image::ExifTool::Exif;
48
48
  use Image::ExifTool::GPS;
49
49
 
50
- $VERSION = '2.57';
50
+ $VERSION = '2.63';
51
51
 
52
52
  sub ProcessMOV($$;$);
53
53
  sub ProcessKeys($$$);
@@ -65,6 +65,7 @@ sub Process_gsen($$$);
65
65
  sub ProcessRIFFTrailer($$$);
66
66
  sub ProcessTTAD($$$);
67
67
  sub ProcessNMEA($$$);
68
+ sub ProcessGPSLog($$$);
68
69
  sub SaveMetaKeys($$$);
69
70
  # ++^^^^^^^^^^^^++
70
71
  sub ParseItemLocation($$);
@@ -160,8 +161,15 @@ my %ftypLookup = (
160
161
  'F4P ' => 'Protected Video for Adobe Flash Player 9+ (.F4P)', # video/mp4
161
162
  'F4V ' => 'Video for Adobe Flash Player 9+ (.F4V)', # video/mp4
162
163
  'isc2' => 'ISMACryp 2.0 Encrypted File', # ?/enc-isoff-generic
163
- 'iso2' => 'MP4 Base Media v2 [ISO 14496-12:2005]', # video/mp4
164
- 'isom' => 'MP4 Base Media v1 [IS0 14496-12:2003]', # video/mp4
164
+ 'iso2' => 'MP4 Base Media v2 [ISO 14496-12:2005]', # video/mp4 (or audio)
165
+ 'iso3' => 'MP4 Base Media v3', # video/mp4 (or audio)
166
+ 'iso4' => 'MP4 Base Media v4', # video/mp4 (or audio)
167
+ 'iso5' => 'MP4 Base Media v5', # video/mp4 (or audio)
168
+ 'iso6' => 'MP4 Base Media v6', # video/mp4 (or audio)
169
+ 'iso7' => 'MP4 Base Media v7', # video/mp4 (or audio)
170
+ 'iso8' => 'MP4 Base Media v8', # video/mp4 (or audio)
171
+ 'iso9' => 'MP4 Base Media v9', # video/mp4 (or audio)
172
+ 'isom' => 'MP4 Base Media v1 [IS0 14496-12:2003]', # video/mp4 (or audio)
165
173
  'JP2 ' => 'JPEG 2000 Image (.JP2) [ISO 15444-1 ?]', # image/jp2
166
174
  'JP20' => 'Unknown, from GPAC samples (prob non-existent)',
167
175
  'jpm ' => 'JPEG 2000 Compound Image (.JPM) [ISO 15444-6]', # image/jpm
@@ -243,7 +251,11 @@ my %timeInfo = (
243
251
  },
244
252
  # (all CR3 files store UTC times - PH)
245
253
  ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC") || $$self{FileType} eq "CR3")',
246
- ValueConvInv => 'GetUnixTime($val, $self->Options("QuickTimeUTC")) + (66 * 365 + 17) * 24 * 3600',
254
+ ValueConvInv => q{
255
+ $val = GetUnixTime($val, $self->Options("QuickTimeUTC"));
256
+ return undef unless defined $val;
257
+ return $val + (66 * 365 + 17) * 24 * 3600;
258
+ },
247
259
  PrintConv => '$self->ConvertDateTime($val)',
248
260
  PrintConvInv => '$self->InverseDateTime($val)',
249
261
  # (can't put Groups here because they aren't constant!)
@@ -258,11 +270,15 @@ my %unknownInfo = (
258
270
  Unknown => 1,
259
271
  ValueConv => '$val =~ /^([\x20-\x7e]*)\0*$/ ? $1 : \$val',
260
272
  );
273
+
274
+ # multi-language text with 6-byte header
275
+ my %langText = ( IText => 6 );
276
+
261
277
  # parsing for most of the 3gp udta language text boxes
262
- my %langText = (
278
+ my %langText3gp = (
263
279
  Notes => 'used in 3gp videos',
264
- IText => 6,
265
280
  Avoid => 1,
281
+ IText => 6,
266
282
  );
267
283
 
268
284
  # 4-character Vendor ID codes (ref PH)
@@ -670,6 +686,15 @@ my %eeBox2 = (
670
686
  udat => { #PH (GPS NMEA-format log written by Datakam Player software)
671
687
  Name => 'GPSLog',
672
688
  Binary => 1, # (actually ASCII, but very lengthy)
689
+ Notes => 'parsed to extract GPS separately when ExtractEmbedded is used',
690
+ RawConv => q{
691
+ $val =~ s/\0+$//; # remove trailing nulls
692
+ if (length $val and $$self{OPTIONS}{ExtractEmbedded}) {
693
+ my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
694
+ Image::ExifTool::QuickTime::ProcessGPSLog($self, { DataPt => \$val }, $tagTbl);
695
+ }
696
+ return $val;
697
+ },
673
698
  },
674
699
  # meta - proprietary XML information written by some Flip cameras - PH
675
700
  # beam - 16 bytes found in an iPhone video
@@ -1545,47 +1570,43 @@ my %eeBox2 = (
1545
1570
  # the following are 3gp tags, references:
1546
1571
  # http://atomicparsley.sourceforge.net
1547
1572
  # http://www.3gpp.org/ftp/tsg_sa/WG4_CODEC/TSGS4_25/Docs/
1548
- # (note that all %langText tags are Avoid => 1)
1549
- cprt => { Name => 'Copyright', %langText, Groups => { 2 => 'Author' } },
1550
- auth => { Name => 'Author', %langText, Groups => { 2 => 'Author' } },
1551
- titl => { Name => 'Title', %langText },
1552
- dscp => { Name => 'Description',%langText },
1553
- perf => { Name => 'Performer', %langText },
1554
- gnre => { Name => 'Genre', %langText },
1555
- albm => { Name => 'Album', %langText },
1556
- coll => { Name => 'CollectionName', %langText }, #17
1573
+ # (note that all %langText3gp tags are Avoid => 1)
1574
+ cprt => { Name => 'Copyright', %langText3gp, Groups => { 2 => 'Author' } },
1575
+ auth => { Name => 'Author', %langText3gp, Groups => { 2 => 'Author' } },
1576
+ titl => { Name => 'Title', %langText3gp },
1577
+ dscp => { Name => 'Description',%langText3gp },
1578
+ perf => { Name => 'Performer', %langText3gp },
1579
+ gnre => { Name => 'Genre', %langText3gp },
1580
+ albm => { Name => 'Album', %langText3gp },
1581
+ coll => { Name => 'CollectionName', %langText3gp }, #17
1557
1582
  rtng => {
1558
1583
  Name => 'Rating',
1584
+ Writable => 'undef',
1585
+ Avoid => 1,
1559
1586
  # (4-byte flags, 4-char entity, 4-char criteria, 2-byte lang, string)
1560
- RawConv => q{
1561
- return '<err>' unless length $val >= 14;
1562
- my $str = 'Entity=' . substr($val,4,4) . ' Criteria=' . substr($val,8,4);
1563
- $str =~ tr/\0-\x1f\x7f-\xff//d; # remove unprintable characters
1564
- my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 12));
1565
- $lang = $lang ? "($lang) " : '';
1566
- $val = substr($val, 14);
1567
- $val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/;
1568
- return $lang . $str . ' ' . $val;
1569
- },
1587
+ IText => 14, # (14 bytes before string)
1588
+ Notes => 'string in the form "Entity=XXXX Criteria=XXXX XXXXX", used in 3gp videos',
1589
+ ValueConv => '$val=~s/^(.{4})(.{4})/Entity=$1 Criteria=$2 /i; $val',
1590
+ ValueConvInv => '$val=~s/Entity=(.{4}) Criteria=(.{4}) ?/$1$2/i; $val',
1570
1591
  },
1571
1592
  clsf => {
1572
1593
  Name => 'Classification',
1594
+ Writable => 'undef',
1595
+ Avoid => 1,
1573
1596
  # (4-byte flags, 4-char entity, 2-byte index, 2-byte lang, string)
1574
- RawConv => q{
1575
- return '<err>' unless length $val >= 12;
1576
- my $str = 'Entity=' . substr($val,4,4) . ' Index=' . Get16u(\$val,8);
1577
- $str =~ tr/\0-\x1f\x7f-\xff//d; # remove unprintable characters
1578
- my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 10));
1579
- $lang = $lang ? "($lang) " : '';
1580
- $val = substr($val, 12);
1581
- $val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/;
1582
- return $lang . $str . ' ' . $val;
1583
- },
1597
+ IText => 12,
1598
+ Notes => 'string in the form "Entity=XXXX Index=### XXXXX", used in 3gp videos',
1599
+ ValueConv => '$val=~s/^(.{4})(.{2})/"Entity=$1 Index=".unpack("n",$2)." "/ie; $val',
1600
+ ValueConvInv => '$val=~s/Entity=(.{4}) Index=(\d+) ?/$1.pack("n",$2)/ie; $val',
1584
1601
  },
1585
1602
  kywd => {
1586
1603
  Name => 'Keywords',
1587
- # (4 byte flags, 2-byte lang, 1-byte count, count x pascal strings)
1604
+ # (4 byte flags, 2-byte lang, 1-byte count, count x pascal strings, ref 17)
1605
+ # (but I have also seen a simple string written by iPhone, so don't make writable yet)
1606
+ Notes => "not writable because Apple doesn't follow the 3gp specification",
1588
1607
  RawConv => q{
1608
+ my $sep = $self->Options('ListSep');
1609
+ return join($sep, split /\0+/, $val) unless $val =~ /^\0/; # (iPhone)
1589
1610
  return '<err>' unless length $val >= 7;
1590
1611
  my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4));
1591
1612
  $lang = $lang ? "($lang) " : '';
@@ -1601,27 +1622,30 @@ my %eeBox2 = (
1601
1622
  push @vals, $v;
1602
1623
  $pos += $len;
1603
1624
  }
1604
- my $sep = $self->Options('ListSep');
1605
1625
  return $lang . join($sep, @vals);
1606
1626
  },
1607
1627
  },
1608
1628
  loci => {
1609
1629
  Name => 'LocationInformation',
1610
1630
  Groups => { 2 => 'Location' },
1631
+ Writable => 'undef',
1632
+ IText => 6,
1633
+ Avoid => 1,
1634
+ NoDecode => 1, # (we'll decode the data ourself)
1635
+ Notes => q{
1636
+ string in the form "XXXXX Role=XXX Lat=XXX Lon=XXX Alt=XXX Body=XXX
1637
+ Notes=XXX", used in 3gp videos
1638
+ },
1611
1639
  # (4-byte flags, 2-byte lang, location string, 1-byte role, 4-byte fixed longitude,
1612
1640
  # 4-byte fixed latitude, 4-byte fixed altitude, body string, notes string)
1613
1641
  RawConv => q{
1614
- return '<err>' unless length $val >= 6;
1615
- my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4));
1616
- $lang = $lang ? "($lang) " : '';
1617
- $val = substr($val, 6);
1618
1642
  my $str;
1619
1643
  if ($val =~ /^\xfe\xff/) {
1620
1644
  $val =~ s/^(\xfe\xff(.{2})*?)\0\0//s or return '<err>';
1621
1645
  $str = $self->Decode($1, 'UCS2');
1622
1646
  } else {
1623
1647
  $val =~ s/^(.*?)\0//s or return '<err>';
1624
- $str = $1;
1648
+ $str = $self->Decode($1, 'UTF8');
1625
1649
  }
1626
1650
  $str = '(none)' unless length $str;
1627
1651
  return '<err>' if length $val < 13;
@@ -1636,27 +1660,52 @@ my %eeBox2 = (
1636
1660
  if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) {
1637
1661
  $str .= ' Body=' . $self->Decode($1, 'UCS2');
1638
1662
  } elsif ($val =~ s/^(.*?)\0//s) {
1639
- $str .= " Body=$1";
1663
+ $str .= ' Body=' . $self->Decode($1, 'UTF8');
1640
1664
  }
1641
1665
  if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) {
1642
1666
  $str .= ' Notes=' . $self->Decode($1, 'UCS2');
1643
1667
  } elsif ($val =~ s/^(.*?)\0//s) {
1644
- $str .= " Notes=$1";
1668
+ $str .= ' Notes=' . $self->Decode($1, 'UTF8');
1645
1669
  }
1646
- return $lang . $str;
1670
+ return $str;
1671
+ },
1672
+ RawConvInv => q{
1673
+ my ($role, $lat, $lon, $alt, $body, $note);
1674
+ $lat = $1 if $val =~ s/ Lat=([-+]?[.\d]+)//i;
1675
+ $lon = $1 if $val =~ s/ Lon=([-+]?[.\d]+)//i;
1676
+ $alt = $1 if $val =~ s/ Alt=([-+]?[.\d]+)//i;
1677
+ $note = $val =~ s/ Notes=(.*)//i ? $1 : '';
1678
+ $body = $val =~ s/ Body=(.*)//i ? $1 : '';
1679
+ $role = $val =~ s/ Role=(.*)//i ? $1 : '';
1680
+ $val = '' if $val eq '(none)';
1681
+ $role = {shooting=>0,real=>1,fictional=>2}->{lc $role} || 0;
1682
+ return $self->Encode($val, 'UTF8') . "\0" . Set8u($role) .
1683
+ SetFixed32s(defined $lon ? $lon : 999) .
1684
+ SetFixed32s(defined $lat ? $lat : 999) .
1685
+ SetFixed32s(defined $alt ? $alt : 0) .
1686
+ $self->Encode($body) . "\0" .
1687
+ $self->Encode($note) . "\0";
1647
1688
  },
1648
1689
  },
1649
1690
  yrrc => {
1650
1691
  Name => 'Year',
1692
+ Writable => 'undef',
1651
1693
  Groups => { 2 => 'Time' },
1652
- RawConv => 'length($val) >= 6 ? Get16u(\$val,4) : "<err>"',
1694
+ Avoid => 1,
1695
+ Notes => 'used in 3gp videos',
1696
+ ValueConv => 'length($val) >= 6 ? unpack("x4n",$val) : "<err>"',
1697
+ ValueConvInv => 'pack("Nn",0,$val)',
1653
1698
  },
1654
1699
  urat => { #17
1655
1700
  Name => 'UserRating',
1656
- RawConv => q{
1701
+ Writable => 'undef',
1702
+ Notes => 'used in 3gp videos',
1703
+ Avoid => 1,
1704
+ ValueConv => q{
1657
1705
  return '<err>' unless length $val >= 8;
1658
- return Get8u(\$val, 7);
1706
+ unpack('x7C', $val);
1659
1707
  },
1708
+ ValueConvInv => 'pack("N2",0,$val)',
1660
1709
  },
1661
1710
  # tsel - TrackSelection (ref 17)
1662
1711
  # Apple tags (ref 16[dead] -- see ref 25 instead)
@@ -1988,7 +2037,11 @@ my %eeBox2 = (
1988
2037
  # ---- Microsoft ----
1989
2038
  Xtra => { #PH (microsoft)
1990
2039
  Name => 'MicrosoftXtra',
1991
- SubDirectory => { TagTable => 'Image::ExifTool::Microsoft::Xtra' },
2040
+ WriteGroup => 'Microsoft',
2041
+ SubDirectory => {
2042
+ DirName => 'Microsoft',
2043
+ TagTable => 'Image::ExifTool::Microsoft::Xtra',
2044
+ },
1992
2045
  },
1993
2046
  # ---- Minolta ----
1994
2047
  MMA0 => { #PH (DiMage 7Hi)
@@ -2037,7 +2090,7 @@ my %eeBox2 = (
2037
2090
  SubDirectory => { TagTable => 'Image::ExifTool::Olympus::thmb' },
2038
2091
  },{ #17 (format is in bytes 3-7)
2039
2092
  Name => 'ThumbnailImage',
2040
- Condition => '$$valPt =~ /^.{8}\xff\xd8\xff\xdb/s',
2093
+ Condition => '$$valPt =~ /^.{8}\xff\xd8\xff[\xdb\xe0]/s',
2041
2094
  Groups => { 2 => 'Preview' },
2042
2095
  RawConv => 'substr($val, 8)',
2043
2096
  Binary => 1,
@@ -2994,9 +3047,9 @@ my %eeBox2 = (
2994
3047
  3-character ISO 639-2 language code and an optional ISO 3166-1 alpha 2
2995
3048
  country code to the tag name (eg. "ItemList:Title-fra" or
2996
3049
  "ItemList::Title-fra-FR"). When creating a new Meta box to contain the
2997
- ItemList directory, by default ExifTool does not specify a
2998
- L<Handler|Image::ExifTool::TagNames/QuickTime Handler Tags>, but the
2999
- API L<QuickTimeHandler|../ExifTool.html#QuickTimeHandler> option may be used to include an 'mdir' Handler box.
3050
+ ItemList directory, by default ExifTool adds an 'mdir' (Metadata) Handler
3051
+ box because Apple software may ignore ItemList tags otherwise, but the API
3052
+ L<QuickTimeHandler|../ExifTool.html#QuickTimeHandler> option may be set to 0 to avoid this.
3000
3053
  },
3001
3054
  # in this table, binary 1 and 2-byte "data"-type tags are interpreted as
3002
3055
  # int8u and int16u. Multi-byte binary "data" tags are extracted as binary data.
@@ -6157,13 +6210,12 @@ my %eeBox2 = (
6157
6210
  PROCESS_PROC => \&ProcessKeys,
6158
6211
  WRITE_PROC => \&WriteKeys,
6159
6212
  CHECK_PROC => \&CheckQTValue,
6160
- VARS => { LONG_TAGS => 3 },
6213
+ VARS => { LONG_TAGS => 7 },
6161
6214
  WRITABLE => 1,
6162
6215
  # (not PREFERRED when writing)
6163
6216
  GROUPS => { 1 => 'Keys' },
6164
6217
  WRITE_GROUP => 'Keys',
6165
6218
  LANG_INFO => \&GetLangInfo,
6166
- FORMAT => 'string',
6167
6219
  NOTES => q{
6168
6220
  This directory contains a list of key names which are used to decode tags
6169
6221
  written by the "mdta" handler. Also in this table are a few tags found in
@@ -6265,6 +6317,11 @@ my %eeBox2 = (
6265
6317
  PrintConv => '$self->ConvertDateTime($val)',
6266
6318
  PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
6267
6319
  },
6320
+ 'location.accuracy.horizontal' => { Name => 'LocationAccuracyHorizontal' },
6321
+ 'live-photo.auto' => { Name => 'LivePhotoAuto', Writable => 'int8u' },
6322
+ 'live-photo.vitality-score' => { Name => 'LivePhotoVitalityScore', Writable => 'float' },
6323
+ 'live-photo.vitality-scoring-version' => { Name => 'LivePhotoVitalityScoringVersion', Writable => 'int64s' },
6324
+ 'apple.photos.variation-identifier' => { Name => 'ApplePhotosVariationIdentifier', Writable => 'int64s' },
6268
6325
  'direction.facing' => { Name => 'CameraDirection', Groups => { 2 => 'Location' } },
6269
6326
  'direction.motion' => { Name => 'CameraMotion', Groups => { 2 => 'Location' } },
6270
6327
  'location.body' => { Name => 'LocationBody', Groups => { 2 => 'Location' } },
@@ -6300,11 +6357,15 @@ my %eeBox2 = (
6300
6357
  # com.divergentmedia.clipwrap.manufacturer ('Sony')
6301
6358
  # com.divergentmedia.clipwrap.originalDateTime ('2013/2/6 10:30:40+0200')
6302
6359
  #
6303
- # seen in timed metadata (mebx), and added dynamically to the table
6304
- # via SaveMetaKeys(). NOTE: these tags are not writable!
6360
+ # seen in timed metadata (mebx), and added dynamically to the table via SaveMetaKeys()
6361
+ # NOTE: these tags are not writable! (timed metadata cannot yet be written)
6305
6362
  #
6306
6363
  # (mdta)com.apple.quicktime.video-orientation (dtyp=66, int16s)
6307
- 'video-orientation' => { Name => 'VideoOrientation', Writable => 0 },
6364
+ 'video-orientation' => {
6365
+ Name => 'VideoOrientation',
6366
+ Writable => 0,
6367
+ PrintConv => \%Image::ExifTool::Exif::orientation, #PH (NC)
6368
+ },
6308
6369
  # (mdta)com.apple.quicktime.live-photo-info (dtyp=com.apple.quicktime.com.apple.quicktime.live-photo-info)
6309
6370
  'live-photo-info' => {
6310
6371
  Name => 'LivePhotoInfo',
@@ -7589,7 +7650,11 @@ my %eeBox2 = (
7589
7650
  8 => {
7590
7651
  Name => 'HandlerType',
7591
7652
  Format => 'undef[4]',
7592
- RawConv => '$$self{HandlerType} = $val unless $val eq "alis" or $val eq "url "; $val',
7653
+ RawConv => q{
7654
+ $$self{HandlerType} = $val unless $val eq 'alis' or $val eq 'url ';
7655
+ $$self{HasHandler}{$val} = 1; # remember all our handlers
7656
+ return $val;
7657
+ },
7593
7658
  PrintConvColumns => 2,
7594
7659
  PrintConv => {
7595
7660
  alis => 'Alias Data', #PH
@@ -7694,7 +7759,7 @@ my %eeBox2 = (
7694
7759
  $val =~ s/\0+$//; # remove trailing nulls
7695
7760
  if (length $val and $$self{OPTIONS}{ExtractEmbedded}) {
7696
7761
  my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
7697
- Image::ExifTool::QuickTime::ProcessNMEA($self, { DataPt => \$val }, $tagTbl);
7762
+ Image::ExifTool::QuickTime::ProcessGPSLog($self, { DataPt => \$val }, $tagTbl);
7698
7763
  }
7699
7764
  return $val;
7700
7765
  },
@@ -8574,7 +8639,7 @@ sub QuickTimeFormat($$)
8574
8639
  my ($flags, $len) = @_;
8575
8640
  my $format;
8576
8641
  if ($flags == 0x15 or $flags == 0x16) {
8577
- $format = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len};
8642
+ $format = { 1=>'int8', 2=>'int16', 4=>'int32', 8=>'int64' }->{$len};
8578
8643
  $format .= $flags == 0x15 ? 's' : 'u' if $format;
8579
8644
  } elsif ($flags == 0x17) {
8580
8645
  $format = 'float';
@@ -8927,6 +8992,7 @@ sub ProcessMOV($$;$)
8927
8992
  if ($raf->Read($buff, $size-8) == $size-8) {
8928
8993
  $raf->Seek(-($size-8), 1);
8929
8994
  my $type = substr($buff, 0, 4);
8995
+ $$et{save_ftyp} = $type;
8930
8996
  # see if we know the extension for this file type
8931
8997
  if ($ftypLookup{$type} and $ftypLookup{$type} =~ /\(\.(\w+)/) {
8932
8998
  $fileType = $1;
@@ -9350,9 +9416,9 @@ ItemID: foreach $id (keys %$items) {
9350
9416
  }
9351
9417
  for (;;) {
9352
9418
  my ($len, $lang);
9353
- if ($$tagInfo{IText} and $$tagInfo{IText} == 6) {
9354
- last if $pos + 6 > $size;
9355
- $pos += 4;
9419
+ if ($$tagInfo{IText} and $$tagInfo{IText} >= 6) {
9420
+ last if $pos + $$tagInfo{IText} > $size;
9421
+ $pos += $$tagInfo{IText} - 2;
9356
9422
  $lang = unpack("x${pos}n", $val);
9357
9423
  $pos += 2;
9358
9424
  $len = $size - $pos;
@@ -9372,7 +9438,7 @@ ItemID: foreach $id (keys %$items) {
9372
9438
  # ignore any empty entries (or null padding) after the first
9373
9439
  next if not $len and $pos;
9374
9440
  my $str = substr($val, $pos, $len);
9375
- my $langInfo;
9441
+ my ($langInfo, $enc);
9376
9442
  if (($lang < 0x400 or $lang == 0x7fff) and $str !~ /^\xfe\xff/) {
9377
9443
  # this is a Macintosh language code
9378
9444
  # a language code of 0 is Macintosh english, so treat as default
@@ -9389,15 +9455,22 @@ ItemID: foreach $id (keys %$items) {
9389
9455
  }
9390
9456
  # the spec says only "Macintosh text encoding", but
9391
9457
  # allow this to be configured by the user
9392
- $str = $et->Decode($str, $charsetQuickTime);
9458
+ $enc = $charsetQuickTime;
9393
9459
  } else {
9394
9460
  # convert language code to ASCII (ignore read-only bit)
9395
9461
  $lang = UnpackLang($lang);
9396
9462
  # may be either UTF-8 or UTF-16BE
9397
- my $enc = $str=~s/^\xfe\xff// ? 'UTF16' : 'UTF8';
9463
+ $enc = $str=~s/^\xfe\xff// ? 'UTF16' : 'UTF8';
9464
+ }
9465
+ unless ($$tagInfo{NoDecode}) {
9398
9466
  $str = $et->Decode($str, $enc);
9467
+ $str =~ s/\0+$//; # remove any trailing nulls (eg. 3gp tags)
9468
+ }
9469
+ if ($$tagInfo{IText} and $$tagInfo{IText} > 6) {
9470
+ my $n = $$tagInfo{IText} - 6;
9471
+ # add back extra bytes (eg. 'rtng' box)
9472
+ $str = substr($val, $pos-$n-2, $n) . $str;
9399
9473
  }
9400
- $str =~ s/\0+$//; # remove any trailing nulls (eg. 3gp tags)
9401
9474
  $langInfo = GetLangInfoQT($et, $tagInfo, $lang) if $lang;
9402
9475
  $et->FoundTag($langInfo || $tagInfo, $str);
9403
9476
  $pos += $len;
@@ -9447,6 +9520,13 @@ ItemID: foreach $id (keys %$items) {
9447
9520
  ($size, $tag) = unpack('Na4', $buff);
9448
9521
  ++$index if defined $index;
9449
9522
  }
9523
+ # tweak file type based on track content ("iso*" ftyp only)
9524
+ if ($$et{VALUE}{FileType} and $$et{VALUE}{FileType} eq 'MP4' and
9525
+ $$et{save_ftyp} and $$et{HasHandler} and $$et{save_ftyp} =~ /^iso/ and
9526
+ $$et{HasHandler}{soun} and not $$et{HasHandler}{vide})
9527
+ {
9528
+ $et->OverrideFileType('M4A', 'audio/mp4');
9529
+ }
9450
9530
  # fill in missing defaults for alternate language tags
9451
9531
  # (the first language is taken as the default)
9452
9532
  if ($doDefaultLang and $$et{QTLang}) {