mirror of
https://github.com/axiomatic-systems/Bento4.git
synced 2026-01-12 00:18:59 +08:00
support for iframe index with mp4-dash in HLS mode
This commit is contained in:
@@ -156,7 +156,7 @@ LibraryModule(name = 'Bento4',
|
||||
build_source_files = env['AP4_SYSTEM_SOURCES'],
|
||||
included_modules = 'Config')
|
||||
|
||||
for name in ['Mp4Dump', 'Mp4Info', 'Mp4Edit', 'Mp4Encrypt', 'Mp4Decrypt', 'Mp4Tag', 'Mp4Extract', 'Mp4RtpHintInfo', 'Mp42Aac', 'Mp42Avc', 'Mp42Hevc', 'Mp42Ts', 'Mp42Hls', 'Mp4DcfPackager', 'Mp4Fragment', 'Mp4Compact', 'Mp4Split', 'Mp4AudioClip', 'Mp4Mux', 'AvcInfo', 'HevcInfo']:
|
||||
for name in ['Mp4Dump', 'Mp4Info', 'Mp4Edit', 'Mp4Encrypt', 'Mp4Decrypt', 'Mp4Tag', 'Mp4Extract', 'Mp4RtpHintInfo', 'Mp42Aac', 'Mp42Avc', 'Mp42Hevc', 'Mp42Ts', 'Mp42Hls', 'Mp4DcfPackager', 'Mp4Fragment', 'Mp4Compact', 'Mp4Split', 'Mp4AudioClip', 'Mp4Mux', 'Mp4Diff', 'Mp4IframeIndex', 'AvcInfo', 'HevcInfo']:
|
||||
Executable(name, source_dir='C++/Apps/'+name)
|
||||
|
||||
Executable('Aac2Mp4', source_dir='C++/Apps/Aac2Mp4')
|
||||
|
||||
35
Build/Makefiles/Mp4IframeIndex.mak
Normal file
35
Build/Makefiles/Mp4IframeIndex.mak
Normal file
@@ -0,0 +1,35 @@
|
||||
##########################################################################
|
||||
#
|
||||
# Mp4Info Program
|
||||
#
|
||||
# (c) 2002-2008 Axiomatic Systems, LLC
|
||||
#
|
||||
##########################################################################
|
||||
all: mp4iframeindex
|
||||
|
||||
##########################################################################
|
||||
# includes
|
||||
##########################################################################
|
||||
include $(BUILD_ROOT)/Makefiles/Lib.exp
|
||||
|
||||
##########################################################################
|
||||
# targets
|
||||
##########################################################################
|
||||
TARGET_SOURCES = Mp4IframeIndex.cpp
|
||||
|
||||
##########################################################################
|
||||
# make path
|
||||
##########################################################################
|
||||
VPATH += $(SOURCE_ROOT)/Apps/Mp4IframeIndex
|
||||
|
||||
##########################################################################
|
||||
# includes
|
||||
##########################################################################
|
||||
include $(BUILD_ROOT)/Makefiles/Rules.mak
|
||||
|
||||
##########################################################################
|
||||
# rules
|
||||
##########################################################################
|
||||
mp4iframeindex: $(TARGET_OBJECTS) $(TARGET_LIBRARY_FILES)
|
||||
$(LINK) $(TARGET_OBJECTS) -o $@ $(LINK_LIBRARIES)
|
||||
|
||||
@@ -153,6 +153,10 @@ mp42hls: lib
|
||||
$(TITLE)
|
||||
@$(INVOKE_SUBMAKE) -f $(BUILD_ROOT)/Makefiles/Mp42Hls.mak
|
||||
|
||||
mp4iframeindex: lib
|
||||
$(TITLE)
|
||||
@$(INVOKE_SUBMAKE) -f $(BUILD_ROOT)/Makefiles/Mp4IframeIndex.mak
|
||||
|
||||
##################################################################
|
||||
# includes
|
||||
##################################################################
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
buildPhases = (
|
||||
);
|
||||
dependencies = (
|
||||
CACAF6931F91C49400B75DC3 /* PBXTargetDependency */,
|
||||
CACAF6911F91C48F00B75DC3 /* PBXTargetDependency */,
|
||||
CA640EA11B09AAEF00C93DCF /* PBXTargetDependency */,
|
||||
CA00A65E1A1C383E0064B4D3 /* PBXTargetDependency */,
|
||||
CA418B141948F0A300D202E0 /* PBXTargetDependency */,
|
||||
@@ -144,6 +146,8 @@
|
||||
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 */; };
|
||||
CA87B95B1F895AD9005F42D6 /* libBento4.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAA7E6C914ACD763008AA54E /* libBento4.a */; };
|
||||
CA87B95E1F895F90005F42D6 /* Mp4IframeIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CA87B95D1F895B14005F42D6 /* Mp4IframeIndex.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 */; };
|
||||
@@ -732,6 +736,13 @@
|
||||
remoteGlobalIDString = CA86EED619A95DD3008A3B00;
|
||||
remoteInfo = FragmentCreatorTest;
|
||||
};
|
||||
CA87B9591F895ACE005F42D6 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D2AAC045055464E500DB518D;
|
||||
remoteInfo = Bento4;
|
||||
};
|
||||
CA8A94D71929A67500836179 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
@@ -816,6 +827,20 @@
|
||||
remoteGlobalIDString = D2AAC045055464E500DB518D;
|
||||
remoteInfo = Bento4;
|
||||
};
|
||||
CACAF6901F91C48F00B75DC3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = CA87B9511F895A84005F42D6;
|
||||
remoteInfo = Mp4IframeIndex;
|
||||
};
|
||||
CACAF6921F91C49400B75DC3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = CA87B9411F81B08B005F42D6;
|
||||
remoteInfo = Mp4Diff;
|
||||
};
|
||||
CAE1FBEE1AF8493E00607B3C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
@@ -981,6 +1006,15 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
CA87B9501F895A84005F42D6 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
CAFE9C671D1B487700F9FF67 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1079,8 +1113,9 @@
|
||||
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>"; };
|
||||
CA87B9521F895A84005F42D6 /* Mp4IframeIndex */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = Mp4IframeIndex; path = mp4iframeindex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CA87B95D1F895B14005F42D6 /* Mp4IframeIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mp4IframeIndex.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>"; };
|
||||
@@ -1514,6 +1549,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CA87B94F1F895A84005F42D6 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CA87B95B1F895AD9005F42D6 /* libBento4.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CA8A94CB1929A65E00836179 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1665,7 +1708,6 @@
|
||||
CA646A860CE97B2D009699D7 /* Apps */,
|
||||
CA646A9B0CE97B51009699D7 /* Test */,
|
||||
C6A0FF2B0290797F04C91782 /* Documentation */,
|
||||
CA87B9431F81B08B005F42D6 /* Mp4Diff */,
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */,
|
||||
CA87B9491F81B0C4005F42D6 /* Frameworks */,
|
||||
);
|
||||
@@ -1730,6 +1772,7 @@
|
||||
CAE1FBF61AF8493E00607B3C /* mp42hls */,
|
||||
CAFE9C691D1B487700F9FF67 /* LargeFilesTest */,
|
||||
CA87B9421F81B08B005F42D6 /* mp4diff */,
|
||||
CA87B9521F895A84005F42D6 /* Mp4IframeIndex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -1821,6 +1864,7 @@
|
||||
CA646A910CE97B2D009699D7 /* Mp4Encrypt */,
|
||||
CA646A930CE97B2D009699D7 /* Mp4Extract */,
|
||||
CA6103E2128599C20039C7E6 /* Mp4Fragment */,
|
||||
CA87B95C1F895B14005F42D6 /* Mp4IframeIndex */,
|
||||
CA646A950CE97B2D009699D7 /* Mp4Info */,
|
||||
CA8A94DA1929A6C100836179 /* Mp4Mux */,
|
||||
CA00A65A1A1C38210064B4D3 /* Mp4Pssh */,
|
||||
@@ -1961,14 +2005,6 @@
|
||||
path = FragmentCreator;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA87B9431F81B08B005F42D6 /* Mp4Diff */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CA87B9441F81B08B005F42D6 /* main.cpp */,
|
||||
);
|
||||
path = Mp4Diff;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA87B9491F81B0C4005F42D6 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1984,6 +2020,14 @@
|
||||
path = Mp4Diff;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA87B95C1F895B14005F42D6 /* Mp4IframeIndex */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CA87B95D1F895B14005F42D6 /* Mp4IframeIndex.cpp */,
|
||||
);
|
||||
path = Mp4IframeIndex;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CA8A94DA1929A6C100836179 /* Mp4Mux */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2969,6 +3013,24 @@
|
||||
productReference = CA87B9421F81B08B005F42D6 /* mp4diff */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
CA87B9511F895A84005F42D6 /* Mp4IframeIndex */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CA87B9581F895A84005F42D6 /* Build configuration list for PBXNativeTarget "Mp4IframeIndex" */;
|
||||
buildPhases = (
|
||||
CA87B94E1F895A84005F42D6 /* Sources */,
|
||||
CA87B94F1F895A84005F42D6 /* Frameworks */,
|
||||
CA87B9501F895A84005F42D6 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
CA87B95A1F895ACE005F42D6 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Mp4IframeIndex;
|
||||
productName = Mp4IframeIndex;
|
||||
productReference = CA87B9521F895A84005F42D6 /* Mp4IframeIndex */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
CA8A94CD1929A65E00836179 /* Mp4Mux */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CA8A94D61929A65E00836179 /* Build configuration list for PBXNativeTarget "Mp4Mux" */;
|
||||
@@ -3293,6 +3355,10 @@
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
CA87B9511F895A84005F42D6 = {
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
CAFE9C681D1B487700F9FF67 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
};
|
||||
@@ -3355,6 +3421,7 @@
|
||||
CAFC31B80FEB3DDD00EF80A0 /* FragmentParserTest */,
|
||||
CA86EED619A95DD3008A3B00 /* FragmentCreatorTest */,
|
||||
CAFE9C681D1B487700F9FF67 /* LargeFilesTest */,
|
||||
CA87B9511F895A84005F42D6 /* Mp4IframeIndex */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -3536,6 +3603,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CA87B94E1F895A84005F42D6 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CA87B95E1F895F90005F42D6 /* Mp4IframeIndex.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CA8A94CA1929A65E00836179 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -4033,6 +4108,11 @@
|
||||
target = CA86EED619A95DD3008A3B00 /* FragmentCreatorTest */;
|
||||
targetProxy = CA86EEEC19BD6865008A3B00 /* PBXContainerItemProxy */;
|
||||
};
|
||||
CA87B95A1F895ACE005F42D6 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D2AAC045055464E500DB518D /* Bento4 */;
|
||||
targetProxy = CA87B9591F895ACE005F42D6 /* PBXContainerItemProxy */;
|
||||
};
|
||||
CA8A94D81929A67500836179 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D2AAC045055464E500DB518D /* Bento4 */;
|
||||
@@ -4093,6 +4173,16 @@
|
||||
target = D2AAC045055464E500DB518D /* Bento4 */;
|
||||
targetProxy = CAC8F17A16BE447A00C49741 /* PBXContainerItemProxy */;
|
||||
};
|
||||
CACAF6911F91C48F00B75DC3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = CA87B9511F895A84005F42D6 /* Mp4IframeIndex */;
|
||||
targetProxy = CACAF6901F91C48F00B75DC3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
CACAF6931F91C49400B75DC3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = CA87B9411F81B08B005F42D6 /* Mp4Diff */;
|
||||
targetProxy = CACAF6921F91C49400B75DC3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
CAE1FBED1AF8493E00607B3C /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D2AAC045055464E500DB518D /* Bento4 */;
|
||||
@@ -4846,6 +4936,69 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CA87B9561F895A84005F42D6 /* 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 = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
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.13;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_NAME = mp4iframeindex;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CA87B9571F895A84005F42D6 /* 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 = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
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.13;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_NAME = mp4iframeindex;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CA8A94D41929A65E00836179 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -5621,6 +5774,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CA87B9581F895A84005F42D6 /* Build configuration list for PBXNativeTarget "Mp4IframeIndex" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CA87B9561F895A84005F42D6 /* Debug */,
|
||||
CA87B9571F895A84005F42D6 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CA8A94D61929A65E00836179 /* Build configuration list for PBXNativeTarget "Mp4Mux" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -103,6 +103,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mp42Avc", "Mp42Avc\Mp42Avc.
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mp42Hevc", "Mp42Hevc\Mp42Hevc.vcxproj", "{2ED2DF44-488D-470A-9C52-88D9D10518F7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mp4IframeIndex", "Mp4IframeIndex\Mp4IframeIndex.vcxproj", "{FD311CE7-C059-457C-BEEC-86CEB1E7014D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@@ -213,6 +215,10 @@ Global
|
||||
{2ED2DF44-488D-470A-9C52-88D9D10518F7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{2ED2DF44-488D-470A-9C52-88D9D10518F7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{2ED2DF44-488D-470A-9C52-88D9D10518F7}.Release|Win32.Build.0 = Release|Win32
|
||||
{FD311CE7-C059-457C-BEEC-86CEB1E7014D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{FD311CE7-C059-457C-BEEC-86CEB1E7014D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{FD311CE7-C059-457C-BEEC-86CEB1E7014D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{FD311CE7-C059-457C-BEEC-86CEB1E7014D}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -237,6 +243,7 @@ Global
|
||||
{EA2B1E39-B9F4-4424-A01B-65628E87BEB5} = {92E4C2EB-ED44-4B47-805D-CC272C8838EB}
|
||||
{28D14679-1C21-4B6E-B891-62769EDCEFFF} = {92E4C2EB-ED44-4B47-805D-CC272C8838EB}
|
||||
{2ED2DF44-488D-470A-9C52-88D9D10518F7} = {92E4C2EB-ED44-4B47-805D-CC272C8838EB}
|
||||
{FD311CE7-C059-457C-BEEC-86CEB1E7014D} = {92E4C2EB-ED44-4B47-805D-CC272C8838EB}
|
||||
{FA13F082-633C-4DAD-B282-6B0E1BDD3412} = {FAE70B4A-0D9D-4748-9DED-991D4101AE93}
|
||||
{B031A581-FDE5-4CDC-A124-573F6EECB54A} = {FAE70B4A-0D9D-4748-9DED-991D4101AE93}
|
||||
{23C9BE84-E4D3-4F06-9188-533991022D48} = {FAE70B4A-0D9D-4748-9DED-991D4101AE93}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{FD311CE7-C059-457C-BEEC-86CEB1E7014D}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>Mp4IframeIndex</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\Source\C++\Core;..\..\..\..\Source\C++\MetaData;..\..\..\..\Source\C++\Codecs;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\Source\C++\Core;..\..\..\..\Source\C++\MetaData;..\..\..\..\Source\C++\Codecs;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Bento4\Bento4.vcxproj">
|
||||
<Project>{a714aa1c-45a9-403d-a6e1-020e520119a2}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\..\Source\C++\Apps\Mp4IframeIndex\Mp4IframeIndex.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\..\Source\C++\Apps\Mp4IframeIndex\Mp4IframeIndex.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -44,7 +44,7 @@ include_directories(
|
||||
)
|
||||
|
||||
# Apps
|
||||
set(BENTO4_APPS "Aac2Mp4;Mp42Aac;Mp42Ts;Mp42Hls;Mp4Compact;Mp4DcfPackager;Mp4Decrypt;Mp4Dump;Mp4Edit;Mp4Encrypt;Mp4Extract;Mp4Fragment;Mp4Info;Mp4Mux;Mp4Split;Mp4Tag")
|
||||
set(BENTO4_APPS "Aac2Mp4;Mp42Aac;Mp42Ts;Mp42Hls;Mp4Compact;Mp4DcfPackager;Mp4Decrypt;Mp4Dump;Mp4Edit;Mp4Encrypt;Mp4Extract;Mp4Fragment;Mp4Info;Mp4Mux;Mp4Split;Mp4Tag;Mp4Diff;Mp4IframeIndex")
|
||||
foreach(app ${BENTO4_APPS})
|
||||
string(TOLOWER ${app} binary_name)
|
||||
add_executable(${binary_name} ${SOURCE_ROOT}/Apps/${app}/${app}.cpp)
|
||||
|
||||
@@ -237,6 +237,7 @@ bin_files = [
|
||||
(bin_in,'aac2mp4','bin'),
|
||||
(bin_in,'mp42ts','bin'),
|
||||
(bin_in,'mp42hls','bin'),
|
||||
(bin_in,'mp4iframeindex','bin'),
|
||||
(bin_in,'*.a','lib'),
|
||||
(bin_in,'*.dll','bin'),
|
||||
(bin_in,'*.dylib','bin'),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*****************************************************************
|
||||
|
|
||||
| AP4 - MP4 File Info
|
||||
| AP4 - MP4 File Comparator
|
||||
|
|
||||
| Copyright 2002-2015 Axiomatic Systems, LLC
|
||||
| Copyright 2002-2017 Axiomatic Systems, LLC
|
||||
|
|
||||
|
|
||||
| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
|
||||
|
||||
263
Source/C++/Apps/Mp4IframeIndex/Mp4IframeIndex.cpp
Normal file
263
Source/C++/Apps/Mp4IframeIndex/Mp4IframeIndex.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/*****************************************************************
|
||||
|
|
||||
| AP4 - MP4 I-Frame Indexer
|
||||
|
|
||||
| Copyright 2002-2017 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"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| constants
|
||||
+---------------------------------------------------------------------*/
|
||||
#define BANNER "MP4 Iframe Index - Version 1.0.0\n"\
|
||||
"(Bento4 Version " AP4_VERSION_STRING ")\n"\
|
||||
"(c) 2002-2017 Axiomatic Systems, LLC"
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| PrintUsageAndExit
|
||||
+---------------------------------------------------------------------*/
|
||||
static void
|
||||
PrintUsageAndExit()
|
||||
{
|
||||
fprintf(stderr,
|
||||
BANNER
|
||||
"\n\nusage: mp4iframeindex [options] <input> [<output>]\n"
|
||||
" options:\n"
|
||||
" --track <id>: ID of the video track\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| IndexTrack
|
||||
+---------------------------------------------------------------------*/
|
||||
static AP4_Result
|
||||
IndexTrack(AP4_Track& track, const char** separator, AP4_ByteStream* output)
|
||||
{
|
||||
AP4_Sample sample;
|
||||
for (unsigned int i=0; i<track.GetSampleCount(); i++) {
|
||||
// get the sample
|
||||
AP4_Result result = track.GetSample(i, sample);
|
||||
if (AP4_FAILED(result)) return result;
|
||||
|
||||
if (sample.IsSync()) {
|
||||
AP4_Offset offset = sample.GetOffset();
|
||||
char workspace[256];
|
||||
AP4_FormatString(workspace, sizeof(workspace),
|
||||
"%s{ \"size\": %u, \"offset\": %llu, \"fragmentStart\": 0 }",
|
||||
*separator,
|
||||
(unsigned int)sample.GetSize(),
|
||||
(unsigned long long)offset);
|
||||
*separator = ",\n";
|
||||
output->WriteString(workspace);
|
||||
}
|
||||
}
|
||||
|
||||
return AP4_SUCCESS;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| IndexFragments
|
||||
+---------------------------------------------------------------------*/
|
||||
static AP4_Result
|
||||
IndexFragments(AP4_Movie& movie, unsigned int track_id, AP4_ByteStream* stream, const char** separator, AP4_ByteStream* output)
|
||||
{
|
||||
stream->Seek(0);
|
||||
AP4_LinearReader reader(movie, stream);
|
||||
reader.EnableTrack(track_id);
|
||||
|
||||
AP4_Sample sample;
|
||||
AP4_Position last_fragment_position = (AP4_Position)(-1);
|
||||
for (unsigned int i=0; ; i++) {
|
||||
AP4_UI32 found_track_id = 0;
|
||||
AP4_Result result = reader.GetNextSample(sample, found_track_id);
|
||||
if (AP4_FAILED(result)) break;
|
||||
|
||||
// only output the first sync sample of each fragment
|
||||
if (reader.GetCurrentFragmentPosition() == last_fragment_position) {
|
||||
continue;
|
||||
}
|
||||
if (found_track_id == track_id && sample.IsSync()) {
|
||||
AP4_Offset offset = sample.GetOffset();
|
||||
char workspace[256];
|
||||
AP4_FormatString(workspace, sizeof(workspace),
|
||||
"%s{ \"size\": %u, \"offset\": %llu, \"fragmentStart\": %llu }",
|
||||
*separator,
|
||||
(unsigned int)sample.GetSize(),
|
||||
(unsigned long long)offset,
|
||||
(unsigned long long)reader.GetCurrentFragmentPosition());
|
||||
*separator = ",\n";
|
||||
output->WriteString(workspace);
|
||||
}
|
||||
last_fragment_position = reader.GetCurrentFragmentPosition();
|
||||
}
|
||||
|
||||
return AP4_SUCCESS;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
| main
|
||||
+---------------------------------------------------------------------*/
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
PrintUsageAndExit();
|
||||
}
|
||||
const char* input_filename = NULL;
|
||||
const char* output_filename = NULL;
|
||||
const char* moov_filename = NULL;
|
||||
unsigned int track_id = 0;
|
||||
|
||||
++argv;
|
||||
while (char* arg = *argv++) {
|
||||
if (!strcmp(arg, "--track")) {
|
||||
arg = *argv++;
|
||||
if (arg == NULL) {
|
||||
fprintf(stderr, "ERROR: missing argument after --track option\n");
|
||||
return 1;
|
||||
}
|
||||
track_id = (unsigned int)strtoul(arg, NULL, 10);
|
||||
} else if (!strcmp(arg, "--fragments-info")) {
|
||||
moov_filename = *argv++;
|
||||
if (moov_filename == NULL) {
|
||||
fprintf(stderr, "ERROR: missing argument after --fragments-info option\n");
|
||||
}
|
||||
} else if (input_filename == NULL) {
|
||||
input_filename = arg;
|
||||
} else if (output_filename == NULL) {
|
||||
output_filename = arg;
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: unexpected argument '%s'\n", arg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (input_filename == NULL) {
|
||||
fprintf(stderr, "ERROR: input filename missing\n");
|
||||
return 1;
|
||||
}
|
||||
if (output_filename == NULL) {
|
||||
output_filename = "-stdout";
|
||||
}
|
||||
|
||||
AP4_ByteStream* output = NULL;
|
||||
AP4_Result result = AP4_FileByteStream::Create(output_filename,
|
||||
AP4_FileByteStream::STREAM_MODE_WRITE,
|
||||
output);
|
||||
if (AP4_FAILED(result)) {
|
||||
fprintf(stderr, "ERROR: cannot open output file %s (%d)\n", input_filename, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
AP4_ByteStream* input = NULL;
|
||||
result = AP4_FileByteStream::Create(input_filename,
|
||||
AP4_FileByteStream::STREAM_MODE_READ,
|
||||
input);
|
||||
if (AP4_FAILED(result)) {
|
||||
fprintf(stderr, "ERROR: cannot open input file %s (%d)\n", input_filename, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
AP4_ByteStream* moov = NULL;
|
||||
if (moov_filename) {
|
||||
result = AP4_FileByteStream::Create(moov_filename,
|
||||
AP4_FileByteStream::STREAM_MODE_READ,
|
||||
moov);
|
||||
if (AP4_FAILED(result)) {
|
||||
fprintf(stderr, "ERROR: cannot open fragments info file %s (%d)\n", moov_filename, result);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
AP4_File* input_file = new AP4_File(*input, true);
|
||||
AP4_Movie* input_movie = input_file->GetMovie();
|
||||
AP4_File* moov_file = moov ? new AP4_File(*moov, true) : NULL;
|
||||
AP4_Track* track = NULL;
|
||||
const char* separator = "";
|
||||
|
||||
if (input_movie == NULL) {
|
||||
// we need a movie to get to the fragments
|
||||
if (moov_file == NULL) {
|
||||
fprintf(stderr, "ERROR: input file does not contain a movie (use --fragments-info option)\n");
|
||||
goto end;
|
||||
}
|
||||
input_movie = moov_file->GetMovie();
|
||||
}
|
||||
|
||||
// select the track
|
||||
if (track_id == 0) {
|
||||
track = input_movie->GetTrack(AP4_Track::TYPE_VIDEO);
|
||||
if (track) {
|
||||
track_id = track->GetId();
|
||||
}
|
||||
} else {
|
||||
track = input_movie->GetTrack(track_id);
|
||||
}
|
||||
|
||||
// check that we found the track
|
||||
if (!track) {
|
||||
fprintf(stderr, "ERROR: video track not found\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
// check the track type
|
||||
if (track->GetType() != AP4_Track::TYPE_VIDEO) {
|
||||
fprintf(stderr, "ERROR: track ID %d is not a video track\n", track->GetId());
|
||||
goto end;
|
||||
}
|
||||
|
||||
// start
|
||||
output->WriteString("[\n");
|
||||
|
||||
// index the track
|
||||
result = IndexTrack(*track, &separator, output);
|
||||
if (AP4_FAILED(result)) {
|
||||
fprintf(stderr, "ERROR: failed to index track (%d)\n", result);
|
||||
}
|
||||
|
||||
// index the fragments
|
||||
result = IndexFragments(*input_movie, track_id, input, &separator, output);
|
||||
if (AP4_FAILED(result)) {
|
||||
fprintf(stderr, "ERROR: failed to index fragments (%d)\n", result);
|
||||
}
|
||||
|
||||
// end
|
||||
output->WriteString("\n]\n");
|
||||
|
||||
end:
|
||||
delete input_file;
|
||||
delete moov_file;
|
||||
if (moov) moov->Release();
|
||||
input->Release();
|
||||
output->Release();
|
||||
|
||||
return result == AP4_SUCCESS ? 0 : 1;
|
||||
}
|
||||
@@ -1189,6 +1189,7 @@ AP4_HevcFrameParser::Feed(const AP4_UI08* nal_unit,
|
||||
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;
|
||||
(void)nuh_layer_id;
|
||||
|
||||
if (nuh_temporal_id-- == 0) {
|
||||
// illegal value, ignore this NAL unit
|
||||
|
||||
@@ -46,6 +46,7 @@ AP4_LinearReader::AP4_LinearReader(AP4_Movie& movie,
|
||||
m_Movie(movie),
|
||||
m_Fragment(NULL),
|
||||
m_FragmentStream(fragment_stream),
|
||||
m_CurrentFragmentPosition(0),
|
||||
m_NextFragmentPosition(0),
|
||||
m_BufferFullness(0),
|
||||
m_BufferFullnessPeak(0),
|
||||
@@ -55,7 +56,8 @@ AP4_LinearReader::AP4_LinearReader(AP4_Movie& movie,
|
||||
m_HasFragments = movie.HasFragments();
|
||||
if (fragment_stream) {
|
||||
fragment_stream->AddReference();
|
||||
fragment_stream->Tell(m_NextFragmentPosition);
|
||||
fragment_stream->Tell(m_CurrentFragmentPosition);
|
||||
m_NextFragmentPosition = m_CurrentFragmentPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,6 +341,7 @@ AP4_LinearReader::AdvanceFragment()
|
||||
// go the the start of the next fragment
|
||||
result = m_FragmentStream->Seek(m_NextFragmentPosition);
|
||||
if (AP4_FAILED(result)) return result;
|
||||
m_CurrentFragmentPosition = m_NextFragmentPosition;
|
||||
|
||||
// read atoms until we find a moof
|
||||
assert(m_HasFragments);
|
||||
@@ -346,11 +349,16 @@ AP4_LinearReader::AdvanceFragment()
|
||||
AP4_DefaultAtomFactory atom_factory;
|
||||
do {
|
||||
AP4_Atom* atom = NULL;
|
||||
AP4_Position last_position = 0;
|
||||
m_FragmentStream->Tell(last_position);
|
||||
result = atom_factory.CreateAtomFromStream(*m_FragmentStream, atom);
|
||||
if (AP4_SUCCEEDED(result)) {
|
||||
if (atom->GetType() == AP4_ATOM_TYPE_MOOF) {
|
||||
AP4_ContainerAtom* moof = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
|
||||
if (moof) {
|
||||
// remember where the moof started
|
||||
m_CurrentFragmentPosition = last_position;
|
||||
|
||||
// remember where we are in the stream
|
||||
AP4_Position position = 0;
|
||||
m_FragmentStream->Tell(position);
|
||||
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
|
||||
// accessors
|
||||
AP4_Size GetBufferFullness() { return m_BufferFullness; }
|
||||
AP4_Position GetCurrentFragmentPosition() { return m_CurrentFragmentPosition; }
|
||||
|
||||
// classes
|
||||
class SampleReader {
|
||||
@@ -178,6 +179,7 @@ protected:
|
||||
bool m_HasFragments;
|
||||
AP4_MovieFragment* m_Fragment;
|
||||
AP4_ByteStream* m_FragmentStream;
|
||||
AP4_Position m_CurrentFragmentPosition;
|
||||
AP4_Position m_NextFragmentPosition;
|
||||
AP4_Array<Tracker*> m_Trackers;
|
||||
AP4_Size m_BufferFullness;
|
||||
|
||||
@@ -571,27 +571,70 @@ def OutputDash(options, set_attributes, audio_sets, video_sets, subtitles_sets,
|
||||
|
||||
|
||||
#############################################
|
||||
def OutputHlsTrack(options, track, media_subdir, media_playlist_name, media_file_name):
|
||||
def ComputeHlsWidevineKeyLine(options, track):
|
||||
try:
|
||||
pairs = options.widevine_header.split('#')
|
||||
fields = {}
|
||||
for pair in pairs:
|
||||
name, value = pair.split(':', 1)
|
||||
fields[name] = value
|
||||
except:
|
||||
raise Exception('invalid syntax for --widevine-header option')
|
||||
|
||||
if 'content_id' not in fields:
|
||||
fields['content_id'] = '*'
|
||||
if 'kid' not in fields:
|
||||
fields['kid'] = track.key_info['kid']
|
||||
|
||||
json_param = '{ "provider": "%(provider)s", "content_id": "%(content_id)s", "key_ids": ["%(kid)s"] }' % fields
|
||||
key_line = 'URI="data:text/plain;base64,'+json_param.encode('base64').replace('\n','')+'",KEYFORMAT="com.widevine",KEYFORMATVERSIONS="1",IV=0x'+track.key_info['iv']
|
||||
|
||||
return key_line
|
||||
|
||||
#############################################
|
||||
def ComputeHlsFairplayKeyLine(options):
|
||||
return 'URI="'+options.fairplay_key_uri+'",KEYFORMAT="com.apple.streamingkeydelivery",KEYFORMATVERSIONS="1"'
|
||||
|
||||
#############################################
|
||||
def OutputHlsCommon(options, track, media_subdir, playlist_name, media_file_name):
|
||||
hls_target_duration = math.ceil(max(track.segment_durations))
|
||||
|
||||
media_playlist_file = open(path.join(options.output_dir, media_subdir, media_playlist_name), 'w+')
|
||||
media_playlist_file.write('#EXTM3U\r\n')
|
||||
media_playlist_file.write('# Created with Bento4 mp4-dash.py, VERSION=' + VERSION + '-' + SDK_REVISION+'\r\n')
|
||||
media_playlist_file.write('#\r\n')
|
||||
media_playlist_file.write('#EXT-X-VERSION:6\r\n')
|
||||
media_playlist_file.write('#EXT-X-PLAYLIST-TYPE:VOD\r\n')
|
||||
media_playlist_file.write('#EXT-X-INDEPENDENT-SEGMENTS\r\n')
|
||||
media_playlist_file.write('#EXT-X-TARGETDURATION:%d\r\n' % (hls_target_duration))
|
||||
media_playlist_file.write('#EXT-X-MEDIA-SEQUENCE:0\r\n')
|
||||
if options.on_demand or not options.split:
|
||||
init_segment_size = track.parent.init_segment.position + track.parent.init_segment.size
|
||||
media_playlist_file.write('#EXT-X-MAP:URI="%s",BYTERANGE="%d@0"\r\n' % (media_file_name, init_segment_size))
|
||||
playlist_file = open(path.join(options.output_dir, media_subdir, playlist_name), 'w+')
|
||||
playlist_file.write('#EXTM3U\r\n')
|
||||
playlist_file.write('# Created with Bento4 mp4-dash.py, VERSION=' + VERSION + '-' + SDK_REVISION+'\r\n')
|
||||
playlist_file.write('#\r\n')
|
||||
playlist_file.write('#EXT-X-VERSION:6\r\n')
|
||||
playlist_file.write('#EXT-X-PLAYLIST-TYPE:VOD\r\n')
|
||||
playlist_file.write('#EXT-X-INDEPENDENT-SEGMENTS\r\n')
|
||||
playlist_file.write('#EXT-X-TARGETDURATION:%d\r\n' % (hls_target_duration))
|
||||
playlist_file.write('#EXT-X-MEDIA-SEQUENCE:0\r\n')
|
||||
if options.split:
|
||||
playlist_file.write('#EXT-X-MAP:URI="%s"\r\n' % (SPLIT_INIT_SEGMENT_NAME))
|
||||
else:
|
||||
media_playlist_file.write('#EXT-X-MAP:URI="%s"\r\n' % (SPLIT_INIT_SEGMENT_NAME))
|
||||
segment_pattern = SEGMENT_PATTERN.replace('ll','')
|
||||
init_segment_size = track.parent.init_segment.position + track.parent.init_segment.size
|
||||
playlist_file.write('#EXT-X-MAP:URI="%s",BYTERANGE="%d@0"\r\n' % (media_file_name, init_segment_size))
|
||||
|
||||
if options.encryption_key:
|
||||
media_playlist_file.write('#EXT-X-KEY:METHOD=SAMPLE-AES,URI="'+options.hls_key_url+'",IV=0x'+track.key_info['iv']+'\r\n')
|
||||
key_lines = []
|
||||
if options.fairplay_key_uri:
|
||||
key_lines.append(ComputeHlsFairplayKeyLine(options))
|
||||
if options.widevine_header:
|
||||
key_lines.append(ComputeHlsWidevineKeyLine(options, track))
|
||||
|
||||
if len(key_lines) == 0:
|
||||
key_lines.append('URI="'+options.hls_key_url+'",IV=0x'+track.key_info['iv'])
|
||||
|
||||
for key_line in key_lines:
|
||||
playlist_file.write('#EXT-X-KEY:METHOD=SAMPLE-AES,'+key_line+'\r\n')
|
||||
|
||||
return playlist_file
|
||||
|
||||
#############################################
|
||||
def OutputHlsTrack(options, track, media_subdir, media_playlist_name, media_file_name):
|
||||
media_playlist_file = OutputHlsCommon(options, track, media_subdir, media_playlist_name, media_file_name)
|
||||
|
||||
if options.split:
|
||||
segment_pattern = SEGMENT_PATTERN.replace('ll','')
|
||||
|
||||
for i in range(len(track.segment_durations)):
|
||||
media_playlist_file.write('#EXTINF:%f,\r\n' % (track.segment_durations[i]))
|
||||
@@ -607,6 +650,47 @@ def OutputHlsTrack(options, track, media_subdir, media_playlist_name, media_file
|
||||
|
||||
media_playlist_file.write('#EXT-X-ENDLIST\r\n')
|
||||
|
||||
#############################################
|
||||
def OutputHlsIframeIndex(options, track, media_subdir, iframes_playlist_name, media_file_name):
|
||||
index_playlist_file = OutputHlsCommon(options, track, media_subdir, iframes_playlist_name, media_file_name)
|
||||
|
||||
index_playlist_file.write('#EXT-X-I-FRAMES-ONLY\r\n')
|
||||
|
||||
if not options.split:
|
||||
# get the I-frame index for a single file
|
||||
json_index = Mp4IframIndex(options, path.join(options.output_dir, media_file_name))
|
||||
index = json.loads(json_index)
|
||||
for i in range(len(track.segment_durations)):
|
||||
if i < len(index):
|
||||
index_entry = index[i]
|
||||
index_playlist_file.write('#EXTINF:%f,\r\n' % (track.segment_durations[i]))
|
||||
fragment_start = int(index_entry['fragmentStart'])
|
||||
iframe_offset = int(index_entry['offset'])
|
||||
iframe_size = int(index_entry['size'])
|
||||
iframe_range_size = iframe_size + (iframe_offset-fragment_start)
|
||||
index_playlist_file.write('#EXT-X-BYTERANGE:%d@%d\r\n' % (iframe_range_size, fragment_start))
|
||||
index_playlist_file.write(media_file_name+'\r\n')
|
||||
else:
|
||||
segment_pattern = SEGMENT_PATTERN.replace('ll','')
|
||||
for i in range(len(track.segment_durations)):
|
||||
fragment_basename = segment_pattern % (i+1)
|
||||
fragment_file = path.join(options.output_dir, media_subdir, fragment_basename)
|
||||
init_file = path.join(options.output_dir, media_subdir, options.init_segment)
|
||||
if not path.exists(fragment_file):
|
||||
break
|
||||
json_index = Mp4IframIndex(options, fragment_file, fragments_info=init_file)
|
||||
index = json.loads(json_index)
|
||||
if len(index) < 1:
|
||||
break
|
||||
iframe_size = int(index[0]['size'])
|
||||
iframe_offset = int(index[0]['offset'])
|
||||
iframe_range_size = iframe_size + iframe_offset
|
||||
index_playlist_file.write('#EXTINF:%f,\r\n' % (track.segment_durations[i]))
|
||||
index_playlist_file.write('#EXT-X-BYTERANGE:%d@0\r\n' % (iframe_range_size))
|
||||
index_playlist_file.write(fragment_basename+'\r\n')
|
||||
|
||||
index_playlist_file.write('#EXT-X-ENDLIST\r\n')
|
||||
|
||||
#############################################
|
||||
def OutputHls(options, set_attributes, audio_sets, video_sets, subtitles_sets, subtitles_files):
|
||||
all_audio_tracks = sum(audio_sets.values(), [])
|
||||
@@ -670,15 +754,17 @@ def OutputHls(options, set_attributes, audio_sets, video_sets, subtitles_sets, s
|
||||
master_playlist_file.write('# Video\r\n')
|
||||
for video_track in all_video_tracks:
|
||||
if options.on_demand or not options.split:
|
||||
media_subdir = ''
|
||||
media_file_name = video_track.parent.media_name
|
||||
media_playlist_name = video_track.representation_id+".m3u8"
|
||||
media_playlist_path = media_playlist_name
|
||||
media_subdir = ''
|
||||
media_file_name = video_track.parent.media_name
|
||||
media_playlist_name = video_track.representation_id+".m3u8"
|
||||
media_playlist_path = media_playlist_name
|
||||
iframes_playlist_name = video_track.representation_id+"_iframes.m3u8"
|
||||
else:
|
||||
media_subdir = video_track.representation_id
|
||||
media_file_name = ''
|
||||
media_playlist_name = options.hls_media_playlist_name
|
||||
media_playlist_path = media_subdir+'/'+media_playlist_name
|
||||
media_subdir = video_track.representation_id
|
||||
media_file_name = ''
|
||||
media_playlist_name = options.hls_media_playlist_name
|
||||
media_playlist_path = media_subdir+'/'+media_playlist_name
|
||||
iframes_playlist_name = options.hls_iframes_playlist_name
|
||||
|
||||
if len(audio_groups):
|
||||
# one entry per audio group
|
||||
@@ -703,6 +789,17 @@ def OutputHls(options, set_attributes, audio_sets, video_sets, subtitles_sets, s
|
||||
master_playlist_file.write(media_playlist_path+'\r\n')
|
||||
|
||||
OutputHlsTrack(options, video_track, media_subdir, media_playlist_name, media_file_name)
|
||||
OutputHlsIframeIndex(options, video_track, media_subdir, iframes_playlist_name, media_file_name)
|
||||
|
||||
master_playlist_file.write('\r\n# I-Frame Playlists\r\n')
|
||||
for video_track in all_video_tracks:
|
||||
master_playlist_file.write('#EXT-X-I-FRAME-STREAM-INF:AVERAGE-BANDWIDTH=%d,BANDWIDTH=%d,CODECS="%s",RESOLUTION=%dx%d,URI="%s"\r\n' % (
|
||||
video_track.average_segment_bitrate,
|
||||
video_track.max_segment_bitrate,
|
||||
video_track.codec,
|
||||
video_track.width,
|
||||
video_track.height,
|
||||
media_playlist_path))
|
||||
|
||||
if len(subtitles_files):
|
||||
master_playlist_file.write('# Subtitles\r\n')
|
||||
@@ -1244,6 +1341,8 @@ def main():
|
||||
"The <primetime-data> argument can be either: " +
|
||||
"(1) the character '@' followed by the name of a file containing the Primetime Metadata to use, or "
|
||||
"(2) the character '#' followed by the Primetime Metadata encoded in Base64")
|
||||
parser.add_option('', "--fairplay-key-uri", dest="fairplay_key_uri",
|
||||
help="Specify the key URI to use for FairPlay Streaming key delivery (only valid with --hls option)")
|
||||
parser.add_option('', "--exec-dir", metavar="<exec_dir>", dest="exec_dir", default=default_exec_dir,
|
||||
help="Directory where the Bento4 executables are located")
|
||||
(options, args) = parser.parse_args()
|
||||
@@ -1337,10 +1436,16 @@ def main():
|
||||
|
||||
if options.widevine_header:
|
||||
options.widevine = True
|
||||
if options.hls and options.widevine_header.startswith('#'):
|
||||
raise Exception('with --hls, only the <name>:<value> pair syntax is supported for the --widevine-header option')
|
||||
|
||||
if options.primetime_metadata:
|
||||
options.primetime = True
|
||||
|
||||
if options.fairplay_key_uri:
|
||||
if not options.hls:
|
||||
sys.stderr.write('WARNING: --fairplay-key-uri is only valid with --hls, ignoring\n')
|
||||
|
||||
if options.hls:
|
||||
if options.encryption_key and options.encryption_cenc_scheme != 'cbcs':
|
||||
raise Exception('--hls requires --encryption-cenc-scheme=cbcs')
|
||||
|
||||
@@ -302,6 +302,9 @@ def Mp4Encrypt(options, input_filename, output_filename, *args, **kwargs):
|
||||
def Mp42Hls(options, input_filename, *args, **kwargs):
|
||||
return Bento4Command(options, 'mp42hls', input_filename, *args, **kwargs)
|
||||
|
||||
def Mp4IframIndex(options, input_filename, *args, **kwargs):
|
||||
return Bento4Command(options, 'mp4iframeindex', input_filename, *args, **kwargs)
|
||||
|
||||
class Mp4Atom:
|
||||
def __init__(self, type, size, position):
|
||||
self.type = type
|
||||
|
||||
Reference in New Issue
Block a user