- Timestamp:
- 2021-02-26T19:39:51+13:00 (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone2/perllib/cpan/Image/ExifTool/H264.pm
r24107 r34921 13 13 # 6) Dave Nicholson private communication 14 14 # 7) http://www.freepatentsonline.com/20050076039.pdf 15 # 8) Michael Reitinger private communication (RX100) 15 16 # 16 17 # Glossary: RBSP = Raw Byte Sequence Payload … … 23 24 use Image::ExifTool qw(:DataAccess :Utils); 24 25 use Image::ExifTool::Exif; 25 26 $VERSION = '1.06'; 26 use Image::ExifTool::GPS; 27 28 $VERSION = '1.17'; 27 29 28 30 sub ProcessSEI($$); … … 35 37 0x0108 => 'Sony', 36 38 0x1011 => 'Canon', 39 0x1104 => 'JVC', #Rob Lewis 37 40 ); 38 41 … … 62 65 compared to the challenge of actually decoding the data!]> This information 63 66 may exist at regular intervals through the entire video, but only the first 64 occurrence is extracted unless the ExtractEmbedded(-ee) option is used (in67 occurrence is extracted unless the L<ExtractEmbedded|../ExifTool.html#ExtractEmbedded> (-ee) option is used (in 65 68 which case subsequent occurrences are extracted as sub-documents). 66 69 }, … … 82 85 # 0x11 - TitleRemainTime (ref 7) 83 86 # 0x12 - TitleChapterTotalNo (ref 7) 84 # 0x13 - TitleTimecode 85 # 0x14 - TitleBinaryGroup 87 0x13 => { 88 Name => 'TimeCode', 89 Notes => 'hours:minutes:seconds:frames', 90 ValueConv => 'sprintf("%.2x:%.2x:%.2x:%.2x",reverse unpack("C*",$val))', 91 }, 92 # 0x14 - TitleBinaryGroup - val: 0x00000000,0x14200130 86 93 # 0x15 - TitleCassetteNo (ref 7) 87 94 # 0x16-0x17 - TitleSoftID (ref 7) … … 95 102 # first byte is timezone information: 96 103 # 0x80 - unused 97 # 0x40 - DST flag (not currently decoded)104 # 0x40 - DST flag 98 105 # 0x20 - TimeZoneSign 99 106 # 0x1e - TimeZoneValue … … 101 108 ValueConv => q{ 102 109 my ($tz, @a) = unpack('C*',$val); 103 return sprintf('%.2x%.2x:%.2x:%.2x %.2x:%.2x:%.2x%s%.2d:%s ', @a,110 return sprintf('%.2x%.2x:%.2x:%.2x %.2x:%.2x:%.2x%s%.2d:%s%s', @a, 104 111 $tz & 0x20 ? '-' : '+', ($tz >> 1) & 0x0f, 105 $tz & 0x01 ? '30' : '00'); 112 $tz & 0x01 ? '30' : '00', 113 $tz & 0x40 ? ' DST' : ''); 106 114 }, 107 115 PrintConv => '$self->ConvertDateTime($val)', … … 127 135 SubDirectory => { TagTable => 'Image::ExifTool::H264::Camera2' }, 128 136 }, 129 # 0x73 Lens - val: 0x 75ffffd3,0x0effffd3,0x59ffffd3,0x79ffffd3,0xffffffd3...130 # 0x74 Gain 137 # 0x73 Lens - val: 0x04ffffd3,0x0effffd3,0x15ffffd3,0x41ffffd3,0x52ffffd3,0x59ffffd3,0x65ffffd3,0x71ffffd3,0x75ffffd3,0x79ffffd3,0x7fffffd3,0xffffffd3... 138 # 0x74 Gain - val: 0xb8ffff0f 131 139 # 0x75 Pedestal 132 140 # 0x76 Gamma … … 292 300 Notes => 'combined with tags 0xbc and 0xbd', 293 301 ValueConv => 'Image::ExifTool::GPS::ConvertTimeStamp($val)', 302 PrintConv => 'Image::ExifTool::GPS::PrintTimeStamp($val)', 294 303 }, 295 304 0xbe => { … … 368 377 }, 369 378 # 0xc9-0xcf - GPSOption 379 # 0xc9 - val: 0x001d0203 380 0xca => { #PH (Sony DSC-HX7V) 381 Name => 'GPSDateStamp', 382 Format => 'string', 383 Groups => { 1 => 'GPS', 2 => 'Time' }, 384 Combine => 2, # the next 2 tags contain the rest of the string 385 Notes => 'combined with tags 0xcb and 0xcc', 386 ValueConv => 'Image::ExifTool::Exif::ExifDate($val)', 387 }, 370 388 0xe0 => { 371 389 Name => 'MakeModel', … … 374 392 # 0xe1-0xef - MakerOption 375 393 # 0xe1 - val: 0x01000670,0x01000678,0x06ffffff,0x01ffffff,0x01000020,0x01000400... 376 # 0xe2-0xe8 - val: 0x00000000 in many samples377 394 0xe1 => { #6 378 395 Name => 'RecInfo', … … 381 398 SubDirectory => { TagTable => 'Image::ExifTool::H264::RecInfo' }, 382 399 }, 400 # 0xe2-0xe8 - val: 0x00000000 in many samples 401 # 0xe2 - val: 0x00000000,0x01000000,0x01010000,0x8080900c,0x8080a074 402 # 0xe3 - val: 0x00801f89,0x00801f8b,0x00c01f89,0xc9c01f80 383 403 0xe4 => { #PH 384 404 Name => 'Model', 385 Condition => '$$self{Make} eq "Sony"', 405 Condition => '$$self{Make} eq "Sony"', # (possibly also Canon models?) 386 406 Description => 'Camera Model Name', 387 Notes => 'Sony camerasonly, combined with tags 0xe5 and 0xe6',407 Notes => 'Sony only, combined with tags 0xe5 and 0xe6', 388 408 Format => 'string', 389 409 Combine => 2, # (not sure about 0xe6, but include it just in case) 390 410 RawConv => '$val eq "" ? undef : $val', 391 411 }, 412 # 0xeb - val: 0x008a0a00,0x0a300000,0x508a0a00,0x52880a00,0x528a0a00 413 # 0xec - val: 0x0b700000 414 # 0xed - val: 0x0ce0f819 392 415 0xee => { #6 (HFS200) 393 416 Name => 'FrameInfo', … … 396 419 SubDirectory => { TagTable => 'Image::ExifTool::H264::FrameInfo' }, 397 420 }, 421 # 0xef - val: 0x01c00000,0x0e00000c 398 422 ); 399 423 … … 417 441 Name => 'Gain', 418 442 Mask => 0x0f, 443 # (0x0f would translate to 42 dB, but this value is used by the Sony 444 # HXR-NX5U for any out-of-range value such as -6 dB or "hyper gain" - PH) 419 445 ValueConv => '($val - 1) * 3', 420 PrintConv => ' "$val dB"',446 PrintConv => '$val==42 ? "Out of range" : "$val dB"', 421 447 }, 422 448 1.1 => { 423 449 Name => 'ExposureProgram', 424 450 Mask => 0xf0, 425 ValueConv => '$val == 0xf0? undef : $val',426 PrintConv => { 427 0 x00=> 'Program AE',428 0x10=> 'Gain', #?429 0x20=> 'Shutter speed priority AE',430 0x30=> 'Aperture-priority AE',431 0x40=> 'Manual',451 ValueConv => '$val == 15 ? undef : $val', 452 PrintConv => { 453 0 => 'Program AE', 454 1 => 'Gain', #? 455 2 => 'Shutter speed priority AE', 456 3 => 'Aperture-priority AE', 457 4 => 'Manual', 432 458 }, 433 459 }, … … 435 461 Name => 'WhiteBalance', 436 462 Mask => 0xe0, 437 ValueConv => '$val == 0xe0? undef : $val',438 PrintConv => { 439 0 x00=> 'Auto',440 0x20=> 'Hold',441 0x40=> '1-Push',442 0x60=> 'Daylight',463 ValueConv => '$val == 7 ? undef : $val', 464 PrintConv => { 465 0 => 'Auto', 466 1 => 'Hold', 467 2 => '1-Push', 468 3 => 'Daylight', 443 469 }, 444 470 }, … … 448 474 PrintConv => q{ 449 475 my $foc = ($val & 0x7e) / (($val & 0x01) ? 40 : 400); 450 return ($val & 0x80 ? 'Manual' : 'Auto') . " ($foc)";476 return(($val & 0x80 ? 'Manual' : 'Auto') . " ($foc)"); 451 477 }, 452 478 }, … … 462 488 1 => { 463 489 Name => 'ImageStabilization', 490 PrintHex => 1, 464 491 PrintConv => { 465 492 0 => 'Off', 493 0x3f => 'On (0x3f)', #8 494 0xbf => 'Off (0xbf)', #8 466 495 0xff => 'n/a', 467 496 OTHER => sub { … … 485 514 Mask => 0x7fff, # (what is bit 0x8000 for?) 486 515 RawConv => '$val == 0x7fff ? undef : $val', #7 487 ValueConv => '$val / 33640', #PH (conversion factor determined empirically)516 ValueConv => '$val / 28125', #PH (Vixia HF G30, ref forum5588) (was $val/33640 until 9.49) 488 517 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', 489 518 }, … … 502 531 PrintConv => \%convMake, 503 532 }, 504 # 1 => ModelIDCode according to ref 4/5 (I think not) 505 # vals: 0x3001 - Sony HDR-CX105E/TG3E/XR500V 533 # 1 => ModelIDCode according to ref 4/5 (I think not - PH) 534 # 1 => { Name => 'ModelIDCode', PrintConv => 'sprintf("%.4x",$val)' }, 535 # vals: 0x0313 - various Pansonic HDC models 536 # 0x0345 - Panasonic HC-V7272 537 # 0x0414 - Panasonic AG-AF100 538 # 0x0591 - various Panasonic DMC models 539 # 0x0802 - Panasonic DMC-TZ60 with GPS information off 540 # 0x0803 - Panasonic DMC-TZ60 with GPS information on 541 # 0x3001 - various Sony DSC, HDR, NEX and SLT models 542 # 0x3003 - various Sony DSC models 543 # 0x3100 - various Sony DSC, ILCE, NEX and SLT models 506 544 # 0x1000 - Sony HDR-UX1 545 # 0x2000 - Canon HF100 (60i) 507 546 # 0x3000 - Canon HF100 (30p) 508 # 0x2000 - Canon HF100 (60i)509 547 # 0x3101 - Canon HFM300 (PH, all qualities and frame rates) 548 # 0x3102 - Canon HFS200 549 # 0x4300 - Canon HFG30 510 550 ); 511 551 … … 686 726 #------------------------------------------------------------------------------ 687 727 # Parse H.264 sequence parameter set RBSP (ref 1) 688 # Inputs) 0) ExifTool ref, 1) tag table ref, 2) data ref 728 # Inputs: 0) ExifTool ref, 1) tag table ref, 2) data ref 729 # Notes: All this just to get the image size! 689 730 sub ParseSeqParamSet($$$) 690 731 { 691 my ($e xifTool, $tagTablePtr, $dataPt) = @_;732 my ($et, $tagTablePtr, $dataPt) = @_; 692 733 # initialize our bitstream object 693 734 my $bstr = NewBitStream($dataPt) or return; 694 735 my ($t, $i, $j, $n); 695 736 # the messy nature of H.264 encoding makes it difficult to use 696 # data-driven structure parsing, so I code it explicit ely (yuck!)737 # data-driven structure parsing, so I code it explicitly (yuck!) 697 738 $t = GetIntN($bstr, 8); # profile_idc 698 739 GetIntN($bstr, 16); # constraints and level_idc … … 746 787 return unless $$bstr{Mask}; 747 788 if ($w>=160 and $w<=4096 and $h>=120 and $h<=3072) { 748 $e xifTool->HandleTag($tagTablePtr, ImageWidth => $w);749 $e xifTool->HandleTag($tagTablePtr, ImageHeight => $h);789 $et->HandleTag($tagTablePtr, ImageWidth => $w); 790 $et->HandleTag($tagTablePtr, ImageHeight => $h); 750 791 # (whew! -- so much work just to get ImageSize!!) 751 792 } … … 778 819 if ($t) { 779 820 return if BitsLeft($bstr) < 65; 780 $$e xifTool{VUI_units} = GetIntN($bstr, 32); # num_units_in_tick781 $$e xifTool{VUI_scale} = GetIntN($bstr, 32); # time_scale821 $$et{VUI_units} = GetIntN($bstr, 32); # num_units_in_tick 822 $$et{VUI_scale} = GetIntN($bstr, 32); # time_scale 782 823 GetIntN($bstr, 1); # fixed_frame_rate_flag 783 824 } … … 786 827 $t = GetIntN($bstr, 1); # nal_/vcl_hrd_parameters_present_flag 787 828 if ($t) { 788 $$e xifTool{VUI_hard} = 1;829 $$et{VUI_hard} = 1; 789 830 $hard = 1; 790 831 $n = GetGolomb($bstr); # cpb_cnt_minus1 … … 796 837 } 797 838 GetIntN($bstr, 5); # initial_cpb_removal_delay_length_minus1 798 $$e xifTool{VUI_clen} = GetIntN($bstr, 5); # cpb_removal_delay_length_minus1799 $$e xifTool{VUI_dlen} = GetIntN($bstr, 5); # dpb_output_delay_length_minus1800 $$e xifTool{VUI_toff} = GetIntN($bstr, 5); # time_offset_length839 $$et{VUI_clen} = GetIntN($bstr, 5); # cpb_removal_delay_length_minus1 840 $$et{VUI_dlen} = GetIntN($bstr, 5); # dpb_output_delay_length_minus1 841 $$et{VUI_toff} = GetIntN($bstr, 5); # time_offset_length 801 842 } 802 843 } 803 844 GetIntN($bstr, 1) if $hard; # low_delay_hrd_flag 804 $$e xifTool{VUI_pic} = GetIntN($bstr, 1); # pic_struct_present_flag845 $$et{VUI_pic} = GetIntN($bstr, 1); # pic_struct_present_flag 805 846 # (don't yet decode the rest of the vui data) 806 847 } … … 808 849 #------------------------------------------------------------------------------ 809 850 # Parse H.264 picture timing SEI message (payload type 1) (ref 1) 810 # Inputs) 0) ExifTool ref, 1) data ref 851 # Inputs: 0) ExifTool ref, 1) data ref 852 # Notes: this routine is for test purposes only, and not called unless the 853 # $parsePictureTiming flag is set 811 854 sub ParsePictureTiming($$) 812 855 { 813 my ($e xifTool, $dataPt) = @_;856 my ($et, $dataPt) = @_; 814 857 my $bstr = NewBitStream($dataPt) or return; 815 858 my ($i, $t, $n); … … 817 860 # exist if the VUI hardware parameters are present, or if 818 861 # "determined by the application, by some means not specified" -- WTF?? 819 if ($$e xifTool{VUI_hard}) {820 GetIntN($bstr, $$e xifTool{VUI_clen} + 1); # cpb_removal_delay821 GetIntN($bstr, $$e xifTool{VUI_dlen} + 1); # dpb_output_delay822 } 823 if ($$e xifTool{VUI_pic}) {862 if ($$et{VUI_hard}) { 863 GetIntN($bstr, $$et{VUI_clen} + 1); # cpb_removal_delay 864 GetIntN($bstr, $$et{VUI_dlen} + 1); # dpb_output_delay 865 } 866 if ($$et{VUI_pic}) { 824 867 $t = GetIntN($bstr, 4); # pic_struct 825 868 # determine NumClockTS ($n) … … 853 896 } 854 897 } 855 if ($$e xifTool{VUI_toff}) {856 $o = GetIntN($bstr, $$e xifTool{VUI_toff}); # time_offset898 if ($$et{VUI_toff}) { 899 $o = GetIntN($bstr, $$et{VUI_toff}); # time_offset 857 900 } 858 901 last; # only parse the first clock timestamp found … … 863 906 #------------------------------------------------------------------------------ 864 907 # Process H.264 Supplementary Enhancement Information (ref 1/PH) 865 # Inputs: 0) Exif tool ref, 1) dirInfo ref, 2) tag table ref908 # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref 866 909 # Returns: 1 if we processed payload type 5 910 # Payload types: 911 # 0 - buffer period 912 # 1 - pic timing 913 # 2 - pan scan rect 914 # 3 - filler payload 915 # 4 - user data registered itu t t35 916 # 5 - user data unregistered 917 # 6 - recovery point 918 # 7 - dec ref pic marking repetition 919 # 8 - spare pic 920 # 9 - sene info 921 # 10 - sub seq info 922 # 11 - sub seq layer characteristics 923 # 12 - sub seq characteristics 924 # 13 - full frame freeze 925 # 14 - full frame freeze release 926 # 15 - full frame snapshot 927 # 16 - progressive refinement segment start 928 # 17 - progressive refinement segment end 929 # 18 - motion constrained slice group set 867 930 sub ProcessSEI($$) 868 931 { 869 my ($e xifTool, $dirInfo) = @_;932 my ($et, $dirInfo) = @_; 870 933 my $dataPt = $$dirInfo{DataPt}; 871 934 my $end = length($$dataPt); … … 891 954 } 892 955 return 0 if $pos + $size > $end; 956 $et->VPrint(1," (SEI type $type)\n"); 893 957 if ($type == 1) { # picture timing information 894 958 if ($parsePictureTiming) { 895 959 my $buff = substr($$dataPt, $pos, $size); 896 ParsePictureTiming($e xifTool, $dataPt);960 ParsePictureTiming($et, $dataPt); 897 961 } 898 962 } elsif ($type == 5) { # unregistered user data … … 904 968 # look for our 16-byte UUID 905 969 # - plus "MDPM" for "ModifiedDVPackMeta" 906 # - plus "GA94" for closed-caption data ( not currentlydecoded)970 # - plus "GA94" for closed-caption data (currently not decoded) 907 971 return 0 unless $size > 20 and substr($$dataPt, $pos, 20) eq 908 972 "\x17\xee\x8c\x60\xf8\x4d\x11\xd9\x8c\xd6\x08\0\x20\x0c\x9a\x66MDPM"; 909 910 # load the GPS module because it contains conversion routines and911 # Composite tags needed for a number of tags we may be extracting912 require Image::ExifTool::GPS;913 973 # 914 974 # parse the MDPM records in the UUID 17ee8c60f84d11d98cd60800200c9a66 … … 916 976 # 917 977 my $tagTablePtr = GetTagTable('Image::ExifTool::H264::MDPM'); 918 my $oldIndent = $$e xifTool{INDENT};919 $$e xifTool{INDENT} .= '| ';978 my $oldIndent = $$et{INDENT}; 979 $$et{INDENT} .= '| '; 920 980 $end = $pos + $size; # end of payload 921 981 $pos += 20; # skip UUID + "MDPM" 922 982 my $num = Get8u($dataPt, $pos++); # get entry count 923 983 my $lastTag = 0; 924 $e xifTool->VerboseDir('MDPM', $num) if $exifTool->Options('Verbose');984 $et->VerboseDir('MDPM', $num) if $et->Options('Verbose'); 925 985 # walk through entries in the MDPM payload 926 986 for ($index=0; $index<$num and $pos<$end; ++$index) { 927 987 my $tag = Get8u($dataPt, $pos); 928 988 if ($tag <= $lastTag) { # should be in numerical order (PH) 929 $e xifTool->Warn('Entries in MDPM directory are out of sequence');989 $et->Warn('Entries in MDPM directory are out of sequence'); 930 990 last; 931 991 } … … 933 993 my $buff = substr($$dataPt, $pos + 1, 4); 934 994 my $from; 935 my $tagInfo = $e xifTool->GetTagInfo($tagTablePtr, $tag);995 my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); 936 996 if ($tagInfo) { 937 997 # use our own print conversion for Unknown tags … … 953 1013 --$combine; 954 1014 } 955 $e xifTool->HandleTag($tagTablePtr, $tag, undef,1015 $et->HandleTag($tagTablePtr, $tag, undef, 956 1016 TagInfo => $tagInfo, 957 1017 DataPt => \$buff, … … 962 1022 $pos += 5; 963 1023 } 964 $$e xifTool{INDENT} = $oldIndent;1024 $$et{INDENT} = $oldIndent; 965 1025 return 1; 966 1026 } … … 972 1032 sub ParseH264Video($$) 973 1033 { 974 my ($e xifTool, $dataPt) = @_;975 my $verbose = $e xifTool->Options('Verbose');976 my $out = $e xifTool->Options('TextOut');1034 my ($et, $dataPt) = @_; 1035 my $verbose = $et->Options('Verbose'); 1036 my $out = $et->Options('TextOut'); 977 1037 my $tagTablePtr = GetTagTable('Image::ExifTool::H264::Main'); 978 1038 my %parseNalUnit = ( 0x06 => 1, 0x07 => 1 ); # NAL unit types to parse … … 996 1056 ++$pos; 997 1057 # check forbidden_zero_bit 998 $nal_unit_type & 0x80 and $e xifTool->Warn('H264 forbidden bit error'), last;1058 $nal_unit_type & 0x80 and $et->Warn('H264 forbidden bit error'), last; 999 1059 $nal_unit_type &= 0x1f; 1000 1060 # ignore this NAL unit unless we will parse it … … 1011 1071 if ($verbose > 1) { 1012 1072 printf $out " NAL Unit Type: 0x%x (%d bytes)\n",$nal_unit_type, length $buff; 1013 my %parms = ( Out => $out ); 1014 $parms{MaxLen} = 96 if $verbose < 4; 1015 Image::ExifTool::HexDump(\$buff, undef, %parms) if $verbose > 2; 1073 $et->VerboseDump(\$buff); 1016 1074 } 1017 1075 pos($$dataPt) = $pos = $nextPos; … … 1019 1077 if ($nal_unit_type == 0x06) { # sei_rbsp (supplemental enhancement info) 1020 1078 1021 if ($$e xifTool{GotNAL06}) {1079 if ($$et{GotNAL06}) { 1022 1080 # process only the first SEI unless ExtractEmbedded is set 1023 next unless $e xifTool->Options('ExtractEmbedded');1024 $$e xifTool{DOC_NUM} = $$exifTool{GotNAL06};1081 next unless $et->Options('ExtractEmbedded'); 1082 $$et{DOC_NUM} = $$et{GotNAL06}; 1025 1083 } 1026 $foundUserData = ProcessSEI($e xifTool, { DataPt => \$buff } );1027 delete $$e xifTool{DOC_NUM};1084 $foundUserData = ProcessSEI($et, { DataPt => \$buff } ); 1085 delete $$et{DOC_NUM}; 1028 1086 # keep parsing SEI's until we find the user data 1029 1087 next unless $foundUserData; 1030 $$e xifTool{GotNAL06} = ($$exifTool{GotNAL06} || 0) + 1;1088 $$et{GotNAL06} = ($$et{GotNAL06} || 0) + 1; 1031 1089 1032 1090 } elsif ($nal_unit_type == 0x07) { # sequence_parameter_set_rbsp 1033 1091 1034 1092 # process this NAL unit type only once 1035 next if $$e xifTool{GotNAL07};1036 $$e xifTool{GotNAL07} = 1;1037 ParseSeqParamSet($e xifTool, $tagTablePtr, \$buff);1093 next if $$et{GotNAL07}; 1094 $$et{GotNAL07} = 1; 1095 ParseSeqParamSet($et, $tagTablePtr, \$buff); 1038 1096 } 1039 1097 # we were successful, so don't parse this NAL unit type again … … 1042 1100 # parse one extra H264 frame if we didn't find the user data in this one 1043 1101 # (Panasonic cameras don't put the SEI in the first frame) 1044 return 0 if $foundUserData or $$e xifTool{ParsedH264};1045 $$e xifTool{ParsedH264} = 1;1102 return 0 if $foundUserData or $$et{ParsedH264}; 1103 $$et{ParsedH264} = 1; 1046 1104 return 1; 1047 1105 } … … 1066 1124 =head1 AUTHOR 1067 1125 1068 Copyright 2003-20 11, Phil Harvey (phil at owl.phy.queensu.ca)1126 Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com) 1069 1127 1070 1128 This library is free software; you can redistribute it and/or modify it
Note:
See TracChangeset
for help on using the changeset viewer.