Projects
Multimedia
bento4
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 7
View file
bento4.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Sat Oct 7 07:10:54 UTC 2017 - aloisio@gmx.com + +- Update to 1.5.1-620 + +------------------------------------------------------------------- Sun Oct 1 14:51:10 UTC 2017 - aloisio@gmx.com - Update to 1.5.0-619
View file
bento4.spec
Changed
@@ -16,10 +16,10 @@ # -%define _over 1.5.0-619 -%define _libver 1_5_0r619 +%define _over 1.5.1-620 +%define _libver 1_5_1r620 Name: bento4 -Version: 1.5.0r619 +Version: 1.5.1r620 Release: 0 Summary: C++ toolkit for all your MP4 and MPEG DASH media format needs License: GPL-2.0
View file
bento4-1.5.0r619.tar.gz/Build/Targets/universal-apple-macosx/Bento4.xcodeproj/project.pbxproj -> bento4-1.5.1r620.tar.gz/Build/Targets/universal-apple-macosx/Bento4.xcodeproj/project.pbxproj
Changed
@@ -142,6 +142,8 @@ CA86EED219A95C68008A3B00 /* Ap4SegmentBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = CA86EED019A95C68008A3B00 /* Ap4SegmentBuilder.h */; }; CA86EEE219A95DFF008A3B00 /* libBento4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA7E6C914ACD763008AA54E /* libBento4.a */; }; CA86EEE519A95E30008A3B00 /* FragmentCreatorTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA86EEE419A95E30008A3B00 /* FragmentCreatorTest.cpp */; }; + CA87B94A1F81B0C4005F42D6 /* libBento4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA7E6C914ACD763008AA54E /* libBento4.a */; }; + CA87B94D1F81B130005F42D6 /* Mp4Diff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA87B94C1F81B122005F42D6 /* Mp4Diff.cpp */; }; CA8A94D91929A68700836179 /* libBento4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA7E6C914ACD763008AA54E /* libBento4.a */; }; CA8A94DC1929A6C100836179 /* Mp4Mux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA8A94DB1929A6C100836179 /* Mp4Mux.cpp */; }; CA8A94DD1929DD9100836179 /* Ap4AvcParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA3EDA960D7E14D3007AE943 /* Ap4AvcParser.cpp */; }; @@ -970,6 +972,15 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + CA87B9401F81B08B005F42D6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; CAFE9C671D1B487700F9FF67 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1067,6 +1078,9 @@ CA86EED019A95C68008A3B00 /* Ap4SegmentBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Ap4SegmentBuilder.h; sourceTree = "<group>"; }; CA86EED719A95DD3008A3B00 /* FragmentCreatorTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = FragmentCreatorTest; sourceTree = BUILT_PRODUCTS_DIR; }; CA86EEE419A95E30008A3B00 /* FragmentCreatorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FragmentCreatorTest.cpp; sourceTree = "<group>"; }; + CA87B9421F81B08B005F42D6 /* mp4diff */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mp4diff; sourceTree = BUILT_PRODUCTS_DIR; }; + CA87B9441F81B08B005F42D6 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; }; + CA87B94C1F81B122005F42D6 /* Mp4Diff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mp4Diff.cpp; sourceTree = "<group>"; }; CA8A94CE1929A65E00836179 /* mp4mux */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mp4mux; sourceTree = BUILT_PRODUCTS_DIR; }; CA8A94DB1929A6C100836179 /* Mp4Mux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mp4Mux.cpp; sourceTree = "<group>"; }; CA8B6A600F66D20900720A07 /* Ap4MfhdAtom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Ap4MfhdAtom.cpp; sourceTree = "<group>"; }; @@ -1492,6 +1506,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + CA87B93F1F81B08B005F42D6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CA87B94A1F81B0C4005F42D6 /* libBento4.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; CA8A94CB1929A65E00836179 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1643,7 +1665,9 @@ CA646A860CE97B2D009699D7 /* Apps */, CA646A9B0CE97B51009699D7 /* Test */, C6A0FF2B0290797F04C91782 /* Documentation */, + CA87B9431F81B08B005F42D6 /* Mp4Diff */, 1AB674ADFE9D54B511CA2CBB /* Products */, + CA87B9491F81B0C4005F42D6 /* Frameworks */, ); name = Bento4; sourceTree = "<group>"; @@ -1705,6 +1729,7 @@ CA00A6531A1C36560064B4D3 /* mp4pssh */, CAE1FBF61AF8493E00607B3C /* mp42hls */, CAFE9C691D1B487700F9FF67 /* LargeFilesTest */, + CA87B9421F81B08B005F42D6 /* mp4diff */, ); name = Products; sourceTree = "<group>"; @@ -1790,6 +1815,7 @@ CA00CB8513D9F1EC00C1A140 /* Mp4Compact */, CA44C5260D46371C00173F5F /* Mp4DcfPackager */, CA646A8B0CE97B2D009699D7 /* Mp4Decrypt */, + CA87B94B1F81B122005F42D6 /* Mp4Diff */, CA646A8D0CE97B2D009699D7 /* Mp4Dump */, CA646A8F0CE97B2D009699D7 /* Mp4Edit */, CA646A910CE97B2D009699D7 /* Mp4Encrypt */, @@ -1935,6 +1961,29 @@ path = FragmentCreator; sourceTree = "<group>"; }; + CA87B9431F81B08B005F42D6 /* Mp4Diff */ = { + isa = PBXGroup; + children = ( + CA87B9441F81B08B005F42D6 /* main.cpp */, + ); + path = Mp4Diff; + sourceTree = "<group>"; + }; + CA87B9491F81B0C4005F42D6 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = "<group>"; + }; + CA87B94B1F81B122005F42D6 /* Mp4Diff */ = { + isa = PBXGroup; + children = ( + CA87B94C1F81B122005F42D6 /* Mp4Diff.cpp */, + ); + path = Mp4Diff; + sourceTree = "<group>"; + }; CA8A94DA1929A6C100836179 /* Mp4Mux */ = { isa = PBXGroup; children = ( @@ -2903,6 +2952,23 @@ productReference = CA86EED719A95DD3008A3B00 /* FragmentCreatorTest */; productType = "com.apple.product-type.tool"; }; + CA87B9411F81B08B005F42D6 /* Mp4Diff */ = { + isa = PBXNativeTarget; + buildConfigurationList = CA87B9481F81B08B005F42D6 /* Build configuration list for PBXNativeTarget "Mp4Diff" */; + buildPhases = ( + CA87B93E1F81B08B005F42D6 /* Sources */, + CA87B93F1F81B08B005F42D6 /* Frameworks */, + CA87B9401F81B08B005F42D6 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Mp4Diff; + productName = Mp4Diff; + productReference = CA87B9421F81B08B005F42D6 /* mp4diff */; + productType = "com.apple.product-type.tool"; + }; CA8A94CD1929A65E00836179 /* Mp4Mux */ = { isa = PBXNativeTarget; buildConfigurationList = CA8A94D61929A65E00836179 /* Build configuration list for PBXNativeTarget "Mp4Mux" */; @@ -3223,6 +3289,10 @@ CA00A6521A1C36560064B4D3 = { CreatedOnToolsVersion = 6.1; }; + CA87B9411F81B08B005F42D6 = { + CreatedOnToolsVersion = 9.0; + ProvisioningStyle = Manual; + }; CAFE9C681D1B487700F9FF67 = { CreatedOnToolsVersion = 7.3; }; @@ -3251,6 +3321,7 @@ F9FDDA2D0EA798FF0061DCB2 /* Bento4C */, CA646ABA0CE97BFD009699D7 /* Mp4Dump */, CA646ACD0CE97C80009699D7 /* Mp4Info */, + CA87B9411F81B08B005F42D6 /* Mp4Diff */, CA646AE00CE97CD2009699D7 /* Mp4Encrypt */, CA44C5290D46375F00173F5F /* Mp4DcfPackager */, CA646AED0CE97CEE009699D7 /* Mp4Decrypt */, @@ -3457,6 +3528,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + CA87B93E1F81B08B005F42D6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CA87B94D1F81B130005F42D6 /* Mp4Diff.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; CA8A94CA1929A65E00836179 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -4700,6 +4779,73 @@ }; name = Release; }; + CA87B9461F81B08B005F42D6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = mp4diff; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx; + }; + name = Debug; + }; + CA87B9471F81B08B005F42D6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = mp4diff; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx; + }; + name = Release; + }; CA8A94D41929A65E00836179 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -5465,6 +5611,15 @@ ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; + }; + CA87B9481F81B08B005F42D6 /* Build configuration list for PBXNativeTarget "Mp4Diff" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CA87B9461F81B08B005F42D6 /* Debug */, + CA87B9471F81B08B005F42D6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; CA8A94D61929A65E00836179 /* Build configuration list for PBXNativeTarget "Mp4Mux" */ = { isa = XCConfigurationList;
View file
bento4-1.5.1r620.tar.gz/Source/C++/Apps/Mp4Diff
Added
+(directory)
View file
bento4-1.5.1r620.tar.gz/Source/C++/Apps/Mp4Diff/Mp4Diff.cpp
Added
@@ -0,0 +1,231 @@ +/***************************************************************** +| +| AP4 - MP4 File Info +| +| Copyright 2002-2015 Axiomatic Systems, LLC +| +| +| This file is part of Bento4/AP4 (MP4 Atom Processing Library). +| +| Unless you have obtained Bento4 under a difference license, +| this version of Bento4 is Bento4|GPL. +| Bento4|GPL is free software; you can redistribute it and/or modify +| it under the terms of the GNU General Public License as published by +| the Free Software Foundation; either version 2, or (at your option) +| any later version. +| +| Bento4|GPL is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +| GNU General Public License for more details. +| +| You should have received a copy of the GNU General Public License +| along with Bento4|GPL; see the file COPYING. If not, write to the +| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA +| 02111-1307, USA. +| + ****************************************************************/ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#include <stdio.h> +#include <stdlib.h> + +#include "Ap4.h" +#include "Ap4BitStream.h" +#include "Ap4Mp4AudioInfo.h" +#include "Ap4HevcParser.h" + +/*---------------------------------------------------------------------- +| constants ++---------------------------------------------------------------------*/ +#define BANNER "MP4 Diff - Version 1.0.0\n"\ + "(Bento4 Version " AP4_VERSION_STRING ")\n"\ + "(c) 2002-2017 Axiomatic Systems, LLC" + +/*---------------------------------------------------------------------- +| globals ++---------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- +| PrintUsageAndExit ++---------------------------------------------------------------------*/ +static void +PrintUsageAndExit() +{ + fprintf(stderr, + BANNER + "\n\nusage: mp4diff [options] <input1> <input2>\n" + ); + exit(1); +} + +/*---------------------------------------------------------------------- +| DiffSamples ++---------------------------------------------------------------------*/ +static void +DiffSamples(unsigned int index, + AP4_Sample& sample1, AP4_DataBuffer& sample_data1, + AP4_Sample& sample2, AP4_DataBuffer& sample_data2) +{ + if (sample_data1.GetDataSize() != sample_data2.GetDataSize()) { + printf("!!! sample %d: sizes not equal: %d, %d\n", index, sample_data1.GetDataSize(), sample_data2.GetDataSize()); + return; + } + + const AP4_UI08* data1 = (const AP4_UI08*)sample_data1.GetData(); + const AP4_UI08* data2 = (const AP4_UI08*)sample_data2.GetData(); + bool in_diff = false; + unsigned int diff_start = 0; + for (unsigned int i=0; i<sample_data1.GetDataSize(); i++) { + if (in_diff) { + if (data1[i] == data2[i]) { + // end of diff + printf("!!! sample %d, %d differences at %d / %d\n", index, i-diff_start, diff_start, sample_data1.GetDataSize()); + in_diff = false; + } + } else { + if (data1[i] != data2[i]) { + diff_start = i; + in_diff = true; + } + } + } + if (in_diff) { + printf("!!! sample %d, %d differences at %d / %d\n", index, sample_data1.GetDataSize()-diff_start, diff_start, sample_data1.GetDataSize()); + } +} + +/*---------------------------------------------------------------------- +| DiffFragments ++---------------------------------------------------------------------*/ +static void +DiffFragments(AP4_Movie& movie1, AP4_ByteStream* stream1, AP4_Movie& movie2, AP4_ByteStream* stream2) +{ + stream1->Seek(0); + stream2->Seek(0); + AP4_LinearReader reader1(movie1, stream1); + AP4_LinearReader reader2(movie2, stream2); + AP4_List<AP4_Track>::Item* track_item1 = movie1.GetTracks().FirstItem(); + AP4_List<AP4_Track>::Item* track_item2 = movie2.GetTracks().FirstItem(); + while (track_item1 && track_item2) { + reader1.EnableTrack(track_item1->GetData()->GetId()); + reader2.EnableTrack(track_item1->GetData()->GetId()); + track_item1 = track_item1->GetNext(); + track_item2 = track_item2->GetNext(); + } + + AP4_Sample sample1; + AP4_Sample sample2; + AP4_DataBuffer sample_data1; + AP4_DataBuffer sample_data2; + AP4_UI32 prev_track_id = 0; + for(unsigned int i=0; ; i++) { + AP4_UI32 track_id1 = 0; + AP4_UI32 track_id2 = 0; + AP4_Result result1 = reader1.ReadNextSample(sample1, sample_data1, track_id1); + AP4_Result result2 = reader2.ReadNextSample(sample2, sample_data2, track_id2); + if (AP4_SUCCEEDED(result1) && AP4_SUCCEEDED(result2)) { + if (track_id1 != track_id2) { + fprintf(stderr, "!!! sample %d, track ID 1 = %d, track ID 2 = %d\n", i, track_id1, track_id2); + return; + } + + if (track_id1 != prev_track_id) { + printf("Track %d:\n", track_id1); + prev_track_id = track_id1; + } + + DiffSamples(i, sample1, sample_data1, sample2, sample_data2); + } else { + printf("### processed %d samples\n", i+1); + break; + } + } +} + +/*---------------------------------------------------------------------- +| main ++---------------------------------------------------------------------*/ +int +main(int argc, char** argv) +{ + if (argc < 3) { + PrintUsageAndExit(); + } + const char* filename1 = NULL; + const char* filename2 = NULL; + + while (char* arg = *++argv) { + if (filename1 == NULL) { + filename1 = arg; + } else if (filename2 == NULL) { + filename2 = arg; + } else { + fprintf(stderr, "ERROR: unexpected argument '%s'\n", arg); + return 1; + } + } + if (filename1 == NULL || filename2 == NULL) { + fprintf(stderr, "ERROR: filename missing\n"); + return 1; + } + + AP4_ByteStream* input1 = NULL; + AP4_Result result = AP4_FileByteStream::Create(filename1, + AP4_FileByteStream::STREAM_MODE_READ, + input1); + if (AP4_FAILED(result)) { + fprintf(stderr, "ERROR: cannot open input file %s (%d)\n", filename1, result); + return 1; + } + + AP4_ByteStream* input2 = NULL; + result = AP4_FileByteStream::Create(filename2, + AP4_FileByteStream::STREAM_MODE_READ, + input2); + if (AP4_FAILED(result)) { + fprintf(stderr, "ERROR: cannot open input file %s (%d)\n", filename2, result); + return 1; + } + + AP4_File* file1 = new AP4_File(*input1, true); + AP4_File* file2 = new AP4_File(*input2, true); + + AP4_Movie* movie1 = file1->GetMovie(); + AP4_Movie* movie2 = file2->GetMovie(); + + if (movie1 && movie2) { + AP4_List<AP4_Track>& tracks1 = movie1->GetTracks(); + AP4_List<AP4_Track>& tracks2 = movie1->GetTracks(); + + if (tracks1.ItemCount() != tracks2.ItemCount()) { + fprintf(stderr, "### file 1 has %d tracks, file 2 has %d tracks\n", tracks1.ItemCount(), tracks2.ItemCount()); + } else { + for (unsigned int i=0; i<tracks1.ItemCount(); i++) { + AP4_Track* track1; + AP4_Track* track2; + tracks1.Get(i, track1); + tracks2.Get(i, track2); + printf("--- comparing track ID %d\n", track1->GetId()); + } + } + + if (movie1->HasFragments() != movie2->HasFragments()) { + fprintf(stderr, "### file 1 fragmented=%s, file2 fragmented=%s\n", + movie1->HasFragments() ? "true" : "false", + movie2->HasFragments() ? "true" : "false"); + } + if (movie1->HasFragments() && movie2->HasFragments()) { + DiffFragments(*movie1, input1, *movie2, input2); + } + } + + delete file1; + delete file2; + input1->Release(); + input2->Release(); + + return 0; +}
View file
bento4-1.5.0r619.tar.gz/Source/C++/Apps/Mp4Mux/Mp4Mux.cpp -> bento4-1.5.1r620.tar.gz/Source/C++/Apps/Mp4Mux/Mp4Mux.cpp
Changed
@@ -82,7 +82,7 @@ { fprintf(stderr, BANNER - "\n\nusage: mp4mux [options] --track [<type>:]<input>[#<params] [--track [<type>:]<input>[#<params] ...] <output>\n" + "\n\nusage: mp4mux [options] --track [<type>:]<input>[#<params>] [--track [<type>:]<input>[#<params>] ...] <output>\n" "\n" " <params>, when specified, are expressd as a comma-separated list of\n" " one or more <name>=<value> parameters\n" @@ -92,6 +92,7 @@ " h265: H265/HEVC NAL units\n" " optional params:\n" " frame_rate: floating point number in frames per second (default=24.0)\n" + " format: hev1 or hvc1 (default) for HEVC tracks\n" " aac: AAC in ADTS format\n" " mp4: MP4 track(s) from an MP4 file\n" " optional params:\n" @@ -585,7 +586,8 @@ { unsigned int video_width = 0; unsigned int video_height = 0; - + AP4_UI32 format = AP4_SAMPLE_FORMAT_HVC1; + AP4_ByteStream* input; AP4_Result result = AP4_FileByteStream::Create(input_name, AP4_FileByteStream::STREAM_MODE_READ, input); if (AP4_FAILED(result)) { @@ -603,6 +605,12 @@ return; } video_frame_rate = (unsigned int)(1000.0*frame_rate); + } else if (parameters[i].m_Name == "format") { + if (parameters[i].m_Value == "hev1") { + format = AP4_SAMPLE_FORMAT_HEV1; + } else if (parameters[i].m_Value == "hvc1") { + format = AP4_SAMPLE_FORMAT_HVC1; + } } } @@ -764,8 +772,9 @@ } // setup the video the sample descripton + AP4_UI08 parameters_completeness = (format == AP4_SAMPLE_FORMAT_HVC1 ? 1 : 0); AP4_HevcSampleDescription* sample_description = - new AP4_HevcSampleDescription(AP4_SAMPLE_FORMAT_HEV1, + new AP4_HevcSampleDescription(format, video_width, video_height, 24, @@ -787,8 +796,11 @@ temporal_id_nested, nalu_length_size, vps_array, + parameters_completeness, sps_array, - pps_array); + parameters_completeness, + pps_array, + parameters_completeness); sample_table->AddSampleDescription(sample_description);
View file
bento4-1.5.0r619.tar.gz/Source/C++/Codecs/Ap4AvcParser.cpp -> bento4-1.5.1r620.tar.gz/Source/C++/Codecs/Ap4AvcParser.cpp
Changed
@@ -1001,7 +1001,10 @@ eos = false; } - return Feed(nal_unit->GetData(), nal_unit->GetDataSize(), access_unit_info, eos); + return Feed(nal_unit ? nal_unit->GetData() : NULL, + nal_unit ? nal_unit->GetDataSize() : 0, + access_unit_info, + eos); } /*----------------------------------------------------------------------
View file
bento4-1.5.0r619.tar.gz/Source/C++/Codecs/Ap4AvcParser.h -> bento4-1.5.1r620.tar.gz/Source/C++/Codecs/Ap4AvcParser.h
Changed
@@ -236,16 +236,16 @@ /** * Feed some data to the parser and look for the next NAL Unit. * - * @param data: Pointer to the memory buffer with the data to feed. - * @param data_size: Size in bytes of the buffer pointed to by the + * @param data Pointer to the memory buffer with the data to feed. + * @param data_size Size in bytes of the buffer pointed to by the * data pointer. - * @param bytes_consumed: Number of bytes from the data buffer that were + * @param bytes_consumed Number of bytes from the data buffer that were * consumed and stored by the parser. - * @param access_unit_info: Reference to a AccessUnitInfo structure that will + * @param access_unit_info Reference to a AccessUnitInfo structure that will * contain information about any access unit found in the data. If no * access unit was found, the nal_units field of this structure will be an * empty array. - * @param eos: Boolean flag that indicates if this buffer is the last + * @param eos Boolean flag that indicates if this buffer is the last * buffer in the stream/file (End Of Stream). * * @result: AP4_SUCCESS is the call succeeds, or an error code if it
View file
bento4-1.5.0r619.tar.gz/Source/C++/Codecs/Ap4HevcParser.cpp -> bento4-1.5.1r620.tar.gz/Source/C++/Codecs/Ap4HevcParser.cpp
Changed
@@ -35,7 +35,7 @@ /*---------------------------------------------------------------------- | debugging +---------------------------------------------------------------------*/ -#define AP4_HEVC_PARSER_ENABLE_DEBUG 1 +#define AP4_HEVC_PARSER_ENABLE_DEBUG 0 #if defined(AP4_HEVC_PARSER_ENABLE_DEBUG) #define DBG_PRINTF_0(_x0) printf(_x0) @@ -130,9 +130,9 @@ AP4_HevcNalParser::SliceTypeName(unsigned int slice_type) { switch (slice_type) { - case 0: return "B"; - case 1: return "P"; - case 2: return "I"; + case AP4_HEVC_SLICE_TYPE_B: return "B"; + case AP4_HEVC_SLICE_TYPE_P: return "P"; + case AP4_HEVC_SLICE_TYPE_I: return "I"; default: return NULL; } } @@ -156,6 +156,33 @@ } /*---------------------------------------------------------------------- +| SignedGolomb ++---------------------------------------------------------------------*/ +static int +SignedGolomb(unsigned int code_num) +{ + if (code_num % 2) { + return (code_num+1)/2; + } else { + return -((int)code_num/2); + } +} + +/*---------------------------------------------------------------------- +| BitsNeeded ++---------------------------------------------------------------------*/ +static unsigned int +BitsNeeded(unsigned int num_values) +{ + unsigned int bits_needed = 1; + while (num_values > (unsigned int)(1 << bits_needed)) { + ++bits_needed; + } + + return bits_needed; +} + +/*---------------------------------------------------------------------- | AP4_HevcNalParser::AP4_HevcNalParser +---------------------------------------------------------------------*/ AP4_HevcNalParser::AP4_HevcNalParser() : @@ -164,28 +191,89 @@ } /*---------------------------------------------------------------------- -| AP4_HevcSliceSegmentHeader +| scaling_list_data +---------------------------------------------------------------------*/ -struct AP4_HevcSliceSegmentHeader { - AP4_HevcSliceSegmentHeader() {} // leave members uninitialized on purpose +static void +scaling_list_data(AP4_BitReader& bits) +{ + for (unsigned int sizeId = 0; sizeId < 4; sizeId++) { + for (unsigned int matrixId = 0; matrixId < ((sizeId == 3)?2:6); matrixId++) { + unsigned int flag = bits.ReadBit(); // scaling_list_pred_mode_flag[ sizeId ][ matrixId ] + if (!flag) { + ReadGolomb(bits); // scaling_list_pred_matrix_id_delta[ sizeId ][ matrixId ] + } else { + // nextCoef = 8; + unsigned int coefNum = (1 << (4+(sizeId << 1))); + if (coefNum > 64) coefNum = 64; + if (sizeId > 1) { + ReadGolomb(bits); // scaling_list_dc_coef_minus8[ sizeId − 2 ][ matrixId ] + // nextCoef = scaling_list_dc_coef_minus8[ sizeId − 2 ][ matrixId ] + 8 + } + for (unsigned i = 0; i < coefNum; i++) { + ReadGolomb(bits); // scaling_list_delta_coef + // nextCoef = ( nextCoef + scaling_list_delta_coef + 256 ) % 256 + // ScalingList[ sizeId ][ matrixId ][ i ] = nextCoef + } + } + } + } +} + +/*---------------------------------------------------------------------- +| short_term_ref_pic_set ++---------------------------------------------------------------------*/ +typedef struct { + unsigned int delta_poc_s0_minus1[16]; + unsigned int delta_poc_s1_minus1[16]; + unsigned int used_by_curr_pic_s0_flag[16]; + unsigned int used_by_curr_pic_s1_flag[16]; +} short_term_ref_pic_set; + +static AP4_Result +parse_short_term_ref_pic_set(short_term_ref_pic_set* rps, unsigned int stRpsIdx, unsigned int num_short_term_ref_pic_sets, AP4_BitReader& bits) { + AP4_SetMemory(rps, 0, sizeof(*rps)); + + unsigned int inter_ref_pic_set_prediction_flag = 0; + if (stRpsIdx != 0) { + inter_ref_pic_set_prediction_flag = bits.ReadBit(); + } + if (inter_ref_pic_set_prediction_flag) { + unsigned int delta_idx_minus1 = 0; + if (stRpsIdx == num_short_term_ref_pic_sets) { + delta_idx_minus1 = ReadGolomb(bits); + } + /* delta_rps_sign = */ bits.ReadBit(); + /* abs_delta_rps_minus1 = */ ReadGolomb(bits); + if (delta_idx_minus1+1 > stRpsIdx) return AP4_ERROR_INVALID_FORMAT; // should not happen + //unsigned int RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1); + // TODO: finish parsing this + printf("### This bitstream uses features that are not yet supported. Please file a ticket."); + return AP4_ERROR_NOT_SUPPORTED; +// for (unsigned j=0; j<=NumDeltaPocs[RefRpsIdx]; j++) { +// unsigned int used_by_curr_pic_flag /*[j]*/ = bits.ReadBit(); +// if (!used_by_curr_pic_flag /*[j]*/) { +// /* use_delta_flag[j] = */ bits.ReadBit(); +// } +// } + // <TODO + } else { + unsigned int num_negative_pics = ReadGolomb(bits); + unsigned int num_positive_pics = ReadGolomb(bits); + if (num_negative_pics > 16 || num_positive_pics > 16) { + return AP4_ERROR_INVALID_FORMAT; + } + for (unsigned int i=0; i<num_negative_pics; i++) { + rps->delta_poc_s0_minus1[i] = ReadGolomb(bits); + rps->used_by_curr_pic_s0_flag[i] = bits.ReadBit(); + } + for (unsigned i=0; i<num_positive_pics; i++) { + rps->delta_poc_s1_minus1[i] = ReadGolomb(bits); + rps->used_by_curr_pic_s1_flag[i] = bits.ReadBit(); + } + } - AP4_Result Parse(const AP4_UI08* data, - unsigned int data_size, - unsigned int nal_unit_type, - AP4_HevcPictureParameterSet** picture_parameter_sets, - AP4_HevcSequenceParameterSet** sequence_parameter_sets); - - unsigned int first_slice_segment_in_pic_flag; - unsigned int no_output_of_prior_pics_flag; - unsigned int slice_pic_parameter_set_id; - unsigned int dependent_slice_segment_flag; - unsigned int slice_segment_address; - unsigned int slice_type; - unsigned int pic_output_flag; - unsigned int colour_plane_id; - unsigned int slice_pic_order_cnt_lsb; - unsigned int short_term_ref_pic_set_sps_flag; -}; + return AP4_SUCCESS; +} /*---------------------------------------------------------------------- | AP4_HevcSliceSegmentHeader::Parse @@ -199,12 +287,14 @@ // initialize all members to 0 AP4_SetMemory(this, 0, sizeof(*this)); + // some fields default to 1 + pic_output_flag = 1; + + // start the parser AP4_DataBuffer unescaped(data, data_size); AP4_NalParser::Unescape(unescaped); AP4_BitReader bits(unescaped.GetData(), unescaped.GetDataSize()); - bits.SkipBits(16); // NAL Unit Header - first_slice_segment_in_pic_flag = bits.ReadBit(); if (nal_unit_type >= AP4_HEVC_NALU_TYPE_BLA_W_LP && nal_unit_type <= AP4_HEVC_NALU_TYPE_RSV_IRAP_VCL23) { no_output_of_prior_pics_flag = bits.ReadBit(); @@ -222,48 +312,228 @@ return AP4_ERROR_INVALID_FORMAT; } + // PicSizeInCtbsY = PicWidthInCtbsY * PicHeightInCtbsY + // PicWidthInCtbsY = Ceil( pic_width_in_luma_samples / CtbSizeY ) + // PicHeightInCtbsY = Ceil( pic_height_in_luma_samples / CtbSizeY ) + // CtbSizeY = 1 << CtbLog2SizeY + // CtbLog2SizeY = MinCbLog2SizeY + log2_diff_max_min_luma_coding_block_size + // MinCbLog2SizeY = log2_min_luma_coding_block_size_minus3 + 3 + unsigned int MinCbLog2SizeY = sps->log2_min_luma_coding_block_size_minus3 + 3; + unsigned int CtbLog2SizeY = MinCbLog2SizeY + sps->log2_diff_max_min_luma_coding_block_size; + unsigned int CtbSizeY = 1 << CtbLog2SizeY; + unsigned int PicWidthInCtbsY = (sps->pic_width_in_luma_samples + CtbSizeY - 1) / CtbSizeY; + unsigned int PicHeightInCtbsY = (sps->pic_height_in_luma_samples + CtbSizeY - 1) / CtbSizeY; + unsigned int PicSizeInCtbsY = PicWidthInCtbsY * PicHeightInCtbsY; + if (!first_slice_segment_in_pic_flag) { if (pps->dependent_slice_segments_enabled_flag) { dependent_slice_segment_flag = bits.ReadBit(); } - // compute how many bits the next field: - // n_bits = Ceil( Log2( PicSizeInCtbsY ) ) - // PicSizeInCtbsY = PicWidthInCtbsY * PicHeightInCtbsY - // PicWidthInCtbsY = Ceil( pic_width_in_luma_samples / CtbSizeY ) - // PicHeightInCtbsY = Ceil( pic_height_in_luma_samples / CtbSizeY ) - // CtbSizeY = 1 << CtbLog2SizeY - // CtbLog2SizeY = MinCbLog2SizeY + log2_diff_max_min_luma_coding_block_size - // MinCbLog2SizeY = log2_min_luma_coding_block_size_minus3 + 3 - unsigned int MinCbLog2SizeY = sps->log2_min_luma_coding_block_size_minus3 + 3; - unsigned int CtbLog2SizeY = MinCbLog2SizeY + sps->log2_diff_max_min_luma_coding_block_size; - unsigned int CtbSizeY = 1 << CtbLog2SizeY; - unsigned int PicWidthInCtbsY = (sps->pic_width_in_luma_samples + CtbSizeY - 1) / CtbSizeY; - unsigned int PicHeightInCtbsY = (sps->pic_height_in_luma_samples + CtbSizeY - 1) / CtbSizeY; - unsigned int PicSizeInCtbsY = PicWidthInCtbsY * PicHeightInCtbsY; - unsigned int bits_needed = 1; - while (PicSizeInCtbsY > (unsigned int)(1 << bits_needed)) { - ++bits_needed; - } - slice_segment_address = bits.ReadBits(bits_needed); + unsigned int bits_needed = BitsNeeded(PicSizeInCtbsY); + if (bits_needed) { + slice_segment_address = bits.ReadBits(bits_needed); + } } if (!dependent_slice_segment_flag) { - bits.ReadBits(pps->num_extra_slice_header_bits); - } + if (pps->num_extra_slice_header_bits) { + bits.ReadBits(pps->num_extra_slice_header_bits); // slice_reserved_flag[...] + } - slice_type = ReadGolomb(bits); - if (pps->output_flag_present_flag) { - pic_output_flag = bits.ReadBit(); + slice_type = ReadGolomb(bits); + if (slice_type != AP4_HEVC_SLICE_TYPE_B && slice_type != AP4_HEVC_SLICE_TYPE_P && slice_type != AP4_HEVC_SLICE_TYPE_I) { + return AP4_ERROR_INVALID_FORMAT; + } + if (pps->output_flag_present_flag) { + pic_output_flag = bits.ReadBit(); + } + if (sps->separate_colour_plane_flag) { + colour_plane_id = bits.ReadBits(2); + } + unsigned int slice_sao_luma_flag = 0; + unsigned int slice_sao_chroma_flag = 0; + unsigned int slice_deblocking_filter_disabled_flag = 0; + unsigned int slice_temporal_mvp_enabled_flag = 0; + if (nal_unit_type != AP4_HEVC_NALU_TYPE_IDR_W_RADL && nal_unit_type != AP4_HEVC_NALU_TYPE_IDR_N_LP) { + slice_pic_order_cnt_lsb = bits.ReadBits(sps->log2_max_pic_order_cnt_lsb_minus4+4); + short_term_ref_pic_set_sps_flag = bits.ReadBit(); + if (!short_term_ref_pic_set_sps_flag) { + short_term_ref_pic_set rps; + AP4_Result result = parse_short_term_ref_pic_set(&rps, sps->num_short_term_ref_pic_sets, sps->num_short_term_ref_pic_sets, bits); + if (AP4_FAILED(result)) return result; + } else if (sps->num_short_term_ref_pic_sets > 1) { + short_term_ref_pic_set_idx = bits.ReadBits(BitsNeeded(sps->num_short_term_ref_pic_sets)); + } + + if (sps->long_term_ref_pics_present_flag) { + unsigned int num_long_term_sps = 0; + if (sps->num_long_term_ref_pics_sps > 0) { + num_long_term_sps = ReadGolomb(bits); + } + unsigned int num_long_term_pics = ReadGolomb(bits); + for (unsigned int i=0; i<num_long_term_sps + num_long_term_pics; i++) { + if (i < num_long_term_sps) { + if (sps->num_long_term_ref_pics_sps > 1) { + /* lt_idx_sps[i] = */ bits.ReadBits(BitsNeeded(sps->num_long_term_ref_pics_sps)); + } + } else { + /* poc_lsb_lt[i] = */ bits.ReadBits(sps->log2_max_pic_order_cnt_lsb_minus4+4); + /* used_by_curr_pic_lt_flag[i] = */ bits.ReadBit(); + } + unsigned int delta_poc_msb_present_flag /*[i]*/ = bits.ReadBit(); + if (delta_poc_msb_present_flag /*[i]*/) { + /* delta_poc_msb_cycle_lt[i] = */ ReadGolomb(bits); + } + } + } + if (sps->sps_temporal_mvp_enabled_flag) { + slice_temporal_mvp_enabled_flag = bits.ReadBit(); + } + } + if (sps->sample_adaptive_offset_enabled_flag) { + slice_sao_luma_flag = bits.ReadBit(); + unsigned int ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc; + if (ChromaArrayType) { + slice_sao_chroma_flag = bits.ReadBit(); + } + } + if (slice_type == AP4_HEVC_SLICE_TYPE_P || slice_type == AP4_HEVC_SLICE_TYPE_B) { + unsigned int num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; + unsigned int num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; + unsigned int num_ref_idx_active_override_flag = bits.ReadBit(); + if (num_ref_idx_active_override_flag) { + num_ref_idx_l0_active_minus1 = ReadGolomb(bits); + if (slice_type == AP4_HEVC_SLICE_TYPE_B) { + num_ref_idx_l1_active_minus1 = ReadGolomb(bits); + } + } + if (num_ref_idx_l0_active_minus1 > 14 || num_ref_idx_l1_active_minus1 > 14) { + return AP4_ERROR_INVALID_FORMAT; + } + // TODO: finish parsing this + //if (pps->lists_modification_present_flag && NumPicTotalCurr > 1) { + //ref_pic_lists_modification( ) + //} + if (slice_type == AP4_HEVC_SLICE_TYPE_B) { + /* mvd_l1_zero_flag = */ bits.ReadBit(); + } + if (pps->cabac_init_present_flag) { + /* cabac_init_flag = */ bits.ReadBit(); + } + if (slice_temporal_mvp_enabled_flag) { + unsigned int collocated_from_l0_flag = 1; + if (slice_type == AP4_HEVC_SLICE_TYPE_B) { + collocated_from_l0_flag = bits.ReadBit(); + } + if (( collocated_from_l0_flag && num_ref_idx_l0_active_minus1 > 0) || + (!collocated_from_l0_flag && num_ref_idx_l1_active_minus1 > 0)) { + /* collocated_ref_idx = */ ReadGolomb(bits); + } + } + if ((pps->weighted_pred_flag && slice_type == AP4_HEVC_SLICE_TYPE_P) || + (pps->weighted_bipred_flag && slice_type == AP4_HEVC_SLICE_TYPE_B)) { + // +++ pred_weight_table() + /* luma_log2_weight_denom = */ ReadGolomb(bits); + if (sps->chroma_format_idc != 0) { + /* delta_chroma_log2_weight_denom = */ /* SignedGolomb( */ ReadGolomb(bits) /*)*/; + } + unsigned int luma_weight_l0_flag[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + for (unsigned int i=0; i<=num_ref_idx_l0_active_minus1; i++) { + luma_weight_l0_flag[i] = bits.ReadBit(); + } + unsigned int chroma_weight_l0_flag[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + if (sps->chroma_format_idc != 0) { + for (unsigned int i=0; i<=num_ref_idx_l0_active_minus1; i++) { + chroma_weight_l0_flag[i] = bits.ReadBit(); + } + } + for (unsigned int i=0; i<=num_ref_idx_l0_active_minus1; i++) { + if (luma_weight_l0_flag[i]) { + /* delta_luma_weight_l0[i] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + /* luma_offset_l0[i] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + } + if (chroma_weight_l0_flag[i]) { + for (unsigned int j=0; j<2; j++) { + /* delta_chroma_weight_l0[i][j] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + /* delta_chroma_offset_l0[i][j] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + } + } + } + if (slice_type == AP4_HEVC_SLICE_TYPE_B) { + unsigned int luma_weight_l1_flag[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + for (unsigned int i=0; i<=num_ref_idx_l1_active_minus1; i++) { + luma_weight_l1_flag[i] = bits.ReadBit(); + } + unsigned int chroma_weight_l1_flag[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + if (sps->chroma_format_idc != 0) { + for (unsigned int i=0; i<=num_ref_idx_l1_active_minus1; i++) { + chroma_weight_l1_flag[i] = bits.ReadBit(); + } + } + for (unsigned int i=0; i<=num_ref_idx_l1_active_minus1; i++) { + if (luma_weight_l1_flag[i]) { + /* delta_luma_weight_l1[i] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + /* luma_offset_l1[i] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + } + if (chroma_weight_l1_flag[i]) { + for (unsigned int j=0; j<2; j++) { + /* delta_chroma_weight_l1[i][j] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + /* delta_chroma_offset_l1[i][j] = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + } + } + } + } + // --- pred_weight_table() + } + /* five_minus_max_num_merge_cand = */ ReadGolomb(bits); + } + /* slice_qp_delta = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + if (pps->pps_slice_chroma_qp_offsets_present_flag) { + /* slice_cb_qp_offset = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + /* slice_cr_qp_offset = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + } + unsigned int deblocking_filter_override_flag = 0; + if (pps->deblocking_filter_override_enabled_flag) { + deblocking_filter_override_flag = bits.ReadBit(); + } + if (deblocking_filter_override_flag) { + slice_deblocking_filter_disabled_flag = bits.ReadBit(); + if (!slice_deblocking_filter_disabled_flag) { + /* slice_beta_offset_div2 = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + /* slice_tc_offset_div2 = */ /*SignedGolomb(*/ ReadGolomb(bits) /*)*/; + } + } + if (pps->pps_loop_filter_across_slices_enabled_flag && + (slice_sao_luma_flag || slice_sao_chroma_flag || !slice_deblocking_filter_disabled_flag)) { + /* slice_loop_filter_across_slices_enabled_flag = */ bits.ReadBit(); + } } - if (sps->separate_colour_plane_flag) { - colour_plane_id = bits.ReadBits(2); + + if (pps->tiles_enabled_flag || pps->entropy_coding_sync_enabled_flag) { + num_entry_point_offsets = ReadGolomb(bits); + if (num_entry_point_offsets > 0 ) { + offset_len_minus1 = ReadGolomb(bits); + if (offset_len_minus1 > 31) { + return AP4_ERROR_INVALID_FORMAT; + } + for (unsigned int i=0; i<num_entry_point_offsets; i++) { + bits.ReadBits(offset_len_minus1+1); + } + } } - if (nal_unit_type != AP4_HEVC_NALU_TYPE_IDR_W_RADL && nal_unit_type != AP4_HEVC_NALU_TYPE_IDR_N_LP) { - slice_pic_order_cnt_lsb = bits.ReadBits(sps->log2_max_pic_order_cnt_lsb_minus4+4); - short_term_ref_pic_set_sps_flag = bits.ReadBit(); + + if (pps->slice_segment_header_extension_present_flag) { + unsigned int slice_segment_header_extension_length = ReadGolomb(bits); + for (unsigned int i=0; i<slice_segment_header_extension_length; i++) { + bits.ReadBits(8); // slice_segment_header_extension_data_byte[i] + } } - + + /* compute the size */ + size = bits.GetBitsRead(); + DBG_PRINTF_1("*** slice segment header size=%d bits\n", size); + return AP4_SUCCESS; } @@ -334,7 +604,38 @@ pps_seq_parameter_set_id(0), dependent_slice_segments_enabled_flag(0), output_flag_present_flag(0), - num_extra_slice_header_bits(0) + num_extra_slice_header_bits(0), + sign_data_hiding_enabled_flag(0), + cabac_init_present_flag(0), + num_ref_idx_l0_default_active_minus1(0), + num_ref_idx_l1_default_active_minus1(0), + init_qp_minus26(0), + constrained_intra_pred_flag(0), + transform_skip_enabled_flag(0), + cu_qp_delta_enabled_flag(0), + diff_cu_qp_delta_depth(0), + pps_cb_qp_offset(0), + pps_cr_qp_offset(0), + pps_slice_chroma_qp_offsets_present_flag(0), + weighted_pred_flag(0), + weighted_bipred_flag(0), + transquant_bypass_enabled_flag(0), + tiles_enabled_flag(0), + entropy_coding_sync_enabled_flag(0), + num_tile_columns_minus1(0), + num_tile_rows_minus1(0), + uniform_spacing_flag(1), + loop_filter_across_tiles_enabled_flag(0), + pps_loop_filter_across_slices_enabled_flag(0), + deblocking_filter_control_present_flag(0), + deblocking_filter_override_enabled_flag(0), + pps_deblocking_filter_disabled_flag(0), + pps_beta_offset_div2(0), + pps_tc_offset_div2(0), + pps_scaling_list_data_present_flag(0), + lists_modification_present_flag(0), + log2_parallel_merge_level_minus2(0), + slice_segment_header_extension_present_flag(0) { } @@ -360,10 +661,60 @@ if (pps_seq_parameter_set_id > AP4_HEVC_SPS_MAX_ID) { return AP4_ERROR_INVALID_FORMAT; } - dependent_slice_segments_enabled_flag = bits.ReadBit(); - output_flag_present_flag = bits.ReadBit(); - num_extra_slice_header_bits = bits.ReadBits(3); - + dependent_slice_segments_enabled_flag = bits.ReadBit(); + output_flag_present_flag = bits.ReadBit(); + num_extra_slice_header_bits = bits.ReadBits(3); + sign_data_hiding_enabled_flag = bits.ReadBit(); + cabac_init_present_flag = bits.ReadBit(); + num_ref_idx_l0_default_active_minus1 = ReadGolomb(bits); + num_ref_idx_l1_default_active_minus1 = ReadGolomb(bits); + init_qp_minus26 = SignedGolomb(ReadGolomb(bits)); + constrained_intra_pred_flag = bits.ReadBit(); + transform_skip_enabled_flag = bits.ReadBit(); + cu_qp_delta_enabled_flag = bits.ReadBit(); + if (cu_qp_delta_enabled_flag) { + diff_cu_qp_delta_depth = ReadGolomb(bits); + } + pps_cb_qp_offset = SignedGolomb(ReadGolomb(bits)); + pps_cr_qp_offset = SignedGolomb(ReadGolomb(bits)); + pps_slice_chroma_qp_offsets_present_flag = bits.ReadBit(); + weighted_pred_flag = bits.ReadBit(); + weighted_bipred_flag = bits.ReadBit(); + transquant_bypass_enabled_flag = bits.ReadBit(); + tiles_enabled_flag = bits.ReadBit(); + entropy_coding_sync_enabled_flag = bits.ReadBit(); + if (tiles_enabled_flag) { + num_tile_columns_minus1 = ReadGolomb(bits); + num_tile_rows_minus1 = ReadGolomb(bits); + uniform_spacing_flag = bits.ReadBit(); + if (!uniform_spacing_flag) { + for (unsigned int i=0; i<num_tile_columns_minus1; i++) { + ReadGolomb(bits); // column_width_minus1[i] + } + for (unsigned int i = 0; i < num_tile_rows_minus1; i++) { + ReadGolomb(bits); // row_height_minus1[i] + } + } + loop_filter_across_tiles_enabled_flag = bits.ReadBit(); + } + pps_loop_filter_across_slices_enabled_flag = bits.ReadBit(); + deblocking_filter_control_present_flag = bits.ReadBit(); + if (deblocking_filter_control_present_flag) { + deblocking_filter_override_enabled_flag = bits.ReadBit(); + pps_deblocking_filter_disabled_flag = bits.ReadBit(); + if (!pps_deblocking_filter_disabled_flag) { + pps_beta_offset_div2 = SignedGolomb(ReadGolomb(bits)); + pps_tc_offset_div2 = SignedGolomb(ReadGolomb(bits)); + } + } + pps_scaling_list_data_present_flag = bits.ReadBit(); + if (pps_scaling_list_data_present_flag) { + scaling_list_data(bits); + } + lists_modification_present_flag = bits.ReadBit(); + log2_parallel_merge_level_minus2 = ReadGolomb(bits); + slice_segment_header_extension_present_flag = bits.ReadBit(); + return AP4_SUCCESS; } @@ -404,7 +755,11 @@ log2_min_pcm_luma_coding_block_size_minus3(0), log2_diff_max_min_pcm_luma_coding_block_size(0), pcm_loop_filter_disabled_flag(0), - num_short_term_ref_pic_sets(0) + num_short_term_ref_pic_sets(0), + long_term_ref_pics_present_flag(0), + num_long_term_ref_pics_sps(0), + sps_temporal_mvp_enabled_flag(0), + strong_intra_smoothing_enabled_flag(0) { AP4_SetMemory(&profile_tier_level, 0, sizeof(profile_tier_level)); for (unsigned int i=0; i<8; i++) { @@ -476,7 +831,43 @@ log2_diff_max_min_transform_block_size = ReadGolomb(bits); max_transform_hierarchy_depth_inter = ReadGolomb(bits); max_transform_hierarchy_depth_intra = ReadGolomb(bits); - + scaling_list_enabled_flag = bits.ReadBit(); + if (scaling_list_enabled_flag) { + sps_scaling_list_data_present_flag = bits.ReadBit(); + if (sps_scaling_list_data_present_flag) { + scaling_list_data(bits); + } + } + amp_enabled_flag = bits.ReadBit(); + sample_adaptive_offset_enabled_flag = bits.ReadBit(); + pcm_enabled_flag = bits.ReadBit(); + if (pcm_enabled_flag) { + pcm_sample_bit_depth_luma_minus1 = bits.ReadBits(4); + pcm_sample_bit_depth_chroma_minus1 = bits.ReadBits(4); + log2_min_pcm_luma_coding_block_size_minus3 = ReadGolomb(bits); + log2_diff_max_min_pcm_luma_coding_block_size = ReadGolomb(bits); + pcm_loop_filter_disabled_flag = bits.ReadBit(); + } + num_short_term_ref_pic_sets = ReadGolomb(bits); + if (num_short_term_ref_pic_sets > 64) { + return AP4_ERROR_INVALID_FORMAT; + } + for (unsigned int i=0; i<num_short_term_ref_pic_sets; i++) { + short_term_ref_pic_set rps; + AP4_Result result = parse_short_term_ref_pic_set(&rps, i, num_short_term_ref_pic_sets, bits); + if (AP4_FAILED(result)) return result; + } + long_term_ref_pics_present_flag = bits.ReadBit(); + if (long_term_ref_pics_present_flag) { + num_long_term_ref_pics_sps = ReadGolomb(bits); + for (unsigned int i=0; i<num_long_term_ref_pics_sps; i++) { + /* lt_ref_pic_poc_lsb_sps[i] = */ bits.ReadBits(log2_max_pic_order_cnt_lsb_minus4 + 4); + /* used_by_curr_pic_lt_sps_flag[i] = */ bits.ReadBit(); + } + } + sps_temporal_mvp_enabled_flag = bits.ReadBit(); + strong_intra_smoothing_enabled_flag = bits.ReadBit(); + return AP4_SUCCESS; } @@ -701,20 +1092,41 @@ { const AP4_DataBuffer* nal_unit = NULL; - // default return values - access_unit_info.Reset(); - // feed the NAL unit parser AP4_Result result = m_NalParser.Feed(data, data_size, bytes_consumed, nal_unit, eos); if (AP4_FAILED(result)) { return result; } - if (nal_unit && nal_unit->GetDataSize()) { - const unsigned char* nal_unit_payload = (const unsigned char*)nal_unit->GetData(); - unsigned int nal_unit_size = nal_unit->GetDataSize(); - unsigned int nal_unit_type = (nal_unit_payload[0] >> 1) & 0x3F; - unsigned int nuh_layer_id = (((nal_unit_payload[0] & 1) << 5) | (nal_unit_payload[1] >> 3)); - unsigned int nuh_temporal_id = nal_unit_payload[1] & 0x7; + + if (bytes_consumed < data_size) { + // there will be more to parse + eos = false; + } + + return Feed(nal_unit ? nal_unit->GetData() : NULL, + nal_unit ? nal_unit->GetDataSize() : 0, + access_unit_info, + eos); +} + +/*---------------------------------------------------------------------- +| AP4_HevcFrameParser::Feed ++---------------------------------------------------------------------*/ +AP4_Result +AP4_HevcFrameParser::Feed(const AP4_UI08* nal_unit, + AP4_Size nal_unit_size, + AccessUnitInfo& access_unit_info, + bool last_unit) +{ + AP4_Result result; + + // default return values + access_unit_info.Reset(); + + if (nal_unit && nal_unit_size >= 2) { + unsigned int nal_unit_type = (nal_unit[0] >> 1) & 0x3F; + unsigned int nuh_layer_id = (((nal_unit[0] & 1) << 5) | (nal_unit[1] >> 3)); + unsigned int nuh_temporal_id = nal_unit[1] & 0x7; if (nuh_temporal_id-- == 0) { // illegal value, ignore this NAL unit @@ -737,20 +1149,21 @@ if (nal_unit_type < AP4_HEVC_NALU_TYPE_VPS_NUT) { // this is a VCL NAL Unit AP4_HevcSliceSegmentHeader* slice_header = new AP4_HevcSliceSegmentHeader; - result = slice_header->Parse(nal_unit_payload, nal_unit_size, nal_unit_type, &m_PPS[0], &m_SPS[0]); + result = slice_header->Parse(nal_unit+2, nal_unit_size-2, nal_unit_type, &m_PPS[0], &m_SPS[0]); if (AP4_FAILED(result)) { - DBG_PRINTF_1("VLC parsing failed (%d)", result); + DBG_PRINTF_1("VCL parsing failed (%d)", result); return AP4_ERROR_INVALID_FORMAT; } #if defined(AP4_HEVC_PARSER_ENABLE_DEBUG) const char* slice_type_name = AP4_HevcNalParser::SliceTypeName(slice_header->slice_type); if (slice_type_name == NULL) slice_type_name = "?"; - DBG_PRINTF_4(" pps_id=%d, first=%s, slice_type=%d (%s), ", + DBG_PRINTF_5(" pps_id=%d, first=%s, slice_type=%d (%s), size=%d, ", slice_header->slice_pic_parameter_set_id, slice_header->first_slice_segment_in_pic_flag?"YES":"NO", slice_header->slice_type, - slice_type_name); + slice_type_name, + slice_header->size); #endif if (slice_header->first_slice_segment_in_pic_flag) { CheckIfAccessUnitIsCompleted(access_unit_info); @@ -783,10 +1196,10 @@ } // buffer this NAL unit - AppendNalUnitData(nal_unit_payload, nal_unit_size); + AppendNalUnitData(nal_unit, nal_unit_size); ++m_VclNalUnitsInAccessUnit; } else if (nal_unit_type == AP4_HEVC_NALU_TYPE_AUD_NUT) { - unsigned int pic_type = (nal_unit_payload[1]>>5); + unsigned int pic_type = (nal_unit[1]>>5); const char* pic_type_name = AP4_HevcNalParser::PicTypeName(pic_type); if (pic_type_name == NULL) pic_type_name = "UNKNOWN"; DBG_PRINTF_2("[%d:%s]\n", pic_type, pic_type_name); @@ -794,7 +1207,7 @@ CheckIfAccessUnitIsCompleted(access_unit_info); } else if (nal_unit_type == AP4_HEVC_NALU_TYPE_PPS_NUT) { AP4_HevcPictureParameterSet* pps = new AP4_HevcPictureParameterSet; - result = pps->Parse(nal_unit_payload, nal_unit_size); + result = pps->Parse(nal_unit, nal_unit_size); if (AP4_FAILED(result)) { DBG_PRINTF_0("PPS ERROR!!!"); delete pps; @@ -805,11 +1218,11 @@ DBG_PRINTF_2("PPS pps_id=%d, sps_id=%d", pps->pps_pic_parameter_set_id, pps->pps_seq_parameter_set_id); // keep the PPS with the NAL unit (this is optional) - AppendNalUnitData(nal_unit_payload, nal_unit_size); + AppendNalUnitData(nal_unit, nal_unit_size); CheckIfAccessUnitIsCompleted(access_unit_info); } else if (nal_unit_type == AP4_HEVC_NALU_TYPE_SPS_NUT) { AP4_HevcSequenceParameterSet* sps = new AP4_HevcSequenceParameterSet; - result = sps->Parse(nal_unit_payload, nal_unit_size); + result = sps->Parse(nal_unit, nal_unit_size); if (AP4_FAILED(result)) { DBG_PRINTF_0("SPS ERROR!!!\n"); delete sps; @@ -820,11 +1233,11 @@ DBG_PRINTF_2("SPS sps_id=%d, vps_id=%d", sps->sps_seq_parameter_set_id, sps->sps_video_parameter_set_id); // keep the SPS with the NAL unit (this is optional) - AppendNalUnitData(nal_unit_payload, nal_unit_size); + AppendNalUnitData(nal_unit, nal_unit_size); CheckIfAccessUnitIsCompleted(access_unit_info); } else if (nal_unit_type == AP4_HEVC_NALU_TYPE_VPS_NUT) { AP4_HevcVideoParameterSet* vps = new AP4_HevcVideoParameterSet; - result = vps->Parse(nal_unit_payload, nal_unit_size); + result = vps->Parse(nal_unit, nal_unit_size); if (AP4_FAILED(result)) { DBG_PRINTF_0("VPS ERROR!!!\n"); delete vps; @@ -835,23 +1248,23 @@ DBG_PRINTF_1("VPS vps_id=%d", vps->vps_video_parameter_set_id); // keep the VPS with the NAL unit (this is optional) - AppendNalUnitData(nal_unit_payload, nal_unit_size); + AppendNalUnitData(nal_unit, nal_unit_size); CheckIfAccessUnitIsCompleted(access_unit_info); } else if (nal_unit_type == AP4_HEVC_NALU_TYPE_EOS_NUT || nal_unit_type == AP4_HEVC_NALU_TYPE_EOB_NUT) { CheckIfAccessUnitIsCompleted(access_unit_info); } else if (nal_unit_type == AP4_HEVC_NALU_TYPE_PREFIX_SEI_NUT) { CheckIfAccessUnitIsCompleted(access_unit_info); - AppendNalUnitData(nal_unit_payload, nal_unit_size); + AppendNalUnitData(nal_unit, nal_unit_size); } else if (nal_unit_type == AP4_HEVC_NALU_TYPE_SUFFIX_SEI_NUT){ - AppendNalUnitData(nal_unit_payload, nal_unit_size); + AppendNalUnitData(nal_unit, nal_unit_size); } DBG_PRINTF_0("\n"); m_TotalNalUnitCount++; } // flush if needed - if (eos && bytes_consumed == data_size && access_unit_info.nal_units.ItemCount() == 0) { + if (last_unit && access_unit_info.nal_units.ItemCount() == 0) { DBG_PRINTF_0("------ last unit\n"); CheckIfAccessUnitIsCompleted(access_unit_info); } @@ -862,6 +1275,18 @@ /*---------------------------------------------------------------------- | AP4_HevFrameParser::AccessUnitInfo::Reset +---------------------------------------------------------------------*/ +AP4_Result +AP4_HevcFrameParser::ParseSliceSegmentHeader(const AP4_UI08* data, + unsigned int data_size, + unsigned int nal_unit_type, + AP4_HevcSliceSegmentHeader& slice_header) +{ + return slice_header.Parse(data, data_size, nal_unit_type, &m_PPS[0], &m_SPS[0]); +} + +/*---------------------------------------------------------------------- +| AP4_HevFrameParser::AccessUnitInfo::Reset ++---------------------------------------------------------------------*/ void AP4_HevcFrameParser::AccessUnitInfo::Reset() {
View file
bento4-1.5.0r619.tar.gz/Source/C++/Codecs/Ap4HevcParser.h -> bento4-1.5.1r620.tar.gz/Source/C++/Codecs/Ap4HevcParser.h
Changed
@@ -102,6 +102,10 @@ const unsigned int AP4_HEVC_ACCESS_UNIT_FLAG_IS_RASL = 0x10; const unsigned int AP4_HEVC_ACCESS_UNIT_FLAG_IS_SUBLAYER_NON_REF = 0x20; +const unsigned int AP4_HEVC_SLICE_TYPE_B = 0; +const unsigned int AP4_HEVC_SLICE_TYPE_P = 1; +const unsigned int AP4_HEVC_SLICE_TYPE_I = 2; + /*---------------------------------------------------------------------- | class references +---------------------------------------------------------------------*/ @@ -160,6 +164,37 @@ unsigned int dependent_slice_segments_enabled_flag; unsigned int output_flag_present_flag; unsigned int num_extra_slice_header_bits; + unsigned int sign_data_hiding_enabled_flag; + unsigned int cabac_init_present_flag; + unsigned int num_ref_idx_l0_default_active_minus1; + unsigned int num_ref_idx_l1_default_active_minus1; + int init_qp_minus26; + unsigned int constrained_intra_pred_flag; + unsigned int transform_skip_enabled_flag; + unsigned int cu_qp_delta_enabled_flag; + unsigned int diff_cu_qp_delta_depth; + int pps_cb_qp_offset; + int pps_cr_qp_offset; + unsigned int pps_slice_chroma_qp_offsets_present_flag; + unsigned int weighted_pred_flag; + unsigned int weighted_bipred_flag; + unsigned int transquant_bypass_enabled_flag; + unsigned int tiles_enabled_flag; + unsigned int entropy_coding_sync_enabled_flag; + unsigned int num_tile_columns_minus1; + unsigned int num_tile_rows_minus1; + unsigned int uniform_spacing_flag; + unsigned int loop_filter_across_tiles_enabled_flag; + unsigned int pps_loop_filter_across_slices_enabled_flag; + unsigned int deblocking_filter_control_present_flag; + unsigned int deblocking_filter_override_enabled_flag; + unsigned int pps_deblocking_filter_disabled_flag; + int pps_beta_offset_div2; + int pps_tc_offset_div2; + unsigned int pps_scaling_list_data_present_flag; + unsigned int lists_modification_present_flag; + unsigned int log2_parallel_merge_level_minus2; + unsigned int slice_segment_header_extension_present_flag; }; /*---------------------------------------------------------------------- @@ -212,6 +247,10 @@ unsigned int log2_diff_max_min_pcm_luma_coding_block_size; unsigned int pcm_loop_filter_disabled_flag; unsigned int num_short_term_ref_pic_sets; + unsigned int long_term_ref_pics_present_flag; + unsigned int num_long_term_ref_pics_sps; + unsigned int sps_temporal_mvp_enabled_flag; + unsigned int strong_intra_smoothing_enabled_flag; }; /*---------------------------------------------------------------------- @@ -243,6 +282,35 @@ }; /*---------------------------------------------------------------------- +| AP4_HevcSliceSegmentHeader ++---------------------------------------------------------------------*/ +struct AP4_HevcSliceSegmentHeader { + AP4_HevcSliceSegmentHeader() {} // leave members uninitialized on purpose + + AP4_Result Parse(const AP4_UI08* data, + unsigned int data_size, + unsigned int nal_unit_type, + AP4_HevcPictureParameterSet** picture_parameter_sets, + AP4_HevcSequenceParameterSet** sequence_parameter_sets); + + unsigned int size; // size of the parsed data + + unsigned int first_slice_segment_in_pic_flag; + unsigned int no_output_of_prior_pics_flag; + unsigned int slice_pic_parameter_set_id; + unsigned int dependent_slice_segment_flag; + unsigned int slice_segment_address; + unsigned int slice_type; + unsigned int pic_output_flag; + unsigned int colour_plane_id; + unsigned int slice_pic_order_cnt_lsb; + unsigned int short_term_ref_pic_set_sps_flag; + unsigned int short_term_ref_pic_set_idx; + unsigned int num_entry_point_offsets; + unsigned int offset_len_minus1; +}; + +/*---------------------------------------------------------------------- | AP4_HevcNalParser +---------------------------------------------------------------------*/ class AP4_HevcNalParser : public AP4_NalParser { @@ -276,16 +344,16 @@ /** * Feed some data to the parser and look for the next NAL Unit. * - * @param data: Pointer to the memory buffer with the data to feed. - * @param data_size: Size in bytes of the buffer pointed to by the + * @param data Pointer to the memory buffer with the data to feed. + * @param data_size Size in bytes of the buffer pointed to by the * data pointer. - * @param bytes_consumed: Number of bytes from the data buffer that were + * @param bytes_consumed Number of bytes from the data buffer that were * consumed and stored by the parser. - * @param access_unit_info: Reference to a AccessUnitInfo structure that will + * @param access_unit_info Reference to a AccessUnitInfo structure that will * contain information about any access unit found in the data. If no * access unit was found, the nal_units field of this structure will be an * empty array. - * @param eos: Boolean flag that indicates if this buffer is the last + * @param eos Boolean flag that indicates if this buffer is the last * buffer in the stream/file (End Of Stream). * * @result: AP4_SUCCESS is the call succeeds, or an error code if it @@ -310,6 +378,16 @@ AccessUnitInfo& access_unit_info, bool eos=false); + AP4_Result Feed(const AP4_UI08* nal_unit, + AP4_Size nal_unit_size, + AccessUnitInfo& access_unit_info, + bool last_unit=false); + + AP4_Result ParseSliceSegmentHeader(const AP4_UI08* data, + unsigned int data_size, + unsigned int nal_unit_type, + AP4_HevcSliceSegmentHeader& slice_header); + AP4_HevcVideoParameterSet** GetVideoParameterSets() { return &m_VPS[0]; } AP4_HevcSequenceParameterSet** GetSequenceParameterSets() { return &m_SPS[0]; } AP4_HevcPictureParameterSet** GetPictureParameterSets() { return &m_PPS[0]; }
View file
bento4-1.5.0r619.tar.gz/Source/C++/Codecs/Ap4NalParser.h -> bento4-1.5.1r620.tar.gz/Source/C++/Codecs/Ap4NalParser.h
Changed
@@ -49,15 +49,15 @@ /** * Feed some data to the parser and look for the next NAL Unit. * - * @param data: Pointer to the memory buffer with the data to feed. - * @param data_size: Size in bytes of the buffer pointed to by the + * @param data Pointer to the memory buffer with the data to feed. + * @param data_size Size in bytes of the buffer pointed to by the * data pointer. - * @param bytes_consumed: Number of bytes from the data buffer that were + * @param bytes_consumed Number of bytes from the data buffer that were * consumed and stored by the parser. - * @param nalu: Reference to a pointer to a buffer object that contains + * @param nalu Reference to a pointer to a buffer object that contains * a NAL unit found in the previously fed data, or a NULL pointer if no * NAL unit can be found so far. - * @param eos: Boolean flag that indicates if this buffer is the last + * @param eos Boolean flag that indicates if this buffer is the last * buffer in the stream/file (End Of Stream). * * @result: AP4_SUCCESS is the call succeeds, or an error code if it
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4CommonEncryption.cpp -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4CommonEncryption.cpp
Changed
@@ -217,7 +217,8 @@ +---------------------------------------------------------------------*/ AP4_CencCbcsSubSampleMapper::AP4_CencCbcsSubSampleMapper(AP4_Size nalu_length_size, AP4_UI32 format, AP4_TrakAtom* trak) : AP4_CencSubSampleMapper(nalu_length_size, format), - m_AvcParser(NULL) + m_AvcParser(NULL), + m_HevcParser(NULL) { if (!trak) return; @@ -225,26 +226,49 @@ AP4_StsdAtom* stsd = AP4_DYNAMIC_CAST(AP4_StsdAtom, trak->FindChild("mdia/minf/stbl/stsd")); if (!stsd) return; - // create the parser - m_AvcParser = new AP4_AvcFrameParser(); - - // look for an avc sample description - AP4_AvccAtom* avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, stsd->FindChild("avc1/avcC")); - if (!avcc) avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, stsd->FindChild("avc2/avcC")); - if (!avcc) avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, stsd->FindChild("avc3/avcC")); - if (!avcc) avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, stsd->FindChild("avc4/avcC")); - if (!avcc) return; - - // parse the sps and pps if we have them - AP4_Array<AP4_DataBuffer>& sps_list = avcc->GetSequenceParameters(); - for (unsigned int i=0; i<sps_list.ItemCount(); i++) { - AP4_DataBuffer& sps = sps_list[i]; - ParseAvcData(sps.GetData(), sps.GetDataSize()); - } - AP4_Array<AP4_DataBuffer>& pps_list = avcc->GetPictureParameters(); - for (unsigned int i=0; i<pps_list.ItemCount(); i++) { - AP4_DataBuffer& pps = pps_list[i]; - ParseAvcData(pps.GetData(), pps.GetDataSize()); + if (format == AP4_SAMPLE_FORMAT_AVC1 || + format == AP4_SAMPLE_FORMAT_AVC2 || + format == AP4_SAMPLE_FORMAT_AVC3 || + format == AP4_SAMPLE_FORMAT_AVC4) { + // create the parser + m_AvcParser = new AP4_AvcFrameParser(); + + // look for an avc sample description + AP4_AvccAtom* avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, stsd->FindChild("avc1/avcC")); + if (!avcc) avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, stsd->FindChild("avc2/avcC")); + if (!avcc) avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, stsd->FindChild("avc3/avcC")); + if (!avcc) avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, stsd->FindChild("avc4/avcC")); + if (!avcc) return; + + // parse the sps and pps if we have them + AP4_Array<AP4_DataBuffer>& sps_list = avcc->GetSequenceParameters(); + for (unsigned int i=0; i<sps_list.ItemCount(); i++) { + AP4_DataBuffer& sps = sps_list[i]; + ParseAvcData(sps.GetData(), sps.GetDataSize()); + } + AP4_Array<AP4_DataBuffer>& pps_list = avcc->GetPictureParameters(); + for (unsigned int i=0; i<pps_list.ItemCount(); i++) { + AP4_DataBuffer& pps = pps_list[i]; + ParseAvcData(pps.GetData(), pps.GetDataSize()); + } + } else if (format == AP4_SAMPLE_FORMAT_HEV1 || + format == AP4_SAMPLE_FORMAT_HVC1) { + // create the parser + m_HevcParser = new AP4_HevcFrameParser(); + + // look for an hevc sample description + AP4_HvccAtom* hvcc = AP4_DYNAMIC_CAST(AP4_HvccAtom, stsd->FindChild("hvc1/hvcC")); + if (!hvcc) hvcc = AP4_DYNAMIC_CAST(AP4_HvccAtom, stsd->FindChild("hev1/hvcC")); + if (!hvcc) return; + + // parse the vps, sps and pps if we have them + const AP4_Array<AP4_HvccAtom::Sequence>& sequence_list = hvcc->GetSequences(); + for (unsigned int i=0; i<sequence_list.ItemCount(); i++) { + const AP4_Array<AP4_DataBuffer>& nalus = sequence_list[i].m_Nalus; + for (unsigned int j=0; j<nalus.ItemCount(); j++) { + ParseHevcData(nalus[j].GetData(), nalus[j].GetDataSize()); + } + } } } @@ -275,6 +299,24 @@ } /*---------------------------------------------------------------------- +| AP4_CencCbcsSubSampleMapper::ParseHevcData ++---------------------------------------------------------------------*/ +AP4_Result +AP4_CencCbcsSubSampleMapper::ParseHevcData(const AP4_UI08* data, AP4_Size data_size) +{ + if (!m_HevcParser) return AP4_ERROR_INVALID_PARAMETERS; + + AP4_HevcFrameParser::AccessUnitInfo access_unit_info; + AP4_Result result = m_HevcParser->Feed(data, data_size, access_unit_info); + if (AP4_FAILED(result)) return result; + + // cleanup + access_unit_info.Reset(); + + return AP4_SUCCESS; +} + +/*---------------------------------------------------------------------- | AP4_CencCbcsSubSampleMapper::GetSubSampleMap +---------------------------------------------------------------------*/ AP4_Result @@ -313,29 +355,87 @@ // skip encryption if the NAL unit should be left unencrypted for this specific format/type bool skip = false; - const AP4_UI08* nalu_data = &in[m_NaluLengthSize]; - unsigned int nalu_type = nalu_data[0] & 0x1F; if (m_Format == AP4_SAMPLE_FORMAT_AVC1 || m_Format == AP4_SAMPLE_FORMAT_AVC2 || m_Format == AP4_SAMPLE_FORMAT_AVC3 || m_Format == AP4_SAMPLE_FORMAT_AVC4) { - if (nalu_type != AP4_AVC_NAL_UNIT_TYPE_CODED_SLICE_OF_NON_IDR_PICTURE && - nalu_type != AP4_AVC_NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_A && - nalu_type != AP4_AVC_NAL_UNIT_TYPE_CODED_SLICE_OF_IDR_PICTURE) { + const AP4_UI08* nalu_data = &in[m_NaluLengthSize]; + unsigned int nalu_type = nalu_data[0] & 0x1F; + + if (nalu_type == AP4_AVC_NAL_UNIT_TYPE_CODED_SLICE_OF_NON_IDR_PICTURE || + nalu_type == AP4_AVC_NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_A || + nalu_type == AP4_AVC_NAL_UNIT_TYPE_CODED_SLICE_OF_IDR_PICTURE) { + // parse the NAL unit to get the slice header size + if (m_AvcParser == NULL) return AP4_ERROR_INTERNAL; + AP4_AvcSliceHeader slice_header; + unsigned int nalu_ref_idc = (nalu_data[0]>>5)&3; + AP4_Result result = m_AvcParser->ParseSliceHeader(&nalu_data[1], + nalu_length-1, + nalu_type, + nalu_ref_idc, + slice_header); + if (AP4_FAILED(result)) { + return result; + } + + // leave the slice header in the clear, including the NAL type + unsigned int cleartext_size = m_NaluLengthSize+1+(slice_header.size+7)/8; + unsigned int encrypted_size = nalu_size-cleartext_size; + + bytes_of_cleartext_data.Append(cleartext_size); + bytes_of_encrypted_data.Append(encrypted_size); + } else { // this NAL unit does not have a slice header skip = true; + + // parse SPS and PPS NAL units + if (nalu_type == AP4_AVC_NAL_UNIT_TYPE_SPS || + nalu_type == AP4_AVC_NAL_UNIT_TYPE_PPS) { + AP4_Result result = ParseAvcData(nalu_data, nalu_length); + if (AP4_FAILED(result)) { + return result; + } + } } + } else if (m_Format == AP4_SAMPLE_FORMAT_HEV1 || + m_Format == AP4_SAMPLE_FORMAT_HVC1) { + const AP4_UI08* nalu_data = &in[m_NaluLengthSize]; + unsigned int nalu_type = (nalu_data[0] >> 1) & 0x3F; - // parse SPS and PPS NAL units - if (nalu_type == AP4_AVC_NAL_UNIT_TYPE_SPS || - nalu_type == AP4_AVC_NAL_UNIT_TYPE_PPS) { - AP4_Result result = ParseAvcData(nalu_data, nalu_length); + if (nalu_type < AP4_HEVC_NALU_TYPE_VPS_NUT) { + // this is a VCL NAL Unit + if (m_HevcParser == NULL) return AP4_ERROR_INTERNAL; + AP4_HevcSliceSegmentHeader slice_header; + AP4_Result result = m_HevcParser->ParseSliceSegmentHeader(&nalu_data[2], nalu_length-2, nalu_type, slice_header); if (AP4_FAILED(result)) { return result; } + + // leave the slice header in the clear, including the NAL type + //unsigned int cleartext_size = m_NaluLengthSize+2+(slice_header.size+7)/8; + // HACK: add one byte when the slice header is a multiple of 8 bits, to match what Apple is doing + unsigned int header_size = 1+(slice_header.size/8); + unsigned int cleartext_size = m_NaluLengthSize+2+header_size; + // + unsigned int encrypted_size = nalu_size-cleartext_size; + + bytes_of_cleartext_data.Append(cleartext_size); + bytes_of_encrypted_data.Append(encrypted_size); + } else { + skip = true; + + // parse VPS, SPS and PPS NAL units + if (nalu_type == AP4_HEVC_NALU_TYPE_VPS_NUT || + nalu_type == AP4_HEVC_NALU_TYPE_SPS_NUT || + nalu_type == AP4_HEVC_NALU_TYPE_PPS_NUT) { + AP4_Result result = ParseHevcData(nalu_data, nalu_length); + if (AP4_FAILED(result)) { + return result; + } + } } } else { - // non-AVC formats not supported here yet + // only AVC and HEVC elementary streams are supported. return AP4_ERROR_NOT_SUPPORTED; } @@ -348,28 +448,8 @@ bytes_of_encrypted_data.Append(0); range -= cleartext_size; } - } else { - // parse the NAL unit to get the slice header size - if (m_AvcParser == NULL) return AP4_ERROR_INTERNAL; - AP4_AvcSliceHeader slice_header; - unsigned int nalu_ref_idc = (nalu_data[0]>>5)&3; - AP4_Result result = m_AvcParser->ParseSliceHeader(&nalu_data[1], - nalu_length-1, - nalu_type, - nalu_ref_idc, - slice_header); - if (AP4_FAILED(result)) { - return result; - } - - // leave the slice header in the clear, including the NAL type - unsigned int cleartext_size = m_NaluLengthSize+1+(slice_header.size+7)/8; - unsigned int encrypted_size = nalu_size-cleartext_size; - - bytes_of_cleartext_data.Append(cleartext_size); - bytes_of_encrypted_data.Append(encrypted_size); } - + // move the pointers in += nalu_size; } @@ -1378,7 +1458,7 @@ cipher_mode = AP4_BlockCipher::CTR; cipher_ctr_params.counter_size = 8; cipher_mode_params = &cipher_ctr_params; - + cipher_iv_size = 8; track_encrypter = new AP4_CencTrackEncrypter(m_Variant, 1, cipher_iv_size, @@ -1391,6 +1471,20 @@ enc_format); break; + case AP4_CENC_VARIANT_PIFF_CBC: + cipher_mode = AP4_BlockCipher::CBC; + track_encrypter = new AP4_CencTrackEncrypter(m_Variant, + 2, + cipher_iv_size, + kid, + 0, + NULL, + 0, + 0, + entries, + enc_format); + break; + case AP4_CENC_VARIANT_MPEG_CENC: cipher_mode = AP4_BlockCipher::CTR; cipher_ctr_params.counter_size = 8; @@ -1436,20 +1530,6 @@ enc_format); break; - case AP4_CENC_VARIANT_PIFF_CBC: - cipher_mode = AP4_BlockCipher::CBC; - track_encrypter = new AP4_CencTrackEncrypter(m_Variant, - 2, - cipher_iv_size, - kid, - 0, - NULL, - 0, - 0, - entries, - enc_format); - break; - case AP4_CENC_VARIANT_MPEG_CBC1: cipher_mode = AP4_BlockCipher::CBC; track_encrypter = new AP4_CencTrackEncrypter(m_Variant,
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4CommonEncryption.h -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4CommonEncryption.h
Changed
@@ -47,6 +47,7 @@ class AP4_SaioAtom; class AP4_CencSampleInfoTable; class AP4_AvcFrameParser; +class AP4_HevcFrameParser; /*---------------------------------------------------------------------- | constants @@ -497,10 +498,12 @@ private: // members - AP4_AvcFrameParser* m_AvcParser; + AP4_AvcFrameParser* m_AvcParser; + AP4_HevcFrameParser* m_HevcParser; // methods AP4_Result ParseAvcData(const AP4_UI08* data, AP4_Size data_size); + AP4_Result ParseHevcData(const AP4_UI08* data, AP4_Size data_size); }; /*----------------------------------------------------------------------
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4File.h -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4File.h
Changed
@@ -93,7 +93,7 @@ /** * Constructs an AP4_File from a stream * @param stream the stream containing the data of the file - * @param factory the atom factory that will be used to parse the stream + * @param atom_factory the atom factory that will be used to parse the stream * @param moov_only indicates whether parsing of the atoms should stop * when the moov atom is found or if all atoms should be parsed until the * end of the file.
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4HvccAtom.cpp -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4HvccAtom.cpp
Changed
@@ -178,8 +178,11 @@ AP4_UI08 temporal_id_nested, AP4_UI08 nalu_length_size, const AP4_Array<AP4_DataBuffer>& video_parameters, + AP4_UI08 video_parameters_completeness, const AP4_Array<AP4_DataBuffer>& sequence_parameters, - const AP4_Array<AP4_DataBuffer>& picture_parameters) : + AP4_UI08 sequence_parameters_completeness, + const AP4_Array<AP4_DataBuffer>& picture_parameters, + AP4_UI08 picture_parameters_completeness) : AP4_Atom(AP4_ATOM_TYPE_HVCC, AP4_ATOM_HEADER_SIZE), m_ConfigurationVersion(1), m_GeneralProfileSpace(general_profile_space), @@ -207,7 +210,7 @@ // deep copy of the parameters AP4_HvccAtom::Sequence vps_sequence; vps_sequence.m_NaluType = AP4_HEVC_NALU_TYPE_VPS_NUT; - vps_sequence.m_ArrayCompleteness = 0; + vps_sequence.m_ArrayCompleteness = video_parameters_completeness; for (unsigned int i=0; i<video_parameters.ItemCount(); i++) { vps_sequence.m_Nalus.Append(video_parameters[i]); } @@ -217,7 +220,7 @@ AP4_HvccAtom::Sequence sps_sequence; sps_sequence.m_NaluType = AP4_HEVC_NALU_TYPE_SPS_NUT; - sps_sequence.m_ArrayCompleteness = 0; + sps_sequence.m_ArrayCompleteness = sequence_parameters_completeness; for (unsigned int i=0; i<sequence_parameters.ItemCount(); i++) { sps_sequence.m_Nalus.Append(sequence_parameters[i]); } @@ -227,7 +230,7 @@ AP4_HvccAtom::Sequence pps_sequence; pps_sequence.m_NaluType = AP4_HEVC_NALU_TYPE_PPS_NUT; - pps_sequence.m_ArrayCompleteness = 0; + pps_sequence.m_ArrayCompleteness = picture_parameters_completeness; for (unsigned int i=0; i<picture_parameters.ItemCount(); i++) { pps_sequence.m_Nalus.Append(picture_parameters[i]); }
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4HvccAtom.h -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4HvccAtom.h
Changed
@@ -90,8 +90,11 @@ AP4_UI08 temporal_id_nested, AP4_UI08 nalu_length_size, const AP4_Array<AP4_DataBuffer>& video_parameters, + AP4_UI08 video_parameters_completeness, const AP4_Array<AP4_DataBuffer>& sequence_parameters, - const AP4_Array<AP4_DataBuffer>& picture_parameters); + AP4_UI08 sequence_parameters_completeness, + const AP4_Array<AP4_DataBuffer>& picture_parameters, + AP4_UI08 picture_parameters_completeness); // methods virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4OdheAtom.h -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4OdheAtom.h
Changed
@@ -57,7 +57,7 @@ // constructor /** - * @param: ohdr ohdr atom passed with transfer of ownership semantics + * @param ohdr ohdr atom passed with transfer of ownership semantics */ AP4_OdheAtom(const char* content_type, AP4_OhdrAtom* ohdr);
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4OmaDcf.cpp -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4OmaDcf.cpp
Changed
@@ -351,6 +351,8 @@ if (odaf) { if (odaf->GetIvLength() > AP4_CIPHER_BLOCK_SIZE) return AP4_ERROR_INVALID_FORMAT; if (odaf->GetKeyIndicatorLength() != 0) return AP4_ERROR_INVALID_FORMAT; + } else { + return AP4_ERROR_INVALID_FORMAT; } // check the scheme details and create the cipher
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4SampleDescription.cpp -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4SampleDescription.cpp
Changed
@@ -465,8 +465,11 @@ AP4_UI08 temporal_id_nested, AP4_UI08 nalu_length_size, const AP4_Array<AP4_DataBuffer>& video_parameters, + AP4_UI08 video_parameters_completeness, const AP4_Array<AP4_DataBuffer>& sequence_parameters, - const AP4_Array<AP4_DataBuffer>& picture_parameters) : + AP4_UI08 sequence_parameters_completeness, + const AP4_Array<AP4_DataBuffer>& picture_parameters, + AP4_UI08 picture_parameters_completeness) : AP4_SampleDescription(TYPE_HEVC, format, NULL), AP4_VideoSampleDescription(width, height, depth, compressor_name) { @@ -487,8 +490,11 @@ temporal_id_nested, nalu_length_size, video_parameters, + video_parameters_completeness, sequence_parameters, - picture_parameters); + sequence_parameters_completeness, + picture_parameters, + picture_parameters_completeness); m_Details.AddChild(m_HvccAtom); } @@ -506,7 +512,7 @@ bits >>= 1; count--; } - return reverse_bits << count; + return (count < 32) ? (reverse_bits << count) : 0; } /*----------------------------------------------------------------------
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4SampleDescription.h -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4SampleDescription.h
Changed
@@ -374,9 +374,12 @@ AP4_UI08 temporal_id_nested, AP4_UI08 nalu_length_size, const AP4_Array<AP4_DataBuffer>& video_parameters, + AP4_UI08 video_parameters_completeness, const AP4_Array<AP4_DataBuffer>& sequence_parameters, - const AP4_Array<AP4_DataBuffer>& picture_parameters); - + AP4_UI08 sequence_parameters_completeness, + const AP4_Array<AP4_DataBuffer>& picture_parameters, + AP4_UI08 picture_parameters_completeness); + // accessors AP4_UI08 GetConfigurationVersion() const { return m_HvccAtom->GetConfigurationVersion(); } AP4_UI08 GetGeneralProfileSpace() const { return m_HvccAtom->GetGeneralProfileSpace(); }
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4Utils.cpp -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4Utils.cpp
Changed
@@ -440,6 +440,7 @@ AP4_UI32 AP4_BitReader::ReadBits(unsigned int n) { + if (n == 0) return 0; AP4_BitReader::BitsWord result; if (m_BitsCached >= n) { /* we have enough bits in the cache to satisfy the request */
View file
bento4-1.5.0r619.tar.gz/Source/C++/Core/Ap4Version.h -> bento4-1.5.1r620.tar.gz/Source/C++/Core/Ap4Version.h
Changed
@@ -37,7 +37,7 @@ /** * Version number of the SDK */ -#define AP4_VERSION 0x01050002 -#define AP4_VERSION_STRING "1.5.0.2" +#define AP4_VERSION 0x01050100 +#define AP4_VERSION_STRING "1.5.1.0" #endif // _AP4_VERSION_H_
View file
bento4-1.5.0r619.tar.gz/Source/Python/utils/mp4-dash.py -> bento4-1.5.1r620.tar.gz/Source/Python/utils/mp4-dash.py
Changed
@@ -28,7 +28,7 @@ # setup main options VERSION = "1.8.0" -SDK_REVISION = '619' +SDK_REVISION = '620' SCRIPT_PATH = path.abspath(path.dirname(__file__)) sys.path += [SCRIPT_PATH]
View file
bento4-1.5.0r619.tar.gz/Source/Python/utils/mp4-hls.py -> bento4-1.5.1r620.tar.gz/Source/Python/utils/mp4-hls.py
Changed
@@ -27,7 +27,7 @@ # setup main options VERSION = "1.1.0" -SDK_REVISION = '619' +SDK_REVISION = '620' SCRIPT_PATH = path.abspath(path.dirname(__file__)) sys.path += [SCRIPT_PATH]
View file
bento4-1.5.0r619.tar.gz/Source/Python/utils/mp4utils.py -> bento4-1.5.1r620.tar.gz/Source/Python/utils/mp4utils.py
Changed
@@ -445,6 +445,8 @@ # compute the max segment bitrates if len(self.segment_bitrates) > 1: self.max_segment_bitrate = max(self.segment_bitrates[:-1]) + else: + self.max_segment_bitrate = self.average_segment_bitrate # compute the bandwidth if options.min_buffer_time == 0.0:
View file
bento4-1.5.0r619.tar.gz/Test/Bento4CryptoTester.py -> bento4-1.5.1r620.tar.gz/Test/Bento4CryptoTester.py
Changed
@@ -26,7 +26,7 @@ '0000000000000000', 'FFFFFFFFFFFFFFFF'] METHODS_FOR_LINEAR_MP4 = ['OMA-PDCF-CBC', 'OMA-PDCF-CTR', 'OMA-DCF-CBC', 'OMA-DCF-CTR', 'ISMA-IAEC'] -METHODS_FOR_FRAGMENTED_MP4 = ['MPEG-CENC', 'MPEG-CBC1', 'MPEG-CENS', 'MPEG-CBCS'] +METHODS_FOR_FRAGMENTED_MP4 = ['MPEG-CENC', 'MPEG-CBC1', 'MPEG-CENS', 'MPEG-CBCS', 'PIFF-CBC', 'PIFF-CTR'] def Bento4Command(name, *args, **kwargs): executable = path.join(BIN_ROOT, name)
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.