mirror of
https://github.com/axiomatic-systems/Bento4.git
synced 2026-01-12 00:18:59 +08:00
should work with hevc/fmp4/cbcs
This commit is contained in:
@@ -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 = {
|
||||
@@ -5466,6 +5612,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;
|
||||
buildConfigurations = (
|
||||
|
||||
231
Source/C++/Apps/Mp4Diff/Mp4Diff.cpp
Normal file
231
Source/C++/Apps/Mp4Diff/Mp4Diff.cpp
Normal file
@@ -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;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ PrintUsageAndExit()
|
||||
{
|
||||
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"
|
||||
|
||||
@@ -236,16 +236,16 @@ public:
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -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 @@ const char*
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -190,6 +190,91 @@ AP4_HevcNalParser::AP4_HevcNalParser() :
|
||||
{
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| scaling_list_data
|
||||
+---------------------------------------------------------------------*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
return AP4_SUCCESS;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| AP4_HevcSliceSegmentHeader::Parse
|
||||
+---------------------------------------------------------------------*/
|
||||
@@ -202,6 +287,10 @@ AP4_HevcSliceSegmentHeader::Parse(const AP4_UI08* data,
|
||||
// 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());
|
||||
@@ -242,39 +331,182 @@ AP4_HevcSliceSegmentHeader::Parse(const AP4_UI08* data,
|
||||
}
|
||||
|
||||
unsigned int bits_needed = BitsNeeded(PicSizeInCtbsY);
|
||||
slice_segment_address = bits.ReadBits(bits_needed);
|
||||
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 (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(num_short_term_ref_pic_sets)
|
||||
unsigned int stRpsIdx = sps->num_short_term_ref_pic_sets;
|
||||
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) {
|
||||
if (stRpsIdx == sps->num_short_term_ref_pic_sets) {
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,11 +514,11 @@ AP4_HevcSliceSegmentHeader::Parse(const AP4_UI08* data,
|
||||
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++) {
|
||||
// the value of num_entry_point_offsets shall be in the range of
|
||||
// 0 to ( num_tile_columns_minus1 + 1 ) * PicHeightInCtbsY − 1, inclusive.
|
||||
unsigned int bits_needed = BitsNeeded((pps->num_tile_columns_minus1 + 1) * PicHeightInCtbsY - 1);
|
||||
bits.ReadBits(bits_needed);
|
||||
bits.ReadBits(offset_len_minus1+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,6 +532,7 @@ AP4_HevcSliceSegmentHeader::Parse(const AP4_UI08* data,
|
||||
|
||||
/* compute the size */
|
||||
size = bits.GetBitsRead();
|
||||
DBG_PRINTF_1("*** slice segment header size=%d bits\n", size);
|
||||
|
||||
return AP4_SUCCESS;
|
||||
}
|
||||
@@ -391,7 +624,7 @@ AP4_HevcPictureParameterSet::AP4_HevcPictureParameterSet() :
|
||||
entropy_coding_sync_enabled_flag(0),
|
||||
num_tile_columns_minus1(0),
|
||||
num_tile_rows_minus1(0),
|
||||
uniform_spacing_flag(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),
|
||||
@@ -406,35 +639,6 @@ AP4_HevcPictureParameterSet::AP4_HevcPictureParameterSet() :
|
||||
{
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| scaling_list_data
|
||||
+---------------------------------------------------------------------*/
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| AP4_HevcPictureParameterSet::Parse
|
||||
+---------------------------------------------------------------------*/
|
||||
@@ -551,7 +755,11 @@ AP4_HevcSequenceParameterSet::AP4_HevcSequenceParameterSet() :
|
||||
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++) {
|
||||
@@ -623,7 +831,43 @@ AP4_HevcSequenceParameterSet::Parse(const unsigned char* data, unsigned int data
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,10 @@ const unsigned int AP4_HEVC_ACCESS_UNIT_FLAG_IS_RADL = 0x08;
|
||||
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
|
||||
+---------------------------------------------------------------------*/
|
||||
@@ -243,6 +247,10 @@ struct AP4_HevcSequenceParameterSet {
|
||||
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;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@@ -336,16 +344,16 @@ public:
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -49,15 +49,15 @@ public:
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -412,7 +412,11 @@ AP4_CencCbcsSubSampleMapper::GetSubSampleMap(AP4_DataBuffer& sample_data,
|
||||
}
|
||||
|
||||
// leave the slice header in the clear, including the NAL type
|
||||
unsigned int cleartext_size = m_NaluLengthSize+2+(slice_header.size+7)/8;
|
||||
//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);
|
||||
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -440,6 +440,7 @@ AP4_BitReader::ReadCache() const
|
||||
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 */
|
||||
|
||||
Reference in New Issue
Block a user