Ignore:
Timestamp:
2021-02-26T19:39:51+13:00 (3 years ago)
Author:
anupama
Message:

Committing the improvements to EmbeddedMetaPlugin's processing of Keywords vs other metadata fields. Keywords were literally stored as arrays of words rather than phrases in PDFs (at least in Diego's sample PDF), whereas other meta fields like Subjects and Creators stored them as arrays of phrases. To get both to work, Kathy updated EXIF to a newer version, to retrieve the actual EXIF values stored in the PDF. And Kathy and Dr Bainbridge came up with a new option that I added called apply_join_before_split_to_metafields that's a regex which can list the metadata fields to apply the join_before_split to and whcih previously always got applied to all metadata fields. Now it's applied to any *Keywords metafields by default, as that's the metafield we have experience of that behaves differently to the others, as it stores by word instead of phrases. Tested on Diego's sample PDF. Diego has double-checked it to works on his sample PDF too, setting the split char to ; and turning on the join_before_split and leaving apply_join_before_split_to_metafields at its default of .*Keywords. File changes are strings.properties for the tooltip, the plugin introducing the option and working with it and Kathy's EXIF updates affecting cpan/File and cpan/Image.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone2/perllib/cpan/Image/ExifTool/QuickTime.pm

    r24107 r34921  
    22# File:         QuickTime.pm
    33#
    4 # Description:  Read QuickTime, MP4 and M4A meta information
     4# Description:  Read QuickTime and MP4 meta information
    55#
    66# Revisions:    10/04/2005 - P. Harvey Created
     
    99#               07/27/2010 - P. Harvey Updated to 2010-05-03 QuickTime spec
    1010#
    11 # References:   1) http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html
    12 #               2) http://search.cpan.org/dist/MP4-Info-1.04/
    13 #               3) http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
    14 #               4) http://wiki.multimedia.cx/index.php?title=Apple_QuickTime
    15 #               5) ISO 14496-12 (http://neuron2.net/library/avc/c041828_ISO_IEC_14496-12_2005(E).pdf)
    16 #               6) ISO 14496-16 (http://www.iec-normen.de/previewpdf/info_isoiec14496-16%7Bed2.0%7Den.pdf)
    17 #               7) http://atomicparsley.sourceforge.net/mpeg-4files.html
    18 #               8) http://wiki.multimedia.cx/index.php?title=QuickTime_container
    19 #               9) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart3.pdf (Oct 2008)
    20 #               10) http://code.google.com/p/mp4v2/wiki/iTunesMetadata
    21 #               11) http://www.canieti.com.mx/assets/files/1011/IEC_100_1384_DC.pdf
    22 #               12) QuickTime file format specification 2010-05-03
    23 #               13) http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v10.pdf
    24 #               14) http://standards.iso.org/ittf/PubliclyAvailableStandards/c051533_ISO_IEC_14496-12_2008.zip
     11# References:
     12#
     13#   1) http://developer.apple.com/mac/library/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html
     14#   2) http://search.cpan.org/dist/MP4-Info-1.04/
     15#   3) http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
     16#   4) http://wiki.multimedia.cx/index.php?title=Apple_QuickTime
     17#   5) ISO 14496-12 (http://read.pudn.com/downloads64/ebook/226547/ISO_base_media_file_format.pdf)
     18#   6) ISO 14496-16 (http://www.iec-normen.de/previewpdf/info_isoiec14496-16%7Bed2.0%7Den.pdf)
     19#   7) http://atomicparsley.sourceforge.net/mpeg-4files.html
     20#   8) http://wiki.multimedia.cx/index.php?title=QuickTime_container
     21#   9) http://www.adobe.com/devnet/xmp/pdfs/XMPSpecificationPart3.pdf (Oct 2008)
     22#   10) http://code.google.com/p/mp4v2/wiki/iTunesMetadata
     23#   11) http://www.canieti.com.mx/assets/files/1011/IEC_100_1384_DC.pdf
     24#   12) QuickTime file format specification 2010-05-03
     25#   13) http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v10.pdf
     26#   14) http://standards.iso.org/ittf/PubliclyAvailableStandards/c051533_ISO_IEC_14496-12_2008.zip
     27#   15) http://getid3.sourceforge.net/source/module.audio-video.quicktime.phps
     28#   16) http://qtra.apple.com/atoms.html
     29#   17) http://www.etsi.org/deliver/etsi_ts/126200_126299/126244/10.01.00_60/ts_126244v100100p.pdf
     30#   18) https://github.com/appsec-labs/iNalyzer/blob/master/scinfo.m
     31#   19) http://nah6.com/~itsme/cvs-xdadevtools/iphone/tools/decodesinf.pl
     32#   20) https://developer.apple.com/legacy/library/documentation/quicktime/reference/QT7-1_Update_Reference/QT7-1_Update_Reference.pdf
     33#   21) Francois Bonzon private communication
     34#   22) https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
     35#   23) http://atomicparsley.sourceforge.net/mpeg-4files.html
     36#   24) https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata
     37#   25) https://cconcolato.github.io/mp4ra/atoms.html
     38#   26) https://github.com/SamsungVR/android_upload_sdk/blob/master/SDKLib/src/main/java/com/samsung/msca/samsungvr/sdk/UserVideo.java
     39#   27) https://exiftool.org/forum/index.php?topic=11517.0
    2540#------------------------------------------------------------------------------
    2641
     
    2843
    2944use strict;
    30 use vars qw($VERSION);
     45use vars qw($VERSION $AUTOLOAD %stringEncoding);
    3146use Image::ExifTool qw(:DataAccess :Utils);
    3247use Image::ExifTool::Exif;
    33 
    34 $VERSION = '1.48';
    35 
    36 sub FixWrongFormat($);
     48use Image::ExifTool::GPS;
     49
     50$VERSION = '2.59';
     51
    3752sub ProcessMOV($$;$);
    3853sub ProcessKeys($$$);
     54sub ProcessMetaKeys($$$);
    3955sub ProcessMetaData($$$);
     56sub ProcessEncodingParams($$$);
     57sub ProcessSampleDesc($$$);
     58sub ProcessHybrid($$$);
     59sub ProcessRights($$$);
     60# ++vvvvvvvvvvvv++ (in QuickTimeStream.pl)
     61sub Process_mebx($$$);
     62sub Process_3gf($$$);
     63sub Process_gps0($$$);
     64sub Process_gsen($$$);
     65sub ProcessRIFFTrailer($$$);
     66sub ProcessTTAD($$$);
     67sub ProcessNMEA($$$);
     68sub SaveMetaKeys($$$);
     69# ++^^^^^^^^^^^^++
     70sub ParseItemLocation($$);
     71sub ParseContentDescribes($$);
     72sub ParseItemInfoEntry($$);
     73sub ParseItemPropAssoc($$);
     74sub FixWrongFormat($);
     75sub GetMatrixStructure($$);
    4076sub ConvertISO6709($);
     77sub ConvInvISO6709($);
     78sub ConvertChapterList($);
     79sub PrintChapter($);
    4180sub PrintGPSCoordinates($);
    42 
    43 # information for time/date-based tags (time zero is Jan 1, 1904)
    44 my %timeInfo = (
    45     # Note: This value will be in UTC if generated by a system that is aware of the time zone
    46     ValueConv => 'ConvertUnixTime($val - ((66 * 365 + 17) * 24 * 3600))',
    47     PrintConv => '$self->ConvertDateTime($val)',
    48     # (can't put Groups here because they aren't constant!)
    49 );
    50 # information for duration tags
    51 my %durationInfo = (
    52     ValueConv => '$$self{TimeScale} ? $val / $$self{TimeScale} : $val',
    53     PrintConv => '$$self{TimeScale} ? ConvertDuration($val) : $val',
    54 );
    55 
    56 # 4-character Vendor ID codes (ref PH)
    57 my %vendorID = (
    58     appl => 'Apple',
    59     fe20 => 'Olympus (fe20)', # (FE200)
    60     FFMP => 'FFmpeg',
    61    'GIC '=> 'General Imaging Co.',
    62     kdak => 'Kodak',
    63     KMPI => 'Konica-Minolta',
    64     mino => 'Minolta',
    65     niko => 'Nikon',
    66     NIKO => 'Nikon',
    67     olym => 'Olympus',
    68     pana => 'Panasonic',
    69     pent => 'Pentax',
    70     pr01 => 'Olympus (pr01)', # (FE100,FE110,FE115)
    71     sany => 'Sanyo',
    72    'SMI '=> 'Sorenson Media Inc.',
    73     ZORA => 'Zoran Corporation',
    74 );
    75 
    76 # QuickTime data atom encodings for string types (ref 12)
    77 my %stringEncoding = (
    78     1 => 'UTF8',
    79     2 => 'UTF16',
    80     3 => 'ShiftJIS',
    81     4 => 'UTF8',
    82     5 => 'UTF16',
    83 );
     81sub PrintInvGPSCoordinates($);
     82sub UnpackLang($;$);
     83sub WriteKeys($$$);
     84sub WriteQuickTime($$$);
     85sub WriteMOV($$);
     86sub GetLangInfo($$);
     87sub CheckQTValue($$$);
    8488
    8589# MIME types for all entries in the ftypLookup with file extensions
     
    8892   '3G2' => 'video/3gpp2',
    8993   '3GP' => 'video/3gpp',
     94    AAX  => 'audio/vnd.audible.aax',
    9095    DVB  => 'video/vnd.dvb.file',
    9196    F4A  => 'audio/mp4',
     
    100105    MOV  => 'video/quicktime',
    101106    MQV  => 'video/quicktime',
    102 );
    103 
    104 my %graphicsMode = (
    105     # (ref http://homepage.mac.com/vanhoek/MovieGuts%20docs/64.html)
    106     0x00 => 'srcCopy',
    107     0x01 => 'srcOr',
    108     0x02 => 'srcXor',
    109     0x03 => 'srcBic',
    110     0x04 => 'notSrcCopy',
    111     0x05 => 'notSrcOr',
    112     0x06 => 'notSrcXor',
    113     0x07 => 'notSrcBic',
    114     0x08 => 'patCopy',
    115     0x09 => 'patOr',
    116     0x0a => 'patXor',
    117     0x0b => 'patBic',
    118     0x0c => 'notPatCopy',
    119     0x0d => 'notPatOr',
    120     0x0e => 'notPatXor',
    121     0x0f => 'notPatBic',
    122     0x20 => 'blend',
    123     0x21 => 'addPin',
    124     0x22 => 'addOver',
    125     0x23 => 'subPin',
    126     0x24 => 'transparent',
    127     0x25 => 'addMax',
    128     0x26 => 'subOver',
    129     0x27 => 'addMin',
    130     0x31 => 'grayishTextOr',
    131     0x32 => 'hilite',
    132     0x40 => 'ditherCopy',
    133     # the following ref ISO/IEC 15444-3
    134     0x100 => 'Alpha',
    135     0x101 => 'White Alpha',
    136     0x102 => 'Pre-multiplied Black Alpha',
    137     0x110 => 'Component Alpha',
     107    HEIC => 'image/heic',
     108    HEVC => 'image/heic-sequence',
     109    HEICS=> 'image/heic-sequence',
     110    HEIF => 'image/heif',
     111    HEIFS=> 'image/heif-sequence',
     112    AVIF => 'image/avif', #PH (NC)
     113    CRX  => 'video/x-canon-crx',    # (will get overridden)
    138114);
    139115
     
    156132    '3gp6' => '3GPP Media (.3GP) Release 6 Streaming Servers', # video/3gpp
    157133    '3gs7' => '3GPP Media (.3GP) Release 7 Streaming Servers', # video/3gpp
     134    'aax ' => 'Audible Enhanced Audiobook (.AAX)', #PH
    158135    'avc1' => 'MP4 Base w/ AVC ext [ISO 14496-12:2005]', # video/mp4
    159136    'CAEP' => 'Canon Digital Camera',
     
    191168    'jpx ' => 'JPEG 2000 with extensions (.JPX) [ISO 15444-2]', # image/jpx
    192169    'KDDI' => '3GPP2 EZmovie for KDDI 3G cellphones', # video/3gpp2
     170    #LCAG  => (found in CompatibleBrands of Leica MOV videos)
    193171    'M4A ' => 'Apple iTunes AAC-LC (.M4A) Audio', # audio/x-m4a
    194172    'M4B ' => 'Apple iTunes AAC-LC (.M4B) Audio Book', # audio/mp4
     
    227205    'ssc1' => 'Samsung stereoscopic, single stream',
    228206    'ssc2' => 'Samsung stereoscopic, dual stream',
     207    'XAVC' => 'Sony XAVC', #PH
     208    'heic' => 'High Efficiency Image Format HEVC still image (.HEIC)', # image/heic
     209    'hevc' => 'High Efficiency Image Format HEVC sequence (.HEICS)', # image/heic-sequence
     210    'mif1' => 'High Efficiency Image Format still image (.HEIF)', # image/heif
     211    'msf1' => 'High Efficiency Image Format sequence (.HEIFS)', # image/heif-sequence
     212    'heix' => 'High Efficiency Image Format still image (.HEIF)', # image/heif (ref PH, Canon 1DXmkIII)
     213    'avif' => 'AV1 Image File Format (.AVIF)', # image/avif
     214    'crx ' => 'Canon Raw (.CRX)', #PH (CR3 or CRM; use Canon CompressorVersion to decide)
     215);
     216
     217# information for int32u date/time tags (time zero is Jan 1, 1904)
     218my %timeInfo = (
     219    Notes => 'converted from UTC to local time if the QuickTimeUTC option is set',
     220    Shift => 'Time',
     221    Writable => 1,
     222    Permanent => 1,
     223    DelValue => 0,
     224    # It is not uncommon for brain-dead software to use the wrong time zero,
     225    # so assume a time zero of Jan 1, 1970 if the date is before this
     226    # Note: This value will be in UTC if generated by a system that is aware of the time zone
     227    RawConv => q{
     228        my $offset = (66 * 365 + 17) * 24 * 3600;
     229        return $val - $offset if $val >= $offset or $$self{OPTIONS}{QuickTimeUTC};
     230        if ($val and not $$self{IsWriting}) {
     231            $self->WarnOnce('Patched incorrect time zero for QuickTime date/time tag',1);
     232        }
     233        return $val;
     234    },
     235    RawConvInv => q{
     236        if ($$self{FileType} eq 'CR3' and not $self->Options('QuickTimeUTC')) {
     237            # convert to UTC
     238            my $offset = (66 * 365 + 17) * 24 * 3600;
     239            $val = ConvertUnixTime($val - $offset);
     240            $val = GetUnixTime($val, 1) + $offset;
     241        }
     242        return $val;
     243    },
     244    # (all CR3 files store UTC times - PH)
     245    ValueConv => 'ConvertUnixTime($val, $self->Options("QuickTimeUTC") || $$self{FileType} eq "CR3")',
     246    ValueConvInv => 'GetUnixTime($val, $self->Options("QuickTimeUTC")) + (66 * 365 + 17) * 24 * 3600',
     247    PrintConv => '$self->ConvertDateTime($val)',
     248    PrintConvInv => '$self->InverseDateTime($val)',
     249    # (can't put Groups here because they aren't constant!)
     250);
     251# information for duration tags
     252my %durationInfo = (
     253    ValueConv => '$$self{TimeScale} ? $val / $$self{TimeScale} : $val',
     254    PrintConv => '$$self{TimeScale} ? ConvertDuration($val) : $val',
     255);
     256# handle unknown tags
     257my %unknownInfo = (
     258    Unknown => 1,
     259    ValueConv => '$val =~ /^([\x20-\x7e]*)\0*$/ ? $1 : \$val',
     260);
     261
     262# multi-language text with 6-byte header
     263my %langText = ( IText => 6 );
     264
     265# parsing for most of the 3gp udta language text boxes
     266my %langText3gp = (
     267    Notes => 'used in 3gp videos',
     268    Avoid => 1,
     269    IText => 6,
     270);
     271
     272# 4-character Vendor ID codes (ref PH)
     273my %vendorID = (
     274    appl => 'Apple',
     275    fe20 => 'Olympus (fe20)', # (FE200)
     276    FFMP => 'FFmpeg',
     277   'GIC '=> 'General Imaging Co.',
     278    kdak => 'Kodak',
     279    KMPI => 'Konica-Minolta',
     280    leic => 'Leica',
     281    mino => 'Minolta',
     282    niko => 'Nikon',
     283    NIKO => 'Nikon',
     284    olym => 'Olympus',
     285    pana => 'Panasonic',
     286    pent => 'Pentax',
     287    pr01 => 'Olympus (pr01)', # (FE100,FE110,FE115)
     288    sany => 'Sanyo',
     289   'SMI '=> 'Sorenson Media Inc.',
     290    ZORA => 'Zoran Corporation',
     291   'AR.D'=> 'Parrot AR.Drone',
     292   ' KD '=> 'Kodak', # (FZ201)
     293);
     294
     295# QuickTime data atom encodings for string types (ref 12)
     296%stringEncoding = (
     297    1 => 'UTF8',
     298    2 => 'UTF16',
     299    3 => 'ShiftJIS',
     300    4 => 'UTF8',
     301    5 => 'UTF16',
     302);
     303
     304my %graphicsMode = (
     305    # (ref http://homepage.mac.com/vanhoek/MovieGuts%20docs/64.html)
     306    0x00 => 'srcCopy',
     307    0x01 => 'srcOr',
     308    0x02 => 'srcXor',
     309    0x03 => 'srcBic',
     310    0x04 => 'notSrcCopy',
     311    0x05 => 'notSrcOr',
     312    0x06 => 'notSrcXor',
     313    0x07 => 'notSrcBic',
     314    0x08 => 'patCopy',
     315    0x09 => 'patOr',
     316    0x0a => 'patXor',
     317    0x0b => 'patBic',
     318    0x0c => 'notPatCopy',
     319    0x0d => 'notPatOr',
     320    0x0e => 'notPatXor',
     321    0x0f => 'notPatBic',
     322    0x20 => 'blend',
     323    0x21 => 'addPin',
     324    0x22 => 'addOver',
     325    0x23 => 'subPin',
     326    0x24 => 'transparent',
     327    0x25 => 'addMax',
     328    0x26 => 'subOver',
     329    0x27 => 'addMin',
     330    0x31 => 'grayishTextOr',
     331    0x32 => 'hilite',
     332    0x40 => 'ditherCopy',
     333    # the following ref ISO/IEC 15444-3
     334    0x100 => 'Alpha',
     335    0x101 => 'White Alpha',
     336    0x102 => 'Pre-multiplied Black Alpha',
     337    0x110 => 'Component Alpha',
     338);
     339
     340my %channelLabel = (
     341    0xFFFFFFFF => 'Unknown',
     342    0 => 'Unused',
     343    100 => 'UseCoordinates',
     344    1 => 'Left',
     345    2 => 'Right',
     346    3 => 'Center',
     347    4 => 'LFEScreen',
     348    5 => 'LeftSurround',
     349    6 => 'RightSurround',
     350    7 => 'LeftCenter',
     351    8 => 'RightCenter',
     352    9 => 'CenterSurround',
     353    10 => 'LeftSurroundDirect',
     354    11 => 'RightSurroundDirect',
     355    12 => 'TopCenterSurround',
     356    13 => 'VerticalHeightLeft',
     357    14 => 'VerticalHeightCenter',
     358    15 => 'VerticalHeightRight',
     359    16 => 'TopBackLeft',
     360    17 => 'TopBackCenter',
     361    18 => 'TopBackRight',
     362    33 => 'RearSurroundLeft',
     363    34 => 'RearSurroundRight',
     364    35 => 'LeftWide',
     365    36 => 'RightWide',
     366    37 => 'LFE2',
     367    38 => 'LeftTotal',
     368    39 => 'RightTotal',
     369    40 => 'HearingImpaired',
     370    41 => 'Narration',
     371    42 => 'Mono',
     372    43 => 'DialogCentricMix',
     373    44 => 'CenterSurroundDirect',
     374    45 => 'Haptic',
     375    200 => 'Ambisonic_W',
     376    201 => 'Ambisonic_X',
     377    202 => 'Ambisonic_Y',
     378    203 => 'Ambisonic_Z',
     379    204 => 'MS_Mid',
     380    205 => 'MS_Side',
     381    206 => 'XY_X',
     382    207 => 'XY_Y',
     383    301 => 'HeadphonesLeft',
     384    302 => 'HeadphonesRight',
     385    304 => 'ClickTrack',
     386    305 => 'ForeignLanguage',
     387    400 => 'Discrete',
     388    0x10000 => 'Discrete_0',
     389    0x10001 => 'Discrete_1',
     390    0x10002 => 'Discrete_2',
     391    0x10003 => 'Discrete_3',
     392    0x10004 => 'Discrete_4',
     393    0x10005 => 'Discrete_5',
     394    0x10006 => 'Discrete_6',
     395    0x10007 => 'Discrete_7',
     396    0x10008 => 'Discrete_8',
     397    0x10009 => 'Discrete_9',
     398    0x1000a => 'Discrete_10',
     399    0x1000b => 'Discrete_11',
     400    0x1000c => 'Discrete_12',
     401    0x1000d => 'Discrete_13',
     402    0x1000e => 'Discrete_14',
     403    0x1000f => 'Discrete_15',
     404    0x1ffff => 'Discrete_65535',
     405);
     406
     407# properties which don't get inherited from the parent
     408my %dontInherit = (
     409    ispe => 1,  # size of parent may be different
     410    hvcC => 1,  # (likely redundant)
     411);
     412
     413# tags that may be duplicated and directories that may contain duplicate tags
     414# (used only to avoid warnings when Validate-ing)
     415my %dupTagOK = ( mdat => 1, trak => 1, free => 1, infe => 1, sgpd => 1, dimg => 1, CCDT => 1,
     416                 sbgp => 1, csgm => 1, uuid => 1, cdsc => 1, maxr => 1, '----' => 1 );
     417my %dupDirOK = ( ipco => 1, '----' => 1 );
     418
     419# the usual atoms required to decode timed metadata with the ExtractEmbedded option
     420my %eeStd = ( stco => 'stbl', co64 => 'stbl', stsz => 'stbl', stz2 => 'stbl',
     421              stsc => 'stbl', stts => 'stbl' );
     422
     423# boxes and their containers for the various handler types that we want to save
     424# when the ExtractEmbedded is enabled (currently only the 'gps ' container name is
     425# used, but others have been checked against all available sample files and may be
     426# useful in the future if the names are used for different boxes on other locations)
     427my %eeBox = (
     428    # (note: vide is only processed if specific atoms exist in the VideoSampleDesc)
     429    vide => { %eeStd,
     430        JPEG => 'stsd',
     431    },
     432    text => { %eeStd },
     433    meta => { %eeStd },
     434    sbtl => { %eeStd },
     435    data => { %eeStd },
     436    camm => { %eeStd }, # (Insta360)
     437    ctbx => { %eeStd }, # (GM cars)
     438    ''   => { 'gps ' => 'moov', 'GPS ' => 'main' }, # (no handler -- in top level 'moov' box, and main)
     439);
     440# boxes to save when ExtractEmbedded is set to 2 or higher
     441my %eeBox2 = (
     442    vide => { avcC => 'stsd' }, # (parses H264 video stream)
    229443);
    230444
     
    232446%Image::ExifTool::QuickTime::Main = (
    233447    PROCESS_PROC => \&ProcessMOV,
     448    WRITE_PROC => \&WriteQuickTime, # (only needs to be defined for directories to process when writing)
    234449    GROUPS => { 2 => 'Video' },
    235     NOTES => q{
    236         The QuickTime format is used for many different types of audio, video and
    237         image files.  Exiftool extracts meta information from the UserData atom
    238         (including some proprietary manufacturer-specific information), as well as
    239         extracting various audio, video and image parameters.  Tags with a question
    240         mark after their name are not extracted unless the Unknown option is set.
    241     },
    242     free => { Unknown => 1, Binary => 1 },
    243     skip => { Unknown => 1, Binary => 1 },
     450    meta => { # 'meta' is found here in my Sony ILCE-7S MP4 sample - PH
     451        Name => 'Meta',
     452        SubDirectory => {
     453            TagTable => 'Image::ExifTool::QuickTime::Meta',
     454            Start => 4, # skip 4-byte version number header
     455        },
     456    },
     457    meco => { #ISO14496-12:2015
     458        Name => 'OtherMeta',
     459        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::OtherMeta' },
     460    },
     461    free => [
     462        {
     463            Name => 'KodakFree',
     464            # (found in Kodak M5370 MP4 videos)
     465            Condition => '$$valPt =~ /^\0\0\0.Seri/s',
     466            SubDirectory => { TagTable => 'Image::ExifTool::Kodak::Free' },
     467        },{
     468            Name => 'Pittasoft',
     469            # (Pittasoft Blackview dashcam MP4 videos)
     470            Condition => '$$valPt =~ /^\0\0..(cprt|sttm|ptnm|ptrh|thum|gps |3gf )/s',
     471            SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Pittasoft' },
     472        },{
     473            Unknown => 1,
     474            Binary => 1,
     475        },
     476        # (also Samsung WB750 uncompressed thumbnail data starting with "SDIC\0")
     477    ],
     478    # fre1 - 4 bytes: "june" (Kodak PixPro SP360)
     479    frea => {
     480        Name => 'Kodak_frea',
     481        SubDirectory => { TagTable => 'Image::ExifTool::Kodak::frea' },
     482    },
     483    skip => [
     484        {
     485            Name => 'CanonSkip',
     486            Condition => '$$valPt =~ /^\0.{3}(CNDB|CNCV|CNMN|CNFV|CNTH|CNDM)/s',
     487            SubDirectory => { TagTable => 'Image::ExifTool::Canon::Skip' },
     488        },
     489        {
     490            Name => 'PreviewImage', # (found in  DuDuBell M1 dashcam MOV files)
     491            Groups => { 2 => 'Preview' },
     492            Condition => '$$valPt =~ /^.{12}\xff\xd8\xff/',
     493            Binary => 1,
     494            RawConv => q{
     495                my $len = Get32u(\$val, 8);
     496                return undef unless length($val) >= $len + 12;
     497                return substr($val, 12, $len);
     498            },
     499        },
     500        { Name => 'Skip', Unknown => 1, Binary => 1 },
     501    ],
    244502    wide => { Unknown => 1, Binary => 1 },
    245503    ftyp => { #MP4
     
    253511    PICT => {
    254512        Name => 'PreviewPICT',
     513        Groups => { 2 => 'Preview' },
    255514        Binary => 1,
    256515    },
    257516    pict => { #8
    258517        Name => 'PreviewPICT',
     518        Groups => { 2 => 'Preview' },
    259519        Binary => 1,
    260520    },
     521    # (note that moov is present for an HEIF sequence)
    261522    moov => {
    262523        Name => 'Movie',
    263524        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Movie' },
    264525    },
    265     mdat => { Name => 'MovieData', Unknown => 1, Binary => 1 },
     526    moof => {
     527        Name => 'MovieFragment',
     528        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MovieFragment' },
     529    },
     530    # mfra - movie fragment random access: contains tfra (track fragment random access), and
     531    #           mfro (movie fragment random access offset) (ref 5)
     532    mdat => { Name => 'MediaData', Unknown => 1, Binary => 1 },
    266533    'mdat-size' => {
    267         Name => 'MovieDataSize',
     534        Name => 'MediaDataSize',
    268535        Notes => q{
    269536            not a real tag ID, this tag represents the size of the 'mdat' data in bytes
     
    271538        },
    272539    },
     540    'mdat-offset' => 'MediaDataOffset',
    273541    junk => { Unknown => 1, Binary => 1 }, #8
    274542    uuid => [
    275543        { #9 (MP4 files)
    276             Name => 'UUID-XMP',
     544            Name => 'XMP',
     545            # *** this is where ExifTool writes XMP in MP4 videos (as per XMP spec) ***
    277546            Condition => '$$valPt=~/^\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac/',
     547            WriteGroup => 'XMP',    # (write main XMP tags here)
    278548            SubDirectory => {
    279549                TagTable => 'Image::ExifTool::XMP::Main',
     
    291561        { #PH (Flip MP4 files)
    292562            Name => 'UUID-Flip',
    293             Condition => '$$valPt=~/\x4a\xb0\x3b\x0f\x61\x8d\x40\x75\x82\xb2\xd9\xfa\xce\xd3\x5f\xf5/',
     563            Condition => '$$valPt=~/^\x4a\xb0\x3b\x0f\x61\x8d\x40\x75\x82\xb2\xd9\xfa\xce\xd3\x5f\xf5/',
    294564            SubDirectory => {
    295565                TagTable => 'Image::ExifTool::QuickTime::Flip',
     
    298568        },
    299569        # "\x98\x7f\xa3\xdf\x2a\x85\x43\xc0\x8f\x8f\xd9\x7c\x47\x1e\x8e\xea" - unknown data in Flip videos
     570        { #PH (Canon CR3)
     571            Name => 'UUID-Canon2',
     572            WriteLast => 1, # MUST come after mdat or DPP will drop mdat when writing!
     573            Condition => '$$valPt=~/^\x21\x0f\x16\x87\x91\x49\x11\xe4\x81\x11\x00\x24\x21\x31\xfc\xe4/',
     574            SubDirectory => {
     575                TagTable => 'Image::ExifTool::Canon::uuid2',
     576                Start => 16,
     577            },
     578        },
     579        { # (ref https://github.com/JamesHeinrich/getID3/blob/master/getid3/module.audio-video.quicktime.php)
     580            Name => 'SensorData', # sensor data for the 360Fly
     581            Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/ and $$self{OPTIONS}{ExtractEmbedded}',
     582            SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Tags360Fly' },
     583        },
     584        {
     585            Name => 'SensorData',
     586            Condition => '$$valPt=~/^\xef\xe1\x58\x9a\xbb\x77\x49\xef\x80\x95\x27\x75\x9e\xb1\xdc\x6f/',
     587            Notes => 'raw 360Fly sensor data without ExtractEmbedded option',
     588            RawConv => q{
     589                $self->WarnOnce('Use the ExtractEmbedded option to decode timed SensorData',3);
     590                return \$val;
     591            },
     592        },
     593        { #PH (Canon CR3)
     594            Name => 'PreviewImage',
     595            Condition => '$$valPt=~/^\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16/',
     596            Groups => { 2 => 'Preview' },
     597            # 0x00 - undef[16]: UUID
     598            # 0x10 - int32u[2]: "0 1" (version and/or item count?)
     599            # 0x18 - int32u: PRVW atom size
     600            # 0x20 - int32u: 'PRVW'
     601            # 0x30 - int32u: 0
     602            # 0x34 - int16u: 1
     603            # 0x36 - int16u: image width
     604            # 0x38 - int16u: image height
     605            # 0x3a - int16u: 1
     606            # 0x3c - int32u: preview length
     607            RawConv => '$val = substr($val, 0x30); $self->ValidateImage(\$val, $tag)',
     608        },
    300609        { #8
    301610            Name => 'UUID-Unknown',
    302             Unknown => 1,
    303             Binary => 1,
     611            %unknownInfo,
    304612        },
    305613    ],
     614    _htc => {
     615        Name => 'HTCInfo',
     616        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HTCInfo' },
     617    },
     618    udta => {
     619        Name => 'UserData',
     620        SubDirectory => { TagTable => 'Image::ExifTool::FLIR::UserData' },
     621    },
     622    thum => { #PH
     623        Name => 'ThumbnailImage',
     624        Groups => { 2 => 'Preview' },
     625        Binary => 1,
     626    },
     627   'thm ' => { #PH (70mai A800)
     628        Name => 'ThumbnailImage',
     629        Groups => { 2 => 'Preview' },
     630        Binary => 1,
     631    },
     632    ardt => { #PH
     633        Name => 'ARDroneFile',
     634        ValueConv => 'length($val) > 4 ? substr($val,4) : $val', # remove length
     635    },
     636    prrt => { #PH
     637        Name => 'ARDroneTelemetry',
     638        Notes => q{
     639            telemetry information for each video frame: status1, status2, time, pitch,
     640            roll, yaw, speed, altitude
     641        },
     642        ValueConv => q{
     643            my $size = length $val;
     644            return \$val if $size < 12 or not $$self{OPTIONS}{Binary};
     645            my $len = Get16u(\$val, 2);
     646            my $str = '';
     647            SetByteOrder('II');
     648            my $pos = 12;
     649            while ($pos + $len <= $size) {
     650                my $s1 = Get16u(\$val, $pos);
     651                # s2: 7=take-off?, 3=moving, 4=hovering, 9=landing?, 2=landed
     652                my $s2 = Get16u(\$val, $pos + 2);
     653                $str .= "$s1 $s2";
     654                my $num = int(($len-4)/4);
     655                my ($i, $v);
     656                for ($i=0; $i<$num; ++$i) {
     657                    my $pt = $pos + 4 + $i * 4;
     658                    if ($i > 0 && $i < 4) {
     659                        $v = GetFloat(\$val, $pt); # pitch/roll/yaw
     660                    } else {
     661                        $v = Get32u(\$val, $pt);
     662                        # convert time to sec, and speed(NC)/altitude to metres
     663                        $v /= 1000 if $i <= 5;
     664                    }
     665                    $str .= " $v";
     666                }
     667                $str .= "\n";
     668                $pos += $len;
     669            }
     670            SetByteOrder('MM');
     671            return \$str;
     672        },
     673    },
     674    udat => { #PH (GPS NMEA-format log written by Datakam Player software)
     675        Name => 'GPSLog',
     676        Binary => 1,    # (actually ASCII, but very lengthy)
     677    },
     678    # meta - proprietary XML information written by some Flip cameras - PH
     679    # beam - 16 bytes found in an iPhone video
     680    IDIT => { #PH (written by DuDuBell M1, VSYS M6L dashcams)
     681        Name => 'DateTimeOriginal',
     682        Description => 'Date/Time Original',
     683        Groups => { 2 => 'Time' },
     684        Format => 'string', # (removes trailing "\0")
     685        Shift => 'Time',
     686        Writable => 1,
     687        Permanent => 1,
     688        DelValue => '0000-00-00T00:00:00+0000',
     689        ValueConv => '$val=~tr/-/:/; $val',
     690        ValueConvInv => '$val=~s/(\d+):(\d+):/$1-$2-/; $val',
     691        PrintConv => '$self->ConvertDateTime($val)',
     692        PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
     693    },
     694    gps0 => { #PH (DuDuBell M1, VSYS M6L)
     695        Name => 'GPSTrack',
     696        SubDirectory => {
     697            TagTable => 'Image::ExifTool::QuickTime::Stream',
     698            ProcessProc => \&Process_gps0,
     699        },
     700    },
     701    gsen => { #PH (DuDuBell M1, VSYS M6L)
     702        Name => 'GSensor',
     703        SubDirectory => {
     704            TagTable => 'Image::ExifTool::QuickTime::Stream',
     705            ProcessProc => \&Process_gsen,
     706        },
     707    },
     708    # gpsa - seen hex "01 20 00 00" (DuDuBell M1, VSYS M6L)
     709    # gsea - 20 bytes hex "05 00's..." (DuDuBell M1) "05 08 02 01 ..." (VSYS M6L)
     710   'GPS ' => {  # GPS data written by 70mai dashcam (parsed in QuickTimeStream.pl)
     711        Name => 'GPSDataList2',
     712        Unknown => 1,
     713        Binary => 1,
     714    },
    306715);
    307716
     
    326735        Format => 'undef[$size-8]',
    327736        # ignore any entry with a null, and return others as a list
    328         ValueConv => 'my @a=($val=~/.{4}/sg); @a=grep(!/\0/,@a); \@a',
     737        ValueConv => 'my @a=($val=~/.{4}/sg); @a=grep(!/\0/,@a); \@a',
     738    },
     739);
     740
     741# proprietary HTC atom (HTC One MP4 video)
     742%Image::ExifTool::QuickTime::HTCInfo = (
     743    PROCESS_PROC => \&ProcessMOV,
     744    GROUPS => { 2 => 'Video' },
     745    NOTES => 'Tags written by some HTC camera phones.',
     746    slmt => {
     747        Name => 'Unknown_slmt',
     748        Unknown => 1,
     749        Format => 'int32u', # (observed values: 4)
    329750    },
    330751);
     
    351772# image description data block
    352773%Image::ExifTool::QuickTime::ImageDesc = (
    353     PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     774    PROCESS_PROC => \&ProcessHybrid,
     775    VARS => { ID_LABEL => 'ID/Index' },
    354776    GROUPS => { 2 => 'Image' },
    355777    FORMAT => 'int16u',
     
    385807#            v410 => "Uncompressed Y'CbCr, 10-bit 4:4:4",
    386808#            v210 => "Uncompressed Y'CbCr, 10-bit 4:2:2",
     809#            hvc1 => 'HEVC', #PH
    387810#        },
    388811    },
     
    410833    },
    411834    41 => 'BitDepth',
     835#
     836# Observed offsets for child atoms of various CompressorID types:
     837#
     838#   CompressorID  Offset  Child atoms
     839#   -----------   ------  ----------------
     840#   avc1          86      avcC, btrt, colr, pasp, fiel, clap, svcC
     841#   mp4v          86      esds, pasp
     842#   s263          86      d263
     843#
     844    btrt => {
     845        Name => 'BitrateInfo',
     846        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Bitrate' },
     847    },
     848    # Reference for fiel, colr, pasp, clap:
     849    # https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
     850    fiel => {
     851        Name => 'VideoFieldOrder',
     852        ValueConv => 'join(" ", unpack("C*",$val))',
     853        PrintConv => [{
     854            1 => 'Progressive',
     855            2 => '2:1 Interlaced',
     856        }],
     857    },
     858    colr => {
     859        Name => 'ColorRepresentation',
     860        ValueConv => 'join(" ", substr($val,0,4), unpack("x4n*",$val))',
     861    },
     862    pasp => {
     863        Name => 'PixelAspectRatio',
     864        ValueConv => 'join(":", unpack("N*",$val))',
     865    },
     866    clap => {
     867        Name => 'CleanAperture',
     868        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::CleanAperture' },
     869    },
     870    avcC => {
     871        # (see http://thompsonng.blogspot.ca/2010/11/mp4-file-format-part-2.html)
     872        Name => 'AVCConfiguration',
     873        Unknown => 1,
     874        Binary => 1,
     875    },
     876    JPEG => { # (found in CR3 images; used as a flag to identify JpgFromRaw 'vide' stream)
     877        Name => 'JPEGInfo',
     878        # (4 bytes all zero)
     879        Unknown => 1,
     880        Binary => 1,
     881    },
     882    # hvcC - HEVC configuration
     883    # svcC - 7 bytes: 00 00 00 00 ff e0 00
     884    # esds - elementary stream descriptor
     885    # d263
     886    gama => { Name => 'Gamma', Format => 'fixed32u' },
     887    # mjqt - default quantization table for MJPEG
     888    # mjht - default Huffman table for MJPEG
     889    # csgm ? (seen in hevc video)
     890    CMP1 => { # Canon CR3
     891        Name => 'CMP1',
     892        SubDirectory => { TagTable => 'Image::ExifTool::Canon::CMP1' },
     893    },
     894    CDI1 => { # Canon CR3
     895        Name => 'CDI1',
     896        SubDirectory => {
     897            TagTable => 'Image::ExifTool::Canon::CDI1',
     898            Start => 4,
     899        },
     900    },
     901    # JPEG - 4 bytes all 0 (Canon CR3)
     902    # free - (Canon CR3)
     903#
     904# spherical video v2 stuff (untested)
     905#
     906    st3d => {
     907        Name => 'Stereoscopic3D',
     908        Format => 'int8u',
     909        ValueConv => '$val =~ s/.* //; $val', # (remove leading version/flags bytes?)
     910        PrintConv => {
     911            0 => 'Monoscopic',
     912            1 => 'Stereoscopic Top-Bottom',
     913            2 => 'Stereoscopic Left-Right',
     914            3 => 'Stereoscopic Stereo-Custom', # (provisional in spec as of 2017-10-10)
     915        },
     916    },
     917    sv3d => {
     918        Name => 'SphericalVideo',
     919        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::sv3d' },
     920    },
     921);
     922
     923# 'sv3d' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md)
     924%Image::ExifTool::QuickTime::sv3d = (
     925    PROCESS_PROC => \&ProcessMOV,
     926    GROUPS => { 2 => 'Video' },
     927    NOTES => q{
     928        Tags defined by the Spherical Video V2 specification.  See
     929        L<https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md>
     930        for the specification.
     931    },
     932    svhd => {
     933        Name => 'MetadataSource',
     934        Format => 'undef',
     935        ValueConv => '$val=~tr/\0//d; $val', # (remove version/flags? and terminator?)
     936    },
     937    proj => {
     938        Name => 'Projection',
     939        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::proj' },
     940    },
     941);
     942
     943# 'proj' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md)
     944%Image::ExifTool::QuickTime::proj = (
     945    PROCESS_PROC => \&ProcessMOV,
     946    GROUPS => { 2 => 'Video' },
     947    prhd => {
     948        Name => 'ProjectionHeader',
     949        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::prhd' },
     950    },
     951    cbmp => {
     952        Name => 'CubemapProj',
     953        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::cbmp' },
     954    },
     955    equi => {
     956        Name => 'EquirectangularProj',
     957        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::equi' },
     958    },
     959    # mshp - MeshProjection (P.I.T.A. to decode, for not much reward, see ref)
     960);
     961
     962# 'prhd' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md)
     963%Image::ExifTool::QuickTime::prhd = (
     964    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     965    GROUPS => { 2 => 'Video' },
     966    FORMAT => 'fixed32s',
     967    # 0 - version (high 8 bits) / flags (low 24 bits)
     968    1 => 'PoseYawDegrees',
     969    2 => 'PosePitchDegrees',
     970    3 => 'PoseRollDegrees',
     971);
     972
     973# 'cbmp' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md)
     974%Image::ExifTool::QuickTime::cbmp = (
     975    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     976    GROUPS => { 2 => 'Video' },
     977    FORMAT => 'int32u',
     978    # 0 - version (high 8 bits) / flags (low 24 bits)
     979    1 => 'Layout',
     980    2 => 'Padding',
     981);
     982
     983# 'equi' atom information (ref https://github.com/google/spatial-media/blob/master/docs/spherical-video-v2-rfc.md)
     984%Image::ExifTool::QuickTime::equi = (
     985    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     986    GROUPS => { 2 => 'Video' },
     987    FORMAT => 'int32u', # (actually 0.32 fixed point)
     988    # 0 - version (high 8 bits) / flags (low 24 bits)
     989    1 => { Name => 'ProjectionBoundsTop',   ValueConv => '$val / 4294967296' },
     990    2 => { Name => 'ProjectionBoundsBottom',ValueConv => '$val / 4294967296' },
     991    3 => { Name => 'ProjectionBoundsLeft',  ValueConv => '$val / 4294967296' },
     992    4 => { Name => 'ProjectionBoundsRight', ValueConv => '$val / 4294967296' },
     993);
     994
     995# 'btrt' atom information (ref http://lists.freedesktop.org/archives/gstreamer-commits/2011-October/054459.html)
     996%Image::ExifTool::QuickTime::Bitrate = (
     997    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     998    GROUPS => { 2 => 'Video' },
     999    FORMAT => 'int32u',
     1000    PRIORITY => 0, # often filled with zeros
     1001    0 => 'BufferSize',
     1002    1 => 'MaxBitrate',
     1003    2 => 'AverageBitrate',
     1004);
     1005
     1006# 'clap' atom information (ref https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9)
     1007%Image::ExifTool::QuickTime::CleanAperture = (
     1008    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     1009    GROUPS => { 2 => 'Video' },
     1010    FORMAT => 'rational64s',
     1011    0 => 'CleanApertureWidth',
     1012    1 => 'CleanApertureHeight',
     1013    2 => 'CleanApertureOffsetX',
     1014    3 => 'CleanApertureOffsetY',
    4121015);
    4131016
     
    4151018%Image::ExifTool::QuickTime::Preview = (
    4161019    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     1020    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
     1021    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
    4171022    GROUPS => { 2 => 'Image' },
    4181023    FORMAT => 'int16u',
     
    4341039%Image::ExifTool::QuickTime::Movie = (
    4351040    PROCESS_PROC => \&ProcessMOV,
     1041    WRITE_PROC => \&WriteQuickTime,
    4361042    GROUPS => { 2 => 'Video' },
    4371043    mvhd => {
     
    4411047    trak => {
    4421048        Name => 'Track',
     1049        CanCreate => 0, # don't create this atom
    4431050        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Track' },
    4441051    },
     
    4641071            },
    4651072        },
     1073        { #PH (Canon SX280)
     1074            Name => 'UUID-Canon',
     1075            Condition => '$$valPt=~/^\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48/',
     1076            SubDirectory => {
     1077                TagTable => 'Image::ExifTool::Canon::uuid',
     1078                Start => 16,
     1079            },
     1080        },
    4661081        {
    4671082            Name => 'UUID-Unknown',
    468             Unknown => 1,
    469             Binary => 1,
     1083            %unknownInfo,
    4701084        },
    4711085    ],
     1086    cmov => {
     1087        Name => 'CompressedMovie',
     1088        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::CMovie' },
     1089    },
     1090    htka => { # (written by HTC One M8 in slow-motion 1280x720 video - PH)
     1091        Name => 'HTCTrack',
     1092        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Track' },
     1093    },
     1094   'gps ' => {  # GPS data written by Novatek cameras (parsed in QuickTimeStream.pl)
     1095        Name => 'GPSDataList',
     1096        Unknown => 1,
     1097        Binary => 1,
     1098    },
     1099    meco => { #ISO14496-12:2015
     1100        Name => 'OtherMeta',
     1101        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::OtherMeta' },
     1102    },
    4721103    # prfl - Profile (ref 12)
    4731104    # clip - clipping --> contains crgn (clip region) (ref 12)
    4741105    # mvex - movie extends --> contains mehd (movie extends header), trex (track extends) (ref 14)
     1106    # ICAT - 4 bytes: "6350" (Nikon CoolPix S6900), "6500" (Panasonic FT7)
     1107);
     1108
     1109# (ref CFFMediaFormat-2_1.pdf)
     1110%Image::ExifTool::QuickTime::MovieFragment = (
     1111    PROCESS_PROC => \&ProcessMOV,
     1112    WRITE_PROC => \&WriteQuickTime,
     1113    GROUPS => { 2 => 'Video' },
     1114    mfhd => {
     1115        Name => 'MovieFragmentHeader',
     1116        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MovieFragHdr' },
     1117    },
     1118    traf => {
     1119        Name => 'TrackFragment',
     1120        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackFragment' },
     1121    },
     1122    meta => { #ISO14496-12:2015
     1123        Name => 'Meta',
     1124        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' },
     1125    },
     1126);
     1127
     1128# (ref CFFMediaFormat-2_1.pdf)
     1129%Image::ExifTool::QuickTime::MovieFragHdr = (
     1130    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     1131    GROUPS => { 2 => 'Video' },
     1132    FORMAT => 'int32u',
     1133    1 => 'MovieFragmentSequence',
     1134);
     1135
     1136# (ref CFFMediaFormat-2_1.pdf)
     1137%Image::ExifTool::QuickTime::TrackFragment = (
     1138    PROCESS_PROC => \&ProcessMOV,
     1139    WRITE_PROC => \&WriteQuickTime,
     1140    GROUPS => { 2 => 'Video' },
     1141    meta => { #ISO14496-12:2015
     1142        Name => 'Meta',
     1143        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' },
     1144    },
     1145    # tfhd - track fragment header
     1146    # edts - edits --> contains elst (edit list) (ref PH)
     1147    # tfdt - track fragment base media decode time
     1148    # trik - trick play box
     1149    # trun - track fragment run box
     1150    # avcn - AVC NAL unit storage box
     1151    # secn - sample encryption box
     1152    # saio - sample auxiliary information offsets box
     1153    # sbgp - sample to group box
     1154    # sgpd - sample group description box
     1155    # sdtp - independent and disposable samples (ref 5)
     1156    # subs - sub-sample information (ref 5)
    4751157);
    4761158
     
    4781160%Image::ExifTool::QuickTime::MovieHeader = (
    4791161    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     1162    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
     1163    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
    4801164    GROUPS => { 2 => 'Video' },
    4811165    FORMAT => 'int32u',
     1166    DATAMEMBER => [ 0, 1, 2, 3, 4 ],
    4821167    0 => {
    4831168        Name => 'MovieHeaderVersion',
     
    5411226%Image::ExifTool::QuickTime::Track = (
    5421227    PROCESS_PROC => \&ProcessMOV,
    543     GROUPS => { 2 => 'Video' },
     1228    WRITE_PROC => \&WriteQuickTime,
     1229    GROUPS => { 1 => 'Track#', 2 => 'Video' },
    5441230    tkhd => {
    5451231        Name => 'TrackHeader',
     
    5611247        Name => 'TrackRef',
    5621248        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackRef' },
     1249    },
     1250    tapt => {
     1251        Name => 'TrackAperture',
     1252        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TrackAperture' },
    5631253    },
    5641254    uuid => [
     
    5711261            },
    5721262        },
     1263        { #https://github.com/google/spatial-media/blob/master/docs/spherical-video-rfc.md
     1264            Name => 'SphericalVideoXML',
     1265            Condition => '$$valPt=~/^\xff\xcc\x82\x63\xf8\x55\x4a\x93\x88\x14\x58\x7a\x02\x52\x1f\xdd/',
     1266            WriteGroup => 'GSpherical', # write only GSpherical XMP tags here
     1267            HandlerType => 'vide',      # only write in video tracks
     1268            SubDirectory => {
     1269                TagTable => 'Image::ExifTool::XMP::Main',
     1270                Start => 16,
     1271                WriteProc => 'Image::ExifTool::XMP::WriteGSpherical',
     1272            },
     1273        },
    5731274        {
    5741275            Name => 'UUID-Unknown',
    575             Unknown => 1,
    576             Binary => 1,
     1276            %unknownInfo,
    5771277        },
    5781278    ],
     1279    meco => { #ISO14492-12:2015 pg 83
     1280        Name => 'OtherMeta',
     1281        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::OtherMeta' },
     1282    },
    5791283    # edts - edits --> contains elst (edit list)
    580     # tapt - TrackApertureModeDimensionsAID --> contains clef (TrackCleanApertureDimensionsAID),
    581     #        prof (TrackProductionApertureDimensionsAID), enof (TrackEncodedPixelsDimensionsAID)
    5821284    # clip - clipping --> contains crgn (clip region)
    5831285    # matt - track matt --> contains kmat (compressed matt)
     
    5901292%Image::ExifTool::QuickTime::TrackHeader = (
    5911293    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     1294    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
     1295    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
    5921296    GROUPS => { 1 => 'Track#', 2 => 'Video' },
    5931297    FORMAT => 'int32u',
     1298    DATAMEMBER => [ 0, 1, 2, 5, 7 ],
    5941299    0 => {
    5951300        Name => 'TrackHeaderVersion',
     
    6251330        Hook => '$$self{TrackHeaderVersion} and $format = "int64u", $varSize += 4',
    6261331    },
     1332    7 => { # (used only for writing MatrixStructure)
     1333        Name => 'ImageSizeLookahead',
     1334        Hidden => 1,
     1335        Format => 'int32u[14]',
     1336        RawConv => '$$self{ImageSizeLookahead} = $val; undef',
     1337    },
    6271338    8 => {
    6281339        Name => 'TrackLayer',
     
    6401351        Name => 'MatrixStructure',
    6411352        Format => 'fixed32s[9]',
     1353        Notes => 'writable for the video track via the Composite Rotation tag',
     1354        Writable => 1,
     1355        Protected => 1,
     1356        Permanent => 1,
     1357        # only set rotation if image size is non-zero
     1358        RawConvInv => \&GetMatrixStructure,
    6421359        # (the right column is fixed 2.30 instead of 16.16)
    6431360        ValueConv => q{
     
    6461363            return "@a";
    6471364        },
     1365        ValueConvInv => q{
     1366            my @a = split ' ',$val;
     1367            $_ *= 0x4000 foreach @a[2,5,8];
     1368            return "@a";
     1369        },
    6481370    },
    6491371    19 => {
     
    6621384%Image::ExifTool::QuickTime::UserData = (
    6631385    PROCESS_PROC => \&ProcessMOV,
    664     GROUPS => { 2 => 'Video' },
     1386    WRITE_PROC => \&WriteQuickTime,
     1387    CHECK_PROC => \&CheckQTValue,
     1388    GROUPS => { 1 => 'UserData', 2 => 'Video' },
     1389    WRITABLE => 1,
     1390    PREFERRED => 1, # (preferred over Keys tags when writing)
     1391    FORMAT => 'string',
     1392    WRITE_GROUP => 'UserData',
     1393    LANG_INFO => \&GetLangInfo,
    6651394    NOTES => q{
    6661395        Tag ID's beginning with the copyright symbol (hex 0xa9) are multi-language
    667         text.  Alternate language tags are accessed by adding a dash followed by the
    668         language/country code to the tag name.  ExifTool will extract any
    669         multi-language user data tags found, even if they don't exist in this table.
     1396        text.  Alternate language tags are accessed by adding a dash followed by a
     1397        3-character ISO 639-2 language code to the tag name.  ExifTool will extract
     1398        any multi-language user data tags found, even if they aren't in this table.
     1399        Note when creating new tags,
     1400        L<ItemList|Image::ExifTool::TagNames/QuickTime ItemList Tags> tags are
     1401        preferred over these, so to create the tag when a same-named ItemList tag
     1402        exists, either "UserData" must be specified (eg. C<-UserData:Artist=Monet>
     1403        on the command line), or the PREFERRED level must be changed via
     1404        L<the config file|../config.html#PREF>.
    6701405    },
    6711406    "\xa9cpy" => { Name => 'Copyright',  Groups => { 2 => 'Author' } },
    6721407    "\xa9day" => {
    673         Name => 'CreateDate',
     1408        Name => 'ContentCreateDate',
    6741409        Groups => { 2 => 'Time' },
     1410        Shift => 'Time',
    6751411        # handle values in the form "2010-02-12T13:27:14-0800" (written by Apple iPhone)
    6761412        ValueConv => q{
     
    6801416            return $val;
    6811417        },
     1418        ValueConvInv => q{
     1419            require Image::ExifTool::XMP;
     1420            my $tmp = Image::ExifTool::XMP::FormatXMPDate($val);
     1421            ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon
     1422            return $val;
     1423        },
    6821424        PrintConv => '$self->ConvertDateTime($val)',
     1425        PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
    6831426    },
    6841427    "\xa9ART" => 'Artist', #PH (iTunes 8.0.2)
     
    7171460    "\xa9prk" => 'PerformerKeywords', #12
    7181461    "\xa9prl" => 'PerformerURL',
    719     "\xa9dir" => 'Director', #12
    7201462    "\xa9req" => 'Requirements',
    7211463    "\xa9snk" => 'SubtitleKeywords', #12
     
    7271469    "\xa9too" => 'Encoder', #PH (NC)
    7281470    "\xa9trk" => 'Track', #PH (NC)
    729     "\xa9wrt" => 'Composer',
     1471    "\xa9wrt" => { Name => 'Composer', Avoid => 1 }, # ("\xa9com" is preferred in UserData)
    7301472    "\xa9xyz" => { #PH (iPhone 3GS)
    7311473        Name => 'GPSCoordinates',
    7321474        Groups => { 2 => 'Location' },
    7331475        ValueConv => \&ConvertISO6709,
     1476        ValueConvInv => \&ConvInvISO6709,
    7341477        PrintConv => \&PrintGPSCoordinates,
    735     },
     1478        PrintConvInv => \&PrintInvGPSCoordinates,
     1479    },
     1480    # \xa9 tags written by DJI Phantom 3: (ref PH)
     1481    "\xa9xsp" => 'SpeedX', #PH (guess)
     1482    "\xa9ysp" => 'SpeedY', #PH (guess)
     1483    "\xa9zsp" => 'SpeedZ', #PH (guess)
     1484    "\xa9fpt" => 'Pitch', #PH
     1485    "\xa9fyw" => 'Yaw', #PH
     1486    "\xa9frl" => 'Roll', #PH
     1487    "\xa9gpt" => 'CameraPitch', #PH
     1488    "\xa9gyw" => 'CameraYaw', #PH
     1489    "\xa9grl" => 'CameraRoll', #PH
     1490    "\xa9enc" => 'EncoderID', #PH (forum9271)
     1491    # and the following entries don't have the proper 4-byte header for \xa9 tags:
     1492    "\xa9dji" => { Name => 'UserData_dji', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 },
     1493    "\xa9res" => { Name => 'UserData_res', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 },
     1494    "\xa9uid" => { Name => 'UserData_uid', Format => 'undef', Binary => 1, Unknown => 1, Hidden => 1 },
     1495    "\xa9mdl" => {
     1496        Name => 'Model',
     1497        Notes => 'non-standard-format DJI tag',
     1498        Format => 'string',
     1499        Avoid => 1,
     1500    },
     1501    # end DJI tags
    7361502    name => 'Name',
    7371503    WLOC => {
     
    7621528        },
    7631529    },
    764     DcMD => {
    765         Name => 'DcMD',
    766         SubDirectory => {
    767             TagTable => 'Image::ExifTool::QuickTime::DcMD',
    768         },
    769     },
    7701530   'ptv '=> {
    7711531        Name => 'PrintToVideo',
    7721532        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Video' },
    7731533    },
    774    'hnti'=> {
     1534    hnti => {
    7751535        Name => 'HintInfo',
    7761536        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HintInfo' },
    7771537    },
    778    'hinf' => {
     1538    hinf => {
    7791539        Name => 'HintTrackInfo',
    7801540        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HintTrackInfo' },
    7811541    },
     1542    hinv => 'HintVersion', #PH (guess)
     1543    XMP_ => { #PH (Adobe CS3 Bridge)
     1544        Name => 'XMP',
     1545        WriteGroup => 'XMP',    # (write main tags here)
     1546        # *** this is where ExifTool writes XMP in MOV videos (as per XMP spec) ***
     1547        SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' },
     1548    },
     1549    # the following are 3gp tags, references:
     1550    # http://atomicparsley.sourceforge.net
     1551    # http://www.3gpp.org/ftp/tsg_sa/WG4_CODEC/TSGS4_25/Docs/
     1552    # (note that all %langText3gp tags are Avoid => 1)
     1553    cprt => { Name => 'Copyright',  %langText3gp, Groups => { 2 => 'Author' } },
     1554    auth => { Name => 'Author',     %langText3gp, Groups => { 2 => 'Author' } },
     1555    titl => { Name => 'Title',      %langText3gp },
     1556    dscp => { Name => 'Description',%langText3gp },
     1557    perf => { Name => 'Performer',  %langText3gp },
     1558    gnre => { Name => 'Genre',      %langText3gp },
     1559    albm => { Name => 'Album',      %langText3gp },
     1560    coll => { Name => 'CollectionName', %langText3gp }, #17
     1561    rtng => {
     1562        Name => 'Rating',
     1563        # (4-byte flags, 4-char entity, 4-char criteria, 2-byte lang, string)
     1564        RawConv => q{
     1565            return '<err>' unless length $val >= 14;
     1566            my $str = 'Entity=' . substr($val,4,4) . ' Criteria=' . substr($val,8,4);
     1567            $str =~ tr/\0-\x1f\x7f-\xff//d; # remove unprintable characters
     1568            my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 12));
     1569            $lang = $lang ? "($lang) " : '';
     1570            $val = substr($val, 14);
     1571            $val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/;
     1572            return $lang . $str . ' ' . $val;
     1573        },
     1574    },
     1575    clsf => {
     1576        Name => 'Classification',
     1577        # (4-byte flags, 4-char entity, 2-byte index, 2-byte lang, string)
     1578        RawConv => q{
     1579            return '<err>' unless length $val >= 12;
     1580            my $str = 'Entity=' . substr($val,4,4) . ' Index=' . Get16u(\$val,8);
     1581            $str =~ tr/\0-\x1f\x7f-\xff//d; # remove unprintable characters
     1582            my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 10));
     1583            $lang = $lang ? "($lang) " : '';
     1584            $val = substr($val, 12);
     1585            $val = $self->Decode($val, 'UCS2') if $val =~ /^\xfe\xff/;
     1586            return $lang . $str . ' ' . $val;
     1587        },
     1588    },
     1589    kywd => {
     1590        Name => 'Keywords',
     1591        # (4 byte flags, 2-byte lang, 1-byte count, count x pascal strings, ref 17)
     1592        # (but I have also seen a simple string written by iPhone)
     1593        RawConv => q{
     1594            my $sep = $self->Options('ListSep');
     1595            return join($sep, split /\0+/, $val) unless $val =~ /^\0/; # (iPhone)
     1596            return '<err>' unless length $val >= 7;
     1597            my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4));
     1598            $lang = $lang ? "($lang) " : '';
     1599            my $num = Get8u(\$val, 6);
     1600            my ($i, @vals);
     1601            my $pos = 7;
     1602            for ($i=0; $i<$num; ++$i) {
     1603                last if $pos >= length $val;
     1604                my $len = Get8u(\$val, $pos++);
     1605                last if $pos + $len > length $val;
     1606                my $v = substr($val, $pos, $len);
     1607                $v = $self->Decode($v, 'UCS2') if $v =~ /^\xfe\xff/;
     1608                push @vals, $v;
     1609                $pos += $len;
     1610            }
     1611            return $lang . join($sep, @vals);
     1612        },
     1613    },
     1614    loci => {
     1615        Name => 'LocationInformation',
     1616        Groups => { 2 => 'Location' },
     1617        # (4-byte flags, 2-byte lang, location string, 1-byte role, 4-byte fixed longitude,
     1618        #  4-byte fixed latitude, 4-byte fixed altitude, body string, notes string)
     1619        RawConv => q{
     1620            return '<err>' unless length $val >= 6;
     1621            my $lang = Image::ExifTool::QuickTime::UnpackLang(Get16u(\$val, 4));
     1622            $lang = $lang ? "($lang) " : '';
     1623            $val = substr($val, 6);
     1624            my $str;
     1625            if ($val =~ /^\xfe\xff/) {
     1626                $val =~ s/^(\xfe\xff(.{2})*?)\0\0//s or return '<err>';
     1627                $str = $self->Decode($1, 'UCS2');
     1628            } else {
     1629                $val =~ s/^(.*?)\0//s or return '<err>';
     1630                $str = $1;
     1631            }
     1632            $str = '(none)' unless length $str;
     1633            return '<err>' if length $val < 13;
     1634            my $role = Get8u(\$val, 0);
     1635            my $lon = GetFixed32s(\$val, 1);
     1636            my $lat = GetFixed32s(\$val, 5);
     1637            my $alt = GetFixed32s(\$val, 9);
     1638            my $roleStr = {0=>'shooting',1=>'real',2=>'fictional',3=>'reserved'}->{$role};
     1639            $str .= ' Role=' . ($roleStr || "unknown($role)");
     1640            $str .= sprintf(' Lat=%.5f Lon=%.5f Alt=%.2f', $lat, $lon, $alt);
     1641            $val = substr($val, 13);
     1642            if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) {
     1643                $str .= ' Body=' . $self->Decode($1, 'UCS2');
     1644            } elsif ($val =~ s/^(.*?)\0//s) {
     1645                $str .= " Body=$1";
     1646            }
     1647            if ($val =~ s/^(\xfe\xff(.{2})*?)\0\0//s) {
     1648                $str .= ' Notes=' . $self->Decode($1, 'UCS2');
     1649            } elsif ($val =~ s/^(.*?)\0//s) {
     1650                $str .= " Notes=$1";
     1651            }
     1652            return $lang . $str;
     1653        },
     1654    },
     1655    yrrc => {
     1656        Name => 'Year',
     1657        Groups => { 2 => 'Time' },
     1658        RawConv => 'length($val) >= 6 ? Get16u(\$val,4) : "<err>"',
     1659    },
     1660    urat => { #17
     1661        Name => 'UserRating',
     1662        RawConv => q{
     1663            return '<err>' unless length $val >= 8;
     1664            return Get8u(\$val, 7);
     1665        },
     1666    },
     1667    # tsel - TrackSelection (ref 17)
     1668    # Apple tags (ref 16[dead] -- see ref 25 instead)
     1669    angl => { Name => 'CameraAngle',  Format => 'string' }, # (NC)
     1670    clfn => { Name => 'ClipFileName', Format => 'string' }, # (NC)
     1671    clid => { Name => 'ClipID',       Format => 'string' }, # (NC)
     1672    cmid => { Name => 'CameraID',     Format => 'string' }, # (NC)
     1673    cmnm => { # (NC)
     1674        Name => 'Model',
     1675        Description => 'Camera Model Name',
     1676        Avoid => 1,
     1677        Format => 'string', # (necessary to remove the trailing NULL)
     1678    },
     1679    date => {
     1680        Name => 'DateTimeOriginal',
     1681        Description => 'Date/Time Original',
     1682        Groups => { 2 => 'Time' },
     1683        Notes => q{
     1684            Apple Photos has been reported to show a crazy date/time for some MP4 files
     1685            containing this tag, but perhaps only if it is missing a time zone
     1686        }, #forum10690/11125
     1687        Shift => 'Time',
     1688        ValueConv => q{
     1689            require Image::ExifTool::XMP;
     1690            $val =  Image::ExifTool::XMP::ConvertXMPDate($val);
     1691            $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary
     1692            return $val;
     1693        },
     1694        ValueConvInv => q{
     1695            require Image::ExifTool::XMP;
     1696            $val =  Image::ExifTool::XMP::FormatXMPDate($val);
     1697            $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon
     1698            return $val;
     1699        },
     1700        PrintConv => '$self->ConvertDateTime($val)',
     1701        PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
     1702    },
     1703    manu => { # (SX280)
     1704        Name => 'Make',
     1705        Avoid => 1,
     1706        # (with Canon there are 6 unknown bytes before the model: "\0\0\0\0\x15\xc7")
     1707        RawConv => '$val=~s/^\0{4}..//s; $val=~s/\0.*//; $val',
     1708    },
     1709    modl => { # (Samsung GT-S8530, Canon SX280)
     1710        Name => 'Model',
     1711        Description => 'Camera Model Name',
     1712        Avoid => 1,
     1713        # (with Canon there are 6 unknown bytes before the model: "\0\0\0\0\x15\xc7")
     1714        RawConv => '$val=~s/^\0{4}..//s; $val=~s/\0.*//; $val',
     1715    },
     1716    reel => { Name => 'ReelName',     Format => 'string' }, # (NC)
     1717    scen => { Name => 'Scene',        Format => 'string' }, # (NC)
     1718    shot => { Name => 'ShotName',     Format => 'string' }, # (NC)
     1719    slno => { Name => 'SerialNumber', Format => 'string' }, # (NC)
     1720    apmd => { Name => 'ApertureMode', Format => 'undef' }, #20
     1721    kgtt => { #http://lists.ffmpeg.org/pipermail/ffmpeg-devel-irc/2012-June/000707.html
     1722        # 'TrackType' will expand to 'Track#Type' when found inside a track
     1723        Name => 'TrackType',
     1724        # set flag to process this as international text
     1725        # even though the tag ID doesn't start with 0xa9
     1726        IText => 4, # IText with 4-byte header
     1727    },
     1728    chpl => { # (Nero chapter list)
     1729        Name => 'ChapterList',
     1730        ValueConv => \&ConvertChapterList,
     1731        PrintConv => \&PrintChapter,
     1732    },
     1733    # ndrm - 7 bytes (0 0 0 1 0 0 0) Nero Digital Rights Management? (PH)
     1734    # other non-Apple tags (ref 16)
     1735    # hpix - HipixRichPicture (ref 16, HIPIX)
     1736    # strk - sub-track information (ref 16, ISO)
     1737#
     1738# Manufacturer-specific metadata
     1739#
    7821740    TAGS => [ #PH
    7831741        # these tags were initially discovered in a Pentax movie,
    7841742        # but similar information is found in videos from other manufacturers
     1743        {
     1744            Name => 'FujiFilmTags',
     1745            Condition => '$$valPt =~ /^FUJIFILM DIGITAL CAMERA\0/',
     1746            SubDirectory => {
     1747                TagTable => 'Image::ExifTool::FujiFilm::MOV',
     1748                ByteOrder => 'LittleEndian',
     1749            },
     1750        },
    7851751        {
    7861752            Name => 'KodakTags',
     
    8371803                TagTable => 'Image::ExifTool::Olympus::MP4',
    8381804                ByteOrder => 'LittleEndian',
     1805            },
     1806        },
     1807        {
     1808            Name => 'OlympusTags4',
     1809            Condition => '$$valPt =~ /^.{16}OLYM\0/s',
     1810            SubDirectory => {
     1811                TagTable => 'Image::ExifTool::Olympus::MOV3',
     1812                Start => 12,
    8391813            },
    8401814        },
     
    8831857        },
    8841858    ],
    885     NCDT => { #PH
    886         Name => 'NikonNCDT',
    887         SubDirectory => {
    888             TagTable => 'Image::ExifTool::Nikon::NCDT',
    889             ProcessProc => \&ProcessMOV,
    890         },
    891     },
     1859    # ---- Canon ----
     1860    CNCV => { Name => 'CompressorVersion', Format => 'string' }, #PH (5D Mark II)
     1861    CNMN => {
     1862        Name => 'Model', #PH (EOS 550D)
     1863        Description => 'Camera Model Name',
     1864        Avoid => 1,
     1865        Format => 'string', # (necessary to remove the trailing NULL)
     1866    },
     1867    CNFV => { Name => 'FirmwareVersion', Format => 'string' }, #PH (EOS 550D)
     1868    CNTH => { #PH (PowerShot S95)
     1869        Name => 'CanonCNTH',
     1870        SubDirectory => { TagTable => 'Image::ExifTool::Canon::CNTH' },
     1871    },
     1872    CNOP => { #PH (7DmkII)
     1873        Name => 'CanonCNOP',
     1874        SubDirectory => { TagTable => 'Image::ExifTool::Canon::CNOP' },
     1875    },
     1876    # CNDB - 2112 bytes (550D)
     1877    # CNDM - 4 bytes - 0xff,0xd8,0xff,0xd9 (S95)
     1878    # CNDG - 10232 bytes, mostly zeros (N100)
     1879    # ---- Casio ----
    8921880    QVMI => { #PH
    8931881        Name => 'CasioQVMI',
    894         # Casio stores standard EXIF-format information in MOV videos (ie. EX-S880)
     1882        # Casio stores standard EXIF-format information in MOV videos (eg. EX-S880)
    8951883        SubDirectory => {
    8961884            TagTable => 'Image::ExifTool::Exif::Main',
     1885            ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default)
    8971886            DirName => 'IFD0',
    8981887            Multi => 0, # (no NextIFD pointer)
     
    9011890        },
    9021891    },
    903     MMA0 => { #PH (DiMage 7Hi)
    904         Name => 'MinoltaMMA0',
    905         SubDirectory => { TagTable => 'Image::ExifTool::Minolta::MMA' },
    906     },
    907     MMA1 => { #PH (Dimage A2)
    908         Name => 'MinoltaMMA1',
    909         SubDirectory => { TagTable => 'Image::ExifTool::Minolta::MMA' },
    910     },
    911     XMP_ => { #PH (Adobe CS3 Bridge)
    912         Name => 'XMP',
    913         SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' },
    914     },
    915     vndr => 'Vendor', #PH (Samsung PL70)
    916     SDLN => 'PlayMode', #PH (NC, Samsung ST80 "SEQ_PLAY")
    917     # Canon tags
    918     CNCV => 'CompressorVersion', #PH (5D Mark II)
    919     CNMN => 'Model', #PH (EOS 550D)
    920     CNFV => 'FirmwareVersion', #PH (EOS 550D)
    921     CNTH => { #PH (PowerShot S95)
    922         Name => 'CanonCNTH',
    923         SubDirectory => {
    924             TagTable => 'Image::ExifTool::Canon::CNTH',
    925             ProcessProc => \&ProcessMOV,
    926         },
    927     },
    928     # CNDB - 2112 bytes (550D)
    929     # CNDM - 4 bytes - 0xff,0xd8,0xff,0xd9 (S95)
    930     INFO => {
    931         Name => 'SamsungINFO',
    932         SubDirectory => { TagTable => 'Image::ExifTool::Samsung::INFO' },
    933     },
     1892    # ---- FujiFilm ----
    9341893    FFMV => { #PH (FinePix HS20EXR)
    9351894        Name => 'FujiFilmFFMV',
     
    9401899        SubDirectory => {
    9411900            TagTable => 'Image::ExifTool::Exif::Main',
     1901            ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default)
    9421902            DirName => 'IFD0',
    9431903            Start => 16,
     
    9461906        },
    9471907    },
     1908    # ---- Garmin ---- (ref PH)
     1909    uuid => [{
     1910        Name => 'GarminSoftware', # (NC)
     1911        Condition => '$$valPt =~ /^VIRBactioncamera/',
     1912        RawConv => 'substr($val, 16)',
     1913        RawConvInv => '"VIRBactioncamera$val"',
     1914    },{
     1915        # have seen "28 f3 11 e2 b7 91 4f 6f 94 e2 4f 5d ea cb 3c 01" for RicohThetaZ1 accelerometer RADT data (not yet decoded)
     1916        Name => 'UUID-Unknown',
     1917        Writable => 0,
     1918        %unknownInfo,
     1919    }],
     1920    pmcc => {
     1921        Name => 'GarminSettings',
     1922        ValueConv => 'substr($val, 4)',
     1923        ValueConvInv => '"\0\0\0\x01$val"',
     1924    },
     1925    # hmtp - "\0\0\0\x01" followed by 408 bytes of zero
     1926    # vrin - "\0\0\0\x01" followed by 8 bytes of zero
     1927    # ---- GoPro ---- (ref PH)
     1928    GoPr => 'GoProType', # (Hero3+)
     1929    FIRM => { Name => 'FirmwareVersion', Avoid => 1 }, # (Hero4)
     1930    LENS => 'LensSerialNumber', # (Hero4)
     1931    CAME => { # (Hero4)
     1932        Name => 'SerialNumberHash',
     1933        Description => 'Camera Serial Number Hash',
     1934        ValueConv => 'unpack("H*",$val)',
     1935        ValueConvInv => 'pack("H*",$val)',
     1936    },
     1937    # SETT? 12 bytes (Hero4)
     1938    # MUID? 32 bytes (Hero4, starts with serial number hash)
     1939    # HMMT? 404 bytes (Hero4, all zero)
     1940    # BCID? 26 bytes (Hero5, all zero), 36 bytes GoPro Max
     1941    # GUMI? 16 bytes (Hero5)
     1942   "FOV\0" => 'FieldOfView', #forum8938 (Hero2) seen: "Wide"
     1943    GPMF => {
     1944        Name => 'GoProGPMF',
     1945        SubDirectory => { TagTable => 'Image::ExifTool::GoPro::GPMF' },
     1946    },
     1947    # free (all zero)
     1948    "\xa9TSC" => 'StartTimeScale', # (Hero6)
     1949    "\xa9TSZ" => 'StartTimeSampleSize', # (Hero6)
     1950    "\xa9TIM" => 'StartTimecode', #PH (NC)
     1951    # --- HTC ----
     1952    htcb => {
     1953        Name => 'HTCBinary',
     1954        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HTCBinary' },
     1955    },
     1956    # ---- Kodak ----
     1957    DcMD => {
     1958        Name => 'KodakDcMD',
     1959        SubDirectory => { TagTable => 'Image::ExifTool::Kodak::DcMD' },
     1960    },
     1961    SNum => { Name => 'SerialNumber', Avoid => 1, Groups => { 2 => 'Camera' } },
     1962    ptch => { Name => 'Pitch', Format => 'rational64s', Avoid => 1 }, # Units??
     1963    _yaw => { Name => 'Yaw',   Format => 'rational64s', Avoid => 1 }, # Units??
     1964    roll => { Name => 'Roll',  Format => 'rational64s', Avoid => 1 }, # Units??
     1965    _cx_ => { Name => 'CX',    Format => 'rational64s', Unknown => 1 },
     1966    _cy_ => { Name => 'CY',    Format => 'rational64s', Unknown => 1 },
     1967    rads => { Name => 'Rads',  Format => 'rational64s', Unknown => 1 },
     1968    lvlm => { Name => 'LevelMeter', Format => 'rational64s', Unknown => 1 }, # (guess)
     1969    Lvlm => { Name => 'LevelMeter', Format => 'rational64s', Unknown => 1 }, # (guess)
     1970    pose => { Name => 'pose', SubDirectory => { TagTable => 'Image::ExifTool::Kodak::pose' } },
     1971    # AMBA => Ambarella AVC atom (unknown data written by Kodak Playsport video cam)
     1972    # tmlp - 1 byte: 0 (PixPro SP360/4KVR360)
     1973    # pivi - 72 bytes (PixPro SP360)
     1974    # pive - 12 bytes (PixPro SP360)
     1975    # loop - 4 bytes: 0 0 0 0 (PixPro 4KVR360)
     1976    # m cm - 2 bytes: 0 0 (PixPro 4KVR360)
     1977    # m ev - 2 bytes: 0 0 (PixPro SP360/4KVR360) (exposure comp?)
     1978    # m vr - 2 bytes: 0 1 (PixPro 4KVR360) (virtual reality?)
     1979    # m wb - 4 bytes: 0 0 0 0 (PixPro SP360/4KVR360) (white balance?)
     1980    # mclr - 4 bytes: 0 0 0 0 (PixPro SP360/4KVR360)
     1981    # mmtr - 4 bytes: 0,6 0 0 0 (PixPro SP360/4KVR360)
     1982    # mflr - 4 bytes: 0 0 0 0 (PixPro SP360)
     1983    # lvlm - 24 bytes (PixPro SP360)
     1984    # Lvlm - 24 bytes (PixPro 4KVR360)
     1985    # ufdm - 4 bytes: 0 0 0 1 (PixPro SP360)
     1986    # mtdt - 1 byte: 0 (PixPro SP360/4KVR360)
     1987    # gdta - 75240 bytes (PixPro SP360)
     1988    # EIS1 - 4 bytes: 03 07 00 00 (PixPro 4KVR360)
     1989    # EIS2 - 4 bytes: 04 97 00 00 (PixPro 4KVR360)
     1990    # ---- LG ----
     1991    adzc => { Name => 'Unknown_adzc', Unknown => 1, Hidden => 1, %langText }, # "false\0/","true\0/"
     1992    adze => { Name => 'Unknown_adze', Unknown => 1, Hidden => 1, %langText }, # "false\0/"
     1993    adzm => { Name => 'Unknown_adzm', Unknown => 1, Hidden => 1, %langText }, # "\x0e\x04/","\x10\x06"
     1994    # ---- Microsoft ----
     1995    Xtra => { #PH (microsoft)
     1996        Name => 'MicrosoftXtra',
     1997        SubDirectory => { TagTable => 'Image::ExifTool::Microsoft::Xtra' },
     1998    },
     1999    # ---- Minolta ----
     2000    MMA0 => { #PH (DiMage 7Hi)
     2001        Name => 'MinoltaMMA0',
     2002        SubDirectory => { TagTable => 'Image::ExifTool::Minolta::MMA' },
     2003    },
     2004    MMA1 => { #PH (Dimage A2)
     2005        Name => 'MinoltaMMA1',
     2006        SubDirectory => { TagTable => 'Image::ExifTool::Minolta::MMA' },
     2007    },
     2008    # ---- Nikon ----
     2009    NCDT => { #PH
     2010        Name => 'NikonNCDT',
     2011        SubDirectory => { TagTable => 'Image::ExifTool::Nikon::NCDT' },
     2012    },
     2013    # ---- Olympus ----
     2014    scrn => { #PH (TG-810)
     2015        Name => 'OlympusPreview',
     2016        Condition => '$$valPt =~ /^.{4}\xff\xd8\xff\xdb/s',
     2017        SubDirectory => { TagTable => 'Image::ExifTool::Olympus::scrn' },
     2018    },
     2019    # ---- Panasonic/Leica ----
     2020    PANA => { #PH
     2021        Name => 'PanasonicPANA',
     2022        SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::PANA' },
     2023    },
     2024    LEIC => { #PH
     2025        Name => 'LeicaLEIC',
     2026        SubDirectory => { TagTable => 'Image::ExifTool::Panasonic::PANA' },
     2027    },
     2028    # ---- Pentax ----
     2029    thmb => [ # (apparently defined by 3gpp, ref 16)
     2030        { #PH (Pentax Q)
     2031            Name => 'MakerNotePentax5a',
     2032            Condition => '$$valPt =~ /^PENTAX \0II/',
     2033            SubDirectory => {
     2034                TagTable => 'Image::ExifTool::Pentax::Main',
     2035                ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default)
     2036                Start => 10,
     2037                Base => '$start - 10',
     2038                ByteOrder => 'LittleEndian',
     2039            },
     2040        },{ #PH (TG-810)
     2041            Name => 'OlympusThumbnail',
     2042            Condition => '$$valPt =~ /^.{4}\xff\xd8\xff\xdb/s',
     2043            SubDirectory => { TagTable => 'Image::ExifTool::Olympus::thmb' },
     2044        },{ #17 (format is in bytes 3-7)
     2045            Name => 'ThumbnailImage',
     2046            Condition => '$$valPt =~ /^.{8}\xff\xd8\xff[\xdb\xe0]/s',
     2047            Groups => { 2 => 'Preview' },
     2048            RawConv => 'substr($val, 8)',
     2049            Binary => 1,
     2050        },{ #17 (format is in bytes 3-7)
     2051            Name => 'ThumbnailPNG',
     2052            Condition => '$$valPt =~ /^.{8}\x89PNG\r\n\x1a\n/s',
     2053            Groups => { 2 => 'Preview' },
     2054            RawConv => 'substr($val, 8)',
     2055            Binary => 1,
     2056        },{
     2057            Name => 'UnknownThumbnail',
     2058            Groups => { 2 => 'Preview' },
     2059            Binary => 1,
     2060        },
     2061    ],
     2062    PENT => { #PH
     2063        Name => 'PentaxPENT',
     2064        SubDirectory => {
     2065            TagTable => 'Image::ExifTool::Pentax::PENT',
     2066            ByteOrder => 'LittleEndian',
     2067        },
     2068    },
     2069    PXTH => { #PH (Pentax K-01)
     2070        Name => 'PentaxPreview',
     2071        SubDirectory => { TagTable => 'Image::ExifTool::Pentax::PXTH' },
     2072    },
     2073    PXMN => [{ #PH (Pentax K-01)
     2074        Name => 'MakerNotePentax5b',
     2075        Condition => '$$valPt =~ /^PENTAX \0MM/',
     2076        SubDirectory => {
     2077            TagTable => 'Image::ExifTool::Pentax::Main',
     2078            ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default)
     2079            Start => 10,
     2080            Base => '$start - 10',
     2081            ByteOrder => 'BigEndian',
     2082        },
     2083    },{ #PH (Pentax 645Z)
     2084        Name => 'MakerNotePentax5c',
     2085        Condition => '$$valPt =~ /^PENTAX \0II/',
     2086        SubDirectory => {
     2087            TagTable => 'Image::ExifTool::Pentax::Main',
     2088            ProcessProc => \&Image::ExifTool::Exif::ProcessExif, # (because ProcessMOV is default)
     2089            Start => 10,
     2090            Base => '$start - 10',
     2091            ByteOrder => 'LittleEndian',
     2092        },
     2093    },{
     2094        Name => 'MakerNotePentaxUnknown',
     2095        Binary => 1,
     2096    }],
     2097    # ---- Ricoh ----
     2098    RTHU => { #PH (GR)
     2099        Name => 'PreviewImage',
     2100        Groups => { 2 => 'Preview' },
     2101        RawConv => '$self->ValidateImage(\$val, $tag)',
     2102    },
     2103    RMKN => { #PH (GR)
     2104        Name => 'RicohRMKN',
     2105        SubDirectory => {
     2106            TagTable => 'Image::ExifTool::Exif::Main',
     2107            ProcessProc => \&Image::ExifTool::ProcessTIFF, # (because ProcessMOV is default)
     2108        },
     2109    },
     2110    '@mak' => { Name => 'Make',     Avoid => 1 },
     2111    '@mod' => { Name => 'Model',    Avoid => 1 },
     2112    '@swr' => { Name => 'SoftwareVersion', Avoid => 1 },
     2113    '@day' => {
     2114        Name => 'ContentCreateDate',
     2115        Notes => q{
     2116            some stupid Ricoh programmer used the '@' symbol instead of the copyright
     2117            symbol in these tag ID's for the Ricoh Theta Z1 and maybe other models
     2118        },
     2119        Groups => { 2 => 'Time' },
     2120        Shift => 'Time',
     2121        Avoid => 1,
     2122        # handle values in the form "2010-02-12T13:27:14-0800"
     2123        ValueConv => q{
     2124            require Image::ExifTool::XMP;
     2125            $val =  Image::ExifTool::XMP::ConvertXMPDate($val);
     2126            $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary
     2127            return $val;
     2128        },
     2129        ValueConvInv => q{
     2130            require Image::ExifTool::XMP;
     2131            my $tmp = Image::ExifTool::XMP::FormatXMPDate($val);
     2132            ($val = $tmp) =~ s/([-+]\d{2}):(\d{2})$/$1$2/ if defined $tmp; # remove time zone colon
     2133            return $val;
     2134        },
     2135        PrintConv => '$self->ConvertDateTime($val)',
     2136        PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
     2137    },
     2138    '@xyz' => { #PH (iPhone 3GS)
     2139        Name => 'GPSCoordinates',
     2140        Groups => { 2 => 'Location' },
     2141        Avoid => 1,
     2142        ValueConv => \&ConvertISO6709,
     2143        ValueConvInv => \&ConvInvISO6709,
     2144        PrintConv => \&PrintGPSCoordinates,
     2145        PrintConvInv => \&PrintInvGPSCoordinates,
     2146    },
     2147    # RDT1 - pairs of int32u_BE, starting at byte 8: "458275 471846"
     2148    # RDT2 - pairs of int32u_BE, starting at byte 8: "472276 468526"
     2149    # RDT3 - pairs of int32u_BE, starting at byte 8: "876603 482191"
     2150    # RDT4 - pairs of int32u_BE, starting at byte 8: "1955 484612"
     2151    # RDT6 - empty
     2152    # RDT7 - empty
     2153    # RDT8 - empty
     2154    # RDT9 - only 16-byte header?
     2155    # the boxes below all have a similar header (little-endian):
     2156    #  0 int32u - number of records
     2157    #  4 ? - "1e 00"
     2158    #  6 int16u - record length in bytes
     2159    #  8 ? - "23 01 00 00 00 00 00 00"
     2160    #  16 - start of records (each record ends in an int64u timestamp in ns)
     2161    # RDTA - float[4],ts: "-0.31289672 -0.2245330 11.303817 0 775.780"
     2162    # RDTB - float[4],ts: "-0.04841613 -0.2166595 0.0724792 0 775.780"
     2163    # RDTC - float[4],ts: "27.60925 -27.10037 -13.27285 0 775.829"
     2164    # RDTD - int16s[3],ts: "353 -914 16354 0 775.829"
     2165    # RDTG - ts: "775.825"
     2166    # RDTI - float[4],ts: "0.00165951 0.005770059 0.06838259 0.1744695 775.862"
     2167    # ---- Samsung ----
     2168    vndr => 'Vendor', #PH (Samsung PL70)
     2169    SDLN => 'PlayMode', #PH (NC, Samsung ST80 "SEQ_PLAY")
     2170    INFO => {
     2171        Name => 'SamsungINFO',
     2172        SubDirectory => { TagTable => 'Image::ExifTool::Samsung::INFO' },
     2173    },
     2174   '@sec' => { #PH (Samsung WB30F)
     2175        Name => 'SamsungSec',
     2176        SubDirectory => { TagTable => 'Image::ExifTool::Samsung::sec' },
     2177    },
     2178    'smta' => { #PH (Samsung SM-C101)
     2179        Name => 'SamsungSmta',
     2180        SubDirectory => {
     2181            TagTable => 'Image::ExifTool::Samsung::smta',
     2182            Start => 4,
     2183        },
     2184    },
     2185    cver => 'CodeVersion', #PH (guess, Samsung MV900F)
     2186    # ducp - 4 bytes all zero (Samsung ST96,WB750), 52 bytes all zero (Samsung WB30F)
     2187    # edli - 52 bytes all zero (Samsung WB30F)
     2188    # @etc - 4 bytes all zero (Samsung WB30F)
     2189    # saut - 4 bytes all zero (Samsung SM-N900T)
     2190    # smrd - string "TRUEBLUE" (Samsung SM-C101)
     2191    # ---- TomTom Bandit Action Cam ----
     2192    TTMD => {
     2193        Name => 'TomTomMetaData',
     2194        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TomTom' },
     2195    },
     2196    # ---- Samsung Gear 360 ----
     2197    vrot => {
     2198        Name => 'AccelerometerData',
     2199        Notes => q{
     2200            accelerometer readings for each frame of the video, expressed as sets of
     2201            yaw, pitch and roll angles in degrees
     2202        },
     2203        Format => 'rational64s',
     2204        ValueConv => '$val =~ s/^-?\d+ //; \$val', # (ignore leading version/size words)
     2205    },
     2206    # m360 - 8 bytes "0 0 0 0 0 0 0 1"
     2207    # opax - 164 bytes unknown (center and affine arrays? ref 26)
     2208    # opai - 32 bytes (maybe contains a serial number starting at byte 16? - PH) (rgb gains, degamma, gamma? ref 26)
     2209    # intv - 16 bytes all zero
     2210    # ---- Unknown ----
     2211    # CDET - 128 bytes (unknown origin)
     2212    # mtyp - 4 bytes all zero (some drone video)
     2213    # kgrf - 8 bytes all zero ? (in udta inside trak atom)
     2214    # kgcg - 128 bytes 0's and 1's
     2215    # kgsi - 4 bytes "00 00 00 80"
     2216    # FIEL - 18 bytes "FIEL\0\x01\0\0\0..."
     2217#
     2218# other 3rd-party tags
     2219# (ref http://code.google.com/p/mp4parser/source/browse/trunk/isoparser/src/main/resources/isoparser-default.properties?r=814)
     2220#
     2221    ccid => 'ContentID',
     2222    icnu => 'IconURI',
     2223    infu => 'InfoURL',
     2224    cdis => 'ContentDistributorID',
     2225    albr => { Name => 'AlbumArtist', Groups => { 2 => 'Author' } },
     2226    cvru => 'CoverURI',
     2227    lrcu => 'LyricsURI',
     2228
     2229    tags => {   # found in Audible .m4b audio books (ref PH)
     2230        Name => 'Audible_tags',
     2231        SubDirectory => { TagTable => 'Image::ExifTool::Audible::tags' },
     2232    },
     2233);
     2234
     2235# Unknown information stored in HTC One (M8) videos - PH
     2236%Image::ExifTool::QuickTime::HTCBinary = (
     2237    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     2238    GROUPS => { 0 => 'MakerNotes', 1 => 'HTC', 2 => 'Video' },
     2239    TAG_PREFIX => 'HTCBinary',
     2240    FORMAT => 'int32u',
     2241    FIRST_ENTRY => 0,
     2242    # 0 - values: 1
     2243    # 1 - values: 0
     2244    # 2 - values: 0
     2245    # 3 - values: FileSize minus 12 (why?)
     2246    # 4 - values: 12
     2247);
     2248
     2249# TomTom Bandit Action Cam metadata (ref PH)
     2250%Image::ExifTool::QuickTime::TomTom = (
     2251    PROCESS_PROC => \&ProcessMOV,
     2252    GROUPS => { 2 => 'Video' },
     2253    NOTES => 'Tags found in TomTom Bandit Action Cam MP4 videos.',
     2254    TTAD => {
     2255        Name => 'TomTomAD',
     2256        SubDirectory => {
     2257            TagTable => 'Image::ExifTool::QuickTime::Stream',
     2258            ProcessProc => \&Image::ExifTool::QuickTime::ProcessTTAD,
     2259        },
     2260    },
     2261    TTHL => { Name => 'TomTomHL', Binary => 1, Unknown => 1 }, # (mostly zeros)
     2262    # (TTID values are different for each video)
     2263    TTID => { Name => 'TomTomID', ValueConv => 'unpack("x4H*",$val)' },
     2264    TTVI => { Name => 'TomTomVI', Format => 'int32u', Unknown => 1 }, # seen: "0 1 61 508 508"
     2265    # TTVD seen: "normal 720p 60fps 60fps 16/9 wide 1x"
     2266    TTVD => { Name => 'TomTomVD', ValueConv => 'my @a = ($val =~ /[\x20-\x7f]+/g); "@a"' },
    9482267);
    9492268
     
    9602279# User-specific media data atoms (ref 11)
    9612280%Image::ExifTool::QuickTime::MetaData = (
    962     PROCESS_PROC => \&Image::ExifTool::QuickTime::ProcessMetaData,
     2281    PROCESS_PROC => \&ProcessMetaData,
    9632282    GROUPS => { 2 => 'Video' },
    9642283    TAG_PREFIX => 'MetaData',
     
    9672286        Name => 'ProductionDate',
    9682287        Groups => { 2 => 'Time' },
     2288        Shift => 'Time',
     2289        Writable => 1,
     2290        Permanent => 1,
     2291        DelValue => '0000/00/00 00:00:00',
    9692292        # translate from format "YYYY/mm/dd HH:MM:SS"
    9702293        ValueConv => '$val=~tr{/}{:}; $val',
     2294        ValueConvInv => '$val=~s[^(\d{4}):(\d{2}):][$1/$2/]; $val',
    9712295        PrintConv => '$self->ConvertDateTime($val)',
     2296        PrintConvInv => '$self->InverseDateTime($val)',
    9722297    },
    9732298    0x04 => 'Software',
     
    9852310        Name => 'TimeZone',
    9862311        Groups => { 2 => 'Time' },
     2312        Writable => 1,
     2313        Permanent => 1,
     2314        DelValue => 0,
    9872315        RawConv => 'Get16s(\$val,0)',
     2316        RawConvInv => 'Set16s($val)',
    9882317        PrintConv => 'TimeZoneString($val)',
     2318        PrintConvInv => q{
     2319            return undef unless $val =~ /^([-+])(\d{1,2}):?(\d{2})$/'
     2320            my $tzmin = $2 * 60 + $3;
     2321            $tzmin = -$tzmin if $1 eq '-';
     2322            return $tzmin;
     2323        }
    9892324    },
    9902325    0x0c => {
    9912326        Name => 'ModifyDate',
    9922327        Groups => { 2 => 'Time' },
     2328        Shift => 'Time',
     2329        Writable => 1,
     2330        Permanent => 1,
     2331        DelValue => '0000/00/00 00:00:00',
    9932332        # translate from format "YYYY/mm/dd HH:MM:SS"
    9942333        ValueConv => '$val=~tr{/}{:}; $val',
     2334        ValueConvInv => '$val=~s[^(\d{4}):(\d{2}):][$1/$2/]; $val',
    9952335        PrintConv => '$self->ConvertDateTime($val)',
    996     },
     2336        PrintConvInv => '$self->InverseDateTime($val)',
     2337    },
     2338);
     2339
     2340# compressed movie atoms (ref http://wiki.multimedia.cx/index.php?title=QuickTime_container#cmov)
     2341%Image::ExifTool::QuickTime::CMovie = (
     2342    PROCESS_PROC => \&ProcessMOV,
     2343    GROUPS => { 2 => 'Video' },
     2344    dcom => 'Compression',
     2345    # cmvd - compressed moov atom data
    9972346);
    9982347
     
    10122361        Name => 'VideoProfile',
    10132362        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::VideoProf' },
     2363    },
     2364    OLYM => { #PH
     2365        Name => 'OlympusOLYM',
     2366        SubDirectory => {
     2367            TagTable => 'Image::ExifTool::Olympus::OLYM',
     2368            ByteOrder => 'BigEndian',
     2369        },
    10142370    },
    10152371);
     
    11302486%Image::ExifTool::QuickTime::Meta = (
    11312487    PROCESS_PROC => \&ProcessMOV,
    1132     GROUPS => { 2 => 'Video' },
     2488    WRITE_PROC => \&WriteQuickTime,
     2489    GROUPS => { 1 => 'Meta', 2 => 'Video' },
    11332490    ilst => {
    11342491        Name => 'ItemList',
     
    11442501    },
    11452502    dinf => {
    1146         Name => 'DataInformation',
    1147         Flags => ['Binary','Unknown'],
     2503        Name => 'DataInfo', # (don't change this name -- used to recognize directory when writing)
     2504        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::DataInfo' },
    11482505    },
    11492506    ipmc => {
     
    11532510    iloc => {
    11542511        Name => 'ItemLocation',
    1155         Flags => ['Binary','Unknown'],
     2512        RawConv => \&ParseItemLocation,
     2513        WriteHook => \&ParseItemLocation,
     2514        Notes => 'parsed, but not extracted as a tag',
    11562515    },
    11572516    ipro => {
     
    11592518        Flags => ['Binary','Unknown'],
    11602519    },
    1161     iinf => {
     2520    iinf => [{
    11622521        Name => 'ItemInformation',
    1163         Flags => ['Binary','Unknown'],
    1164     },
     2522        Condition => '$$valPt =~ /^\0/', # (check for version 0)
     2523        SubDirectory => {
     2524            TagTable => 'Image::ExifTool::QuickTime::ItemInfo',
     2525            Start => 6, # (4-byte version/flags + 2-byte count)
     2526        },
     2527    },{
     2528        Name => 'ItemInformation',
     2529        SubDirectory => {
     2530            TagTable => 'Image::ExifTool::QuickTime::ItemInfo',
     2531            Start => 8, # (4-byte version/flags + 4-byte count)
     2532        },
     2533    }],
    11652534   'xml ' => {
    11662535        Name => 'XML',
    1167         SubDirectory => { TagTable => 'Image::ExifTool::XMP::Main' },
     2536        Flags => [ 'Binary', 'Protected' ],
     2537        SubDirectory => {
     2538            TagTable => 'Image::ExifTool::XMP::XML',
     2539            IgnoreProp => { NonRealTimeMeta => 1 }, # ignore container for Sony 'nrtm'
     2540        },
    11682541    },
    11692542   'keys' => {
     
    11752548        Flags => ['Binary','Unknown'],
    11762549    },
    1177     pitm => {
     2550    pitm => [{
    11782551        Name => 'PrimaryItemReference',
    1179         Flags => ['Binary','Unknown'],
    1180     },
     2552        Condition => '$$valPt =~ /^\0/', # (version 0?)
     2553        RawConv => '$$self{PrimaryItem} = unpack("x4n",$val)',
     2554        WriteHook => sub { my ($val,$et) = @_; $$et{PrimaryItem} = unpack("x4n",$val); },
     2555    },{
     2556        Name => 'PrimaryItemReference',
     2557        RawConv => '$$self{PrimaryItem} = unpack("x4N",$val)',
     2558        WriteHook => sub { my ($val,$et) = @_; $$et{PrimaryItem} = unpack("x4N",$val); },
     2559    }],
    11812560    free => { #PH
    11822561        Name => 'Free',
    11832562        Flags => ['Binary','Unknown'],
    11842563    },
     2564    iprp => {
     2565        Name => 'ItemProperties',
     2566        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ItemProp' },
     2567    },
     2568    iref => {
     2569        Name => 'ItemReference',
     2570        # the version is needed to parse some of the item references
     2571        Condition => '$$self{ItemRefVersion} = ord($$valPt); 1',
     2572        SubDirectory => {
     2573            TagTable => 'Image::ExifTool::QuickTime::ItemRef',
     2574            Start => 4,
     2575        },
     2576    },
     2577    idat => {
     2578        Name => 'MetaImageSize', #PH (NC)
     2579        Format => 'int16u',
     2580        # (don't know what the first two numbers are for)
     2581        PrintConv => '$val =~ s/^(\d+) (\d+) (\d+) (\d+)/${3}x$4/; $val',
     2582    },
     2583    uuid => [
     2584        { #PH (Canon R5/R6 HIF)
     2585            Name => 'MetaVersion', # (NC)
     2586            Condition => '$$valPt=~/^\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48/',
     2587            RawConv => 'substr($val, 0x14)',
     2588        },
     2589        {
     2590            Name => 'UUID-Unknown',
     2591            %unknownInfo,
     2592        },
     2593    ],
     2594);
     2595
     2596# additional metadata container (ref ISO14496-12:2015)
     2597%Image::ExifTool::QuickTime::OtherMeta = (
     2598    PROCESS_PROC => \&ProcessMOV,
     2599    WRITE_PROC => \&WriteQuickTime,
     2600    GROUPS => { 2 => 'Video' },
     2601    mere => {
     2602        Name => 'MetaRelation',
     2603        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::MetaRelation' },
     2604    },
     2605    meta => {
     2606        Name => 'Meta',
     2607        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Meta' },
     2608    },
     2609);
     2610
     2611# metabox relation (ref ISO14496-12:2015)
     2612%Image::ExifTool::QuickTime::MetaRelation = (
     2613    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     2614    GROUPS => { 2 => 'Video' },
     2615    FORMAT => 'int32u',
     2616    # 0 => 'MetaRelationVersion',
     2617    # 1 => 'FirstMetaboxHandlerType',
     2618    # 2 => 'FirstMetaboxHandlerType',
     2619    # 3 => { Name => 'MetaboxRelation', Format => 'int8u' },
     2620);
     2621
     2622%Image::ExifTool::QuickTime::ItemProp = (
     2623    PROCESS_PROC => \&ProcessMOV,
     2624    WRITE_PROC => \&WriteQuickTime,
     2625    GROUPS => { 2 => 'Image' },
     2626    ipco => {
     2627        Name => 'ItemPropertyContainer',
     2628        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ItemPropCont' },
     2629    },
     2630    ipma => {
     2631        Name => 'ItemPropertyAssociation',
     2632        RawConv => \&ParseItemPropAssoc,
     2633        WriteHook => \&ParseItemPropAssoc,
     2634        Notes => 'parsed, but not extracted as a tag',
     2635    },
     2636);
     2637
     2638%Image::ExifTool::QuickTime::ItemPropCont = (
     2639    PROCESS_PROC => \&ProcessMOV,
     2640    WRITE_PROC => \&WriteQuickTime,
     2641    PERMANENT => 1, # (can't be deleted)
     2642    GROUPS => { 2 => 'Image' },
     2643    VARS => { START_INDEX => 1 },   # show verbose indices starting at 1
     2644    colr => [{
     2645        Name => 'ICC_Profile',
     2646        Condition => '$$valPt =~ /^(prof|rICC)/',
     2647        SubDirectory => {
     2648            TagTable => 'Image::ExifTool::ICC_Profile::Main',
     2649            Start => 4,
     2650        },
     2651    },{
     2652        Name => 'ColorRepresentation',
     2653        ValueConv => 'join(" ", substr($val,0,4), unpack("x4n*",$val))',
     2654    }],
     2655    irot => {
     2656        Name => 'Rotation',
     2657        Format => 'int8u',
     2658        Writable => 'int8u',
     2659        Protected => 1,
     2660        ValueConv => '$val * 90',
     2661        ValueConvInv => 'int($val / 90 + 0.5)',
     2662    },
     2663    ispe => {
     2664        Name => 'ImageSpatialExtent',
     2665        Condition => '$$valPt =~ /^\0{4}/',     # (version/flags == 0/0)
     2666        RawConv => q{
     2667            my @dim = unpack("x4N*", $val);
     2668            return undef if @dim < 2;
     2669            unless ($$self{DOC_NUM}) {
     2670                $self->FoundTag(ImageWidth => $dim[0]);
     2671                $self->FoundTag(ImageHeight => $dim[1]);
     2672            }
     2673            return join ' ', @dim;
     2674        },
     2675        PrintConv => '$val =~ tr/ /x/; $val',
     2676    },
     2677    pixi => {
     2678        Name => 'ImagePixelDepth',
     2679        Condition => '$$valPt =~ /^\0{4}./s',   # (version/flags == 0/0 and count)
     2680        RawConv => 'join " ", unpack("x5C*", $val)',
     2681    },
     2682    auxC => {
     2683        Name => 'AuxiliaryImageType',
     2684        Format => 'undef',
     2685        RawConv => '$val = substr($val, 4); $val =~ s/\0.*//s; $val',
     2686    },
     2687    pasp => {
     2688        Name => 'PixelAspectRatio',
     2689        Format => 'int32u',
     2690        Writable => 'int32u',
     2691        Protected => 1,
     2692    },
     2693    rloc => {
     2694        Name => 'RelativeLocation',
     2695        Format => 'int32u',
     2696        RawConv => '$val =~ s/^\S+\s+//; $val', # remove version/flags
     2697    },
     2698    clap => {
     2699        Name => 'CleanAperture',
     2700        Format => 'rational64s',
     2701        Notes => '4 numbers: width, height, left and top',
     2702    },
     2703    hvcC => {
     2704        Name => 'HEVCConfiguration',
     2705        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::HEVCConfig' },
     2706    },
     2707    av1C => {
     2708        Name => 'AV1Configuration',
     2709        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::AV1Config' },
     2710    },
     2711);
     2712
     2713# HEVC configuration (ref https://github.com/MPEGGroup/isobmff/blob/master/IsoLib/libisomediafile/src/HEVCConfigAtom.c)
     2714%Image::ExifTool::QuickTime::HEVCConfig = (
     2715    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     2716    GROUPS => { 2 => 'Video' },
     2717    FIRST_ENTRY => 0,
     2718    0 => 'HEVCConfigurationVersion',
     2719    1 => {
     2720        Name => 'GeneralProfileSpace',
     2721        Mask => 0xc0,
     2722        PrintConv => { 0 => 'Conforming' },
     2723    },
     2724    1.1 => {
     2725        Name => 'GeneralTierFlag',
     2726        Mask => 0x20,
     2727        PrintConv => {
     2728            0 => 'Main Tier',
     2729            1 => 'High Tier',
     2730        },
     2731    },
     2732    1.2 => {
     2733        Name => 'GeneralProfileIDC',
     2734        Mask => 0x1f,
     2735        PrintConv => {
     2736            0 => 'No Profile',
     2737            1 => 'Main',
     2738            2 => 'Main 10',
     2739            3 => 'Main Still Picture',
     2740            4 => 'Format Range Extensions',
     2741            5 => 'High Throughput',
     2742            6 => 'Multiview Main',
     2743            7 => 'Scalable Main',
     2744            8 => '3D Main',
     2745            9 => 'Screen Content Coding Extensions',
     2746            10 => 'Scalable Format Range Extensions',
     2747            11 => 'High Throughput Screen Content Coding Extensions',
     2748        },
     2749    },
     2750    2 => {
     2751        Name => 'GenProfileCompatibilityFlags',
     2752        Format => 'int32u',
     2753        PrintConv => { BITMASK => {
     2754            31 => 'No Profile',             # (bit 0 in stream)
     2755            30 => 'Main',                   # (bit 1 in stream)
     2756            29 => 'Main 10',                # (bit 2 in stream)
     2757            28 => 'Main Still Picture',     # (bit 3 in stream)
     2758            27 => 'Format Range Extensions',# (...)
     2759            26 => 'High Throughput',
     2760            25 => 'Multiview Main',
     2761            24 => 'Scalable Main',
     2762            23 => '3D Main',
     2763            22 => 'Screen Content Coding Extensions',
     2764            21 => 'Scalable Format Range Extensions',
     2765            20 => 'High Throughput Screen Content Coding Extensions',
     2766        }},
     2767    },
     2768    6 => {
     2769        Name => 'ConstraintIndicatorFlags',
     2770        Format => 'int8u[6]',
     2771    },
     2772    12 => {
     2773        Name => 'GeneralLevelIDC',
     2774        PrintConv => 'sprintf("%d (level %.1f)", $val, $val/30)',
     2775    },
     2776    13 => {
     2777        Name => 'MinSpatialSegmentationIDC',
     2778        Format => 'int16u',
     2779        Mask => 0x0fff,
     2780    },
     2781    15 => {
     2782        Name => 'ParallelismType',
     2783        Mask => 0x03,
     2784    },
     2785    16 => {
     2786        Name => 'ChromaFormat',
     2787        Mask => 0x03,
     2788        PrintConv => {
     2789            0 => 'Monochrome',
     2790            1 => '4:2:0',
     2791            2 => '4:2:2',
     2792            3 => '4:4:4',
     2793        },
     2794    },
     2795    17 => {
     2796        Name => 'BitDepthLuma',
     2797        Mask => 0x07,
     2798        ValueConv => '$val + 8',
     2799    },
     2800    18 => {
     2801        Name => 'BitDepthChroma',
     2802        Mask => 0x07,
     2803        ValueConv => '$val + 8',
     2804    },
     2805    19 => {
     2806        Name => 'AverageFrameRate',
     2807        Format => 'int16u',
     2808        ValueConv => '$val / 256',
     2809    },
     2810    21 => {
     2811        Name => 'ConstantFrameRate',
     2812        Mask => 0xc0,
     2813        PrintConv => {
     2814            0 => 'Unknown',
     2815            1 => 'Constant Frame Rate',
     2816            2 => 'Each Temporal Layer is Constant Frame Rate',
     2817        },
     2818    },
     2819    21.1 => {
     2820        Name => 'NumTemporalLayers',
     2821        Mask => 0x38,
     2822    },
     2823    21.2 => {
     2824        Name => 'TemporalIDNested',
     2825        Mask => 0x04,
     2826        PrintConv => { 0 => 'No', 1 => 'Yes' },
     2827    },
     2828    #21.3 => {
     2829    #    Name => 'NALUnitLengthSize',
     2830    #    Mask => 0x03,
     2831    #    ValueConv => '$val + 1',
     2832    #    PrintConv => { 1 => '8-bit', 2 => '16-bit', 4 => '32-bit' },
     2833    #},
     2834    #22 => 'NumberOfNALUnitArrays',
     2835    # (don't decode the NAL unit arrays)
     2836);
     2837
     2838# HEVC configuration (ref https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox)
     2839%Image::ExifTool::QuickTime::AV1Config = (
     2840    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     2841    GROUPS => { 2 => 'Video' },
     2842    FIRST_ENTRY => 0,
     2843    0 => {
     2844        Name => 'AV1ConfigurationVersion',
     2845        Mask => 0x7f,
     2846    },
     2847    1.0 => {
     2848        Name => 'SeqProfile',
     2849        Mask => 0xe0,
     2850        Unknown => 1,
     2851    },
     2852    1.1 => {
     2853        Name => 'SeqLevelIdx0',
     2854        Mask => 0x1f,
     2855        Unknown => 1,
     2856    },
     2857    2.0 => {
     2858        Name => 'SeqTier0',
     2859        Mask => 0x80,
     2860        Unknown => 1,
     2861    },
     2862    2.1 => {
     2863        Name => 'HighBitDepth',
     2864        Mask => 0x40,
     2865        Unknown => 1,
     2866    },
     2867    2.2 => {
     2868        Name => 'TwelveBit',
     2869        Mask => 0x20,
     2870        Unknown => 1,
     2871    },
     2872    2.3 => {
     2873        Name => 'ChromaFormat', # (Monochrome+SubSamplingX+SubSamplingY)
     2874        Notes => 'bits: 0x04 = Monochrome, 0x02 = SubSamplingX, 0x01 = SubSamplingY',
     2875        Mask => 0x1c,
     2876        PrintConv => {
     2877            0x00 => 'YUV 4:4:4',
     2878            0x02 => 'YUV 4:2:2',
     2879            0x03 => 'YUV 4:2:0',
     2880            0x07 => 'Monochrome 4:0:0',
     2881        },
     2882    },
     2883    2.4 => {
     2884        Name => 'ChromaSamplePosition',
     2885        Mask => 0x03,
     2886        PrintConv => {
     2887            0 => 'Unknown',
     2888            1 => 'Vertical',
     2889            2 => 'Colocated',
     2890            3 => '(reserved)',
     2891        },
     2892    },
     2893    3 => {
     2894        Name => 'InitialDelaySamples',
     2895        RawConv => '$val & 0x10 ? undef : ($val & 0x0f) + 1',
     2896        Unknown => 1,
     2897    },
     2898);
     2899
     2900%Image::ExifTool::QuickTime::ItemRef = (
     2901    PROCESS_PROC => \&ProcessMOV,
     2902    WRITE_PROC => \&WriteQuickTime,
     2903    GROUPS => { 2 => 'Image' },
     2904    # (Note: ExifTool's ItemRefVersion may be used to test the iref version number)
     2905    NOTES => q{
     2906        The Item reference entries listed in the table below contain information about
     2907        the associations between items in the file.  This information is used by
     2908        ExifTool, but these entries are not extracted as tags.
     2909    },
     2910    dimg => { Name => 'DerivedImageRef',   RawConv => 'undef' },
     2911    thmb => { Name => 'ThumbnailRef',      RawConv => 'undef' },
     2912    auxl => { Name => 'AuxiliaryImageRef', RawConv => 'undef' },
     2913    cdsc => {
     2914        Name => 'ContentDescribes',
     2915        RawConv => \&ParseContentDescribes,
     2916        WriteHook => \&ParseContentDescribes,
     2917    },
     2918);
     2919
     2920%Image::ExifTool::QuickTime::ItemInfo = (
     2921    PROCESS_PROC => \&ProcessMOV,
     2922    WRITE_PROC => \&WriteQuickTime,
     2923    GROUPS => { 2 => 'Image' },
     2924    # avc1 - AVC image
     2925    # hvc1 - HEVC image
     2926    # lhv1 - L-HEVC image
     2927    # infe - ItemInformationEntry
     2928    # infe types: avc1,hvc1,lhv1,Exif,xml1,iovl(overlay image),grid,mime,hvt1(tile image)
     2929    infe => {
     2930        Name => 'ItemInfoEntry',
     2931        RawConv => \&ParseItemInfoEntry,
     2932        WriteHook => \&ParseItemInfoEntry,
     2933        Notes => 'parsed, but not extracted as a tag',
     2934    },
    11852935);
    11862936
     
    11882938%Image::ExifTool::QuickTime::TrackRef = (
    11892939    PROCESS_PROC => \&ProcessMOV,
    1190     GROUPS => { 2 => 'Video' },
    1191     chap => { Name => 'ChapterList', Format => 'int32u' },
    1192     # also: tmcd, sync, scpt, ssrc, iTunesInfo
     2940    GROUPS => { 1 => 'Track#', 2 => 'Video' },
     2941    chap => { Name => 'ChapterListTrackID', Format => 'int32u' },
     2942    tmcd => { Name => 'TimeCode', Format => 'int32u' },
     2943    mpod => { #PH (FLIR MP4)
     2944        Name => 'ElementaryStreamTrack',
     2945        Format => 'int32u',
     2946        ValueConv => '$val =~ s/^1 //; $val',  # (why 2 numbers? -- ignore the first if "1")
     2947    },
     2948    # also: sync, scpt, ssrc, iTunesInfo
     2949    cdsc => {
     2950        Name => 'ContentDescribes',
     2951        Format => 'int32u',
     2952        PrintConv => '"Track $val"',
     2953    },
     2954    # cdep (Structural Dependency QT tag?)
     2955);
     2956
     2957# track aperture mode dimensions atoms
     2958# (ref https://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap2/qtff2.html)
     2959%Image::ExifTool::QuickTime::TrackAperture = (
     2960    PROCESS_PROC => \&ProcessMOV,
     2961    GROUPS => { 1 => 'Track#', 2 => 'Video' },
     2962    clef => {
     2963        Name => 'CleanApertureDimensions',
     2964        Format => 'fixed32u',
     2965        Count => 3,
     2966        ValueConv => '$val =~ s/^.*? //; $val', # remove flags word
     2967        PrintConv => '$val =~ tr/ /x/; $val',
     2968    },
     2969    prof => {
     2970        Name => 'ProductionApertureDimensions',
     2971        Format => 'fixed32u',
     2972        Count => 3,
     2973        ValueConv => '$val =~ s/^.*? //; $val',
     2974        PrintConv => '$val =~ tr/ /x/; $val',
     2975    },
     2976    enof => {
     2977        Name => 'EncodedPixelsDimensions',
     2978        Format => 'fixed32u',
     2979        Count => 3,
     2980        ValueConv => '$val =~ s/^.*? //; $val',
     2981        PrintConv => '$val =~ tr/ /x/; $val',
     2982    },
    11932983);
    11942984
     
    11972987%Image::ExifTool::QuickTime::ItemList = (
    11982988    PROCESS_PROC => \&ProcessMOV,
    1199     GROUPS => { 2 => 'Audio' },
     2989    WRITE_PROC => \&WriteQuickTime,
     2990    CHECK_PROC => \&CheckQTValue,
     2991    WRITABLE => 1,
     2992    PREFERRED => 2, # (preferred over UserData and Keys tags when writing)
     2993    FORMAT => 'string',
     2994    GROUPS => { 1 => 'ItemList', 2 => 'Audio' },
     2995    WRITE_GROUP => 'ItemList',
     2996    LANG_INFO => \&GetLangInfo,
    12002997    NOTES => q{
    1201         As well as these tags, the 'mdta' handler uses numerical tag ID's which are
    1202         added dynamically to this table after processing the Meta Keys information.
     2998        This is the preferred location for creating new QuickTime tags.  Tags in
     2999        this table support alternate languages which are accessed by adding a
     3000        3-character ISO 639-2 language code and an optional ISO 3166-1 alpha 2
     3001        country code to the tag name (eg. "ItemList:Title-fra" or
     3002        "ItemList::Title-fra-FR").  When creating a new Meta box to contain the
     3003        ItemList directory, by default ExifTool adds an 'mdir' (Metadata) Handler
     3004        box because Apple software may ignore ItemList tags otherwise, but the API
     3005        L<QuickTimeHandler|../ExifTool.html#QuickTimeHandler> option may be set to 0 to avoid this.
    12033006    },
    12043007    # in this table, binary 1 and 2-byte "data"-type tags are interpreted as
    1205     # int8u and int16u.  Multi-byte binary "data" tags are extracted as binary data
     3008    # int8u and int16u.  Multi-byte binary "data" tags are extracted as binary data.
     3009    # (Note that the Preferred property is set to 0 for some tags to prevent them
     3010    #  from being created when a same-named tag already exists in the table)
    12063011    "\xa9ART" => 'Artist',
    12073012    "\xa9alb" => 'Album',
     3013    "\xa9aut" => { Name => 'Author', Avoid => 1, Groups => { 2 => 'Author' } }, #forum10091 ('auth' is preferred)
    12083014    "\xa9cmt" => 'Comment',
    1209     "\xa9com" => 'Composer',
    1210     "\xa9day" => { Name => 'Year', Groups => { 2 => 'Time' } },
     3015    "\xa9com" => { Name => 'Composer', Avoid => 1, }, # ("\xa9wrt" is preferred in ItemList)
     3016    "\xa9day" => {
     3017        Name => 'ContentCreateDate',
     3018        Groups => { 2 => 'Time' },
     3019        Shift => 'Time',
     3020        # handle values in the form "2010-02-12T13:27:14-0800"
     3021        ValueConv => q{
     3022            require Image::ExifTool::XMP;
     3023            $val =  Image::ExifTool::XMP::ConvertXMPDate($val);
     3024            $val =~ s/([-+]\d{2})(\d{2})$/$1:$2/; # add colon to timezone if necessary
     3025            return $val;
     3026        },
     3027        ValueConvInv => q{
     3028            require Image::ExifTool::XMP;
     3029            $val =  Image::ExifTool::XMP::FormatXMPDate($val);
     3030            $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon
     3031            return $val;
     3032        },
     3033        PrintConv => '$self->ConvertDateTime($val)',
     3034        PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
     3035    },
    12113036    "\xa9des" => 'Description', #4
    12123037    "\xa9enc" => 'EncodedBy', #10
     
    12153040    "\xa9lyr" => 'Lyrics',
    12163041    "\xa9nam" => 'Title',
    1217     # "\xa9st3" ? #10
    12183042    "\xa9too" => 'Encoder',
    12193043    "\xa9trk" => 'Track',
    12203044    "\xa9wrt" => 'Composer',
     3045#
     3046# the following tags written by AtomicParsley 0.9.6
     3047# (ref https://exiftool.org/forum/index.php?topic=11455.0)
     3048#
     3049    "\xa9st3" => 'Subtitle',
     3050    "\xa9con" => 'Conductor',
     3051    "\xa9sol" => 'Soloist',
     3052    "\xa9arg" => 'Arranger',
     3053    "\xa9ope" => 'OriginalArtist',
     3054    "\xa9dir" => 'Director',
     3055    "\xa9ard" => 'ArtDirector',
     3056    "\xa9sne" => 'SoundEngineer',
     3057    "\xa9prd" => 'Producer',
     3058    "\xa9xpd" => 'ExecutiveProducer',
     3059    sdes      => 'StoreDescription',
     3060#
    12213061    '----' => {
    12223062        Name => 'iTunesInfo',
    12233063        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::iTunesInfo' },
    12243064    },
    1225     aART => 'AlbumArtist',
    1226     covr => 'CoverArt',
     3065    aART => { Name => 'AlbumArtist', Groups => { 2 => 'Author' } },
     3066    covr => { Name => 'CoverArt',    Groups => { 2 => 'Preview' } },
    12273067    cpil => { #10
    12283068        Name => 'Compilation',
     3069        Format => 'int8u', #27 (ref 23 contradicts what AtomicParsley actually writes, which is int8s)
     3070        Writable => 'int8s',
    12293071        PrintConv => { 0 => 'No', 1 => 'Yes' },
    12303072    },
    12313073    disk => {
    12323074        Name => 'DiskNumber',
    1233         ValueConv => 'length($val) >= 6 ? join(" of ",unpack("x2nn",$val)) : \$val',
     3075        Format => 'undef',  # (necessary to prevent decoding as string!)
     3076        ValueConv => q{
     3077            return \$val unless length($val) >= 6;
     3078            my @a = unpack 'x2nn', $val;
     3079            return $a[1] ? join(' of ', @a) : $a[0];
     3080        },
     3081        ValueConvInv => q{
     3082            my @a = $val =~ /\d+/g;
     3083            return undef if @a == 0 or @a > 2;
     3084            push @a, 0 if @a == 1;
     3085            return pack('n3', 0, @a);
     3086        },
    12343087    },
    12353088    pgap => { #10
    12363089        Name => 'PlayGap',
     3090        Format => 'int8u', #23
     3091        Writable => 'int8s', #27
    12373092        PrintConv => {
    12383093            0 => 'Insert Gap',
     
    12423097    tmpo => {
    12433098        Name => 'BeatsPerMinute',
    1244         Format => 'int16u', # marked as boolean but really int16u in my sample
     3099        # marked as boolean but really int16u in my sample
     3100        # (but written as int16s by iTunes and AtomicParsley, ref forum11506)
     3101        Format => 'int16u',
     3102        Writable => 'int16s',
    12453103    },
    12463104    trkn => {
    12473105        Name => 'TrackNumber',
    1248         ValueConv => 'length($val) >= 6 ? join(" of ",unpack("x2nn",$val)) : \$val',
     3106        Format => 'undef',  # (necessary to prevent decoding as string!)
     3107        ValueConv => q{
     3108            return \$val unless length($val) >= 6;
     3109            my @a = unpack 'x2nn', $val;
     3110            return $a[1] ? join(' of ', @a) : $a[0];
     3111        },
     3112        # (see forum11501 for discussion about the format used)
     3113        ValueConvInv => q{
     3114            my @a = $val =~ /\d+/g;
     3115            return undef if @a == 0 or @a > 2;
     3116            push @a, 0 if @a == 1;
     3117            return pack('n4', 0, @a, 0);
     3118        },
    12493119    },
    12503120#
     
    12543124    akID => { #10
    12553125        Name => 'AppleStoreAccountType',
     3126        Format => 'int8u', #24
     3127        Writable => 'int8s', #27
    12563128        PrintConv => {
    12573129            0 => 'iTunes',
     
    12593131        },
    12603132    },
    1261     albm => 'Album', #(ffmpeg source)
     3133    albm => { Name => 'Album', Avoid => 1 }, #(ffmpeg source)
    12623134    apID => 'AppleStoreAccount',
    12633135    atID => { #10 (or TV series)
    12643136        Name => 'AlbumTitleID',
    12653137        Format => 'int32u',
     3138        Writable => 'int32s', #27
    12663139    },
    12673140    auth => { Name => 'Author', Groups => { 2 => 'Author' } },
     
    12703143        Name => 'AppleStoreCatalogID',
    12713144        Format => 'int32u',
     3145        Writable => 'int32s', #27
    12723146    },
    12733147    cprt => { Name => 'Copyright', Groups => { 2 => 'Author' } },
    1274     dscp => 'Description',
    1275     desc => 'Description', #7
     3148    dscp => { Name => 'Description', Avoid => 1 },
     3149    desc => { Name => 'Description', Avoid => 1 }, #7
    12763150    gnre => { #10
    12773151        Name => 'Genre',
     3152        Avoid => 1,
     3153        # (Note: see https://exiftool.org/forum/index.php?topic=11537.0)
     3154        Format => 'undef',
     3155        ValueConv => 'unpack("n",$val)',
     3156        ValueConvInv => '$val =~ /^\d+$/ ? pack("n",$val) : undef',
    12783157        PrintConv => q{
    12793158            return $val unless $val =~ /^\d+$/;
     
    12813160            Image::ExifTool::ID3::PrintGenre($val - 1); # note the "- 1"
    12823161        },
     3162        PrintConvInv => q{
     3163            return $val if $val =~ /^[0-9]+$/;
     3164            require Image::ExifTool::ID3;
     3165            my $id = Image::ExifTool::ID3::GetGenreID($val);
     3166            return unless defined $id and $id =~ /^\d+$/;
     3167            return $id + 1;
     3168        },
    12833169    },
    12843170    egid => 'EpisodeGlobalUniqueID', #7
     
    12863172        Name => 'GenreID',
    12873173        Format => 'int32u',
    1288         # 4005 = Kids
    1289         # 4010 = Teens
    1290     },
    1291     grup => 'Grouping', #10
     3174        Writable => 'int32s', #27
     3175        SeparateTable => 1,
     3176        # the following lookup is based on http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/genres
     3177        # (see scripts/parse_genre to parse genre JSON file from above)
     3178        PrintConv => { #21/PH
     3179            2 => 'Music|Blues',
     3180            3 => 'Music|Comedy',
     3181            4 => "Music|Children's Music",
     3182            5 => 'Music|Classical',
     3183            6 => 'Music|Country',
     3184            7 => 'Music|Electronic',
     3185            8 => 'Music|Holiday',
     3186            9 => 'Music|Classical|Opera',
     3187            10 => 'Music|Singer/Songwriter',
     3188            11 => 'Music|Jazz',
     3189            12 => 'Music|Latino',
     3190            13 => 'Music|New Age',
     3191            14 => 'Music|Pop',
     3192            15 => 'Music|R&B/Soul',
     3193            16 => 'Music|Soundtrack',
     3194            17 => 'Music|Dance',
     3195            18 => 'Music|Hip-Hop/Rap',
     3196            19 => 'Music|World',
     3197            20 => 'Music|Alternative',
     3198            21 => 'Music|Rock',
     3199            22 => 'Music|Christian & Gospel',
     3200            23 => 'Music|Vocal',
     3201            24 => 'Music|Reggae',
     3202            25 => 'Music|Easy Listening',
     3203            26 => 'Podcasts',
     3204            27 => 'Music|J-Pop',
     3205            28 => 'Music|Enka',
     3206            29 => 'Music|Anime',
     3207            30 => 'Music|Kayokyoku',
     3208            31 => 'Music Videos',
     3209            32 => 'TV Shows',
     3210            33 => 'Movies',
     3211            34 => 'Music',
     3212            35 => 'iPod Games',
     3213            36 => 'App Store',
     3214            37 => 'Tones',
     3215            38 => 'Books',
     3216            39 => 'Mac App Store',
     3217            40 => 'Textbooks',
     3218            50 => 'Music|Fitness & Workout',
     3219            51 => 'Music|Pop|K-Pop',
     3220            52 => 'Music|Karaoke',
     3221            53 => 'Music|Instrumental',
     3222            74 => 'Audiobooks|News',
     3223            75 => 'Audiobooks|Programs & Performances',
     3224            500 => 'Fitness Music',
     3225            501 => 'Fitness Music|Pop',
     3226            502 => 'Fitness Music|Dance',
     3227            503 => 'Fitness Music|Hip-Hop',
     3228            504 => 'Fitness Music|Rock',
     3229            505 => 'Fitness Music|Alt/Indie',
     3230            506 => 'Fitness Music|Latino',
     3231            507 => 'Fitness Music|Country',
     3232            508 => 'Fitness Music|World',
     3233            509 => 'Fitness Music|New Age',
     3234            510 => 'Fitness Music|Classical',
     3235            1001 => 'Music|Alternative|College Rock',
     3236            1002 => 'Music|Alternative|Goth Rock',
     3237            1003 => 'Music|Alternative|Grunge',
     3238            1004 => 'Music|Alternative|Indie Rock',
     3239            1005 => 'Music|Alternative|New Wave',
     3240            1006 => 'Music|Alternative|Punk',
     3241            1007 => 'Music|Blues|Chicago Blues',
     3242            1009 => 'Music|Blues|Classic Blues',
     3243            1010 => 'Music|Blues|Contemporary Blues',
     3244            1011 => 'Music|Blues|Country Blues',
     3245            1012 => 'Music|Blues|Delta Blues',
     3246            1013 => 'Music|Blues|Electric Blues',
     3247            1014 => "Music|Children's Music|Lullabies",
     3248            1015 => "Music|Children's Music|Sing-Along",
     3249            1016 => "Music|Children's Music|Stories",
     3250            1017 => 'Music|Classical|Avant-Garde',
     3251            1018 => 'Music|Classical|Baroque Era',
     3252            1019 => 'Music|Classical|Chamber Music',
     3253            1020 => 'Music|Classical|Chant',
     3254            1021 => 'Music|Classical|Choral',
     3255            1022 => 'Music|Classical|Classical Crossover',
     3256            1023 => 'Music|Classical|Early Music',
     3257            1024 => 'Music|Classical|Impressionist',
     3258            1025 => 'Music|Classical|Medieval Era',
     3259            1026 => 'Music|Classical|Minimalism',
     3260            1027 => 'Music|Classical|Modern Era',
     3261            1028 => 'Music|Classical|Opera',
     3262            1029 => 'Music|Classical|Orchestral',
     3263            1030 => 'Music|Classical|Renaissance',
     3264            1031 => 'Music|Classical|Romantic Era',
     3265            1032 => 'Music|Classical|Wedding Music',
     3266            1033 => 'Music|Country|Alternative Country',
     3267            1034 => 'Music|Country|Americana',
     3268            1035 => 'Music|Country|Bluegrass',
     3269            1036 => 'Music|Country|Contemporary Bluegrass',
     3270            1037 => 'Music|Country|Contemporary Country',
     3271            1038 => 'Music|Country|Country Gospel',
     3272            1039 => 'Music|Country|Honky Tonk',
     3273            1040 => 'Music|Country|Outlaw Country',
     3274            1041 => 'Music|Country|Traditional Bluegrass',
     3275            1042 => 'Music|Country|Traditional Country',
     3276            1043 => 'Music|Country|Urban Cowboy',
     3277            1044 => 'Music|Dance|Breakbeat',
     3278            1045 => 'Music|Dance|Exercise',
     3279            1046 => 'Music|Dance|Garage',
     3280            1047 => 'Music|Dance|Hardcore',
     3281            1048 => 'Music|Dance|House',
     3282            1049 => "Music|Dance|Jungle/Drum'n'bass",
     3283            1050 => 'Music|Dance|Techno',
     3284            1051 => 'Music|Dance|Trance',
     3285            1052 => 'Music|Jazz|Big Band',
     3286            1053 => 'Music|Jazz|Bop',
     3287            1054 => 'Music|Easy Listening|Lounge',
     3288            1055 => 'Music|Easy Listening|Swing',
     3289            1056 => 'Music|Electronic|Ambient',
     3290            1057 => 'Music|Electronic|Downtempo',
     3291            1058 => 'Music|Electronic|Electronica',
     3292            1060 => 'Music|Electronic|IDM/Experimental',
     3293            1061 => 'Music|Electronic|Industrial',
     3294            1062 => 'Music|Singer/Songwriter|Alternative Folk',
     3295            1063 => 'Music|Singer/Songwriter|Contemporary Folk',
     3296            1064 => 'Music|Singer/Songwriter|Contemporary Singer/Songwriter',
     3297            1065 => 'Music|Singer/Songwriter|Folk-Rock',
     3298            1066 => 'Music|Singer/Songwriter|New Acoustic',
     3299            1067 => 'Music|Singer/Songwriter|Traditional Folk',
     3300            1068 => 'Music|Hip-Hop/Rap|Alternative Rap',
     3301            1069 => 'Music|Hip-Hop/Rap|Dirty South',
     3302            1070 => 'Music|Hip-Hop/Rap|East Coast Rap',
     3303            1071 => 'Music|Hip-Hop/Rap|Gangsta Rap',
     3304            1072 => 'Music|Hip-Hop/Rap|Hardcore Rap',
     3305            1073 => 'Music|Hip-Hop/Rap|Hip-Hop',
     3306            1074 => 'Music|Hip-Hop/Rap|Latin Rap',
     3307            1075 => 'Music|Hip-Hop/Rap|Old School Rap',
     3308            1076 => 'Music|Hip-Hop/Rap|Rap',
     3309            1077 => 'Music|Hip-Hop/Rap|Underground Rap',
     3310            1078 => 'Music|Hip-Hop/Rap|West Coast Rap',
     3311            1079 => 'Music|Holiday|Chanukah',
     3312            1080 => 'Music|Holiday|Christmas',
     3313            1081 => "Music|Holiday|Christmas: Children's",
     3314            1082 => 'Music|Holiday|Christmas: Classic',
     3315            1083 => 'Music|Holiday|Christmas: Classical',
     3316            1084 => 'Music|Holiday|Christmas: Jazz',
     3317            1085 => 'Music|Holiday|Christmas: Modern',
     3318            1086 => 'Music|Holiday|Christmas: Pop',
     3319            1087 => 'Music|Holiday|Christmas: R&B',
     3320            1088 => 'Music|Holiday|Christmas: Religious',
     3321            1089 => 'Music|Holiday|Christmas: Rock',
     3322            1090 => 'Music|Holiday|Easter',
     3323            1091 => 'Music|Holiday|Halloween',
     3324            1092 => 'Music|Holiday|Holiday: Other',
     3325            1093 => 'Music|Holiday|Thanksgiving',
     3326            1094 => 'Music|Christian & Gospel|CCM',
     3327            1095 => 'Music|Christian & Gospel|Christian Metal',
     3328            1096 => 'Music|Christian & Gospel|Christian Pop',
     3329            1097 => 'Music|Christian & Gospel|Christian Rap',
     3330            1098 => 'Music|Christian & Gospel|Christian Rock',
     3331            1099 => 'Music|Christian & Gospel|Classic Christian',
     3332            1100 => 'Music|Christian & Gospel|Contemporary Gospel',
     3333            1101 => 'Music|Christian & Gospel|Gospel',
     3334            1103 => 'Music|Christian & Gospel|Praise & Worship',
     3335            1104 => 'Music|Christian & Gospel|Southern Gospel',
     3336            1105 => 'Music|Christian & Gospel|Traditional Gospel',
     3337            1106 => 'Music|Jazz|Avant-Garde Jazz',
     3338            1107 => 'Music|Jazz|Contemporary Jazz',
     3339            1108 => 'Music|Jazz|Crossover Jazz',
     3340            1109 => 'Music|Jazz|Dixieland',
     3341            1110 => 'Music|Jazz|Fusion',
     3342            1111 => 'Music|Jazz|Latin Jazz',
     3343            1112 => 'Music|Jazz|Mainstream Jazz',
     3344            1113 => 'Music|Jazz|Ragtime',
     3345            1114 => 'Music|Jazz|Smooth Jazz',
     3346            1115 => 'Music|Latino|Latin Jazz',
     3347            1116 => 'Music|Latino|Contemporary Latin',
     3348            1117 => 'Music|Latino|Pop Latino',
     3349            1118 => 'Music|Latino|Raices', # (Ra&iacute;ces)
     3350            1119 => 'Music|Latino|Urbano latino',
     3351            1120 => 'Music|Latino|Baladas y Boleros',
     3352            1121 => 'Music|Latino|Rock y Alternativo',
     3353            1122 => 'Music|Brazilian',
     3354            1123 => 'Music|Latino|Musica Mexicana', # (M&uacute;sica Mexicana)
     3355            1124 => 'Music|Latino|Musica tropical', # (M&uacute;sica tropical)
     3356            1125 => 'Music|New Age|Environmental',
     3357            1126 => 'Music|New Age|Healing',
     3358            1127 => 'Music|New Age|Meditation',
     3359            1128 => 'Music|New Age|Nature',
     3360            1129 => 'Music|New Age|Relaxation',
     3361            1130 => 'Music|New Age|Travel',
     3362            1131 => 'Music|Pop|Adult Contemporary',
     3363            1132 => 'Music|Pop|Britpop',
     3364            1133 => 'Music|Pop|Pop/Rock',
     3365            1134 => 'Music|Pop|Soft Rock',
     3366            1135 => 'Music|Pop|Teen Pop',
     3367            1136 => 'Music|R&B/Soul|Contemporary R&B',
     3368            1137 => 'Music|R&B/Soul|Disco',
     3369            1138 => 'Music|R&B/Soul|Doo Wop',
     3370            1139 => 'Music|R&B/Soul|Funk',
     3371            1140 => 'Music|R&B/Soul|Motown',
     3372            1141 => 'Music|R&B/Soul|Neo-Soul',
     3373            1142 => 'Music|R&B/Soul|Quiet Storm',
     3374            1143 => 'Music|R&B/Soul|Soul',
     3375            1144 => 'Music|Rock|Adult Alternative',
     3376            1145 => 'Music|Rock|American Trad Rock',
     3377            1146 => 'Music|Rock|Arena Rock',
     3378            1147 => 'Music|Rock|Blues-Rock',
     3379            1148 => 'Music|Rock|British Invasion',
     3380            1149 => 'Music|Rock|Death Metal/Black Metal',
     3381            1150 => 'Music|Rock|Glam Rock',
     3382            1151 => 'Music|Rock|Hair Metal',
     3383            1152 => 'Music|Rock|Hard Rock',
     3384            1153 => 'Music|Rock|Metal',
     3385            1154 => 'Music|Rock|Jam Bands',
     3386            1155 => 'Music|Rock|Prog-Rock/Art Rock',
     3387            1156 => 'Music|Rock|Psychedelic',
     3388            1157 => 'Music|Rock|Rock & Roll',
     3389            1158 => 'Music|Rock|Rockabilly',
     3390            1159 => 'Music|Rock|Roots Rock',
     3391            1160 => 'Music|Rock|Singer/Songwriter',
     3392            1161 => 'Music|Rock|Southern Rock',
     3393            1162 => 'Music|Rock|Surf',
     3394            1163 => 'Music|Rock|Tex-Mex',
     3395            1165 => 'Music|Soundtrack|Foreign Cinema',
     3396            1166 => 'Music|Soundtrack|Musicals',
     3397            1167 => 'Music|Comedy|Novelty',
     3398            1168 => 'Music|Soundtrack|Original Score',
     3399            1169 => 'Music|Soundtrack|Soundtrack',
     3400            1171 => 'Music|Comedy|Standup Comedy',
     3401            1172 => 'Music|Soundtrack|TV Soundtrack',
     3402            1173 => 'Music|Vocal|Standards',
     3403            1174 => 'Music|Vocal|Traditional Pop',
     3404            1175 => 'Music|Jazz|Vocal Jazz',
     3405            1176 => 'Music|Vocal|Vocal Pop',
     3406            1177 => 'Music|African|Afro-Beat',
     3407            1178 => 'Music|African|Afro-Pop',
     3408            1179 => 'Music|World|Cajun',
     3409            1180 => 'Music|World|Celtic',
     3410            1181 => 'Music|World|Celtic Folk',
     3411            1182 => 'Music|World|Contemporary Celtic',
     3412            1183 => 'Music|Reggae|Modern Dancehall',
     3413            1184 => 'Music|World|Drinking Songs',
     3414            1185 => 'Music|Indian|Indian Pop',
     3415            1186 => 'Music|World|Japanese Pop',
     3416            1187 => 'Music|World|Klezmer',
     3417            1188 => 'Music|World|Polka',
     3418            1189 => 'Music|World|Traditional Celtic',
     3419            1190 => 'Music|World|Worldbeat',
     3420            1191 => 'Music|World|Zydeco',
     3421            1192 => 'Music|Reggae|Roots Reggae',
     3422            1193 => 'Music|Reggae|Dub',
     3423            1194 => 'Music|Reggae|Ska',
     3424            1195 => 'Music|World|Caribbean',
     3425            1196 => 'Music|World|South America',
     3426            1197 => 'Music|Arabic',
     3427            1198 => 'Music|World|North America',
     3428            1199 => 'Music|World|Hawaii',
     3429            1200 => 'Music|World|Australia',
     3430            1201 => 'Music|World|Japan',
     3431            1202 => 'Music|World|France',
     3432            1203 => 'Music|African',
     3433            1204 => 'Music|World|Asia',
     3434            1205 => 'Music|World|Europe',
     3435            1206 => 'Music|World|South Africa',
     3436            1207 => 'Music|Jazz|Hard Bop',
     3437            1208 => 'Music|Jazz|Trad Jazz',
     3438            1209 => 'Music|Jazz|Cool Jazz',
     3439            1210 => 'Music|Blues|Acoustic Blues',
     3440            1211 => 'Music|Classical|High Classical',
     3441            1220 => 'Music|Brazilian|Axe', # (Ax&eacute;)
     3442            1221 => 'Music|Brazilian|Bossa Nova',
     3443            1222 => 'Music|Brazilian|Choro',
     3444            1223 => 'Music|Brazilian|Forro', # (Forr&oacute;)
     3445            1224 => 'Music|Brazilian|Frevo',
     3446            1225 => 'Music|Brazilian|MPB',
     3447            1226 => 'Music|Brazilian|Pagode',
     3448            1227 => 'Music|Brazilian|Samba',
     3449            1228 => 'Music|Brazilian|Sertanejo',
     3450            1229 => 'Music|Brazilian|Baile Funk',
     3451            1230 => 'Music|Alternative|Chinese Alt',
     3452            1231 => 'Music|Alternative|Korean Indie',
     3453            1232 => 'Music|Chinese',
     3454            1233 => 'Music|Chinese|Chinese Classical',
     3455            1234 => 'Music|Chinese|Chinese Flute',
     3456            1235 => 'Music|Chinese|Chinese Opera',
     3457            1236 => 'Music|Chinese|Chinese Orchestral',
     3458            1237 => 'Music|Chinese|Chinese Regional Folk',
     3459            1238 => 'Music|Chinese|Chinese Strings',
     3460            1239 => 'Music|Chinese|Taiwanese Folk',
     3461            1240 => 'Music|Chinese|Tibetan Native Music',
     3462            1241 => 'Music|Hip-Hop/Rap|Chinese Hip-Hop',
     3463            1242 => 'Music|Hip-Hop/Rap|Korean Hip-Hop',
     3464            1243 => 'Music|Korean',
     3465            1244 => 'Music|Korean|Korean Classical',
     3466            1245 => 'Music|Korean|Korean Trad Song',
     3467            1246 => 'Music|Korean|Korean Trad Instrumental',
     3468            1247 => 'Music|Korean|Korean Trad Theater',
     3469            1248 => 'Music|Rock|Chinese Rock',
     3470            1249 => 'Music|Rock|Korean Rock',
     3471            1250 => 'Music|Pop|C-Pop',
     3472            1251 => 'Music|Pop|Cantopop/HK-Pop',
     3473            1252 => 'Music|Pop|Korean Folk-Pop',
     3474            1253 => 'Music|Pop|Mandopop',
     3475            1254 => 'Music|Pop|Tai-Pop',
     3476            1255 => 'Music|Pop|Malaysian Pop',
     3477            1256 => 'Music|Pop|Pinoy Pop',
     3478            1257 => 'Music|Pop|Original Pilipino Music',
     3479            1258 => 'Music|Pop|Manilla Sound',
     3480            1259 => 'Music|Pop|Indo Pop',
     3481            1260 => 'Music|Pop|Thai Pop',
     3482            1261 => 'Music|Vocal|Trot',
     3483            1262 => 'Music|Indian',
     3484            1263 => 'Music|Indian|Bollywood',
     3485            1264 => 'Music|Indian|Regional Indian|Tamil',
     3486            1265 => 'Music|Indian|Regional Indian|Telugu',
     3487            1266 => 'Music|Indian|Regional Indian',
     3488            1267 => 'Music|Indian|Devotional & Spiritual',
     3489            1268 => 'Music|Indian|Sufi',
     3490            1269 => 'Music|Indian|Indian Classical',
     3491            1270 => 'Music|Russian|Russian Chanson',
     3492            1271 => 'Music|World|Dini',
     3493            1272 => 'Music|Turkish|Halk',
     3494            1273 => 'Music|Turkish|Sanat',
     3495            1274 => 'Music|World|Dangdut',
     3496            1275 => 'Music|World|Indonesian Religious',
     3497            1276 => 'Music|World|Calypso',
     3498            1277 => 'Music|World|Soca',
     3499            1278 => 'Music|Indian|Ghazals',
     3500            1279 => 'Music|Indian|Indian Folk',
     3501            1280 => 'Music|Turkish|Arabesque',
     3502            1281 => 'Music|African|Afrikaans',
     3503            1282 => 'Music|World|Farsi',
     3504            1283 => 'Music|World|Israeli',
     3505            1284 => 'Music|Arabic|Khaleeji',
     3506            1285 => 'Music|Arabic|North African',
     3507            1286 => 'Music|Arabic|Arabic Pop',
     3508            1287 => 'Music|Arabic|Islamic',
     3509            1288 => 'Music|Soundtrack|Sound Effects',
     3510            1289 => 'Music|Folk',
     3511            1290 => 'Music|Orchestral',
     3512            1291 => 'Music|Marching',
     3513            1293 => 'Music|Pop|Oldies',
     3514            1294 => 'Music|Country|Thai Country',
     3515            1295 => 'Music|World|Flamenco',
     3516            1296 => 'Music|World|Tango',
     3517            1297 => 'Music|World|Fado',
     3518            1298 => 'Music|World|Iberia',
     3519            1299 => 'Music|Russian',
     3520            1300 => 'Music|Turkish',
     3521            1301 => 'Podcasts|Arts',
     3522            1302 => 'Podcasts|Society & Culture|Personal Journals',
     3523            1303 => 'Podcasts|Comedy',
     3524            1304 => 'Podcasts|Education',
     3525            1305 => 'Podcasts|Kids & Family',
     3526            1306 => 'Podcasts|Arts|Food',
     3527            1307 => 'Podcasts|Health',
     3528            1309 => 'Podcasts|TV & Film',
     3529            1310 => 'Podcasts|Music',
     3530            1311 => 'Podcasts|News & Politics',
     3531            1314 => 'Podcasts|Religion & Spirituality',
     3532            1315 => 'Podcasts|Science & Medicine',
     3533            1316 => 'Podcasts|Sports & Recreation',
     3534            1318 => 'Podcasts|Technology',
     3535            1320 => 'Podcasts|Society & Culture|Places & Travel',
     3536            1321 => 'Podcasts|Business',
     3537            1323 => 'Podcasts|Games & Hobbies',
     3538            1324 => 'Podcasts|Society & Culture',
     3539            1325 => 'Podcasts|Government & Organizations',
     3540            1337 => 'Music Videos|Classical|Piano',
     3541            1401 => 'Podcasts|Arts|Literature',
     3542            1402 => 'Podcasts|Arts|Design',
     3543            1404 => 'Podcasts|Games & Hobbies|Video Games',
     3544            1405 => 'Podcasts|Arts|Performing Arts',
     3545            1406 => 'Podcasts|Arts|Visual Arts',
     3546            1410 => 'Podcasts|Business|Careers',
     3547            1412 => 'Podcasts|Business|Investing',
     3548            1413 => 'Podcasts|Business|Management & Marketing',
     3549            1415 => 'Podcasts|Education|K-12',
     3550            1416 => 'Podcasts|Education|Higher Education',
     3551            1417 => 'Podcasts|Health|Fitness & Nutrition',
     3552            1420 => 'Podcasts|Health|Self-Help',
     3553            1421 => 'Podcasts|Health|Sexuality',
     3554            1438 => 'Podcasts|Religion & Spirituality|Buddhism',
     3555            1439 => 'Podcasts|Religion & Spirituality|Christianity',
     3556            1440 => 'Podcasts|Religion & Spirituality|Islam',
     3557            1441 => 'Podcasts|Religion & Spirituality|Judaism',
     3558            1443 => 'Podcasts|Society & Culture|Philosophy',
     3559            1444 => 'Podcasts|Religion & Spirituality|Spirituality',
     3560            1446 => 'Podcasts|Technology|Gadgets',
     3561            1448 => 'Podcasts|Technology|Tech News',
     3562            1450 => 'Podcasts|Technology|Podcasting',
     3563            1454 => 'Podcasts|Games & Hobbies|Automotive',
     3564            1455 => 'Podcasts|Games & Hobbies|Aviation',
     3565            1456 => 'Podcasts|Sports & Recreation|Outdoor',
     3566            1459 => 'Podcasts|Arts|Fashion & Beauty',
     3567            1460 => 'Podcasts|Games & Hobbies|Hobbies',
     3568            1461 => 'Podcasts|Games & Hobbies|Other Games',
     3569            1462 => 'Podcasts|Society & Culture|History',
     3570            1463 => 'Podcasts|Religion & Spirituality|Hinduism',
     3571            1464 => 'Podcasts|Religion & Spirituality|Other',
     3572            1465 => 'Podcasts|Sports & Recreation|Professional',
     3573            1466 => 'Podcasts|Sports & Recreation|College & High School',
     3574            1467 => 'Podcasts|Sports & Recreation|Amateur',
     3575            1468 => 'Podcasts|Education|Educational Technology',
     3576            1469 => 'Podcasts|Education|Language Courses',
     3577            1470 => 'Podcasts|Education|Training',
     3578            1471 => 'Podcasts|Business|Business News',
     3579            1472 => 'Podcasts|Business|Shopping',
     3580            1473 => 'Podcasts|Government & Organizations|National',
     3581            1474 => 'Podcasts|Government & Organizations|Regional',
     3582            1475 => 'Podcasts|Government & Organizations|Local',
     3583            1476 => 'Podcasts|Government & Organizations|Non-Profit',
     3584            1477 => 'Podcasts|Science & Medicine|Natural Sciences',
     3585            1478 => 'Podcasts|Science & Medicine|Medicine',
     3586            1479 => 'Podcasts|Science & Medicine|Social Sciences',
     3587            1480 => 'Podcasts|Technology|Software How-To',
     3588            1481 => 'Podcasts|Health|Alternative Health',
     3589            1482 => 'Podcasts|Arts|Books',
     3590            1483 => 'Podcasts|Fiction',
     3591            1484 => 'Podcasts|Fiction|Drama',
     3592            1485 => 'Podcasts|Fiction|Science Fiction',
     3593            1486 => 'Podcasts|Fiction|Comedy Fiction',
     3594            1487 => 'Podcasts|History',
     3595            1488 => 'Podcasts|True Crime',
     3596            1489 => 'Podcasts|News',
     3597            1490 => 'Podcasts|News|Business News',
     3598            1491 => 'Podcasts|Business|Management',
     3599            1492 => 'Podcasts|Business|Marketing',
     3600            1493 => 'Podcasts|Business|Entrepreneurship',
     3601            1494 => 'Podcasts|Business|Non-Profit',
     3602            1495 => 'Podcasts|Comedy|Improv',
     3603            1496 => 'Podcasts|Comedy|Comedy Interviews',
     3604            1497 => 'Podcasts|Comedy|Stand-Up',
     3605            1498 => 'Podcasts|Education|Language Learning',
     3606            1499 => 'Podcasts|Education|How To',
     3607            1500 => 'Podcasts|Education|Self-Improvement',
     3608            1501 => 'Podcasts|Education|Courses',
     3609            1502 => 'Podcasts|Leisure',
     3610            1503 => 'Podcasts|Leisure|Automotive',
     3611            1504 => 'Podcasts|Leisure|Aviation',
     3612            1505 => 'Podcasts|Leisure|Hobbies',
     3613            1506 => 'Podcasts|Leisure|Crafts',
     3614            1507 => 'Podcasts|Leisure|Games',
     3615            1508 => 'Podcasts|Leisure|Home & Garden',
     3616            1509 => 'Podcasts|Leisure|Video Games',
     3617            1510 => 'Podcasts|Leisure|Animation & Manga',
     3618            1511 => 'Podcasts|Government',
     3619            1512 => 'Podcasts|Health & Fitness',
     3620            1513 => 'Podcasts|Health & Fitness|Alternative Health',
     3621            1514 => 'Podcasts|Health & Fitness|Fitness',
     3622            1515 => 'Podcasts|Health & Fitness|Nutrition',
     3623            1516 => 'Podcasts|Health & Fitness|Sexuality',
     3624            1517 => 'Podcasts|Health & Fitness|Mental Health',
     3625            1518 => 'Podcasts|Health & Fitness|Medicine',
     3626            1519 => 'Podcasts|Kids & Family|Education for Kids',
     3627            1520 => 'Podcasts|Kids & Family|Stories for Kids',
     3628            1521 => 'Podcasts|Kids & Family|Parenting',
     3629            1522 => 'Podcasts|Kids & Family|Pets & Animals',
     3630            1523 => 'Podcasts|Music|Music Commentary',
     3631            1524 => 'Podcasts|Music|Music History',
     3632            1525 => 'Podcasts|Music|Music Interviews',
     3633            1526 => 'Podcasts|News|Daily News',
     3634            1527 => 'Podcasts|News|Politics',
     3635            1528 => 'Podcasts|News|Tech News',
     3636            1529 => 'Podcasts|News|Sports News',
     3637            1530 => 'Podcasts|News|News Commentary',
     3638            1531 => 'Podcasts|News|Entertainment News',
     3639            1532 => 'Podcasts|Religion & Spirituality|Religion',
     3640            1533 => 'Podcasts|Science',
     3641            1534 => 'Podcasts|Science|Natural Sciences',
     3642            1535 => 'Podcasts|Science|Social Sciences',
     3643            1536 => 'Podcasts|Science|Mathematics',
     3644            1537 => 'Podcasts|Science|Nature',
     3645            1538 => 'Podcasts|Science|Astronomy',
     3646            1539 => 'Podcasts|Science|Chemistry',
     3647            1540 => 'Podcasts|Science|Earth Sciences',
     3648            1541 => 'Podcasts|Science|Life Sciences',
     3649            1542 => 'Podcasts|Science|Physics',
     3650            1543 => 'Podcasts|Society & Culture|Documentary',
     3651            1544 => 'Podcasts|Society & Culture|Relationships',
     3652            1545 => 'Podcasts|Sports',
     3653            1546 => 'Podcasts|Sports|Soccer',
     3654            1547 => 'Podcasts|Sports|Football',
     3655            1548 => 'Podcasts|Sports|Basketball',
     3656            1549 => 'Podcasts|Sports|Baseball',
     3657            1550 => 'Podcasts|Sports|Hockey',
     3658            1551 => 'Podcasts|Sports|Running',
     3659            1552 => 'Podcasts|Sports|Rugby',
     3660            1553 => 'Podcasts|Sports|Golf',
     3661            1554 => 'Podcasts|Sports|Cricket',
     3662            1555 => 'Podcasts|Sports|Wrestling',
     3663            1556 => 'Podcasts|Sports|Tennis',
     3664            1557 => 'Podcasts|Sports|Volleyball',
     3665            1558 => 'Podcasts|Sports|Swimming',
     3666            1559 => 'Podcasts|Sports|Wilderness',
     3667            1560 => 'Podcasts|Sports|Fantasy Sports',
     3668            1561 => 'Podcasts|TV & Film|TV Reviews',
     3669            1562 => 'Podcasts|TV & Film|After Shows',
     3670            1563 => 'Podcasts|TV & Film|Film Reviews',
     3671            1564 => 'Podcasts|TV & Film|Film History',
     3672            1565 => 'Podcasts|TV & Film|Film Interviews',
     3673            1602 => 'Music Videos|Blues',
     3674            1603 => 'Music Videos|Comedy',
     3675            1604 => "Music Videos|Children's Music",
     3676            1605 => 'Music Videos|Classical',
     3677            1606 => 'Music Videos|Country',
     3678            1607 => 'Music Videos|Electronic',
     3679            1608 => 'Music Videos|Holiday',
     3680            1609 => 'Music Videos|Classical|Opera',
     3681            1610 => 'Music Videos|Singer/Songwriter',
     3682            1611 => 'Music Videos|Jazz',
     3683            1612 => 'Music Videos|Latin',
     3684            1613 => 'Music Videos|New Age',
     3685            1614 => 'Music Videos|Pop',
     3686            1615 => 'Music Videos|R&B/Soul',
     3687            1616 => 'Music Videos|Soundtrack',
     3688            1617 => 'Music Videos|Dance',
     3689            1618 => 'Music Videos|Hip-Hop/Rap',
     3690            1619 => 'Music Videos|World',
     3691            1620 => 'Music Videos|Alternative',
     3692            1621 => 'Music Videos|Rock',
     3693            1622 => 'Music Videos|Christian & Gospel',
     3694            1623 => 'Music Videos|Vocal',
     3695            1624 => 'Music Videos|Reggae',
     3696            1625 => 'Music Videos|Easy Listening',
     3697            1626 => 'Music Videos|Podcasts',
     3698            1627 => 'Music Videos|J-Pop',
     3699            1628 => 'Music Videos|Enka',
     3700            1629 => 'Music Videos|Anime',
     3701            1630 => 'Music Videos|Kayokyoku',
     3702            1631 => 'Music Videos|Disney',
     3703            1632 => 'Music Videos|French Pop',
     3704            1633 => 'Music Videos|German Pop',
     3705            1634 => 'Music Videos|German Folk',
     3706            1635 => 'Music Videos|Alternative|Chinese Alt',
     3707            1636 => 'Music Videos|Alternative|Korean Indie',
     3708            1637 => 'Music Videos|Chinese',
     3709            1638 => 'Music Videos|Chinese|Chinese Classical',
     3710            1639 => 'Music Videos|Chinese|Chinese Flute',
     3711            1640 => 'Music Videos|Chinese|Chinese Opera',
     3712            1641 => 'Music Videos|Chinese|Chinese Orchestral',
     3713            1642 => 'Music Videos|Chinese|Chinese Regional Folk',
     3714            1643 => 'Music Videos|Chinese|Chinese Strings',
     3715            1644 => 'Music Videos|Chinese|Taiwanese Folk',
     3716            1645 => 'Music Videos|Chinese|Tibetan Native Music',
     3717            1646 => 'Music Videos|Hip-Hop/Rap|Chinese Hip-Hop',
     3718            1647 => 'Music Videos|Hip-Hop/Rap|Korean Hip-Hop',
     3719            1648 => 'Music Videos|Korean',
     3720            1649 => 'Music Videos|Korean|Korean Classical',
     3721            1650 => 'Music Videos|Korean|Korean Trad Song',
     3722            1651 => 'Music Videos|Korean|Korean Trad Instrumental',
     3723            1652 => 'Music Videos|Korean|Korean Trad Theater',
     3724            1653 => 'Music Videos|Rock|Chinese Rock',
     3725            1654 => 'Music Videos|Rock|Korean Rock',
     3726            1655 => 'Music Videos|Pop|C-Pop',
     3727            1656 => 'Music Videos|Pop|Cantopop/HK-Pop',
     3728            1657 => 'Music Videos|Pop|Korean Folk-Pop',
     3729            1658 => 'Music Videos|Pop|Mandopop',
     3730            1659 => 'Music Videos|Pop|Tai-Pop',
     3731            1660 => 'Music Videos|Pop|Malaysian Pop',
     3732            1661 => 'Music Videos|Pop|Pinoy Pop',
     3733            1662 => 'Music Videos|Pop|Original Pilipino Music',
     3734            1663 => 'Music Videos|Pop|Manilla Sound',
     3735            1664 => 'Music Videos|Pop|Indo Pop',
     3736            1665 => 'Music Videos|Pop|Thai Pop',
     3737            1666 => 'Music Videos|Vocal|Trot',
     3738            1671 => 'Music Videos|Brazilian',
     3739            1672 => 'Music Videos|Brazilian|Axe', # (Ax&eacute;)
     3740            1673 => 'Music Videos|Brazilian|Baile Funk',
     3741            1674 => 'Music Videos|Brazilian|Bossa Nova',
     3742            1675 => 'Music Videos|Brazilian|Choro',
     3743            1676 => 'Music Videos|Brazilian|Forro',
     3744            1677 => 'Music Videos|Brazilian|Frevo',
     3745            1678 => 'Music Videos|Brazilian|MPB',
     3746            1679 => 'Music Videos|Brazilian|Pagode',
     3747            1680 => 'Music Videos|Brazilian|Samba',
     3748            1681 => 'Music Videos|Brazilian|Sertanejo',
     3749            1682 => 'Music Videos|Classical|High Classical',
     3750            1683 => 'Music Videos|Fitness & Workout',
     3751            1684 => 'Music Videos|Instrumental',
     3752            1685 => 'Music Videos|Jazz|Big Band',
     3753            1686 => 'Music Videos|Pop|K-Pop',
     3754            1687 => 'Music Videos|Karaoke',
     3755            1688 => 'Music Videos|Rock|Heavy Metal',
     3756            1689 => 'Music Videos|Spoken Word',
     3757            1690 => 'Music Videos|Indian',
     3758            1691 => 'Music Videos|Indian|Bollywood',
     3759            1692 => 'Music Videos|Indian|Regional Indian|Tamil',
     3760            1693 => 'Music Videos|Indian|Regional Indian|Telugu',
     3761            1694 => 'Music Videos|Indian|Regional Indian',
     3762            1695 => 'Music Videos|Indian|Devotional & Spiritual',
     3763            1696 => 'Music Videos|Indian|Sufi',
     3764            1697 => 'Music Videos|Indian|Indian Classical',
     3765            1698 => 'Music Videos|Russian|Russian Chanson',
     3766            1699 => 'Music Videos|World|Dini',
     3767            1700 => 'Music Videos|Turkish|Halk',
     3768            1701 => 'Music Videos|Turkish|Sanat',
     3769            1702 => 'Music Videos|World|Dangdut',
     3770            1703 => 'Music Videos|World|Indonesian Religious',
     3771            1704 => 'Music Videos|Indian|Indian Pop',
     3772            1705 => 'Music Videos|World|Calypso',
     3773            1706 => 'Music Videos|World|Soca',
     3774            1707 => 'Music Videos|Indian|Ghazals',
     3775            1708 => 'Music Videos|Indian|Indian Folk',
     3776            1709 => 'Music Videos|Turkish|Arabesque',
     3777            1710 => 'Music Videos|African|Afrikaans',
     3778            1711 => 'Music Videos|World|Farsi',
     3779            1712 => 'Music Videos|World|Israeli',
     3780            1713 => 'Music Videos|Arabic',
     3781            1714 => 'Music Videos|Arabic|Khaleeji',
     3782            1715 => 'Music Videos|Arabic|North African',
     3783            1716 => 'Music Videos|Arabic|Arabic Pop',
     3784            1717 => 'Music Videos|Arabic|Islamic',
     3785            1718 => 'Music Videos|Soundtrack|Sound Effects',
     3786            1719 => 'Music Videos|Folk',
     3787            1720 => 'Music Videos|Orchestral',
     3788            1721 => 'Music Videos|Marching',
     3789            1723 => 'Music Videos|Pop|Oldies',
     3790            1724 => 'Music Videos|Country|Thai Country',
     3791            1725 => 'Music Videos|World|Flamenco',
     3792            1726 => 'Music Videos|World|Tango',
     3793            1727 => 'Music Videos|World|Fado',
     3794            1728 => 'Music Videos|World|Iberia',
     3795            1729 => 'Music Videos|Russian',
     3796            1730 => 'Music Videos|Turkish',
     3797            1731 => 'Music Videos|Alternative|College Rock',
     3798            1732 => 'Music Videos|Alternative|Goth Rock',
     3799            1733 => 'Music Videos|Alternative|Grunge',
     3800            1734 => 'Music Videos|Alternative|Indie Rock',
     3801            1735 => 'Music Videos|Alternative|New Wave',
     3802            1736 => 'Music Videos|Alternative|Punk',
     3803            1737 => 'Music Videos|Blues|Acoustic Blues',
     3804            1738 => 'Music Videos|Blues|Chicago Blues',
     3805            1739 => 'Music Videos|Blues|Classic Blues',
     3806            1740 => 'Music Videos|Blues|Contemporary Blues',
     3807            1741 => 'Music Videos|Blues|Country Blues',
     3808            1742 => 'Music Videos|Blues|Delta Blues',
     3809            1743 => 'Music Videos|Blues|Electric Blues',
     3810            1744 => "Music Videos|Children's Music|Lullabies",
     3811            1745 => "Music Videos|Children's Music|Sing-Along",
     3812            1746 => "Music Videos|Children's Music|Stories",
     3813            1747 => 'Music Videos|Christian & Gospel|CCM',
     3814            1748 => 'Music Videos|Christian & Gospel|Christian Metal',
     3815            1749 => 'Music Videos|Christian & Gospel|Christian Pop',
     3816            1750 => 'Music Videos|Christian & Gospel|Christian Rap',
     3817            1751 => 'Music Videos|Christian & Gospel|Christian Rock',
     3818            1752 => 'Music Videos|Christian & Gospel|Classic Christian',
     3819            1753 => 'Music Videos|Christian & Gospel|Contemporary Gospel',
     3820            1754 => 'Music Videos|Christian & Gospel|Gospel',
     3821            1755 => 'Music Videos|Christian & Gospel|Praise & Worship',
     3822            1756 => 'Music Videos|Christian & Gospel|Southern Gospel',
     3823            1757 => 'Music Videos|Christian & Gospel|Traditional Gospel',
     3824            1758 => 'Music Videos|Classical|Avant-Garde',
     3825            1759 => 'Music Videos|Classical|Baroque Era',
     3826            1760 => 'Music Videos|Classical|Chamber Music',
     3827            1761 => 'Music Videos|Classical|Chant',
     3828            1762 => 'Music Videos|Classical|Choral',
     3829            1763 => 'Music Videos|Classical|Classical Crossover',
     3830            1764 => 'Music Videos|Classical|Early Music',
     3831            1765 => 'Music Videos|Classical|Impressionist',
     3832            1766 => 'Music Videos|Classical|Medieval Era',
     3833            1767 => 'Music Videos|Classical|Minimalism',
     3834            1768 => 'Music Videos|Classical|Modern Era',
     3835            1769 => 'Music Videos|Classical|Orchestral',
     3836            1770 => 'Music Videos|Classical|Renaissance',
     3837            1771 => 'Music Videos|Classical|Romantic Era',
     3838            1772 => 'Music Videos|Classical|Wedding Music',
     3839            1773 => 'Music Videos|Comedy|Novelty',
     3840            1774 => 'Music Videos|Comedy|Standup Comedy',
     3841            1775 => 'Music Videos|Country|Alternative Country',
     3842            1776 => 'Music Videos|Country|Americana',
     3843            1777 => 'Music Videos|Country|Bluegrass',
     3844            1778 => 'Music Videos|Country|Contemporary Bluegrass',
     3845            1779 => 'Music Videos|Country|Contemporary Country',
     3846            1780 => 'Music Videos|Country|Country Gospel',
     3847            1781 => 'Music Videos|Country|Honky Tonk',
     3848            1782 => 'Music Videos|Country|Outlaw Country',
     3849            1783 => 'Music Videos|Country|Traditional Bluegrass',
     3850            1784 => 'Music Videos|Country|Traditional Country',
     3851            1785 => 'Music Videos|Country|Urban Cowboy',
     3852            1786 => 'Music Videos|Dance|Breakbeat',
     3853            1787 => 'Music Videos|Dance|Exercise',
     3854            1788 => 'Music Videos|Dance|Garage',
     3855            1789 => 'Music Videos|Dance|Hardcore',
     3856            1790 => 'Music Videos|Dance|House',
     3857            1791 => "Music Videos|Dance|Jungle/Drum'n'bass",
     3858            1792 => 'Music Videos|Dance|Techno',
     3859            1793 => 'Music Videos|Dance|Trance',
     3860            1794 => 'Music Videos|Easy Listening|Lounge',
     3861            1795 => 'Music Videos|Easy Listening|Swing',
     3862            1796 => 'Music Videos|Electronic|Ambient',
     3863            1797 => 'Music Videos|Electronic|Downtempo',
     3864            1798 => 'Music Videos|Electronic|Electronica',
     3865            1799 => 'Music Videos|Electronic|IDM/Experimental',
     3866            1800 => 'Music Videos|Electronic|Industrial',
     3867            1801 => 'Music Videos|Hip-Hop/Rap|Alternative Rap',
     3868            1802 => 'Music Videos|Hip-Hop/Rap|Dirty South',
     3869            1803 => 'Music Videos|Hip-Hop/Rap|East Coast Rap',
     3870            1804 => 'Music Videos|Hip-Hop/Rap|Gangsta Rap',
     3871            1805 => 'Music Videos|Hip-Hop/Rap|Hardcore Rap',
     3872            1806 => 'Music Videos|Hip-Hop/Rap|Hip-Hop',
     3873            1807 => 'Music Videos|Hip-Hop/Rap|Latin Rap',
     3874            1808 => 'Music Videos|Hip-Hop/Rap|Old School Rap',
     3875            1809 => 'Music Videos|Hip-Hop/Rap|Rap',
     3876            1810 => 'Music Videos|Hip-Hop/Rap|Underground Rap',
     3877            1811 => 'Music Videos|Hip-Hop/Rap|West Coast Rap',
     3878            1812 => 'Music Videos|Holiday|Chanukah',
     3879            1813 => 'Music Videos|Holiday|Christmas',
     3880            1814 => "Music Videos|Holiday|Christmas: Children's",
     3881            1815 => 'Music Videos|Holiday|Christmas: Classic',
     3882            1816 => 'Music Videos|Holiday|Christmas: Classical',
     3883            1817 => 'Music Videos|Holiday|Christmas: Jazz',
     3884            1818 => 'Music Videos|Holiday|Christmas: Modern',
     3885            1819 => 'Music Videos|Holiday|Christmas: Pop',
     3886            1820 => 'Music Videos|Holiday|Christmas: R&B',
     3887            1821 => 'Music Videos|Holiday|Christmas: Religious',
     3888            1822 => 'Music Videos|Holiday|Christmas: Rock',
     3889            1823 => 'Music Videos|Holiday|Easter',
     3890            1824 => 'Music Videos|Holiday|Halloween',
     3891            1825 => 'Music Videos|Holiday|Thanksgiving',
     3892            1826 => 'Music Videos|Jazz|Avant-Garde Jazz',
     3893            1828 => 'Music Videos|Jazz|Bop',
     3894            1829 => 'Music Videos|Jazz|Contemporary Jazz',
     3895            1830 => 'Music Videos|Jazz|Cool Jazz',
     3896            1831 => 'Music Videos|Jazz|Crossover Jazz',
     3897            1832 => 'Music Videos|Jazz|Dixieland',
     3898            1833 => 'Music Videos|Jazz|Fusion',
     3899            1834 => 'Music Videos|Jazz|Hard Bop',
     3900            1835 => 'Music Videos|Jazz|Latin Jazz',
     3901            1836 => 'Music Videos|Jazz|Mainstream Jazz',
     3902            1837 => 'Music Videos|Jazz|Ragtime',
     3903            1838 => 'Music Videos|Jazz|Smooth Jazz',
     3904            1839 => 'Music Videos|Jazz|Trad Jazz',
     3905            1840 => 'Music Videos|Latin|Alternative & Rock in Spanish',
     3906            1841 => 'Music Videos|Latin|Baladas y Boleros',
     3907            1842 => 'Music Videos|Latin|Contemporary Latin',
     3908            1843 => 'Music Videos|Latin|Latin Jazz',
     3909            1844 => 'Music Videos|Latin|Latin Urban',
     3910            1845 => 'Music Videos|Latin|Pop in Spanish',
     3911            1846 => 'Music Videos|Latin|Raices',
     3912            1847 => 'Music Videos|Latin|Musica Mexicana', # (M&uacute;sica Mexicana)
     3913            1848 => 'Music Videos|Latin|Salsa y Tropical',
     3914            1849 => 'Music Videos|New Age|Healing',
     3915            1850 => 'Music Videos|New Age|Meditation',
     3916            1851 => 'Music Videos|New Age|Nature',
     3917            1852 => 'Music Videos|New Age|Relaxation',
     3918            1853 => 'Music Videos|New Age|Travel',
     3919            1854 => 'Music Videos|Pop|Adult Contemporary',
     3920            1855 => 'Music Videos|Pop|Britpop',
     3921            1856 => 'Music Videos|Pop|Pop/Rock',
     3922            1857 => 'Music Videos|Pop|Soft Rock',
     3923            1858 => 'Music Videos|Pop|Teen Pop',
     3924            1859 => 'Music Videos|R&B/Soul|Contemporary R&B',
     3925            1860 => 'Music Videos|R&B/Soul|Disco',
     3926            1861 => 'Music Videos|R&B/Soul|Doo Wop',
     3927            1862 => 'Music Videos|R&B/Soul|Funk',
     3928            1863 => 'Music Videos|R&B/Soul|Motown',
     3929            1864 => 'Music Videos|R&B/Soul|Neo-Soul',
     3930            1865 => 'Music Videos|R&B/Soul|Soul',
     3931            1866 => 'Music Videos|Reggae|Modern Dancehall',
     3932            1867 => 'Music Videos|Reggae|Dub',
     3933            1868 => 'Music Videos|Reggae|Roots Reggae',
     3934            1869 => 'Music Videos|Reggae|Ska',
     3935            1870 => 'Music Videos|Rock|Adult Alternative',
     3936            1871 => 'Music Videos|Rock|American Trad Rock',
     3937            1872 => 'Music Videos|Rock|Arena Rock',
     3938            1873 => 'Music Videos|Rock|Blues-Rock',
     3939            1874 => 'Music Videos|Rock|British Invasion',
     3940            1875 => 'Music Videos|Rock|Death Metal/Black Metal',
     3941            1876 => 'Music Videos|Rock|Glam Rock',
     3942            1877 => 'Music Videos|Rock|Hair Metal',
     3943            1878 => 'Music Videos|Rock|Hard Rock',
     3944            1879 => 'Music Videos|Rock|Jam Bands',
     3945            1880 => 'Music Videos|Rock|Prog-Rock/Art Rock',
     3946            1881 => 'Music Videos|Rock|Psychedelic',
     3947            1882 => 'Music Videos|Rock|Rock & Roll',
     3948            1883 => 'Music Videos|Rock|Rockabilly',
     3949            1884 => 'Music Videos|Rock|Roots Rock',
     3950            1885 => 'Music Videos|Rock|Singer/Songwriter',
     3951            1886 => 'Music Videos|Rock|Southern Rock',
     3952            1887 => 'Music Videos|Rock|Surf',
     3953            1888 => 'Music Videos|Rock|Tex-Mex',
     3954            1889 => 'Music Videos|Singer/Songwriter|Alternative Folk',
     3955            1890 => 'Music Videos|Singer/Songwriter|Contemporary Folk',
     3956            1891 => 'Music Videos|Singer/Songwriter|Contemporary Singer/Songwriter',
     3957            1892 => 'Music Videos|Singer/Songwriter|Folk-Rock',
     3958            1893 => 'Music Videos|Singer/Songwriter|New Acoustic',
     3959            1894 => 'Music Videos|Singer/Songwriter|Traditional Folk',
     3960            1895 => 'Music Videos|Soundtrack|Foreign Cinema',
     3961            1896 => 'Music Videos|Soundtrack|Musicals',
     3962            1897 => 'Music Videos|Soundtrack|Original Score',
     3963            1898 => 'Music Videos|Soundtrack|Soundtrack',
     3964            1899 => 'Music Videos|Soundtrack|TV Soundtrack',
     3965            1900 => 'Music Videos|Vocal|Standards',
     3966            1901 => 'Music Videos|Vocal|Traditional Pop',
     3967            1902 => 'Music Videos|Jazz|Vocal Jazz',
     3968            1903 => 'Music Videos|Vocal|Vocal Pop',
     3969            1904 => 'Music Videos|African',
     3970            1905 => 'Music Videos|African|Afro-Beat',
     3971            1906 => 'Music Videos|African|Afro-Pop',
     3972            1907 => 'Music Videos|World|Asia',
     3973            1908 => 'Music Videos|World|Australia',
     3974            1909 => 'Music Videos|World|Cajun',
     3975            1910 => 'Music Videos|World|Caribbean',
     3976            1911 => 'Music Videos|World|Celtic',
     3977            1912 => 'Music Videos|World|Celtic Folk',
     3978            1913 => 'Music Videos|World|Contemporary Celtic',
     3979            1914 => 'Music Videos|World|Europe',
     3980            1915 => 'Music Videos|World|France',
     3981            1916 => 'Music Videos|World|Hawaii',
     3982            1917 => 'Music Videos|World|Japan',
     3983            1918 => 'Music Videos|World|Klezmer',
     3984            1919 => 'Music Videos|World|North America',
     3985            1920 => 'Music Videos|World|Polka',
     3986            1921 => 'Music Videos|World|South Africa',
     3987            1922 => 'Music Videos|World|South America',
     3988            1923 => 'Music Videos|World|Traditional Celtic',
     3989            1924 => 'Music Videos|World|Worldbeat',
     3990            1925 => 'Music Videos|World|Zydeco',
     3991            1926 => 'Music Videos|Christian & Gospel',
     3992            1928 => 'Music Videos|Classical|Art Song',
     3993            1929 => 'Music Videos|Classical|Brass & Woodwinds',
     3994            1930 => 'Music Videos|Classical|Solo Instrumental',
     3995            1931 => 'Music Videos|Classical|Contemporary Era',
     3996            1932 => 'Music Videos|Classical|Oratorio',
     3997            1933 => 'Music Videos|Classical|Cantata',
     3998            1934 => 'Music Videos|Classical|Electronic',
     3999            1935 => 'Music Videos|Classical|Sacred',
     4000            1936 => 'Music Videos|Classical|Guitar',
     4001            1938 => 'Music Videos|Classical|Violin',
     4002            1939 => 'Music Videos|Classical|Cello',
     4003            1940 => 'Music Videos|Classical|Percussion',
     4004            1941 => 'Music Videos|Electronic|Dubstep',
     4005            1942 => 'Music Videos|Electronic|Bass',
     4006            1943 => 'Music Videos|Hip-Hop/Rap|UK Hip-Hop',
     4007            1944 => 'Music Videos|Reggae|Lovers Rock',
     4008            1945 => 'Music Videos|Alternative|EMO',
     4009            1946 => 'Music Videos|Alternative|Pop Punk',
     4010            1947 => 'Music Videos|Alternative|Indie Pop',
     4011            1948 => 'Music Videos|New Age|Yoga',
     4012            1949 => 'Music Videos|Pop|Tribute',
     4013            1950 => 'Music Videos|Pop|Shows',
     4014            1951 => 'Music Videos|Cuban',
     4015            1952 => 'Music Videos|Cuban|Mambo',
     4016            1953 => 'Music Videos|Cuban|Chachacha',
     4017            1954 => 'Music Videos|Cuban|Guajira',
     4018            1955 => 'Music Videos|Cuban|Son',
     4019            1956 => 'Music Videos|Cuban|Bolero',
     4020            1957 => 'Music Videos|Cuban|Guaracha',
     4021            1958 => 'Music Videos|Cuban|Timba',
     4022            1959 => 'Music Videos|Soundtrack|Video Game',
     4023            1960 => 'Music Videos|Indian|Regional Indian|Punjabi|Punjabi Pop',
     4024            1961 => 'Music Videos|Indian|Regional Indian|Bengali|Rabindra Sangeet',
     4025            1962 => 'Music Videos|Indian|Regional Indian|Malayalam',
     4026            1963 => 'Music Videos|Indian|Regional Indian|Kannada',
     4027            1964 => 'Music Videos|Indian|Regional Indian|Marathi',
     4028            1965 => 'Music Videos|Indian|Regional Indian|Gujarati',
     4029            1966 => 'Music Videos|Indian|Regional Indian|Assamese',
     4030            1967 => 'Music Videos|Indian|Regional Indian|Bhojpuri',
     4031            1968 => 'Music Videos|Indian|Regional Indian|Haryanvi',
     4032            1969 => 'Music Videos|Indian|Regional Indian|Odia',
     4033            1970 => 'Music Videos|Indian|Regional Indian|Rajasthani',
     4034            1971 => 'Music Videos|Indian|Regional Indian|Urdu',
     4035            1972 => 'Music Videos|Indian|Regional Indian|Punjabi',
     4036            1973 => 'Music Videos|Indian|Regional Indian|Bengali',
     4037            1974 => 'Music Videos|Indian|Indian Classical|Carnatic Classical',
     4038            1975 => 'Music Videos|Indian|Indian Classical|Hindustani Classical',
     4039            1976 => 'Music Videos|African|Afro House',
     4040            1977 => 'Music Videos|African|Afro Soul',
     4041            1978 => 'Music Videos|African|Afrobeats',
     4042            1979 => 'Music Videos|African|Benga',
     4043            1980 => 'Music Videos|African|Bongo-Flava',
     4044            1981 => 'Music Videos|African|Coupe-Decale',
     4045            1982 => 'Music Videos|African|Gqom',
     4046            1983 => 'Music Videos|African|Highlife',
     4047            1984 => 'Music Videos|African|Kuduro',
     4048            1985 => 'Music Videos|African|Kizomba',
     4049            1986 => 'Music Videos|African|Kwaito',
     4050            1987 => 'Music Videos|African|Mbalax',
     4051            1988 => 'Music Videos|African|Ndombolo',
     4052            1989 => 'Music Videos|African|Shangaan Electro',
     4053            1990 => 'Music Videos|African|Soukous',
     4054            1991 => 'Music Videos|African|Taarab',
     4055            1992 => 'Music Videos|African|Zouglou',
     4056            1993 => 'Music Videos|Turkish|Ozgun',
     4057            1994 => 'Music Videos|Turkish|Fantezi',
     4058            1995 => 'Music Videos|Turkish|Religious',
     4059            1996 => 'Music Videos|Pop|Turkish Pop',
     4060            1997 => 'Music Videos|Rock|Turkish Rock',
     4061            1998 => 'Music Videos|Alternative|Turkish Alternative',
     4062            1999 => 'Music Videos|Hip-Hop/Rap|Turkish Hip-Hop/Rap',
     4063            2000 => 'Music Videos|African|Maskandi',
     4064            2001 => 'Music Videos|Russian|Russian Romance',
     4065            2002 => 'Music Videos|Russian|Russian Bard',
     4066            2003 => 'Music Videos|Russian|Russian Pop',
     4067            2004 => 'Music Videos|Russian|Russian Rock',
     4068            2005 => 'Music Videos|Russian|Russian Hip-Hop',
     4069            2006 => 'Music Videos|Arabic|Levant',
     4070            2007 => 'Music Videos|Arabic|Levant|Dabke',
     4071            2008 => 'Music Videos|Arabic|Maghreb Rai',
     4072            2009 => 'Music Videos|Arabic|Khaleeji|Khaleeji Jalsat',
     4073            2010 => 'Music Videos|Arabic|Khaleeji|Khaleeji Shailat',
     4074            2011 => 'Music Videos|Tarab',
     4075            2012 => 'Music Videos|Tarab|Iraqi Tarab',
     4076            2013 => 'Music Videos|Tarab|Egyptian Tarab',
     4077            2014 => 'Music Videos|Tarab|Khaleeji Tarab',
     4078            2015 => 'Music Videos|Pop|Levant Pop',
     4079            2016 => 'Music Videos|Pop|Iraqi Pop',
     4080            2017 => 'Music Videos|Pop|Egyptian Pop',
     4081            2018 => 'Music Videos|Pop|Maghreb Pop',
     4082            2019 => 'Music Videos|Pop|Khaleeji Pop',
     4083            2020 => 'Music Videos|Hip-Hop/Rap|Levant Hip-Hop',
     4084            2021 => 'Music Videos|Hip-Hop/Rap|Egyptian Hip-Hop',
     4085            2022 => 'Music Videos|Hip-Hop/Rap|Maghreb Hip-Hop',
     4086            2023 => 'Music Videos|Hip-Hop/Rap|Khaleeji Hip-Hop',
     4087            2024 => 'Music Videos|Alternative|Indie Levant',
     4088            2025 => 'Music Videos|Alternative|Indie Egyptian',
     4089            2026 => 'Music Videos|Alternative|Indie Maghreb',
     4090            2027 => 'Music Videos|Electronic|Levant Electronic',
     4091            2028 => "Music Videos|Electronic|Electro-Cha'abi",
     4092            2029 => 'Music Videos|Electronic|Maghreb Electronic',
     4093            2030 => 'Music Videos|Folk|Iraqi Folk',
     4094            2031 => 'Music Videos|Folk|Khaleeji Folk',
     4095            2032 => 'Music Videos|Dance|Maghreb Dance',
     4096            4000 => 'TV Shows|Comedy',
     4097            4001 => 'TV Shows|Drama',
     4098            4002 => 'TV Shows|Animation',
     4099            4003 => 'TV Shows|Action & Adventure',
     4100            4004 => 'TV Shows|Classics',
     4101            4005 => 'TV Shows|Kids & Family',
     4102            4006 => 'TV Shows|Nonfiction',
     4103            4007 => 'TV Shows|Reality TV',
     4104            4008 => 'TV Shows|Sci-Fi & Fantasy',
     4105            4009 => 'TV Shows|Sports',
     4106            4010 => 'TV Shows|Teens',
     4107            4011 => 'TV Shows|Latino TV',
     4108            4401 => 'Movies|Action & Adventure',
     4109            4402 => 'Movies|Anime',
     4110            4403 => 'Movies|Classics',
     4111            4404 => 'Movies|Comedy',
     4112            4405 => 'Movies|Documentary',
     4113            4406 => 'Movies|Drama',
     4114            4407 => 'Movies|Foreign',
     4115            4408 => 'Movies|Horror',
     4116            4409 => 'Movies|Independent',
     4117            4410 => 'Movies|Kids & Family',
     4118            4411 => 'Movies|Musicals',
     4119            4412 => 'Movies|Romance',
     4120            4413 => 'Movies|Sci-Fi & Fantasy',
     4121            4414 => 'Movies|Short Films',
     4122            4415 => 'Movies|Special Interest',
     4123            4416 => 'Movies|Thriller',
     4124            4417 => 'Movies|Sports',
     4125            4418 => 'Movies|Western',
     4126            4419 => 'Movies|Urban',
     4127            4420 => 'Movies|Holiday',
     4128            4421 => 'Movies|Made for TV',
     4129            4422 => 'Movies|Concert Films',
     4130            4423 => 'Movies|Music Documentaries',
     4131            4424 => 'Movies|Music Feature Films',
     4132            4425 => 'Movies|Japanese Cinema',
     4133            4426 => 'Movies|Jidaigeki',
     4134            4427 => 'Movies|Tokusatsu',
     4135            4428 => 'Movies|Korean Cinema',
     4136            4429 => 'Movies|Russian',
     4137            4430 => 'Movies|Turkish',
     4138            4431 => 'Movies|Bollywood',
     4139            4432 => 'Movies|Regional Indian',
     4140            4433 => 'Movies|Middle Eastern',
     4141            4434 => 'Movies|African',
     4142            6000 => 'App Store|Business',
     4143            6001 => 'App Store|Weather',
     4144            6002 => 'App Store|Utilities',
     4145            6003 => 'App Store|Travel',
     4146            6004 => 'App Store|Sports',
     4147            6005 => 'App Store|Social Networking',
     4148            6006 => 'App Store|Reference',
     4149            6007 => 'App Store|Productivity',
     4150            6008 => 'App Store|Photo & Video',
     4151            6009 => 'App Store|News',
     4152            6010 => 'App Store|Navigation',
     4153            6011 => 'App Store|Music',
     4154            6012 => 'App Store|Lifestyle',
     4155            6013 => 'App Store|Health & Fitness',
     4156            6014 => 'App Store|Games',
     4157            6015 => 'App Store|Finance',
     4158            6016 => 'App Store|Entertainment',
     4159            6017 => 'App Store|Education',
     4160            6018 => 'App Store|Books',
     4161            6020 => 'App Store|Medical',
     4162            6021 => 'App Store|Magazines & Newspapers',
     4163            6022 => 'App Store|Catalogs',
     4164            6023 => 'App Store|Food & Drink',
     4165            6024 => 'App Store|Shopping',
     4166            6025 => 'App Store|Stickers',
     4167            6026 => 'App Store|Developer Tools',
     4168            6027 => 'App Store|Graphics & Design',
     4169            7001 => 'App Store|Games|Action',
     4170            7002 => 'App Store|Games|Adventure',
     4171            7003 => 'App Store|Games|Casual',
     4172            7004 => 'App Store|Games|Board',
     4173            7005 => 'App Store|Games|Card',
     4174            7006 => 'App Store|Games|Casino',
     4175            7007 => 'App Store|Games|Dice',
     4176            7008 => 'App Store|Games|Educational',
     4177            7009 => 'App Store|Games|Family',
     4178            7011 => 'App Store|Games|Music',
     4179            7012 => 'App Store|Games|Puzzle',
     4180            7013 => 'App Store|Games|Racing',
     4181            7014 => 'App Store|Games|Role Playing',
     4182            7015 => 'App Store|Games|Simulation',
     4183            7016 => 'App Store|Games|Sports',
     4184            7017 => 'App Store|Games|Strategy',
     4185            7018 => 'App Store|Games|Trivia',
     4186            7019 => 'App Store|Games|Word',
     4187            8001 => 'Tones|Ringtones|Alternative',
     4188            8002 => 'Tones|Ringtones|Blues',
     4189            8003 => "Tones|Ringtones|Children's Music",
     4190            8004 => 'Tones|Ringtones|Classical',
     4191            8005 => 'Tones|Ringtones|Comedy',
     4192            8006 => 'Tones|Ringtones|Country',
     4193            8007 => 'Tones|Ringtones|Dance',
     4194            8008 => 'Tones|Ringtones|Electronic',
     4195            8009 => 'Tones|Ringtones|Enka',
     4196            8010 => 'Tones|Ringtones|French Pop',
     4197            8011 => 'Tones|Ringtones|German Folk',
     4198            8012 => 'Tones|Ringtones|German Pop',
     4199            8013 => 'Tones|Ringtones|Hip-Hop/Rap',
     4200            8014 => 'Tones|Ringtones|Holiday',
     4201            8015 => 'Tones|Ringtones|Inspirational',
     4202            8016 => 'Tones|Ringtones|J-Pop',
     4203            8017 => 'Tones|Ringtones|Jazz',
     4204            8018 => 'Tones|Ringtones|Kayokyoku',
     4205            8019 => 'Tones|Ringtones|Latin',
     4206            8020 => 'Tones|Ringtones|New Age',
     4207            8021 => 'Tones|Ringtones|Classical|Opera',
     4208            8022 => 'Tones|Ringtones|Pop',
     4209            8023 => 'Tones|Ringtones|R&B/Soul',
     4210            8024 => 'Tones|Ringtones|Reggae',
     4211            8025 => 'Tones|Ringtones|Rock',
     4212            8026 => 'Tones|Ringtones|Singer/Songwriter',
     4213            8027 => 'Tones|Ringtones|Soundtrack',
     4214            8028 => 'Tones|Ringtones|Spoken Word',
     4215            8029 => 'Tones|Ringtones|Vocal',
     4216            8030 => 'Tones|Ringtones|World',
     4217            8050 => 'Tones|Alert Tones|Sound Effects',
     4218            8051 => 'Tones|Alert Tones|Dialogue',
     4219            8052 => 'Tones|Alert Tones|Music',
     4220            8053 => 'Tones|Ringtones',
     4221            8054 => 'Tones|Alert Tones',
     4222            8055 => 'Tones|Ringtones|Alternative|Chinese Alt',
     4223            8056 => 'Tones|Ringtones|Alternative|College Rock',
     4224            8057 => 'Tones|Ringtones|Alternative|Goth Rock',
     4225            8058 => 'Tones|Ringtones|Alternative|Grunge',
     4226            8059 => 'Tones|Ringtones|Alternative|Indie Rock',
     4227            8060 => 'Tones|Ringtones|Alternative|Korean Indie',
     4228            8061 => 'Tones|Ringtones|Alternative|New Wave',
     4229            8062 => 'Tones|Ringtones|Alternative|Punk',
     4230            8063 => 'Tones|Ringtones|Anime',
     4231            8064 => 'Tones|Ringtones|Arabic',
     4232            8065 => 'Tones|Ringtones|Arabic|Arabic Pop',
     4233            8066 => 'Tones|Ringtones|Arabic|Islamic',
     4234            8067 => 'Tones|Ringtones|Arabic|Khaleeji',
     4235            8068 => 'Tones|Ringtones|Arabic|North African',
     4236            8069 => 'Tones|Ringtones|Blues|Acoustic Blues',
     4237            8070 => 'Tones|Ringtones|Blues|Chicago Blues',
     4238            8071 => 'Tones|Ringtones|Blues|Classic Blues',
     4239            8072 => 'Tones|Ringtones|Blues|Contemporary Blues',
     4240            8073 => 'Tones|Ringtones|Blues|Country Blues',
     4241            8074 => 'Tones|Ringtones|Blues|Delta Blues',
     4242            8075 => 'Tones|Ringtones|Blues|Electric Blues',
     4243            8076 => 'Tones|Ringtones|Brazilian',
     4244            8077 => 'Tones|Ringtones|Brazilian|Axe', # (Ax&eacute;)
     4245            8078 => 'Tones|Ringtones|Brazilian|Baile Funk',
     4246            8079 => 'Tones|Ringtones|Brazilian|Bossa Nova',
     4247            8080 => 'Tones|Ringtones|Brazilian|Choro',
     4248            8081 => 'Tones|Ringtones|Brazilian|Forro', # (Forr&oacute;)
     4249            8082 => 'Tones|Ringtones|Brazilian|Frevo',
     4250            8083 => 'Tones|Ringtones|Brazilian|MPB',
     4251            8084 => 'Tones|Ringtones|Brazilian|Pagode',
     4252            8085 => 'Tones|Ringtones|Brazilian|Samba',
     4253            8086 => 'Tones|Ringtones|Brazilian|Sertanejo',
     4254            8087 => "Tones|Ringtones|Children's Music|Lullabies",
     4255            8088 => "Tones|Ringtones|Children's Music|Sing-Along",
     4256            8089 => "Tones|Ringtones|Children's Music|Stories",
     4257            8090 => 'Tones|Ringtones|Chinese',
     4258            8091 => 'Tones|Ringtones|Chinese|Chinese Classical',
     4259            8092 => 'Tones|Ringtones|Chinese|Chinese Flute',
     4260            8093 => 'Tones|Ringtones|Chinese|Chinese Opera',
     4261            8094 => 'Tones|Ringtones|Chinese|Chinese Orchestral',
     4262            8095 => 'Tones|Ringtones|Chinese|Chinese Regional Folk',
     4263            8096 => 'Tones|Ringtones|Chinese|Chinese Strings',
     4264            8097 => 'Tones|Ringtones|Chinese|Taiwanese Folk',
     4265            8098 => 'Tones|Ringtones|Chinese|Tibetan Native Music',
     4266            8099 => 'Tones|Ringtones|Christian & Gospel',
     4267            8100 => 'Tones|Ringtones|Christian & Gospel|CCM',
     4268            8101 => 'Tones|Ringtones|Christian & Gospel|Christian Metal',
     4269            8102 => 'Tones|Ringtones|Christian & Gospel|Christian Pop',
     4270            8103 => 'Tones|Ringtones|Christian & Gospel|Christian Rap',
     4271            8104 => 'Tones|Ringtones|Christian & Gospel|Christian Rock',
     4272            8105 => 'Tones|Ringtones|Christian & Gospel|Classic Christian',
     4273            8106 => 'Tones|Ringtones|Christian & Gospel|Contemporary Gospel',
     4274            8107 => 'Tones|Ringtones|Christian & Gospel|Gospel',
     4275            8108 => 'Tones|Ringtones|Christian & Gospel|Praise & Worship',
     4276            8109 => 'Tones|Ringtones|Christian & Gospel|Southern Gospel',
     4277            8110 => 'Tones|Ringtones|Christian & Gospel|Traditional Gospel',
     4278            8111 => 'Tones|Ringtones|Classical|Avant-Garde',
     4279            8112 => 'Tones|Ringtones|Classical|Baroque Era',
     4280            8113 => 'Tones|Ringtones|Classical|Chamber Music',
     4281            8114 => 'Tones|Ringtones|Classical|Chant',
     4282            8115 => 'Tones|Ringtones|Classical|Choral',
     4283            8116 => 'Tones|Ringtones|Classical|Classical Crossover',
     4284            8117 => 'Tones|Ringtones|Classical|Early Music',
     4285            8118 => 'Tones|Ringtones|Classical|High Classical',
     4286            8119 => 'Tones|Ringtones|Classical|Impressionist',
     4287            8120 => 'Tones|Ringtones|Classical|Medieval Era',
     4288            8121 => 'Tones|Ringtones|Classical|Minimalism',
     4289            8122 => 'Tones|Ringtones|Classical|Modern Era',
     4290            8123 => 'Tones|Ringtones|Classical|Orchestral',
     4291            8124 => 'Tones|Ringtones|Classical|Renaissance',
     4292            8125 => 'Tones|Ringtones|Classical|Romantic Era',
     4293            8126 => 'Tones|Ringtones|Classical|Wedding Music',
     4294            8127 => 'Tones|Ringtones|Comedy|Novelty',
     4295            8128 => 'Tones|Ringtones|Comedy|Standup Comedy',
     4296            8129 => 'Tones|Ringtones|Country|Alternative Country',
     4297            8130 => 'Tones|Ringtones|Country|Americana',
     4298            8131 => 'Tones|Ringtones|Country|Bluegrass',
     4299            8132 => 'Tones|Ringtones|Country|Contemporary Bluegrass',
     4300            8133 => 'Tones|Ringtones|Country|Contemporary Country',
     4301            8134 => 'Tones|Ringtones|Country|Country Gospel',
     4302            8135 => 'Tones|Ringtones|Country|Honky Tonk',
     4303            8136 => 'Tones|Ringtones|Country|Outlaw Country',
     4304            8137 => 'Tones|Ringtones|Country|Thai Country',
     4305            8138 => 'Tones|Ringtones|Country|Traditional Bluegrass',
     4306            8139 => 'Tones|Ringtones|Country|Traditional Country',
     4307            8140 => 'Tones|Ringtones|Country|Urban Cowboy',
     4308            8141 => 'Tones|Ringtones|Dance|Breakbeat',
     4309            8142 => 'Tones|Ringtones|Dance|Exercise',
     4310            8143 => 'Tones|Ringtones|Dance|Garage',
     4311            8144 => 'Tones|Ringtones|Dance|Hardcore',
     4312            8145 => 'Tones|Ringtones|Dance|House',
     4313            8146 => "Tones|Ringtones|Dance|Jungle/Drum'n'bass",
     4314            8147 => 'Tones|Ringtones|Dance|Techno',
     4315            8148 => 'Tones|Ringtones|Dance|Trance',
     4316            8149 => 'Tones|Ringtones|Disney',
     4317            8150 => 'Tones|Ringtones|Easy Listening',
     4318            8151 => 'Tones|Ringtones|Easy Listening|Lounge',
     4319            8152 => 'Tones|Ringtones|Easy Listening|Swing',
     4320            8153 => 'Tones|Ringtones|Electronic|Ambient',
     4321            8154 => 'Tones|Ringtones|Electronic|Downtempo',
     4322            8155 => 'Tones|Ringtones|Electronic|Electronica',
     4323            8156 => 'Tones|Ringtones|Electronic|IDM/Experimental',
     4324            8157 => 'Tones|Ringtones|Electronic|Industrial',
     4325            8158 => 'Tones|Ringtones|Fitness & Workout',
     4326            8159 => 'Tones|Ringtones|Folk',
     4327            8160 => 'Tones|Ringtones|Hip-Hop/Rap|Alternative Rap',
     4328            8161 => 'Tones|Ringtones|Hip-Hop/Rap|Chinese Hip-Hop',
     4329            8162 => 'Tones|Ringtones|Hip-Hop/Rap|Dirty South',
     4330            8163 => 'Tones|Ringtones|Hip-Hop/Rap|East Coast Rap',
     4331            8164 => 'Tones|Ringtones|Hip-Hop/Rap|Gangsta Rap',
     4332            8165 => 'Tones|Ringtones|Hip-Hop/Rap|Hardcore Rap',
     4333            8166 => 'Tones|Ringtones|Hip-Hop/Rap|Hip-Hop',
     4334            8167 => 'Tones|Ringtones|Hip-Hop/Rap|Korean Hip-Hop',
     4335            8168 => 'Tones|Ringtones|Hip-Hop/Rap|Latin Rap',
     4336            8169 => 'Tones|Ringtones|Hip-Hop/Rap|Old School Rap',
     4337            8170 => 'Tones|Ringtones|Hip-Hop/Rap|Rap',
     4338            8171 => 'Tones|Ringtones|Hip-Hop/Rap|Underground Rap',
     4339            8172 => 'Tones|Ringtones|Hip-Hop/Rap|West Coast Rap',
     4340            8173 => 'Tones|Ringtones|Holiday|Chanukah',
     4341            8174 => 'Tones|Ringtones|Holiday|Christmas',
     4342            8175 => "Tones|Ringtones|Holiday|Christmas: Children's",
     4343            8176 => 'Tones|Ringtones|Holiday|Christmas: Classic',
     4344            8177 => 'Tones|Ringtones|Holiday|Christmas: Classical',
     4345            8178 => 'Tones|Ringtones|Holiday|Christmas: Jazz',
     4346            8179 => 'Tones|Ringtones|Holiday|Christmas: Modern',
     4347            8180 => 'Tones|Ringtones|Holiday|Christmas: Pop',
     4348            8181 => 'Tones|Ringtones|Holiday|Christmas: R&B',
     4349            8182 => 'Tones|Ringtones|Holiday|Christmas: Religious',
     4350            8183 => 'Tones|Ringtones|Holiday|Christmas: Rock',
     4351            8184 => 'Tones|Ringtones|Holiday|Easter',
     4352            8185 => 'Tones|Ringtones|Holiday|Halloween',
     4353            8186 => 'Tones|Ringtones|Holiday|Thanksgiving',
     4354            8187 => 'Tones|Ringtones|Indian',
     4355            8188 => 'Tones|Ringtones|Indian|Bollywood',
     4356            8189 => 'Tones|Ringtones|Indian|Devotional & Spiritual',
     4357            8190 => 'Tones|Ringtones|Indian|Ghazals',
     4358            8191 => 'Tones|Ringtones|Indian|Indian Classical',
     4359            8192 => 'Tones|Ringtones|Indian|Indian Folk',
     4360            8193 => 'Tones|Ringtones|Indian|Indian Pop',
     4361            8194 => 'Tones|Ringtones|Indian|Regional Indian',
     4362            8195 => 'Tones|Ringtones|Indian|Sufi',
     4363            8196 => 'Tones|Ringtones|Indian|Regional Indian|Tamil',
     4364            8197 => 'Tones|Ringtones|Indian|Regional Indian|Telugu',
     4365            8198 => 'Tones|Ringtones|Instrumental',
     4366            8199 => 'Tones|Ringtones|Jazz|Avant-Garde Jazz',
     4367            8201 => 'Tones|Ringtones|Jazz|Big Band',
     4368            8202 => 'Tones|Ringtones|Jazz|Bop',
     4369            8203 => 'Tones|Ringtones|Jazz|Contemporary Jazz',
     4370            8204 => 'Tones|Ringtones|Jazz|Cool Jazz',
     4371            8205 => 'Tones|Ringtones|Jazz|Crossover Jazz',
     4372            8206 => 'Tones|Ringtones|Jazz|Dixieland',
     4373            8207 => 'Tones|Ringtones|Jazz|Fusion',
     4374            8208 => 'Tones|Ringtones|Jazz|Hard Bop',
     4375            8209 => 'Tones|Ringtones|Jazz|Latin Jazz',
     4376            8210 => 'Tones|Ringtones|Jazz|Mainstream Jazz',
     4377            8211 => 'Tones|Ringtones|Jazz|Ragtime',
     4378            8212 => 'Tones|Ringtones|Jazz|Smooth Jazz',
     4379            8213 => 'Tones|Ringtones|Jazz|Trad Jazz',
     4380            8214 => 'Tones|Ringtones|Pop|K-Pop',
     4381            8215 => 'Tones|Ringtones|Karaoke',
     4382            8216 => 'Tones|Ringtones|Korean',
     4383            8217 => 'Tones|Ringtones|Korean|Korean Classical',
     4384            8218 => 'Tones|Ringtones|Korean|Korean Trad Instrumental',
     4385            8219 => 'Tones|Ringtones|Korean|Korean Trad Song',
     4386            8220 => 'Tones|Ringtones|Korean|Korean Trad Theater',
     4387            8221 => 'Tones|Ringtones|Latin|Alternative & Rock in Spanish',
     4388            8222 => 'Tones|Ringtones|Latin|Baladas y Boleros',
     4389            8223 => 'Tones|Ringtones|Latin|Contemporary Latin',
     4390            8224 => 'Tones|Ringtones|Latin|Latin Jazz',
     4391            8225 => 'Tones|Ringtones|Latin|Latin Urban',
     4392            8226 => 'Tones|Ringtones|Latin|Pop in Spanish',
     4393            8227 => 'Tones|Ringtones|Latin|Raices',
     4394            8228 => 'Tones|Ringtones|Latin|Musica Mexicana', # (M&uacute;sica Mexicana)
     4395            8229 => 'Tones|Ringtones|Latin|Salsa y Tropical',
     4396            8230 => 'Tones|Ringtones|Marching Bands',
     4397            8231 => 'Tones|Ringtones|New Age|Healing',
     4398            8232 => 'Tones|Ringtones|New Age|Meditation',
     4399            8233 => 'Tones|Ringtones|New Age|Nature',
     4400            8234 => 'Tones|Ringtones|New Age|Relaxation',
     4401            8235 => 'Tones|Ringtones|New Age|Travel',
     4402            8236 => 'Tones|Ringtones|Orchestral',
     4403            8237 => 'Tones|Ringtones|Pop|Adult Contemporary',
     4404            8238 => 'Tones|Ringtones|Pop|Britpop',
     4405            8239 => 'Tones|Ringtones|Pop|C-Pop',
     4406            8240 => 'Tones|Ringtones|Pop|Cantopop/HK-Pop',
     4407            8241 => 'Tones|Ringtones|Pop|Indo Pop',
     4408            8242 => 'Tones|Ringtones|Pop|Korean Folk-Pop',
     4409            8243 => 'Tones|Ringtones|Pop|Malaysian Pop',
     4410            8244 => 'Tones|Ringtones|Pop|Mandopop',
     4411            8245 => 'Tones|Ringtones|Pop|Manilla Sound',
     4412            8246 => 'Tones|Ringtones|Pop|Oldies',
     4413            8247 => 'Tones|Ringtones|Pop|Original Pilipino Music',
     4414            8248 => 'Tones|Ringtones|Pop|Pinoy Pop',
     4415            8249 => 'Tones|Ringtones|Pop|Pop/Rock',
     4416            8250 => 'Tones|Ringtones|Pop|Soft Rock',
     4417            8251 => 'Tones|Ringtones|Pop|Tai-Pop',
     4418            8252 => 'Tones|Ringtones|Pop|Teen Pop',
     4419            8253 => 'Tones|Ringtones|Pop|Thai Pop',
     4420            8254 => 'Tones|Ringtones|R&B/Soul|Contemporary R&B',
     4421            8255 => 'Tones|Ringtones|R&B/Soul|Disco',
     4422            8256 => 'Tones|Ringtones|R&B/Soul|Doo Wop',
     4423            8257 => 'Tones|Ringtones|R&B/Soul|Funk',
     4424            8258 => 'Tones|Ringtones|R&B/Soul|Motown',
     4425            8259 => 'Tones|Ringtones|R&B/Soul|Neo-Soul',
     4426            8260 => 'Tones|Ringtones|R&B/Soul|Soul',
     4427            8261 => 'Tones|Ringtones|Reggae|Modern Dancehall',
     4428            8262 => 'Tones|Ringtones|Reggae|Dub',
     4429            8263 => 'Tones|Ringtones|Reggae|Roots Reggae',
     4430            8264 => 'Tones|Ringtones|Reggae|Ska',
     4431            8265 => 'Tones|Ringtones|Rock|Adult Alternative',
     4432            8266 => 'Tones|Ringtones|Rock|American Trad Rock',
     4433            8267 => 'Tones|Ringtones|Rock|Arena Rock',
     4434            8268 => 'Tones|Ringtones|Rock|Blues-Rock',
     4435            8269 => 'Tones|Ringtones|Rock|British Invasion',
     4436            8270 => 'Tones|Ringtones|Rock|Chinese Rock',
     4437            8271 => 'Tones|Ringtones|Rock|Death Metal/Black Metal',
     4438            8272 => 'Tones|Ringtones|Rock|Glam Rock',
     4439            8273 => 'Tones|Ringtones|Rock|Hair Metal',
     4440            8274 => 'Tones|Ringtones|Rock|Hard Rock',
     4441            8275 => 'Tones|Ringtones|Rock|Metal',
     4442            8276 => 'Tones|Ringtones|Rock|Jam Bands',
     4443            8277 => 'Tones|Ringtones|Rock|Korean Rock',
     4444            8278 => 'Tones|Ringtones|Rock|Prog-Rock/Art Rock',
     4445            8279 => 'Tones|Ringtones|Rock|Psychedelic',
     4446            8280 => 'Tones|Ringtones|Rock|Rock & Roll',
     4447            8281 => 'Tones|Ringtones|Rock|Rockabilly',
     4448            8282 => 'Tones|Ringtones|Rock|Roots Rock',
     4449            8283 => 'Tones|Ringtones|Rock|Singer/Songwriter',
     4450            8284 => 'Tones|Ringtones|Rock|Southern Rock',
     4451            8285 => 'Tones|Ringtones|Rock|Surf',
     4452            8286 => 'Tones|Ringtones|Rock|Tex-Mex',
     4453            8287 => 'Tones|Ringtones|Singer/Songwriter|Alternative Folk',
     4454            8288 => 'Tones|Ringtones|Singer/Songwriter|Contemporary Folk',
     4455            8289 => 'Tones|Ringtones|Singer/Songwriter|Contemporary Singer/Songwriter',
     4456            8290 => 'Tones|Ringtones|Singer/Songwriter|Folk-Rock',
     4457            8291 => 'Tones|Ringtones|Singer/Songwriter|New Acoustic',
     4458            8292 => 'Tones|Ringtones|Singer/Songwriter|Traditional Folk',
     4459            8293 => 'Tones|Ringtones|Soundtrack|Foreign Cinema',
     4460            8294 => 'Tones|Ringtones|Soundtrack|Musicals',
     4461            8295 => 'Tones|Ringtones|Soundtrack|Original Score',
     4462            8296 => 'Tones|Ringtones|Soundtrack|Sound Effects',
     4463            8297 => 'Tones|Ringtones|Soundtrack|Soundtrack',
     4464            8298 => 'Tones|Ringtones|Soundtrack|TV Soundtrack',
     4465            8299 => 'Tones|Ringtones|Vocal|Standards',
     4466            8300 => 'Tones|Ringtones|Vocal|Traditional Pop',
     4467            8301 => 'Tones|Ringtones|Vocal|Trot',
     4468            8302 => 'Tones|Ringtones|Jazz|Vocal Jazz',
     4469            8303 => 'Tones|Ringtones|Vocal|Vocal Pop',
     4470            8304 => 'Tones|Ringtones|African',
     4471            8305 => 'Tones|Ringtones|African|Afrikaans',
     4472            8306 => 'Tones|Ringtones|African|Afro-Beat',
     4473            8307 => 'Tones|Ringtones|African|Afro-Pop',
     4474            8308 => 'Tones|Ringtones|Turkish|Arabesque',
     4475            8309 => 'Tones|Ringtones|World|Asia',
     4476            8310 => 'Tones|Ringtones|World|Australia',
     4477            8311 => 'Tones|Ringtones|World|Cajun',
     4478            8312 => 'Tones|Ringtones|World|Calypso',
     4479            8313 => 'Tones|Ringtones|World|Caribbean',
     4480            8314 => 'Tones|Ringtones|World|Celtic',
     4481            8315 => 'Tones|Ringtones|World|Celtic Folk',
     4482            8316 => 'Tones|Ringtones|World|Contemporary Celtic',
     4483            8317 => 'Tones|Ringtones|World|Dangdut',
     4484            8318 => 'Tones|Ringtones|World|Dini',
     4485            8319 => 'Tones|Ringtones|World|Europe',
     4486            8320 => 'Tones|Ringtones|World|Fado',
     4487            8321 => 'Tones|Ringtones|World|Farsi',
     4488            8322 => 'Tones|Ringtones|World|Flamenco',
     4489            8323 => 'Tones|Ringtones|World|France',
     4490            8324 => 'Tones|Ringtones|Turkish|Halk',
     4491            8325 => 'Tones|Ringtones|World|Hawaii',
     4492            8326 => 'Tones|Ringtones|World|Iberia',
     4493            8327 => 'Tones|Ringtones|World|Indonesian Religious',
     4494            8328 => 'Tones|Ringtones|World|Israeli',
     4495            8329 => 'Tones|Ringtones|World|Japan',
     4496            8330 => 'Tones|Ringtones|World|Klezmer',
     4497            8331 => 'Tones|Ringtones|World|North America',
     4498            8332 => 'Tones|Ringtones|World|Polka',
     4499            8333 => 'Tones|Ringtones|Russian',
     4500            8334 => 'Tones|Ringtones|Russian|Russian Chanson',
     4501            8335 => 'Tones|Ringtones|Turkish|Sanat',
     4502            8336 => 'Tones|Ringtones|World|Soca',
     4503            8337 => 'Tones|Ringtones|World|South Africa',
     4504            8338 => 'Tones|Ringtones|World|South America',
     4505            8339 => 'Tones|Ringtones|World|Tango',
     4506            8340 => 'Tones|Ringtones|World|Traditional Celtic',
     4507            8341 => 'Tones|Ringtones|Turkish',
     4508            8342 => 'Tones|Ringtones|World|Worldbeat',
     4509            8343 => 'Tones|Ringtones|World|Zydeco',
     4510            8345 => 'Tones|Ringtones|Classical|Art Song',
     4511            8346 => 'Tones|Ringtones|Classical|Brass & Woodwinds',
     4512            8347 => 'Tones|Ringtones|Classical|Solo Instrumental',
     4513            8348 => 'Tones|Ringtones|Classical|Contemporary Era',
     4514            8349 => 'Tones|Ringtones|Classical|Oratorio',
     4515            8350 => 'Tones|Ringtones|Classical|Cantata',
     4516            8351 => 'Tones|Ringtones|Classical|Electronic',
     4517            8352 => 'Tones|Ringtones|Classical|Sacred',
     4518            8353 => 'Tones|Ringtones|Classical|Guitar',
     4519            8354 => 'Tones|Ringtones|Classical|Piano',
     4520            8355 => 'Tones|Ringtones|Classical|Violin',
     4521            8356 => 'Tones|Ringtones|Classical|Cello',
     4522            8357 => 'Tones|Ringtones|Classical|Percussion',
     4523            8358 => 'Tones|Ringtones|Electronic|Dubstep',
     4524            8359 => 'Tones|Ringtones|Electronic|Bass',
     4525            8360 => 'Tones|Ringtones|Hip-Hop/Rap|UK Hip Hop',
     4526            8361 => 'Tones|Ringtones|Reggae|Lovers Rock',
     4527            8362 => 'Tones|Ringtones|Alternative|EMO',
     4528            8363 => 'Tones|Ringtones|Alternative|Pop Punk',
     4529            8364 => 'Tones|Ringtones|Alternative|Indie Pop',
     4530            8365 => 'Tones|Ringtones|New Age|Yoga',
     4531            8366 => 'Tones|Ringtones|Pop|Tribute',
     4532            8367 => 'Tones|Ringtones|Pop|Shows',
     4533            8368 => 'Tones|Ringtones|Cuban',
     4534            8369 => 'Tones|Ringtones|Cuban|Mambo',
     4535            8370 => 'Tones|Ringtones|Cuban|Chachacha',
     4536            8371 => 'Tones|Ringtones|Cuban|Guajira',
     4537            8372 => 'Tones|Ringtones|Cuban|Son',
     4538            8373 => 'Tones|Ringtones|Cuban|Bolero',
     4539            8374 => 'Tones|Ringtones|Cuban|Guaracha',
     4540            8375 => 'Tones|Ringtones|Cuban|Timba',
     4541            8376 => 'Tones|Ringtones|Soundtrack|Video Game',
     4542            8377 => 'Tones|Ringtones|Indian|Regional Indian|Punjabi|Punjabi Pop',
     4543            8378 => 'Tones|Ringtones|Indian|Regional Indian|Bengali|Rabindra Sangeet',
     4544            8379 => 'Tones|Ringtones|Indian|Regional Indian|Malayalam',
     4545            8380 => 'Tones|Ringtones|Indian|Regional Indian|Kannada',
     4546            8381 => 'Tones|Ringtones|Indian|Regional Indian|Marathi',
     4547            8382 => 'Tones|Ringtones|Indian|Regional Indian|Gujarati',
     4548            8383 => 'Tones|Ringtones|Indian|Regional Indian|Assamese',
     4549            8384 => 'Tones|Ringtones|Indian|Regional Indian|Bhojpuri',
     4550            8385 => 'Tones|Ringtones|Indian|Regional Indian|Haryanvi',
     4551            8386 => 'Tones|Ringtones|Indian|Regional Indian|Odia',
     4552            8387 => 'Tones|Ringtones|Indian|Regional Indian|Rajasthani',
     4553            8388 => 'Tones|Ringtones|Indian|Regional Indian|Urdu',
     4554            8389 => 'Tones|Ringtones|Indian|Regional Indian|Punjabi',
     4555            8390 => 'Tones|Ringtones|Indian|Regional Indian|Bengali',
     4556            8391 => 'Tones|Ringtones|Indian|Indian Classical|Carnatic Classical',
     4557            8392 => 'Tones|Ringtones|Indian|Indian Classical|Hindustani Classical',
     4558            8393 => 'Tones|Ringtones|African|Afro House',
     4559            8394 => 'Tones|Ringtones|African|Afro Soul',
     4560            8395 => 'Tones|Ringtones|African|Afrobeats',
     4561            8396 => 'Tones|Ringtones|African|Benga',
     4562            8397 => 'Tones|Ringtones|African|Bongo-Flava',
     4563            8398 => 'Tones|Ringtones|African|Coupe-Decale',
     4564            8399 => 'Tones|Ringtones|African|Gqom',
     4565            8400 => 'Tones|Ringtones|African|Highlife',
     4566            8401 => 'Tones|Ringtones|African|Kuduro',
     4567            8402 => 'Tones|Ringtones|African|Kizomba',
     4568            8403 => 'Tones|Ringtones|African|Kwaito',
     4569            8404 => 'Tones|Ringtones|African|Mbalax',
     4570            8405 => 'Tones|Ringtones|African|Ndombolo',
     4571            8406 => 'Tones|Ringtones|African|Shangaan Electro',
     4572            8407 => 'Tones|Ringtones|African|Soukous',
     4573            8408 => 'Tones|Ringtones|African|Taarab',
     4574            8409 => 'Tones|Ringtones|African|Zouglou',
     4575            8410 => 'Tones|Ringtones|Turkish|Ozgun',
     4576            8411 => 'Tones|Ringtones|Turkish|Fantezi',
     4577            8412 => 'Tones|Ringtones|Turkish|Religious',
     4578            8413 => 'Tones|Ringtones|Pop|Turkish Pop',
     4579            8414 => 'Tones|Ringtones|Rock|Turkish Rock',
     4580            8415 => 'Tones|Ringtones|Alternative|Turkish Alternative',
     4581            8416 => 'Tones|Ringtones|Hip-Hop/Rap|Turkish Hip-Hop/Rap',
     4582            8417 => 'Tones|Ringtones|African|Maskandi',
     4583            8418 => 'Tones|Ringtones|Russian|Russian Romance',
     4584            8419 => 'Tones|Ringtones|Russian|Russian Bard',
     4585            8420 => 'Tones|Ringtones|Russian|Russian Pop',
     4586            8421 => 'Tones|Ringtones|Russian|Russian Rock',
     4587            8422 => 'Tones|Ringtones|Russian|Russian Hip-Hop',
     4588            8423 => 'Tones|Ringtones|Arabic|Levant',
     4589            8424 => 'Tones|Ringtones|Arabic|Levant|Dabke',
     4590            8425 => 'Tones|Ringtones|Arabic|Maghreb Rai',
     4591            8426 => 'Tones|Ringtones|Arabic|Khaleeji|Khaleeji Jalsat',
     4592            8427 => 'Tones|Ringtones|Arabic|Khaleeji|Khaleeji Shailat',
     4593            8428 => 'Tones|Ringtones|Tarab',
     4594            8429 => 'Tones|Ringtones|Tarab|Iraqi Tarab',
     4595            8430 => 'Tones|Ringtones|Tarab|Egyptian Tarab',
     4596            8431 => 'Tones|Ringtones|Tarab|Khaleeji Tarab',
     4597            8432 => 'Tones|Ringtones|Pop|Levant Pop',
     4598            8433 => 'Tones|Ringtones|Pop|Iraqi Pop',
     4599            8434 => 'Tones|Ringtones|Pop|Egyptian Pop',
     4600            8435 => 'Tones|Ringtones|Pop|Maghreb Pop',
     4601            8436 => 'Tones|Ringtones|Pop|Khaleeji Pop',
     4602            8437 => 'Tones|Ringtones|Hip-Hop/Rap|Levant Hip-Hop',
     4603            8438 => 'Tones|Ringtones|Hip-Hop/Rap|Egyptian Hip-Hop',
     4604            8439 => 'Tones|Ringtones|Hip-Hop/Rap|Maghreb Hip-Hop',
     4605            8440 => 'Tones|Ringtones|Hip-Hop/Rap|Khaleeji Hip-Hop',
     4606            8441 => 'Tones|Ringtones|Alternative|Indie Levant',
     4607            8442 => 'Tones|Ringtones|Alternative|Indie Egyptian',
     4608            8443 => 'Tones|Ringtones|Alternative|Indie Maghreb',
     4609            8444 => 'Tones|Ringtones|Electronic|Levant Electronic',
     4610            8445 => "Tones|Ringtones|Electronic|Electro-Cha'abi",
     4611            8446 => 'Tones|Ringtones|Electronic|Maghreb Electronic',
     4612            8447 => 'Tones|Ringtones|Folk|Iraqi Folk',
     4613            8448 => 'Tones|Ringtones|Folk|Khaleeji Folk',
     4614            8449 => 'Tones|Ringtones|Dance|Maghreb Dance',
     4615            9002 => 'Books|Nonfiction',
     4616            9003 => 'Books|Romance',
     4617            9004 => 'Books|Travel & Adventure',
     4618            9007 => 'Books|Arts & Entertainment',
     4619            9008 => 'Books|Biographies & Memoirs',
     4620            9009 => 'Books|Business & Personal Finance',
     4621            9010 => 'Books|Children & Teens',
     4622            9012 => 'Books|Humor',
     4623            9015 => 'Books|History',
     4624            9018 => 'Books|Religion & Spirituality',
     4625            9019 => 'Books|Science & Nature',
     4626            9020 => 'Books|Sci-Fi & Fantasy',
     4627            9024 => 'Books|Lifestyle & Home',
     4628            9025 => 'Books|Self-Development',
     4629            9026 => 'Books|Comics & Graphic Novels',
     4630            9027 => 'Books|Computers & Internet',
     4631            9028 => 'Books|Cookbooks, Food & Wine',
     4632            9029 => 'Books|Professional & Technical',
     4633            9030 => 'Books|Parenting',
     4634            9031 => 'Books|Fiction & Literature',
     4635            9032 => 'Books|Mysteries & Thrillers',
     4636            9033 => 'Books|Reference',
     4637            9034 => 'Books|Politics & Current Events',
     4638            9035 => 'Books|Sports & Outdoors',
     4639            10001 => 'Books|Lifestyle & Home|Antiques & Collectibles',
     4640            10002 => 'Books|Arts & Entertainment|Art & Architecture',
     4641            10003 => 'Books|Religion & Spirituality|Bibles',
     4642            10004 => 'Books|Self-Development|Spirituality',
     4643            10005 => 'Books|Business & Personal Finance|Industries & Professions',
     4644            10006 => 'Books|Business & Personal Finance|Marketing & Sales',
     4645            10007 => 'Books|Business & Personal Finance|Small Business & Entrepreneurship',
     4646            10008 => 'Books|Business & Personal Finance|Personal Finance',
     4647            10009 => 'Books|Business & Personal Finance|Reference',
     4648            10010 => 'Books|Business & Personal Finance|Careers',
     4649            10011 => 'Books|Business & Personal Finance|Economics',
     4650            10012 => 'Books|Business & Personal Finance|Investing',
     4651            10013 => 'Books|Business & Personal Finance|Finance',
     4652            10014 => 'Books|Business & Personal Finance|Management & Leadership',
     4653            10015 => 'Books|Comics & Graphic Novels|Graphic Novels',
     4654            10016 => 'Books|Comics & Graphic Novels|Manga',
     4655            10017 => 'Books|Computers & Internet|Computers',
     4656            10018 => 'Books|Computers & Internet|Databases',
     4657            10019 => 'Books|Computers & Internet|Digital Media',
     4658            10020 => 'Books|Computers & Internet|Internet',
     4659            10021 => 'Books|Computers & Internet|Network',
     4660            10022 => 'Books|Computers & Internet|Operating Systems',
     4661            10023 => 'Books|Computers & Internet|Programming',
     4662            10024 => 'Books|Computers & Internet|Software',
     4663            10025 => 'Books|Computers & Internet|System Administration',
     4664            10026 => 'Books|Cookbooks, Food & Wine|Beverages',
     4665            10027 => 'Books|Cookbooks, Food & Wine|Courses & Dishes',
     4666            10028 => 'Books|Cookbooks, Food & Wine|Special Diet',
     4667            10029 => 'Books|Cookbooks, Food & Wine|Special Occasions',
     4668            10030 => 'Books|Cookbooks, Food & Wine|Methods',
     4669            10031 => 'Books|Cookbooks, Food & Wine|Reference',
     4670            10032 => 'Books|Cookbooks, Food & Wine|Regional & Ethnic',
     4671            10033 => 'Books|Cookbooks, Food & Wine|Specific Ingredients',
     4672            10034 => 'Books|Lifestyle & Home|Crafts & Hobbies',
     4673            10035 => 'Books|Professional & Technical|Design',
     4674            10036 => 'Books|Arts & Entertainment|Theater',
     4675            10037 => 'Books|Professional & Technical|Education',
     4676            10038 => 'Books|Nonfiction|Family & Relationships',
     4677            10039 => 'Books|Fiction & Literature|Action & Adventure',
     4678            10040 => 'Books|Fiction & Literature|African American',
     4679            10041 => 'Books|Fiction & Literature|Religious',
     4680            10042 => 'Books|Fiction & Literature|Classics',
     4681            10043 => 'Books|Fiction & Literature|Erotica',
     4682            10044 => 'Books|Sci-Fi & Fantasy|Fantasy',
     4683            10045 => 'Books|Fiction & Literature|Gay',
     4684            10046 => 'Books|Fiction & Literature|Ghost',
     4685            10047 => 'Books|Fiction & Literature|Historical',
     4686            10048 => 'Books|Fiction & Literature|Horror',
     4687            10049 => 'Books|Fiction & Literature|Literary',
     4688            10050 => 'Books|Mysteries & Thrillers|Hard-Boiled',
     4689            10051 => 'Books|Mysteries & Thrillers|Historical',
     4690            10052 => 'Books|Mysteries & Thrillers|Police Procedural',
     4691            10053 => 'Books|Mysteries & Thrillers|Short Stories',
     4692            10054 => 'Books|Mysteries & Thrillers|British Detectives',
     4693            10055 => 'Books|Mysteries & Thrillers|Women Sleuths',
     4694            10056 => 'Books|Romance|Erotic Romance',
     4695            10057 => 'Books|Romance|Contemporary',
     4696            10058 => 'Books|Romance|Paranormal',
     4697            10059 => 'Books|Romance|Historical',
     4698            10060 => 'Books|Romance|Short Stories',
     4699            10061 => 'Books|Romance|Suspense',
     4700            10062 => 'Books|Romance|Western',
     4701            10063 => 'Books|Sci-Fi & Fantasy|Science Fiction',
     4702            10064 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature',
     4703            10065 => 'Books|Fiction & Literature|Short Stories',
     4704            10066 => 'Books|Reference|Foreign Languages',
     4705            10067 => 'Books|Arts & Entertainment|Games',
     4706            10068 => 'Books|Lifestyle & Home|Gardening',
     4707            10069 => 'Books|Self-Development|Health & Fitness',
     4708            10070 => 'Books|History|Africa',
     4709            10071 => 'Books|History|Americas',
     4710            10072 => 'Books|History|Ancient',
     4711            10073 => 'Books|History|Asia',
     4712            10074 => 'Books|History|Australia & Oceania',
     4713            10075 => 'Books|History|Europe',
     4714            10076 => 'Books|History|Latin America',
     4715            10077 => 'Books|History|Middle East',
     4716            10078 => 'Books|History|Military',
     4717            10079 => 'Books|History|United States',
     4718            10080 => 'Books|History|World',
     4719            10081 => "Books|Children & Teens|Children's Fiction",
     4720            10082 => "Books|Children & Teens|Children's Nonfiction",
     4721            10083 => 'Books|Professional & Technical|Law',
     4722            10084 => 'Books|Fiction & Literature|Literary Criticism',
     4723            10085 => 'Books|Science & Nature|Mathematics',
     4724            10086 => 'Books|Professional & Technical|Medical',
     4725            10087 => 'Books|Arts & Entertainment|Music',
     4726            10088 => 'Books|Science & Nature|Nature',
     4727            10089 => 'Books|Arts & Entertainment|Performing Arts',
     4728            10090 => 'Books|Lifestyle & Home|Pets',
     4729            10091 => 'Books|Nonfiction|Philosophy',
     4730            10092 => 'Books|Arts & Entertainment|Photography',
     4731            10093 => 'Books|Fiction & Literature|Poetry',
     4732            10094 => 'Books|Self-Development|Psychology',
     4733            10095 => 'Books|Reference|Almanacs & Yearbooks',
     4734            10096 => 'Books|Reference|Atlases & Maps',
     4735            10097 => 'Books|Reference|Catalogs & Directories',
     4736            10098 => 'Books|Reference|Consumer Guides',
     4737            10099 => 'Books|Reference|Dictionaries & Thesauruses',
     4738            10100 => 'Books|Reference|Encyclopedias',
     4739            10101 => 'Books|Reference|Etiquette',
     4740            10102 => 'Books|Reference|Quotations',
     4741            10103 => 'Books|Reference|Words & Language',
     4742            10104 => 'Books|Reference|Writing',
     4743            10105 => 'Books|Religion & Spirituality|Bible Studies',
     4744            10106 => 'Books|Religion & Spirituality|Buddhism',
     4745            10107 => 'Books|Religion & Spirituality|Christianity',
     4746            10108 => 'Books|Religion & Spirituality|Hinduism',
     4747            10109 => 'Books|Religion & Spirituality|Islam',
     4748            10110 => 'Books|Religion & Spirituality|Judaism',
     4749            10111 => 'Books|Science & Nature|Astronomy',
     4750            10112 => 'Books|Science & Nature|Chemistry',
     4751            10113 => 'Books|Science & Nature|Earth Sciences',
     4752            10114 => 'Books|Science & Nature|Essays',
     4753            10115 => 'Books|Science & Nature|History',
     4754            10116 => 'Books|Science & Nature|Life Sciences',
     4755            10117 => 'Books|Science & Nature|Physics',
     4756            10118 => 'Books|Science & Nature|Reference',
     4757            10119 => 'Books|Self-Development|Self-Improvement',
     4758            10120 => 'Books|Nonfiction|Social Science',
     4759            10121 => 'Books|Sports & Outdoors|Baseball',
     4760            10122 => 'Books|Sports & Outdoors|Basketball',
     4761            10123 => 'Books|Sports & Outdoors|Coaching',
     4762            10124 => 'Books|Sports & Outdoors|Extreme Sports',
     4763            10125 => 'Books|Sports & Outdoors|Football',
     4764            10126 => 'Books|Sports & Outdoors|Golf',
     4765            10127 => 'Books|Sports & Outdoors|Hockey',
     4766            10128 => 'Books|Sports & Outdoors|Mountaineering',
     4767            10129 => 'Books|Sports & Outdoors|Outdoors',
     4768            10130 => 'Books|Sports & Outdoors|Racket Sports',
     4769            10131 => 'Books|Sports & Outdoors|Reference',
     4770            10132 => 'Books|Sports & Outdoors|Soccer',
     4771            10133 => 'Books|Sports & Outdoors|Training',
     4772            10134 => 'Books|Sports & Outdoors|Water Sports',
     4773            10135 => 'Books|Sports & Outdoors|Winter Sports',
     4774            10136 => 'Books|Reference|Study Aids',
     4775            10137 => 'Books|Professional & Technical|Engineering',
     4776            10138 => 'Books|Nonfiction|Transportation',
     4777            10139 => 'Books|Travel & Adventure|Africa',
     4778            10140 => 'Books|Travel & Adventure|Asia',
     4779            10141 => 'Books|Travel & Adventure|Specialty Travel',
     4780            10142 => 'Books|Travel & Adventure|Canada',
     4781            10143 => 'Books|Travel & Adventure|Caribbean',
     4782            10144 => 'Books|Travel & Adventure|Latin America',
     4783            10145 => 'Books|Travel & Adventure|Essays & Memoirs',
     4784            10146 => 'Books|Travel & Adventure|Europe',
     4785            10147 => 'Books|Travel & Adventure|Middle East',
     4786            10148 => 'Books|Travel & Adventure|United States',
     4787            10149 => 'Books|Nonfiction|True Crime',
     4788            11001 => 'Books|Sci-Fi & Fantasy|Fantasy|Contemporary',
     4789            11002 => 'Books|Sci-Fi & Fantasy|Fantasy|Epic',
     4790            11003 => 'Books|Sci-Fi & Fantasy|Fantasy|Historical',
     4791            11004 => 'Books|Sci-Fi & Fantasy|Fantasy|Paranormal',
     4792            11005 => 'Books|Sci-Fi & Fantasy|Fantasy|Short Stories',
     4793            11006 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|Adventure',
     4794            11007 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|High Tech',
     4795            11008 => 'Books|Sci-Fi & Fantasy|Science Fiction & Literature|Short Stories',
     4796            11009 => 'Books|Professional & Technical|Education|Language Arts & Disciplines',
     4797            11010 => 'Books|Communications & Media',
     4798            11011 => 'Books|Communications & Media|Broadcasting',
     4799            11012 => 'Books|Communications & Media|Digital Media',
     4800            11013 => 'Books|Communications & Media|Journalism',
     4801            11014 => 'Books|Communications & Media|Photojournalism',
     4802            11015 => 'Books|Communications & Media|Print',
     4803            11016 => 'Books|Communications & Media|Speech',
     4804            11017 => 'Books|Communications & Media|Writing',
     4805            11018 => 'Books|Arts & Entertainment|Art & Architecture|Urban Planning',
     4806            11019 => 'Books|Arts & Entertainment|Dance',
     4807            11020 => 'Books|Arts & Entertainment|Fashion',
     4808            11021 => 'Books|Arts & Entertainment|Film',
     4809            11022 => 'Books|Arts & Entertainment|Interior Design',
     4810            11023 => 'Books|Arts & Entertainment|Media Arts',
     4811            11024 => 'Books|Arts & Entertainment|Radio',
     4812            11025 => 'Books|Arts & Entertainment|TV',
     4813            11026 => 'Books|Arts & Entertainment|Visual Arts',
     4814            11027 => 'Books|Biographies & Memoirs|Arts & Entertainment',
     4815            11028 => 'Books|Biographies & Memoirs|Business',
     4816            11029 => 'Books|Biographies & Memoirs|Culinary',
     4817            11030 => 'Books|Biographies & Memoirs|Gay & Lesbian',
     4818            11031 => 'Books|Biographies & Memoirs|Historical',
     4819            11032 => 'Books|Biographies & Memoirs|Literary',
     4820            11033 => 'Books|Biographies & Memoirs|Media & Journalism',
     4821            11034 => 'Books|Biographies & Memoirs|Military',
     4822            11035 => 'Books|Biographies & Memoirs|Politics',
     4823            11036 => 'Books|Biographies & Memoirs|Religious',
     4824            11037 => 'Books|Biographies & Memoirs|Science & Technology',
     4825            11038 => 'Books|Biographies & Memoirs|Sports',
     4826            11039 => 'Books|Biographies & Memoirs|Women',
     4827            11040 => 'Books|Romance|New Adult',
     4828            11042 => 'Books|Romance|Romantic Comedy',
     4829            11043 => 'Books|Romance|Gay & Lesbian',
     4830            11044 => 'Books|Fiction & Literature|Essays',
     4831            11045 => 'Books|Fiction & Literature|Anthologies',
     4832            11046 => 'Books|Fiction & Literature|Comparative Literature',
     4833            11047 => 'Books|Fiction & Literature|Drama',
     4834            11049 => 'Books|Fiction & Literature|Fairy Tales, Myths & Fables',
     4835            11050 => 'Books|Fiction & Literature|Family',
     4836            11051 => 'Books|Comics & Graphic Novels|Manga|School Drama',
     4837            11052 => 'Books|Comics & Graphic Novels|Manga|Human Drama',
     4838            11053 => 'Books|Comics & Graphic Novels|Manga|Family Drama',
     4839            11054 => 'Books|Sports & Outdoors|Boxing',
     4840            11055 => 'Books|Sports & Outdoors|Cricket',
     4841            11056 => 'Books|Sports & Outdoors|Cycling',
     4842            11057 => 'Books|Sports & Outdoors|Equestrian',
     4843            11058 => 'Books|Sports & Outdoors|Martial Arts & Self Defense',
     4844            11059 => 'Books|Sports & Outdoors|Motor Sports',
     4845            11060 => 'Books|Sports & Outdoors|Rugby',
     4846            11061 => 'Books|Sports & Outdoors|Running',
     4847            11062 => 'Books|Self-Development|Diet & Nutrition',
     4848            11063 => 'Books|Science & Nature|Agriculture',
     4849            11064 => 'Books|Science & Nature|Atmosphere',
     4850            11065 => 'Books|Science & Nature|Biology',
     4851            11066 => 'Books|Science & Nature|Ecology',
     4852            11067 => 'Books|Science & Nature|Environment',
     4853            11068 => 'Books|Science & Nature|Geography',
     4854            11069 => 'Books|Science & Nature|Geology',
     4855            11070 => 'Books|Nonfiction|Social Science|Anthropology',
     4856            11071 => 'Books|Nonfiction|Social Science|Archaeology',
     4857            11072 => 'Books|Nonfiction|Social Science|Civics',
     4858            11073 => 'Books|Nonfiction|Social Science|Government',
     4859            11074 => 'Books|Nonfiction|Social Science|Social Studies',
     4860            11075 => 'Books|Nonfiction|Social Science|Social Welfare',
     4861            11076 => 'Books|Nonfiction|Social Science|Society',
     4862            11077 => 'Books|Nonfiction|Philosophy|Aesthetics',
     4863            11078 => 'Books|Nonfiction|Philosophy|Epistemology',
     4864            11079 => 'Books|Nonfiction|Philosophy|Ethics',
     4865            11080 => 'Books|Nonfiction|Philosophy|Language',
     4866            11081 => 'Books|Nonfiction|Philosophy|Logic',
     4867            11082 => 'Books|Nonfiction|Philosophy|Metaphysics',
     4868            11083 => 'Books|Nonfiction|Philosophy|Political',
     4869            11084 => 'Books|Nonfiction|Philosophy|Religion',
     4870            11085 => 'Books|Reference|Manuals',
     4871            11086 => 'Books|Kids',
     4872            11087 => 'Books|Kids|Animals',
     4873            11088 => 'Books|Kids|Basic Concepts',
     4874            11089 => 'Books|Kids|Basic Concepts|Alphabet',
     4875            11090 => 'Books|Kids|Basic Concepts|Body',
     4876            11091 => 'Books|Kids|Basic Concepts|Colors',
     4877            11092 => 'Books|Kids|Basic Concepts|Counting & Numbers',
     4878            11093 => 'Books|Kids|Basic Concepts|Date & Time',
     4879            11094 => 'Books|Kids|Basic Concepts|General',
     4880            11095 => 'Books|Kids|Basic Concepts|Money',
     4881            11096 => 'Books|Kids|Basic Concepts|Opposites',
     4882            11097 => 'Books|Kids|Basic Concepts|Seasons',
     4883            11098 => 'Books|Kids|Basic Concepts|Senses & Sensation',
     4884            11099 => 'Books|Kids|Basic Concepts|Size & Shape',
     4885            11100 => 'Books|Kids|Basic Concepts|Sounds',
     4886            11101 => 'Books|Kids|Basic Concepts|Words',
     4887            11102 => 'Books|Kids|Biography',
     4888            11103 => 'Books|Kids|Careers & Occupations',
     4889            11104 => 'Books|Kids|Computers & Technology',
     4890            11105 => 'Books|Kids|Cooking & Food',
     4891            11106 => 'Books|Kids|Arts & Entertainment',
     4892            11107 => 'Books|Kids|Arts & Entertainment|Art',
     4893            11108 => 'Books|Kids|Arts & Entertainment|Crafts',
     4894            11109 => 'Books|Kids|Arts & Entertainment|Music',
     4895            11110 => 'Books|Kids|Arts & Entertainment|Performing Arts',
     4896            11111 => 'Books|Kids|Family',
     4897            11112 => 'Books|Kids|Fiction',
     4898            11113 => 'Books|Kids|Fiction|Action & Adventure',
     4899            11114 => 'Books|Kids|Fiction|Animals',
     4900            11115 => 'Books|Kids|Fiction|Classics',
     4901            11116 => 'Books|Kids|Fiction|Comics & Graphic Novels',
     4902            11117 => 'Books|Kids|Fiction|Culture, Places & People',
     4903            11118 => 'Books|Kids|Fiction|Family & Relationships',
     4904            11119 => 'Books|Kids|Fiction|Fantasy',
     4905            11120 => 'Books|Kids|Fiction|Fairy Tales, Myths & Fables',
     4906            11121 => 'Books|Kids|Fiction|Favorite Characters',
     4907            11122 => 'Books|Kids|Fiction|Historical',
     4908            11123 => 'Books|Kids|Fiction|Holidays & Celebrations',
     4909            11124 => 'Books|Kids|Fiction|Monsters & Ghosts',
     4910            11125 => 'Books|Kids|Fiction|Mysteries',
     4911            11126 => 'Books|Kids|Fiction|Nature',
     4912            11127 => 'Books|Kids|Fiction|Religion',
     4913            11128 => 'Books|Kids|Fiction|Sci-Fi',
     4914            11129 => 'Books|Kids|Fiction|Social Issues',
     4915            11130 => 'Books|Kids|Fiction|Sports & Recreation',
     4916            11131 => 'Books|Kids|Fiction|Transportation',
     4917            11132 => 'Books|Kids|Games & Activities',
     4918            11133 => 'Books|Kids|General Nonfiction',
     4919            11134 => 'Books|Kids|Health',
     4920            11135 => 'Books|Kids|History',
     4921            11136 => 'Books|Kids|Holidays & Celebrations',
     4922            11137 => 'Books|Kids|Holidays & Celebrations|Birthdays',
     4923            11138 => 'Books|Kids|Holidays & Celebrations|Christmas & Advent',
     4924            11139 => 'Books|Kids|Holidays & Celebrations|Easter & Lent',
     4925            11140 => 'Books|Kids|Holidays & Celebrations|General',
     4926            11141 => 'Books|Kids|Holidays & Celebrations|Halloween',
     4927            11142 => 'Books|Kids|Holidays & Celebrations|Hanukkah',
     4928            11143 => 'Books|Kids|Holidays & Celebrations|Other',
     4929            11144 => 'Books|Kids|Holidays & Celebrations|Passover',
     4930            11145 => 'Books|Kids|Holidays & Celebrations|Patriotic Holidays',
     4931            11146 => 'Books|Kids|Holidays & Celebrations|Ramadan',
     4932            11147 => 'Books|Kids|Holidays & Celebrations|Thanksgiving',
     4933            11148 => "Books|Kids|Holidays & Celebrations|Valentine's Day",
     4934            11149 => 'Books|Kids|Humor',
     4935            11150 => 'Books|Kids|Humor|Jokes & Riddles',
     4936            11151 => 'Books|Kids|Poetry',
     4937            11152 => 'Books|Kids|Learning to Read',
     4938            11153 => 'Books|Kids|Learning to Read|Chapter Books',
     4939            11154 => 'Books|Kids|Learning to Read|Early Readers',
     4940            11155 => 'Books|Kids|Learning to Read|Intermediate Readers',
     4941            11156 => 'Books|Kids|Nursery Rhymes',
     4942            11157 => 'Books|Kids|Government',
     4943            11158 => 'Books|Kids|Reference',
     4944            11159 => 'Books|Kids|Religion',
     4945            11160 => 'Books|Kids|Science & Nature',
     4946            11161 => 'Books|Kids|Social Issues',
     4947            11162 => 'Books|Kids|Social Studies',
     4948            11163 => 'Books|Kids|Sports & Recreation',
     4949            11164 => 'Books|Kids|Transportation',
     4950            11165 => 'Books|Young Adult',
     4951            11166 => 'Books|Young Adult|Animals',
     4952            11167 => 'Books|Young Adult|Biography',
     4953            11168 => 'Books|Young Adult|Careers & Occupations',
     4954            11169 => 'Books|Young Adult|Computers & Technology',
     4955            11170 => 'Books|Young Adult|Cooking & Food',
     4956            11171 => 'Books|Young Adult|Arts & Entertainment',
     4957            11172 => 'Books|Young Adult|Arts & Entertainment|Art',
     4958            11173 => 'Books|Young Adult|Arts & Entertainment|Crafts',
     4959            11174 => 'Books|Young Adult|Arts & Entertainment|Music',
     4960            11175 => 'Books|Young Adult|Arts & Entertainment|Performing Arts',
     4961            11176 => 'Books|Young Adult|Family',
     4962            11177 => 'Books|Young Adult|Fiction',
     4963            11178 => 'Books|Young Adult|Fiction|Action & Adventure',
     4964            11179 => 'Books|Young Adult|Fiction|Animals',
     4965            11180 => 'Books|Young Adult|Fiction|Classics',
     4966            11181 => 'Books|Young Adult|Fiction|Comics & Graphic Novels',
     4967            11182 => 'Books|Young Adult|Fiction|Culture, Places & People',
     4968            11183 => 'Books|Young Adult|Fiction|Dystopian',
     4969            11184 => 'Books|Young Adult|Fiction|Family & Relationships',
     4970            11185 => 'Books|Young Adult|Fiction|Fantasy',
     4971            11186 => 'Books|Young Adult|Fiction|Fairy Tales, Myths & Fables',
     4972            11187 => 'Books|Young Adult|Fiction|Favorite Characters',
     4973            11188 => 'Books|Young Adult|Fiction|Historical',
     4974            11189 => 'Books|Young Adult|Fiction|Holidays & Celebrations',
     4975            11190 => 'Books|Young Adult|Fiction|Horror, Monsters & Ghosts',
     4976            11191 => 'Books|Young Adult|Fiction|Crime & Mystery',
     4977            11192 => 'Books|Young Adult|Fiction|Nature',
     4978            11193 => 'Books|Young Adult|Fiction|Religion',
     4979            11194 => 'Books|Young Adult|Fiction|Romance',
     4980            11195 => 'Books|Young Adult|Fiction|Sci-Fi',
     4981            11196 => 'Books|Young Adult|Fiction|Coming of Age',
     4982            11197 => 'Books|Young Adult|Fiction|Sports & Recreation',
     4983            11198 => 'Books|Young Adult|Fiction|Transportation',
     4984            11199 => 'Books|Young Adult|Games & Activities',
     4985            11200 => 'Books|Young Adult|General Nonfiction',
     4986            11201 => 'Books|Young Adult|Health',
     4987            11202 => 'Books|Young Adult|History',
     4988            11203 => 'Books|Young Adult|Holidays & Celebrations',
     4989            11204 => 'Books|Young Adult|Holidays & Celebrations|Birthdays',
     4990            11205 => 'Books|Young Adult|Holidays & Celebrations|Christmas & Advent',
     4991            11206 => 'Books|Young Adult|Holidays & Celebrations|Easter & Lent',
     4992            11207 => 'Books|Young Adult|Holidays & Celebrations|General',
     4993            11208 => 'Books|Young Adult|Holidays & Celebrations|Halloween',
     4994            11209 => 'Books|Young Adult|Holidays & Celebrations|Hanukkah',
     4995            11210 => 'Books|Young Adult|Holidays & Celebrations|Other',
     4996            11211 => 'Books|Young Adult|Holidays & Celebrations|Passover',
     4997            11212 => 'Books|Young Adult|Holidays & Celebrations|Patriotic Holidays',
     4998            11213 => 'Books|Young Adult|Holidays & Celebrations|Ramadan',
     4999            11214 => 'Books|Young Adult|Holidays & Celebrations|Thanksgiving',
     5000            11215 => "Books|Young Adult|Holidays & Celebrations|Valentine's Day",
     5001            11216 => 'Books|Young Adult|Humor',
     5002            11217 => 'Books|Young Adult|Humor|Jokes & Riddles',
     5003            11218 => 'Books|Young Adult|Poetry',
     5004            11219 => 'Books|Young Adult|Politics & Government',
     5005            11220 => 'Books|Young Adult|Reference',
     5006            11221 => 'Books|Young Adult|Religion',
     5007            11222 => 'Books|Young Adult|Science & Nature',
     5008            11223 => 'Books|Young Adult|Coming of Age',
     5009            11224 => 'Books|Young Adult|Social Studies',
     5010            11225 => 'Books|Young Adult|Sports & Recreation',
     5011            11226 => 'Books|Young Adult|Transportation',
     5012            11227 => 'Books|Communications & Media',
     5013            11228 => 'Books|Military & Warfare',
     5014            11229 => 'Books|Romance|Inspirational',
     5015            11231 => 'Books|Romance|Holiday',
     5016            11232 => 'Books|Romance|Wholesome',
     5017            11233 => 'Books|Romance|Military',
     5018            11234 => 'Books|Arts & Entertainment|Art History',
     5019            11236 => 'Books|Arts & Entertainment|Design',
     5020            11243 => 'Books|Business & Personal Finance|Accounting',
     5021            11244 => 'Books|Business & Personal Finance|Hospitality',
     5022            11245 => 'Books|Business & Personal Finance|Real Estate',
     5023            11246 => 'Books|Humor|Jokes & Riddles',
     5024            11247 => 'Books|Religion & Spirituality|Comparative Religion',
     5025            11255 => 'Books|Cookbooks, Food & Wine|Culinary Arts',
     5026            11259 => 'Books|Mysteries & Thrillers|Cozy',
     5027            11260 => 'Books|Politics & Current Events|Current Events',
     5028            11261 => 'Books|Politics & Current Events|Foreign Policy & International Relations',
     5029            11262 => 'Books|Politics & Current Events|Local Government',
     5030            11263 => 'Books|Politics & Current Events|National Government',
     5031            11264 => 'Books|Politics & Current Events|Political Science',
     5032            11265 => 'Books|Politics & Current Events|Public Administration',
     5033            11266 => 'Books|Politics & Current Events|World Affairs',
     5034            11273 => 'Books|Nonfiction|Family & Relationships|Family & Childcare',
     5035            11274 => 'Books|Nonfiction|Family & Relationships|Love & Romance',
     5036            11275 => 'Books|Sci-Fi & Fantasy|Fantasy|Urban',
     5037            11276 => 'Books|Reference|Foreign Languages|Arabic',
     5038            11277 => 'Books|Reference|Foreign Languages|Bilingual Editions',
     5039            11278 => 'Books|Reference|Foreign Languages|African Languages',
     5040            11279 => 'Books|Reference|Foreign Languages|Ancient Languages',
     5041            11280 => 'Books|Reference|Foreign Languages|Chinese',
     5042            11281 => 'Books|Reference|Foreign Languages|English',
     5043            11282 => 'Books|Reference|Foreign Languages|French',
     5044            11283 => 'Books|Reference|Foreign Languages|German',
     5045            11284 => 'Books|Reference|Foreign Languages|Hebrew',
     5046            11285 => 'Books|Reference|Foreign Languages|Hindi',
     5047            11286 => 'Books|Reference|Foreign Languages|Italian',
     5048            11287 => 'Books|Reference|Foreign Languages|Japanese',
     5049            11288 => 'Books|Reference|Foreign Languages|Korean',
     5050            11289 => 'Books|Reference|Foreign Languages|Linguistics',
     5051            11290 => 'Books|Reference|Foreign Languages|Other Languages',
     5052            11291 => 'Books|Reference|Foreign Languages|Portuguese',
     5053            11292 => 'Books|Reference|Foreign Languages|Russian',
     5054            11293 => 'Books|Reference|Foreign Languages|Spanish',
     5055            11294 => 'Books|Reference|Foreign Languages|Speech Pathology',
     5056            11295 => 'Books|Science & Nature|Mathematics|Advanced Mathematics',
     5057            11296 => 'Books|Science & Nature|Mathematics|Algebra',
     5058            11297 => 'Books|Science & Nature|Mathematics|Arithmetic',
     5059            11298 => 'Books|Science & Nature|Mathematics|Calculus',
     5060            11299 => 'Books|Science & Nature|Mathematics|Geometry',
     5061            11300 => 'Books|Science & Nature|Mathematics|Statistics',
     5062            11301 => 'Books|Professional & Technical|Medical|Veterinary',
     5063            11302 => 'Books|Professional & Technical|Medical|Neuroscience',
     5064            11303 => 'Books|Professional & Technical|Medical|Immunology',
     5065            11304 => 'Books|Professional & Technical|Medical|Nursing',
     5066            11305 => 'Books|Professional & Technical|Medical|Pharmacology & Toxicology',
     5067            11306 => 'Books|Professional & Technical|Medical|Anatomy & Physiology',
     5068            11307 => 'Books|Professional & Technical|Medical|Dentistry',
     5069            11308 => 'Books|Professional & Technical|Medical|Emergency Medicine',
     5070            11309 => 'Books|Professional & Technical|Medical|Genetics',
     5071            11310 => 'Books|Professional & Technical|Medical|Psychiatry',
     5072            11311 => 'Books|Professional & Technical|Medical|Radiology',
     5073            11312 => 'Books|Professional & Technical|Medical|Alternative Medicine',
     5074            11317 => 'Books|Nonfiction|Philosophy|Political Philosophy',
     5075            11319 => 'Books|Nonfiction|Philosophy|Philosophy of Language',
     5076            11320 => 'Books|Nonfiction|Philosophy|Philosophy of Religion',
     5077            11327 => 'Books|Nonfiction|Social Science|Sociology',
     5078            11329 => 'Books|Professional & Technical|Engineering|Aeronautics',
     5079            11330 => 'Books|Professional & Technical|Engineering|Chemical & Petroleum Engineering',
     5080            11331 => 'Books|Professional & Technical|Engineering|Civil Engineering',
     5081            11332 => 'Books|Professional & Technical|Engineering|Computer Science',
     5082            11333 => 'Books|Professional & Technical|Engineering|Electrical Engineering',
     5083            11334 => 'Books|Professional & Technical|Engineering|Environmental Engineering',
     5084            11335 => 'Books|Professional & Technical|Engineering|Mechanical Engineering',
     5085            11336 => 'Books|Professional & Technical|Engineering|Power Resources',
     5086            11337 => 'Books|Comics & Graphic Novels|Manga|Boys',
     5087            11338 => 'Books|Comics & Graphic Novels|Manga|Men',
     5088            11339 => 'Books|Comics & Graphic Novels|Manga|Girls',
     5089            11340 => 'Books|Comics & Graphic Novels|Manga|Women',
     5090            11341 => 'Books|Comics & Graphic Novels|Manga|Other',
     5091            11342 => 'Books|Comics & Graphic Novels|Manga|Yaoi',
     5092            11343 => 'Books|Comics & Graphic Novels|Manga|Comic Essays',
     5093            12001 => 'Mac App Store|Business',
     5094            12002 => 'Mac App Store|Developer Tools',
     5095            12003 => 'Mac App Store|Education',
     5096            12004 => 'Mac App Store|Entertainment',
     5097            12005 => 'Mac App Store|Finance',
     5098            12006 => 'Mac App Store|Games',
     5099            12007 => 'Mac App Store|Health & Fitness',
     5100            12008 => 'Mac App Store|Lifestyle',
     5101            12010 => 'Mac App Store|Medical',
     5102            12011 => 'Mac App Store|Music',
     5103            12012 => 'Mac App Store|News',
     5104            12013 => 'Mac App Store|Photography',
     5105            12014 => 'Mac App Store|Productivity',
     5106            12015 => 'Mac App Store|Reference',
     5107            12016 => 'Mac App Store|Social Networking',
     5108            12017 => 'Mac App Store|Sports',
     5109            12018 => 'Mac App Store|Travel',
     5110            12019 => 'Mac App Store|Utilities',
     5111            12020 => 'Mac App Store|Video',
     5112            12021 => 'Mac App Store|Weather',
     5113            12022 => 'Mac App Store|Graphics & Design',
     5114            12201 => 'Mac App Store|Games|Action',
     5115            12202 => 'Mac App Store|Games|Adventure',
     5116            12203 => 'Mac App Store|Games|Casual',
     5117            12204 => 'Mac App Store|Games|Board',
     5118            12205 => 'Mac App Store|Games|Card',
     5119            12206 => 'Mac App Store|Games|Casino',
     5120            12207 => 'Mac App Store|Games|Dice',
     5121            12208 => 'Mac App Store|Games|Educational',
     5122            12209 => 'Mac App Store|Games|Family',
     5123            12210 => 'Mac App Store|Games|Kids',
     5124            12211 => 'Mac App Store|Games|Music',
     5125            12212 => 'Mac App Store|Games|Puzzle',
     5126            12213 => 'Mac App Store|Games|Racing',
     5127            12214 => 'Mac App Store|Games|Role Playing',
     5128            12215 => 'Mac App Store|Games|Simulation',
     5129            12216 => 'Mac App Store|Games|Sports',
     5130            12217 => 'Mac App Store|Games|Strategy',
     5131            12218 => 'Mac App Store|Games|Trivia',
     5132            12219 => 'Mac App Store|Games|Word',
     5133            13001 => 'App Store|Magazines & Newspapers|News & Politics',
     5134            13002 => 'App Store|Magazines & Newspapers|Fashion & Style',
     5135            13003 => 'App Store|Magazines & Newspapers|Home & Garden',
     5136            13004 => 'App Store|Magazines & Newspapers|Outdoors & Nature',
     5137            13005 => 'App Store|Magazines & Newspapers|Sports & Leisure',
     5138            13006 => 'App Store|Magazines & Newspapers|Automotive',
     5139            13007 => 'App Store|Magazines & Newspapers|Arts & Photography',
     5140            13008 => 'App Store|Magazines & Newspapers|Brides & Weddings',
     5141            13009 => 'App Store|Magazines & Newspapers|Business & Investing',
     5142            13010 => "App Store|Magazines & Newspapers|Children's Magazines",
     5143            13011 => 'App Store|Magazines & Newspapers|Computers & Internet',
     5144            13012 => 'App Store|Magazines & Newspapers|Cooking, Food & Drink',
     5145            13013 => 'App Store|Magazines & Newspapers|Crafts & Hobbies',
     5146            13014 => 'App Store|Magazines & Newspapers|Electronics & Audio',
     5147            13015 => 'App Store|Magazines & Newspapers|Entertainment',
     5148            13017 => 'App Store|Magazines & Newspapers|Health, Mind & Body',
     5149            13018 => 'App Store|Magazines & Newspapers|History',
     5150            13019 => 'App Store|Magazines & Newspapers|Literary Magazines & Journals',
     5151            13020 => "App Store|Magazines & Newspapers|Men's Interest",
     5152            13021 => 'App Store|Magazines & Newspapers|Movies & Music',
     5153            13023 => 'App Store|Magazines & Newspapers|Parenting & Family',
     5154            13024 => 'App Store|Magazines & Newspapers|Pets',
     5155            13025 => 'App Store|Magazines & Newspapers|Professional & Trade',
     5156            13026 => 'App Store|Magazines & Newspapers|Regional News',
     5157            13027 => 'App Store|Magazines & Newspapers|Science',
     5158            13028 => 'App Store|Magazines & Newspapers|Teens',
     5159            13029 => 'App Store|Magazines & Newspapers|Travel & Regional',
     5160            13030 => "App Store|Magazines & Newspapers|Women's Interest",
     5161            15000 => 'Textbooks|Arts & Entertainment',
     5162            15001 => 'Textbooks|Arts & Entertainment|Art & Architecture',
     5163            15002 => 'Textbooks|Arts & Entertainment|Art & Architecture|Urban Planning',
     5164            15003 => 'Textbooks|Arts & Entertainment|Art History',
     5165            15004 => 'Textbooks|Arts & Entertainment|Dance',
     5166            15005 => 'Textbooks|Arts & Entertainment|Design',
     5167            15006 => 'Textbooks|Arts & Entertainment|Fashion',
     5168            15007 => 'Textbooks|Arts & Entertainment|Film',
     5169            15008 => 'Textbooks|Arts & Entertainment|Games',
     5170            15009 => 'Textbooks|Arts & Entertainment|Interior Design',
     5171            15010 => 'Textbooks|Arts & Entertainment|Media Arts',
     5172            15011 => 'Textbooks|Arts & Entertainment|Music',
     5173            15012 => 'Textbooks|Arts & Entertainment|Performing Arts',
     5174            15013 => 'Textbooks|Arts & Entertainment|Photography',
     5175            15014 => 'Textbooks|Arts & Entertainment|Theater',
     5176            15015 => 'Textbooks|Arts & Entertainment|TV',
     5177            15016 => 'Textbooks|Arts & Entertainment|Visual Arts',
     5178            15017 => 'Textbooks|Biographies & Memoirs',
     5179            15018 => 'Textbooks|Business & Personal Finance',
     5180            15019 => 'Textbooks|Business & Personal Finance|Accounting',
     5181            15020 => 'Textbooks|Business & Personal Finance|Careers',
     5182            15021 => 'Textbooks|Business & Personal Finance|Economics',
     5183            15022 => 'Textbooks|Business & Personal Finance|Finance',
     5184            15023 => 'Textbooks|Business & Personal Finance|Hospitality',
     5185            15024 => 'Textbooks|Business & Personal Finance|Industries & Professions',
     5186            15025 => 'Textbooks|Business & Personal Finance|Investing',
     5187            15026 => 'Textbooks|Business & Personal Finance|Management & Leadership',
     5188            15027 => 'Textbooks|Business & Personal Finance|Marketing & Sales',
     5189            15028 => 'Textbooks|Business & Personal Finance|Personal Finance',
     5190            15029 => 'Textbooks|Business & Personal Finance|Real Estate',
     5191            15030 => 'Textbooks|Business & Personal Finance|Reference',
     5192            15031 => 'Textbooks|Business & Personal Finance|Small Business & Entrepreneurship',
     5193            15032 => 'Textbooks|Children & Teens',
     5194            15033 => 'Textbooks|Children & Teens|Fiction',
     5195            15034 => 'Textbooks|Children & Teens|Nonfiction',
     5196            15035 => 'Textbooks|Comics & Graphic Novels',
     5197            15036 => 'Textbooks|Comics & Graphic Novels|Graphic Novels',
     5198            15037 => 'Textbooks|Comics & Graphic Novels|Manga',
     5199            15038 => 'Textbooks|Communications & Media',
     5200            15039 => 'Textbooks|Communications & Media|Broadcasting',
     5201            15040 => 'Textbooks|Communications & Media|Digital Media',
     5202            15041 => 'Textbooks|Communications & Media|Journalism',
     5203            15042 => 'Textbooks|Communications & Media|Photojournalism',
     5204            15043 => 'Textbooks|Communications & Media|Print',
     5205            15044 => 'Textbooks|Communications & Media|Speech',
     5206            15045 => 'Textbooks|Communications & Media|Writing',
     5207            15046 => 'Textbooks|Computers & Internet',
     5208            15047 => 'Textbooks|Computers & Internet|Computers',
     5209            15048 => 'Textbooks|Computers & Internet|Databases',
     5210            15049 => 'Textbooks|Computers & Internet|Digital Media',
     5211            15050 => 'Textbooks|Computers & Internet|Internet',
     5212            15051 => 'Textbooks|Computers & Internet|Network',
     5213            15052 => 'Textbooks|Computers & Internet|Operating Systems',
     5214            15053 => 'Textbooks|Computers & Internet|Programming',
     5215            15054 => 'Textbooks|Computers & Internet|Software',
     5216            15055 => 'Textbooks|Computers & Internet|System Administration',
     5217            15056 => 'Textbooks|Cookbooks, Food & Wine',
     5218            15057 => 'Textbooks|Cookbooks, Food & Wine|Beverages',
     5219            15058 => 'Textbooks|Cookbooks, Food & Wine|Courses & Dishes',
     5220            15059 => 'Textbooks|Cookbooks, Food & Wine|Culinary Arts',
     5221            15060 => 'Textbooks|Cookbooks, Food & Wine|Methods',
     5222            15061 => 'Textbooks|Cookbooks, Food & Wine|Reference',
     5223            15062 => 'Textbooks|Cookbooks, Food & Wine|Regional & Ethnic',
     5224            15063 => 'Textbooks|Cookbooks, Food & Wine|Special Diet',
     5225            15064 => 'Textbooks|Cookbooks, Food & Wine|Special Occasions',
     5226            15065 => 'Textbooks|Cookbooks, Food & Wine|Specific Ingredients',
     5227            15066 => 'Textbooks|Engineering',
     5228            15067 => 'Textbooks|Engineering|Aeronautics',
     5229            15068 => 'Textbooks|Engineering|Chemical & Petroleum Engineering',
     5230            15069 => 'Textbooks|Engineering|Civil Engineering',
     5231            15070 => 'Textbooks|Engineering|Computer Science',
     5232            15071 => 'Textbooks|Engineering|Electrical Engineering',
     5233            15072 => 'Textbooks|Engineering|Environmental Engineering',
     5234            15073 => 'Textbooks|Engineering|Mechanical Engineering',
     5235            15074 => 'Textbooks|Engineering|Power Resources',
     5236            15075 => 'Textbooks|Fiction & Literature',
     5237            15076 => 'Textbooks|Fiction & Literature|Latino',
     5238            15077 => 'Textbooks|Fiction & Literature|Action & Adventure',
     5239            15078 => 'Textbooks|Fiction & Literature|African American',
     5240            15079 => 'Textbooks|Fiction & Literature|Anthologies',
     5241            15080 => 'Textbooks|Fiction & Literature|Classics',
     5242            15081 => 'Textbooks|Fiction & Literature|Comparative Literature',
     5243            15082 => 'Textbooks|Fiction & Literature|Erotica',
     5244            15083 => 'Textbooks|Fiction & Literature|Gay',
     5245            15084 => 'Textbooks|Fiction & Literature|Ghost',
     5246            15085 => 'Textbooks|Fiction & Literature|Historical',
     5247            15086 => 'Textbooks|Fiction & Literature|Horror',
     5248            15087 => 'Textbooks|Fiction & Literature|Literary',
     5249            15088 => 'Textbooks|Fiction & Literature|Literary Criticism',
     5250            15089 => 'Textbooks|Fiction & Literature|Poetry',
     5251            15090 => 'Textbooks|Fiction & Literature|Religious',
     5252            15091 => 'Textbooks|Fiction & Literature|Short Stories',
     5253            15092 => 'Textbooks|Health, Mind & Body',
     5254            15093 => 'Textbooks|Health, Mind & Body|Fitness',
     5255            15094 => 'Textbooks|Health, Mind & Body|Self-Improvement',
     5256            15095 => 'Textbooks|History',
     5257            15096 => 'Textbooks|History|Africa',
     5258            15097 => 'Textbooks|History|Americas',
     5259            15098 => 'Textbooks|History|Americas|Canada',
     5260            15099 => 'Textbooks|History|Americas|Latin America',
     5261            15100 => 'Textbooks|History|Americas|United States',
     5262            15101 => 'Textbooks|History|Ancient',
     5263            15102 => 'Textbooks|History|Asia',
     5264            15103 => 'Textbooks|History|Australia & Oceania',
     5265            15104 => 'Textbooks|History|Europe',
     5266            15105 => 'Textbooks|History|Middle East',
     5267            15106 => 'Textbooks|History|Military',
     5268            15107 => 'Textbooks|History|World',
     5269            15108 => 'Textbooks|Humor',
     5270            15109 => 'Textbooks|Language Studies',
     5271            15110 => 'Textbooks|Language Studies|African Languages',
     5272            15111 => 'Textbooks|Language Studies|Ancient Languages',
     5273            15112 => 'Textbooks|Language Studies|Arabic',
     5274            15113 => 'Textbooks|Language Studies|Bilingual Editions',
     5275            15114 => 'Textbooks|Language Studies|Chinese',
     5276            15115 => 'Textbooks|Language Studies|English',
     5277            15116 => 'Textbooks|Language Studies|French',
     5278            15117 => 'Textbooks|Language Studies|German',
     5279            15118 => 'Textbooks|Language Studies|Hebrew',
     5280            15119 => 'Textbooks|Language Studies|Hindi',
     5281            15120 => 'Textbooks|Language Studies|Indigenous Languages',
     5282            15121 => 'Textbooks|Language Studies|Italian',
     5283            15122 => 'Textbooks|Language Studies|Japanese',
     5284            15123 => 'Textbooks|Language Studies|Korean',
     5285            15124 => 'Textbooks|Language Studies|Linguistics',
     5286            15125 => 'Textbooks|Language Studies|Other Language',
     5287            15126 => 'Textbooks|Language Studies|Portuguese',
     5288            15127 => 'Textbooks|Language Studies|Russian',
     5289            15128 => 'Textbooks|Language Studies|Spanish',
     5290            15129 => 'Textbooks|Language Studies|Speech Pathology',
     5291            15130 => 'Textbooks|Lifestyle & Home',
     5292            15131 => 'Textbooks|Lifestyle & Home|Antiques & Collectibles',
     5293            15132 => 'Textbooks|Lifestyle & Home|Crafts & Hobbies',
     5294            15133 => 'Textbooks|Lifestyle & Home|Gardening',
     5295            15134 => 'Textbooks|Lifestyle & Home|Pets',
     5296            15135 => 'Textbooks|Mathematics',
     5297            15136 => 'Textbooks|Mathematics|Advanced Mathematics',
     5298            15137 => 'Textbooks|Mathematics|Algebra',
     5299            15138 => 'Textbooks|Mathematics|Arithmetic',
     5300            15139 => 'Textbooks|Mathematics|Calculus',
     5301            15140 => 'Textbooks|Mathematics|Geometry',
     5302            15141 => 'Textbooks|Mathematics|Statistics',
     5303            15142 => 'Textbooks|Medicine',
     5304            15143 => 'Textbooks|Medicine|Anatomy & Physiology',
     5305            15144 => 'Textbooks|Medicine|Dentistry',
     5306            15145 => 'Textbooks|Medicine|Emergency Medicine',
     5307            15146 => 'Textbooks|Medicine|Genetics',
     5308            15147 => 'Textbooks|Medicine|Immunology',
     5309            15148 => 'Textbooks|Medicine|Neuroscience',
     5310            15149 => 'Textbooks|Medicine|Nursing',
     5311            15150 => 'Textbooks|Medicine|Pharmacology & Toxicology',
     5312            15151 => 'Textbooks|Medicine|Psychiatry',
     5313            15152 => 'Textbooks|Medicine|Psychology',
     5314            15153 => 'Textbooks|Medicine|Radiology',
     5315            15154 => 'Textbooks|Medicine|Veterinary',
     5316            15155 => 'Textbooks|Mysteries & Thrillers',
     5317            15156 => 'Textbooks|Mysteries & Thrillers|British Detectives',
     5318            15157 => 'Textbooks|Mysteries & Thrillers|Hard-Boiled',
     5319            15158 => 'Textbooks|Mysteries & Thrillers|Historical',
     5320            15159 => 'Textbooks|Mysteries & Thrillers|Police Procedural',
     5321            15160 => 'Textbooks|Mysteries & Thrillers|Short Stories',
     5322            15161 => 'Textbooks|Mysteries & Thrillers|Women Sleuths',
     5323            15162 => 'Textbooks|Nonfiction',
     5324            15163 => 'Textbooks|Nonfiction|Family & Relationships',
     5325            15164 => 'Textbooks|Nonfiction|Transportation',
     5326            15165 => 'Textbooks|Nonfiction|True Crime',
     5327            15166 => 'Textbooks|Parenting',
     5328            15167 => 'Textbooks|Philosophy',
     5329            15168 => 'Textbooks|Philosophy|Aesthetics',
     5330            15169 => 'Textbooks|Philosophy|Epistemology',
     5331            15170 => 'Textbooks|Philosophy|Ethics',
     5332            15171 => 'Textbooks|Philosophy|Philosophy of Language',
     5333            15172 => 'Textbooks|Philosophy|Logic',
     5334            15173 => 'Textbooks|Philosophy|Metaphysics',
     5335            15174 => 'Textbooks|Philosophy|Political Philosophy',
     5336            15175 => 'Textbooks|Philosophy|Philosophy of Religion',
     5337            15176 => 'Textbooks|Politics & Current Events',
     5338            15177 => 'Textbooks|Politics & Current Events|Current Events',
     5339            15178 => 'Textbooks|Politics & Current Events|Foreign Policy & International Relations',
     5340            15179 => 'Textbooks|Politics & Current Events|Local Governments',
     5341            15180 => 'Textbooks|Politics & Current Events|National Governments',
     5342            15181 => 'Textbooks|Politics & Current Events|Political Science',
     5343            15182 => 'Textbooks|Politics & Current Events|Public Administration',
     5344            15183 => 'Textbooks|Politics & Current Events|World Affairs',
     5345            15184 => 'Textbooks|Professional & Technical',
     5346            15185 => 'Textbooks|Professional & Technical|Design',
     5347            15186 => 'Textbooks|Professional & Technical|Language Arts & Disciplines',
     5348            15187 => 'Textbooks|Professional & Technical|Engineering',
     5349            15188 => 'Textbooks|Professional & Technical|Law',
     5350            15189 => 'Textbooks|Professional & Technical|Medical',
     5351            15190 => 'Textbooks|Reference',
     5352            15191 => 'Textbooks|Reference|Almanacs & Yearbooks',
     5353            15192 => 'Textbooks|Reference|Atlases & Maps',
     5354            15193 => 'Textbooks|Reference|Catalogs & Directories',
     5355            15194 => 'Textbooks|Reference|Consumer Guides',
     5356            15195 => 'Textbooks|Reference|Dictionaries & Thesauruses',
     5357            15196 => 'Textbooks|Reference|Encyclopedias',
     5358            15197 => 'Textbooks|Reference|Etiquette',
     5359            15198 => 'Textbooks|Reference|Quotations',
     5360            15199 => 'Textbooks|Reference|Study Aids',
     5361            15200 => 'Textbooks|Reference|Words & Language',
     5362            15201 => 'Textbooks|Reference|Writing',
     5363            15202 => 'Textbooks|Religion & Spirituality',
     5364            15203 => 'Textbooks|Religion & Spirituality|Bible Studies',
     5365            15204 => 'Textbooks|Religion & Spirituality|Bibles',
     5366            15205 => 'Textbooks|Religion & Spirituality|Buddhism',
     5367            15206 => 'Textbooks|Religion & Spirituality|Christianity',
     5368            15207 => 'Textbooks|Religion & Spirituality|Comparative Religion',
     5369            15208 => 'Textbooks|Religion & Spirituality|Hinduism',
     5370            15209 => 'Textbooks|Religion & Spirituality|Islam',
     5371            15210 => 'Textbooks|Religion & Spirituality|Judaism',
     5372            15211 => 'Textbooks|Religion & Spirituality|Spirituality',
     5373            15212 => 'Textbooks|Romance',
     5374            15213 => 'Textbooks|Romance|Contemporary',
     5375            15214 => 'Textbooks|Romance|Erotic Romance',
     5376            15215 => 'Textbooks|Romance|Paranormal',
     5377            15216 => 'Textbooks|Romance|Historical',
     5378            15217 => 'Textbooks|Romance|Short Stories',
     5379            15218 => 'Textbooks|Romance|Suspense',
     5380            15219 => 'Textbooks|Romance|Western',
     5381            15220 => 'Textbooks|Sci-Fi & Fantasy',
     5382            15221 => 'Textbooks|Sci-Fi & Fantasy|Fantasy',
     5383            15222 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Contemporary',
     5384            15223 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Epic',
     5385            15224 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Historical',
     5386            15225 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Paranormal',
     5387            15226 => 'Textbooks|Sci-Fi & Fantasy|Fantasy|Short Stories',
     5388            15227 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction',
     5389            15228 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature',
     5390            15229 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|Adventure',
     5391            15230 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|High Tech',
     5392            15231 => 'Textbooks|Sci-Fi & Fantasy|Science Fiction & Literature|Short Stories',
     5393            15232 => 'Textbooks|Science & Nature',
     5394            15233 => 'Textbooks|Science & Nature|Agriculture',
     5395            15234 => 'Textbooks|Science & Nature|Astronomy',
     5396            15235 => 'Textbooks|Science & Nature|Atmosphere',
     5397            15236 => 'Textbooks|Science & Nature|Biology',
     5398            15237 => 'Textbooks|Science & Nature|Chemistry',
     5399            15238 => 'Textbooks|Science & Nature|Earth Sciences',
     5400            15239 => 'Textbooks|Science & Nature|Ecology',
     5401            15240 => 'Textbooks|Science & Nature|Environment',
     5402            15241 => 'Textbooks|Science & Nature|Essays',
     5403            15242 => 'Textbooks|Science & Nature|Geography',
     5404            15243 => 'Textbooks|Science & Nature|Geology',
     5405            15244 => 'Textbooks|Science & Nature|History',
     5406            15245 => 'Textbooks|Science & Nature|Life Sciences',
     5407            15246 => 'Textbooks|Science & Nature|Nature',
     5408            15247 => 'Textbooks|Science & Nature|Physics',
     5409            15248 => 'Textbooks|Science & Nature|Reference',
     5410            15249 => 'Textbooks|Social Science',
     5411            15250 => 'Textbooks|Social Science|Anthropology',
     5412            15251 => 'Textbooks|Social Science|Archaeology',
     5413            15252 => 'Textbooks|Social Science|Civics',
     5414            15253 => 'Textbooks|Social Science|Government',
     5415            15254 => 'Textbooks|Social Science|Social Studies',
     5416            15255 => 'Textbooks|Social Science|Social Welfare',
     5417            15256 => 'Textbooks|Social Science|Society',
     5418            15257 => 'Textbooks|Social Science|Society|African Studies',
     5419            15258 => 'Textbooks|Social Science|Society|American Studies',
     5420            15259 => 'Textbooks|Social Science|Society|Asia Pacific Studies',
     5421            15260 => 'Textbooks|Social Science|Society|Cross-Cultural Studies',
     5422            15261 => 'Textbooks|Social Science|Society|European Studies',
     5423            15262 => 'Textbooks|Social Science|Society|Immigration & Emigration',
     5424            15263 => 'Textbooks|Social Science|Society|Indigenous Studies',
     5425            15264 => 'Textbooks|Social Science|Society|Latin & Caribbean Studies',
     5426            15265 => 'Textbooks|Social Science|Society|Middle Eastern Studies',
     5427            15266 => 'Textbooks|Social Science|Society|Race & Ethnicity Studies',
     5428            15267 => 'Textbooks|Social Science|Society|Sexuality Studies',
     5429            15268 => "Textbooks|Social Science|Society|Women's Studies",
     5430            15269 => 'Textbooks|Social Science|Sociology',
     5431            15270 => 'Textbooks|Sports & Outdoors',
     5432            15271 => 'Textbooks|Sports & Outdoors|Baseball',
     5433            15272 => 'Textbooks|Sports & Outdoors|Basketball',
     5434            15273 => 'Textbooks|Sports & Outdoors|Coaching',
     5435            15274 => 'Textbooks|Sports & Outdoors|Equestrian',
     5436            15275 => 'Textbooks|Sports & Outdoors|Extreme Sports',
     5437            15276 => 'Textbooks|Sports & Outdoors|Football',
     5438            15277 => 'Textbooks|Sports & Outdoors|Golf',
     5439            15278 => 'Textbooks|Sports & Outdoors|Hockey',
     5440            15279 => 'Textbooks|Sports & Outdoors|Motor Sports',
     5441            15280 => 'Textbooks|Sports & Outdoors|Mountaineering',
     5442            15281 => 'Textbooks|Sports & Outdoors|Outdoors',
     5443            15282 => 'Textbooks|Sports & Outdoors|Racket Sports',
     5444            15283 => 'Textbooks|Sports & Outdoors|Reference',
     5445            15284 => 'Textbooks|Sports & Outdoors|Soccer',
     5446            15285 => 'Textbooks|Sports & Outdoors|Training',
     5447            15286 => 'Textbooks|Sports & Outdoors|Water Sports',
     5448            15287 => 'Textbooks|Sports & Outdoors|Winter Sports',
     5449            15288 => 'Textbooks|Teaching & Learning',
     5450            15289 => 'Textbooks|Teaching & Learning|Adult Education',
     5451            15290 => 'Textbooks|Teaching & Learning|Curriculum & Teaching',
     5452            15291 => 'Textbooks|Teaching & Learning|Educational Leadership',
     5453            15292 => 'Textbooks|Teaching & Learning|Educational Technology',
     5454            15293 => 'Textbooks|Teaching & Learning|Family & Childcare',
     5455            15294 => 'Textbooks|Teaching & Learning|Information & Library Science',
     5456            15295 => 'Textbooks|Teaching & Learning|Learning Resources',
     5457            15296 => 'Textbooks|Teaching & Learning|Psychology & Research',
     5458            15297 => 'Textbooks|Teaching & Learning|Special Education',
     5459            15298 => 'Textbooks|Travel & Adventure',
     5460            15299 => 'Textbooks|Travel & Adventure|Africa',
     5461            15300 => 'Textbooks|Travel & Adventure|Americas',
     5462            15301 => 'Textbooks|Travel & Adventure|Americas|Canada',
     5463            15302 => 'Textbooks|Travel & Adventure|Americas|Latin America',
     5464            15303 => 'Textbooks|Travel & Adventure|Americas|United States',
     5465            15304 => 'Textbooks|Travel & Adventure|Asia',
     5466            15305 => 'Textbooks|Travel & Adventure|Caribbean',
     5467            15306 => 'Textbooks|Travel & Adventure|Essays & Memoirs',
     5468            15307 => 'Textbooks|Travel & Adventure|Europe',
     5469            15308 => 'Textbooks|Travel & Adventure|Middle East',
     5470            15309 => 'Textbooks|Travel & Adventure|Oceania',
     5471            15310 => 'Textbooks|Travel & Adventure|Specialty Travel',
     5472            15311 => 'Textbooks|Comics & Graphic Novels|Comics',
     5473            15312 => 'Textbooks|Reference|Manuals',
     5474            16001 => 'App Store|Stickers|Emoji & Expressions',
     5475            16003 => 'App Store|Stickers|Animals & Nature',
     5476            16005 => 'App Store|Stickers|Art',
     5477            16006 => 'App Store|Stickers|Celebrations',
     5478            16007 => 'App Store|Stickers|Celebrities',
     5479            16008 => 'App Store|Stickers|Comics & Cartoons',
     5480            16009 => 'App Store|Stickers|Eating & Drinking',
     5481            16010 => 'App Store|Stickers|Gaming',
     5482            16014 => 'App Store|Stickers|Movies & TV',
     5483            16015 => 'App Store|Stickers|Music',
     5484            16017 => 'App Store|Stickers|People',
     5485            16019 => 'App Store|Stickers|Places & Objects',
     5486            16021 => 'App Store|Stickers|Sports & Activities',
     5487            16025 => 'App Store|Stickers|Kids & Family',
     5488            16026 => 'App Store|Stickers|Fashion',
     5489            100000 => 'Music|Christian & Gospel',
     5490            100001 => 'Music|Classical|Art Song',
     5491            100002 => 'Music|Classical|Brass & Woodwinds',
     5492            100003 => 'Music|Classical|Solo Instrumental',
     5493            100004 => 'Music|Classical|Contemporary Era',
     5494            100005 => 'Music|Classical|Oratorio',
     5495            100006 => 'Music|Classical|Cantata',
     5496            100007 => 'Music|Classical|Electronic',
     5497            100008 => 'Music|Classical|Sacred',
     5498            100009 => 'Music|Classical|Guitar',
     5499            100010 => 'Music|Classical|Piano',
     5500            100011 => 'Music|Classical|Violin',
     5501            100012 => 'Music|Classical|Cello',
     5502            100013 => 'Music|Classical|Percussion',
     5503            100014 => 'Music|Electronic|Dubstep',
     5504            100015 => 'Music|Electronic|Bass',
     5505            100016 => 'Music|Hip-Hop/Rap|UK Hip-Hop',
     5506            100017 => 'Music|Reggae|Lovers Rock',
     5507            100018 => 'Music|Alternative|EMO',
     5508            100019 => 'Music|Alternative|Pop Punk',
     5509            100020 => 'Music|Alternative|Indie Pop',
     5510            100021 => 'Music|New Age|Yoga',
     5511            100022 => 'Music|Pop|Tribute',
     5512            100023 => 'Music|Pop|Shows',
     5513            100024 => 'Music|Cuban',
     5514            100025 => 'Music|Cuban|Mambo',
     5515            100026 => 'Music|Cuban|Chachacha',
     5516            100027 => 'Music|Cuban|Guajira',
     5517            100028 => 'Music|Cuban|Son',
     5518            100029 => 'Music|Cuban|Bolero',
     5519            100030 => 'Music|Cuban|Guaracha',
     5520            100031 => 'Music|Cuban|Timba',
     5521            100032 => 'Music|Soundtrack|Video Game',
     5522            100033 => 'Music|Indian|Regional Indian|Punjabi|Punjabi Pop',
     5523            100034 => 'Music|Indian|Regional Indian|Bengali|Rabindra Sangeet',
     5524            100035 => 'Music|Indian|Regional Indian|Malayalam',
     5525            100036 => 'Music|Indian|Regional Indian|Kannada',
     5526            100037 => 'Music|Indian|Regional Indian|Marathi',
     5527            100038 => 'Music|Indian|Regional Indian|Gujarati',
     5528            100039 => 'Music|Indian|Regional Indian|Assamese',
     5529            100040 => 'Music|Indian|Regional Indian|Bhojpuri',
     5530            100041 => 'Music|Indian|Regional Indian|Haryanvi',
     5531            100042 => 'Music|Indian|Regional Indian|Odia',
     5532            100043 => 'Music|Indian|Regional Indian|Rajasthani',
     5533            100044 => 'Music|Indian|Regional Indian|Urdu',
     5534            100045 => 'Music|Indian|Regional Indian|Punjabi',
     5535            100046 => 'Music|Indian|Regional Indian|Bengali',
     5536            100047 => 'Music|Indian|Indian Classical|Carnatic Classical',
     5537            100048 => 'Music|Indian|Indian Classical|Hindustani Classical',
     5538            100049 => 'Music|African|Afro House',
     5539            100050 => 'Music|African|Afro Soul',
     5540            100051 => 'Music|African|Afrobeats',
     5541            100052 => 'Music|African|Benga',
     5542            100053 => 'Music|African|Bongo-Flava',
     5543            100054 => 'Music|African|Coupe-Decale',
     5544            100055 => 'Music|African|Gqom',
     5545            100056 => 'Music|African|Highlife',
     5546            100057 => 'Music|African|Kuduro',
     5547            100058 => 'Music|African|Kizomba',
     5548            100059 => 'Music|African|Kwaito',
     5549            100060 => 'Music|African|Mbalax',
     5550            100061 => 'Music|African|Ndombolo',
     5551            100062 => 'Music|African|Shangaan Electro',
     5552            100063 => 'Music|African|Soukous',
     5553            100064 => 'Music|African|Taarab',
     5554            100065 => 'Music|African|Zouglou',
     5555            100066 => 'Music|Turkish|Ozgun',
     5556            100067 => 'Music|Turkish|Fantezi',
     5557            100068 => 'Music|Turkish|Religious',
     5558            100069 => 'Music|Pop|Turkish Pop',
     5559            100070 => 'Music|Rock|Turkish Rock',
     5560            100071 => 'Music|Alternative|Turkish Alternative',
     5561            100072 => 'Music|Hip-Hop/Rap|Turkish Hip-Hop/Rap',
     5562            100073 => 'Music|African|Maskandi',
     5563            100074 => 'Music|Russian|Russian Romance',
     5564            100075 => 'Music|Russian|Russian Bard',
     5565            100076 => 'Music|Russian|Russian Pop',
     5566            100077 => 'Music|Russian|Russian Rock',
     5567            100078 => 'Music|Russian|Russian Hip-Hop',
     5568            100079 => 'Music|Arabic|Levant',
     5569            100080 => 'Music|Arabic|Levant|Dabke',
     5570            100081 => 'Music|Arabic|Maghreb Rai',
     5571            100082 => 'Music|Arabic|Khaleeji|Khaleeji Jalsat',
     5572            100083 => 'Music|Arabic|Khaleeji|Khaleeji Shailat',
     5573            100084 => 'Music|Tarab',
     5574            100085 => 'Music|Tarab|Iraqi Tarab',
     5575            100086 => 'Music|Tarab|Egyptian Tarab',
     5576            100087 => 'Music|Tarab|Khaleeji Tarab',
     5577            100088 => 'Music|Pop|Levant Pop',
     5578            100089 => 'Music|Pop|Iraqi Pop',
     5579            100090 => 'Music|Pop|Egyptian Pop',
     5580            100091 => 'Music|Pop|Maghreb Pop',
     5581            100092 => 'Music|Pop|Khaleeji Pop',
     5582            100093 => 'Music|Hip-Hop/Rap|Levant Hip-Hop',
     5583            100094 => 'Music|Hip-Hop/Rap|Egyptian Hip-Hop',
     5584            100095 => 'Music|Hip-Hop/Rap|Maghreb Hip-Hop',
     5585            100096 => 'Music|Hip-Hop/Rap|Khaleeji Hip-Hop',
     5586            100097 => 'Music|Alternative|Indie Levant',
     5587            100098 => 'Music|Alternative|Indie Egyptian',
     5588            100099 => 'Music|Alternative|Indie Maghreb',
     5589            100100 => 'Music|Electronic|Levant Electronic',
     5590            100101 => "Music|Electronic|Electro-Cha'abi",
     5591            100102 => 'Music|Electronic|Maghreb Electronic',
     5592            100103 => 'Music|Folk|Iraqi Folk',
     5593            100104 => 'Music|Folk|Khaleeji Folk',
     5594            100105 => 'Music|Dance|Maghreb Dance',
     5595            40000000 => 'iTunes U',
     5596            40000001 => 'iTunes U|Business & Economics',
     5597            40000002 => 'iTunes U|Business & Economics|Economics',
     5598            40000003 => 'iTunes U|Business & Economics|Finance',
     5599            40000004 => 'iTunes U|Business & Economics|Hospitality',
     5600            40000005 => 'iTunes U|Business & Economics|Management',
     5601            40000006 => 'iTunes U|Business & Economics|Marketing',
     5602            40000007 => 'iTunes U|Business & Economics|Personal Finance',
     5603            40000008 => 'iTunes U|Business & Economics|Real Estate',
     5604            40000009 => 'iTunes U|Engineering',
     5605            40000010 => 'iTunes U|Engineering|Chemical & Petroleum Engineering',
     5606            40000011 => 'iTunes U|Engineering|Civil Engineering',
     5607            40000012 => 'iTunes U|Engineering|Computer Science',
     5608            40000013 => 'iTunes U|Engineering|Electrical Engineering',
     5609            40000014 => 'iTunes U|Engineering|Environmental Engineering',
     5610            40000015 => 'iTunes U|Engineering|Mechanical Engineering',
     5611            40000016 => 'iTunes U|Music, Art, & Design',
     5612            40000017 => 'iTunes U|Music, Art, & Design|Architecture',
     5613            40000019 => 'iTunes U|Music, Art, & Design|Art History',
     5614            40000020 => 'iTunes U|Music, Art, & Design|Dance',
     5615            40000021 => 'iTunes U|Music, Art, & Design|Film',
     5616            40000022 => 'iTunes U|Music, Art, & Design|Design',
     5617            40000023 => 'iTunes U|Music, Art, & Design|Interior Design',
     5618            40000024 => 'iTunes U|Music, Art, & Design|Music',
     5619            40000025 => 'iTunes U|Music, Art, & Design|Theater',
     5620            40000026 => 'iTunes U|Health & Medicine',
     5621            40000027 => 'iTunes U|Health & Medicine|Anatomy & Physiology',
     5622            40000028 => 'iTunes U|Health & Medicine|Behavioral Science',
     5623            40000029 => 'iTunes U|Health & Medicine|Dentistry',
     5624            40000030 => 'iTunes U|Health & Medicine|Diet & Nutrition',
     5625            40000031 => 'iTunes U|Health & Medicine|Emergency Medicine',
     5626            40000032 => 'iTunes U|Health & Medicine|Genetics',
     5627            40000033 => 'iTunes U|Health & Medicine|Gerontology',
     5628            40000034 => 'iTunes U|Health & Medicine|Health & Exercise Science',
     5629            40000035 => 'iTunes U|Health & Medicine|Immunology',
     5630            40000036 => 'iTunes U|Health & Medicine|Neuroscience',
     5631            40000037 => 'iTunes U|Health & Medicine|Pharmacology & Toxicology',
     5632            40000038 => 'iTunes U|Health & Medicine|Psychiatry',
     5633            40000039 => 'iTunes U|Health & Medicine|Global Health',
     5634            40000040 => 'iTunes U|Health & Medicine|Radiology',
     5635            40000041 => 'iTunes U|History',
     5636            40000042 => 'iTunes U|History|Ancient History',
     5637            40000043 => 'iTunes U|History|Medieval History',
     5638            40000044 => 'iTunes U|History|Military History',
     5639            40000045 => 'iTunes U|History|Modern History',
     5640            40000046 => 'iTunes U|History|African History',
     5641            40000047 => 'iTunes U|History|Asia-Pacific History',
     5642            40000048 => 'iTunes U|History|European History',
     5643            40000049 => 'iTunes U|History|Middle Eastern History',
     5644            40000050 => 'iTunes U|History|North American History',
     5645            40000051 => 'iTunes U|History|South American History',
     5646            40000053 => 'iTunes U|Communications & Journalism',
     5647            40000054 => 'iTunes U|Philosophy',
     5648            40000055 => 'iTunes U|Religion & Spirituality',
     5649            40000056 => 'iTunes U|Languages',
     5650            40000057 => 'iTunes U|Languages|African Languages',
     5651            40000058 => 'iTunes U|Languages|Ancient Languages',
     5652            40000061 => 'iTunes U|Languages|English',
     5653            40000063 => 'iTunes U|Languages|French',
     5654            40000064 => 'iTunes U|Languages|German',
     5655            40000065 => 'iTunes U|Languages|Italian',
     5656            40000066 => 'iTunes U|Languages|Linguistics',
     5657            40000068 => 'iTunes U|Languages|Spanish',
     5658            40000069 => 'iTunes U|Languages|Speech Pathology',
     5659            40000070 => 'iTunes U|Writing & Literature',
     5660            40000071 => 'iTunes U|Writing & Literature|Anthologies',
     5661            40000072 => 'iTunes U|Writing & Literature|Biography',
     5662            40000073 => 'iTunes U|Writing & Literature|Classics',
     5663            40000074 => 'iTunes U|Writing & Literature|Literary Criticism',
     5664            40000075 => 'iTunes U|Writing & Literature|Fiction',
     5665            40000076 => 'iTunes U|Writing & Literature|Poetry',
     5666            40000077 => 'iTunes U|Mathematics',
     5667            40000078 => 'iTunes U|Mathematics|Advanced Mathematics',
     5668            40000079 => 'iTunes U|Mathematics|Algebra',
     5669            40000080 => 'iTunes U|Mathematics|Arithmetic',
     5670            40000081 => 'iTunes U|Mathematics|Calculus',
     5671            40000082 => 'iTunes U|Mathematics|Geometry',
     5672            40000083 => 'iTunes U|Mathematics|Statistics',
     5673            40000084 => 'iTunes U|Science',
     5674            40000085 => 'iTunes U|Science|Agricultural',
     5675            40000086 => 'iTunes U|Science|Astronomy',
     5676            40000087 => 'iTunes U|Science|Atmosphere',
     5677            40000088 => 'iTunes U|Science|Biology',
     5678            40000089 => 'iTunes U|Science|Chemistry',
     5679            40000090 => 'iTunes U|Science|Ecology',
     5680            40000091 => 'iTunes U|Science|Geography',
     5681            40000092 => 'iTunes U|Science|Geology',
     5682            40000093 => 'iTunes U|Science|Physics',
     5683            40000094 => 'iTunes U|Social Science',
     5684            40000095 => 'iTunes U|Law & Politics|Law',
     5685            40000096 => 'iTunes U|Law & Politics|Political Science',
     5686            40000097 => 'iTunes U|Law & Politics|Public Administration',
     5687            40000098 => 'iTunes U|Social Science|Psychology',
     5688            40000099 => 'iTunes U|Social Science|Social Welfare',
     5689            40000100 => 'iTunes U|Social Science|Sociology',
     5690            40000101 => 'iTunes U|Society',
     5691            40000103 => 'iTunes U|Society|Asia Pacific Studies',
     5692            40000104 => 'iTunes U|Society|European Studies',
     5693            40000105 => 'iTunes U|Society|Indigenous Studies',
     5694            40000106 => 'iTunes U|Society|Latin & Caribbean Studies',
     5695            40000107 => 'iTunes U|Society|Middle Eastern Studies',
     5696            40000108 => "iTunes U|Society|Women's Studies",
     5697            40000109 => 'iTunes U|Teaching & Learning',
     5698            40000110 => 'iTunes U|Teaching & Learning|Curriculum & Teaching',
     5699            40000111 => 'iTunes U|Teaching & Learning|Educational Leadership',
     5700            40000112 => 'iTunes U|Teaching & Learning|Family & Childcare',
     5701            40000113 => 'iTunes U|Teaching & Learning|Learning Resources',
     5702            40000114 => 'iTunes U|Teaching & Learning|Psychology & Research',
     5703            40000115 => 'iTunes U|Teaching & Learning|Special Education',
     5704            40000116 => 'iTunes U|Music, Art, & Design|Culinary Arts',
     5705            40000117 => 'iTunes U|Music, Art, & Design|Fashion',
     5706            40000118 => 'iTunes U|Music, Art, & Design|Media Arts',
     5707            40000119 => 'iTunes U|Music, Art, & Design|Photography',
     5708            40000120 => 'iTunes U|Music, Art, & Design|Visual Art',
     5709            40000121 => 'iTunes U|Business & Economics|Entrepreneurship',
     5710            40000122 => 'iTunes U|Communications & Journalism|Broadcasting',
     5711            40000123 => 'iTunes U|Communications & Journalism|Digital Media',
     5712            40000124 => 'iTunes U|Communications & Journalism|Journalism',
     5713            40000125 => 'iTunes U|Communications & Journalism|Photojournalism',
     5714            40000126 => 'iTunes U|Communications & Journalism|Print',
     5715            40000127 => 'iTunes U|Communications & Journalism|Speech',
     5716            40000128 => 'iTunes U|Communications & Journalism|Writing',
     5717            40000129 => 'iTunes U|Health & Medicine|Nursing',
     5718            40000130 => 'iTunes U|Languages|Arabic',
     5719            40000131 => 'iTunes U|Languages|Chinese',
     5720            40000132 => 'iTunes U|Languages|Hebrew',
     5721            40000133 => 'iTunes U|Languages|Hindi',
     5722            40000134 => 'iTunes U|Languages|Indigenous Languages',
     5723            40000135 => 'iTunes U|Languages|Japanese',
     5724            40000136 => 'iTunes U|Languages|Korean',
     5725            40000137 => 'iTunes U|Languages|Other Languages',
     5726            40000138 => 'iTunes U|Languages|Portuguese',
     5727            40000139 => 'iTunes U|Languages|Russian',
     5728            40000140 => 'iTunes U|Law & Politics',
     5729            40000141 => 'iTunes U|Law & Politics|Foreign Policy & International Relations',
     5730            40000142 => 'iTunes U|Law & Politics|Local Governments',
     5731            40000143 => 'iTunes U|Law & Politics|National Governments',
     5732            40000144 => 'iTunes U|Law & Politics|World Affairs',
     5733            40000145 => 'iTunes U|Writing & Literature|Comparative Literature',
     5734            40000146 => 'iTunes U|Philosophy|Aesthetics',
     5735            40000147 => 'iTunes U|Philosophy|Epistemology',
     5736            40000148 => 'iTunes U|Philosophy|Ethics',
     5737            40000149 => 'iTunes U|Philosophy|Metaphysics',
     5738            40000150 => 'iTunes U|Philosophy|Political Philosophy',
     5739            40000151 => 'iTunes U|Philosophy|Logic',
     5740            40000152 => 'iTunes U|Philosophy|Philosophy of Language',
     5741            40000153 => 'iTunes U|Philosophy|Philosophy of Religion',
     5742            40000154 => 'iTunes U|Social Science|Archaeology',
     5743            40000155 => 'iTunes U|Social Science|Anthropology',
     5744            40000156 => 'iTunes U|Religion & Spirituality|Buddhism',
     5745            40000157 => 'iTunes U|Religion & Spirituality|Christianity',
     5746            40000158 => 'iTunes U|Religion & Spirituality|Comparative Religion',
     5747            40000159 => 'iTunes U|Religion & Spirituality|Hinduism',
     5748            40000160 => 'iTunes U|Religion & Spirituality|Islam',
     5749            40000161 => 'iTunes U|Religion & Spirituality|Judaism',
     5750            40000162 => 'iTunes U|Religion & Spirituality|Other Religions',
     5751            40000163 => 'iTunes U|Religion & Spirituality|Spirituality',
     5752            40000164 => 'iTunes U|Science|Environment',
     5753            40000165 => 'iTunes U|Society|African Studies',
     5754            40000166 => 'iTunes U|Society|American Studies',
     5755            40000167 => 'iTunes U|Society|Cross-cultural Studies',
     5756            40000168 => 'iTunes U|Society|Immigration & Emigration',
     5757            40000169 => 'iTunes U|Society|Race & Ethnicity Studies',
     5758            40000170 => 'iTunes U|Society|Sexuality Studies',
     5759            40000171 => 'iTunes U|Teaching & Learning|Educational Technology',
     5760            40000172 => 'iTunes U|Teaching & Learning|Information/Library Science',
     5761            40000173 => 'iTunes U|Languages|Dutch',
     5762            40000174 => 'iTunes U|Languages|Luxembourgish',
     5763            40000175 => 'iTunes U|Languages|Swedish',
     5764            40000176 => 'iTunes U|Languages|Norwegian',
     5765            40000177 => 'iTunes U|Languages|Finnish',
     5766            40000178 => 'iTunes U|Languages|Danish',
     5767            40000179 => 'iTunes U|Languages|Polish',
     5768            40000180 => 'iTunes U|Languages|Turkish',
     5769            40000181 => 'iTunes U|Languages|Flemish',
     5770            50000024 => 'Audiobooks',
     5771            50000040 => 'Audiobooks|Fiction',
     5772            50000041 => 'Audiobooks|Arts & Entertainment',
     5773            50000042 => 'Audiobooks|Biographies & Memoirs',
     5774            50000043 => 'Audiobooks|Business & Personal Finance',
     5775            50000044 => 'Audiobooks|Kids & Young Adults',
     5776            50000045 => 'Audiobooks|Classics',
     5777            50000046 => 'Audiobooks|Comedy',
     5778            50000047 => 'Audiobooks|Drama & Poetry',
     5779            50000048 => 'Audiobooks|Speakers & Storytellers',
     5780            50000049 => 'Audiobooks|History',
     5781            50000050 => 'Audiobooks|Languages',
     5782            50000051 => 'Audiobooks|Mysteries & Thrillers',
     5783            50000052 => 'Audiobooks|Nonfiction',
     5784            50000053 => 'Audiobooks|Religion & Spirituality',
     5785            50000054 => 'Audiobooks|Science & Nature',
     5786            50000055 => 'Audiobooks|Sci Fi & Fantasy',
     5787            50000056 => 'Audiobooks|Self-Development',
     5788            50000057 => 'Audiobooks|Sports & Outdoors',
     5789            50000058 => 'Audiobooks|Technology',
     5790            50000059 => 'Audiobooks|Travel & Adventure',
     5791            50000061 => 'Music|Spoken Word',
     5792            50000063 => 'Music|Disney',
     5793            50000064 => 'Music|French Pop',
     5794            50000066 => 'Music|German Pop',
     5795            50000068 => 'Music|German Folk',
     5796            50000069 => 'Audiobooks|Romance',
     5797            50000070 => 'Audiobooks|Audiobooks Latino',
     5798            50000071 => 'Books|Comics & Graphic Novels|Manga|Action',
     5799            50000072 => 'Books|Comics & Graphic Novels|Manga|Comedy',
     5800            50000073 => 'Books|Comics & Graphic Novels|Manga|Erotica',
     5801            50000074 => 'Books|Comics & Graphic Novels|Manga|Fantasy',
     5802            50000075 => 'Books|Comics & Graphic Novels|Manga|Four Cell Manga',
     5803            50000076 => 'Books|Comics & Graphic Novels|Manga|Gay & Lesbian',
     5804            50000077 => 'Books|Comics & Graphic Novels|Manga|Hard-Boiled',
     5805            50000078 => 'Books|Comics & Graphic Novels|Manga|Heroes',
     5806            50000079 => 'Books|Comics & Graphic Novels|Manga|Historical Fiction',
     5807            50000080 => 'Books|Comics & Graphic Novels|Manga|Mecha',
     5808            50000081 => 'Books|Comics & Graphic Novels|Manga|Mystery',
     5809            50000082 => 'Books|Comics & Graphic Novels|Manga|Nonfiction',
     5810            50000083 => 'Books|Comics & Graphic Novels|Manga|Religious',
     5811            50000084 => 'Books|Comics & Graphic Novels|Manga|Romance',
     5812            50000085 => 'Books|Comics & Graphic Novels|Manga|Romantic Comedy',
     5813            50000086 => 'Books|Comics & Graphic Novels|Manga|Science Fiction',
     5814            50000087 => 'Books|Comics & Graphic Novels|Manga|Sports',
     5815            50000088 => 'Books|Fiction & Literature|Light Novels',
     5816            50000089 => 'Books|Comics & Graphic Novels|Manga|Horror',
     5817            50000090 => 'Books|Comics & Graphic Novels|Comics',
     5818            50000091 => 'Books|Romance|Multicultural',
     5819            50000092 => 'Audiobooks|Erotica',
     5820            50000093 => 'Audiobooks|Light Novels',
     5821        },
     5822    },
     5823    grup => { Name => 'Grouping', Avoid => 1 }, #10
    12925824    hdvd => { #10
    12935825        Name => 'HDVideo',
     5826        Format => 'int8u', #24
     5827        Writable => 'int8s', #27
    12945828        PrintConv => { 0 => 'No', 1 => 'Yes' },
    12955829    },
     
    12985832    pcst => { #7
    12995833        Name => 'Podcast',
     5834        Format => 'int8u', #23
     5835        Writable => 'int8s', #27
    13005836        PrintConv => { 0 => 'No', 1 => 'Yes' },
    13015837    },
     
    13045840        Name => 'PlayListID',
    13055841        Format => 'int8u',  # actually int64u, but split it up
     5842        Writable => 'int32s', #27
    13065843    },
    13075844    purd => 'PurchaseDate', #7
     
    13095846    rtng => { #10
    13105847        Name => 'Rating',
     5848        Format => 'int8u', #23
     5849        Writable => 'int8s', #27
    13115850        PrintConv => {
    13125851            0 => 'none',
     5852            1 => 'Explicit',
    13135853            2 => 'Clean',
    1314             4 => 'Explicit',
     5854            4 => 'Explicit (old)',
    13155855        },
    13165856    },
     
    13185858        Name => 'AppleStoreCountry',
    13195859        Format => 'int32u',
    1320         PrintConv => {
    1321             143460 => 'Australia',
    1322             143445 => 'Austria',
    1323             143446 => 'Belgium',
    1324             143455 => 'Canada',
    1325             143458 => 'Denmark',
    1326             143447 => 'Finland',
    1327             143442 => 'France',
    1328             143443 => 'Germany',
    1329             143448 => 'Greece',
    1330             143449 => 'Ireland',
    1331             143450 => 'Italy',
    1332             143462 => 'Japan',
    1333             143451 => 'Luxembourg',
    1334             143452 => 'Netherlands',
    1335             143461 => 'New Zealand',
    1336             143457 => 'Norway',
    1337             143453 => 'Portugal',
    1338             143454 => 'Spain',
    1339             143456 => 'Sweden',
    1340             143459 => 'Switzerland',
    1341             143444 => 'United Kingdom',
    1342             143441 => 'United States',
     5860        Writable => 'int32s', #27
     5861        SeparateTable => 1,
     5862        PrintConv => { #21
     5863            143441 => 'United States', # US
     5864            143442 => 'France', # FR
     5865            143443 => 'Germany', # DE
     5866            143444 => 'United Kingdom', # GB
     5867            143445 => 'Austria', # AT
     5868            143446 => 'Belgium', # BE
     5869            143447 => 'Finland', # FI
     5870            143448 => 'Greece', # GR
     5871            143449 => 'Ireland', # IE
     5872            143450 => 'Italy', # IT
     5873            143451 => 'Luxembourg', # LU
     5874            143452 => 'Netherlands', # NL
     5875            143453 => 'Portugal', # PT
     5876            143454 => 'Spain', # ES
     5877            143455 => 'Canada', # CA
     5878            143456 => 'Sweden', # SE
     5879            143457 => 'Norway', # NO
     5880            143458 => 'Denmark', # DK
     5881            143459 => 'Switzerland', # CH
     5882            143460 => 'Australia', # AU
     5883            143461 => 'New Zealand', # NZ
     5884            143462 => 'Japan', # JP
     5885            143463 => 'Hong Kong', # HK
     5886            143464 => 'Singapore', # SG
     5887            143465 => 'China', # CN
     5888            143466 => 'Republic of Korea', # KR
     5889            143467 => 'India', # IN
     5890            143468 => 'Mexico', # MX
     5891            143469 => 'Russia', # RU
     5892            143470 => 'Taiwan', # TW
     5893            143471 => 'Vietnam', # VN
     5894            143472 => 'South Africa', # ZA
     5895            143473 => 'Malaysia', # MY
     5896            143474 => 'Philippines', # PH
     5897            143475 => 'Thailand', # TH
     5898            143476 => 'Indonesia', # ID
     5899            143477 => 'Pakistan', # PK
     5900            143478 => 'Poland', # PL
     5901            143479 => 'Saudi Arabia', # SA
     5902            143480 => 'Turkey', # TR
     5903            143481 => 'United Arab Emirates', # AE
     5904            143482 => 'Hungary', # HU
     5905            143483 => 'Chile', # CL
     5906            143484 => 'Nepal', # NP
     5907            143485 => 'Panama', # PA
     5908            143486 => 'Sri Lanka', # LK
     5909            143487 => 'Romania', # RO
     5910            143489 => 'Czech Republic', # CZ
     5911            143491 => 'Israel', # IL
     5912            143492 => 'Ukraine', # UA
     5913            143493 => 'Kuwait', # KW
     5914            143494 => 'Croatia', # HR
     5915            143495 => 'Costa Rica', # CR
     5916            143496 => 'Slovakia', # SK
     5917            143497 => 'Lebanon', # LB
     5918            143498 => 'Qatar', # QA
     5919            143499 => 'Slovenia', # SI
     5920            143501 => 'Colombia', # CO
     5921            143502 => 'Venezuela', # VE
     5922            143503 => 'Brazil', # BR
     5923            143504 => 'Guatemala', # GT
     5924            143505 => 'Argentina', # AR
     5925            143506 => 'El Salvador', # SV
     5926            143507 => 'Peru', # PE
     5927            143508 => 'Dominican Republic', # DO
     5928            143509 => 'Ecuador', # EC
     5929            143510 => 'Honduras', # HN
     5930            143511 => 'Jamaica', # JM
     5931            143512 => 'Nicaragua', # NI
     5932            143513 => 'Paraguay', # PY
     5933            143514 => 'Uruguay', # UY
     5934            143515 => 'Macau', # MO
     5935            143516 => 'Egypt', # EG
     5936            143517 => 'Kazakhstan', # KZ
     5937            143518 => 'Estonia', # EE
     5938            143519 => 'Latvia', # LV
     5939            143520 => 'Lithuania', # LT
     5940            143521 => 'Malta', # MT
     5941            143523 => 'Moldova', # MD
     5942            143524 => 'Armenia', # AM
     5943            143525 => 'Botswana', # BW
     5944            143526 => 'Bulgaria', # BG
     5945            143528 => 'Jordan', # JO
     5946            143529 => 'Kenya', # KE
     5947            143530 => 'Macedonia', # MK
     5948            143531 => 'Madagascar', # MG
     5949            143532 => 'Mali', # ML
     5950            143533 => 'Mauritius', # MU
     5951            143534 => 'Niger', # NE
     5952            143535 => 'Senegal', # SN
     5953            143536 => 'Tunisia', # TN
     5954            143537 => 'Uganda', # UG
     5955            143538 => 'Anguilla', # AI
     5956            143539 => 'Bahamas', # BS
     5957            143540 => 'Antigua and Barbuda', # AG
     5958            143541 => 'Barbados', # BB
     5959            143542 => 'Bermuda', # BM
     5960            143543 => 'British Virgin Islands', # VG
     5961            143544 => 'Cayman Islands', # KY
     5962            143545 => 'Dominica', # DM
     5963            143546 => 'Grenada', # GD
     5964            143547 => 'Montserrat', # MS
     5965            143548 => 'St. Kitts and Nevis', # KN
     5966            143549 => 'St. Lucia', # LC
     5967            143550 => 'St. Vincent and The Grenadines', # VC
     5968            143551 => 'Trinidad and Tobago', # TT
     5969            143552 => 'Turks and Caicos', # TC
     5970            143553 => 'Guyana', # GY
     5971            143554 => 'Suriname', # SR
     5972            143555 => 'Belize', # BZ
     5973            143556 => 'Bolivia', # BO
     5974            143557 => 'Cyprus', # CY
     5975            143558 => 'Iceland', # IS
     5976            143559 => 'Bahrain', # BH
     5977            143560 => 'Brunei Darussalam', # BN
     5978            143561 => 'Nigeria', # NG
     5979            143562 => 'Oman', # OM
     5980            143563 => 'Algeria', # DZ
     5981            143564 => 'Angola', # AO
     5982            143565 => 'Belarus', # BY
     5983            143566 => 'Uzbekistan', # UZ
     5984            143568 => 'Azerbaijan', # AZ
     5985            143571 => 'Yemen', # YE
     5986            143572 => 'Tanzania', # TZ
     5987            143573 => 'Ghana', # GH
     5988            143575 => 'Albania', # AL
     5989            143576 => 'Benin', # BJ
     5990            143577 => 'Bhutan', # BT
     5991            143578 => 'Burkina Faso', # BF
     5992            143579 => 'Cambodia', # KH
     5993            143580 => 'Cape Verde', # CV
     5994            143581 => 'Chad', # TD
     5995            143582 => 'Republic of the Congo', # CG
     5996            143583 => 'Fiji', # FJ
     5997            143584 => 'Gambia', # GM
     5998            143585 => 'Guinea-Bissau', # GW
     5999            143586 => 'Kyrgyzstan', # KG
     6000            143587 => "Lao People's Democratic Republic", # LA
     6001            143588 => 'Liberia', # LR
     6002            143589 => 'Malawi', # MW
     6003            143590 => 'Mauritania', # MR
     6004            143591 => 'Federated States of Micronesia', # FM
     6005            143592 => 'Mongolia', # MN
     6006            143593 => 'Mozambique', # MZ
     6007            143594 => 'Namibia', # NA
     6008            143595 => 'Palau', # PW
     6009            143597 => 'Papua New Guinea', # PG
     6010            143598 => 'Sao Tome and Principe', # ST (S&atilde;o Tom&eacute; and Pr&iacute;ncipe)
     6011            143599 => 'Seychelles', # SC
     6012            143600 => 'Sierra Leone', # SL
     6013            143601 => 'Solomon Islands', # SB
     6014            143602 => 'Swaziland', # SZ
     6015            143603 => 'Tajikistan', # TJ
     6016            143604 => 'Turkmenistan', # TM
     6017            143605 => 'Zimbabwe', # ZW
    13436018        },
    13446019    },
     
    13516026    stik => { #10
    13526027        Name => 'MediaType',
     6028        Format => 'int8u', #23
     6029        Writable => 'int8s', #27
     6030        PrintConvColumns => 2,
    13536031        PrintConv => { #(http://weblog.xanga.com/gryphondwb/615474010/iphone-ringtones---what-did-itunes-741-really-do.html)
    1354             0 => 'Movie',
     6032            0 => 'Movie (old)', #forum9059 (was Movie)
    13556033            1 => 'Normal (Music)',
    13566034            2 => 'Audiobook',
    13576035            5 => 'Whacked Bookmark',
    13586036            6 => 'Music Video',
    1359             9 => 'Short Film',
     6037            9 => 'Movie', #forum9059 (was Short Film)
    13606038            10 => 'TV Show',
    13616039            11 => 'Booklet',
    13626040            14 => 'Ringtone',
    1363         },
    1364     },
    1365     titl => 'Title',
     6041            21 => 'Podcast', #15
     6042            23 => 'iTunes U', #forum9059
     6043        },
     6044    },
     6045    rate => 'RatingPercent', #PH
     6046    titl => { Name => 'Title', Avoid => 1 },
    13666047    tven => 'TVEpisodeID', #7
    13676048    tves => { #7/10
    13686049        Name => 'TVEpisode',
    13696050        Format => 'int32u',
     6051        Writable => 'int32s', #27
    13706052    },
    13716053    tvnn => 'TVNetworkName', #7
     
    13766058    },
    13776059    yrrc => 'Year', #(ffmpeg source)
     6060    itnu => { #PH (iTunes 10.5)
     6061        Name => 'iTunesU',
     6062        Format => 'int8u', #27
     6063        Writable => 'int8s', #27
     6064        Description => 'iTunes U',
     6065        PrintConv => { 0 => 'No', 1 => 'Yes' },
     6066    },
     6067    #https://github.com/communitymedia/mediautilities/blob/master/src/net/sourceforge/jaad/mp4/boxes/BoxTypes.java
     6068    gshh => { Name => 'GoogleHostHeader',   Format => 'string' },
     6069    gspm => { Name => 'GooglePingMessage',  Format => 'string' },
     6070    gspu => { Name => 'GooglePingURL',      Format => 'string' },
     6071    gssd => { Name => 'GoogleSourceData',   Format => 'string' },
     6072    gsst => { Name => 'GoogleStartTime',    Format => 'string' },
     6073    gstd => {
     6074        Name => 'GoogleTrackDuration',
     6075        Format => 'string',
     6076        ValueConv => '$val / 1000',
     6077        ValueConvInv => '$val * 1000',
     6078        PrintConv => 'ConvertDuration($val)',
     6079        PrintConvInv => q{
     6080           $val =~ s/ s$//;
     6081           my @a = split /(:| days )/, $val;
     6082           my $sign = ($val =~ s/^-//) ? -1 : 1;
     6083           $a[0] += shift(@a) * 24 if @a == 4;
     6084           $a[0] += shift(@a) * 60 while @a > 1;
     6085           return $a[0] * $sign;
     6086        },
     6087    },
     6088
     6089    # atoms observed in AAX audiobooks (ref PH)
     6090    "\xa9cpy" => { Name => 'Copyright', Avoid => 1, Groups => { 2 => 'Author' } },
     6091    "\xa9pub" => 'Publisher',
     6092    "\xa9nrt" => 'Narrator',
     6093    '@pti' => 'ParentTitle', # (guess -- same as "\xa9nam")
     6094    '@PST' => 'ParentShortTitle', # (guess -- same as "\xa9nam")
     6095    '@ppi' => 'ParentProductID', # (guess -- same as 'prID')
     6096    '@sti' => 'ShortTitle', # (guess -- same as "\xa9nam")
     6097    prID => 'ProductID',
     6098    rldt => { Name => 'ReleaseDate', Groups => { 2 => 'Time' }},
     6099    CDEK => { Name => 'Unknown_CDEK', Unknown => 1 }, # eg: "B004ZMTFEG" - used in URL's ("asin=")
     6100    CDET => { Name => 'Unknown_CDET', Unknown => 1 }, # eg: "ADBL"
     6101    VERS => 'ProductVersion',
     6102    GUID => 'GUID',
     6103    AACR => { Name => 'Unknown_AACR', Unknown => 1 }, # eg: "CR!1T1H1QH6WX7T714G2BMFX3E9MC4S"
     6104    # ausr - 30 bytes (User Alias?)
     6105    "\xa9xyz" => { #PH (written by Google Photos)
     6106        Name => 'GPSCoordinates',
     6107        Groups => { 2 => 'Location' },
     6108        ValueConv => \&ConvertISO6709,
     6109        ValueConvInv => \&ConvInvISO6709,
     6110        PrintConv => \&PrintGPSCoordinates,
     6111        PrintConvInv => \&PrintInvGPSCoordinates,
     6112    },
     6113    # the following tags written by iTunes 12.5.1.21
     6114    # (ref https://www.ventismedia.com/mantis/view.php?id=14963
     6115    #  https://community.mp3tag.de/t/x-mp4-new-tag-problems/19488)
     6116    "\xa9wrk" => 'Work', #PH
     6117    "\xa9mvn" => 'MovementName', #PH
     6118    "\xa9mvi" => { #PH
     6119        Name => 'MovementNumber',
     6120        Format => 'int16u', #27
     6121        Writable => 'int16s', #27
     6122    },
     6123    "\xa9mvc" => { #PH
     6124        Name => 'MovementCount',
     6125        Format => 'int16u', #27
     6126        Writable => 'int16s', #27
     6127    },
     6128    shwm => { #PH
     6129        Name => 'ShowMovement',
     6130        Format => 'int8u', #27
     6131        Writable => 'int8s', #27
     6132        PrintConv => { 0 => 'No', 1 => 'Yes' },
     6133    },
     6134);
     6135
     6136# tag decoded from timed face records
     6137%Image::ExifTool::QuickTime::FaceInfo = (
     6138    PROCESS_PROC => \&ProcessMOV,
     6139    GROUPS => { 2 => 'Video' },
     6140    crec => {
     6141        Name => 'FaceRec',
     6142        SubDirectory => {
     6143            TagTable => 'Image::ExifTool::QuickTime::FaceRec',
     6144        },
     6145    },
     6146);
     6147
     6148# tag decoded from timed face records
     6149%Image::ExifTool::QuickTime::FaceRec = (
     6150    PROCESS_PROC => \&ProcessMOV,
     6151    GROUPS => { 2 => 'Video' },
     6152    cits => {
     6153        Name => 'FaceItem',
     6154        SubDirectory => {
     6155            TagTable => 'Image::ExifTool::QuickTime::Keys',
     6156            ProcessProc => \&Process_mebx,
     6157        },
     6158    },
    13786159);
    13796160
    13806161# item list keys (ref PH)
    13816162%Image::ExifTool::QuickTime::Keys = (
    1382     PROCESS_PROC => \&Image::ExifTool::QuickTime::ProcessKeys,
     6163    PROCESS_PROC => \&ProcessKeys,
     6164    WRITE_PROC => \&WriteKeys,
     6165    CHECK_PROC => \&CheckQTValue,
     6166    VARS => { LONG_TAGS => 3 },
     6167    WRITABLE => 1,
     6168    # (not PREFERRED when writing)
     6169    GROUPS => { 1 => 'Keys' },
     6170    WRITE_GROUP => 'Keys',
     6171    LANG_INFO => \&GetLangInfo,
     6172    FORMAT => 'string',
    13836173    NOTES => q{
    1384         This directory contains a list of key names which are used to decode
    1385         ItemList tags written by the "mdta" handler.  The prefix of
    1386         "com.apple.quicktime." has been removed from all TagID's below.
     6174        This directory contains a list of key names which are used to decode tags
     6175        written by the "mdta" handler.  Also in this table are a few tags found in
     6176        timed metadata that are not yet writable by ExifTool.  The prefix of
     6177        "com.apple.quicktime." has been removed from the TagID's below.  These tags
     6178        support alternate languages in the same way as the
     6179        L<ItemList|Image::ExifTool::TagNames/QuickTime ItemList Tags> tags.  Note
     6180        that by default,
     6181        L<ItemList|Image::ExifTool::TagNames/QuickTime ItemList Tags> and
     6182        L<UserData|Image::ExifTool::TagNames/QuickTime UserData Tags> tags are
     6183        preferred when writing, so to create a tag when a same-named tag exists in
     6184        either of these tables, either the "Keys" location must be specified (eg.
     6185        C<-Keys:Author=Phil> on the command line), or the PREFERRED level must be
     6186        changed via L<the config file|../config.html#PREF>.
    13876187    },
    13886188    version     => 'Version',
     
    13966196        Name => 'CreationDate',
    13976197        Groups => { 2 => 'Time' },
     6198        Shift => 'Time',
    13986199        ValueConv => q{
    13996200            require Image::ExifTool::XMP;
     
    14026203            return $val;
    14036204        },
     6205        ValueConvInv => q{
     6206            require Image::ExifTool::XMP;
     6207            $val =  Image::ExifTool::XMP::FormatXMPDate($val);
     6208            $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon
     6209            return $val;
     6210        },
    14046211        PrintConv => '$self->ConvertDateTime($val)',
     6212        PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
    14056213    },
    14066214    description => { },
    14076215    director    => { },
     6216    displayname => { Name => 'DisplayName' },
     6217    title       => { }, #22
    14086218    genre       => { },
    14096219    information => { },
    14106220    keywords    => { },
     6221    producer    => { }, #22
    14116222    make        => { Name => 'Make',        Groups => { 2 => 'Camera' } },
    14126223    model       => { Name => 'Model',       Groups => { 2 => 'Camera' } },
     
    14186229        Name => 'FrameReadoutTime',
    14196230        ValueConv => '$val * 1e-6',
     6231        ValueConvInv => 'int($val * 1e6 + 0.5)',
    14206232        PrintConv => '$val * 1e6 . " microseconds"',
     6233        PrintConvInv => '$val =~ s/ .*//; $val * 1e-6',
    14216234    },
    14226235    'location.ISO6709' => {
     
    14246237        Groups => { 2 => 'Location' },
    14256238        ValueConv => \&ConvertISO6709,
     6239        ValueConvInv => \&ConvInvISO6709,
    14266240        PrintConv => \&PrintGPSCoordinates,
     6241        PrintConvInv => \&PrintInvGPSCoordinates,
    14276242    },
    14286243    'location.name' => { Name => 'LocationName', Groups => { 2 => 'Location' } },
     
    14416256        Name => 'LocationDate',
    14426257        Groups => { 2 => 'Time' },
     6258        Shift => 'Time',
    14436259        ValueConv => q{
    14446260            require Image::ExifTool::XMP;
     
    14476263            return $val;
    14486264        },
     6265        ValueConvInv => q{
     6266            require Image::ExifTool::XMP;
     6267            $val =  Image::ExifTool::XMP::FormatXMPDate($val);
     6268            $val =~ s/([-+]\d{2}):(\d{2})$/$1$2/; # remove time zone colon
     6269            return $val;
     6270        },
    14496271        PrintConv => '$self->ConvertDateTime($val)',
     6272        PrintConvInv => '$self->InverseDateTime($val,1)', # (add time zone if it didn't exist)
    14506273    },
    14516274    'direction.facing' => { Name => 'CameraDirection', Groups => { 2 => 'Location' } },
    1452     'direction.motion' => { Name => 'CameraMotion', Groups => { 2 => 'Location' } },
    1453     'location.body' => { Name => 'LocationBody', Groups => { 2 => 'Location' } },
     6275    'direction.motion' => { Name => 'CameraMotion',    Groups => { 2 => 'Location' } },
     6276    'location.body'    => { Name => 'LocationBody',    Groups => { 2 => 'Location' } },
    14546277    'player.version'                => 'PlayerVersion',
    14556278    'player.movie.visual.brightness'=> 'Brightness',
     
    14676290        PrintConv => { 0 => 'Off', 1 => 'On' },
    14686291    },
     6292    'rating.user'  => 'UserRating', # (Canon ELPH 510 HS)
     6293    'collection.user' => 'UserCollection', #22
     6294    'Encoded_With' => 'EncodedWith',
     6295#
     6296# the following tags aren't in the com.apple.quicktime namespace:
     6297#
     6298    'com.apple.photos.captureMode' => 'CaptureMode',
     6299    'com.android.version' => 'AndroidVersion',
     6300#
     6301# also seen
     6302#
     6303    # com.divergentmedia.clipwrap.model            ('NEX-FS700EK')
     6304    # com.divergentmedia.clipwrap.model1           ('49')
     6305    # com.divergentmedia.clipwrap.model2           ('0')
     6306    # com.divergentmedia.clipwrap.manufacturer     ('Sony')
     6307    # com.divergentmedia.clipwrap.originalDateTime ('2013/2/6 10:30:40+0200')
     6308#
     6309# seen in timed metadata (mebx), and added dynamically to the table
     6310# via SaveMetaKeys().  NOTE: these tags are not writable!
     6311#
     6312    # (mdta)com.apple.quicktime.video-orientation (dtyp=66, int16s)
     6313    'video-orientation' => { Name => 'VideoOrientation', Writable => 0 },
     6314    # (mdta)com.apple.quicktime.live-photo-info (dtyp=com.apple.quicktime.com.apple.quicktime.live-photo-info)
     6315    'live-photo-info' => {
     6316        Name => 'LivePhotoInfo',
     6317        Writable => 0,
     6318        # not sure what these values mean, but unpack them anyway - PH
     6319        # (ignore the fact that the "f" and "l" unpacks won't work on a big-endian machine)
     6320        ValueConv => 'join " ",unpack "VfVVf6c4lCCcclf4Vvv", $val',
     6321    },
     6322    # (mdta)com.apple.quicktime.still-image-time (dtyp=65, int8s)
     6323    'still-image-time' => { # (found in live photo)
     6324        Name => 'StillImageTime',
     6325        Writable => 0,
     6326        Notes => q{
     6327            this tag always has a value of -1; the time of the still image is obtained
     6328            from the associated SampleTime
     6329        },
     6330    },
     6331    # (mdta)com.apple.quicktime.detected-face (dtyp='com.apple.quicktime.detected-face')
     6332    'detected-face' => {
     6333        Name => 'FaceInfo',
     6334        Writable => 0,
     6335        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::FaceInfo' },
     6336    },
     6337    # ---- detected-face fields ( ----
     6338    # --> back here after a round trip through FaceInfo -> FaceRec -> FaceItem
     6339    # (fiel)com.apple.quicktime.detected-face.bounds (dtyp=80, float[8])
     6340    'detected-face.bounds' => {
     6341        Name => 'DetectedFaceBounds',
     6342        Writable => 0,
     6343        # round to a reasonable number of decimal places
     6344        PrintConv => 'my @a=split " ",$val;$_=int($_*1e6+.5)/1e6 foreach @a;join " ",@a',
     6345        PrintConvInv => '$val',
     6346    },
     6347    # (fiel)com.apple.quicktime.detected-face.face-id (dtyp=77, int32u)
     6348    'detected-face.face-id'    => { Name => 'DetectedFaceID',        Writable => 0 },
     6349    # (fiel)com.apple.quicktime.detected-face.roll-angle (dtyp=23, float)
     6350    'detected-face.roll-angle' => { Name => 'DetectedFaceRollAngle', Writable => 0 },
     6351    # (fiel)com.apple.quicktime.detected-face.yaw-angle (dtyp=23, float)
     6352    'detected-face.yaw-angle'  => { Name => 'DetectedFaceYawAngle',  Writable => 0 },
     6353#
     6354# seen in Apple ProRes RAW file
     6355#
     6356    # (mdta)com.apple.proapps.manufacturer (eg. "Sony")
     6357    # (mdta)com.apple.proapps.exif.{Exif}.FNumber (float, eg. 1.0)
     6358    # (mdta)org.smpte.rdd18.lens.irisfnumber (eg. "F1.0")
     6359    # (mdta)com.apple.proapps.exif.{Exif}.ShutterSpeedValue (float, eg. 1.006)
     6360    # (mdta)org.smpte.rdd18.camera.shutterspeed_angle (eg. "179.2deg")
     6361    # (mdta)org.smpte.rdd18.camera.neutraldensityfilterwheelsetting (eg. "ND1")
     6362    # (mdta)org.smpte.rdd18.camera.whitebalance (eg. "4300K")
     6363    # (mdta)com.apple.proapps.exif.{Exif}.ExposureIndex (float, eg. 4000)
     6364    # (mdta)org.smpte.rdd18.camera.isosensitivity (eg. "4000")
     6365    # (mdta)com.apple.proapps.image.{TIFF}.Make (eg. "Atmos")
     6366    # (mdta)com.apple.proapps.image.{TIFF}.Model (eg. "ShogunInferno")
     6367    # (mdta)com.apple.proapps.image.{TIFF}.Software (eg. "9.0")
    14696368);
    14706369
     
    14736372    PROCESS_PROC => \&ProcessMOV,
    14746373    GROUPS => { 2 => 'Audio' },
     6374    NOTES => q{
     6375        ExifTool will extract any iTunesInfo tags that exist, even if they are not
     6376        defined in this table.
     6377    },
    14756378    # 'mean'/'name'/'data' atoms form a triplet, but unfortunately
    1476     # I can't find any source for decoding 'data'.
     6379    # I haven't been able to find any documentation on this.
    14776380    # 'mean' is normally 'com.apple.iTunes'
    1478     # 'name' values: 'tool', 'iTunNORM' (volume normalization),
    1479     #   'iTunSMPB', 'iTunes_CDDB_IDs', 'iTunes_CDDB_TrackNumber'
    14806381    mean => {
    14816382        Name => 'Mean',
    1482         Unknown => 1,
     6383        # the 'Triplet' flag tells ProcessMOV() to generate
     6384        # a single tag from the mean/name/data triplet
     6385        Triplet => 1,
     6386        Hidden => 1,
    14836387    },
    14846388    name => {
    14856389        Name => 'Name',
    1486         Unknown => 1,
     6390        Triplet => 1,
     6391        Hidden => 1,
    14876392    },
    14886393    data => {
    14896394        Name => 'Data',
    1490         Flags => ['Binary','Unknown'],
     6395        Triplet => 1,
     6396        Hidden => 1,
     6397    },
     6398    # the tag ID's below are composed from "mean/name",
     6399    # but "mean/" is omitted if it is "com.apple.iTunes/":
     6400    'iTunMOVI' => {
     6401        Name => 'iTunMOVI',
     6402        SubDirectory => { TagTable => 'Image::ExifTool::PLIST::Main' },
     6403    },
     6404    'tool' => {
     6405        Name => 'iTunTool',
     6406        Description => 'iTunTool',
     6407        Format => 'int32u',
     6408        PrintConv => 'sprintf("0x%.8x",$val)',
     6409    },
     6410    'iTunEXTC' => {
     6411        Name => 'ContentRating',
     6412        Notes => 'standard | rating | score | reasons',
     6413        # eg. 'us-tv|TV-14|500|V', 'mpaa|PG-13|300|For violence and sexuality'
     6414        # (see http://shadowofged.blogspot.ca/2008/06/itunes-content-ratings.html)
     6415    },
     6416    'iTunNORM' => {
     6417        Name => 'VolumeNormalization',
     6418        PrintConv => '$val=~s/ 0+(\w)/ $1/g; $val=~s/^\s+//; $val',
     6419    },
     6420    'iTunSMPB' => {
     6421        Name => 'iTunSMPB',
     6422        Description => 'iTunSMPB',
     6423        # hex format, similar to iTunNORM, but 12 words instead of 10,
     6424        # and 4th word is 16 hex digits (all others are 8)
     6425        # (gives AAC encoder delay, ref http://code.google.com/p/l-smash/issues/detail?id=1)
     6426        PrintConv => '$val=~s/ 0+(\w)/ $1/g; $val=~s/^\s+//; $val',
     6427    },
     6428    # (CDDB = Compact Disc DataBase)
     6429    # iTunes_CDDB_1 = <CDDB1 disk ID>+<# tracks>+<logical block address for each track>...
     6430    'iTunes_CDDB_1' => 'CDDB1Info',
     6431    'iTunes_CDDB_TrackNumber' => 'CDDBTrackNumber',
     6432    'Encoding Params' => {
     6433        Name => 'EncodingParams',
     6434        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::EncodingParams' },
     6435    },
     6436    # also heard about 'iTunPGAP', but I haven't seen a sample
     6437    DISCNUMBER => 'DiscNumber', #PH
     6438    TRACKNUMBER => 'TrackNumber', #PH
     6439    popularimeter => 'Popularimeter', #PH
     6440);
     6441
     6442# iTunes audio encoding parameters
     6443# ref https://developer.apple.com/library/mac/#documentation/MusicAudio/Reference/AudioCodecServicesRef/Reference/reference.html
     6444%Image::ExifTool::QuickTime::EncodingParams = (
     6445    PROCESS_PROC => \&ProcessEncodingParams,
     6446    GROUPS => { 2 => 'Audio' },
     6447    # (I have commented out the ones that don't have integer values because they
     6448    #  probably don't appear, and definitely wouldn't work with current decoding - PH)
     6449
     6450    # global codec properties
     6451    #'lnam' => 'AudioCodecName',
     6452    #'lmak' => 'AudioCodecManufacturer',
     6453    #'lfor' => 'AudioCodecFormat',
     6454    'vpk?' => 'AudioHasVariablePacketByteSizes',
     6455    #'ifm#' => 'AudioSupportedInputFormats',
     6456    #'ofm#' => 'AudioSupportedOutputFormats',
     6457    #'aisr' => 'AudioAvailableInputSampleRates',
     6458    #'aosr' => 'AudioAvailableOutputSampleRates',
     6459    'abrt' => 'AudioAvailableBitRateRange',
     6460    'mnip' => 'AudioMinimumNumberInputPackets',
     6461    'mnop' => 'AudioMinimumNumberOutputPackets',
     6462    'cmnc' => 'AudioAvailableNumberChannels',
     6463    'lmrc' => 'AudioDoesSampleRateConversion',
     6464    #'aicl' => 'AudioAvailableInputChannelLayoutTags',
     6465    #'aocl' => 'AudioAvailableOutputChannelLayoutTags',
     6466    #'if4o' => 'AudioInputFormatsForOutputFormat',
     6467    #'of4i' => 'AudioOutputFormatsForInputFormat',
     6468    #'acfi' => 'AudioFormatInfo',
     6469
     6470    # instance codec properties
     6471    'tbuf' => 'AudioInputBufferSize',
     6472    'pakf' => 'AudioPacketFrameSize',
     6473    'pakb' => 'AudioMaximumPacketByteSize',
     6474    #'ifmt' => 'AudioCurrentInputFormat',
     6475    #'ofmt' => 'AudioCurrentOutputFormat',
     6476    #'kuki' => 'AudioMagicCookie',
     6477    'ubuf' => 'AudioUsedInputBufferSize',
     6478    'init' => 'AudioIsInitialized',
     6479    'brat' => 'AudioCurrentTargetBitRate',
     6480    #'cisr' => 'AudioCurrentInputSampleRate',
     6481    #'cosr' => 'AudioCurrentOutputSampleRate',
     6482    'srcq' => 'AudioQualitySetting',
     6483    #'brta' => 'AudioApplicableBitRateRange',
     6484    #'isra' => 'AudioApplicableInputSampleRates',
     6485    #'osra' => 'AudioApplicableOutputSampleRates',
     6486    'pad0' => 'AudioZeroFramesPadded',
     6487    'prmm' => 'AudioCodecPrimeMethod',
     6488    #'prim' => 'AudioCodecPrimeInfo',
     6489    #'icl ' => 'AudioInputChannelLayout',
     6490    #'ocl ' => 'AudioOutputChannelLayout',
     6491    #'acs ' => 'AudioCodecSettings',
     6492    #'acfl' => 'AudioCodecFormatList',
     6493    'acbf' => 'AudioBitRateControlMode',
     6494    'vbrq' => 'AudioVBRQuality',
     6495    'mdel' => 'AudioMinimumDelayMode',
     6496
     6497    # deprecated
     6498    'pakd' => 'AudioRequiresPacketDescription',
     6499    #'brt#' => 'AudioAvailableBitRates',
     6500    'acef' => 'AudioExtendFrequencies',
     6501    'ursr' => 'AudioUseRecommendedSampleRate',
     6502    'oppr' => 'AudioOutputPrecedence',
     6503    #'loud' => 'AudioCurrentLoudnessStatistics',
     6504
     6505    # others
     6506    'vers' => 'AudioEncodingParamsVersion', #PH
     6507    'cdcv' => { #PH
     6508        Name => 'AudioComponentVersion',
     6509        ValueConv => 'join ".", unpack("ncc", pack("N",$val))',
    14916510    },
    14926511);
     
    15656584    payt => {
    15666585        Name => 'PayloadType',
     6586        Format => 'undef',  # (necessary to prevent decoding as string!)
    15676587        ValueConv => 'unpack("N",$val) . " " . substr($val, 5)',
    15686588        PrintConv => '$val=~s/ /, /;$val',
    15696589    },
    1570 );
    1571 
    1572 # Kodak DcMD atoms (ref PH)
    1573 %Image::ExifTool::QuickTime::DcMD = (
    1574     PROCESS_PROC => \&ProcessMOV,
    1575     GROUPS => { 2 => 'Video' },
    1576     NOTES => 'Metadata directory found in MOV videos from some Kodak cameras.',
    1577     Cmbo => {
    1578         Name => 'CameraByteOrder',
    1579         PrintConv => {
    1580             II => 'Little-endian (Intel, II)',
    1581             MM => 'Big-endian (Motorola, MM)',
    1582         },
    1583     },
    1584     DcME => {
    1585         Name => 'DcME',
    1586         SubDirectory => {
    1587             TagTable => 'Image::ExifTool::QuickTime::DcME',
    1588         },
    1589     },
    1590 );
    1591 
    1592 # Kodak DcME atoms (ref PH)
    1593 %Image::ExifTool::QuickTime::DcME = (
    1594     PROCESS_PROC => \&ProcessMOV,
    1595     GROUPS => { 2 => 'Video' },
    1596     # Mtmd = binary data ("00 00 00 00 00 00 00 01" x 3)
    1597     # Keyw = keywords? (six bytes all zero)
    1598     # Rate = 2 bytes "00 00"
    15996590);
    16006591
     
    16026593%Image::ExifTool::QuickTime::Media = (
    16036594    PROCESS_PROC => \&ProcessMOV,
    1604     GROUPS => { 2 => 'Video' },
     6595    WRITE_PROC => \&WriteQuickTime,
     6596    GROUPS => { 1 => 'Track#', 2 => 'Video' },
    16056597    NOTES => 'MP4 media box.',
    16066598    mdhd => {
     
    16216613%Image::ExifTool::QuickTime::MediaHeader = (
    16226614    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
    1623     GROUPS => { 2 => 'Video' },
     6615    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
     6616    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
     6617    GROUPS => { 1 => 'Track#', 2 => 'Video' },
    16246618    FORMAT => 'int32u',
     6619    DATAMEMBER => [ 0, 1, 2, 3, 4 ],
    16256620    0 => {
    16266621        Name => 'MediaHeaderVersion',
     
    16576652        RawConv => '$val ? $val : undef',
    16586653        # allow both Macintosh (for MOV files) and ISO (for MP4 files) language codes
    1659         ValueConv => '$val < 0x400 ? $val : pack "C*", map { (($val>>$_)&0x1f)+0x60 } 10, 5, 0',
     6654        ValueConv => '($val < 0x400 or $val == 0x7fff) ? $val : pack "C*", map { (($val>>$_)&0x1f)+0x60 } 10, 5, 0',
    16606655        PrintConv => q{
    16616656            return $val unless $val =~ /^\d+$/;
     
    16696664%Image::ExifTool::QuickTime::MediaInfo = (
    16706665    PROCESS_PROC => \&ProcessMOV,
    1671     GROUPS => { 2 => 'Video' },
     6666    WRITE_PROC => \&WriteQuickTime,
     6667    GROUPS => { 1 => 'Track#', 2 => 'Video' },
    16726668    NOTES => 'MP4 media info box.',
    16736669    vmhd => {
     
    16886684    },
    16896685    dinf => {
    1690         Name => 'DataInfo',
     6686        Name => 'DataInfo', # (don't change this name -- used to recognize directory when writing)
    16916687        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::DataInfo' },
    16926688    },
     
    17436739%Image::ExifTool::QuickTime::SampleTable = (
    17446740    PROCESS_PROC => \&ProcessMOV,
     6741    WRITE_PROC => \&WriteQuickTime,
    17456742    GROUPS => { 2 => 'Video' },
    17466743    NOTES => 'MP4 sample table box.',
     
    17516748            SubDirectory => {
    17526749                TagTable => 'Image::ExifTool::QuickTime::AudioSampleDesc',
    1753                 Start => 8, # skip version number and count
     6750                ProcessProc => \&ProcessSampleDesc,
    17546751            },
    17556752        },{
     
    17586755            SubDirectory => {
    17596756                TagTable => 'Image::ExifTool::QuickTime::ImageDesc',
    1760                 Start => 8, # skip version number and count
     6757                ProcessProc => \&ProcessSampleDesc,
    17616758            },
    17626759        },{
     
    17656762            SubDirectory => {
    17666763                TagTable => 'Image::ExifTool::QuickTime::HintSampleDesc',
    1767                 Start => 8, # skip version number and count
     6764                ProcessProc => \&ProcessSampleDesc,
     6765            },
     6766        },{
     6767            Name => 'MetaSampleDesc',
     6768            Condition => '$$self{HandlerType} and $$self{HandlerType} eq "meta"',
     6769            SubDirectory => {
     6770                TagTable => 'Image::ExifTool::QuickTime::MetaSampleDesc',
     6771                ProcessProc => \&ProcessSampleDesc,
    17686772            },
    17696773        },{
     
    17716775            SubDirectory => {
    17726776                TagTable => 'Image::ExifTool::QuickTime::OtherSampleDesc',
    1773                 Start => 8, # skip version number and count
     6777                ProcessProc => \&ProcessSampleDesc,
    17746778            },
    17756779        },
     
    17816785            Notes => 'average rate calculated from time-to-sample table for video media',
    17826786            Condition => '$$self{HandlerType} and $$self{HandlerType} eq "vide"',
     6787            Format => 'undef',  # (necessary to prevent decoding as string!)
    17836788            # (must be RawConv so appropriate MediaTS is used in calculation)
    17846789            RawConv => 'Image::ExifTool::QuickTime::CalcSampleRate($self, \$val)',
     
    18416846        Name => 'SampleGroupDescription',
    18426847        Flags => ['Binary','Unknown'],
     6848        # bytes 4-7 give grouping type (ref ISO/IEC 14496-15:2014)
     6849        #   tsas - temporal sublayer sample
     6850        #   stsa - step-wise temporal layer access
     6851        #   avss - AVC sample
     6852        #   tscl - temporal layer scalability
     6853        #   sync - sync sample
    18436854    },
    18446855    subs => {
     
    18506861        Flags => ['Binary','Unknown'],
    18516862    },
     6863    stps => {
     6864        Name => 'PartialSyncSamples',
     6865        ValueConv => 'join " ",unpack("x8N*",$val)',
     6866    },
     6867    # mark - 8 bytes all zero (GoPro)
    18526868);
    18536869
    1854 # MP4 audio sample description box (ref 5)
     6870# MP4 audio sample description box (ref 5/AtomicParsley 0.9.4 parsley.cpp)
    18556871%Image::ExifTool::QuickTime::AudioSampleDesc = (
    1856     PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     6872    PROCESS_PROC => \&ProcessHybrid,
     6873    VARS => { ID_LABEL => 'ID/Index' },
    18576874    GROUPS => { 2 => 'Audio' },
    1858     FORMAT => 'int16u',
    1859     NOTES => 'MP4 audio sample description.',
    1860     2  => {
     6875    NOTES => q{
     6876        MP4 audio sample description.  This hybrid atom contains both data and child
     6877        atoms.
     6878    },
     6879    4  => {
    18616880        Name => 'AudioFormat',
    18626881        Format => 'undef[4]',
    18636882        RawConv => q{
     6883            $$self{AudioFormat} = $val;
    18646884            return undef unless $val =~ /^[\w ]{4}$/i;
    18656885            # check for protected audio format
     
    18676887            return $val;
    18686888        },
    1869     },
    1870     10 => { #PH
     6889        # see this link for print conversions (not complete):
     6890        # https://github.com/yannickcr/brooser/blob/master/php/librairies/getid3/module.audio-video.quicktime.php
     6891    },
     6892    20 => { #PH
    18716893        Name => 'AudioVendorID',
     6894        Condition => '$$self{AudioFormat} ne "mp4s"',
    18726895        Format => 'undef[4]',
    18736896        RawConv => '$val eq "\0\0\0\0" ? undef : $val',
     
    18756898        SeparateTable => 'VendorID',
    18766899    },
    1877     12 => 'AudioChannels',
    1878     13 => 'AudioBitsPerSample',
    1879     16 => { Name => 'AudioSampleRate', Format => 'fixed32u' },
    1880     28 => { #PH
    1881         Name => 'AudioFormat',
     6900    24 => { Name => 'AudioChannels',        Format => 'int16u' },
     6901    26 => { Name => 'AudioBitsPerSample',   Format => 'int16u' },
     6902    32 => { Name => 'AudioSampleRate',      Format => 'fixed32u' },
     6903#
     6904# Observed offsets for child atoms of various AudioFormat types:
     6905#
     6906#   AudioFormat  Offset  Child atoms
     6907#   -----------  ------  ----------------
     6908#   mp4a         52 *    wave, chan, esds, SA3D(Insta360 spherical video params?,also GoPro Max)
     6909#   in24         52      wave, chan
     6910#   "ms\0\x11"   52      wave
     6911#   sowt         52      chan
     6912#   mp4a         36 *    esds, pinf
     6913#   drms         36      esds, sinf
     6914#   samr         36      damr
     6915#   alac         36      alac
     6916#   ac-3         36      dac3
     6917#
     6918# (* child atoms found at different offsets in mp4a)
     6919#
     6920    pinf => {
     6921        Name => 'PurchaseInfo',
     6922        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ProtectionInfo' },
     6923    },
     6924    sinf => { # "protection scheme information"
     6925        Name => 'ProtectionInfo', #3
     6926        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ProtectionInfo' },
     6927    },
     6928    # f - 16/36 bytes
     6929    # esds - 31/40/42/43 bytes - ES descriptor (ref 3)
     6930    damr => { #3
     6931        Name => 'DecodeConfig',
     6932        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::DecodeConfig' },
     6933    },
     6934    wave => {
     6935        Name => 'Wave',
     6936        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Wave' },
     6937    },
     6938    chan => {
     6939        Name => 'AudioChannelLayout',
     6940        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::ChannelLayout' },
     6941    }
     6942    # alac - 28 bytes
     6943    # adrm - AAX DRM atom? 148 bytes
     6944    # aabd - AAX unknown 17kB (contains 'aavd' strings)
     6945    # SA3D - written by Garmin VIRB360
     6946);
     6947
     6948# AMR decode config box (ref 3)
     6949%Image::ExifTool::QuickTime::DecodeConfig = (
     6950    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     6951    GROUPS => { 2 => 'Audio' },
     6952    0 => {
     6953        Name => 'EncoderVendor',
    18826954        Format => 'undef[4]',
    1883         RawConv => '$val =~ /^[\w ]{4}$/i ? $val : undef',
    1884         Notes => 'in Casio MOV videos',
    1885     },
     6955    },
     6956    4 => 'EncoderVersion',
     6957    # 5 - int16u - packet modes
     6958    # 7 - int8u - number of packet mode changes
     6959    # 8 - int8u - bytes per packet
    18866960);
    18876961
     6962%Image::ExifTool::QuickTime::ProtectionInfo = (
     6963    PROCESS_PROC => \&ProcessMOV,
     6964    GROUPS => { 2 => 'Audio' },
     6965    NOTES => 'Child atoms found in "sinf" and/or "pinf" atoms.',
     6966    frma => 'OriginalFormat',
     6967    # imif - IPMP information
     6968    schm => {
     6969        Name => 'SchemeType',
     6970        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SchemeType' },
     6971    },
     6972    schi => {
     6973        Name => 'SchemeInfo',
     6974        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::SchemeInfo' },
     6975    },
     6976    enda => {
     6977        Name => 'Endianness',
     6978        Format => 'int16u',
     6979        PrintConv => {
     6980            0 => 'Big-endian (Motorola, MM)',
     6981            1 => 'Little-endian (Intel, II)',
     6982        },
     6983    },
     6984    # skcr
     6985);
     6986
     6987%Image::ExifTool::QuickTime::Wave = (
     6988    PROCESS_PROC => \&ProcessMOV,
     6989    frma => 'PurchaseFileFormat',
     6990    enda => {
     6991        Name => 'Endianness',
     6992        Format => 'int16u',
     6993        PrintConv => {
     6994            0 => 'Big-endian (Motorola, MM)',
     6995            1 => 'Little-endian (Intel, II)',
     6996        },
     6997    },
     6998    # "ms\0\x11" - 20 bytes
     6999);
     7000
     7001# audio channel layout (ref CoreAudioTypes.h)
     7002%Image::ExifTool::QuickTime::ChannelLayout = (
     7003    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     7004    GROUPS => { 2 => 'Audio' },
     7005    DATAMEMBER => [ 0, 8 ],
     7006    NOTES => 'Audio channel layout.',
     7007    # 0 - version and flags
     7008    4 => {
     7009        Name => 'LayoutFlags',
     7010        Format => 'int16u',
     7011        RawConv => '$$self{LayoutFlags} = $val',
     7012        PrintConvColumns => 2,
     7013        PrintConv => {
     7014            0 => 'UseDescriptions',
     7015            1 => 'UseBitmap',
     7016            100 => 'Mono',
     7017            101 => 'Stereo',
     7018            102 => 'StereoHeadphones',
     7019            100 => 'Mono',
     7020            101 => 'Stereo',
     7021            102 => 'StereoHeadphones',
     7022            103 => 'MatrixStereo',
     7023            104 => 'MidSide',
     7024            105 => 'XY',
     7025            106 => 'Binaural',
     7026            107 => 'Ambisonic_B_Format',
     7027            108 => 'Quadraphonic',
     7028            109 => 'Pentagonal',
     7029            110 => 'Hexagonal',
     7030            111 => 'Octagonal',
     7031            112 => 'Cube',
     7032            113 => 'MPEG_3_0_A',
     7033            114 => 'MPEG_3_0_B',
     7034            115 => 'MPEG_4_0_A',
     7035            116 => 'MPEG_4_0_B',
     7036            117 => 'MPEG_5_0_A',
     7037            118 => 'MPEG_5_0_B',
     7038            119 => 'MPEG_5_0_C',
     7039            120 => 'MPEG_5_0_D',
     7040            121 => 'MPEG_5_1_A',
     7041            122 => 'MPEG_5_1_B',
     7042            123 => 'MPEG_5_1_C',
     7043            124 => 'MPEG_5_1_D',
     7044            125 => 'MPEG_6_1_A',
     7045            126 => 'MPEG_7_1_A',
     7046            127 => 'MPEG_7_1_B',
     7047            128 => 'MPEG_7_1_C',
     7048            129 => 'Emagic_Default_7_1',
     7049            130 => 'SMPTE_DTV',
     7050            131 => 'ITU_2_1',
     7051            132 => 'ITU_2_2',
     7052            133 => 'DVD_4',
     7053            134 => 'DVD_5',
     7054            135 => 'DVD_6',
     7055            136 => 'DVD_10',
     7056            137 => 'DVD_11',
     7057            138 => 'DVD_18',
     7058            139 => 'AudioUnit_6_0',
     7059            140 => 'AudioUnit_7_0',
     7060            141 => 'AAC_6_0',
     7061            142 => 'AAC_6_1',
     7062            143 => 'AAC_7_0',
     7063            144 => 'AAC_Octagonal',
     7064            145 => 'TMH_10_2_std',
     7065            146 => 'TMH_10_2_full',
     7066            147 => 'DiscreteInOrder',
     7067            148 => 'AudioUnit_7_0_Front',
     7068            149 => 'AC3_1_0_1',
     7069            150 => 'AC3_3_0',
     7070            151 => 'AC3_3_1',
     7071            152 => 'AC3_3_0_1',
     7072            153 => 'AC3_2_1_1',
     7073            154 => 'AC3_3_1_1',
     7074            155 => 'EAC_6_0_A',
     7075            156 => 'EAC_7_0_A',
     7076            157 => 'EAC3_6_1_A',
     7077            158 => 'EAC3_6_1_B',
     7078            159 => 'EAC3_6_1_C',
     7079            160 => 'EAC3_7_1_A',
     7080            161 => 'EAC3_7_1_B',
     7081            162 => 'EAC3_7_1_C',
     7082            163 => 'EAC3_7_1_D',
     7083            164 => 'EAC3_7_1_E',
     7084            165 => 'EAC3_7_1_F',
     7085            166 => 'EAC3_7_1_G',
     7086            167 => 'EAC3_7_1_H',
     7087            168 => 'DTS_3_1',
     7088            169 => 'DTS_4_1',
     7089            170 => 'DTS_6_0_A',
     7090            171 => 'DTS_6_0_B',
     7091            172 => 'DTS_6_0_C',
     7092            173 => 'DTS_6_1_A',
     7093            174 => 'DTS_6_1_B',
     7094            175 => 'DTS_6_1_C',
     7095            176 => 'DTS_7_0',
     7096            177 => 'DTS_7_1',
     7097            178 => 'DTS_8_0_A',
     7098            179 => 'DTS_8_0_B',
     7099            180 => 'DTS_8_1_A',
     7100            181 => 'DTS_8_1_B',
     7101            182 => 'DTS_6_1_D',
     7102            183 => 'AAC_7_1_B',
     7103            0xffff => 'Unknown',
     7104        },
     7105    },
     7106    6  => {
     7107        Name => 'AudioChannels',
     7108        Condition => '$$self{LayoutFlags} != 0 and $$self{LayoutFlags} != 1',
     7109        Format => 'int16u',
     7110    },
     7111    8 => {
     7112        Name => 'AudioChannelTypes',
     7113        Condition => '$$self{LayoutFlags} == 1',
     7114        Format => 'int32u',
     7115        PrintConv => { BITMASK => {
     7116            0 => 'Left',
     7117            1 => 'Right',
     7118            2 => 'Center',
     7119            3 => 'LFEScreen',
     7120            4 => 'LeftSurround',
     7121            5 => 'RightSurround',
     7122            6 => 'LeftCenter',
     7123            7 => 'RightCenter',
     7124            8 => 'CenterSurround',
     7125            9 => 'LeftSurroundDirect',
     7126            10 => 'RightSurroundDirect',
     7127            11 => 'TopCenterSurround',
     7128            12 => 'VerticalHeightLeft',
     7129            13 => 'VerticalHeightCenter',
     7130            14 => 'VerticalHeightRight',
     7131            15 => 'TopBackLeft',
     7132            16 => 'TopBackCenter',
     7133            17 => 'TopBackRight',
     7134        }},
     7135    },
     7136    12  => {
     7137        Name => 'NumChannelDescriptions',
     7138        Condition => '$$self{LayoutFlags} == 1',
     7139        Format => 'int32u',
     7140        RawConv => '$$self{NumChannelDescriptions} = $val',
     7141    },
     7142    16 => {
     7143        Name => 'Channel1Label',
     7144        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0',
     7145        Format => 'int32u',
     7146        SeparateTable => 'ChannelLabel',
     7147        PrintConv => \%channelLabel,
     7148    },
     7149    20 => {
     7150        Name => 'Channel1Flags',
     7151        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0',
     7152        Format => 'int32u',
     7153        PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }},
     7154    },
     7155    24 => {
     7156        Name => 'Channel1Coordinates',
     7157        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 0',
     7158        Notes => q{
     7159            3 numbers:  for rectangular coordinates left/right, back/front, down/up; for
     7160            spherical coordinates left/right degrees, down/up degrees, distance
     7161        },
     7162        Format => 'float[3]',
     7163    },
     7164    36 => {
     7165        Name => 'Channel2Label',
     7166        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1',
     7167        Format => 'int32u',
     7168        SeparateTable => 'ChannelLabel',
     7169        PrintConv => \%channelLabel,
     7170    },
     7171    40 => {
     7172        Name => 'Channel2Flags',
     7173        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1',
     7174        Format => 'int32u',
     7175        PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }},
     7176    },
     7177    44 => {
     7178        Name => 'Channel2Coordinates',
     7179        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 1',
     7180        Format => 'float[3]',
     7181    },
     7182    56 => {
     7183        Name => 'Channel3Label',
     7184        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2',
     7185        Format => 'int32u',
     7186        SeparateTable => 'ChannelLabel',
     7187        PrintConv => \%channelLabel,
     7188    },
     7189    60 => {
     7190        Name => 'Channel3Flags',
     7191        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2',
     7192        Format => 'int32u',
     7193        PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }},
     7194    },
     7195    64 => {
     7196        Name => 'Channel3Coordinates',
     7197        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 2',
     7198        Format => 'float[3]',
     7199    },
     7200    76 => {
     7201        Name => 'Channel4Label',
     7202        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3',
     7203        Format => 'int32u',
     7204        SeparateTable => 'ChannelLabel',
     7205        PrintConv => \%channelLabel,
     7206    },
     7207    80 => {
     7208        Name => 'Channel4Flags',
     7209        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3',
     7210        Format => 'int32u',
     7211        PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }},
     7212    },
     7213    84 => {
     7214        Name => 'Channel4Coordinates',
     7215        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 3',
     7216        Format => 'float[3]',
     7217    },
     7218    96 => {
     7219        Name => 'Channel5Label',
     7220        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4',
     7221        Format => 'int32u',
     7222        SeparateTable => 'ChannelLabel',
     7223        PrintConv => \%channelLabel,
     7224    },
     7225    100 => {
     7226        Name => 'Channel5Flags',
     7227        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4',
     7228        Format => 'int32u',
     7229        PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }},
     7230    },
     7231    104 => {
     7232        Name => 'Channel5Coordinates',
     7233        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 4',
     7234        Format => 'float[3]',
     7235    },
     7236    116 => {
     7237        Name => 'Channel6Label',
     7238        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5',
     7239        Format => 'int32u',
     7240        SeparateTable => 'ChannelLabel',
     7241        PrintConv => \%channelLabel,
     7242    },
     7243    120 => {
     7244        Name => 'Channel6Flags',
     7245        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5',
     7246        Format => 'int32u',
     7247        PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }},
     7248    },
     7249    124 => {
     7250        Name => 'Channel6Coordinates',
     7251        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 5',
     7252        Format => 'float[3]',
     7253    },
     7254    136 => {
     7255        Name => 'Channel7Label',
     7256        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6',
     7257        Format => 'int32u',
     7258        SeparateTable => 'ChannelLabel',
     7259        PrintConv => \%channelLabel,
     7260    },
     7261    140 => {
     7262        Name => 'Channel7Flags',
     7263        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6',
     7264        Format => 'int32u',
     7265        PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }},
     7266    },
     7267    144 => {
     7268        Name => 'Channel7Coordinates',
     7269        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 6',
     7270        Format => 'float[3]',
     7271    },
     7272    156 => {
     7273        Name => 'Channel8Label',
     7274        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7',
     7275        Format => 'int32u',
     7276        SeparateTable => 'ChannelLabel',
     7277        PrintConv => \%channelLabel,
     7278    },
     7279    160 => {
     7280        Name => 'Channel8Flags',
     7281        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7',
     7282        Format => 'int32u',
     7283        PrintConv => { BITMASK => { 0 => 'Rectangular', 1 => 'Spherical', 2 => 'Meters' }},
     7284    },
     7285    164 => {
     7286        Name => 'Channel8Coordinates',
     7287        Condition => '$$self{LayoutFlags} == 1 and $$self{NumChannelDescriptions} > 7',
     7288        Format => 'float[3]',
     7289    },
     7290    # (arbitrarily decode only first 8 channels)
     7291);
     7292
     7293# scheme type atom
     7294# ref http://xhelmboyx.tripod.com/formats/mp4-layout.txt
     7295%Image::ExifTool::QuickTime::SchemeType = (
     7296    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     7297    GROUPS => { 2 => 'Audio' },
     7298    # 0 - 4 bytes version
     7299    4 => { Name => 'SchemeType',    Format => 'undef[4]' },
     7300    8 => { Name => 'SchemeVersion', Format => 'int16u' },
     7301    10 => { Name => 'SchemeURL',    Format => 'string[$size-10]' },
     7302);
     7303
     7304%Image::ExifTool::QuickTime::SchemeInfo = (
     7305    PROCESS_PROC => \&ProcessMOV,
     7306    GROUPS => { 2 => 'Audio' },
     7307    user => {
     7308        Name => 'UserID',
     7309        Groups => { 2 => 'Author' },
     7310        ValueConv => '"0x" . unpack("H*",$val)',
     7311    },
     7312    cert => { # ref http://www.onvif.org/specs/stream/ONVIF-ExportFileFormat-Spec-v100.pdf
     7313        Name => 'Certificate',
     7314        ValueConv => '"0x" . unpack("H*",$val)',
     7315    },
     7316    'key ' => {
     7317        Name => 'KeyID',
     7318        ValueConv => '"0x" . unpack("H*",$val)',
     7319    },
     7320    iviv => {
     7321        Name => 'InitializationVector',
     7322        ValueConv => 'unpack("H*",$val)',
     7323    },
     7324    righ => {
     7325        Name => 'Rights',
     7326        Groups => { 2 => 'Author' },
     7327        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Rights' },
     7328    },
     7329    name => { Name => 'UserName', Groups => { 2 => 'Author' } },
     7330    # chtb
     7331    # priv - private data
     7332    # sign
     7333    # adkm - Adobe DRM key management system (ref http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf)
     7334    # iKMS
     7335    # iSFM
     7336    # iSLT
     7337);
     7338
     7339%Image::ExifTool::QuickTime::Rights = (
     7340    PROCESS_PROC => \&ProcessRights,
     7341    GROUPS => { 2 => 'Audio' },
     7342    veID => 'ItemVendorID', #PH ("VendorID" ref 19)
     7343    plat => 'Platform', #18?
     7344    aver => 'VersionRestrictions', #19 ("appversion?" ref 18)
     7345    tran => 'TransactionID', #18
     7346    song => 'ItemID', #19 ("appid" ref 18)
     7347    tool => {
     7348        Name => 'ItemTool', #PH (guess) ("itunes build?" ref 18)
     7349        Format => 'string',
     7350    },
     7351    medi => 'MediaFlags', #PH (?)
     7352    mode => 'ModeFlags', #PH (?) 0x04 is HD flag (https://compilr.com/heksesang/requiem-mac/UnDrm.java)
     7353);
     7354
    18887355# MP4 hint sample description box (ref 5)
     7356# (ref https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-SW1)
    18897357%Image::ExifTool::QuickTime::HintSampleDesc = (
    1890     PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
    1891     FORMAT => 'int16u',
     7358    PROCESS_PROC => \&ProcessHybrid,
     7359    VARS => { ID_LABEL => 'ID/Index' },
    18927360    NOTES => 'MP4 hint sample description.',
    1893     2 => { Name => 'HintFormat', Format => 'undef[4]' },
     7361    4  => { Name => 'HintFormat', Format => 'undef[4]' },
     7362    # 14 - int16u DataReferenceIndex
     7363    16 => { Name => 'HintTrackVersion', Format => 'int16u' },
     7364    # 18 - int16u LastCompatibleHintTrackVersion
     7365    20 => { Name => 'MaxPacketSize', Format => 'int32u' },
     7366#
     7367# Observed offsets for child atoms of various HintFormat types:
     7368#
     7369#   HintFormat   Offset  Child atoms
     7370#   -----------  ------  ----------------
     7371#   "rtp "       24      tims
     7372#
     7373    tims => { Name => 'RTPTimeScale',               Format => 'int32u' },
     7374    tsro => { Name => 'TimestampRandomOffset',      Format => 'int32u' },
     7375    snro => { Name => 'SequenceNumberRandomOffset', Format => 'int32u' },
     7376);
     7377
     7378# MP4 metadata sample description box
     7379%Image::ExifTool::QuickTime::MetaSampleDesc = (
     7380    PROCESS_PROC => \&ProcessHybrid,
     7381    NOTES => 'MP4 metadata sample description.',
     7382    4 => {
     7383        Name => 'MetaFormat',
     7384        Format => 'undef[4]',
     7385        RawConv => '$$self{MetaFormat} = $val',
     7386    },
     7387#
     7388# Observed offsets for child atoms of various MetaFormat types:
     7389#
     7390#   MetaFormat   Offset  Child atoms
     7391#   -----------  ------  ----------------
     7392#   mebx         24      keys,btrt,lidp,lidl
     7393#   fdsc         -       -
     7394#   gpmd         -       -
     7395#   rtmd         -       -
     7396#   CTMD         -       -
     7397#
     7398   'keys' => { #PH (iPhone7+ hevc)
     7399        Name => 'Keys',
     7400        SubDirectory => {
     7401            TagTable => 'Image::ExifTool::QuickTime::Keys',
     7402            ProcessProc => \&ProcessMetaKeys,
     7403        },
     7404    },
     7405    btrt => {
     7406        Name => 'BitrateInfo',
     7407        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Bitrate' },
     7408    },
    18947409);
    18957410
    18967411# MP4 generic sample description box
    18977412%Image::ExifTool::QuickTime::OtherSampleDesc = (
    1898     PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
    1899     FORMAT => 'int16u',
    1900     2 => { Name => 'OtherFormat', Format => 'undef[4]' },
     7413    PROCESS_PROC => \&ProcessHybrid,
     7414    4 => {
     7415        Name => 'OtherFormat',
     7416        Format => 'undef[4]',
     7417        RawConv => '$$self{MetaFormat} = $val', # (yes, use MetaFormat for this too)
     7418    },
     7419#
     7420# Observed offsets for child atoms of various OtherFormat types:
     7421#
     7422#   OtherFormat  Offset  Child atoms
     7423#   -----------  ------  ----------------
     7424#   avc1         86      avcC
     7425#   mp4a         36      esds
     7426#   mp4s         16      esds
     7427#   tmcd         34      name
     7428#   data         -       -
     7429#
     7430    ftab => { Name => 'FontTable',  Format => 'undef', ValueConv => 'substr($val, 5)' },
     7431    name => { Name => 'OtherName',  Format => 'undef', ValueConv => 'substr($val, 4)' },
     7432    # mrlh = GM header?
     7433    # mrlv = GM data
     7434    # mrld = GM data (448-byte records):
     7435    #            0 - int32u count
     7436    #            4 - int32u ? (related to units) 0=none,1=m/km,2=L,3=kph,4=C,7=deg,8=rpm,9=kPa,10=G,11=V,15=Nm,16=%
     7437    #            8 - int32u ? (0,1,3,4,5)
     7438    #           12 - string[64] units
     7439    #           76 - int32u ? (1,3,7,15)
     7440    #           80 - int32u 0
     7441    #           84 - undef[4] ?
     7442    #           88 - int16u[6] ?
     7443    #           100 - undef[32] ?
     7444    #           132 - string[64] measurement name
     7445    #           196 - string[64] measurement name
    19017446);
    19027447
     
    19047449%Image::ExifTool::QuickTime::DataInfo = (
    19057450    PROCESS_PROC => \&ProcessMOV,
     7451    WRITE_PROC => \&WriteQuickTime, # (necessary to parse dref even though we don't change it)
    19067452    NOTES => 'MP4 data information box.',
    19077453    dref => {
     
    19247470        Name => 'Text',
    19257471        Flags => ['Binary','Unknown'],
     7472    },
     7473    tmcd => {
     7474        Name => 'TimeCode',
     7475        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TimeCode' },
     7476    },
     7477);
     7478
     7479# TimeCode header
     7480%Image::ExifTool::QuickTime::TimeCode = (
     7481    PROCESS_PROC => \&ProcessMOV,
     7482    tcmi => {
     7483        Name => 'TCMediaInfo',
     7484        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::TCMediaInfo' },
     7485    },
     7486);
     7487
     7488# TimeCode media info (ref 12)
     7489%Image::ExifTool::QuickTime::TCMediaInfo = (
     7490    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     7491    GROUPS => { 2 => 'Video' },
     7492    4 => {
     7493        Name => 'TextFont',
     7494        Format => 'int16u',
     7495        PrintConv => { 0 => 'System' },
     7496    },
     7497    6 => {
     7498        Name => 'TextFace',
     7499        Format => 'int16u',
     7500        PrintConv => {
     7501            0 => 'Plain',
     7502            BITMASK => {
     7503                0 => 'Bold',
     7504                1 => 'Italic',
     7505                2 => 'Underline',
     7506                3 => 'Outline',
     7507                4 => 'Shadow',
     7508                5 => 'Condense',
     7509                6 => 'Extend',
     7510            },
     7511        },
     7512    },
     7513    8 => {
     7514        Name => 'TextSize',
     7515        Format => 'int16u',
     7516    },
     7517    # 10 - reserved
     7518    12 => {
     7519        Name => 'TextColor',
     7520        Format => 'int16u[3]',
     7521    },
     7522    18 => {
     7523        Name => 'BackgroundColor',
     7524        Format => 'int16u[3]',
     7525    },
     7526    24 => {
     7527        Name => 'FontName',
     7528        Format => 'pstring',
     7529        ValueConv => '$self->Decode($val, $self->Options("CharsetQuickTime"))',
    19267530    },
    19277531);
     
    19467550%Image::ExifTool::QuickTime::DataRef = (
    19477551    PROCESS_PROC => \&ProcessMOV,
     7552    WRITE_PROC => \&WriteQuickTime, # (necessary to parse dref even though we don't change it)
    19487553    NOTES => 'MP4 data reference box.',
    19497554    'url ' => {
    19507555        Name => 'URL',
     7556        Format => 'undef',  # (necessary to prevent decoding as string!)
    19517557        RawConv => q{
    19527558            # ignore if self-contained (flags bit 0 set)
     
    19557561        },
    19567562    },
     7563    "url\0" => { # (written by GoPro)
     7564        Name => 'URL',
     7565        Format => 'undef',  # (necessary to prevent decoding as string!)
     7566        RawConv => q{
     7567            # ignore if self-contained (flags bit 0 set)
     7568            return undef if unpack("N",$val) & 0x01;
     7569            $_ = substr($val,4); s/\0.*//s; $_;
     7570        },
     7571    },
    19577572    'urn ' => {
    19587573        Name => 'URN',
     7574        Format => 'undef',  # (necessary to prevent decoding as string!)
    19597575        RawConv => q{
    19607576            return undef if unpack("N",$val) & 0x01;
    1961             $_ = substr($val,4); s/\0.*//s; $_;
     7577            $_ = substr($val,4); s/\0+/; /; s/\0.*//s; $_;
    19627578        },
    19637579    },
     
    19807596        Name => 'HandlerType',
    19817597        Format => 'undef[4]',
    1982         RawConv => '$$self{HandlerType} = $val unless $val eq "alis"; $val',
     7598        RawConv => '$$self{HandlerType} = $val unless $val eq "alis" or $val eq "url "; $val',
     7599        PrintConvColumns => 2,
    19837600        PrintConv => {
    19847601            alis => 'Alias Data', #PH
     
    19877604            ipsm => 'IPMP', #3
    19887605            m7sm => 'MPEG-7 Stream', #3
     7606            meta => 'NRT Metadata', #PH
    19897607            mdir => 'Metadata', #3
    19907608            mdta => 'Metadata Tags', #PH
     
    19927610            ocsm => 'Object Content', #3
    19937611            odsm => 'Object Descriptor', #3
     7612            priv => 'Private', #PH
    19947613            sdsm => 'Scene Description', #3
    19957614            soun => 'Audio Track',
    19967615            text => 'Text', #PH (but what type? subtitle?)
     7616            tmcd => 'Time Code', #PH
    19977617           'url '=> 'URL', #3
    19987618            vide => 'Video Track',
     7619            subp => 'Subpicture', #http://www.google.nl/patents/US7778526
     7620            nrtm => 'Non-Real Time Metadata', #PH (Sony ILCE-7S) [how is this different from "meta"?]
     7621            pict => 'Picture', # (HEIC images)
     7622            camm => 'Camera Metadata', # (Insta360 MP4)
     7623            psmd => 'Panasonic Static Metadata', #PH (Leica C-Lux CAM-DC25)
     7624            data => 'Data', #PH (GPS and G-sensor data from DataKam)
     7625            sbtl => 'Subtitle', #PH (TomTom Bandit Action Cam)
    19997626        },
    20007627    },
     
    20347661    28 => {
    20357662        Name => 'PreviewImage',
     7663        Groups => { 2 => 'Preview' },
    20367664        Format => 'undef[$val{13}]',
    20377665        RawConv => '$self->ValidateImage(\$val, $tag)',
     7666    },
     7667);
     7668
     7669# atoms in Pittasoft "free" atom
     7670%Image::ExifTool::QuickTime::Pittasoft = (
     7671    PROCESS_PROC => \&ProcessMOV,
     7672    NOTES => 'Tags found in Pittasoft Blackvue dashcam "free" data.',
     7673    cprt => 'Copyright',
     7674    thum => {
     7675        Name => 'PreviewImage',
     7676        Groups => { 2 => 'Preview' },
     7677        Binary => 1,
     7678        RawConv => q{
     7679            return undef unless length $val > 4;
     7680            my $len = unpack('N', $val);
     7681            return undef unless length $val >= 4 + $len;
     7682            return substr($val, 4, $len);
     7683        },
     7684    },
     7685    ptnm => {
     7686        Name => 'OriginalFileName',
     7687        ValueConv => 'substr($val, 4, -1)',
     7688    },
     7689    ptrh => {
     7690        SubDirectory => { TagTable => 'Image::ExifTool::QuickTime::Pittasoft' },
     7691        # contains these atoms:
     7692        # ptvi - 27 bytes: '..avc1...'
     7693        # ptso - 16 bytes: '..mp4a...'
     7694    },
     7695    'gps ' => {
     7696        Name => 'GPSLog',
     7697        Binary => 1,    # (ASCII NMEA track log with leading timestamps)
     7698        Notes => 'parsed to extract GPS separately when ExtractEmbedded is used',
     7699        RawConv => q{
     7700            $val =~ s/\0+$//;   # remove trailing nulls
     7701            if (length $val and $$self{OPTIONS}{ExtractEmbedded}) {
     7702                my $tagTbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
     7703                Image::ExifTool::QuickTime::ProcessNMEA($self, { DataPt => \$val }, $tagTbl);
     7704            }
     7705            return $val;
     7706        },
     7707    },
     7708    '3gf ' => {
     7709        Name => 'AccelData',
     7710        SubDirectory => {
     7711            TagTable => 'Image::ExifTool::QuickTime::Stream',
     7712            ProcessProc => \&Process_3gf,
     7713        },
     7714    },
     7715    sttm => {
     7716        Name => 'StartTime',
     7717        Format => 'int64u',
     7718        Groups => { 2 => 'Time' },
     7719        RawConv => '$$self{StartTime} = $val',
     7720        # (ms since Jan 1, 1970, in local time zone - PH)
     7721        ValueConv => q{
     7722            my $secs = int($val / 1000);
     7723            return ConvertUnixTime($secs) . sprintf(".%03d",$val - $secs * 1000);
     7724        },
     7725        PrintConv => '$self->ConvertDateTime($val)',
    20387726    },
    20397727);
     
    20437731    GROUPS => { 2 => 'Video' },
    20447732    Rotation => {
     7733        Notes => q{
     7734            writing this tag updates QuickTime MatrixStructure for all tracks with a
     7735            non-zero image size
     7736        },
    20457737        Require => {
    20467738            0 => 'QuickTime:MatrixStructure',
    20477739            1 => 'QuickTime:HandlerType',
    20487740        },
     7741        Writable => 1,
     7742        Protected => 1,
     7743        WriteAlso => {
     7744            MatrixStructure => 'Image::ExifTool::QuickTime::GetRotationMatrix($val)',
     7745        },
    20497746        ValueConv => 'Image::ExifTool::QuickTime::CalcRotation($self)',
     7747        ValueConvInv => '$val',
    20507748    },
    20517749    AvgBitrate => {
    20527750        Priority => 0,  # let QuickTime::AvgBitrate take priority
    20537751        Require => {
    2054             0 => 'QuickTime::MovieDataSize',
     7752            0 => 'QuickTime::MediaDataSize',
    20557753            1 => 'QuickTime::Duration',
    20567754        },
     
    20587756            return undef unless $val[1];
    20597757            $val[1] /= $$self{TimeScale} if $$self{TimeScale};
    2060             return int($val[0] * 8 / $val[1] + 0.5);
     7758            my $key = 'MediaDataSize';
     7759            my $size = $val[0];
     7760            for (;;) {
     7761                $key = $self->NextTagKey($key) or last;
     7762                $size += $self->GetValue($key, 'ValueConv');
     7763            }
     7764            return int($size * 8 / $val[1] + 0.5);
    20617765        },
    20627766        PrintConv => 'ConvertBitrate($val)',
     
    20667770        Groups => { 2 => 'Location' },
    20677771        ValueConv => 'my @c = split " ", $val; $c[0]',
    2068         PrintConv => q{
    2069             require Image::ExifTool::GPS;
    2070             Image::ExifTool::GPS::ToDMS($self, $val, 1, 'N');
    2071         },
     7772        PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
    20727773    },
    20737774    GPSLongitude => {
     
    20757776        Groups => { 2 => 'Location' },
    20767777        ValueConv => 'my @c = split " ", $val; $c[1]',
    2077         PrintConv => q{
    2078             require Image::ExifTool::GPS;
    2079             Image::ExifTool::GPS::ToDMS($self, $val, 1, 'E');
    2080         },
     7778        PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
    20817779    },
    20827780    # split altitude into GPSAltitude/GPSAltitudeRef like EXIF and XMP
     
    20987796        },
    20997797    },
     7798    GPSLatitude2 => {
     7799        Name => 'GPSLatitude',
     7800        Require => 'QuickTime:LocationInformation',
     7801        Groups => { 2 => 'Location' },
     7802        ValueConv => '$val =~ /Lat=([-+.\d]+)/; $1',
     7803        PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "N")',
     7804    },
     7805    GPSLongitude2 => {
     7806        Name => 'GPSLongitude',
     7807        Require => 'QuickTime:LocationInformation',
     7808        Groups => { 2 => 'Location' },
     7809        ValueConv => '$val =~ /Lon=([-+.\d]+)/; $1',
     7810        PrintConv => 'Image::ExifTool::GPS::ToDMS($self, $val, 1, "E")',
     7811    },
     7812    GPSAltitude2 => {
     7813        Name => 'GPSAltitude',
     7814        Require => 'QuickTime:LocationInformation',
     7815        Groups => { 2 => 'Location' },
     7816        ValueConv => '$val =~ /Alt=([-+.\d]+)/; abs($1)',
     7817        PrintConv => '"$val m"',
     7818    },
     7819    GPSAltitudeRef2  => {
     7820        Name => 'GPSAltitudeRef',
     7821        Require => 'QuickTime:LocationInformation',
     7822        Groups => { 2 => 'Location' },
     7823        ValueConv => '$val =~ /Alt=([-+.\d]+)/; $1 < 0 ? 1 : 0',
     7824        PrintConv => {
     7825            0 => 'Above Sea Level',
     7826            1 => 'Below Sea Level',
     7827        },
     7828    },
     7829    CDDBDiscPlayTime => {
     7830        Require => 'CDDB1Info',
     7831        Groups => { 2 => 'Audio' },
     7832        ValueConv => '$val =~ /^..([a-z0-9]{4})/i ? hex($1) : undef',
     7833        PrintConv => 'ConvertDuration($val)',
     7834    },
     7835    CDDBDiscTracks => {
     7836        Require => 'CDDB1Info',
     7837        Groups => { 2 => 'Audio' },
     7838        ValueConv => '$val =~ /^.{6}([a-z0-9]{2})/i ? hex($1) : undef',
     7839    },
    21007840);
    21017841
     
    21037843Image::ExifTool::AddCompositeTags('Image::ExifTool::QuickTime');
    21047844
     7845
     7846#------------------------------------------------------------------------------
     7847# AutoLoad our routines when necessary
     7848#
     7849sub AUTOLOAD
     7850{
     7851    # (Note: no need to autoload routines in QuickTimeStream that use Stream table)
     7852    if ($AUTOLOAD eq 'Image::ExifTool::QuickTime::Process_mebx') {
     7853        require 'Image/ExifTool/QuickTimeStream.pl';
     7854        no strict 'refs';
     7855        return &$AUTOLOAD(@_);
     7856    } else {
     7857        return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_);
     7858    }
     7859}
     7860
     7861#------------------------------------------------------------------------------
     7862# Get rotation matrix
     7863# Inputs: 0) angle in degrees
     7864# Returns: 9-element rotation matrix as a string (with 0 x/y offsets)
     7865sub GetRotationMatrix($)
     7866{
     7867    my $ang = 3.1415926536 * shift() / 180;
     7868    my $cos = cos $ang;
     7869    my $sin = sin $ang;
     7870    my $msn = -$sin;
     7871    return "$cos $sin 0 $msn $cos 0 0 0 1";
     7872}
     7873
     7874#------------------------------------------------------------------------------
     7875# Get rotation angle from a matrix
     7876# Inputs: 0) rotation matrix as a string
     7877# Return: positive rotation angle in degrees rounded to 3 decimal points,
     7878#         or undef on error
     7879sub GetRotationAngle($)
     7880{
     7881    my $rotMatrix = shift;
     7882    my @a = split ' ', $rotMatrix;
     7883    return undef if $a[0]==0 and $a[1]==0;
     7884    # calculate the rotation angle (assume uniform rotation)
     7885    my $angle = atan2($a[1], $a[0]) * 180 / 3.14159;
     7886    $angle += 360 if $angle < 0;
     7887    return int($angle * 1000 + 0.5) / 1000;
     7888}
    21057889
    21067890#------------------------------------------------------------------------------
     
    21107894sub CalcRotation($)
    21117895{
    2112     my $exifTool = shift;
    2113     my $value = $$exifTool{VALUE};
     7896    my $et = shift;
     7897    my $value = $$et{VALUE};
    21147898    my ($i, $track);
    2115     # get the video track family 1 group (ie. "Track1");
     7899    # get the video track family 1 group (eg. "Track1");
    21167900    for ($i=0; ; ++$i) {
    21177901        my $idx = $i ? " ($i)" : '';
     
    21197903        last unless $$value{$tag};
    21207904        next unless $$value{$tag} eq 'vide';
    2121         $track = $exifTool->GetGroup($tag, 1);
     7905        $track = $et->GetGroup($tag, 1);
    21227906        last;
    21237907    }
     
    21287912        my $tag = "MatrixStructure$idx";
    21297913        last unless $$value{$tag};
    2130         next unless $exifTool->GetGroup($tag, 1) eq $track;
    2131         my @a = split ' ', $$value{$tag};
    2132         return undef unless $a[0] or $a[1];
    2133         # calculate the rotation angle (assume uniform rotation)
    2134         my $angle = atan2($a[1], $a[0]) * 180 / 3.14159;
    2135         $angle += 360 if $angle < 0;
    2136         return int($angle * 1000 + 0.5) / 1000;
     7914        next unless $et->GetGroup($tag, 1) eq $track;
     7915        return GetRotationAngle($$value{$tag});
    21377916    }
    21387917    return undef;
     7918}
     7919
     7920#------------------------------------------------------------------------------
     7921# Get MatrixStructure for a given rotation angle
     7922# Inputs: 0) rotation angle (deg), 1) ExifTool ref
     7923# Returns: matrix structure as a string, or undef if it can't be rotated
     7924# - requires ImageSizeLookahead to determine the video image size, and doesn't
     7925#   rotate matrix unless image size is valid
     7926sub GetMatrixStructure($$)
     7927{
     7928    my ($val, $et) = @_;
     7929    my @a = split ' ', $val;
     7930    # pass straight through if it already has an offset
     7931    return $val unless $a[6] == 0 and $a[7] == 0;
     7932    my @s = split ' ', $$et{ImageSizeLookahead};
     7933    my ($w, $h) = @s[12,13];
     7934    return undef unless $w and $h;  # don't rotate 0-sized track
     7935    $_ = Image::ExifTool::QuickTime::FixWrongFormat($_) foreach $w,$h;
     7936    # apply necessary offsets for the standard rotations
     7937    my $angle = GetRotationAngle($val);
     7938    return undef unless defined $angle;
     7939    if ($angle == 90) {
     7940        @a[6,7] = ($h, 0);
     7941    } elsif ($angle == 180) {
     7942        @a[6,7] = ($w, $h);
     7943    } elsif ($angle == 270) {
     7944        @a[6,7] = (0, $w);
     7945    }
     7946    return "@a";
    21397947}
    21407948
     
    21457953sub CalcSampleRate($$)
    21467954{
    2147     my ($exifTool, $valPt) = @_;
     7955    my ($et, $valPt) = @_;
    21487956    my @dat = unpack('N*', $$valPt);
    21497957    my ($num, $dur) = (0, 0);
     
    21537961        $dur += $dat[$i] * $dat[$i+1];  # total sample duration
    21547962    }
    2155     return undef unless $num and $dur and $$exifTool{MediaTS};
    2156     return $num * $$exifTool{MediaTS} / $dur;
     7963    return undef unless $num and $dur and $$et{MediaTS};
     7964    return $num * $$et{MediaTS} / $dur;
    21577965}
    21587966
     
    21637971    my $val = shift;
    21647972    return undef unless $val;
    2165     if ($val & 0xffff0000) {
    2166         $val = unpack('n',pack('N',$val));
    2167     }
    2168     return $val;
     7973    return $val & 0xfff00000 ? unpack('n',pack('N',$val)) : $val;
    21697974}
    21707975
     
    21727977# Convert ISO 6709 string to standard lag/lon format
    21737978# Inputs: 0) ISO 6709 string (lat, lon, and optional alt)
    2174 # Returns: position in decimal degress with altitude if available
     7979# Returns: position in decimal degrees with altitude if available
    21757980# Notes: Wikipedia indicates altitude may be in feet -- how is this specified?
    21767981sub ConvertISO6709($)
    21777982{
    21787983    my $val = shift;
    2179     if ($val =~ /^([-+]\d{2}(?:\.\d*)?)([-+]\d{3}(?:\.\d*)?)([-+]\d+)?/) {
     7984    if ($val =~ /^([-+]\d{1,2}(?:\.\d*)?)([-+]\d{1,3}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) {
     7985        # +DD.DDD+DDD.DDD+AA.AAA
    21807986        $val = ($1 + 0) . ' ' . ($2 + 0);
    21817987        $val .= ' ' . ($3 + 0) if $3;
    2182     } elsif ($val =~ /^([-+])(\d{2})(\d{2}(?:\.\d*)?)([-+])(\d{3})(\d{2}(?:\.\d*)?)([-+]\d+)?/) {
     7988    } elsif ($val =~ /^([-+])(\d{2})(\d{2}(?:\.\d*)?)([-+])(\d{3})(\d{2}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) {
     7989        # +DDMM.MMM+DDDMM.MMM+AA.AAA
    21837990        my $lat = $2 + $3 / 60;
    21847991        $lat = -$lat if $1 eq '-';
     
    21877994        $val = "$lat $lon";
    21887995        $val .= ' ' . ($7 + 0) if $7;
    2189     } elsif ($val =~ /^([-+])(\d{2})(\d{2})(\d{2}(?:\.\d*)?)([-+])(\d{3})(\d{2})(\d{2}(?:\.\d*)?)([-+]\d+)?/) {
     7996    } elsif ($val =~ /^([-+])(\d{2})(\d{2})(\d{2}(?:\.\d*)?)([-+])(\d{3})(\d{2})(\d{2}(?:\.\d*)?)([-+]\d+(?:\.\d*)?)?/) {
     7997        # +DDMMSS.SSS+DDDMMSS.SSS+AA.AAA
    21907998        my $lat = $2 + $3 / 60 + $4 / 3600;
    21917999        $lat = -$lat if $1 eq '-';
     
    21998007
    22008008#------------------------------------------------------------------------------
     8009# Convert Nero chapter list (ref ffmpeg libavformat/movenc.c)
     8010# Inputs: 0) binary chpl data
     8011# Returns: chapter list
     8012sub ConvertChapterList($)
     8013{
     8014    my $val = shift;
     8015    my $size = length $val;
     8016    return '<invalid>' if $size < 9;
     8017    my $num = Get8u(\$val, 8);
     8018    my ($i, @chapters);
     8019    my $pos = 9;
     8020    for ($i=0; $i<$num; ++$i) {
     8021        last if $pos + 9 > $size;
     8022        my $dur = Get64u(\$val, $pos) / 10000000;
     8023        my $len = Get8u(\$val, $pos + 8);
     8024        last if $pos + 9 + $len > $size;
     8025        my $title = substr($val, $pos + 9, $len);
     8026        $pos += 9 + $len;
     8027        push @chapters, "$dur $title";
     8028    }
     8029    return \@chapters;  # return as a list
     8030}
     8031
     8032#------------------------------------------------------------------------------
     8033# Print conversion for a Nero chapter list item
     8034# Inputs: 0) ValueConv chapter string
     8035# Returns: formatted chapter string
     8036sub PrintChapter($)
     8037{
     8038    my $val = shift;
     8039    $val =~ /^(\S+) (.*)/ or return $val;
     8040    my ($dur, $title) = ($1, $2);
     8041    my $h = int($dur / 3600);
     8042    $dur -= $h * 3600;
     8043    my $m = int($dur / 60);
     8044    my $s = $dur - $m * 60;
     8045    my $ss = sprintf('%06.3f', $s);
     8046    if ($ss >= 60) {
     8047        $ss = '00.000';
     8048        ++$m >= 60 and $m -= 60, ++$h;
     8049    }
     8050    return sprintf("[%d:%.2d:%s] %s",$h,$m,$ss,$title);
     8051}
     8052
     8053#------------------------------------------------------------------------------
    22018054# Format GPSCoordinates for printing
    22028055# Inputs: 0) string with numerical lat, lon and optional alt, separated by spaces
     
    22058058sub PrintGPSCoordinates($)
    22068059{
    2207     my ($val, $exifTool) = @_;
    2208     require Image::ExifTool::GPS;
     8060    my ($val, $et) = @_;
    22098061    my @v = split ' ', $val;
    2210     my $prt = Image::ExifTool::GPS::ToDMS($exifTool, $v[0], 1, "N") . ', ' .
    2211               Image::ExifTool::GPS::ToDMS($exifTool, $v[1], 1, "E");
     8062    my $prt = Image::ExifTool::GPS::ToDMS($et, $v[0], 1, "N") . ', ' .
     8063              Image::ExifTool::GPS::ToDMS($et, $v[1], 1, "E");
    22128064    if (defined $v[2]) {
    22138065        $prt .= ', ' . ($v[2] < 0 ? -$v[2] . ' m Below' : $v[2] . ' m Above') . ' Sea Level';
     
    22188070#------------------------------------------------------------------------------
    22198071# Unpack packed ISO 639/T language code
    2220 # Inputs: 0) packed language code (or undef)
    2221 # Returns: language code, or undef for default language, or 'err' for format error
    2222 sub UnpackLang($)
     8072# Inputs: 0) packed language code (or undef/0), 1) true to not treat 'und' and 'eng' as default
     8073# Returns: language code, or undef/0 for default language, or 'err' for format error
     8074sub UnpackLang($;$)
    22238075{
    2224     my $lang = shift;
     8076    my ($lang, $noDef) = @_;
    22258077    if ($lang) {
    22268078        # language code is packed in 5-bit characters
    2227         $lang = pack "C*", map { (($lang>>$_)&0x1f)+0x60 } 10, 5, 0;
     8079        $lang = pack 'C*', map { (($lang>>$_)&0x1f)+0x60 } 10, 5, 0;
    22288080        # validate language code
    22298081        if ($lang =~ /^[a-z]+$/) {
    22308082            # treat 'eng' or 'und' as the default language
    2231             undef $lang if $lang eq 'und' or $lang eq 'eng';
     8083            undef $lang if ($lang eq 'und' or $lang eq 'eng') and not $noDef;
    22328084        } else {
    22338085            $lang = 'err';  # invalid language code
     
    22388090
    22398091#------------------------------------------------------------------------------
     8092# Get language code string given QuickTime language and country codes
     8093# Inputs: 0) numerical language code, 1) numerical country code, 2) no defaults
     8094# Returns: language code string (ie. "fra-FR") or undef for default language
     8095sub GetLangCode($;$$)
     8096{
     8097    my ($lang, $ctry, $noDef) = @_;
     8098    # ignore country ('ctry') and language lists ('lang') for now
     8099    undef $ctry if $ctry and $ctry <= 255;
     8100    undef $lang if $lang and $lang <= 255;
     8101    $lang = UnpackLang($lang, $noDef);
     8102    # add country code if specified
     8103    if ($ctry) {
     8104        $ctry = unpack('a2',pack('n',$ctry)); # unpack as ISO 3166-1
     8105        # treat 'ZZ' like a default country (see ref 12)
     8106        undef $ctry if $ctry eq 'ZZ';
     8107        if ($ctry and $ctry =~ /^[A-Z]{2}$/) {
     8108            $lang or $lang = 'und';
     8109            $lang .= "-$ctry";
     8110        }
     8111    }
     8112    return $lang;
     8113}
     8114
     8115#------------------------------------------------------------------------------
     8116# Get langInfo hash and save details about alt-lang tags
     8117# Inputs: 0) ExifTool ref, 1) tagInfo hash ref, 2) locale code
     8118# Returns: new tagInfo hash ref, or undef if invalid
     8119sub GetLangInfoQT($$$)
     8120{
     8121    my ($et, $tagInfo, $langCode) = @_;
     8122    my $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $langCode);
     8123    if ($langInfo) {
     8124        $$et{QTLang} or $$et{QTLang} = [ ];
     8125        push @{$$et{QTLang}}, $$langInfo{Name};
     8126    }
     8127    return $langInfo;
     8128}
     8129
     8130#------------------------------------------------------------------------------
     8131# Get variable-length integer from data (used by ParseItemLocation)
     8132# Inputs: 0) data ref, 1) start position, 2) integer size in bytes (0, 4 or 8),
     8133#         3) default value
     8134# Returns: integer value, and updates current position
     8135sub GetVarInt($$$;$)
     8136{
     8137    my ($dataPt, $pos, $n, $default) = @_;
     8138    my $len = length $$dataPt;
     8139    $_[1] = $pos + $n;  # update current position
     8140    return undef if $pos + $n > $len;
     8141    if ($n == 0) {
     8142        return $default || 0;
     8143    } elsif ($n == 4) {
     8144        return Get32u($dataPt, $pos);
     8145    } elsif ($n == 8) {
     8146        return Get64u($dataPt, $pos);
     8147    }
     8148    return undef;
     8149}
     8150
     8151#------------------------------------------------------------------------------
     8152# Get null-terminated string from binary data (used by ParseItemInfoEntry)
     8153# Inputs: 0) data ref, 1) start position
     8154# Returns: string, and updates current position
     8155sub GetString($$)
     8156{
     8157    my ($dataPt, $pos) = @_;
     8158    my $len = length $$dataPt;
     8159    my $str = '';
     8160    while ($pos < $len) {
     8161        my $ch = substr($$dataPt, $pos, 1);
     8162        ++$pos;
     8163        last if ord($ch) == 0;
     8164        $str .= $ch;
     8165    }
     8166    $_[1] = $pos;   # update current position
     8167    return $str;
     8168}
     8169
     8170#------------------------------------------------------------------------------
     8171# Get a printable version of the tag ID
     8172# Inputs: 0) tag ID, 1) Flag: 0x01 - print as 4- or 8-digit hex value if necessary
     8173#                             0x02 - put leading backslash before escaped character
     8174# Returns: Printable tag ID
     8175sub PrintableTagID($;$)
     8176{
     8177    my $tag = $_[0];
     8178    my $n = ($tag =~ s/([\x00-\x1f\x7f-\xff])/'x'.unpack('H*',$1)/eg);
     8179    if ($n and $_[1]) {
     8180        if ($n > 2 and $_[1] & 0x01) {
     8181            $tag = '0x' . unpack('H8', $_[0]);
     8182            $tag =~ s/^0x0000/0x/;
     8183        } elsif ($_[1] & 0x02) {
     8184            ($tag = $_[0]) =~ s/([\x00-\x1f\x7f-\xff])/'\\x'.unpack('H*',$1)/eg;
     8185        }
     8186    }
     8187    return $tag;
     8188}
     8189
     8190#==============================================================================
     8191# The following ParseXxx routines parse various boxes to extract this
     8192# information about embedded items in a $$et{ItemInfo} hash, keyed by item ID:
     8193#
     8194# iloc:
     8195#  ConstructionMethod - offset type: 0=file, 1=idat, 2=item
     8196#  DataReferenceIndex - 0 for "this file", otherwise index in dref box
     8197#  BaseOffset         - base for file offsets
     8198#  Extents            - list of details for data in file:
     8199#                           0) index  (extent_index)
     8200#                           1) offset (extent_offset)
     8201#                           2) length (extent_length)
     8202#                           3) nlen   (length_size)
     8203#                           4) lenPt  (pointer to length word)
     8204# infe:
     8205#  ProtectionIndex    - index if item is protected (0 for unprotected)
     8206#  Name               - item name
     8207#  ContentType        - mime type of item
     8208#  ContentEncoding    - item encoding
     8209#  URI                - URI of a 'uri '-type item
     8210# ipma:
     8211#  Association        - list of associated properties in the ipco container
     8212#  Essential          - list of "essential" flags for the associated properties
     8213# cdsc:
     8214#  RefersTo           - hash lookup of flags based on referred item ID
     8215# other:
     8216#  DocNum             - exiftool document number for this item
     8217#
     8218#------------------------------------------------------------------------------
     8219# Parse item location (iloc) box (ref ISO 14496-12:2015 pg.79)
     8220# Inputs: 0) iloc data, 1) ExifTool ref
     8221# Returns: undef, and fills in ExifTool ItemInfo hash
     8222# Notes: see also Handle_iloc() in WriteQuickTime.pl
     8223sub ParseItemLocation($$)
     8224{
     8225    my ($val, $et) = @_;
     8226    my ($i, $j, $num, $pos, $id);
     8227    my ($extent_index, $extent_offset, $extent_length);
     8228
     8229    my $verbose = $$et{IsWriting} ? 0 : $et->Options('Verbose');
     8230    my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { });
     8231    my $len = length $val;
     8232    return undef if $len < 8;
     8233    my $ver = Get8u(\$val, 0);
     8234    my $siz = Get16u(\$val, 4);
     8235    my $noff = ($siz >> 12);
     8236    my $nlen = ($siz >> 8) & 0x0f;
     8237    my $nbas = ($siz >> 4) & 0x0f;
     8238    my $nind = $siz & 0x0f;
     8239    if ($ver < 2) {
     8240        $num = Get16u(\$val, 6);
     8241        $pos = 8;
     8242    } else {
     8243        return undef if $len < 10;
     8244        $num = Get32u(\$val, 6);
     8245        $pos = 10;
     8246    }
     8247    for ($i=0; $i<$num; ++$i) {
     8248        if ($ver < 2) {
     8249            return undef if $pos + 2 > $len;
     8250            $id = Get16u(\$val, $pos);
     8251            $pos += 2;
     8252        } else {
     8253            return undef if $pos + 4 > $len;
     8254            $id = Get32u(\$val, $pos);
     8255            $pos += 4;
     8256        }
     8257        if ($ver == 1 or $ver == 2) {
     8258            return undef if $pos + 2 > $len;
     8259            $$items{$id}{ConstructionMethod} = Get16u(\$val, $pos) & 0x0f;
     8260            $pos += 2;
     8261        }
     8262        return undef if $pos + 2 > $len;
     8263        $$items{$id}{DataReferenceIndex} = Get16u(\$val, $pos);
     8264        $pos += 2;
     8265        $$items{$id}{BaseOffset} = GetVarInt(\$val, $pos, $nbas);
     8266        return undef if $pos + 2 > $len;
     8267        my $ext_num = Get16u(\$val, $pos);
     8268        $pos += 2;
     8269        my @extents;
     8270        for ($j=0; $j<$ext_num; ++$j) {
     8271            if ($ver == 1 or $ver == 2) {
     8272                $extent_index = GetVarInt(\$val, $pos, $nind, 1);
     8273            }
     8274            $extent_offset = GetVarInt(\$val, $pos, $noff);
     8275            $extent_length = GetVarInt(\$val, $pos, $nlen);
     8276            return undef unless defined $extent_length;
     8277            $et->VPrint(1, "$$et{INDENT}  Item $id: const_meth=",
     8278                defined $$items{$id}{ConstructionMethod} ? $$items{$id}{ConstructionMethod} : '',
     8279                sprintf(" base=0x%x offset=0x%x len=0x%x\n", $$items{$id}{BaseOffset},
     8280                    $extent_offset, $extent_length)) if $verbose;
     8281            push @extents, [ $extent_index, $extent_offset, $extent_length, $nlen, $pos-$nlen ];
     8282        }
     8283        # save item location information keyed on 1-based item ID:
     8284        $$items{$id}{Extents} = \@extents;
     8285    }
     8286    return undef;
     8287}
     8288
     8289#------------------------------------------------------------------------------
     8290# Parse content describes entry (cdsc) box
     8291# Inputs: 0) cdsc data, 1) ExifTool ref
     8292# Returns: undef, and fills in ExifTool ItemInfo hash
     8293sub ParseContentDescribes($$)
     8294{
     8295    my ($val, $et) = @_;
     8296    my ($id, $count, @to);
     8297    if ($$et{ItemRefVersion}) {
     8298        return undef if length $val < 10;
     8299        ($id, $count, @to) = unpack('NnN*', $val);
     8300    } else {
     8301        return undef if length $val < 6;
     8302        ($id, $count, @to) = unpack('nnn*', $val);
     8303    }
     8304    if ($count > @to) {
     8305        my $str = 'Missing values in ContentDescribes box';
     8306        $$et{IsWriting} ? $et->Error($str) : $et->Warn($str);
     8307    } elsif ($count < @to) {
     8308        $et->Warn('Ignored extra values in ContentDescribes box', 1);
     8309        @to = $count;
     8310    }
     8311    # add all referenced item ID's to a "RefersTo" lookup
     8312    $$et{ItemInfo}{$id}{RefersTo}{$_} = 1 foreach @to;
     8313    return undef;
     8314}
     8315
     8316#------------------------------------------------------------------------------
     8317# Parse item information entry (infe) box (ref ISO 14496-12:2015 pg.82)
     8318# Inputs: 0) infe data, 1) ExifTool ref
     8319# Returns: undef, and fills in ExifTool ItemInfo hash
     8320sub ParseItemInfoEntry($$)
     8321{
     8322    my ($val, $et) = @_;
     8323    my $id;
     8324
     8325    my $verbose = $$et{IsWriting} ? 0 : $et->Options('Verbose');
     8326    my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { });
     8327    my $len = length $val;
     8328    return undef if $len < 4;
     8329    my $ver = Get8u(\$val, 0);
     8330    my $pos = 4;
     8331    return undef if $pos + 4 > $len;
     8332    if ($ver == 0 or $ver == 1) {
     8333        $id = Get16u(\$val, $pos);
     8334        $$items{$id}{ProtectionIndex} = Get16u(\$val, $pos + 2);
     8335        $pos += 4;
     8336        $$items{$id}{Name} = GetString(\$val, $pos);
     8337        $$items{$id}{ContentType} = GetString(\$val, $pos);
     8338        $$items{$id}{ContentEncoding} = GetString(\$val, $pos);
     8339    } else {
     8340        if ($ver == 2) {
     8341            $id = Get16u(\$val, $pos);
     8342            $pos += 2;
     8343        } elsif ($ver == 3) {
     8344            $id = Get32u(\$val, $pos);
     8345            $pos += 4;
     8346        }
     8347        return undef if $pos + 6 > $len;
     8348        $$items{$id}{ProtectionIndex} = Get16u(\$val, $pos);
     8349        my $type = substr($val, $pos + 2, 4);
     8350        $$items{$id}{Type} = $type;
     8351        $pos += 6;
     8352        $$items{$id}{Name} = GetString(\$val, $pos);
     8353        if ($type eq 'mime') {
     8354            $$items{$id}{ContentType} = GetString(\$val, $pos);
     8355            $$items{$id}{ContentEncoding} = GetString(\$val, $pos);
     8356        } elsif ($type eq 'uri ') {
     8357            $$items{$id}{URI} = GetString(\$val, $pos);
     8358        }
     8359    }
     8360    $et->VPrint(1, "$$et{INDENT}  Item $id: Type=", $$items{$id}{Type} || '',
     8361                   ' Name=', $$items{$id}{Name} || '',
     8362                   ' ContentType=', $$items{$id}{ContentType} || '',
     8363                   "\n") if $verbose > 1;
     8364    return undef;
     8365}
     8366
     8367#------------------------------------------------------------------------------
     8368# Parse item property association (ipma) box (ref https://github.com/gpac/gpac/blob/master/src/isomedia/iff.c)
     8369# Inputs: 0) ipma data, 1) ExifTool ref
     8370# Returns: undef, and fills in ExifTool ItemInfo hash
     8371sub ParseItemPropAssoc($$)
     8372{
     8373    my ($val, $et) = @_;
     8374    my ($i, $j, $id);
     8375
     8376    my $verbose = $$et{IsWriting} ? 0 : $et->Options('Verbose');
     8377    my $items = $$et{ItemInfo} || ($$et{ItemInfo} = { });
     8378    my $len = length $val;
     8379    return undef if $len < 8;
     8380    my $ver = Get8u(\$val, 0);
     8381    my $flg = Get32u(\$val, 0);
     8382    my $num = Get32u(\$val, 4);
     8383    my $pos = 8;
     8384    for ($i=0; $i<$num; ++$i) {
     8385        if ($ver == 0) {
     8386            return undef if $pos + 3 > $len;
     8387            $id = Get16u(\$val, $pos);
     8388            $pos += 2;
     8389        } else {
     8390            return undef if $pos + 5 > $len;
     8391            $id = Get32u(\$val, $pos);
     8392            $pos += 4;
     8393        }
     8394        my $n = Get8u(\$val, $pos++);
     8395        my (@association, @essential);
     8396        if ($flg & 0x01) {
     8397            return undef if $pos + $n * 2 > $len;
     8398            for ($j=0; $j<$n; ++$j) {
     8399                my $tmp = Get16u(\$val, $pos + $j * 2);
     8400                push @association, $tmp & 0x7fff;
     8401                push @essential, ($tmp & 0x8000) ? 1 : 0;
     8402            }
     8403            $pos += $n * 2;
     8404        } else {
     8405            return undef if $pos + $n > $len;
     8406            for ($j=0; $j<$n; ++$j) {
     8407                my $tmp = Get8u(\$val, $pos + $j);
     8408                push @association, $tmp & 0x7f;
     8409                push @essential, ($tmp & 0x80) ? 1 : 0;
     8410            }
     8411            $pos += $n;
     8412        }
     8413        $$items{$id}{Association} = \@association;
     8414        $$items{$id}{Essential} = \@essential;
     8415        $et->VPrint(1, "$$et{INDENT}  Item $id properties: @association\n") if $verbose > 1;
     8416    }
     8417    return undef;
     8418}
     8419
     8420#------------------------------------------------------------------------------
     8421# Process item information now
     8422# Inputs: 0) ExifTool ref
     8423sub HandleItemInfo($)
     8424{
     8425    my $et = shift;
     8426    my $raf = $$et{RAF};
     8427    my $items = $$et{ItemInfo};
     8428    my $verbose = $et->Options('Verbose');
     8429    my $buff;
     8430
     8431    # extract information from EXIF/XMP metadata items
     8432    if ($items and $raf) {
     8433        push @{$$et{PATH}}, 'ItemInformation';
     8434        my $curPos = $raf->Tell();
     8435        my $primary = $$et{PrimaryItem};
     8436        my $id;
     8437        $et->VerboseDir('Processing items from ItemInformation', scalar(keys %$items));
     8438        foreach $id (sort { $a <=> $b } keys %$items) {
     8439            my $item = $$items{$id};
     8440            my $type = $$item{ContentType} || $$item{Type} || next;
     8441            if ($verbose) {
     8442                # add up total length of this item for the verbose output
     8443                my $len = 0;
     8444                if ($$item{Extents} and @{$$item{Extents}}) {
     8445                    $len += $$_[2] foreach @{$$item{Extents}};
     8446                }
     8447                $et->VPrint(0, "$$et{INDENT}Item $id) '${type}' ($len bytes)\n");
     8448            }
     8449            # get ExifTool name for this item
     8450            my $name = { Exif => 'EXIF', 'application/rdf+xml' => 'XMP' }->{$type} || '';
     8451            my ($warn, $extent);
     8452            $warn = "Can't currently decode encoded $type metadata" if $$item{ContentEncoding};
     8453            $warn = "Can't currently decode protected $type metadata" if $$item{ProtectionIndex};
     8454            $warn = "Can't currently extract $type with construction method $$item{ConstructionMethod}" if $$item{ConstructionMethod};
     8455            $et->WarnOnce($warn) if $warn and $name;
     8456            $warn = 'Not this file' if $$item{DataReferenceIndex}; # (can only extract from "this file")
     8457            unless (($$item{Extents} and @{$$item{Extents}}) or $warn) {
     8458                $warn = "No Extents for $type item";
     8459                $et->WarnOnce($warn) if $name;
     8460            }
     8461            if ($warn) {
     8462                $et->VPrint(0, "$$et{INDENT}    [not extracted]  ($warn)\n") if $verbose > 2;
     8463                next;
     8464            }
     8465            my $base = $$item{BaseOffset} || 0;
     8466            if ($verbose > 2) {
     8467                # do verbose hex dump
     8468                my $len = 0;
     8469                undef $buff;
     8470                my $val = '';
     8471                my $maxLen = $verbose > 3 ? 2048 : 96;
     8472                foreach $extent (@{$$item{Extents}}) {
     8473                    my $n = $$extent[2];
     8474                    my $more = $maxLen - $len;
     8475                    if ($more > 0 and $n) {
     8476                        $more = $n if $more > $n;
     8477                        $val .= $buff if defined $buff;
     8478                        $raf->Seek($$extent[1] + $base, 0) or last;
     8479                        $raf->Read($buff, $more) or last;
     8480                    }
     8481                    $len += $n;
     8482                }
     8483                if (defined $buff) {
     8484                    $buff = $val . $buff if length $val;
     8485                    $et->VerboseDump(\$buff, DataPos => $$item{Extents}[0][1] + $base);
     8486                    my $snip = $len - length $buff;
     8487                    $et->VPrint(0, "$$et{INDENT}    [snip $snip bytes]\n") if $snip;
     8488                }
     8489            }
     8490            next unless $name;
     8491            # assemble the data for this item
     8492            undef $buff;
     8493            my $val = '';
     8494            foreach $extent (@{$$item{Extents}}) {
     8495                $val .= $buff if defined $buff;
     8496                $raf->Seek($$extent[1] + $base, 0) or last;
     8497                $raf->Read($buff, $$extent[2]) or last;
     8498            }
     8499            next unless defined $buff;
     8500            $buff = $val . $buff if length $val;
     8501            next unless length $buff;   # ignore empty directories
     8502            my ($start, $subTable, $proc);
     8503            my $pos = $$item{Extents}[0][1] + $base;
     8504            if ($name eq 'EXIF' and length $buff >= 4) {
     8505                if ($buff =~ /^(MM\0\x2a|II\x2a\0)/) {
     8506                    $et->Warn('Missing Exif header');
     8507                    $start = 0;
     8508                } elsif ($buff =~ /^Exif\0\0/) {
     8509                    # (haven't seen this yet, but it is just a matter of time
     8510                    #  until someone screws it up like this)
     8511                    $et->Warn('Missing Exif header size');
     8512                    $start = 6;
     8513                } else {
     8514                    my $n = unpack('N', $buff);
     8515                    $start = 4 + $n; # skip "Exif\0\0" header if it exists
     8516                    if ($start > length($buff)) {
     8517                        $et->Warn('Invalid EXIF header');
     8518                        next;
     8519                    }
     8520                    if ($$et{HTML_DUMP}) {
     8521                        $et->HDump($pos, 4, 'Exif header length', "Value: $n");
     8522                        $et->HDump($pos+4, $start-4, 'Exif header') if $n;
     8523                    }
     8524                }
     8525                $subTable = GetTagTable('Image::ExifTool::Exif::Main');
     8526                $proc = \&Image::ExifTool::ProcessTIFF;
     8527            } else {
     8528                $start = 0;
     8529                $subTable = GetTagTable('Image::ExifTool::XMP::Main');
     8530            }
     8531            my %dirInfo = (
     8532                DataPt   => \$buff,
     8533                DataLen  => length $buff,
     8534                DirStart => $start,
     8535                DirLen   => length($buff) - $start,
     8536                DataPos  => $pos,
     8537                Base     => $pos + $start, # (needed for HtmlDump and IsOffset tags in binary data)
     8538            );
     8539            # handle processing of metadata for sub-documents
     8540            if (defined $primary and $$item{RefersTo} and not $$item{RefersTo}{$primary}) {
     8541                # set document number if this doesn't refer to the primary document
     8542                $$et{DOC_NUM} = ++$$et{DOC_COUNT};
     8543                # associate this document number with the lowest item index
     8544                my ($lowest) = sort { $a <=> $b } keys %{$$item{RefersTo}};
     8545                $$items{$lowest}{DocNum} = $$et{DOC_NUM};
     8546            }
     8547            $et->ProcessDirectory(\%dirInfo, $subTable, $proc);
     8548            delete $$et{DOC_NUM};
     8549        }
     8550        $raf->Seek($curPos, 0);     # seek back to original position
     8551        pop @{$$et{PATH}};
     8552    }
     8553    # process the item properties now that we should know their associations and document numbers
     8554    if ($$et{ItemPropertyContainer}) {
     8555        my ($dirInfo, $subTable, $proc) = @{$$et{ItemPropertyContainer}};
     8556        $$et{IsItemProperty} = 1;   # set item property flag
     8557        $et->ProcessDirectory($dirInfo, $subTable, $proc);
     8558        delete $$et{ItemPropertyContainer};
     8559        delete $$et{IsItemProperty};
     8560        delete $$et{DOC_NUM};
     8561    }
     8562    delete $$et{ItemInfo};
     8563}
     8564
     8565#------------------------------------------------------------------------------
     8566# Warn if ExtractEmbedded option isn't used
     8567# Inputs: 0) ExifTool ref
     8568sub EEWarn($)
     8569{
     8570    my $et = shift;
     8571    $et->WarnOnce('The ExtractEmbedded option may find more tags in the media data',3);
     8572}
     8573
     8574#------------------------------------------------------------------------------
     8575# Get quicktime format from flags word
     8576# Inputs: 0) quicktime atom flags, 1) data length
     8577# Returns: ExifTool format string
     8578sub QuickTimeFormat($$)
     8579{
     8580    my ($flags, $len) = @_;
     8581    my $format;
     8582    if ($flags == 0x15 or $flags == 0x16) {
     8583        $format = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len};
     8584        $format .= $flags == 0x15 ? 's' : 'u' if $format;
     8585    } elsif ($flags == 0x17) {
     8586        $format = 'float';
     8587    } elsif ($flags == 0x18) {
     8588        $format = 'double';
     8589    } elsif ($flags == 0x00) {
     8590        $format = { 1=>'int8u', 2=>'int16u' }->{$len};
     8591    }
     8592    return $format;
     8593}
     8594
     8595#------------------------------------------------------------------------------
    22408596# Process MPEG-4 MTDT atom (ref 11)
    22418597# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
     
    22438599sub ProcessMetaData($$$)
    22448600{
    2245     my ($exifTool, $dirInfo, $tagTablePtr) = @_;
     8601    my ($et, $dirInfo, $tagTablePtr) = @_;
    22468602    my $dataPt = $$dirInfo{DataPt};
    22478603    my $dirLen = length $$dataPt;
    2248     my $verbose = $exifTool->Options('Verbose');
     8604    my $verbose = $et->Options('Verbose');
    22498605    return 0 unless $dirLen >= 2;
    22508606    my $count = Get16u($dataPt, 0);
    2251     $verbose and $exifTool->VerboseDir('MetaData', $count);
     8607    $verbose and $et->VerboseDir('MetaData', $count);
    22528608    my $i;
    22538609    my $pos = 2;
     
    22608616        my $enc  = Get16u($dataPt, $pos + 8);
    22618617        my $val  = substr($$dataPt, $pos + 10, $size);
    2262         my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag);
     8618        my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
    22638619        if ($tagInfo) {
    22648620            # convert language code to ASCII (ignore read-only bit)
     
    22668622            # handle alternate languages
    22678623            if ($lang) {
    2268                 my $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $lang);
     8624                my $langInfo = GetLangInfoQT($et, $tagInfo, $lang);
    22698625                $tagInfo = $langInfo if $langInfo;
    22708626            }
    2271             $verbose and $exifTool->VerboseInfo($tag, $tagInfo,
     8627            $verbose and $et->VerboseInfo($tag, $tagInfo,
    22728628                Value  => $val,
    22738629                DataPt => $dataPt,
     
    22768632            );
    22778633            # convert from UTF-16 BE if necessary
    2278             $val = $exifTool->Decode($val, 'UCS2') if $enc == 1;
     8634            $val = $et->Decode($val, 'UCS2') if $enc == 1;
    22798635            if ($enc == 0 and $$tagInfo{Unknown}) {
    22808636                # binary data
    2281                 $exifTool->FoundTag($tagInfo, \$val);
     8637                $et->FoundTag($tagInfo, \$val);
    22828638            } else {
    2283                 $exifTool->FoundTag($tagInfo, $val);
     8639                $et->FoundTag($tagInfo, $val);
    22848640            }
    22858641        }
     
    22908646
    22918647#------------------------------------------------------------------------------
    2292 # Process Meta keys and add tags to the ItemList table ('mdta' handler) (ref PH)
     8648# Process sample description table
     8649# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
     8650# Returns: 1 on success
     8651# (ref https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25691)
     8652sub ProcessSampleDesc($$$)
     8653{
     8654    my ($et, $dirInfo, $tagTablePtr) = @_;
     8655    my $dataPt = $$dirInfo{DataPt};
     8656    my $pos = $$dirInfo{DirStart} || 0;
     8657    my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $pos);
     8658    return 0 if $pos + 8 > $dirLen;
     8659
     8660    my $num = Get32u($dataPt, 4);   # get number of sample entries in table
     8661    $pos += 8;
     8662    my $i;
     8663    for ($i=0; $i<$num; ++$i) {     # loop through sample entries
     8664        last if $pos + 8 > $dirLen;
     8665        my $size = Get32u($dataPt, $pos);
     8666        last if $pos + $size > $dirLen;
     8667        $$dirInfo{DirStart} = $pos;
     8668        $$dirInfo{DirLen} = $size;
     8669        ProcessHybrid($et, $dirInfo, $tagTablePtr);
     8670        $pos += $size;
     8671    }
     8672    return 1;
     8673}
     8674
     8675#------------------------------------------------------------------------------
     8676# Process hybrid binary data + QuickTime container (ref PH)
     8677# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
     8678# Returns: 1 on success
     8679sub ProcessHybrid($$$)
     8680{
     8681    my ($et, $dirInfo, $tagTablePtr) = @_;
     8682    # brute-force search for child atoms after first 8 bytes of binary data
     8683    my $dataPt = $$dirInfo{DataPt};
     8684    my $dirStart = $$dirInfo{DirStart} || 0;
     8685    my $dirLen = $$dirInfo{DirLen} || length($$dataPt) - $dirStart;
     8686    my $end = $dirStart + $dirLen;
     8687    my $pos = $dirStart + 8;   # skip length/version
     8688    my $try = $pos;
     8689    my $childPos;
     8690
     8691    while ($pos <= $end - 8) {
     8692        my $tag = substr($$dataPt, $try+4, 4);
     8693        # look only for well-behaved tag ID's
     8694        $tag =~ /[^\w ]/ and $try = ++$pos, next;
     8695        my $size = Get32u($dataPt, $try);
     8696        if ($size + $try == $end) {
     8697            # the atom ends exactly at the end of the parent -- this must be it
     8698            $childPos = $pos;
     8699            $$dirInfo{DirLen} = $pos;   # the binary data ends at the first child atom
     8700            last;
     8701        }
     8702        if ($size < 8 or $size + $try > $end - 8) {
     8703            $try = ++$pos;  # fail.  try next position
     8704        } else {
     8705            $try += $size;  # could be another atom following this
     8706        }
     8707    }
     8708    # process binary data
     8709    $$dirInfo{MixedTags} = 1; # ignore non-integer tag ID's
     8710    $et->ProcessBinaryData($dirInfo, $tagTablePtr);
     8711    # process child atoms if found
     8712    if ($childPos) {
     8713        $$dirInfo{DirStart} = $childPos;
     8714        $$dirInfo{DirLen} = $end - $childPos;
     8715        ProcessMOV($et, $dirInfo, $tagTablePtr);
     8716    }
     8717    return 1;
     8718}
     8719
     8720#------------------------------------------------------------------------------
     8721# Process iTunes 'righ' atom (ref PH)
     8722# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
     8723# Returns: 1 on success
     8724sub ProcessRights($$$)
     8725{
     8726    my ($et, $dirInfo, $tagTablePtr) = @_;
     8727    my $dataPt = $$dirInfo{DataPt};
     8728    my $dataPos = $$dirInfo{Base};
     8729    my $dirLen = length $$dataPt;
     8730    my $unknown = $$et{OPTIONS}{Unknown} || $$et{OPTIONS}{Verbose};
     8731    my $pos;
     8732    $et->VerboseDir('righ', $dirLen / 8);
     8733    for ($pos = 0; $pos + 8 <= $dirLen; $pos += 8) {
     8734        my $tag = substr($$dataPt, $pos, 4);
     8735        last if $tag eq "\0\0\0\0";
     8736        my $val = substr($$dataPt, $pos + 4, 4);
     8737        my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
     8738        unless ($tagInfo) {
     8739            next unless $unknown;
     8740            my $name = PrintableTagID($tag);
     8741            $tagInfo = {
     8742                Name => "Unknown_$name",
     8743                Description => "Unknown $name",
     8744                Unknown => 1,
     8745            },
     8746            AddTagToTable($tagTablePtr, $tag, $tagInfo);
     8747        }
     8748        $val = '0x' . unpack('H*', $val) unless $$tagInfo{Format};
     8749        $et->HandleTag($tagTablePtr, $tag, $val,
     8750            DataPt  => $dataPt,
     8751            DataPos => $dataPos,
     8752            Start   => $pos + 4,
     8753            Size    => 4,
     8754        );
     8755    }
     8756    return 1;
     8757}
     8758
     8759#------------------------------------------------------------------------------
     8760# Process iTunes Encoding Params (ref PH)
     8761# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
     8762# Returns: 1 on success
     8763sub ProcessEncodingParams($$$)
     8764{
     8765    my ($et, $dirInfo, $tagTablePtr) = @_;
     8766    my $dataPt = $$dirInfo{DataPt};
     8767    my $dirLen = length $$dataPt;
     8768    my $pos;
     8769    $et->VerboseDir('Encoding Params', $dirLen / 8);
     8770    for ($pos = 0; $pos + 8 <= $dirLen; $pos += 8) {
     8771        my ($tag, $val) = unpack("x${pos}a4N", $$dataPt);
     8772        $et->HandleTag($tagTablePtr, $tag, $val);
     8773    }
     8774    return 1;
     8775}
     8776
     8777#------------------------------------------------------------------------------
     8778# Read Meta Keys and add tags to ItemList table ('mdta' handler) (ref PH)
    22938779# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
    22948780# Returns: 1 on success
    22958781sub ProcessKeys($$$)
    22968782{
    2297     my ($exifTool, $dirInfo, $tagTablePtr) = @_;
     8783    local $_;
     8784    my ($et, $dirInfo, $tagTablePtr) = @_;
    22988785    my $dataPt = $$dirInfo{DataPt};
    22998786    my $dirLen = length $$dataPt;
    23008787    my $out;
    2301     if ($exifTool->Options('Verbose')) {
    2302         $exifTool->VerboseDir('Keys');
    2303         $out = $exifTool->Options('TextOut');
     8788    if ($et->Options('Verbose')) {
     8789        $et->VerboseDir('Keys');
     8790        $out = $et->Options('TextOut');
    23048791    }
    23058792    my $pos = 8;
    23068793    my $index = 1;
    2307     my $infoTable = GetTagTable('Image::ExifTool::QuickTime::ItemList');
    2308     my $userTable = GetTagTable('Image::ExifTool::QuickTime::UserData');
     8794    ++$$et{KeysCount};  # increment key count for this directory
     8795    my $itemList = GetTagTable('Image::ExifTool::QuickTime::ItemList');
     8796    my $userData = GetTagTable('Image::ExifTool::QuickTime::UserData');
    23098797    while ($pos < $dirLen - 4) {
    23108798        my $len = unpack("x${pos}N", $$dataPt);
     
    23148802        my $tag = substr($$dataPt, $pos + 8, $len - 8);
    23158803        $tag =~ s/\0.*//s; # truncate at null
    2316         if ($ns eq 'mdta') {
    2317             $tag =~ s/^com\.apple\.quicktime\.//;   # remove common apple quicktime domain
    2318         }
    2319         next unless $tag;
     8804        $tag =~ s/^com\.(apple\.quicktime\.)?// if $ns eq 'mdta'; # remove apple quicktime domain
     8805        $tag = "Tag_$ns" unless $tag;
    23208806        # (I have some samples where the tag is a reversed ItemList or UserData tag ID)
    2321         my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag);
     8807        my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
    23228808        unless ($tagInfo) {
    2323             $tagInfo = $exifTool->GetTagInfo($infoTable, $tag);
     8809            $tagInfo = $et->GetTagInfo($itemList, $tag);
    23248810            unless ($tagInfo) {
    2325                 $tagInfo = $exifTool->GetTagInfo($userTable, $tag);
     8811                $tagInfo = $et->GetTagInfo($userData, $tag);
    23268812                if (not $tagInfo and $tag =~ /^\w{3}\xa9$/) {
    23278813                    $tag = pack('N', unpack('V', $tag));
    2328                     $tagInfo = $exifTool->GetTagInfo($infoTable, $tag);
    2329                     $tagInfo or $tagInfo = $exifTool->GetTagInfo($userTable, $tag);
     8814                    $tagInfo = $et->GetTagInfo($itemList, $tag);
     8815                    $tagInfo or $tagInfo = $et->GetTagInfo($userData, $tag);
    23308816                }
    23318817            }
    23328818        }
    2333         my $newInfo;
     8819        my ($newInfo, $msg);
    23348820        if ($tagInfo) {
     8821            # copy tag information into new Keys tag
    23358822            $newInfo = {
    23368823                Name      => $$tagInfo{Name},
    23378824                Format    => $$tagInfo{Format},
    23388825                ValueConv => $$tagInfo{ValueConv},
     8826                ValueConvInv => $$tagInfo{ValueConvInv},
    23398827                PrintConv => $$tagInfo{PrintConv},
     8828                PrintConvInv => $$tagInfo{PrintConvInv},
     8829                Writable  => defined $$tagInfo{Writable} ? $$tagInfo{Writable} : 1,
     8830                SubDirectory => $$tagInfo{SubDirectory},
    23408831            };
    23418832            my $groups = $$tagInfo{Groups};
    2342             $$newInfo{Groups} = { %$groups } if $groups;
    2343         } elsif ($tag =~ /^[-\w.]+$/) {
     8833            $$newInfo{Groups} = $groups ? { %$groups } : { };
     8834            $$newInfo{Groups}{$_} or $$newInfo{Groups}{$_} = $$tagTablePtr{GROUPS}{$_} foreach 0..2;
     8835            $$newInfo{Groups}{1} = 'Keys';
     8836        } elsif ($tag =~ /^[-\w. ]+$/ or $tag =~ /\w{4}/) {
    23448837            # create info for tags with reasonable id's
    2345             my $name = $tag;
    2346             $name =~ s/\.(.)/\U$1/g;
    2347             $newInfo = { Name => ucfirst($name) };
     8838            my $name = ucfirst $tag;
     8839            $name =~ tr/-0-9a-zA-Z_. //dc;
     8840            $name =~ s/[. ]+(.?)/\U$1/g;
     8841            $name =~ s/_([a-z])/_\U$1/g;
     8842            $name =~ s/([a-z])_([A-Z])/$1$2/g;
     8843            $name = "Tag_$name" if length $name < 2;
     8844            $newInfo = { Name => $name, Groups => { 1 => 'Keys' } };
     8845            $msg = ' (Unknown)';
    23488846        }
    23498847        # substitute this tag in the ItemList table with the given index
    2350         delete $$infoTable{$index};
     8848        my $id = $$et{KeysCount} . '.' . $index;
     8849        if (ref $$itemList{$id} eq 'HASH') {
     8850            # delete other languages too if they exist
     8851            my $oldInfo = $$itemList{$id};
     8852            if ($$oldInfo{OtherLang}) {
     8853                delete $$itemList{$_} foreach @{$$oldInfo{OtherLang}};
     8854            }
     8855            delete $$itemList{$id};
     8856        }
    23518857        if ($newInfo) {
    2352             Image::ExifTool::AddTagToTable($infoTable, $index, $newInfo);
    2353             $out and printf $out "%sAdded ItemList Tag 0x%.4x = $tag\n", $exifTool->{INDENT}, $index;
     8858            AddTagToTable($itemList, $id, $newInfo);
     8859            $msg or $msg = '';
     8860            $out and print $out "$$et{INDENT}Added ItemList Tag $id = ($ns) $tag$msg\n";
    23548861        }
    23558862        $pos += $len;
     
    23608867
    23618868#------------------------------------------------------------------------------
     8869# Process keys in MetaSampleDesc directory
     8870# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
     8871# Returns: 1 on success
     8872sub ProcessMetaKeys($$$)
     8873{
     8874    my ($et, $dirInfo, $tagTablePtr) = @_;
     8875    # save this information to decode timed metadata samples when ExtractEmbedded is used
     8876    SaveMetaKeys($et, $dirInfo, $tagTablePtr) if $$et{OPTIONS}{ExtractEmbedded};
     8877    return 1;
     8878}
     8879
     8880#------------------------------------------------------------------------------
    23628881# Process a QuickTime atom
    23638882# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) optional tag table ref
     
    23658884sub ProcessMOV($$;$)
    23668885{
    2367     my ($exifTool, $dirInfo, $tagTablePtr) = @_;
     8886    local $_;
     8887    my ($et, $dirInfo, $tagTablePtr) = @_;
    23688888    my $raf = $$dirInfo{RAF};
    23698889    my $dataPt = $$dirInfo{DataPt};
    2370     my $verbose = $exifTool->Options('Verbose');
     8890    my $verbose = $et->Options('Verbose');
     8891    my $validate = $$et{OPTIONS}{Validate};
    23718892    my $dataPos = $$dirInfo{Base} || 0;
    2372     my ($buff, $tag, $size, $track);
    2373 
     8893    my $dirID = $$dirInfo{DirID} || '';
     8894    my $charsetQuickTime = $et->Options('CharsetQuickTime');
     8895    my ($buff, $tag, $size, $track, $isUserData, %triplet, $doDefaultLang, $index);
     8896    my ($dirEnd, $unkOpt, %saveOptions, $atomCount);
     8897
     8898    my $topLevel = not $$et{InQuickTime};
     8899    $$et{InQuickTime} = 1;
     8900    $$et{HandlerType} = $$et{MetaFormat} = '' unless defined $$et{HandlerType};
     8901
     8902    unless (defined $$et{KeysCount}) {
     8903        $$et{KeysCount} = 0;    # initialize ItemList key directory count
     8904        $doDefaultLang = 1;     # flag to generate default language tags
     8905    }
    23748906    # more convenient to package data as a RandomAccess file
    2375     $raf or $raf = new File::RandomAccess($dataPt);
     8907    unless ($raf) {
     8908        $raf = new File::RandomAccess($dataPt);
     8909        $dirEnd = $dataPos + $$dirInfo{DirLen} + ($$dirInfo{DirStart} || 0) if $$dirInfo{DirLen};
     8910    }
    23768911    # skip leading bytes if necessary
    23778912    if ($$dirInfo{DirStart}) {
     
    23828917    $raf->Read($buff,8) == 8 or return 0;
    23838918    $dataPos += 8;
    2384     $tagTablePtr or $tagTablePtr = GetTagTable('Image::ExifTool::QuickTime::Main');
     8919    if ($tagTablePtr) {
     8920        $isUserData = ($tagTablePtr eq \%Image::ExifTool::QuickTime::UserData);
     8921    } else {
     8922        $tagTablePtr = GetTagTable('Image::ExifTool::QuickTime::Main');
     8923    }
    23858924    ($size, $tag) = unpack('Na4', $buff);
    23868925    if ($dataPt) {
    2387         $verbose and $exifTool->VerboseDir($$dirInfo{DirName});
     8926        $verbose and $et->VerboseDir($$dirInfo{DirName});
    23888927    } else {
    23898928        # check on file type if called with a RAF
    23908929        $$tagTablePtr{$tag} or return 0;
    2391         if ($tag eq 'ftyp') {
    2392             # read ahead 4 bytes to see what type of file this is
     8930        if ($tag eq 'ftyp' and $size >= 12) {
     8931            # read ftyp atom to see what type of file this is
    23938932            my $fileType;
    2394             if ($raf->Read($buff, 4) == 4) {
    2395                 $raf->Seek(-4, 1);
     8933            if ($raf->Read($buff, $size-8) == $size-8) {
     8934                $raf->Seek(-($size-8), 1);
     8935                my $type = substr($buff, 0, 4);
    23968936                # see if we know the extension for this file type
    2397                 $fileType = $1 if $ftypLookup{$buff} and $ftypLookup{$buff} =~ /\(\.(\w+)/;
     8937                if ($ftypLookup{$type} and $ftypLookup{$type} =~ /\(\.(\w+)/) {
     8938                    $fileType = $1;
     8939                # check compatible brands
     8940                } elsif ($buff =~ /^.{8}(.{4})+(mp41|mp42|avc1)/s) {
     8941                    $fileType = 'MP4';
     8942                } elsif ($buff =~ /^.{8}(.{4})+(f4v )/s) {
     8943                    $fileType = 'F4V';
     8944                } elsif ($buff =~ /^.{8}(.{4})+(qt  )/s) {
     8945                    $fileType = 'MOV';
     8946                }
    23988947            }
    23998948            $fileType or $fileType = 'MP4'; # default to MP4
    2400             $exifTool->SetFileType($fileType, $mimeLookup{$fileType} || 'video/mp4');
     8949            $et->SetFileType($fileType, $mimeLookup{$fileType} || 'video/mp4');
     8950            # temporarily set ExtractEmbedded option for CRX files
     8951            $saveOptions{ExtractEmbedded} = $et->Options(ExtractEmbedded => 1) if $fileType eq 'CRX';
    24018952        } else {
    2402             $exifTool->SetFileType();       # MOV
     8953            $et->SetFileType();       # MOV
    24038954        }
    24048955        SetByteOrder('MM');
     8956        $$et{PRIORITY_DIR} = 'XMP';   # have XMP take priority
     8957    }
     8958    $$raf{NoBuffer} = 1 if $et->Options('FastScan'); # disable buffering in FastScan mode
     8959
     8960    my $ee = $$et{OPTIONS}{ExtractEmbedded};
     8961    if ($ee) {
     8962        $unkOpt = $$et{OPTIONS}{Unknown};
     8963        require 'Image/ExifTool/QuickTimeStream.pl';
     8964    }
     8965    if ($$tagTablePtr{VARS}) {
     8966        $index = $$tagTablePtr{VARS}{START_INDEX};
     8967        $atomCount = $$tagTablePtr{VARS}{ATOM_COUNT};
    24058968    }
    24068969    for (;;) {
     8970        my ($eeTag, $ignore);
     8971        last if defined $atomCount and --$atomCount < 0;
    24078972        if ($size < 8) {
    2408             last if $size == 0;
    2409             $size == 1 or $exifTool->Warn('Invalid atom size'), last;
    2410             $raf->Read($buff, 8) == 8 or last;
     8973            if ($size == 0) {
     8974                if ($dataPt) {
     8975                    # a zero size isn't legal for contained atoms, but Canon uses it to
     8976                    # terminate the CNTH atom (eg. CanonEOS100D.mov), so tolerate it here
     8977                    my $pos = $raf->Tell() - 4;
     8978                    $raf->Seek(0,2);
     8979                    my $str = $$dirInfo{DirName} . ' with ' . ($raf->Tell() - $pos) . ' bytes';
     8980                    $et->VPrint(0,"$$et{INDENT}\[Terminator found in $str remaining]");
     8981                } else {
     8982                    my $t = PrintableTagID($tag,2);
     8983                    $et->VPrint(0,"$$et{INDENT}Tag '${t}' extends to end of file");
     8984                }
     8985                last;
     8986            }
     8987            $size == 1 or $et->Warn('Invalid atom size'), last;
     8988            # read extended atom size
     8989            $raf->Read($buff, 8) == 8 or $et->Warn('Truncated atom header'), last;
    24118990            $dataPos += 8;
    24128991            my ($hi, $lo) = unpack('NN', $buff);
    2413             $size = $lo;
    24148992            if ($hi or $lo > 0x7fffffff) {
    24158993                if ($hi > 0x7fffffff) {
    2416                     $exifTool->Warn('Invalid atom size');
     8994                    $et->Warn('Invalid atom size');
    24178995                    last;
    2418                 } elsif (not $exifTool->Options('LargeFileSupport')) {
    2419                     $exifTool->Warn('End of processing at large atom (LargeFileSupport not enabled)');
     8996                } elsif (not $et->Options('LargeFileSupport')) {
     8997                    $et->Warn('End of processing at large atom (LargeFileSupport not enabled)');
    24208998                    last;
    24218999                }
    24229000            }
    2423             $size = $hi * 4294967296 + $lo;
     9001            $size = $hi * 4294967296 + $lo - 16;
     9002            $size < 0 and $et->Warn('Invalid extended size'), last;
     9003        } else {
     9004            $size -= 8;
    24249005        }
    2425         $size -= 8;
    2426         my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag);
     9006        if ($validate) {
     9007            $$et{ValidatePath} or $$et{ValidatePath} = { };
     9008            my $path = join('-', @{$$et{PATH}}, $tag);
     9009            $path =~ s/-Track-/-$$et{SET_GROUP1}-/ if $$et{SET_GROUP1};
     9010            if ($$et{ValidatePath}{$path} and not $dupTagOK{$tag} and not $dupDirOK{$dirID}) {
     9011                my $i = Get32u(\$tag,0);
     9012                my $str = $i < 255 ? "index $i" : "tag '" . PrintableTagID($tag,2) . "'";
     9013                $et->WarnOnce("Duplicate $str at " . join('-', @{$$et{PATH}}));
     9014                $$et{ValidatePath} = { } if $path eq 'MOV-moov'; # avoid warnings for all contained dups
     9015            }
     9016            $$et{ValidatePath}{$path} = 1;
     9017        }
     9018        if ($isUserData and $$et{SET_GROUP1}) {
     9019            my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
     9020            # add track name to UserData tags inside tracks
     9021            $tag = $$et{SET_GROUP1} . $tag;
     9022            if (not $$tagTablePtr{$tag} and $tagInfo) {
     9023                my %newInfo = %$tagInfo;
     9024                foreach ('Name', 'Description') {
     9025                    next unless $$tagInfo{$_};
     9026                    $newInfo{$_} = $$et{SET_GROUP1} . $$tagInfo{$_};
     9027                    $newInfo{$_} =~ s/^(Track\d+)Track/$1/; # remove duplicate "Track" in name
     9028                }
     9029                AddTagToTable($tagTablePtr, $tag, \%newInfo);
     9030            }
     9031        }
     9032        # set flag to store additional information for ExtractEmbedded option
     9033        my $handlerType = $$et{HandlerType};
     9034        if ($eeBox{$handlerType} and $eeBox{$handlerType}{$tag}) {
     9035            if ($ee) {
     9036                # (there is another 'gps ' box with a track log that doesn't contain offsets)
     9037                if ($tag ne 'gps ' or $eeBox{$handlerType}{$tag} eq $dirID) {
     9038                    $eeTag = 1;
     9039                    $$et{OPTIONS}{Unknown} = 1; # temporarily enable "Unknown" option
     9040                }
     9041            } elsif ($handlerType ne 'vide' and not $$et{OPTIONS}{Validate}) {
     9042                EEWarn($et);
     9043            }
     9044        } elsif ($ee and $ee > 1 and $eeBox2{$handlerType} and $eeBox2{$handlerType}{$tag}) {
     9045            $eeTag = 1;
     9046            $$et{OPTIONS}{Unknown} = 1;
     9047        }
     9048        my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
     9049
     9050        $$et{OPTIONS}{Unknown} = $unkOpt if $eeTag;     # restore Unknown option
     9051
    24279052        # allow numerical tag ID's
    24289053        unless ($tagInfo) {
    2429             my $num = unpack('N', $tag);
    2430             if ($$tagTablePtr{$num}) {
    2431                 $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $num);
    2432                 $tag = $num;
     9054            my $id = $$et{KeysCount} . '.' . unpack('N', $tag);
     9055            if ($$tagTablePtr{$id}) {
     9056                $tagInfo = $et->GetTagInfo($tagTablePtr, $id);
     9057                $tag = $id;
    24339058            }
    24349059        }
    24359060        # generate tagInfo if Unknown option set
    2436         if (not defined $tagInfo and ($exifTool->{OPTIONS}->{Unknown} or
     9061        if (not defined $tagInfo and ($$et{OPTIONS}{Unknown} or
    24379062            $verbose or $tag =~ /^\xa9/))
    24389063        {
    2439             my $name = $tag;
    2440             my $n = ($name =~ s/([\x00-\x1f\x7f-\xff])/'x'.unpack('H*',$1)/eg);
    2441             # print in hex if tag is numerical
    2442             $name = sprintf('0x%.4x',unpack('N',$tag)) if $n > 2;
     9064            my $name = PrintableTagID($tag,1);
    24439065            if ($name =~ /^xa9(.*)/) {
    24449066                $tagInfo = {
     
    24509072                    Name => "Unknown_$name",
    24519073                    Description => "Unknown $name",
    2452                     Unknown => 1,
    2453                     Binary => 1,
     9074                    %unknownInfo,
    24549075                };
    24559076            }
    2456             Image::ExifTool::AddTagToTable($tagTablePtr, $tag, $tagInfo);
     9077            AddTagToTable($tagTablePtr, $tag, $tagInfo);
    24579078        }
    24589079        # save required tag sizes
    2459         $exifTool->HandleTag($tagTablePtr, "$tag-size", $size) if $$tagTablePtr{"$tag-size"};
    2460         # load values only if associated with a tag (or verbose) and < 16MB long
    2461         if ((defined $tagInfo or $verbose) and $size < 0x1000000) {
     9080        if ($$tagTablePtr{"$tag-size"}) {
     9081            $et->HandleTag($tagTablePtr, "$tag-size", $size);
     9082            $et->HandleTag($tagTablePtr, "$tag-offset", $raf->Tell()) if $$tagTablePtr{"$tag-offset"};
     9083        }
     9084        # load values only if associated with a tag (or verbose) and not too big
     9085        if ($size > 0x2000000) {    # start to get worried above 32 MB
     9086            # check for RIFF trailer (written by Auto-Vox dashcam)
     9087            if ($buff =~ /^(gpsa|gps0|gsen|gsea)...\0/s) { # (yet seen only gpsa as first record)
     9088                $et->VPrint(0, "Found RIFF trailer");
     9089                if ($et->Options('ExtractEmbedded')) {
     9090                    $raf->Seek(-8, 1) or last;  # seek back to start of trailer
     9091                    my $tbl = GetTagTable('Image::ExifTool::QuickTime::Stream');
     9092                    ProcessRIFFTrailer($et, { RAF => $raf }, $tbl);
     9093                } else {
     9094                    EEWarn($et);
     9095                }
     9096                last;
     9097            }
     9098            $ignore = 1;
     9099            if ($tagInfo and not $$tagInfo{Unknown} and not $eeTag) {
     9100                my $t = PrintableTagID($tag,2);
     9101                if ($size > 0x8000000) {
     9102                    $et->Warn("Skipping '${t}' atom > 128 MB", 1);
     9103                } else {
     9104                    $et->Warn("Skipping '${t}' atom > 32 MB", 2) or $ignore = 0;
     9105                }
     9106            }
     9107        }
     9108        if (defined $tagInfo and not $ignore) {
     9109            # set document number for this item property if necessary
     9110            if ($$et{IsItemProperty}) {
     9111                my $items = $$et{ItemInfo};
     9112                my ($id, $prop, $docNum, $lowest);
     9113                my $primary = $$et{PrimaryItem} || 0;
     9114ItemID:         foreach $id (keys %$items) {
     9115                    next unless $$items{$id}{Association};
     9116                    my $item = $$items{$id};
     9117                    foreach $prop (@{$$item{Association}}) {
     9118                        next unless $prop == $index;
     9119                        if ($id == $primary or (not $dontInherit{$tag} and
     9120                            (not $$item{RefersTo} or $$item{RefersTo}{$primary})))
     9121                        {
     9122                            # this is associated with the primary item or an item describing
     9123                            # the primary item, so consider this part of the main document
     9124                            undef $docNum;
     9125                            undef $lowest;
     9126                            last ItemID;
     9127                        } elsif ($$item{DocNum}) {
     9128                            # this property is already associated with an item that has
     9129                            # an ExifTool document number, so use the lowest associated DocNum
     9130                            $docNum = $$item{DocNum} if not defined $docNum or $docNum > $$item{DocNum};
     9131                        } elsif (not defined $lowest or $lowest > $id) {
     9132                            # keep track of the lowest associated item ID
     9133                            $lowest = $id;
     9134                        }
     9135                    }
     9136                }
     9137                if (not defined $docNum and defined $lowest) {
     9138                    # this is the first time we've seen metadata from this item,
     9139                    # so use a new document number
     9140                    $docNum = ++$$et{DOC_COUNT};
     9141                    $$items{$lowest}{DocNum} = $docNum;
     9142                }
     9143                $$et{DOC_NUM} = $docNum;
     9144            }
    24629145            my $val;
    2463             unless ($raf->Read($val, $size) == $size) {
    2464                 $exifTool->Warn("Truncated '$tag' data");
     9146            my $missing = $size - $raf->Read($val, $size);
     9147            if ($missing) {
     9148                my $t = PrintableTagID($tag,2);
     9149                $et->Warn("Truncated '${t}' data (missing $missing bytes)");
    24659150                last;
    24669151            }
    24679152            # use value to get tag info if necessary
    2468             $tagInfo or $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag, \$val);
     9153            $tagInfo or $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val);
    24699154            my $hasData = ($$dirInfo{HasData} and $val =~ /\0...data\0/s);
    24709155            if ($verbose and not $hasData) {
    2471                 $exifTool->VerboseInfo($tag, $tagInfo,
    2472                     Value => $val,
    2473                     DataPt => \$val,
     9156                my $tval;
     9157                if ($tagInfo and $$tagInfo{Format}) {
     9158                    $tval = ReadValue(\$val, 0, $$tagInfo{Format}, $$tagInfo{Count}, length($val));
     9159                }
     9160                $et->VerboseInfo($tag, $tagInfo,
     9161                    Value   => $tval,
     9162                    DataPt  => \$val,
    24749163                    DataPos => $dataPos,
     9164                    Size    => $size,
     9165                    Format  => $tagInfo ? $$tagInfo{Format} : undef,
     9166                    Index   => $index,
    24759167                );
     9168                # print iref item ID numbers
     9169                if ($dirID eq 'iref') {
     9170                    my ($id, $count, @to, $i);
     9171                    if ($$et{ItemRefVersion}) {
     9172                        ($id, $count, @to) = unpack('NnN*', $val) if length $val >= 10;
     9173                    } else {
     9174                        ($id, $count, @to) = unpack('nnn*', $val) if length $val >= 6;
     9175                    }
     9176                    defined $id or $id = '<err>', $count = 0;
     9177                    $id .= " (wrong count: $count)" if $count != @to;
     9178                    # convert sequential numbers to a range
     9179                    for ($i=1; $i<@to; ) {
     9180                        $to[$i-1] =~ /(\d+)$/ and $to[$i] == $1 + 1 or ++$i, next;
     9181                        $to[$i-1] =~ s/(-.*)?$/-$to[$i]/;
     9182                        splice @to, $i, 1;
     9183                    }
     9184                    $et->VPrint(1, "$$et{INDENT}  Item $id refers to: ",join(',',@to),"\n");
     9185                }
     9186            }
     9187            # extract metadata from stream if ExtractEmbedded option is enabled
     9188            if ($eeTag) {
     9189                ParseTag($et, $tag, \$val);
     9190                # forget this tag if we generated it only for ExtractEmbedded
     9191                undef $tagInfo if $tagInfo and $$tagInfo{Unknown} and not $unkOpt;
     9192            }
     9193
     9194            # handle iTunesInfo mean/name/data triplets
     9195            if ($tagInfo and $$tagInfo{Triplet}) {
     9196                if ($tag eq 'data' and $triplet{mean} and $triplet{name}) {
     9197                    $tag = $triplet{name};
     9198                    # add 'mean' to name unless it is 'com.apple.iTunes'
     9199                    $tag = $triplet{mean} . '/' . $tag unless $triplet{mean} eq 'com.apple.iTunes';
     9200                    $tagInfo = $et->GetTagInfo($tagTablePtr, $tag, \$val);
     9201                    unless ($tagInfo) {
     9202                        my $name = $triplet{name};
     9203                        my $desc = $name;
     9204                        $name =~ tr/-_a-zA-Z0-9//dc;
     9205                        $desc =~ tr/_/ /;
     9206                        $tagInfo = {
     9207                            Name => $name,
     9208                            Description => $desc,
     9209                        };
     9210                        AddTagToTable($tagTablePtr, $tag, $tagInfo);
     9211                    }
     9212                    # ignore 8-byte header
     9213                    $val = substr($val, 8) if length($val) >= 8;
     9214                    unless ($$tagInfo{Format} or $$tagInfo{SubDirectory}) {
     9215                        # extract as binary if it contains any non-ASCII or control characters
     9216                        if ($val =~ /[^\x20-\x7e]/) {
     9217                            my $buff = $val;
     9218                            $val = \$buff;
     9219                        }
     9220                    }
     9221                    undef %triplet;
     9222                } else {
     9223                    undef %triplet if $tag eq 'mean';
     9224                    $triplet{$tag} = substr($val,4) if length($val) > 4;
     9225                    undef $tagInfo;  # don't store this tag
     9226                }
    24769227            }
    24779228            if ($tagInfo) {
     
    24859236                    }
    24869237                    my %dirInfo = (
    2487                         DataPt   => \$val,
    2488                         DataLen  => $size,
    2489                         DirStart => $start,
    2490                         DirLen   => $size - $start,
    2491                         DirName  => $$subdir{DirName} || $$tagInfo{Name},
    2492                         HasData  => $$subdir{HasData},
    2493                         Multi    => $$subdir{Multi},
    2494                         DataPos  => $dPos,
    2495                         # Base needed for IsOffset tags in binary data
    2496                         Base     => $base,
     9238                        DataPt     => \$val,
     9239                        DataLen    => $size,
     9240                        DirStart   => $start,
     9241                        DirLen     => $size - $start,
     9242                        DirName    => $$subdir{DirName} || $$tagInfo{Name},
     9243                        DirID      => $tag,
     9244                        HasData    => $$subdir{HasData},
     9245                        Multi      => $$subdir{Multi},
     9246                        IgnoreProp => $$subdir{IgnoreProp}, # (XML hack)
     9247                        DataPos    => $dPos,
     9248                        Base       => $base, # (needed for IsOffset tags in binary data)
    24979249                    );
     9250                    $dirInfo{BlockInfo} = $tagInfo if $$tagInfo{BlockExtract};
    24989251                    if ($$subdir{ByteOrder} and $$subdir{ByteOrder} =~ /^Little/) {
    24999252                        SetByteOrder('II');
    25009253                    }
    2501                     my $oldGroup1 = $exifTool->{SET_GROUP1};
    2502                     if ($$tagInfo{Name} eq 'Track') {
     9254                    my $oldGroup1 = $$et{SET_GROUP1};
     9255                    if ($$tagInfo{SubDirectory} and $$tagInfo{SubDirectory}{TagTable} and
     9256                        $$tagInfo{SubDirectory}{TagTable} eq 'Image::ExifTool::QuickTime::Track')
     9257                    {
    25039258                        $track or $track = 0;
    2504                         $exifTool->{SET_GROUP1} = 'Track' . (++$track);
     9259                        $$et{SET_GROUP1} = 'Track' . (++$track);
    25059260                    }
    25069261                    my $subTable = GetTagTable($$subdir{TagTable});
    25079262                    my $proc = $$subdir{ProcessProc};
    2508                     $exifTool->ProcessDirectory(\%dirInfo, $subTable, $proc) if $size > $start;
    2509                     $exifTool->{SET_GROUP1} = $oldGroup1;
     9263                    # make ProcessMOV() the default processing procedure for subdirectories
     9264                    $proc = \&ProcessMOV unless $proc or $$subTable{PROCESS_PROC};
     9265                    if ($size > $start) {
     9266                        # delay processing of ipco box until after all other boxes
     9267                        if ($tag eq 'ipco' and not $$et{IsItemProperty}) {
     9268                            $$et{ItemPropertyContainer} = [ \%dirInfo, $subTable, $proc ];
     9269                            $et->VPrint(0,"$$et{INDENT}\[Process ipco box later]");
     9270                        } else {
     9271                            $et->ProcessDirectory(\%dirInfo, $subTable, $proc);
     9272                        }
     9273                    }
     9274                    if ($tag eq 'stbl') {
     9275                        # process sample data when exiting SampleTable box if extracting embedded
     9276                        ProcessSamples($et) if $ee;
     9277                    } elsif ($tag eq 'minf') {
     9278                        $$et{HandlerType} = ''; # reset handler type at end of media info box
     9279                    }
     9280                    $$et{SET_GROUP1} = $oldGroup1;
    25109281                    SetByteOrder('MM');
    25119282                } elsif ($hasData) {
     
    25179288                        my ($len, $type, $flags, $ctry, $lang) = unpack("x${pos}Na4Nnn", $val);
    25189289                        last if $pos + $len > $size;
    2519                         my $value;
     9290                        my ($value, $langInfo, $oldDir);
    25209291                        my $format = $$tagInfo{Format};
    25219292                        if ($type eq 'data' and $len >= 16) {
     
    25309301                            if ($stringEncoding{$flags}) {
    25319302                                # handle all string formats
    2532                                 $value = $exifTool->Decode($value, $stringEncoding{$flags});
     9303                                $value = $et->Decode($value, $stringEncoding{$flags});
     9304                                # (shouldn't be null terminated, but some software writes it anyway)
     9305                                $value =~ s/\0$// unless $$tagInfo{Binary};
    25339306                            } else {
    2534                                 if (not $format) {
    2535                                     if ($flags == 0x15 or $flags == 0x16) {
    2536                                         $format = { 1=>'int8', 2=>'int16', 4=>'int32' }->{$len};
    2537                                         $format .= $flags == 0x15 ? 's' : 'u' if $format;
    2538                                     } elsif ($flags == 0x17) {
    2539                                         $format = 'float';
    2540                                     } elsif ($flags == 0x18) {
    2541                                         $format = 'double';
    2542                                     } elsif ($flags == 0x00) {
    2543                                         # read 1 and 2-byte binary as integers
    2544                                         if ($len == 1) {
    2545                                             $format = 'int8u',
    2546                                         } elsif ($len == 2) {
    2547                                             $format = 'int16u',
    2548                                         }
    2549                                     }
    2550                                 }
     9307                                $format = QuickTimeFormat($flags, $len) unless $format;
    25519308                                if ($format) {
    25529309                                    $value = ReadValue(\$value, 0, $format, $$tagInfo{Count}, $len);
     
    25589315                            }
    25599316                        }
    2560                         my $langInfo;
    25619317                        if ($ctry or $lang) {
    2562                             # ignore country ('ctry') and language lists ('lang') for now
    2563                             undef $ctry if $ctry and $ctry <= 255;
    2564                             undef $lang if $lang and $lang <= 255;
    2565                             $lang = UnpackLang($lang);
    2566                             # add country code if specified
    2567                             if ($ctry) {
    2568                                 $ctry = unpack('a2',pack('n',$ctry)); # unpack as ISO 3166-1
    2569                                 # treat 'ZZ' like a default country (see ref 12)
    2570                                 undef $ctry if $ctry eq 'ZZ';
    2571                                 if ($ctry and $ctry =~ /^[A-Z]{2}$/) {
    2572                                     $lang or $lang = 'und';
    2573                                     $lang .= "-$ctry";
     9318                            my $langCode = GetLangCode($lang, $ctry);
     9319                            if ($langCode) {
     9320                                # get tagInfo for other language
     9321                                $langInfo = GetLangInfoQT($et, $tagInfo, $langCode);
     9322                                # save other language tag ID's so we can delete later if necessary
     9323                                if ($langInfo) {
     9324                                    $$tagInfo{OtherLang} or $$tagInfo{OtherLang} = [ ];
     9325                                    push @{$$tagInfo{OtherLang}}, $$langInfo{TagID};
    25749326                                }
    25759327                            }
    2576                             $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $lang) if $lang;
    25779328                        }
    25789329                        $langInfo or $langInfo = $tagInfo;
    2579                         $exifTool->VerboseInfo($tag, $langInfo,
     9330                        $et->VerboseInfo($tag, $langInfo,
    25809331                            Value   => ref $value ? $$value : $value,
    25819332                            DataPt  => \$val,
     
    25849335                            Size    => $len,
    25859336                            Format  => $format,
    2586                             Extra   => sprintf(", Type='$type', Flags=0x%x",$flags)
     9337                            Index   => $index,
     9338                            Extra   => sprintf(", Type='${type}', Flags=0x%x, Lang=0x%.4x",$flags,$lang),
    25879339                        ) if $verbose;
    2588                         $exifTool->FoundTag($langInfo, $value) if defined $value;
     9340                        # use "Keys" in path instead of ItemList if this was defined by a Keys tag
     9341                        my $isKey = $$tagInfo{Groups} && $$tagInfo{Groups}{1} && $$tagInfo{Groups}{1} eq 'Keys';
     9342                        if ($isKey) {
     9343                            $oldDir = $$et{PATH}[-1];
     9344                            $$et{PATH}[-1] = 'Keys';
     9345                        }
     9346                        $et->FoundTag($langInfo, $value) if defined $value;
     9347                        $$et{PATH}[-1] = $oldDir if $isKey;
    25899348                        $pos += $len;
    25909349                    }
    2591                 } elsif ($tag =~ /^\xa9/) {
     9350                } elsif ($tag =~ /^\xa9/ or $$tagInfo{IText}) {
    25929351                    # parse international text to extract all languages
    25939352                    my $pos = 0;
     9353                    if ($$tagInfo{Format}) {
     9354                        $et->FoundTag($tagInfo, ReadValue(\$val, 0, $$tagInfo{Format}, undef, length($val)));
     9355                        $pos = $size;
     9356                    }
    25949357                    for (;;) {
    2595                         last if $pos + 4 > $size;
    2596                         my ($len, $lang) = unpack("x${pos}nn", $val);
    2597                         $pos += 4;
    2598                         # according to the QuickTime spec (ref 12), $len should include
    2599                         # 4 bytes for length and type words, but nobody (including
    2600                         # Apple, Pentax and Kodak) seems to add these in, so try
    2601                         # to allow for either
    2602                         if ($pos + $len > $size) {
    2603                             $len -= 4;
    2604                             last if $pos + $len > $size or $len < 0;
     9358                        my ($len, $lang);
     9359                        if ($$tagInfo{IText} and $$tagInfo{IText} == 6) {
     9360                            last if $pos + 6 > $size;
     9361                            $pos += 4;
     9362                            $lang = unpack("x${pos}n", $val);
     9363                            $pos += 2;
     9364                            $len = $size - $pos;
     9365                        } else {
     9366                            last if $pos + 4 > $size;
     9367                            ($len, $lang) = unpack("x${pos}nn", $val);
     9368                            $pos += 4;
     9369                            # according to the QuickTime spec (ref 12), $len should include
     9370                            # 4 bytes for length and type words, but nobody (including
     9371                            # Apple, Pentax and Kodak) seems to add these in, so try
     9372                            # to allow for either
     9373                            if ($pos + $len > $size) {
     9374                                $len -= 4;
     9375                                last if $pos + $len > $size or $len < 0;
     9376                            }
    26059377                        }
    26069378                        # ignore any empty entries (or null padding) after the first
     
    26089380                        my $str = substr($val, $pos, $len);
    26099381                        my $langInfo;
    2610                         if ($lang < 0x400) {
     9382                        if (($lang < 0x400 or $lang == 0x7fff) and $str !~ /^\xfe\xff/) {
    26119383                            # this is a Macintosh language code
    26129384                            # a language code of 0 is Macintosh english, so treat as default
    2613                             if ($lang) {
    2614                                 # use Font.pm to look up language string
    2615                                 require Image::ExifTool::Font;
    2616                                 $lang = $Image::ExifTool::Font::ttLang{Macintosh}{$lang};
     9385                            if ($lang) {
     9386                                if ($lang == 0x7fff) {
     9387                                    # technically, ISO 639-2 doesn't have a 2-character
     9388                                    # equivalent for 'und', but use 'un' anyway
     9389                                    $lang = 'un';
     9390                                } else {
     9391                                    # use Font.pm to look up language string
     9392                                    require Image::ExifTool::Font;
     9393                                    $lang = $Image::ExifTool::Font::ttLang{Macintosh}{$lang};
     9394                                }
    26179395                            }
    2618                             # the spec says only "Macintosh text encoding", so
    2619                             # I can only assume that it is the most common one
    2620                             $str = $exifTool->Decode($str, 'MacRoman');
     9396                            # the spec says only "Macintosh text encoding", but
     9397                            # allow this to be configured by the user
     9398                            $str = $et->Decode($str, $charsetQuickTime);
    26219399                        } else {
    26229400                            # convert language code to ASCII (ignore read-only bit)
     
    26249402                            # may be either UTF-8 or UTF-16BE
    26259403                            my $enc = $str=~s/^\xfe\xff// ? 'UTF16' : 'UTF8';
    2626                             $str = $exifTool->Decode($str, $enc);
     9404                            $str = $et->Decode($str, $enc);
    26279405                        }
    2628                         $langInfo = Image::ExifTool::GetLangInfo($tagInfo, $lang) if $lang;
    2629                         $exifTool->FoundTag($langInfo || $tagInfo, $str);
     9406                        $str =~ s/\0+$//;   # remove any trailing nulls (eg. 3gp tags)
     9407                        $langInfo = GetLangInfoQT($et, $tagInfo, $lang) if $lang;
     9408                        $et->FoundTag($langInfo || $tagInfo, $str);
    26309409                        $pos += $len;
    26319410                    }
    26329411                } else {
    2633                     if ($$tagInfo{Format}) {
    2634                         $val = ReadValue(\$val, 0, $$tagInfo{Format}, $$tagInfo{Count}, length($val));
     9412                    my $format = $$tagInfo{Format};
     9413                    if ($format) {
     9414                        $val = ReadValue(\$val, 0, $format, $$tagInfo{Count}, length($val));
    26359415                    }
    2636                     $exifTool->FoundTag($tagInfo, $val);
     9416                    my $oldBase;
     9417                    if ($$tagInfo{SetBase}) {
     9418                        $oldBase = $$et{BASE};
     9419                        $$et{BASE} = $dataPos;
     9420                    }
     9421                    my $key = $et->FoundTag($tagInfo, $val);
     9422                    $$et{BASE} = $oldBase if defined $oldBase;
     9423                    # decode if necessary (NOTE: must be done after RawConv)
     9424                    if (defined $key and (not $format or $format =~ /^string/) and
     9425                        not $$tagInfo{Unknown} and not $$tagInfo{ValueConv} and
     9426                        not $$tagInfo{Binary} and defined $$et{VALUE}{$key} and not ref $val)
     9427                    {
     9428                        my $vp = \$$et{VALUE}{$key};
     9429                        if (not ref $$vp and length($$vp) <= 65536 and $$vp =~ /[\x80-\xff]/) {
     9430                            # the encoding of this is not specified, so use CharsetQuickTime
     9431                            # unless the string is valid UTF-8
     9432                            require Image::ExifTool::XMP;
     9433                            my $enc = Image::ExifTool::XMP::IsUTF8($vp) > 0 ? 'UTF8' : $charsetQuickTime;
     9434                            $$vp = $et->Decode($$vp, $enc);
     9435                        }
     9436                    }
    26379437                }
    26389438            }
    26399439        } else {
    2640             $raf->Seek($size, 1) or $exifTool->Warn("Truncated '$tag' data"), last;
     9440            $et->VerboseInfo($tag, $tagInfo,
     9441                Size  => $size,
     9442                Extra => sprintf(' at offset 0x%.4x', $raf->Tell()),
     9443            ) if $verbose;
     9444            if ($size and (not $raf->Seek($size-1, 1) or $raf->Read($buff, 1) != 1)) {
     9445                my $t = PrintableTagID($tag,2);
     9446                $et->Warn("Truncated '${t}' data");
     9447                last;
     9448            }
    26419449        }
     9450        $dataPos += $size + 8;  # point to start of next atom data
     9451        last if $dirEnd and $dataPos >= $dirEnd; # (note: ignores last value if 0 bytes)
    26429452        $raf->Read($buff, 8) == 8 or last;
    2643         $dataPos += $size + 8;
    26449453        ($size, $tag) = unpack('Na4', $buff);
     9454        ++$index if defined $index;
    26459455    }
     9456    # fill in missing defaults for alternate language tags
     9457    # (the first language is taken as the default)
     9458    if ($doDefaultLang and $$et{QTLang}) {
     9459QTLang: foreach $tag (@{$$et{QTLang}}) {
     9460            next unless defined $$et{VALUE}{$tag};
     9461            my $langInfo = $$et{TAG_INFO}{$tag} or next;
     9462            my $tagInfo = $$langInfo{SrcTagInfo} or next;
     9463            my $infoHash = $$et{TAG_INFO};
     9464            my $name = $$tagInfo{Name};
     9465            # loop through all instances of this tag name and generate the default-language
     9466            # version only if we don't already have a QuickTime tag with this name
     9467            my ($i, $key);
     9468            for ($i=0, $key=$name; $$infoHash{$key}; ++$i, $key="$name ($i)") {
     9469                next QTLang if $et->GetGroup($key, 0) eq 'QuickTime';
     9470            }
     9471            $et->FoundTag($tagInfo, $$et{VALUE}{$tag});
     9472        }
     9473        delete $$et{QTLang};
     9474    }
     9475    # process item information now that we are done processing its 'meta' container
     9476    HandleItemInfo($et) if $topLevel or $dirID eq 'meta';
     9477
     9478    ScanMediaData($et) if $ee and $topLevel;  # brute force scan for metadata embedded in media data
     9479
     9480    # restore any changed options
     9481    $et->Options($_ => $saveOptions{$_}) foreach keys %saveOptions;
    26469482    return 1;
    26479483}
     
    26539489sub ProcessQTIF($$)
    26549490{
    2655     my ($exifTool, $dirInfo) = @_;
     9491    my ($et, $dirInfo) = @_;
    26569492    my $table = GetTagTable('Image::ExifTool::QuickTime::ImageFile');
    2657     return ProcessMOV($exifTool, $dirInfo, $table);
     9493    return ProcessMOV($et, $dirInfo, $table);
    26589494}
    26599495
     
    26739509
    26749510This module contains routines required by Image::ExifTool to extract
    2675 information from QuickTime and MP4 video, and M4A audio files.
     9511information from QuickTime and MP4 video, M4A audio, and HEIC image files.
    26769512
    26779513=head1 AUTHOR
    26789514
    2679 Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
     9515Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
    26809516
    26819517This library is free software; you can redistribute it and/or modify it
Note: See TracChangeset for help on using the changeset viewer.