exiftool_vendored 12.42.0 → 12.52.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +226 -6
  3. data/bin/MANIFEST +14 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +45 -44
  7. data/bin/config_files/acdsee.config +2 -1
  8. data/bin/config_files/frameCount.config +56 -0
  9. data/bin/config_files/tiff_version.config +1 -1
  10. data/bin/exiftool +116 -97
  11. data/bin/fmt_files/gpx.fmt +3 -0
  12. data/bin/fmt_files/gpx_wpt.fmt +3 -0
  13. data/bin/lib/Image/ExifTool/Apple.pm +16 -3
  14. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +23 -12
  15. data/bin/lib/Image/ExifTool/Canon.pm +66 -37
  16. data/bin/lib/Image/ExifTool/CanonRaw.pm +8 -1
  17. data/bin/lib/Image/ExifTool/CanonVRD.pm +7 -8
  18. data/bin/lib/Image/ExifTool/Casio.pm +3 -3
  19. data/bin/lib/Image/ExifTool/DJI.pm +2 -1
  20. data/bin/lib/Image/ExifTool/DarwinCore.pm +13 -1
  21. data/bin/lib/Image/ExifTool/EXE.pm +9 -1
  22. data/bin/lib/Image/ExifTool/Exif.pm +17 -12
  23. data/bin/lib/Image/ExifTool/FLAC.pm +17 -3
  24. data/bin/lib/Image/ExifTool/FLIR.pm +9 -7
  25. data/bin/lib/Image/ExifTool/FlashPix.pm +26 -3
  26. data/bin/lib/Image/ExifTool/FujiFilm.pm +51 -4
  27. data/bin/lib/Image/ExifTool/GPS.pm +31 -5
  28. data/bin/lib/Image/ExifTool/Geotag.pm +36 -8
  29. data/bin/lib/Image/ExifTool/ICC_Profile.pm +3 -2
  30. data/bin/lib/Image/ExifTool/ICO.pm +143 -0
  31. data/bin/lib/Image/ExifTool/ID3.pm +6 -6
  32. data/bin/lib/Image/ExifTool/IPTC.pm +5 -1
  33. data/bin/lib/Image/ExifTool/JPEG.pm +1 -0
  34. data/bin/lib/Image/ExifTool/Jpeg2000.pm +24 -3
  35. data/bin/lib/Image/ExifTool/LNK.pm +5 -2
  36. data/bin/lib/Image/ExifTool/Lang/de.pm +1 -1
  37. data/bin/lib/Image/ExifTool/Lang/fr.pm +6015 -759
  38. data/bin/lib/Image/ExifTool/Lang/sk.pm +1927 -0
  39. data/bin/lib/Image/ExifTool/M2TS.pm +98 -8
  40. data/bin/lib/Image/ExifTool/MIE.pm +9 -3
  41. data/bin/lib/Image/ExifTool/MISB.pm +494 -0
  42. data/bin/lib/Image/ExifTool/MakerNotes.pm +3 -1
  43. data/bin/lib/Image/ExifTool/Matroska.pm +272 -48
  44. data/bin/lib/Image/ExifTool/Motorola.pm +8 -2
  45. data/bin/lib/Image/ExifTool/Nikon.pm +746 -382
  46. data/bin/lib/Image/ExifTool/NikonCustom.pm +139 -106
  47. data/bin/lib/Image/ExifTool/NikonSettings.pm +5 -3
  48. data/bin/lib/Image/ExifTool/Olympus.pm +6 -4
  49. data/bin/lib/Image/ExifTool/PNG.pm +8 -1
  50. data/bin/lib/Image/ExifTool/Panasonic.pm +21 -4
  51. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +25 -5
  52. data/bin/lib/Image/ExifTool/Parrot.pm +96 -2
  53. data/bin/lib/Image/ExifTool/Pentax.pm +7 -2
  54. data/bin/lib/Image/ExifTool/Photoshop.pm +29 -3
  55. data/bin/lib/Image/ExifTool/QuickTime.pm +166 -13
  56. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +161 -22
  57. data/bin/lib/Image/ExifTool/README +15 -4
  58. data/bin/lib/Image/ExifTool/RIFF.pm +106 -9
  59. data/bin/lib/Image/ExifTool/Samsung.pm +2 -2
  60. data/bin/lib/Image/ExifTool/Sigma.pm +27 -1
  61. data/bin/lib/Image/ExifTool/SigmaRaw.pm +37 -13
  62. data/bin/lib/Image/ExifTool/Sony.pm +75 -47
  63. data/bin/lib/Image/ExifTool/TagInfoXML.pm +13 -6
  64. data/bin/lib/Image/ExifTool/TagLookup.pm +4791 -4519
  65. data/bin/lib/Image/ExifTool/TagNames.pod +2056 -1446
  66. data/bin/lib/Image/ExifTool/Text.pm +3 -4
  67. data/bin/lib/Image/ExifTool/Torrent.pm +2 -3
  68. data/bin/lib/Image/ExifTool/Validate.pm +3 -3
  69. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +7 -0
  70. data/bin/lib/Image/ExifTool/WriteExif.pl +100 -23
  71. data/bin/lib/Image/ExifTool/WriteIPTC.pl +2 -6
  72. data/bin/lib/Image/ExifTool/WritePhotoshop.pl +5 -5
  73. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +12 -7
  74. data/bin/lib/Image/ExifTool/WriteRIFF.pl +359 -0
  75. data/bin/lib/Image/ExifTool/WriteXMP.pl +15 -1
  76. data/bin/lib/Image/ExifTool/Writer.pl +46 -18
  77. data/bin/lib/Image/ExifTool/XMP.pm +78 -59
  78. data/bin/lib/Image/ExifTool/XMP2.pl +19 -4
  79. data/bin/lib/Image/ExifTool/ZIP.pm +19 -7
  80. data/bin/lib/Image/ExifTool.pm +146 -38
  81. data/bin/lib/Image/ExifTool.pod +83 -69
  82. data/bin/perl-Image-ExifTool.spec +43 -43
  83. data/lib/exiftool_vendored/version.rb +1 -1
  84. metadata +10 -4
@@ -6,6 +6,7 @@
6
6
  # Revisions: 05/26/2010 - P. Harvey Created
7
7
  #
8
8
  # References: 1) http://www.matroska.org/technical/specs/index.html
9
+ # 2) https://www.matroska.org/technical/tagging.html
9
10
  #------------------------------------------------------------------------------
10
11
 
11
12
  package Image::ExifTool::Matroska;
@@ -14,10 +15,26 @@ use strict;
14
15
  use vars qw($VERSION);
15
16
  use Image::ExifTool qw(:DataAccess :Utils);
16
17
 
17
- $VERSION = '1.11';
18
+ $VERSION = '1.13';
19
+
20
+ sub HandleStruct($$;$$$$);
18
21
 
19
22
  my %noYes = ( 0 => 'No', 1 => 'Yes' );
20
23
 
24
+ my %dateInfo = (
25
+ Groups => { 2 => 'Time' },
26
+ # the spec says to use "-" as a date separator, but my only sample uses ":", so
27
+ # convert to ":" if necessary, and avoid translating all "-" in case someone wants
28
+ # to include a negative time zone (although the spec doesn't mention time zones)
29
+ ValueConv => '$val =~ s/^(\d{4})-(\d{2})-/$1:$2:/; $val',
30
+ PrintConv => '$self->ConvertDateTime($val)',
31
+ );
32
+
33
+ my %uidInfo = (
34
+ Format => 'string',
35
+ ValueConv => 'unpack("H*",$val)'
36
+ );
37
+
21
38
  # Matroska tags
22
39
  # Note: The tag ID's in the Matroska documentation include the length designation
23
40
  # (the upper bits), which is not included in the tag ID's below
@@ -27,8 +44,10 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
27
44
  NOTES => q{
28
45
  The following tags are extracted from Matroska multimedia container files.
29
46
  This container format is used by file types such as MKA, MKV, MKS and WEBM.
30
- For speed, ExifTool extracts tags only up to the first Cluster unless the
31
- L<Verbose|../ExifTool.html#Verbose> (-v) or L<Unknown|../ExifTool.html#Unknown> = 2 (-U) option is used. See
47
+ For speed, by default ExifTool extracts tags only up to the first Cluster.
48
+ However, the L<Verbose|../ExifTool.html#Verbose> (-v) and L<Unknown|../ExifTool.html#Unknown> = 2 (-U) options force processing of
49
+ Cluster data, and the L<ExtractEmbedded|../ExifTool.html#ExtractEmbedded> (-ee) option skips over Clusters to
50
+ read subsequent tags. See
32
51
  L<http://www.matroska.org/technical/specs/index.html> for the official
33
52
  Matroska specification.
34
53
  },
@@ -56,7 +75,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
56
75
  #
57
76
  # General
58
77
  #
59
- 0x3f => { Name => 'CRC-32', Binary => 1, Unknown => 1 },
78
+ 0x3f => { Name => 'CRC-32', Format => 'unsigned', Unknown => 1 },
60
79
  0x6c => { Name => 'Void', NoSave => 1, Unknown => 1 },
61
80
  #
62
81
  # Signature
@@ -102,18 +121,18 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
102
121
  Name => 'Info',
103
122
  SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
104
123
  },
105
- 0x33a4 => { Name => 'SegmentUID', Binary => 1, Unknown => 1 },
124
+ 0x33a4 => { Name => 'SegmentUID', %uidInfo, Unknown => 1 },
106
125
  0x3384 => { Name => 'SegmentFileName', Format => 'utf8' },
107
- 0x1cb923 => { Name => 'PrevUID', Binary => 1, Unknown => 1 },
126
+ 0x1cb923 => { Name => 'PrevUID', %uidInfo, Unknown => 1 },
108
127
  0x1c83ab => { Name => 'PrevFileName', Format => 'utf8' },
109
- 0x1eb923 => { Name => 'NextUID', Binary => 1, Unknown => 1 },
128
+ 0x1eb923 => { Name => 'NextUID', %uidInfo, Unknown => 1 },
110
129
  0x1e83bb => { Name => 'NextFileName', Format => 'utf8' },
111
130
  0x0444 => { Name => 'SegmentFamily', Binary => 1, Unknown => 1 },
112
131
  0x2924 => {
113
132
  Name => 'ChapterTranslate',
114
133
  SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
115
134
  },
116
- 0x29fc => { Name => 'ChapterTranslateEditionUID',Format => 'unsigned', Unknown => 1 },
135
+ 0x29fc => { Name => 'ChapterTranslateEditionUID', %uidInfo, Unknown => 1 },
117
136
  0x29bf => {
118
137
  Name => 'ChapterTranslateCodec',
119
138
  Format => 'unsigned',
@@ -226,7 +245,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
226
245
  SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
227
246
  },
228
247
  0x57 => { Name => 'TrackNumber', Format => 'unsigned' },
229
- 0x33c5 => { Name => 'TrackUID', Format => 'unsigned', Unknown => 1 },
248
+ 0x33c5 => { Name => 'TrackUID', %uidInfo },
230
249
  0x03 => {
231
250
  Name => 'TrackType',
232
251
  Format => 'unsigned',
@@ -269,10 +288,11 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
269
288
  }
270
289
  ],
271
290
  0x3314f => { Name => 'TrackTimecodeScale',Format => 'float' },
272
- 0x137f => { Name => 'TrackOffset', Format => 'signed', Unknown => 1 },
291
+ 0x137f => { Name => 'TrackOffset', Format => 'signed', Unknown => 1 },
273
292
  0x15ee => { Name => 'MaxBlockAdditionID',Format => 'unsigned', Unknown => 1 },
274
- 0x136e => { Name => 'TrackName', Format => 'utf8' },
275
- 0x2b59c => { Name => 'TrackLanguage', Format => 'string' },
293
+ 0x136e => { Name => 'TrackName', Format => 'utf8' },
294
+ 0x2b59c => { Name => 'TrackLanguage', Format => 'string' },
295
+ 0x2b59d => { Name => 'TrackLanguageIETF', Format => 'string' },
276
296
  0x06 => [
277
297
  {
278
298
  Name => 'VideoCodecID',
@@ -302,7 +322,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
302
322
  Format => 'utf8',
303
323
  }
304
324
  ],
305
- 0x3446 => { Name => 'TrackAttachmentUID',Format => 'unsigned' },
325
+ 0x3446 => { Name => 'TrackAttachmentUID',%uidInfo },
306
326
  0x1a9697=>{ Name => 'CodecSettings', Format => 'utf8' },
307
327
  0x1b4040=>{ Name => 'CodecInfoURL', Format => 'string' },
308
328
  0x6b240 =>{ Name => 'CodecDownloadURL', Format => 'string' },
@@ -312,7 +332,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
312
332
  Name => 'TrackTranslate',
313
333
  SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
314
334
  },
315
- 0x26fc => { Name => 'TrackTranslateEditionUID',Format => 'unsigned', Unknown => 1 },
335
+ 0x26fc => { Name => 'TrackTranslateEditionUID', %uidInfo, Unknown => 1 },
316
336
  0x26bf => {
317
337
  Name => 'TrackTranslateCodec',
318
338
  Format => 'unsigned',
@@ -359,6 +379,8 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
359
379
  0 => 'Pixels',
360
380
  1 => 'cm',
361
381
  2 => 'inches',
382
+ 3 => 'Display Aspect Ratio',
383
+ 4 => 'Unknown',
362
384
  },
363
385
  },
364
386
  0x14b3 => {
@@ -514,7 +536,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
514
536
  0x66e => { Name => 'AttachedFileName', Format => 'utf8' },
515
537
  0x660 => { Name => 'AttachedFileMIMEType', Format => 'string' },
516
538
  0x65c => { Name => 'AttachedFileData', Binary => 1 },
517
- 0x6ae => { Name => 'AttachedFileUID', Format => 'unsigned' },
539
+ 0x6ae => { Name => 'AttachedFileUID', %uidInfo },
518
540
  0x675 => { Name => 'AttachedFileReferral', Binary => 1, Unknown => 1 },
519
541
  #
520
542
  # Chapters
@@ -527,7 +549,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
527
549
  Name => 'EditionEntry',
528
550
  SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
529
551
  },
530
- 0x5bc => { Name => 'EditionUID', Format => 'unsigned', Unknown => 1 },
552
+ 0x5bc => { Name => 'EditionUID', %uidInfo, Unknown => 1 },
531
553
  0x5bd => { Name => 'EditionFlagHidden', Format => 'unsigned', Unknown => 1 },
532
554
  0x5db => { Name => 'EditionFlagDefault',Format => 'unsigned', Unknown => 1 },
533
555
  0x5dd => { Name => 'EditionFlagOrdered',Format => 'unsigned', Unknown => 1 },
@@ -535,7 +557,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
535
557
  Name => 'ChapterAtom',
536
558
  SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
537
559
  },
538
- 0x33c4 => { Name => 'ChapterUID', Format => 'unsigned', Unknown => 1 },
560
+ 0x33c4 => { Name => 'ChapterUID', %uidInfo, Unknown => 1 },
539
561
  0x11 => {
540
562
  Name => 'ChapterTimeStart',
541
563
  Groups => { 1 => 'Chapter#' },
@@ -551,8 +573,8 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
551
573
  },
552
574
  0x18 => { Name => 'ChapterFlagHidden', Format => 'unsigned', Unknown => 1 },
553
575
  0x598 => { Name => 'ChapterFlagEnabled',Format => 'unsigned', Unknown => 1 },
554
- 0x2e67=> { Name => 'ChapterSegmentUID', Binary => 1, Unknown => 1 },
555
- 0x2ebc=> { Name => 'ChapterSegmentEditionUID', Binary => 1, Unknown => 1 },
576
+ 0x2e67=> { Name => 'ChapterSegmentUID', %uidInfo, Unknown => 1 },
577
+ 0x2ebc=> { Name => 'ChapterSegmentEditionUID', %uidInfo, Unknown => 1 },
556
578
  0x23c3 => {
557
579
  Name => 'ChapterPhysicalEquivalent',
558
580
  Format => 'unsigned',
@@ -619,21 +641,24 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
619
641
  Name => 'Targets',
620
642
  SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
621
643
  },
622
- 0x28ca => { Name => 'TargetTypeValue', Format => 'unsigned' },
623
- 0x23ca => { Name => 'TargetType', Format => 'string' },
624
- 0x23c5 => { Name => 'TagTrackUID', Format => 'unsigned', Unknown => 1 },
625
- 0x23c9 => { Name => 'TagEditionUID', Format => 'unsigned', Unknown => 1 },
626
- 0x23c4 => { Name => 'TagChapterUID', Format => 'unsigned', Unknown => 1 },
627
- 0x23c6 => { Name => 'TagAttachmentUID', Format => 'unsigned', Unknown => 1 },
644
+ # Targets elements
645
+ 0x28ca => { Name => 'TargetTypeValue', Format => 'unsigned' },
646
+ 0x23ca => { Name => 'TargetType', Format => 'string' },
647
+ 0x23c5 => { Name => 'TagTrackUID', %uidInfo },
648
+ 0x23c9 => { Name => 'TagEditionUID', %uidInfo },
649
+ 0x23c4 => { Name => 'TagChapterUID', %uidInfo },
650
+ 0x23c6 => { Name => 'TagAttachmentUID', %uidInfo },
628
651
  0x27c8 => {
629
652
  Name => 'SimpleTag',
630
653
  SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
631
654
  },
632
- 0x5a3 => { Name => 'TagName', Format => 'utf8' },
633
- 0x47a => { Name => 'TagLanguage', Format => 'string' },
634
- 0x484 => { Name => 'TagDefault', Format => 'unsigned', PrintConv => \%noYes },
635
- 0x487 => { Name => 'TagString', Format => 'utf8' },
636
- 0x485 => { Name => 'TagBinary', Binary => 1 },
655
+ # SimpleTag elements
656
+ 0x5a3 => { Name => 'TagName', Format => 'utf8' },
657
+ 0x47a => { Name => 'TagLanguage', Format => 'string' },
658
+ 0x47a => { Name => 'TagLanguageBCP47', Format => 'string' },
659
+ 0x484 => { Name => 'TagDefault', Format => 'unsigned', PrintConv => \%noYes },
660
+ 0x487 => { Name => 'TagString', Format => 'utf8' },
661
+ 0x485 => { Name => 'TagBinary', Binary => 1 },
637
662
  #
638
663
  # Spherical Video V2 (untested)
639
664
  #
@@ -682,6 +707,172 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
682
707
  0x7675 => { Name => 'ProjectionPoseRoll', Format => 'float' },
683
708
  );
684
709
 
710
+ # standardized tag names (ref 2)
711
+ %Image::ExifTool::Matroska::Tags = (
712
+ GROUPS => { 2 => 'Video' },
713
+ VARS => { LONG_TAGS => 1 },
714
+ NOTES => q{
715
+ Standardized Matroska tags (see
716
+ L<https://www.matroska.org/technical/tagging.html>).
717
+ },
718
+ ORIGINAL => 'Original', # struct
719
+ SAMPLE => 'Sample', # struct
720
+ COUNTRY => 'Country', # struct (should deal with this properly!)
721
+ TOTAL_PARTS => 'TotalParts',
722
+ PART_NUMBER => 'PartNumber',
723
+ PART_OFFSET => 'PartOffset',
724
+ TITLE => 'Title',
725
+ SUBTITLE => 'Subtitle',
726
+ URL => 'URL', # nested
727
+ SORT_WITH => 'SortWith', # nested
728
+ INSTRUMENTS => 'Instruments', # nested
729
+ EMAIL => 'Email', # nested
730
+ ADDRESS => 'Address', # nested
731
+ FAX => 'FAX', # nested
732
+ PHONE => 'Phone', # nested
733
+ ARTIST => 'Artist',
734
+ LEAD_PERFORMER => 'LeadPerformer',
735
+ ACCOMPANIMENT => 'Accompaniment',
736
+ COMPOSER => 'Composer',
737
+ ARRANGER => 'Arranger',
738
+ LYRICS => 'Lyrics',
739
+ LYRICIST => 'Lyricist',
740
+ CONDUCTOR => 'Conductor',
741
+ DIRECTOR => 'Director',
742
+ ASSISTANT_DIRECTOR => 'AssistantDirector',
743
+ DIRECTOR_OF_PHOTOGRAPHY => 'DirectorOfPhotography',
744
+ SOUND_ENGINEER => 'SoundEngineer',
745
+ ART_DIRECTOR => 'ArtDirector',
746
+ PRODUCTION_DESIGNER => 'ProductionDesigner',
747
+ CHOREGRAPHER => 'Choregrapher',
748
+ COSTUME_DESIGNER => 'CostumeDesigner',
749
+ ACTOR => 'Actor',
750
+ CHARACTER => 'Character',
751
+ WRITTEN_BY => 'WrittenBy',
752
+ SCREENPLAY_BY => 'ScreenplayBy',
753
+ EDITED_BY => 'EditedBy',
754
+ PRODUCER => 'Producer',
755
+ COPRODUCER => 'Coproducer',
756
+ EXECUTIVE_PRODUCER => 'ExecutiveProducer',
757
+ DISTRIBUTED_BY => 'DistributedBy',
758
+ MASTERED_BY => 'MasteredBy',
759
+ ENCODED_BY => 'EncodedBy',
760
+ MIXED_BY => 'MixedBy',
761
+ REMIXED_BY => 'RemixedBy',
762
+ PRODUCTION_STUDIO => 'ProductionStudio',
763
+ THANKS_TO => 'ThanksTo',
764
+ PUBLISHER => 'Publisher',
765
+ LABEL => 'Label',
766
+ GENRE => 'Genre',
767
+ MOOD => 'Mood',
768
+ ORIGINAL_MEDIA_TYPE => 'OriginalMediaType',
769
+ CONTENT_TYPE => 'ContentType',
770
+ SUBJECT => 'Subject',
771
+ DESCRIPTION => 'Description',
772
+ KEYWORDS => 'Keywords',
773
+ SUMMARY => 'Summary',
774
+ SYNOPSIS => 'Synopsis',
775
+ INITIAL_KEY => 'InitialKey',
776
+ PERIOD => 'Period',
777
+ LAW_RATING => 'LawRating',
778
+ DATE_RELEASED => { Name => 'DateReleased', %dateInfo },
779
+ DATE_RECORDED => { Name => 'DateTimeOriginal', %dateInfo, Description => 'Date/Time Original' },
780
+ DATE_ENCODED => { Name => 'DateEncoded', %dateInfo },
781
+ DATE_TAGGED => { Name => 'DateTagged', %dateInfo },
782
+ DATE_DIGITIZED => { Name => 'CreateDate', %dateInfo },
783
+ DATE_WRITTEN => { Name => 'DateWritten', %dateInfo },
784
+ DATE_PURCHASED => { Name => 'DatePurchased', %dateInfo },
785
+ RECORDING_LOCATION => 'RecordingLocation',
786
+ COMPOSITION_LOCATION => 'CompositionLocation',
787
+ COMPOSER_NATIONALITY => 'ComposerNationality',
788
+ COMMENT => 'Comment',
789
+ PLAY_COUNTER => 'PlayCounter',
790
+ RATING => 'Rating',
791
+ ENCODER => 'Encoder',
792
+ ENCODER_SETTINGS => 'EncoderSettings',
793
+ BPS => 'BPS',
794
+ FPS => 'FPS',
795
+ BPM => 'BPM',
796
+ MEASURE => 'Measure',
797
+ TUNING => 'Tuning',
798
+ REPLAYGAIN_GAIN => 'ReplaygainGain',
799
+ REPLAYGAIN_PEAK => 'ReplaygainPeak',
800
+ ISRC => 'ISRC',
801
+ MCDI => 'MCDI',
802
+ ISBN => 'ISBN',
803
+ BARCODE => 'Barcode',
804
+ CATALOG_NUMBER => 'CatalogNumber',
805
+ LABEL_CODE => 'LabelCode',
806
+ LCCN => 'Lccn',
807
+ IMDB => 'IMDB',
808
+ TMDB => 'TMDB',
809
+ TVDB => 'TVDB',
810
+ PURCHASE_ITEM => 'PurchaseItem',
811
+ PURCHASE_INFO => 'PurchaseInfo',
812
+ PURCHASE_OWNER => 'PurchaseOwner',
813
+ PURCHASE_PRICE => 'PurchasePrice',
814
+ PURCHASE_CURRENCY => 'PurchaseCurrency',
815
+ COPYRIGHT => 'Copyright',
816
+ PRODUCTION_COPYRIGHT => 'ProductionCopyright',
817
+ LICENSE => 'License',
818
+ TERMS_OF_USE => 'TermsOfUse',
819
+ );
820
+
821
+ #------------------------------------------------------------------------------
822
+ # Handle MKV SimpleTag structure
823
+ # Inputs: 0) ExifTool ref, 1) structure ref, 2) parent tag ID, 3) parent tag Name,
824
+ # 4) language code, 5) country code
825
+ sub HandleStruct($$;$$$$)
826
+ {
827
+ local $_;
828
+ my ($et, $struct, $pid, $pname, $lang, $ctry) = @_;
829
+ my $tagTbl = GetTagTable('Image::ExifTool::Matroska::Tags');
830
+ my $tag = $$struct{TagName};
831
+ my $tagInfo = $$tagTbl{$tag};
832
+ # create tag if necessary
833
+ unless (ref $tagInfo eq 'HASH') {
834
+ my $name = ucfirst lc $tag;
835
+ $name =~ tr/0-9a-zA-Z_//dc;
836
+ $name =~ s/_([a-z])/\U$1/g;
837
+ $name = "Tag_$name" if length $name < 2;
838
+ $tagInfo = AddTagToTable($tagTbl, $tag, { Name => $name });
839
+ }
840
+ my ($id, $nm);
841
+ if ($pid) {
842
+ $id = "$pid/$tag";
843
+ $nm = "$pname/$$tagInfo{Name}";
844
+ unless ($$tagTbl{$id}) {
845
+ my %copy = %$tagInfo;
846
+ $copy{Name} = $nm;
847
+ $tagInfo = AddTagToTable($tagTbl, $id, \%copy);
848
+ }
849
+ } else {
850
+ ($id, $nm) = ($tag, $$tagInfo{Name});
851
+ }
852
+ if (defined $$struct{TagString} or defined $$struct{TagBinary}) {
853
+ my $val = defined $$struct{TagString} ? $$struct{TagString} : \$$struct{TagBinary};
854
+ $lang = $$struct{TagLanguageBCP47} || $$struct{TagLanguage} || $lang;
855
+ # (Note: not currently handling TagDefault attribute)
856
+ my $code = $lang;
857
+ $code = $lang ? "${lang}-${ctry}" : "eng-${ctry}" if $ctry; # ('eng' is default lang)
858
+ if ($code) {
859
+ $tagInfo = Image::ExifTool::GetLangInfo($tagInfo, $code);
860
+ $et->HandleTag($tagTbl, $$tagInfo{TagID}, $val);
861
+ } else {
862
+ $et->HandleTag($tagTbl, $id, $val);
863
+ }
864
+ # COUNTRY is handled as an attribute for contained tags
865
+ if ($tag eq 'COUNTRY') {
866
+ $ctry = $val;
867
+ ($id, $nm) = ($pid, $pname);
868
+ }
869
+ }
870
+ if ($$struct{struct}) {
871
+ # step into each contained structure
872
+ HandleStruct($et, $_, $id, $nm, $lang, $ctry) foreach @{$$struct{struct}};
873
+ }
874
+ }
875
+
685
876
  #------------------------------------------------------------------------------
686
877
  # Get variable-length Matroska integer
687
878
  # Inputs: 0) data buffer, 1) position in data
@@ -723,7 +914,7 @@ sub ProcessMKV($$)
723
914
  {
724
915
  my ($et, $dirInfo) = @_;
725
916
  my $raf = $$dirInfo{RAF};
726
- my ($buff, $buf2, @dirEnd, $trackIndent, %trackTypes);
917
+ my ($buff, $buf2, @dirEnd, $trackIndent, %trackTypes, $struct);
727
918
 
728
919
  $raf->Read($buff, 4) == 4 or return 0;
729
920
  return 0 unless $buff =~ /^\x1a\x45\xdf\xa3/;
@@ -743,18 +934,38 @@ sub ProcessMKV($$)
743
934
 
744
935
  # set flag to process entire file (otherwise we stop at the first Cluster)
745
936
  my $verbose = $et->Options('Verbose');
746
- my $processAll = ($verbose or $et->Options('Unknown') > 1);
937
+ my $processAll = ($verbose or $et->Options('Unknown') > 1) ? 2 : 0;
938
+ ++$processAll if $et->Options('ExtractEmbedded');
747
939
  $$et{TrackTypes} = \%trackTypes; # store Track types reference
748
940
  my $oldIndent = $$et{INDENT};
749
941
  my $chapterNum = 0;
942
+ my $dirName = 'MKV';
750
943
 
751
944
  # loop over all Matroska elements
752
945
  for (;;) {
753
- while (@dirEnd and $pos + $dataPos >= $dirEnd[-1][0]) {
754
- pop @dirEnd;
755
- # use INDENT to decide whether or not we are done this Track element
756
- delete $$et{SET_GROUP1} if $trackIndent and $trackIndent eq $$et{INDENT};
757
- $$et{INDENT} = substr($$et{INDENT}, 0, -2);
946
+ while (@dirEnd) {
947
+ if ($pos + $dataPos >= $dirEnd[-1][0]) {
948
+ pop @dirEnd;
949
+ if ($struct) {
950
+ if (@dirEnd and $dirEnd[-1][2]) {
951
+ # save this nested structure
952
+ $dirEnd[-1][2]{struct} or $dirEnd[-1][2]{struct} = [ ];
953
+ push @{$dirEnd[-1][2]{struct}}, $struct;
954
+ $struct = $dirEnd[-1][2];
955
+ } else {
956
+ # handle completed structures now
957
+ HandleStruct($et, $struct);
958
+ undef $struct;
959
+ }
960
+ }
961
+ $dirName = @dirEnd ? $dirEnd[-1][1] : 'MKV';
962
+ # use INDENT to decide whether or not we are done this Track element
963
+ delete $$et{SET_GROUP1} if $trackIndent and $trackIndent eq $$et{INDENT};
964
+ $$et{INDENT} = substr($$et{INDENT}, 0, -2);
965
+ } else {
966
+ $dirName = $dirEnd[-1][1];
967
+ last;
968
+ }
758
969
  }
759
970
  # read more if we are getting close to the end of our buffer
760
971
  # (24 more bytes should be enough to read this element header)
@@ -785,17 +996,27 @@ sub ProcessMKV($$)
785
996
  }
786
997
  my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
787
998
  # just fall through into the contained EBML elements
788
- if ($tagInfo and $$tagInfo{SubDirectory}) {
789
- # stop processing at first cluster unless we are in verbose mode
790
- last if $$tagInfo{Name} eq 'Cluster' and not $processAll;
791
- $$et{INDENT} .= '| ';
792
- $et->VerboseDir($$tagTablePtr{$tag}{Name}, undef, $size);
793
- push @dirEnd, [ $pos + $dataPos + $size, $$tagInfo{Name} ];
794
- if ($$tagInfo{Name} eq 'ChapterAtom') {
795
- $$et{SET_GROUP1} = 'Chapter' . (++$chapterNum);
796
- $trackIndent = $$et{INDENT};
999
+ if ($tagInfo) {
1000
+ if ($$tagInfo{SubDirectory}) {
1001
+ # stop processing at first cluster unless we are using -v -U or -ee
1002
+ if ($$tagInfo{Name} eq 'Cluster' and $processAll < 2) {
1003
+ last unless $processAll;
1004
+ undef $tagInfo; # just skip the Cluster when -ee is used
1005
+ } else {
1006
+ $$et{INDENT} .= '| ';
1007
+ $et->VerboseDir($$tagTablePtr{$tag}{Name}, undef, $size);
1008
+ $dirName = $$tagInfo{Name};
1009
+ push @dirEnd, [ $pos + $dataPos + $size, $dirName, $struct ];
1010
+ $struct = { } if $dirName eq 'SimpleTag'; # keep track of SimpleTag elements
1011
+ if ($$tagInfo{Name} eq 'ChapterAtom') {
1012
+ $$et{SET_GROUP1} = 'Chapter' . (++$chapterNum);
1013
+ $trackIndent = $$et{INDENT};
1014
+ }
1015
+ next;
1016
+ }
797
1017
  }
798
- next;
1018
+ } elsif ($verbose) {
1019
+ $et->VPrint(0,sprintf("$$et{INDENT}- Tag 0x%x (Unknown, %d bytes)\n", $tag, $size));
799
1020
  }
800
1021
  last if $unknownSize;
801
1022
  if ($pos + $size > $dataLen) {
@@ -879,8 +1100,9 @@ sub ProcessMKV($$)
879
1100
  Start => $pos,
880
1101
  Size => $size,
881
1102
  );
882
- if ($$tagInfo{NoSave}) {
1103
+ if ($$tagInfo{NoSave} or $struct) {
883
1104
  $et->VerboseInfo($tag, $tagInfo, Value => $val, %parms) if $verbose;
1105
+ $$struct{$$tagInfo{Name}} = $val if $struct;
884
1106
  } else {
885
1107
  $et->HandleTag($tagTablePtr, $tag, $val, %parms);
886
1108
  }
@@ -929,6 +1151,8 @@ under the same terms as Perl itself.
929
1151
 
930
1152
  =item L<http://www.matroska.org/technical/specs/index.html>
931
1153
 
1154
+ =item L<https://www.matroska.org/technical/tagging.html>
1155
+
932
1156
  =back
933
1157
 
934
1158
  =head1 SEE ALSO
@@ -14,7 +14,7 @@ use strict;
14
14
  use vars qw($VERSION);
15
15
  use Image::ExifTool::Exif;
16
16
 
17
- $VERSION = '1.01';
17
+ $VERSION = '1.02';
18
18
 
19
19
  # Motorola makernotes tags (ref PH)
20
20
  %Image::ExifTool::Motorola::Main = (
@@ -54,7 +54,12 @@ $VERSION = '1.01';
54
54
  # 0x6400 - string: 'AUTO','ON','OFF'
55
55
  # 0x6401 - string: 'HDR'
56
56
  # 0x6410 - string: 'NO','YES'
57
- # 0x6420 - int32s: 0 (only exists in HDR images?)
57
+ # 0x6420 - int32s for some models: 0 (only exists in HDR images?)
58
+ 0x6420 => { #forum13731
59
+ Condition => '$format eq "string"',
60
+ Name => 'CustomRendered',
61
+ Writable => 'string',
62
+ },
58
63
  # 0x6430 - float
59
64
  # 0x6431 - int8u: 0,1
60
65
  # 0x6432 - int8u: 0,79,100
@@ -89,6 +94,7 @@ $VERSION = '1.01';
89
94
  # 0x64c2,0x64c3 - int32s
90
95
  # 0x64c4 - int32s
91
96
  # 0x64c5 - int32u
97
+ 0x64d0 => { Name => 'DriveMode', Writable => 'string' }, #forum13731
92
98
  # 0x6500 - int8u: 1
93
99
  # 0x6501 - string: 'Luma-Chroma Plane','Chroma only' or int8u: 0
94
100
  # 0x6502 - string: 'Luma-Chroma Plane','Chroma only','' or int8u: 1,255