exiftool_vendored 12.50.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.
- checksums.yaml +4 -4
- data/bin/Changes +39 -2
- data/bin/MANIFEST +2 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +2 -2
- data/bin/exiftool +5 -4
- data/bin/lib/Image/ExifTool/Casio.pm +3 -3
- data/bin/lib/Image/ExifTool/FLIR.pm +6 -5
- data/bin/lib/Image/ExifTool/GPS.pm +11 -5
- data/bin/lib/Image/ExifTool/Geotag.pm +12 -4
- data/bin/lib/Image/ExifTool/JPEG.pm +1 -0
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +24 -3
- data/bin/lib/Image/ExifTool/Lang/de.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/fr.pm +6015 -759
- data/bin/lib/Image/ExifTool/Lang/sk.pm +1927 -0
- data/bin/lib/Image/ExifTool/Matroska.pm +261 -45
- data/bin/lib/Image/ExifTool/Nikon.pm +470 -272
- data/bin/lib/Image/ExifTool/NikonCustom.pm +139 -106
- data/bin/lib/Image/ExifTool/Olympus.pm +3 -2
- data/bin/lib/Image/ExifTool/PNG.pm +8 -1
- data/bin/lib/Image/ExifTool/QuickTime.pm +4 -1
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +44 -11
- data/bin/lib/Image/ExifTool/README +2 -1
- data/bin/lib/Image/ExifTool/Sony.pm +4 -4
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +11 -6
- data/bin/lib/Image/ExifTool/TagLookup.pm +4543 -4491
- data/bin/lib/Image/ExifTool/TagNames.pod +227 -37
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +12 -7
- data/bin/lib/Image/ExifTool/WriteXMP.pl +15 -1
- data/bin/lib/Image/ExifTool/Writer.pl +33 -13
- data/bin/lib/Image/ExifTool/ZIP.pm +19 -7
- data/bin/lib/Image/ExifTool.pm +36 -15
- data/bin/perl-Image-ExifTool.spec +1 -1
- data/lib/exiftool_vendored/version.rb +1 -1
- metadata +3 -2
|
@@ -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.
|
|
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
|
|
@@ -58,7 +75,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
58
75
|
#
|
|
59
76
|
# General
|
|
60
77
|
#
|
|
61
|
-
0x3f => { Name => 'CRC-32',
|
|
78
|
+
0x3f => { Name => 'CRC-32', Format => 'unsigned', Unknown => 1 },
|
|
62
79
|
0x6c => { Name => 'Void', NoSave => 1, Unknown => 1 },
|
|
63
80
|
#
|
|
64
81
|
# Signature
|
|
@@ -104,18 +121,18 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
104
121
|
Name => 'Info',
|
|
105
122
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
|
|
106
123
|
},
|
|
107
|
-
0x33a4 => { Name => 'SegmentUID',
|
|
124
|
+
0x33a4 => { Name => 'SegmentUID', %uidInfo, Unknown => 1 },
|
|
108
125
|
0x3384 => { Name => 'SegmentFileName', Format => 'utf8' },
|
|
109
|
-
0x1cb923 => { Name => 'PrevUID',
|
|
126
|
+
0x1cb923 => { Name => 'PrevUID', %uidInfo, Unknown => 1 },
|
|
110
127
|
0x1c83ab => { Name => 'PrevFileName', Format => 'utf8' },
|
|
111
|
-
0x1eb923 => { Name => 'NextUID',
|
|
128
|
+
0x1eb923 => { Name => 'NextUID', %uidInfo, Unknown => 1 },
|
|
112
129
|
0x1e83bb => { Name => 'NextFileName', Format => 'utf8' },
|
|
113
130
|
0x0444 => { Name => 'SegmentFamily', Binary => 1, Unknown => 1 },
|
|
114
131
|
0x2924 => {
|
|
115
132
|
Name => 'ChapterTranslate',
|
|
116
133
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
|
|
117
134
|
},
|
|
118
|
-
0x29fc => { Name => 'ChapterTranslateEditionUID',
|
|
135
|
+
0x29fc => { Name => 'ChapterTranslateEditionUID', %uidInfo, Unknown => 1 },
|
|
119
136
|
0x29bf => {
|
|
120
137
|
Name => 'ChapterTranslateCodec',
|
|
121
138
|
Format => 'unsigned',
|
|
@@ -228,7 +245,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
228
245
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
|
|
229
246
|
},
|
|
230
247
|
0x57 => { Name => 'TrackNumber', Format => 'unsigned' },
|
|
231
|
-
0x33c5 => { Name => 'TrackUID',
|
|
248
|
+
0x33c5 => { Name => 'TrackUID', %uidInfo },
|
|
232
249
|
0x03 => {
|
|
233
250
|
Name => 'TrackType',
|
|
234
251
|
Format => 'unsigned',
|
|
@@ -305,7 +322,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
305
322
|
Format => 'utf8',
|
|
306
323
|
}
|
|
307
324
|
],
|
|
308
|
-
0x3446 => { Name => 'TrackAttachmentUID'
|
|
325
|
+
0x3446 => { Name => 'TrackAttachmentUID',%uidInfo },
|
|
309
326
|
0x1a9697=>{ Name => 'CodecSettings', Format => 'utf8' },
|
|
310
327
|
0x1b4040=>{ Name => 'CodecInfoURL', Format => 'string' },
|
|
311
328
|
0x6b240 =>{ Name => 'CodecDownloadURL', Format => 'string' },
|
|
@@ -315,7 +332,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
315
332
|
Name => 'TrackTranslate',
|
|
316
333
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
|
|
317
334
|
},
|
|
318
|
-
0x26fc => { Name => 'TrackTranslateEditionUID',
|
|
335
|
+
0x26fc => { Name => 'TrackTranslateEditionUID', %uidInfo, Unknown => 1 },
|
|
319
336
|
0x26bf => {
|
|
320
337
|
Name => 'TrackTranslateCodec',
|
|
321
338
|
Format => 'unsigned',
|
|
@@ -362,6 +379,8 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
362
379
|
0 => 'Pixels',
|
|
363
380
|
1 => 'cm',
|
|
364
381
|
2 => 'inches',
|
|
382
|
+
3 => 'Display Aspect Ratio',
|
|
383
|
+
4 => 'Unknown',
|
|
365
384
|
},
|
|
366
385
|
},
|
|
367
386
|
0x14b3 => {
|
|
@@ -517,7 +536,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
517
536
|
0x66e => { Name => 'AttachedFileName', Format => 'utf8' },
|
|
518
537
|
0x660 => { Name => 'AttachedFileMIMEType', Format => 'string' },
|
|
519
538
|
0x65c => { Name => 'AttachedFileData', Binary => 1 },
|
|
520
|
-
0x6ae => { Name => 'AttachedFileUID',
|
|
539
|
+
0x6ae => { Name => 'AttachedFileUID', %uidInfo },
|
|
521
540
|
0x675 => { Name => 'AttachedFileReferral', Binary => 1, Unknown => 1 },
|
|
522
541
|
#
|
|
523
542
|
# Chapters
|
|
@@ -530,7 +549,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
530
549
|
Name => 'EditionEntry',
|
|
531
550
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
|
|
532
551
|
},
|
|
533
|
-
0x5bc => { Name => 'EditionUID',
|
|
552
|
+
0x5bc => { Name => 'EditionUID', %uidInfo, Unknown => 1 },
|
|
534
553
|
0x5bd => { Name => 'EditionFlagHidden', Format => 'unsigned', Unknown => 1 },
|
|
535
554
|
0x5db => { Name => 'EditionFlagDefault',Format => 'unsigned', Unknown => 1 },
|
|
536
555
|
0x5dd => { Name => 'EditionFlagOrdered',Format => 'unsigned', Unknown => 1 },
|
|
@@ -538,7 +557,7 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
538
557
|
Name => 'ChapterAtom',
|
|
539
558
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
|
|
540
559
|
},
|
|
541
|
-
0x33c4 => { Name => 'ChapterUID',
|
|
560
|
+
0x33c4 => { Name => 'ChapterUID', %uidInfo, Unknown => 1 },
|
|
542
561
|
0x11 => {
|
|
543
562
|
Name => 'ChapterTimeStart',
|
|
544
563
|
Groups => { 1 => 'Chapter#' },
|
|
@@ -554,8 +573,8 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
554
573
|
},
|
|
555
574
|
0x18 => { Name => 'ChapterFlagHidden', Format => 'unsigned', Unknown => 1 },
|
|
556
575
|
0x598 => { Name => 'ChapterFlagEnabled',Format => 'unsigned', Unknown => 1 },
|
|
557
|
-
0x2e67=> { Name => 'ChapterSegmentUID',
|
|
558
|
-
0x2ebc=> { Name => 'ChapterSegmentEditionUID',
|
|
576
|
+
0x2e67=> { Name => 'ChapterSegmentUID', %uidInfo, Unknown => 1 },
|
|
577
|
+
0x2ebc=> { Name => 'ChapterSegmentEditionUID', %uidInfo, Unknown => 1 },
|
|
559
578
|
0x23c3 => {
|
|
560
579
|
Name => 'ChapterPhysicalEquivalent',
|
|
561
580
|
Format => 'unsigned',
|
|
@@ -622,21 +641,24 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
622
641
|
Name => 'Targets',
|
|
623
642
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
|
|
624
643
|
},
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
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 },
|
|
631
651
|
0x27c8 => {
|
|
632
652
|
Name => 'SimpleTag',
|
|
633
653
|
SubDirectory => { TagTable => 'Image::ExifTool::Matroska::Main' },
|
|
634
654
|
},
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
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 },
|
|
640
662
|
#
|
|
641
663
|
# Spherical Video V2 (untested)
|
|
642
664
|
#
|
|
@@ -685,6 +707,172 @@ my %noYes = ( 0 => 'No', 1 => 'Yes' );
|
|
|
685
707
|
0x7675 => { Name => 'ProjectionPoseRoll', Format => 'float' },
|
|
686
708
|
);
|
|
687
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
|
+
|
|
688
876
|
#------------------------------------------------------------------------------
|
|
689
877
|
# Get variable-length Matroska integer
|
|
690
878
|
# Inputs: 0) data buffer, 1) position in data
|
|
@@ -726,7 +914,7 @@ sub ProcessMKV($$)
|
|
|
726
914
|
{
|
|
727
915
|
my ($et, $dirInfo) = @_;
|
|
728
916
|
my $raf = $$dirInfo{RAF};
|
|
729
|
-
my ($buff, $buf2, @dirEnd, $trackIndent, %trackTypes);
|
|
917
|
+
my ($buff, $buf2, @dirEnd, $trackIndent, %trackTypes, $struct);
|
|
730
918
|
|
|
731
919
|
$raf->Read($buff, 4) == 4 or return 0;
|
|
732
920
|
return 0 unless $buff =~ /^\x1a\x45\xdf\xa3/;
|
|
@@ -751,14 +939,33 @@ sub ProcessMKV($$)
|
|
|
751
939
|
$$et{TrackTypes} = \%trackTypes; # store Track types reference
|
|
752
940
|
my $oldIndent = $$et{INDENT};
|
|
753
941
|
my $chapterNum = 0;
|
|
942
|
+
my $dirName = 'MKV';
|
|
754
943
|
|
|
755
944
|
# loop over all Matroska elements
|
|
756
945
|
for (;;) {
|
|
757
|
-
while (@dirEnd
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
+
}
|
|
762
969
|
}
|
|
763
970
|
# read more if we are getting close to the end of our buffer
|
|
764
971
|
# (24 more bytes should be enough to read this element header)
|
|
@@ -789,21 +996,27 @@ sub ProcessMKV($$)
|
|
|
789
996
|
}
|
|
790
997
|
my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
|
|
791
998
|
# just fall through into the contained EBML elements
|
|
792
|
-
if ($tagInfo
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
$
|
|
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;
|
|
804
1016
|
}
|
|
805
|
-
next;
|
|
806
1017
|
}
|
|
1018
|
+
} elsif ($verbose) {
|
|
1019
|
+
$et->VPrint(0,sprintf("$$et{INDENT}- Tag 0x%x (Unknown, %d bytes)\n", $tag, $size));
|
|
807
1020
|
}
|
|
808
1021
|
last if $unknownSize;
|
|
809
1022
|
if ($pos + $size > $dataLen) {
|
|
@@ -887,8 +1100,9 @@ sub ProcessMKV($$)
|
|
|
887
1100
|
Start => $pos,
|
|
888
1101
|
Size => $size,
|
|
889
1102
|
);
|
|
890
|
-
if ($$tagInfo{NoSave}) {
|
|
1103
|
+
if ($$tagInfo{NoSave} or $struct) {
|
|
891
1104
|
$et->VerboseInfo($tag, $tagInfo, Value => $val, %parms) if $verbose;
|
|
1105
|
+
$$struct{$$tagInfo{Name}} = $val if $struct;
|
|
892
1106
|
} else {
|
|
893
1107
|
$et->HandleTag($tagTablePtr, $tag, $val, %parms);
|
|
894
1108
|
}
|
|
@@ -937,6 +1151,8 @@ under the same terms as Perl itself.
|
|
|
937
1151
|
|
|
938
1152
|
=item L<http://www.matroska.org/technical/specs/index.html>
|
|
939
1153
|
|
|
1154
|
+
=item L<https://www.matroska.org/technical/tagging.html>
|
|
1155
|
+
|
|
940
1156
|
=back
|
|
941
1157
|
|
|
942
1158
|
=head1 SEE ALSO
|