commit
925d397ea4
437
.cproject
437
.cproject
|
|
@ -1,437 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
|
||||||
<cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272">
|
|
||||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272" moduleId="org.eclipse.cdt.core.settings" name="ARM_Debug">
|
|
||||||
<externalSettings>
|
|
||||||
<externalSetting>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/streamPusher"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/SMServer"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/streamPusher/ARM"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/SMServer/ARM"/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="streamPusher" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="SMServer" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
</externalSetting>
|
|
||||||
</externalSettings>
|
|
||||||
<extensions>
|
|
||||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
</extensions>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
|
||||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272" name="ARM_Debug" parent="cdt.managedbuild.config.gnu.cross.exe.debug">
|
|
||||||
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272." name="/" resourcePath="">
|
|
||||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.830471881" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
|
||||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.1087638266" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-linux-gnueabi-" valueType="string"/>
|
|
||||||
<option id="cdt.managedbuild.option.gnu.cross.path.1835104267" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="/home/xzl/soft/arm-gcc-6.2/bin" valueType="string"/>
|
|
||||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.657700061" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
|
||||||
<builder arguments="-j8" buildPath="${workspace_loc:/streamPusher}/Debug" command="make" id="cdt.managedbuild.builder.gnu.cross.1414815504" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1784351355" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
|
||||||
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.221016008" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.most" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.debugging.level.646402024" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.dialect.std.1972177397" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1474182404" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.886102444" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
|
||||||
<option id="gnu.cpp.compiler.option.optimization.level.1960810243" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.debugging.level.809016166" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.dialect.std.1534690969" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.c++1y" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.include.paths.269637576" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
|
||||||
<listOptionValue builtIn="false" value="/home/xzl/soft"/>
|
|
||||||
<listOptionValue builtIn="false" value="../src"/>
|
|
||||||
<listOptionValue builtIn="false" value="../../ZLToolKit/src"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.compiler.option.preprocessor.def.275206662" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTSP2RTMP"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTMP2RTSP"/>
|
|
||||||
</option>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1840656821" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1688616453" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
|
|
||||||
<tool command="g++ -pthread -static-libstdc++" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.156178488" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
|
||||||
<option id="gnu.cpp.link.option.paths.1099158999" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
|
|
||||||
<listOptionValue builtIn="false" value="/home/xzl/workspace/ZLToolKit/ARM"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.link.option.libs.1286710800" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
|
|
||||||
<listOptionValue builtIn="false" value="ZLToolKit"/>
|
|
||||||
</option>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.463559224" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
|
||||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
|
||||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
|
||||||
</inputType>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.237778560" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.987251820" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.321229939" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
|
||||||
</tool>
|
|
||||||
</toolChain>
|
|
||||||
</folderInfo>
|
|
||||||
</configuration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
|
||||||
</cconfiguration>
|
|
||||||
<cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1912216574">
|
|
||||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1912216574" moduleId="org.eclipse.cdt.core.settings" name="X64">
|
|
||||||
<externalSettings>
|
|
||||||
<externalSetting>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/streamPusher"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/SMServer"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/ZLMeidaKit"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/ZLMediaKit"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/streamPusher/Debug"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/SMServer/X64"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/ZLMeidaKit/X64"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/ZLMediaKit/X64"/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="streamPusher" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="SMServer" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="ZLMeidaKit" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="ZLMediaKit" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
</externalSetting>
|
|
||||||
</externalSettings>
|
|
||||||
<extensions>
|
|
||||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
</extensions>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
|
||||||
<configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1912216574" name="X64" parent="cdt.managedbuild.config.gnu.cross.exe.debug" postannouncebuildStep="" postbuildStep="" preannouncebuildStep="" prebuildStep="">
|
|
||||||
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1912216574." name="/" resourcePath="">
|
|
||||||
<toolChain errorParsers="" id="cdt.managedbuild.toolchain.gnu.cross.base.1731210621" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
|
||||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.268604998" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="" valueType="string"/>
|
|
||||||
<option id="cdt.managedbuild.option.gnu.cross.path.105061222" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="" valueType="string"/>
|
|
||||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1847785660" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
|
||||||
<builder arguments="-j8" buildPath="${workspace_loc:/streamPusher}/Debug" command="make" errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator" id="cdt.managedbuild.builder.gnu.cross.1420064773" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
|
||||||
<tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.tool.gnu.cross.c.compiler.883243436" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
|
||||||
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.807081323" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.most" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.debugging.level.769882155" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.dialect.std.1386736984" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.misc.pic.542757068" name="Position Independent Code (-fPIC)" superClass="gnu.c.compiler.option.misc.pic" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1437084291" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool command="g++ " commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.148300194" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
|
||||||
<option id="gnu.cpp.compiler.option.optimization.level.18009049" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.debugging.level.1462613868" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.dialect.std.387448796" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.c++1y" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.include.paths.1977874877" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
|
||||||
<listOptionValue builtIn="false" value="../src"/>
|
|
||||||
<listOptionValue builtIn="false" value="../../ZLToolKit/src"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.compiler.option.preprocessor.def.863813077" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_FAAC"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTSP2RTMP"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTMP2RTSP"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_MP4V2"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_HLS"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_X264"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_OPENSSL"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_MYSQL"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.compiler.option.other.pic.198751626" name="Position Independent Code (-fPIC)" superClass="gnu.cpp.compiler.option.other.pic" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.776990372" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.885569113" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker">
|
|
||||||
<option defaultValue="true" id="gnu.c.link.option.shared.1562973613" name="Shared (-shared)" superClass="gnu.c.link.option.shared" valueType="boolean"/>
|
|
||||||
</tool>
|
|
||||||
<tool command="g++" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GLDErrorParser" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.1728730527" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
|
||||||
<option id="gnu.cpp.link.option.paths.262581495" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false"/>
|
|
||||||
<option id="gnu.cpp.link.option.libs.1197706329" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false"/>
|
|
||||||
<option defaultValue="true" id="gnu.cpp.link.option.shared.1825641787" name="Shared (-shared)" superClass="gnu.cpp.link.option.shared" useByScannerDiscovery="false" valueType="boolean"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.437103762" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
|
||||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
|
||||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
|
||||||
</inputType>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.1902434321" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
|
||||||
<tool command="as" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.tool.gnu.cross.assembler.1152237148" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.583426329" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
|
||||||
</tool>
|
|
||||||
</toolChain>
|
|
||||||
</folderInfo>
|
|
||||||
</configuration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
|
||||||
</cconfiguration>
|
|
||||||
<cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1508415929">
|
|
||||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1508415929" moduleId="org.eclipse.cdt.core.settings" name="WIN32">
|
|
||||||
<externalSettings>
|
|
||||||
<externalSetting>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/streamPusher"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/SMServer"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/streamPusher/Debug"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/SMServer/WIN32"/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="streamPusher" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="SMServer" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
</externalSetting>
|
|
||||||
</externalSettings>
|
|
||||||
<extensions>
|
|
||||||
<extension id="org.eclipse.cdt.core.Cygwin_PE" point="org.eclipse.cdt.core.BinaryParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
</extensions>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
|
||||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1508415929" name="WIN32" parent="cdt.managedbuild.config.gnu.cross.exe.debug">
|
|
||||||
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1508415929." name="/" resourcePath="">
|
|
||||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cygwin.base.1626305239" name="Cygwin GCC" superClass="cdt.managedbuild.toolchain.gnu.cygwin.base">
|
|
||||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.Cygwin_PE" id="cdt.managedbuild.target.gnu.platform.cygwin.base.187178930" name="Debug Platform" osList="win32" superClass="cdt.managedbuild.target.gnu.platform.cygwin.base"/>
|
|
||||||
<builder arguments="-j8" buildPath="${workspace_loc:/SMServer}/WIN32" command="make" id="cdt.managedbuild.target.gnu.builder.cygwin.base.629377026" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.cygwin.base"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.assembler.cygwin.base.1636318789" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.cygwin.base">
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.2010110108" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.archiver.cygwin.base.1059143675" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.cygwin.base"/>
|
|
||||||
<tool command="g++ -std=c++11" id="cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.666287751" name="Cygwin C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base">
|
|
||||||
<option id="gnu.cpp.compiler.option.include.paths.1644470871" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/extra/x264/include}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/extra/faac-1.28/include}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""E:\ServiceCenter\ZLToolKit\src""/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.compiler.option.preprocessor.def.696656907" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_X264"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_FAAC"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTSP2RTMP"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTMP2RTSP"/>
|
|
||||||
<listOptionValue builtIn="false" value="__WIN32__"/>
|
|
||||||
<listOptionValue builtIn="false" value="__x86__"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.compiler.option.optimization.level.930471751" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.debugging.level.654866617" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.dialect.std.1431836233" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.665214370" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin"/>
|
|
||||||
</tool>
|
|
||||||
<tool command="gcc" id="cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1643775314" name="Cygwin C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.cygwin.base">
|
|
||||||
<option id="gnu.c.compiler.option.preprocessor.def.symbols.681328153" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
|
|
||||||
<listOptionValue builtIn="false" value="__WIN32__"/>
|
|
||||||
<listOptionValue builtIn="false" value="__x86__"/>
|
|
||||||
</option>
|
|
||||||
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.173223743" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.most" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.debugging.level.1909420880" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.dialect.std.1329653493" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1758181712" superClass="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin"/>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.c.linker.cygwin.base.1324002540" name="Cygwin C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.cygwin.base">
|
|
||||||
<option defaultValue="true" id="gnu.c.link.option.shared.174924190" name="Shared (-shared)" superClass="gnu.c.link.option.shared" valueType="boolean"/>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base.290725694" name="Cygwin C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base">
|
|
||||||
<option id="gnu.cpp.link.option.libs.1424883692" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
|
|
||||||
<listOptionValue builtIn="false" value="ZLToolKit"/>
|
|
||||||
<listOptionValue builtIn="false" value="x264-148"/>
|
|
||||||
<listOptionValue builtIn="false" value="faac"/>
|
|
||||||
<listOptionValue builtIn="false" value="ws2_32"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.link.option.paths.675383842" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
|
|
||||||
<listOptionValue builtIn="false" value=""E:\ServiceCenter\ZLToolKit\WIN32""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/extra/x264/lib}""/>
|
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/extra/faac-1.28/lib}""/>
|
|
||||||
</option>
|
|
||||||
<option defaultValue="true" id="gnu.cpp.link.option.shared.1889712682" name="Shared (-shared)" superClass="gnu.cpp.link.option.shared" valueType="boolean"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.837966139" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
|
||||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
|
||||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
|
||||||
</inputType>
|
|
||||||
</tool>
|
|
||||||
</toolChain>
|
|
||||||
</folderInfo>
|
|
||||||
</configuration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
|
||||||
</cconfiguration>
|
|
||||||
<cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272.1008616174">
|
|
||||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272.1008616174" moduleId="org.eclipse.cdt.core.settings" name="ARM_Release">
|
|
||||||
<externalSettings>
|
|
||||||
<externalSetting>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/ZLMediaKit"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/ZLMediaKit/ARM_Release"/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="ZLMediaKit" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
</externalSetting>
|
|
||||||
</externalSettings>
|
|
||||||
<extensions>
|
|
||||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
</extensions>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
|
||||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272.1008616174" name="ARM_Release" parent="cdt.managedbuild.config.gnu.cross.exe.debug" postannouncebuildStep="" postbuildStep="" preannouncebuildStep="" prebuildStep="">
|
|
||||||
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272.1008616174." name="/" resourcePath="">
|
|
||||||
<toolChain errorParsers="" id="cdt.managedbuild.toolchain.gnu.cross.base.108901613" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
|
||||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.610863758" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-linux-gnueabi-" valueType="string"/>
|
|
||||||
<option id="cdt.managedbuild.option.gnu.cross.path.161060793" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="/home/xzl/soft/arm-gcc-6.2/bin" valueType="string"/>
|
|
||||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1875755540" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
|
||||||
<builder arguments="-j8" buildPath="${workspace_loc:/streamPusher}/Debug" command="make" errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator" id="cdt.managedbuild.builder.gnu.cross.729870443" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
|
||||||
<tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.tool.gnu.cross.c.compiler.586398911" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
|
||||||
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.1154960592" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.most" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.debugging.level.2076853828" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.dialect.std.2046974900" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1009906236" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool command="g++" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1256212557" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
|
||||||
<option id="gnu.cpp.compiler.option.optimization.level.1220286576" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.debugging.level.342094397" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.dialect.std.1912166648" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.c++1y" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.include.paths.1431226119" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
|
||||||
<listOptionValue builtIn="false" value="/home/xzl/soft"/>
|
|
||||||
<listOptionValue builtIn="false" value="../src"/>
|
|
||||||
<listOptionValue builtIn="false" value="../../ZLToolKit/src"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.compiler.option.preprocessor.def.1726750530" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTSP2RTMP"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTMP2RTSP"/>
|
|
||||||
</option>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1193883355" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1647439287" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
|
|
||||||
<tool command="g++ -pthread -static-libstdc++" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.190896676" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
|
||||||
<option id="gnu.cpp.link.option.paths.619823921" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
|
|
||||||
<listOptionValue builtIn="false" value="/home/xzl/workspace/ZLToolKit/ARM"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.link.option.libs.710761129" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
|
|
||||||
<listOptionValue builtIn="false" value="ZLToolKit"/>
|
|
||||||
</option>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1393070093" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
|
||||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
|
||||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
|
||||||
</inputType>
|
|
||||||
</tool>
|
|
||||||
<tool command="ar" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="" id="cdt.managedbuild.tool.gnu.cross.archiver.1529613332" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
|
||||||
<tool command="as" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" errorParsers="org.eclipse.cdt.core.GASErrorParser" id="cdt.managedbuild.tool.gnu.cross.assembler.1485403119" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1469969271" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
|
||||||
</tool>
|
|
||||||
</toolChain>
|
|
||||||
</folderInfo>
|
|
||||||
</configuration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
|
||||||
</cconfiguration>
|
|
||||||
<cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272.1008616174.636088656">
|
|
||||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272.1008616174.636088656" moduleId="org.eclipse.cdt.core.settings" name="Android">
|
|
||||||
<externalSettings>
|
|
||||||
<externalSetting>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/ZLMediaKit"/>
|
|
||||||
<entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/ZLMediaKit/Android"/>
|
|
||||||
<entry flags="RESOLVED" kind="libraryFile" name="ZLMediaKit" srcPrefixMapping="" srcRootPath=""/>
|
|
||||||
</externalSetting>
|
|
||||||
</externalSettings>
|
|
||||||
<extensions>
|
|
||||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
</extensions>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
|
||||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272.1008616174.636088656" name="Android" parent="cdt.managedbuild.config.gnu.cross.exe.debug">
|
|
||||||
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272.1008616174.636088656." name="/" resourcePath="">
|
|
||||||
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1496829101" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
|
|
||||||
<option id="cdt.managedbuild.option.gnu.cross.prefix.1735944082" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-linux-androideabi-" valueType="string"/>
|
|
||||||
<option id="cdt.managedbuild.option.gnu.cross.path.1772057128" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="/home/xzl/soft/android-gcc/bin" valueType="string"/>
|
|
||||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1223698582" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
|
|
||||||
<builder arguments="-j8" buildPath="${workspace_loc:/streamPusher}/Debug" command="make" id="cdt.managedbuild.builder.gnu.cross.1084270303" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="cdt.managedbuild.builder.gnu.cross"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.compiler.1919121284" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
|
|
||||||
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.590633030" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.most" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.debugging.level.1265789766" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.dialect.std.912511938" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
|
|
||||||
<option id="gnu.c.compiler.option.misc.pic.42634984" name="Position Independent Code (-fPIC)" superClass="gnu.c.compiler.option.misc.pic" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.783534051" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.1754076712" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
|
|
||||||
<option id="gnu.cpp.compiler.option.optimization.level.844780393" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.debugging.level.1929172243" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.dialect.std.1056221099" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.c++1y" valueType="enumerated"/>
|
|
||||||
<option id="gnu.cpp.compiler.option.include.paths.1306233394" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
|
||||||
<listOptionValue builtIn="false" value="../src"/>
|
|
||||||
<listOptionValue builtIn="false" value="/home/xzl/soft/android-openssl/include"/>
|
|
||||||
<listOptionValue builtIn="false" value="../../ZLToolKit/src"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.compiler.option.preprocessor.def.677271031" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
|
|
||||||
<listOptionValue builtIn="false" value="ANDROID"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTSP2RTMP"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_RTMP2RTSP"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_HLS"/>
|
|
||||||
<listOptionValue builtIn="false" value="ENABLE_OPENSSL"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.compiler.option.other.pic.427492920" name="Position Independent Code (-fPIC)" superClass="gnu.cpp.compiler.option.other.pic" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1021305739" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1602894146" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker">
|
|
||||||
<option defaultValue="true" id="gnu.c.link.option.shared.662763664" name="Shared (-shared)" superClass="gnu.c.link.option.shared" valueType="boolean"/>
|
|
||||||
</tool>
|
|
||||||
<tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.300585526" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
|
|
||||||
<option id="gnu.cpp.link.option.paths.2028149580" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
|
|
||||||
<listOptionValue builtIn="false" value="../../ZLToolKit/Android"/>
|
|
||||||
<listOptionValue builtIn="false" value="/home/xzl/soft/android-openssl/lib"/>
|
|
||||||
</option>
|
|
||||||
<option id="gnu.cpp.link.option.libs.1919736544" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
|
|
||||||
<listOptionValue builtIn="false" value="ZLToolKit"/>
|
|
||||||
<listOptionValue builtIn="false" value="ssl"/>
|
|
||||||
<listOptionValue builtIn="false" value="crypto"/>
|
|
||||||
</option>
|
|
||||||
<option defaultValue="true" id="gnu.cpp.link.option.shared.791687128" name="Shared (-shared)" superClass="gnu.cpp.link.option.shared" useByScannerDiscovery="false" valueType="boolean"/>
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.2106177481" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
|
|
||||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
|
||||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
|
||||||
</inputType>
|
|
||||||
</tool>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.1774782901" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.1822549825" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
|
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1426105476" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
|
||||||
</tool>
|
|
||||||
</toolChain>
|
|
||||||
</folderInfo>
|
|
||||||
</configuration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
|
||||||
</cconfiguration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
|
||||||
<project id="streamPusher.cdt.managedbuild.target.gnu.cross.exe.434173064" name="Executable" projectType="cdt.managedbuild.target.gnu.cross.exe"/>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
|
||||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
|
||||||
<configuration configurationName="X64"/>
|
|
||||||
<configuration configurationName="WIN32">
|
|
||||||
<resource resourceType="PROJECT" workspacePath="/SMServer"/>
|
|
||||||
</configuration>
|
|
||||||
<configuration configurationName="ARM"/>
|
|
||||||
<configuration configurationName="Debug">
|
|
||||||
<resource resourceType="PROJECT" workspacePath="/streamPusher"/>
|
|
||||||
</configuration>
|
|
||||||
<configuration configurationName="MAC"/>
|
|
||||||
<configuration configurationName="Android"/>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
|
||||||
<storageModule moduleId="scannerConfiguration">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880;cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.;cdt.managedbuild.tool.gnu.cross.c.compiler.1525620747;cdt.managedbuild.tool.gnu.c.compiler.input.1391645717">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880;cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.;cdt.managedbuild.tool.gnu.c.compiler.base.1084336804;cdt.managedbuild.tool.gnu.c.compiler.input.1990378779">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880;cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1871589793;cdt.managedbuild.tool.gnu.cpp.compiler.input.237645072">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880;cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.;cdt.managedbuild.tool.gnu.cpp.compiler.base.1358852830;cdt.managedbuild.tool.gnu.cpp.compiler.input.280550491">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880;cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.;cdt.managedbuild.tool.gnu.cross.c.compiler.249358015;cdt.managedbuild.tool.gnu.c.compiler.input.886452886">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880;cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.;cdt.managedbuild.tool.gnu.cross.cpp.compiler.1903614826;cdt.managedbuild.tool.gnu.cpp.compiler.input.1655699253">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
|
||||||
</cproject>
|
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
*.pch
|
*.pch
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
# Compiled Dynamic libraries
|
||||||
*.dylib
|
#*.dylib
|
||||||
*.dll
|
#*.dll
|
||||||
|
|
||||||
# Fortran module files
|
# Fortran module files
|
||||||
*.mod
|
*.mod
|
||||||
|
|
@ -23,7 +23,14 @@
|
||||||
*.lib
|
*.lib
|
||||||
|
|
||||||
# Executables
|
# Executables
|
||||||
*.exe
|
#*.exe
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
/X64/
|
/X64/
|
||||||
|
|
||||||
|
|
||||||
|
*.DS_Store
|
||||||
|
|
||||||
|
/cmake-build-debug/
|
||||||
|
/.idea/
|
||||||
|
/c_wrapper/.idea/
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "ZLToolKit"]
|
||||||
|
path = ZLToolKit
|
||||||
|
url = https://github.com/xiongziliang/ZLToolKit.git
|
||||||
27
.project
27
.project
|
|
@ -1,27 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>ZLMediaKit</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
|
||||||
<triggers>clean,full,incremental,</triggers>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
|
||||||
<triggers>full,incremental,</triggers>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
|
||||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
|
||||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
|
||||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<project>
|
|
||||||
<configuration id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1947026272" name="ARM">
|
|
||||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
|
||||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
|
||||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
|
||||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
|
||||||
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="689079599215608580" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
|
||||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
|
||||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
|
||||||
</provider>
|
|
||||||
</extension>
|
|
||||||
</configuration>
|
|
||||||
<configuration id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1912216574" name="X64">
|
|
||||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
|
||||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
|
||||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
|
||||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
|
||||||
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-1840963814096503342" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
|
||||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
|
||||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
|
||||||
</provider>
|
|
||||||
</extension>
|
|
||||||
</configuration>
|
|
||||||
<configuration id="cdt.managedbuild.config.gnu.cross.exe.debug.1307511880.1508415929" name="WIN32">
|
|
||||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
|
||||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
|
||||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
|
||||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
|
||||||
<provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorCygwin" console="false" env-hash="-541370470256839216" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorCygwin" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings Cygwin" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
|
||||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
|
||||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
|
||||||
</provider>
|
|
||||||
</extension>
|
|
||||||
</configuration>
|
|
||||||
</project>
|
|
||||||
|
|
@ -2,7 +2,7 @@ language: cpp
|
||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: trusty
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- clang
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
script:
|
script:
|
||||||
|
|
|
||||||
155
CMakeLists.txt
155
CMakeLists.txt
|
|
@ -1,5 +1,7 @@
|
||||||
project(ZLMediaKit)
|
project(ZLMediaKit)
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 3.1.3)
|
||||||
|
#使能c++11
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
#加载自定义模块
|
#加载自定义模块
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
|
|
@ -7,114 +9,91 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||||
#设置可执行程序路径
|
#设置可执行程序路径
|
||||||
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||||
#设置子目录
|
|
||||||
set(SUB_DIR_LIST "Codec" "Common" "Device" "H264" "Http" "MediaFile" "Player" "Rtmp" "RTP" "Rtsp" "Shell" )
|
|
||||||
|
|
||||||
foreach(SUB_DIR ${SUB_DIR_LIST})
|
#设置工程源码根目录
|
||||||
#遍历源文件
|
set(ToolKit_Root ${CMAKE_SOURCE_DIR}/ZLToolKit/src)
|
||||||
aux_source_directory(src/${SUB_DIR} SRC_LIST)
|
set(MediaKit_Root ${CMAKE_SOURCE_DIR}/src)
|
||||||
#创建头文件安装文件夹
|
|
||||||
execute_process(COMMAND mkdir -p ${PROJECT_BINARY_DIR}/include/${CMAKE_PROJECT_NAME}/${SUB_DIR}/ )
|
|
||||||
#遍历头文件
|
|
||||||
file(GLOB_RECURSE HEADER_FILES "${PROJECT_SOURCE_DIR}/src/${SUB_DIR}/*.h")
|
|
||||||
#拷贝头文件至安装文件夹
|
|
||||||
execute_process(COMMAND cp ${HEADER_FILES} ${PROJECT_BINARY_DIR}/include/${CMAKE_PROJECT_NAME}/${SUB_DIR}/ )
|
|
||||||
endforeach(SUB_DIR ${SUB_DIR_LIST})
|
|
||||||
|
|
||||||
set(LINK_LIB_LIST)
|
#设置头文件目录
|
||||||
|
INCLUDE_DIRECTORIES(${ToolKit_Root})
|
||||||
|
INCLUDE_DIRECTORIES(${MediaKit_Root})
|
||||||
|
|
||||||
|
#收集源代码
|
||||||
|
file(GLOB ToolKit_src_list ${ToolKit_Root}/*/*.cpp ${ToolKit_Root}/*/*.h ${ToolKit_Root}/*/*.c)
|
||||||
|
file(GLOB MediaKit_src_list ${MediaKit_Root}/*/*.cpp ${MediaKit_Root}/*/*.h ${MediaKit_Root}/*/*.c)
|
||||||
|
|
||||||
|
#去除win32的适配代码
|
||||||
|
if (NOT WIN32)
|
||||||
|
list(REMOVE_ITEM ToolKit_src_list ${ToolKit_Root}/win32/getopt.c)
|
||||||
|
else()
|
||||||
|
#防止Windows.h包含Winsock.h
|
||||||
|
add_definitions(-DWIN32_LEAN_AND_MEAN -DMP4V2_NO_STDINT_DEFS)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#添加两个静态库
|
||||||
|
set(LINK_LIB_LIST zlmediakit zltoolkit)
|
||||||
|
|
||||||
#查找openssl是否安装
|
#查找openssl是否安装
|
||||||
find_package(OpenSSL QUIET)
|
find_package(OpenSSL QUIET)
|
||||||
if(OPENSSL_FOUND)
|
if (OPENSSL_FOUND)
|
||||||
message(STATUS "找到openssl库:\"${OPENSSL_INCLUDE_DIR}\",ENABLE_OPENSSL宏已打开")
|
message(STATUS "found openssl library\"${OPENSSL_INCLUDE_DIR}\",ENABLE_OPENSSL enabled")
|
||||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||||
add_definitions(-DENABLE_OPENSSL)
|
add_definitions(-DENABLE_OPENSSL)
|
||||||
list(APPEND LINK_LIB_LIST ${OPENSSL_LIBRARIES})
|
list(APPEND LINK_LIB_LIST ${OPENSSL_LIBRARIES})
|
||||||
endif(OPENSSL_FOUND)
|
endif (OPENSSL_FOUND)
|
||||||
|
|
||||||
#查找mysql是否安装
|
#查找mysql是否安装
|
||||||
find_package(MYSQL QUIET)
|
find_package(MYSQL QUIET)
|
||||||
if(MYSQL_FOUND)
|
if (MYSQL_FOUND)
|
||||||
message(STATUS "找到mysqlclient库:\"${MYSQL_INCLUDE_DIR}\",ENABLE_MYSQL宏已打开")
|
message(STATUS "found mysqlclient library\"${MYSQL_INCLUDE_DIR}\",ENABLE_MYSQL enabled")
|
||||||
include_directories(${MYSQL_INCLUDE_DIR})
|
include_directories(${MYSQL_INCLUDE_DIR})
|
||||||
add_definitions(-DENABLE_MYSQL)
|
add_definitions(-DENABLE_MYSQL)
|
||||||
list(APPEND LINK_LIB_LIST ${MYSQL_LIBRARIES})
|
list(APPEND LINK_LIB_LIST ${MYSQL_LIBRARIES})
|
||||||
endif(MYSQL_FOUND)
|
endif (MYSQL_FOUND)
|
||||||
|
|
||||||
|
#查找MP4V2是否安装
|
||||||
#查找mp4v2是否安装
|
|
||||||
find_package(MP4V2 QUIET)
|
find_package(MP4V2 QUIET)
|
||||||
if(MP4V2_FOUND)
|
if (MP4V2_FOUND)
|
||||||
message(STATUS "找到mp4v2库:\"${MP4V2_INCLUDE_DIR}\",ENABLE_MP4V2宏已打开")
|
include_directories(${MP4V2_INCLUDE_DIR})
|
||||||
include_directories(${MP4V2_INCLUDE_DIR})
|
list(APPEND LINK_LIB_LIST ${MP4V2_LIBRARY})
|
||||||
add_definitions(-DENABLE_MP4V2)
|
add_definitions(-DENABLE_MP4V2)
|
||||||
list(APPEND LINK_LIB_LIST ${MP4V2_LIBRARIES})
|
message(STATUS "found MP4V2:${MP4V2_INCLUDE_DIR},${MP4V2_LIBRARY}")
|
||||||
endif(MP4V2_FOUND)
|
endif (MP4V2_FOUND)
|
||||||
|
|
||||||
#查找x264是否安装
|
#查找x264是否安装
|
||||||
find_package(X264 QUIET)
|
find_package(X264 QUIET)
|
||||||
if(X264_FOUND)
|
if (X264_FOUND)
|
||||||
message(STATUS "找到x264库:\"${X264_INCLUDE_DIR}\",ENABLE_X264宏已打开")
|
message(STATUS "found x264 library\"${X264_INCLUDE_DIRS}\",ENABLE_X264 enabled")
|
||||||
include_directories(${X264_INCLUDE_DIRS})
|
include_directories(${X264_INCLUDE_DIRS})
|
||||||
add_definitions(-DENABLE_X264)
|
add_definitions(-DENABLE_X264)
|
||||||
list(APPEND LINK_LIB_LIST ${X264_LIBRARIES})
|
list(APPEND LINK_LIB_LIST ${X264_LIBRARIES})
|
||||||
endif(X264_FOUND)
|
endif ()
|
||||||
|
|
||||||
#查找faac是否安装
|
#查找faac是否安装
|
||||||
find_package(FAAC QUIET)
|
find_package(FAAC QUIET)
|
||||||
if(FAAC_FOUND)
|
if (FAAC_FOUND)
|
||||||
message(STATUS "找到faac库:\"${FAAC_INCLUDE_DIR}\",ENABLE_FAAC宏已打开")
|
message(STATUS "found faac library\"${FAAC_INCLUDE_DIR}\",ENABLE_FAAC enabled")
|
||||||
include_directories(${FAAC_INCLUDE_DIR})
|
include_directories(${FAAC_INCLUDE_DIR})
|
||||||
add_definitions(-DENABLE_FAAC)
|
add_definitions(-DENABLE_FAAC)
|
||||||
list(APPEND LINK_LIB_LIST ${FAAC_LIBRARIES})
|
list(APPEND LINK_LIB_LIST ${FAAC_LIBRARIES})
|
||||||
endif(FAAC_FOUND)
|
endif ()
|
||||||
|
|
||||||
#查找ZLToolKit是否安装
|
#使能GOP缓存
|
||||||
find_package(ZLTOOLKIT QUIET)
|
add_definitions(-DENABLE_RING_USEBUF)
|
||||||
if(ZLTOOLKIT_FOUND)
|
#添加库
|
||||||
message(STATUS "找到ZLToolKit库:\"${ZLTOOLKIT_INCLUDE_DIR}\"")
|
add_library(zltoolkit STATIC ${ToolKit_src_list})
|
||||||
include_directories(${ZLTOOLKIT_INCLUDE_DIR}/ZLToolKit)
|
add_library(zlmediakit STATIC ${MediaKit_src_list})
|
||||||
list(APPEND LINK_LIB_LIST ${ZLTOOLKIT_LIBRARIES})
|
|
||||||
endif(ZLTOOLKIT_FOUND)
|
|
||||||
|
|
||||||
#打印库文件
|
if (WIN32)
|
||||||
message(STATUS "将链接依赖库:${LINK_LIB_LIST}")
|
list(APPEND LINK_LIB_LIST WS2_32 Iphlpapi shlwapi)
|
||||||
#开启RTSP/RTMP之间的互相转换,开启HLS
|
elseif(NOT ANDROID OR IOS)
|
||||||
add_definitions(-DENABLE_RTMP2RTSP -DENABLE_RTSP2RTMP -DENABLE_HLS)
|
list(APPEND LINK_LIB_LIST pthread)
|
||||||
|
endif ()
|
||||||
|
|
||||||
#引用头文件路径
|
message(STATUS "linked libraries:${LINK_LIB_LIST}")
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
|
||||||
|
|
||||||
#使能c++11
|
|
||||||
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
|
|
||||||
|
|
||||||
#关闭过期接口警告
|
|
||||||
add_compile_options(-Wno-deprecated-declarations)
|
|
||||||
#关闭__FUNCTION__宏在函数外警告
|
|
||||||
add_compile_options(-Wno-predefined-identifier-outside-function)
|
|
||||||
|
|
||||||
#编译动态库
|
|
||||||
if(NOT IOS AND NOT ANDROID)
|
|
||||||
add_library(${CMAKE_PROJECT_NAME}_shared SHARED ${SRC_LIST})
|
|
||||||
set_target_properties(${CMAKE_PROJECT_NAME}_shared PROPERTIES OUTPUT_NAME "${CMAKE_PROJECT_NAME}")
|
|
||||||
install(TARGETS ${CMAKE_PROJECT_NAME}_shared LIBRARY DESTINATION lib)
|
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME}_shared ${LINK_LIB_LIST})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#编译静态库
|
|
||||||
add_library(${CMAKE_PROJECT_NAME}_static STATIC ${SRC_LIST})
|
|
||||||
set_target_properties(${CMAKE_PROJECT_NAME}_static PROPERTIES OUTPUT_NAME "${CMAKE_PROJECT_NAME}")
|
|
||||||
install(TARGETS ${CMAKE_PROJECT_NAME}_static ARCHIVE DESTINATION lib)
|
|
||||||
|
|
||||||
#安装头文件至系统目录
|
|
||||||
install(DIRECTORY ${PROJECT_BINARY_DIR}/include/${CMAKE_PROJECT_NAME} DESTINATION include)
|
|
||||||
|
|
||||||
#测试程序
|
#测试程序
|
||||||
if(NOT IOS)
|
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
else(NOT IOS)
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/../ZLToolKit/src)
|
|
||||||
endif(NOT IOS)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 xiongziliang
|
Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
176
README.md
176
README.md
|
|
@ -1,47 +1,70 @@
|
||||||
# 一个基于C++11简单易用的轻量级流媒体库
|
# 一个基于C++11的高性能运营级流媒体服务框架
|
||||||
平台|编译状态
|
[](https://travis-ci.org/xiongziliang/ZLMediaKit)
|
||||||
----|-------
|
|
||||||
Linux | [](https://travis-ci.org/xiongziliang/ZLMediaKit)
|
|
||||||
macOS | [](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_mac)
|
|
||||||
iOS | [](https://travis-ci.org/xiongziliang/ZLMediaKit-build_for_ios)
|
|
||||||
Android | [](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_android)
|
|
||||||
|
|
||||||
## 项目特点
|
## 项目特点
|
||||||
- 基于C++11开发,避免使用裸指针,代码稳定可靠;同时跨平台移植简单方便,代码清晰简洁。
|
- 基于C++11开发,避免使用裸指针,代码稳定可靠;同时跨平台移植简单方便,代码清晰简洁。
|
||||||
- 打包多种流媒体协议(RTSP/RTMP/HLS),支持协议间的互相转换,提供一站式的服务。
|
- 打包多种流媒体协议(RTSP/RTMP/HLS),支持协议间的互相转换,提供一站式的服务。
|
||||||
- 使用epoll+线程池+异步网络IO模式开发,并发性能优越。
|
- 使用epoll+线程池+异步网络IO模式开发,并发性能优越。
|
||||||
- 只实现主流的的H264+AAC流媒体方案,代码精简,脉络清晰,适合学习。
|
- 已实现主流的的H264+AAC流媒体方案,代码精简,脉络清晰,适合学习。
|
||||||
|
- 编码格式与框架代码解耦,方便自由简洁的添加支持其他编码格式
|
||||||
|
- 代码经过大量的稳定性、性能测试,可满足商用服务器项目。
|
||||||
|
- 支持linux、macos、ios、android、windows平台
|
||||||
|
|
||||||
|
## 项目定位
|
||||||
|
- 移动嵌入式跨平台流媒体解决方案。
|
||||||
|
- 商用级流媒体服务器。
|
||||||
|
- 网络编程二次开发SDK。
|
||||||
|
|
||||||
|
|
||||||
## 功能清单
|
## 功能清单
|
||||||
- RTSP
|
- RTSP
|
||||||
- RTSP 服务器,支持RTMP/MP4转RTSP。
|
- RTSP 服务器,支持RTMP/MP4转RTSP。
|
||||||
- RTSP 播放器,支持RTSP代理。
|
- RTSP 播放器,支持RTSP代理,支持生成静音音频
|
||||||
- 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播` 四种RTP传输方式 。
|
- 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播` 四种RTP传输方式 。
|
||||||
|
- 服务器/客户端完整支持Basic/Digest方式的登录鉴权,全异步可配置化的鉴权接口。
|
||||||
|
- 支持H265编码
|
||||||
|
|
||||||
- RTMP
|
- RTMP
|
||||||
- RTMP 播放服务器,支持RTSP/MP4转RTMP。
|
- RTMP 播放服务器,支持RTSP/MP4转RTMP。
|
||||||
- RTMP 发布服务器,支持录制发布流。
|
- RTMP 发布服务器,支持录制发布流。
|
||||||
- RTMP 播放器,支持RTMP代理。
|
- RTMP 播放器,支持RTMP代理,支持生成静音音频
|
||||||
- RTMP 推流客户端。
|
- RTMP 推流客户端。
|
||||||
|
- 支持http-flv直播。
|
||||||
|
- 支持https-flv直播。
|
||||||
|
|
||||||
- HLS
|
- HLS
|
||||||
- 支持HLS文件生成,自带HTTP文件服务器。
|
- 支持HLS文件生成,自带HTTP文件服务器。
|
||||||
|
|
||||||
- HTTP[S]
|
- HTTP[S]
|
||||||
- 服务器支持`目录索引生成`,`文件下载`,`表单提交请求`。
|
- 服务器支持`目录索引生成`,`文件下载`,`表单提交请求`。
|
||||||
- 客户端提供`文件下载器(支持断点续传)`,`接口请求器`。
|
- 客户端提供`文件下载器(支持断点续传)`,`接口请求器`,`文件上传器`。
|
||||||
|
- 完整HTTP API服务器,可以作为web后台开发框架。
|
||||||
|
- 支持跨域访问。
|
||||||
|
- 客户端支持cookie
|
||||||
|
- 支持WebSocket服务器
|
||||||
|
|
||||||
- 其他
|
- 其他
|
||||||
- 支持输入YUV+PCM自动生成RTSP/RTMP/HLS/MP4.
|
- 支持输入YUV+PCM自动生成RTSP/RTMP/HLS/MP4.
|
||||||
- 支持简单的telnet调试。
|
- 支持简单的telnet调试。
|
||||||
- 支持H264的解析,支持B帧的POC计算排序。
|
- 支持H264的解析,支持B帧的POC计算排序。
|
||||||
|
- 支持配置文件热加载
|
||||||
|
- 支持流量统计、推流播放鉴权等事件
|
||||||
|
- 支持rtsp/rtmp/http虚拟主机
|
||||||
|
- 支持flv、mp4文件录制
|
||||||
|
- 支持rtps/rtmp点播,支持seek
|
||||||
|
|
||||||
|
|
||||||
## 后续任务
|
## 后续任务
|
||||||
- 提供更多的示例代码
|
- 完善支持H265
|
||||||
|
- 添加rtsp推流功能
|
||||||
|
|
||||||
|
## 编译要求
|
||||||
|
- 编译器支持C++11,GCC4.8/Clang3.3/VC2015或以上
|
||||||
|
- cmake3.2或以上
|
||||||
|
|
||||||
## 编译(Linux)
|
## 编译(Linux)
|
||||||
- 我的编译环境
|
- 我的编译环境
|
||||||
- Ubuntu16.04 64 bit + gcc5.4(最低gcc4.7)
|
- Ubuntu16.04 64 bit + gcc5.4
|
||||||
- cmake 3.5.1
|
- cmake 3.5.1
|
||||||
- 编译
|
- 编译
|
||||||
|
|
||||||
|
|
@ -93,39 +116,63 @@ Android | [
|
||||||
|
- 我的编译环境
|
||||||
|
- windows 10
|
||||||
|
- visual studio 2017
|
||||||
|
- [cmake-gui](https://cmake.org/files/v3.10/cmake-3.10.0-rc1-win32-x86.msi)
|
||||||
|
|
||||||
|
- 编译
|
||||||
|
```
|
||||||
|
1 进入ZLMediaKit目录执行 git submodule update --init 以下载ZLToolKit的代码
|
||||||
|
2 使用cmake-gui打开工程并生成vs工程文件.
|
||||||
|
3 找到工程文件(ZLMediaKit.sln),双击用vs2017打开.
|
||||||
|
4 选择编译Release 版本.
|
||||||
|
5 找到目标文件并运行测试用例.
|
||||||
|
```
|
||||||
## 使用方法
|
## 使用方法
|
||||||
- 作为服务器:
|
- 作为服务器:
|
||||||
```
|
```
|
||||||
TcpServer<RtspSession>::Ptr rtspSrv(new TcpServer<RtspSession>());
|
TcpServer::Ptr rtspSrv(new TcpServer());
|
||||||
TcpServer<RtmpSession>::Ptr rtmpSrv(new TcpServer<RtmpSession>());
|
TcpServer::Ptr rtmpSrv(new TcpServer());
|
||||||
TcpServer<HttpSession>::Ptr httpSrv(new TcpServer<HttpSession>());
|
TcpServer::Ptr httpSrv(new TcpServer());
|
||||||
TcpServer<HttpsSession>::Ptr httpsSrv(new TcpServer<HttpsSession>());
|
TcpServer::Ptr httpsSrv(new TcpServer());
|
||||||
|
|
||||||
rtspSrv->start(mINI::Instance()[Config::Rtsp::kPort]);
|
rtspSrv->start<RtspSession>(mINI::Instance()[Config::Rtsp::kPort]);
|
||||||
rtmpSrv->start(mINI::Instance()[Config::Rtmp::kPort]);
|
rtmpSrv->start<RtmpSession>(mINI::Instance()[Config::Rtmp::kPort]);
|
||||||
httpSrv->start(mINI::Instance()[Config::Http::kPort]);
|
httpSrv->start<HttpSession>(mINI::Instance()[Config::Http::kPort]);
|
||||||
httpsSrv->start(mINI::Instance()[Config::Http::kSSLPort]);
|
httpsSrv->start<HttpsSession>(mINI::Instance()[Config::Http::kSSLPort]);
|
||||||
EventPoller::Instance().runLoop();
|
EventPoller::Instance().runLoop();
|
||||||
```
|
```
|
||||||
|
|
||||||
- 作为播放器:
|
- 作为播放器:
|
||||||
```
|
```
|
||||||
MediaPlayer::Ptr player(new MediaPlayer());
|
MediaPlayer::Ptr player(new MediaPlayer());
|
||||||
player->setOnPlayResult([](const SockException &ex) {
|
weak_ptr<MediaPlayer> weakPlayer = player;
|
||||||
|
player->setOnPlayResult([weakPlayer](const SockException &ex) {
|
||||||
InfoL << "OnPlayResult:" << ex.what();
|
InfoL << "OnPlayResult:" << ex.what();
|
||||||
|
auto strongPlayer = weakPlayer.lock();
|
||||||
|
if (ex || !strongPlayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto viedoTrack = strongPlayer->getTrack(TrackVideo);
|
||||||
|
if (!viedoTrack) {
|
||||||
|
WarnL << "没有视频Track!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
viedoTrack->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([](const Frame::Ptr &frame) {
|
||||||
|
//此处解码并播放
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
player->setOnShutdown([](const SockException &ex) {
|
player->setOnShutdown([](const SockException &ex) {
|
||||||
ErrorL << "OnShutdown:" << ex.what();
|
ErrorL << "OnShutdown:" << ex.what();
|
||||||
});
|
});
|
||||||
player->setOnVideoCB([&](const H264Frame &frame){
|
|
||||||
//在这里解码H264并显示
|
|
||||||
});
|
|
||||||
player->setOnAudioCB([&](const AdtsFrame &frame){
|
|
||||||
//在这里解码AAC并播放
|
|
||||||
});
|
|
||||||
//支持rtmp、rtsp
|
//支持rtmp、rtsp
|
||||||
player->play("rtsp://192.168.0.122/","admin","123456",PlayerBase::RTP_TCP);
|
(*player)[RtspPlayer::kRtpType] = PlayerBase::RTP_TCP;
|
||||||
EventPoller::Instance().runLoop();
|
player->play("rtsp://admin:jzan123456@192.168.0.122/");
|
||||||
```
|
```
|
||||||
- 作为代理服务器:
|
- 作为代理服务器:
|
||||||
```
|
```
|
||||||
|
|
@ -173,41 +220,11 @@ Android | [.runLoop();
|
EventPoller::Instance().runLoop();
|
||||||
```
|
```
|
||||||
## QA
|
## QA
|
||||||
- 为什么VLC播放一段时间就停止了?
|
|
||||||
|
|
||||||
由于ZLMediaKit在实现RTSP协议时,采用OPTIONS命令作为心跳包(在RTP over UDP时有效),如果播放器不持续发送OPTIONS指令,那么ZLMediaKit会断开连接。如果你要用第三方播放器测试,你可以改RTP over TCP方式或者修改ZLMediaKit的源码,修改位置位置为src/Rtsp/RtspSession.cpp RtspSession::onManager函数,修改成如下所示:
|
|
||||||
```
|
|
||||||
void RtspSession::onManager() {
|
|
||||||
if (m_ticker.createdTime() > 10 * 1000) {
|
|
||||||
if (m_strSession.size() == 0) {
|
|
||||||
WarnL << "非法链接:" << getPeerIp();
|
|
||||||
shutdown();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_bListenPeerUdpPort) {
|
|
||||||
UDPServer::Instance().stopListenPeer(getPeerIp().data(), this);
|
|
||||||
m_bListenPeerUdpPort = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*if (m_rtpType != PlayerBase::RTP_TCP && m_ticker.elapsedTime() > 15 * 1000) {
|
|
||||||
WarnL << "RTSP会话超时:" << getPeerIp();
|
|
||||||
shutdown();
|
|
||||||
return;
|
|
||||||
/*}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- 怎么测试服务器性能?
|
- 怎么测试服务器性能?
|
||||||
|
|
||||||
ZLMediaKit提供了测试性能的示例,代码在tests/test_benchmark.cpp。由于ZLToolKit默认关闭了tcp客户端多线程的支持,如果需要提高测试并发量,需要在编译ZLToolKit时启用ENABLE_ASNC_TCP_CLIENT宏,具体操作如下:
|
ZLMediaKit提供了测试性能的示例,代码在tests/test_benchmark.cpp。
|
||||||
```
|
|
||||||
#编译ZLToolKit
|
这里是测试报告:[benchmark.md](https://github.com/xiongziliang/ZLMediaKit/blob/master/benchmark.md)
|
||||||
cd ZLToolKit
|
|
||||||
mkdir -p build
|
|
||||||
cd build -DENABLE_ASNC_TCP_CLIENT
|
|
||||||
cmake ..
|
|
||||||
make -j4
|
|
||||||
sudo make install
|
|
||||||
```
|
|
||||||
|
|
||||||
- github下载太慢了,有其他下载方式吗?
|
- github下载太慢了,有其他下载方式吗?
|
||||||
|
|
||||||
|
|
@ -218,7 +235,34 @@ Android | [
|
[ZLMediaKit](http://git.oschina.net/xiahcu/ZLMediaKit)
|
||||||
|
|
||||||
|
|
||||||
## 联系方式
|
- 在windows下编译很多错误?
|
||||||
- 邮箱:<771730766@qq.com>
|
|
||||||
- QQ群:542509000
|
由于本项目主体代码在macOS/linux下开发,部分源码采用的是无bom头的UTF-8编码;由于windows对于utf-8支持不甚友好,所以如果发现编译错误请先尝试添 加bom头再编译。
|
||||||
|
|
||||||
|
## 参考案例
|
||||||
|
- [IOS摄像头实时录制,生成rtsp/rtmp/hls/http-flv](https://gitee.com/xiahcu/IOSMedia)
|
||||||
|
- [IOS rtmp/rtsp播放器,视频推流器](https://gitee.com/xiahcu/IOSPlayer)
|
||||||
|
- [支持linux、windows、mac的rtmp/rtsp播放器](https://github.com/xiongziliang/ZLMediaPlayer)
|
||||||
|
|
||||||
|
上述工程可能在最新的代码的情况下编译不过,请手动修改
|
||||||
|
|
||||||
|
|
||||||
|
## 授权协议
|
||||||
|
|
||||||
|
本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。
|
||||||
|
但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除;
|
||||||
|
由于使用本项目而产生的商业纠纷或侵权行为一概与本项项目及开发者无关,请自行承担法律风险。
|
||||||
|
|
||||||
|
## 联系方式
|
||||||
|
- 邮箱:<771730766@qq.com>
|
||||||
|
- QQ群:542509000
|
||||||
|
|
||||||
|
## 捐赠
|
||||||
|
如果本项目能切实帮助您减少重复开发的工作量,您可以在自愿的基础上支持下作者,谢谢!
|
||||||
|
|
||||||
|
[支付宝](https://raw.githubusercontent.com/xiongziliang/other/master/IMG_3919.JPG)
|
||||||
|
|
||||||
|
[微信](https://raw.githubusercontent.com/xiongziliang/other/master/IMG_3920.JPG)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 666eb9ba01939f739bf145abc5f02539ca2b9c97
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
theme: jekyll-theme-cayman
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
# 测试环境
|
||||||
|
- 系统:centos6.8 64bit
|
||||||
|
- 内存:8GB
|
||||||
|
- CPU:Intel(R) Xeon(R) CPU E3-1220 v5 @ 3.00GHz;4核
|
||||||
|
- 网络:千兆网卡
|
||||||
|
- 测试端环境跟服务端一致(同一千兆局域网内)
|
||||||
|
|
||||||
|
# 测试工具
|
||||||
|
ZLMeidaKit自带测试程序test_benchmark,其为单进程模型;
|
||||||
|
请在编译ZLToolKit时打开宏`ENABLE_ASNC_TCP_CLIENT`,否则测试程序是单线程模型;将影响测试端性能。
|
||||||
|
|
||||||
|
# 测试服务器
|
||||||
|
ZLMeidaKit自带测试服务器test_server,支持RTSP/RTMP/HLS服务器;多线程模型。
|
||||||
|
|
||||||
|
# 测试媒体流
|
||||||
|
使用test_server拉取的rtmp流`rtmp://live.hkstv.hk.lxdns.com/live/hks`;然后通过test_server转发代理。
|
||||||
|
该码流大概300~400Kbit/s左右。
|
||||||
|
|
||||||
|
# 测试结果
|
||||||
|
|
||||||
|
说明:在cmake构建时,输入`cmake .. -DCMKAE_BUILD_TYPE=Release`以编译优化版本。
|
||||||
|
|
||||||
|
| 播放器个数(rtmp) | CPU(最大400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| 1000 | 35% | 582M/14M | 43.11 MByte/s | 无 |
|
||||||
|
| 2000 | 65% | 584M/20M | 84.88 MByte/s | 无 |
|
||||||
|
|
||||||
|
| 播放器个数(rtsp/tcp) | CPU(最大400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| 1000 | 42% | 582M/12M | 43.10 MByte/s| 无 |
|
||||||
|
| 2000 | 80% | 584M/17M | 85.97 MByte/s | 无 |
|
||||||
|
|
||||||
|
# srs性能对比
|
||||||
|
| 播放器个数(rtmp) | CPU(最大400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| 1000 | 10% | 310M/53M | 41.17 MByte/s | 无 |
|
||||||
|
| 2000 | 18% | 604M/117M | 83.86 MByte/s | 无 |
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
path=`pwd`
|
|
||||||
wget https://raw.githubusercontent.com/xiongziliang/ZLToolKit/master/build_for_android.sh -O toolkit_build.sh
|
|
||||||
sudo chmod +x ./toolkit_build.sh
|
|
||||||
./toolkit_build.sh
|
|
||||||
cd $path
|
|
||||||
cd ..
|
cd ..
|
||||||
git clone --depth=50 https://github.com/xiongziliang/ZLMediaKit.git
|
git clone --depth=1 https://github.com/xiongziliang/ZLMediaKit.git
|
||||||
cd ZLMediaKit
|
cd ZLMediaKit
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
|
||||||
mkdir -p android_build
|
mkdir -p android_build
|
||||||
|
rm -rf ./build
|
||||||
|
ln -s ./android_build build
|
||||||
cd android_build
|
cd android_build
|
||||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK_ROOT -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi" -DANDROID_NATIVE_API_LEVEL=android-9
|
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK_ROOT -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi" -DANDROID_NATIVE_API_LEVEL=android-9
|
||||||
make -j4
|
make -j4
|
||||||
sudo make install
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
path=`pwd`
|
|
||||||
wget https://raw.githubusercontent.com/xiongziliang/ZLToolKit/master/build_for_ios.sh -O toolkit_build.sh
|
|
||||||
sudo chmod +x ./toolkit_build.sh
|
|
||||||
./toolkit_build.sh
|
|
||||||
cd $path
|
|
||||||
cd ..
|
cd ..
|
||||||
git clone --depth=50 https://github.com/xiongziliang/ZLMediaKit.git
|
git clone --depth=1 https://github.com/xiongziliang/ZLMediaKit.git
|
||||||
cd ZLMediaKit
|
cd ZLMediaKit
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
|
||||||
mkdir -p ios_build
|
mkdir -p ios_build
|
||||||
|
rm -rf ./build
|
||||||
|
ln -s ./ios_build build
|
||||||
cd ios_build
|
cd ios_build
|
||||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/iOS.cmake -DIOS_PLATFORM=OS
|
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/iOS.cmake -DIOS_PLATFORM=OS
|
||||||
make -j4
|
make -j4
|
||||||
sudo make install
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,24 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
path=`pwd`
|
cd ..
|
||||||
wget https://raw.githubusercontent.com/xiongziliang/ZLToolKit/master/build_for_linux.sh -O ./toolkit_build.sh
|
git clone --depth=1 https://github.com/xiongziliang/ZLMediaKit.git
|
||||||
sudo chmod +x ./toolkit_build.sh
|
cd ZLMediaKit
|
||||||
./toolkit_build.sh
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
|
||||||
|
sudo apt-get install cmake
|
||||||
|
sudo apt-get install libmysqlclient-dev
|
||||||
|
sudo apt-get install libssl-dev
|
||||||
sudo apt-get install libx264-dev
|
sudo apt-get install libx264-dev
|
||||||
sudo apt-get install libfaac-dev
|
sudo apt-get install libfaac-dev
|
||||||
sudo apt-get install libmp4v2-dev
|
sudo apt-get install libmp4v2-dev
|
||||||
#sudo apt-get install libsdl-dev
|
#sudo apt-get install libsdl-dev
|
||||||
#sudo apt-get install libavcodec-dev
|
#sudo apt-get install libavcodec-dev
|
||||||
#sudo apt-get install libavutil-dev
|
#sudo apt-get install libavutil-dev
|
||||||
cd $path
|
|
||||||
cd ..
|
|
||||||
git clone --depth=50 https://github.com/xiongziliang/ZLMediaKit.git
|
|
||||||
cd ZLMediaKit
|
|
||||||
mkdir -p linux_build
|
mkdir -p linux_build
|
||||||
|
rm -rf ./build
|
||||||
|
ln -s ./linux_build build
|
||||||
cd linux_build
|
cd linux_build
|
||||||
|
|
||||||
cmake ..
|
cmake ..
|
||||||
make -j4
|
make -j4
|
||||||
sudo make install
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
path=`pwd`
|
cd ..
|
||||||
wget https://raw.githubusercontent.com/xiongziliang/ZLToolKit/master/build_for_mac.sh -O toolkit_build.sh
|
git clone --depth=1 https://github.com/xiongziliang/ZLMediaKit.git
|
||||||
sudo chmod +x ./toolkit_build.sh
|
cd ZLMediaKit
|
||||||
./toolkit_build.sh
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
|
||||||
|
brew install cmake
|
||||||
|
brew install mysql
|
||||||
|
brew install openssl
|
||||||
brew install x264
|
brew install x264
|
||||||
brew install faac
|
brew install faac
|
||||||
brew install mp4v2
|
brew install mp4v2
|
||||||
brew install sdl
|
brew install sdl
|
||||||
brew install ffmpeg
|
brew install ffmpeg
|
||||||
cd $path
|
|
||||||
cd ..
|
|
||||||
git clone --depth=50 https://github.com/xiongziliang/ZLMediaKit.git
|
|
||||||
cd ZLMediaKit
|
|
||||||
mkdir -p mac_build
|
mkdir -p mac_build
|
||||||
|
rm -rf ./build
|
||||||
|
ln -s ./mac_build build
|
||||||
cd mac_build
|
cd mac_build
|
||||||
cmake .. -DOPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2j/
|
cmake .. -DOPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2j/
|
||||||
make -j4
|
make -j4
|
||||||
sudo make install
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
MediaKitWrapper
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/c_wrapper.iml" filepath="$PROJECT_DIR$/.idea/c_wrapper.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,524 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true" buildAllGenerated="true">
|
||||||
|
<generated>
|
||||||
|
<config projectName="MediaKitWrapper" targetName="MediaKitWrapper_static" />
|
||||||
|
<config projectName="MediaKitWrapper" targetName="test_all" />
|
||||||
|
<config projectName="MediaKitWrapper" targetName="MediaKitWrapper_shared" />
|
||||||
|
</generated>
|
||||||
|
</component>
|
||||||
|
<component name="CMakeSettings" ADDITIONAL_BUILD_OPTIONS="-j4">
|
||||||
|
<configurations>
|
||||||
|
<configuration CONFIG_NAME="Debug" GENERATION_OPTIONS="-DOPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2j/" />
|
||||||
|
</configurations>
|
||||||
|
</component>
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="db5167c7-a7f4-4c11-a19e-0c6c8a7b66f1" name="Default" comment="" />
|
||||||
|
<ignored path="$PROJECT_DIR$/cmake-build-debug/" />
|
||||||
|
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||||
|
<option name="TRACKING_ENABLED" value="true" />
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="FileEditorManager">
|
||||||
|
<leaf>
|
||||||
|
<file leaf-file-name="httpdownloader.cpp" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/httpdownloader.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="242">
|
||||||
|
<caret line="58" column="98" lean-forward="false" selection-start-line="58" selection-start-column="98" selection-end-line="58" selection-end-column="98" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#1238#1265#0" expanded="true" />
|
||||||
|
<marker date="1513154719000" expanded="true" signature="0:1236" ph="/.../" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="media.cpp" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/media.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="142">
|
||||||
|
<caret line="71" column="0" lean-forward="false" selection-start-line="71" selection-start-column="0" selection-end-line="71" selection-end-column="0" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="proxyplayer.cpp" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/proxyplayer.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="0">
|
||||||
|
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="24" selection-end-column="3" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="common.cpp" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/common.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="240">
|
||||||
|
<caret line="82" column="18" lean-forward="false" selection-start-line="82" selection-start-column="18" selection-end-line="82" selection-end-column="18" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#1238#1257#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="media.h" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/media.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="473">
|
||||||
|
<caret line="76" column="52" lean-forward="false" selection-start-line="76" selection-start-column="52" selection-end-line="76" selection-end-column="52" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="player.cpp" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/player.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="170">
|
||||||
|
<caret line="179" column="45" lean-forward="false" selection-start-line="179" selection-start-column="25" selection-end-line="179" selection-end-column="45" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="PlayerBase.h" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file:///usr/local/include/Player/PlayerBase.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="224">
|
||||||
|
<caret line="187" column="9" lean-forward="false" selection-start-line="187" selection-start-column="9" selection-end-line="187" selection-end-column="9" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="player.h" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/player.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="347">
|
||||||
|
<caret line="101" column="35" lean-forward="true" selection-start-line="101" selection-start-column="35" selection-end-line="101" selection-end-column="35" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="test_all.cpp" pinned="false" current-in-tab="true">
|
||||||
|
<entry file="file://$PROJECT_DIR$/tests/test_all.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="1213">
|
||||||
|
<caret line="118" column="19" lean-forward="false" selection-start-line="118" selection-start-column="19" selection-end-line="118" selection-end-column="19" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#1237#1258#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="common.h" pinned="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/common.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="163">
|
||||||
|
<caret line="41" column="8" lean-forward="false" selection-start-line="41" selection-start-column="8" selection-end-line="41" selection-end-column="8" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#1324#1488#0" expanded="true" />
|
||||||
|
<marker date="1513156321000" expanded="true" signature="3358:3361" ph="/.../" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
</leaf>
|
||||||
|
</component>
|
||||||
|
<component name="FindInProjectRecents">
|
||||||
|
<findStrings>
|
||||||
|
<find>s_threadPool</find>
|
||||||
|
</findStrings>
|
||||||
|
</component>
|
||||||
|
<component name="IdeDocumentHistory">
|
||||||
|
<option name="CHANGED_PATHS">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/tests/CMakeLists.txt" />
|
||||||
|
<option value="$PROJECT_DIR$/CMakeLists.txt" />
|
||||||
|
<option value="$PROJECT_DIR$/src/udpsearcher.h" />
|
||||||
|
<option value="$PROJECT_DIR$/src/udpsearcher.cpp" />
|
||||||
|
<option value="$PROJECT_DIR$/src/media.h" />
|
||||||
|
<option value="$PROJECT_DIR$/src/httpdownloader.h" />
|
||||||
|
<option value="$PROJECT_DIR$/src/cleaner.h" />
|
||||||
|
<option value="$PROJECT_DIR$/src/rtspApi.h" />
|
||||||
|
<option value="$PROJECT_DIR$/src/httpdownloader.cpp" />
|
||||||
|
<option value="$PROJECT_DIR$/src/media.cpp" />
|
||||||
|
<option value="$PROJECT_DIR$/src/proxyplayer.h" />
|
||||||
|
<option value="$PROJECT_DIR$/src/proxyplayer.cpp" />
|
||||||
|
<option value="$PROJECT_DIR$/src/common.h" />
|
||||||
|
<option value="$PROJECT_DIR$/src/common.cpp" />
|
||||||
|
<option value="$PROJECT_DIR$/src/mediakit.h" />
|
||||||
|
<option value="$PROJECT_DIR$/tests/test_all.cpp.cpp" />
|
||||||
|
<option value="$PROJECT_DIR$/src/player.h" />
|
||||||
|
<option value="$PROJECT_DIR$/src/player.cpp" />
|
||||||
|
<option value="$PROJECT_DIR$/tests/test_all.cpp" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
|
||||||
|
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
|
||||||
|
<component name="JsGulpfileManager">
|
||||||
|
<detection-done>true</detection-done>
|
||||||
|
<sorting>DEFINITION_ORDER</sorting>
|
||||||
|
</component>
|
||||||
|
<component name="OCFindUsagesOptions" text="true" ivars="false" properties="true" derivedClasses="false" />
|
||||||
|
<component name="ProjectFrameBounds" extendedState="6">
|
||||||
|
<option name="y" value="23" />
|
||||||
|
<option name="width" value="1280" />
|
||||||
|
<option name="height" value="1057" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectView">
|
||||||
|
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||||
|
<flattenPackages />
|
||||||
|
<showMembers />
|
||||||
|
<showModules />
|
||||||
|
<showLibraryContents />
|
||||||
|
<hideEmptyPackages />
|
||||||
|
<abbreviatePackageNames />
|
||||||
|
<autoscrollToSource />
|
||||||
|
<autoscrollFromSource />
|
||||||
|
<sortByType />
|
||||||
|
<manualOrder />
|
||||||
|
<foldersAlwaysOnTop value="true" />
|
||||||
|
</navigator>
|
||||||
|
<panes>
|
||||||
|
<pane id="ProjectPane">
|
||||||
|
<subPane>
|
||||||
|
<expand>
|
||||||
|
<path>
|
||||||
|
<item name="MediaKitWrapper" type="dad4c3:CidrFilesViewHelper$MyProjectTreeStructure$1" />
|
||||||
|
<item name="c_wrapper" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="MediaKitWrapper" type="dad4c3:CidrFilesViewHelper$MyProjectTreeStructure$1" />
|
||||||
|
<item name="c_wrapper" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="src" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<item name="MediaKitWrapper" type="dad4c3:CidrFilesViewHelper$MyProjectTreeStructure$1" />
|
||||||
|
<item name="c_wrapper" type="462c0819:PsiDirectoryNode" />
|
||||||
|
<item name="tests" type="462c0819:PsiDirectoryNode" />
|
||||||
|
</path>
|
||||||
|
</expand>
|
||||||
|
<select />
|
||||||
|
</subPane>
|
||||||
|
</pane>
|
||||||
|
</panes>
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent">
|
||||||
|
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||||
|
<property name="last_opened_file_path" value="$PROJECT_DIR$/CMakeLists.txt" />
|
||||||
|
<property name="settings.editor.selected.configurable" value="CMakeSettings" />
|
||||||
|
</component>
|
||||||
|
<component name="RecentsManager">
|
||||||
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$/cmake" />
|
||||||
|
<recent name="$PROJECT_DIR$/tests" />
|
||||||
|
</key>
|
||||||
|
</component>
|
||||||
|
<component name="RunDashboard">
|
||||||
|
<option name="ruleStates">
|
||||||
|
<list>
|
||||||
|
<RuleState>
|
||||||
|
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||||
|
</RuleState>
|
||||||
|
<RuleState>
|
||||||
|
<option name="name" value="StatusDashboardGroupingRule" />
|
||||||
|
</RuleState>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="RunManager" selected="Application.test_all">
|
||||||
|
<configuration name="Build All" type="CMakeRunConfiguration" factoryName="Application" PASS_PARENT_ENVS_2="true" CONFIG_NAME="Debug" EXPLICIT_BUILD_TARGET_NAME="all">
|
||||||
|
<envs />
|
||||||
|
</configuration>
|
||||||
|
<configuration name="MediaKitWrapper_shared" type="CMakeRunConfiguration" factoryName="Application" PASS_PARENT_ENVS_2="true" PROJECT_NAME="MediaKitWrapper" TARGET_NAME="MediaKitWrapper_shared" CONFIG_NAME="Debug">
|
||||||
|
<envs />
|
||||||
|
</configuration>
|
||||||
|
<configuration name="MediaKitWrapper_static" type="CMakeRunConfiguration" factoryName="Application" PASS_PARENT_ENVS_2="true" PROJECT_NAME="MediaKitWrapper" TARGET_NAME="MediaKitWrapper_static" CONFIG_NAME="Debug">
|
||||||
|
<envs />
|
||||||
|
</configuration>
|
||||||
|
<configuration name="test_all" type="CMakeRunConfiguration" factoryName="Application" PASS_PARENT_ENVS_2="true" PROJECT_NAME="MediaKitWrapper" TARGET_NAME="test_all" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="MediaKitWrapper" RUN_TARGET_NAME="test_all">
|
||||||
|
<envs />
|
||||||
|
</configuration>
|
||||||
|
<list size="4">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="Application.Build All" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="Application.MediaKitWrapper_shared" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="Application.MediaKitWrapper_static" />
|
||||||
|
<item index="3" class="java.lang.String" itemvalue="Application.test_all" />
|
||||||
|
</list>
|
||||||
|
</component>
|
||||||
|
<component name="ShelveChangesManager" show_recycled="false">
|
||||||
|
<option name="remove_strategy" value="false" />
|
||||||
|
</component>
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="Default task">
|
||||||
|
<changelist id="db5167c7-a7f4-4c11-a19e-0c6c8a7b66f1" name="Default" comment="" />
|
||||||
|
<created>1513153608354</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1513153608354</updated>
|
||||||
|
<workItem from="1513153610227" duration="5467000" />
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="TimeTrackingManager">
|
||||||
|
<option name="totallyTimeSpent" value="5467000" />
|
||||||
|
</component>
|
||||||
|
<component name="ToolWindowManager">
|
||||||
|
<frame x="0" y="23" width="1852" height="1057" extended-state="6" />
|
||||||
|
<layout>
|
||||||
|
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.19779006" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||||
|
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32952183" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="CMake" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3846154" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
|
||||||
|
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Terminal" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.44282743" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3991684" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
|
||||||
|
<window_info id="Data View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
|
||||||
|
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
||||||
|
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||||
|
</layout>
|
||||||
|
</component>
|
||||||
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
|
<option name="version" value="1" />
|
||||||
|
</component>
|
||||||
|
<component name="VcsContentAnnotationSettings">
|
||||||
|
<option name="myLimit" value="2678400000" />
|
||||||
|
</component>
|
||||||
|
<component name="XDebuggerManager">
|
||||||
|
<breakpoint-manager>
|
||||||
|
<breakpoints>
|
||||||
|
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
|
||||||
|
<url>file://$PROJECT_DIR$/tests/test_all.cpp</url>
|
||||||
|
<line>67</line>
|
||||||
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
|
||||||
|
<url>file://$PROJECT_DIR$/tests/test_all.cpp</url>
|
||||||
|
<line>88</line>
|
||||||
|
<option name="timeStamp" value="1" />
|
||||||
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
|
||||||
|
<url>file://$PROJECT_DIR$/tests/test_all.cpp</url>
|
||||||
|
<line>99</line>
|
||||||
|
<option name="timeStamp" value="2" />
|
||||||
|
</line-breakpoint>
|
||||||
|
<line-breakpoint enabled="true" type="com.jetbrains.cidr.execution.debugger.OCBreakpointType">
|
||||||
|
<url>file://$PROJECT_DIR$/tests/test_all.cpp</url>
|
||||||
|
<line>110</line>
|
||||||
|
<option name="timeStamp" value="3" />
|
||||||
|
</line-breakpoint>
|
||||||
|
</breakpoints>
|
||||||
|
<option name="time" value="4" />
|
||||||
|
</breakpoint-manager>
|
||||||
|
<watches-manager />
|
||||||
|
</component>
|
||||||
|
<component name="editorHistoryManager">
|
||||||
|
<entry file="file://$PROJECT_DIR$/cmake/FindFAAC.cmake">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="114">
|
||||||
|
<caret line="6" column="25" lean-forward="false" selection-start-line="6" selection-start-column="25" selection-end-line="6" selection-end-column="25" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/proxy.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="-2051">
|
||||||
|
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/udpsearcher.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="456">
|
||||||
|
<caret line="24" column="3" lean-forward="false" selection-start-line="24" selection-start-column="3" selection-end-line="24" selection-end-column="3" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/udpsearcher.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="206">
|
||||||
|
<caret line="33" column="9" lean-forward="false" selection-start-line="33" selection-start-column="9" selection-end-line="33" selection-end-column="9" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/CMakeLists.txt">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="19">
|
||||||
|
<caret line="1" column="23" lean-forward="false" selection-start-line="1" selection-start-column="8" selection-end-line="1" selection-end-column="23" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/cleaner.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="206">
|
||||||
|
<caret line="49" column="16" lean-forward="false" selection-start-line="49" selection-start-column="16" selection-end-line="49" selection-end-column="16" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file:///usr/local/include/Player/MediaPlayer.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="206">
|
||||||
|
<caret line="43" column="6" lean-forward="false" selection-start-line="43" selection-start-column="6" selection-end-line="43" selection-end-column="6" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file:///usr/local/include/Device/PlayerProxy.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="206">
|
||||||
|
<caret line="49" column="11" lean-forward="false" selection-start-line="49" selection-start-column="11" selection-end-line="49" selection-end-column="11" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/mediakit.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="449">
|
||||||
|
<caret line="33" column="0" lean-forward="false" selection-start-line="33" selection-start-column="0" selection-end-line="33" selection-end-column="0" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/tests/CMakeLists.txt">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="266">
|
||||||
|
<caret line="14" column="37" lean-forward="false" selection-start-line="14" selection-start-column="37" selection-end-line="14" selection-end-column="37" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/proxyplayer.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="367">
|
||||||
|
<caret line="44" column="29" lean-forward="false" selection-start-line="44" selection-start-column="11" selection-end-line="44" selection-end-column="29" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/httpdownloader.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="343">
|
||||||
|
<caret line="37" column="107" lean-forward="true" selection-start-line="37" selection-start-column="44" selection-end-line="37" selection-end-column="107" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/common.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="163">
|
||||||
|
<caret line="41" column="8" lean-forward="false" selection-start-line="41" selection-start-column="8" selection-end-line="41" selection-end-column="8" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#1324#1488#0" expanded="true" />
|
||||||
|
<marker date="1513156321000" expanded="true" signature="3358:3361" ph="/.../" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file:///usr/local/include/Player/PlayerBase.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="224">
|
||||||
|
<caret line="187" column="9" lean-forward="false" selection-start-line="187" selection-start-column="9" selection-end-line="187" selection-end-column="9" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/media.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="473">
|
||||||
|
<caret line="76" column="52" lean-forward="false" selection-start-line="76" selection-start-column="52" selection-end-line="76" selection-end-column="52" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/proxyplayer.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="0">
|
||||||
|
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="24" selection-end-column="3" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/common.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="240">
|
||||||
|
<caret line="82" column="18" lean-forward="false" selection-start-line="82" selection-start-column="18" selection-end-line="82" selection-end-column="18" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#1238#1257#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/httpdownloader.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="242">
|
||||||
|
<caret line="58" column="98" lean-forward="false" selection-start-line="58" selection-start-column="98" selection-end-line="58" selection-end-column="98" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#1238#1265#0" expanded="true" />
|
||||||
|
<marker date="1513154719000" expanded="true" signature="0:1236" ph="/.../" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/media.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="142">
|
||||||
|
<caret line="71" column="0" lean-forward="false" selection-start-line="71" selection-start-column="0" selection-end-line="71" selection-end-column="0" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/player.h">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="347">
|
||||||
|
<caret line="101" column="35" lean-forward="true" selection-start-line="101" selection-start-column="35" selection-end-line="101" selection-end-column="35" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/src/player.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="170">
|
||||||
|
<caret line="179" column="45" lean-forward="false" selection-start-line="179" selection-start-column="25" selection-end-line="179" selection-end-column="45" />
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/tests/test_all.cpp">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="1213">
|
||||||
|
<caret line="118" column="19" lean-forward="false" selection-start-line="118" selection-start-column="19" selection-end-line="118" selection-end-column="19" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#1237#1258#0" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
project(MediaKitWrapper)
|
||||||
|
|
||||||
|
#加载自定义模块
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
#设置库文件路径
|
||||||
|
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
#设置可执行程序路径
|
||||||
|
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||||
|
|
||||||
|
#设置需要链接的库
|
||||||
|
set(LINK_LIB_LIST)
|
||||||
|
|
||||||
|
#安装目录
|
||||||
|
if(WIN32)
|
||||||
|
set(INSTALL_PATH_LIB $ENV{HOME}/${CMAKE_PROJECT_NAME}/lib)
|
||||||
|
set(INSTALL_PATH_INCLUDE $ENV{HOME}/${CMAKE_PROJECT_NAME}/include)
|
||||||
|
else()
|
||||||
|
set(INSTALL_PATH_LIB lib)
|
||||||
|
set(INSTALL_PATH_INCLUDE include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#查找openssl是否安装
|
||||||
|
find_package(OpenSSL QUIET)
|
||||||
|
if(OPENSSL_FOUND)
|
||||||
|
message(STATUS "找到openssl库:\"${OPENSSL_INCLUDE_DIR}\",ENABLE_OPENSSL宏已打开")
|
||||||
|
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||||
|
add_definitions(-DENABLE_OPENSSL)
|
||||||
|
list(APPEND LINK_LIB_LIST ${OPENSSL_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#查找mysql是否安装
|
||||||
|
find_package(MYSQL QUIET)
|
||||||
|
if(MYSQL_FOUND)
|
||||||
|
message(STATUS "找到mysqlclient库:\"${MYSQL_INCLUDE_DIR}\",ENABLE_MYSQL宏已打开")
|
||||||
|
include_directories(${MYSQL_INCLUDE_DIR})
|
||||||
|
add_definitions(-DENABLE_MYSQL)
|
||||||
|
list(APPEND LINK_LIB_LIST ${MYSQL_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#查找mp4v2是否安装
|
||||||
|
find_package(MP4V2 QUIET)
|
||||||
|
if(MP4V2_FOUND)
|
||||||
|
message(STATUS "找到mp4v2库:\"${MP4V2_INCLUDE_DIR}\",ENABLE_MP4V2宏已打开")
|
||||||
|
include_directories(${MP4V2_INCLUDE_DIR})
|
||||||
|
add_definitions(-DENABLE_MP4V2)
|
||||||
|
list(APPEND LINK_LIB_LIST ${MP4V2_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#查找x264是否安装
|
||||||
|
find_package(X264 QUIET)
|
||||||
|
if(X264_FOUND)
|
||||||
|
message(STATUS "找到x264库:\"${X264_INCLUDE_DIRS}\",ENABLE_X264宏已打开")
|
||||||
|
include_directories(${X264_INCLUDE_DIRS})
|
||||||
|
add_definitions(-DENABLE_X264)
|
||||||
|
list(APPEND LINK_LIB_LIST ${X264_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#查找faac是否安装
|
||||||
|
find_package(FAAC QUIET)
|
||||||
|
if(FAAC_FOUND)
|
||||||
|
message(STATUS "找到faac库:\"${FAAC_INCLUDE_DIR}\",ENABLE_FAAC宏已打开")
|
||||||
|
include_directories(${FAAC_INCLUDE_DIR})
|
||||||
|
add_definitions(-DENABLE_FAAC)
|
||||||
|
list(APPEND LINK_LIB_LIST ${FAAC_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#设置工程源码根目录
|
||||||
|
set(ToolKit_Root ${CMAKE_SOURCE_DIR}/../ZLToolKit/src)
|
||||||
|
set(MediaKit_Root ${CMAKE_SOURCE_DIR}/../src)
|
||||||
|
|
||||||
|
#设置头文件目录
|
||||||
|
INCLUDE_DIRECTORIES(${ToolKit_Root})
|
||||||
|
INCLUDE_DIRECTORIES(${MediaKit_Root})
|
||||||
|
|
||||||
|
#收集源代码
|
||||||
|
file(GLOB ToolKit_src_list ${ToolKit_Root}/*/*.cpp ${ToolKit_Root}/*/*.h ${ToolKit_Root}/*/*.c)
|
||||||
|
file(GLOB MediaKit_src_list ${MediaKit_Root}/*/*.cpp ${MediaKit_Root}/*/*.h ${MediaKit_Root}/*/*.c)
|
||||||
|
|
||||||
|
#去除win32的适配代码
|
||||||
|
if (NOT WIN32)
|
||||||
|
list(REMOVE_ITEM ToolKit_src_list ${ToolKit_Root}/win32/getopt.c)
|
||||||
|
else()
|
||||||
|
#防止Windows.h包含Winsock.h
|
||||||
|
add_definitions(-DWIN32_LEAN_AND_MEAN -DMP4V2_NO_STDINT_DEFS)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#使能GOP缓存
|
||||||
|
add_definitions(-DENABLE_RING_USEBUF)
|
||||||
|
|
||||||
|
#引用头文件路径
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||||
|
|
||||||
|
#使能c++11
|
||||||
|
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
|
#关闭过期接口警告
|
||||||
|
add_compile_options(-Wno-deprecated-declarations)
|
||||||
|
#关闭__FUNCTION__宏在函数外警告
|
||||||
|
add_compile_options(-Wno-predefined-identifier-outside-function)
|
||||||
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
#收集源文件
|
||||||
|
file(GLOB SRC_LIST src/*.cpp src/*.h)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
list(APPEND LINK_LIB_LIST WS2_32 Iphlpapi shlwapi)
|
||||||
|
elseif(NOT ANDROID OR IOS)
|
||||||
|
list(APPEND LINK_LIB_LIST pthread)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
add_library(zltoolkit STATIC ${ToolKit_src_list})
|
||||||
|
add_library(zlmediakit STATIC ${MediaKit_src_list})
|
||||||
|
|
||||||
|
add_library(${CMAKE_PROJECT_NAME}_shared SHARED ${SRC_LIST})
|
||||||
|
target_link_libraries(${CMAKE_PROJECT_NAME}_shared zlmediakit zltoolkit ${LINK_LIB_LIST})
|
||||||
|
|
||||||
|
#测试程序
|
||||||
|
if(NOT IOS)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif(NOT IOS)
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Copyright (c) 2014, Pavel Rojtberg
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# 3. Neither the name of the copyright holder nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from this
|
||||||
|
# software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Usage:
|
||||||
|
# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH}
|
||||||
|
# 2. inside your project add
|
||||||
|
#
|
||||||
|
# include(AndroidNdkGdb)
|
||||||
|
# android_ndk_gdb_enable()
|
||||||
|
# # for each target
|
||||||
|
# add_library(MyLibrary ...)
|
||||||
|
# android_ndk_gdb_debuggable(MyLibrary)
|
||||||
|
|
||||||
|
|
||||||
|
# add gdbserver and general gdb configuration to project
|
||||||
|
# also create a mininal NDK skeleton so ndk-gdb finds the paths
|
||||||
|
#
|
||||||
|
# the optional parameter defines the path to the android project.
|
||||||
|
# uses PROJECT_SOURCE_DIR by default.
|
||||||
|
macro(android_ndk_gdb_enable)
|
||||||
|
if(ANDROID)
|
||||||
|
# create custom target that depends on the real target so it gets executed afterwards
|
||||||
|
add_custom_target(NDK_GDB ALL)
|
||||||
|
|
||||||
|
if(${ARGC})
|
||||||
|
set(ANDROID_PROJECT_DIR ${ARGV0})
|
||||||
|
else()
|
||||||
|
set(ANDROID_PROJECT_DIR ${PROJECT_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)
|
||||||
|
file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH})
|
||||||
|
|
||||||
|
# 1. generate essential Android Makefiles
|
||||||
|
file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni)
|
||||||
|
if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk)
|
||||||
|
file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
|
||||||
|
endif()
|
||||||
|
if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk)
|
||||||
|
file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 2. generate gdb.setup
|
||||||
|
get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES)
|
||||||
|
string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}")
|
||||||
|
file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n")
|
||||||
|
file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n")
|
||||||
|
|
||||||
|
# 3. copy gdbserver executable
|
||||||
|
file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# register a target for remote debugging
|
||||||
|
# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original
|
||||||
|
macro(android_ndk_gdb_debuggable TARGET_NAME)
|
||||||
|
if(ANDROID)
|
||||||
|
get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION)
|
||||||
|
|
||||||
|
# create custom target that depends on the real target so it gets executed afterwards
|
||||||
|
add_dependencies(NDK_GDB ${TARGET_NAME})
|
||||||
|
|
||||||
|
# 4. copy lib to obj
|
||||||
|
add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_LOCATION} ${NDK_GDB_SOLIB_PATH})
|
||||||
|
|
||||||
|
# 5. strip symbols
|
||||||
|
add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Copyright (c) 2014, Pavel Rojtberg
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# 3. Neither the name of the copyright holder nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from this
|
||||||
|
# software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
macro(android_ndk_import_module_cpufeatures)
|
||||||
|
if(ANDROID)
|
||||||
|
include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
|
||||||
|
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
|
||||||
|
target_link_libraries(cpufeatures dl)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(android_ndk_import_module_native_app_glue)
|
||||||
|
if(ANDROID)
|
||||||
|
include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
|
||||||
|
add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
|
||||||
|
target_link_libraries(native_app_glue log)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(android_ndk_import_module_ndk_helper)
|
||||||
|
if(ANDROID)
|
||||||
|
android_ndk_import_module_cpufeatures()
|
||||||
|
android_ndk_import_module_native_app_glue()
|
||||||
|
|
||||||
|
include_directories(${ANDROID_NDK}/sources/android/ndk_helper)
|
||||||
|
file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c)
|
||||||
|
add_library(ndk_helper ${_NDK_HELPER_SRCS})
|
||||||
|
target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue)
|
||||||
|
|
||||||
|
unset(_NDK_HELPER_SRCS)
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
find_path(AVCODEC_INCLUDE_DIR
|
||||||
|
NAMES libavcodec/avcodec.h
|
||||||
|
PATHS $ENV{HOME}/ffmpeg/include)
|
||||||
|
|
||||||
|
find_library(AVCODEC_LIBRARY
|
||||||
|
NAMES avcodec
|
||||||
|
PATHS $ENV{HOME}/ffmpeg/lib)
|
||||||
|
|
||||||
|
set(AVCODEC_LIBRARIES ${AVCODEC_LIBRARY})
|
||||||
|
set(AVCODEC_INCLUDE_DIRS ${AVCODEC_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(AVCODEC DEFAULT_MSG AVCODEC_LIBRARY AVCODEC_INCLUDE_DIR)
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
find_path(AVUTIL_INCLUDE_DIR
|
||||||
|
NAMES libavutil/avutil.h
|
||||||
|
PATHS $ENV{HOME}/ffmpeg/include)
|
||||||
|
|
||||||
|
find_library(AVUTIL_LIBRARY
|
||||||
|
NAMES avutil
|
||||||
|
PATHS $ENV{HOME}/ffmpeg/lib)
|
||||||
|
|
||||||
|
set(AVUTIL_LIBRARIES ${AVUTIL_LIBRARY})
|
||||||
|
set(AVUTIL_INCLUDE_DIRS ${AVUTIL_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(AVUTIL DEFAULT_MSG AVUTIL_LIBRARY AVUTIL_INCLUDE_DIR)
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
|
||||||
|
find_path(FAAC_INCLUDE_DIR
|
||||||
|
NAMES faac.h
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(FAAC_LIBRARY
|
||||||
|
NAMES faac
|
||||||
|
)
|
||||||
|
|
||||||
|
set(FAAC_INCLUDE_DIRS ${FAAC_INCLUDE_DIR})
|
||||||
|
set(FAAC_LIBRARIES ${FAAC_LIBRARY})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(FAAC DEFAULT_MSG FAAC_LIBRARY FAAC_INCLUDE_DIR)
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
find_path(MP4V2_INCLUDE_DIR
|
||||||
|
NAMES mp4v2/mp4v2.h)
|
||||||
|
|
||||||
|
find_library(MP4V2_LIBRARY
|
||||||
|
NAMES mp4v2)
|
||||||
|
|
||||||
|
set(MP4V2_LIBRARIES ${MP4V2_LIBRARY})
|
||||||
|
set(MP4V2_INCLUDE_DIRS ${MP4V2_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set MP4V2_FOUND to TRUE
|
||||||
|
# if all listed variables are TRUE
|
||||||
|
find_package_handle_standard_args(MP4V2 DEFAULT_MSG MP4V2_LIBRARY MP4V2_INCLUDE_DIR)
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
# - Try to find MySQL / MySQL Embedded library
|
||||||
|
# Find the MySQL includes and client library
|
||||||
|
# This module defines
|
||||||
|
# MYSQL_INCLUDE_DIR, where to find mysql.h
|
||||||
|
# MYSQL_LIBRARIES, the libraries needed to use MySQL.
|
||||||
|
# MYSQL_LIB_DIR, path to the MYSQL_LIBRARIES
|
||||||
|
# MYSQL_EMBEDDED_LIBRARIES, the libraries needed to use MySQL Embedded.
|
||||||
|
# MYSQL_EMBEDDED_LIB_DIR, path to the MYSQL_EMBEDDED_LIBRARIES
|
||||||
|
# MYSQL_FOUND, If false, do not try to use MySQL.
|
||||||
|
# MYSQL_EMBEDDED_FOUND, If false, do not try to use MySQL Embedded.
|
||||||
|
|
||||||
|
# Copyright (c) 2006-2008, Jarosław Staniek <staniek@kde.org>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
find_path(MYSQL_INCLUDE_DIR mysql.h
|
||||||
|
PATHS
|
||||||
|
$ENV{MYSQL_INCLUDE_DIR}
|
||||||
|
$ENV{MYSQL_DIR}/include
|
||||||
|
$ENV{ProgramFiles}/MySQL/*/include
|
||||||
|
$ENV{SystemDrive}/MySQL/*/include
|
||||||
|
$ENV{ProgramW6432}/MySQL/*/include
|
||||||
|
)
|
||||||
|
else(WIN32)
|
||||||
|
find_path(MYSQL_INCLUDE_DIR mysql/mysql.h
|
||||||
|
PATHS
|
||||||
|
$ENV{MYSQL_INCLUDE_DIR}
|
||||||
|
$ENV{MYSQL_DIR}/include
|
||||||
|
/usr/local/mysql/include
|
||||||
|
/opt/mysql/mysql/include
|
||||||
|
PATH_SUFFIXES
|
||||||
|
mysql
|
||||||
|
)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
if (${CMAKE_BUILD_TYPE})
|
||||||
|
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_TOLOWER)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# path suffix for debug/release mode
|
||||||
|
# binary_dist: mysql binary distribution
|
||||||
|
# build_dist: custom build
|
||||||
|
if(CMAKE_BUILD_TYPE_TOLOWER MATCHES "debug")
|
||||||
|
set(binary_dist debug)
|
||||||
|
set(build_dist Debug)
|
||||||
|
else(CMAKE_BUILD_TYPE_TOLOWER MATCHES "debug")
|
||||||
|
ADD_DEFINITIONS(-DDBUG_OFF)
|
||||||
|
set(binary_dist opt)
|
||||||
|
set(build_dist Release)
|
||||||
|
endif(CMAKE_BUILD_TYPE_TOLOWER MATCHES "debug")
|
||||||
|
|
||||||
|
# find_library(MYSQL_LIBRARIES NAMES mysqlclient
|
||||||
|
set(MYSQL_LIB_PATHS
|
||||||
|
$ENV{MYSQL_DIR}/lib/${binary_dist}
|
||||||
|
$ENV{MYSQL_DIR}/libmysql/${build_dist}
|
||||||
|
$ENV{MYSQL_DIR}/client/${build_dist}
|
||||||
|
$ENV{ProgramFiles}/MySQL/*/lib/${binary_dist}
|
||||||
|
$ENV{SystemDrive}/MySQL/*/lib/${binary_dist}
|
||||||
|
$ENV{MYSQL_DIR}/lib/opt
|
||||||
|
$ENV{MYSQL_DIR}/client/release
|
||||||
|
$ENV{ProgramFiles}/MySQL/*/lib/opt
|
||||||
|
$ENV{ProgramFiles}/MySQL/*/lib/
|
||||||
|
$ENV{SystemDrive}/MySQL/*/lib/opt
|
||||||
|
$ENV{ProgramW6432}/MySQL/*/lib
|
||||||
|
)
|
||||||
|
find_library(MYSQL_LIBRARIES NAMES libmysql
|
||||||
|
PATHS
|
||||||
|
${MYSQL_LIB_PATHS}
|
||||||
|
)
|
||||||
|
else(WIN32)
|
||||||
|
# find_library(MYSQL_LIBRARIES NAMES mysqlclient
|
||||||
|
set(MYSQL_LIB_PATHS
|
||||||
|
$ENV{MYSQL_DIR}/libmysql_r/.libs
|
||||||
|
$ENV{MYSQL_DIR}/lib
|
||||||
|
$ENV{MYSQL_DIR}/lib/mysql
|
||||||
|
/usr/local/mysql/lib
|
||||||
|
/opt/mysql/mysql/lib
|
||||||
|
$ENV{MYSQL_DIR}/libmysql_r/.libs
|
||||||
|
$ENV{MYSQL_DIR}/lib
|
||||||
|
$ENV{MYSQL_DIR}/lib/mysql
|
||||||
|
/usr/local/mysql/lib
|
||||||
|
/opt/mysql/mysql/lib
|
||||||
|
PATH_SUFFIXES
|
||||||
|
mysql
|
||||||
|
)
|
||||||
|
find_library(MYSQL_LIBRARIES NAMES mysqlclient
|
||||||
|
PATHS
|
||||||
|
${MYSQL_LIB_PATHS}
|
||||||
|
)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
find_library(MYSQL_EMBEDDED_LIBRARIES NAMES mysqld
|
||||||
|
PATHS
|
||||||
|
${MYSQL_LIB_PATHS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(MYSQL_LIBRARIES)
|
||||||
|
get_filename_component(MYSQL_LIB_DIR ${MYSQL_LIBRARIES} PATH)
|
||||||
|
endif(MYSQL_LIBRARIES)
|
||||||
|
|
||||||
|
if(MYSQL_EMBEDDED_LIBRARIES)
|
||||||
|
get_filename_component(MYSQL_EMBEDDED_LIB_DIR ${MYSQL_EMBEDDED_LIBRARIES} PATH)
|
||||||
|
endif(MYSQL_EMBEDDED_LIBRARIES)
|
||||||
|
|
||||||
|
set( CMAKE_REQUIRED_INCLUDES ${MYSQL_INCLUDE_DIR} )
|
||||||
|
set( CMAKE_REQUIRED_LIBRARIES ${MYSQL_EMBEDDED_LIBRARIES} )
|
||||||
|
check_cxx_source_compiles( "#include <mysql.h>\nint main() { int i = MYSQL_OPT_USE_EMBEDDED_CONNECTION; }" HAVE_MYSQL_OPT_EMBEDDED_CONNECTION )
|
||||||
|
|
||||||
|
if(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||||
|
set(MYSQL_FOUND TRUE)
|
||||||
|
message(STATUS "Found MySQL: ${MYSQL_INCLUDE_DIR}, ${MYSQL_LIBRARIES}")
|
||||||
|
else(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||||
|
set(MYSQL_FOUND FALSE)
|
||||||
|
message(STATUS "MySQL not found.")
|
||||||
|
endif(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
|
||||||
|
|
||||||
|
if(MYSQL_INCLUDE_DIR AND MYSQL_EMBEDDED_LIBRARIES AND HAVE_MYSQL_OPT_EMBEDDED_CONNECTION)
|
||||||
|
set(MYSQL_EMBEDDED_FOUND TRUE)
|
||||||
|
message(STATUS "Found MySQL Embedded: ${MYSQL_INCLUDE_DIR}, ${MYSQL_EMBEDDED_LIBRARIES}")
|
||||||
|
else(MYSQL_INCLUDE_DIR AND MYSQL_EMBEDDED_LIBRARIES AND HAVE_MYSQL_OPT_EMBEDDED_CONNECTION)
|
||||||
|
set(MYSQL_EMBEDDED_FOUND FALSE)
|
||||||
|
message(STATUS "MySQL Embedded not found.")
|
||||||
|
endif(MYSQL_INCLUDE_DIR AND MYSQL_EMBEDDED_LIBRARIES AND HAVE_MYSQL_OPT_EMBEDDED_CONNECTION)
|
||||||
|
|
||||||
|
mark_as_advanced(MYSQL_INCLUDE_DIR MYSQL_LIBRARIES MYSQL_EMBEDDED_LIBRARIES)
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
find_path(SDL2_INCLUDE_DIR
|
||||||
|
NAMES SDL2/SDL.h
|
||||||
|
HINTS SDL2
|
||||||
|
PATHS $ENV{HOME}/sdl2/include)
|
||||||
|
|
||||||
|
find_library(SDL2_LIBRARY
|
||||||
|
NAMES SDL2
|
||||||
|
PATHS $ENV{HOME}/sdl2/lib/x86)
|
||||||
|
|
||||||
|
set(SDL2_LIBRARIES ${SDL2_LIBRARY})
|
||||||
|
set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(SDL2 DEFAULT_MSG SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
############################################################################
|
||||||
|
# FindX264.txt
|
||||||
|
# Copyright (C) 2015 Belledonne Communications, Grenoble France
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
#
|
||||||
|
# This program 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
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
#
|
||||||
|
# - Find the x264 include file and library
|
||||||
|
#
|
||||||
|
# X264_FOUND - system has x264
|
||||||
|
# X264_INCLUDE_DIRS - the x264 include directory
|
||||||
|
# X264_LIBRARIES - The libraries needed to use x264
|
||||||
|
|
||||||
|
include(CMakePushCheckState)
|
||||||
|
include(CheckCXXSymbolExists)
|
||||||
|
|
||||||
|
set(_X264_ROOT_PATHS
|
||||||
|
${CMAKE_INSTALL_PREFIX}
|
||||||
|
)
|
||||||
|
|
||||||
|
find_path(X264_INCLUDE_DIRS
|
||||||
|
NAMES x264.h
|
||||||
|
HINTS _X264_ROOT_PATHS
|
||||||
|
PATH_SUFFIXES include
|
||||||
|
)
|
||||||
|
if(X264_INCLUDE_DIRS)
|
||||||
|
set(HAVE_X264_H 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_library(X264_LIBRARIES
|
||||||
|
NAMES x264
|
||||||
|
HINTS _X264_ROOT_PATHS
|
||||||
|
PATH_SUFFIXES bin lib
|
||||||
|
)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(X264
|
||||||
|
DEFAULT_MSG
|
||||||
|
X264_INCLUDE_DIRS X264_LIBRARIES HAVE_X264_H
|
||||||
|
)
|
||||||
|
|
||||||
|
mark_as_advanced(X264_INCLUDE_DIRS X264_LIBRARIES HAVE_X264_H)
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
find_path(ZLMEDIAKIT_INCLUDE_DIR
|
||||||
|
NAMES Rtsp/Rtsp.h
|
||||||
|
PATHS
|
||||||
|
${PROJECT_SOURCE_DIR}/../ZLMediaKit/src
|
||||||
|
$ENV{HOME}/ZLMediaKit/include)
|
||||||
|
|
||||||
|
find_library(ZLMEDIAKIT_LIBRARY
|
||||||
|
NAMES ZLMediaKit
|
||||||
|
PATHS
|
||||||
|
${PROJECT_SOURCE_DIR}/../ZLMediaKit/build/lib
|
||||||
|
$ENV{HOME}/ZLMediaKit/lib)
|
||||||
|
|
||||||
|
set(ZLMEDIAKIT_LIBRARIES ${ZLMEDIAKIT_LIBRARY})
|
||||||
|
set(ZLMEDIAKIT_INCLUDE_DIRS ${ZLMEDIAKIT_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(ZLMEDIAKIT DEFAULT_MSG ZLMEDIAKIT_LIBRARY ZLMEDIAKIT_INCLUDE_DIR)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
find_path(ZLTOOLKIT_INCLUDE_DIR
|
||||||
|
NAMES Network/Socket.h
|
||||||
|
PATHS
|
||||||
|
${PROJECT_SOURCE_DIR}/../ZLToolKit/src
|
||||||
|
$ENV{HOME}/ZLToolKit/include)
|
||||||
|
|
||||||
|
find_library(ZLTOOLKIT_LIBRARY
|
||||||
|
NAMES ZLToolKit
|
||||||
|
PATHS
|
||||||
|
${PROJECT_SOURCE_DIR}/../ZLToolKit/build/lib
|
||||||
|
$ENV{HOME}/ZLToolKit/lib)
|
||||||
|
|
||||||
|
set(ZLTOOLKIT_LIBRARIES ${ZLTOOLKIT_LIBRARY})
|
||||||
|
set(ZLTOOLKIT_INCLUDE_DIRS ${ZLTOOLKIT_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(ZLTOOLKIT DEFAULT_MSG ZLTOOLKIT_LIBRARY ZLTOOLKIT_INCLUDE_DIR)
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,209 @@
|
||||||
|
# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake
|
||||||
|
# files which are included with CMake 2.8.4
|
||||||
|
# It has been altered for iOS development
|
||||||
|
|
||||||
|
# Options:
|
||||||
|
#
|
||||||
|
# IOS_PLATFORM = OS (default) or SIMULATOR or SIMULATOR64
|
||||||
|
# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders
|
||||||
|
# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch.
|
||||||
|
# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch.
|
||||||
|
#
|
||||||
|
# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
|
||||||
|
# By default this location is automatcially chosen based on the IOS_PLATFORM value above.
|
||||||
|
# If set manually, it will override the default location and force the user of a particular Developer Platform
|
||||||
|
#
|
||||||
|
# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder
|
||||||
|
# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value.
|
||||||
|
# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path.
|
||||||
|
# If set manually, this will force the use of a specific SDK version
|
||||||
|
|
||||||
|
# Macros:
|
||||||
|
#
|
||||||
|
# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE)
|
||||||
|
# A convenience macro for setting xcode specific properties on targets
|
||||||
|
# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1")
|
||||||
|
#
|
||||||
|
# find_host_package (PROGRAM ARGS)
|
||||||
|
# A macro used to find executable programs on the host system, not within the iOS environment.
|
||||||
|
# Thanks to the android-cmake project for providing the command
|
||||||
|
|
||||||
|
# Standard settings
|
||||||
|
set (CMAKE_SYSTEM_NAME Darwin)
|
||||||
|
set (CMAKE_SYSTEM_VERSION 1)
|
||||||
|
set (UNIX True)
|
||||||
|
set (APPLE True)
|
||||||
|
set (IOS True)
|
||||||
|
|
||||||
|
# Required as of cmake 2.8.10
|
||||||
|
set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE)
|
||||||
|
|
||||||
|
# Determine the cmake host system version so we know where to find the iOS SDKs
|
||||||
|
find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin)
|
||||||
|
if (CMAKE_UNAME)
|
||||||
|
exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
|
||||||
|
string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")
|
||||||
|
endif (CMAKE_UNAME)
|
||||||
|
|
||||||
|
# Force the compilers to gcc for iOS
|
||||||
|
include (CMakeForceCompiler)
|
||||||
|
#CMAKE_FORCE_C_COMPILER (/usr/bin/gcc Apple)
|
||||||
|
set(CMAKE_C_COMPILER /usr/bin/clang)
|
||||||
|
#CMAKE_FORCE_CXX_COMPILER (/usr/bin/g++ Apple)
|
||||||
|
set(CMAKE_CXX_COMPILER /usr/bin/clang++)
|
||||||
|
set(CMAKE_AR ar CACHE FILEPATH "" FORCE)
|
||||||
|
|
||||||
|
# Skip the platform compiler checks for cross compiling
|
||||||
|
set (CMAKE_CXX_COMPILER_WORKS TRUE)
|
||||||
|
set (CMAKE_C_COMPILER_WORKS TRUE)
|
||||||
|
|
||||||
|
# All iOS/Darwin specific settings - some may be redundant
|
||||||
|
set (CMAKE_SHARED_LIBRARY_PREFIX "lib")
|
||||||
|
set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
|
||||||
|
set (CMAKE_SHARED_MODULE_PREFIX "lib")
|
||||||
|
set (CMAKE_SHARED_MODULE_SUFFIX ".so")
|
||||||
|
set (CMAKE_MODULE_EXISTS 1)
|
||||||
|
set (CMAKE_DL_LIBS "")
|
||||||
|
|
||||||
|
set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
|
||||||
|
set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ")
|
||||||
|
set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}")
|
||||||
|
set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}")
|
||||||
|
|
||||||
|
# Hidden visibilty is required for cxx on iOS
|
||||||
|
set (CMAKE_C_FLAGS_INIT "")
|
||||||
|
set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden")
|
||||||
|
|
||||||
|
set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}")
|
||||||
|
set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}")
|
||||||
|
|
||||||
|
set (CMAKE_PLATFORM_HAS_INSTALLNAME 1)
|
||||||
|
set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names")
|
||||||
|
set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names")
|
||||||
|
set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,")
|
||||||
|
set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,")
|
||||||
|
set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a")
|
||||||
|
|
||||||
|
# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree
|
||||||
|
# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache
|
||||||
|
# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun)
|
||||||
|
# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex
|
||||||
|
if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
|
||||||
|
find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool)
|
||||||
|
endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
|
||||||
|
|
||||||
|
# Setup iOS platform unless specified manually with IOS_PLATFORM
|
||||||
|
if (NOT DEFINED IOS_PLATFORM)
|
||||||
|
set (IOS_PLATFORM "OS")
|
||||||
|
endif (NOT DEFINED IOS_PLATFORM)
|
||||||
|
set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform")
|
||||||
|
|
||||||
|
# Setup building for arm64 or not
|
||||||
|
if (NOT DEFINED BUILD_ARM64)
|
||||||
|
set (BUILD_ARM64 true)
|
||||||
|
endif (NOT DEFINED BUILD_ARM64)
|
||||||
|
set (BUILD_ARM64 ${BUILD_ARM64} CACHE STRING "Build arm64 arch or not")
|
||||||
|
|
||||||
|
# Check the platform selection and setup for developer root
|
||||||
|
if (${IOS_PLATFORM} STREQUAL "OS")
|
||||||
|
set (IOS_PLATFORM_LOCATION "iPhoneOS.platform")
|
||||||
|
|
||||||
|
# This causes the installers to properly locate the output libraries
|
||||||
|
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos")
|
||||||
|
elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR")
|
||||||
|
set (SIMULATOR true)
|
||||||
|
set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
|
||||||
|
|
||||||
|
# This causes the installers to properly locate the output libraries
|
||||||
|
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
|
||||||
|
elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64")
|
||||||
|
set (SIMULATOR true)
|
||||||
|
set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
|
||||||
|
|
||||||
|
# This causes the installers to properly locate the output libraries
|
||||||
|
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
|
||||||
|
else (${IOS_PLATFORM} STREQUAL "OS")
|
||||||
|
message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR")
|
||||||
|
endif (${IOS_PLATFORM} STREQUAL "OS")
|
||||||
|
|
||||||
|
# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT
|
||||||
|
# Note Xcode 4.3 changed the installation location, choose the most recent one available
|
||||||
|
exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR)
|
||||||
|
set (XCODE_POST_43_ROOT "${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
|
||||||
|
set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
|
||||||
|
if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
|
||||||
|
if (EXISTS ${XCODE_POST_43_ROOT})
|
||||||
|
set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT})
|
||||||
|
elseif(EXISTS ${XCODE_PRE_43_ROOT})
|
||||||
|
set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT})
|
||||||
|
endif (EXISTS ${XCODE_POST_43_ROOT})
|
||||||
|
endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
|
||||||
|
set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform")
|
||||||
|
|
||||||
|
# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT
|
||||||
|
if (NOT DEFINED CMAKE_IOS_SDK_ROOT)
|
||||||
|
file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*")
|
||||||
|
if (_CMAKE_IOS_SDKS)
|
||||||
|
list (SORT _CMAKE_IOS_SDKS)
|
||||||
|
list (REVERSE _CMAKE_IOS_SDKS)
|
||||||
|
list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT)
|
||||||
|
else (_CMAKE_IOS_SDKS)
|
||||||
|
message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.")
|
||||||
|
endif (_CMAKE_IOS_SDKS)
|
||||||
|
message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}")
|
||||||
|
endif (NOT DEFINED CMAKE_IOS_SDK_ROOT)
|
||||||
|
set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK")
|
||||||
|
|
||||||
|
# Set the sysroot default to the most recent SDK
|
||||||
|
set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
|
||||||
|
|
||||||
|
# set the architecture for iOS
|
||||||
|
if (${IOS_PLATFORM} STREQUAL "OS")
|
||||||
|
set (IOS_ARCH armv7 armv7s arm64)
|
||||||
|
elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR")
|
||||||
|
set (IOS_ARCH i386)
|
||||||
|
elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64")
|
||||||
|
set (IOS_ARCH x86_64)
|
||||||
|
endif (${IOS_PLATFORM} STREQUAL "OS")
|
||||||
|
|
||||||
|
set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS")
|
||||||
|
|
||||||
|
# Set the find root to the iOS developer roots and to user defined paths
|
||||||
|
set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string "iOS find search path root")
|
||||||
|
|
||||||
|
# default to searching for frameworks first
|
||||||
|
set (CMAKE_FIND_FRAMEWORK FIRST)
|
||||||
|
|
||||||
|
# set up the default search directories for frameworks
|
||||||
|
set (CMAKE_SYSTEM_FRAMEWORK_PATH
|
||||||
|
${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks
|
||||||
|
${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks
|
||||||
|
${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks
|
||||||
|
)
|
||||||
|
|
||||||
|
# only search the iOS sdks, not the remainder of the host filesystem
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
|
||||||
|
|
||||||
|
# This little macro lets you set any XCode specific property
|
||||||
|
macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
|
||||||
|
set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
|
||||||
|
endmacro (set_xcode_property)
|
||||||
|
|
||||||
|
|
||||||
|
# This macro lets you find executable programs on the host system
|
||||||
|
macro (find_host_package)
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
|
||||||
|
set (IOS FALSE)
|
||||||
|
|
||||||
|
find_package(${ARGN})
|
||||||
|
|
||||||
|
set (IOS TRUE)
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
endmacro (find_host_package)
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_CLEANER_H_
|
||||||
|
#define SRC_CLEANER_H_
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <mutex>
|
||||||
|
#include <functional>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
class cleaner {
|
||||||
|
public:
|
||||||
|
cleaner(){}
|
||||||
|
virtual ~cleaner(){
|
||||||
|
lock_guard<recursive_mutex> lck(_mtx);
|
||||||
|
for(auto &fun : _cleanInvokerList){
|
||||||
|
fun();
|
||||||
|
}
|
||||||
|
_cleanInvokerList.clear();
|
||||||
|
}
|
||||||
|
static cleaner &Instance(){
|
||||||
|
static cleaner *instance(new cleaner);
|
||||||
|
return *instance;
|
||||||
|
}
|
||||||
|
static void Destory(){
|
||||||
|
delete &Instance();
|
||||||
|
}
|
||||||
|
template<typename FUN>
|
||||||
|
void push_front(FUN &&fun){
|
||||||
|
lock_guard<recursive_mutex> lck(_mtx);
|
||||||
|
_cleanInvokerList.push_front(fun);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FUN>
|
||||||
|
void push_back(FUN &&fun){
|
||||||
|
lock_guard<recursive_mutex> lck(_mtx);
|
||||||
|
_cleanInvokerList.push_back(fun);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
recursive_mutex _mtx;
|
||||||
|
list<function<void()> > _cleanInvokerList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SRC_CLEANER_H_ */
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "Util/logger.h"
|
||||||
|
#include "Util/onceToken.h"
|
||||||
|
#include "Util/TimeTicker.h"
|
||||||
|
#include "Network/TcpServer.h"
|
||||||
|
#include "Poller/EventPoller.h"
|
||||||
|
#include "Rtsp/UDPServer.h"
|
||||||
|
#include "Rtsp/RtspSession.h"
|
||||||
|
#include "Rtmp/RtmpSession.h"
|
||||||
|
#include "Http/HttpSession.h"
|
||||||
|
#include "cleaner.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
static TcpServer::Ptr s_pRtspSrv;
|
||||||
|
static TcpServer::Ptr s_pRtmpSrv;
|
||||||
|
static TcpServer::Ptr s_pHttpSrv;
|
||||||
|
|
||||||
|
//////////////////////////environment init///////////////////////////
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL onAppStart(){
|
||||||
|
static onceToken s_token([](){
|
||||||
|
Logger::Instance().add(std::make_shared<ConsoleChannel>("stdout", LTrace));
|
||||||
|
cleaner::Instance().push_back([](){
|
||||||
|
s_pRtspSrv.reset();
|
||||||
|
s_pRtmpSrv.reset();
|
||||||
|
s_pHttpSrv.reset();
|
||||||
|
WorkThreadPool::Destory();
|
||||||
|
UDPServer::Destory();
|
||||||
|
AsyncTaskThread::Destory();
|
||||||
|
EventPoller::Destory();
|
||||||
|
DebugL << "clear common" << endl;
|
||||||
|
Logger::Destory();
|
||||||
|
});
|
||||||
|
},nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL onAppExit(){
|
||||||
|
cleaner::Destory();
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL setGlobalOptionString(const char *key,const char *val){
|
||||||
|
if(mINI::Instance().find(key) == mINI::Instance().end()){
|
||||||
|
WarnL << "key:" << key << " not existed!";
|
||||||
|
}
|
||||||
|
mINI::Instance()[key] = val;
|
||||||
|
}
|
||||||
|
API_EXPORT unsigned short API_CALL initHttpServer(unsigned short port){
|
||||||
|
s_pHttpSrv.reset(new TcpServer());
|
||||||
|
try {
|
||||||
|
s_pHttpSrv->start<HttpSession>(port);
|
||||||
|
return s_pHttpSrv->getPort();
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
s_pHttpSrv.reset();
|
||||||
|
WarnL << ex.what();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
API_EXPORT unsigned short API_CALL initRtspServer(unsigned short port) {
|
||||||
|
s_pRtspSrv.reset(new TcpServer());
|
||||||
|
try {
|
||||||
|
s_pRtspSrv->start<RtspSession>(port);
|
||||||
|
return s_pRtspSrv->getPort();
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
s_pRtspSrv.reset();
|
||||||
|
WarnL << ex.what();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT unsigned short API_CALL initRtmpServer(unsigned short port) {
|
||||||
|
s_pRtmpSrv.reset(new TcpServer());
|
||||||
|
try {
|
||||||
|
s_pRtmpSrv->start<RtmpSession>(port);
|
||||||
|
return s_pRtmpSrv->getPort();
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
s_pRtmpSrv.reset();
|
||||||
|
WarnL << ex.what();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL log_printf(LogType level,const char* file, const char* function, int line,const char *fmt,...){
|
||||||
|
LogInfoMaker info((LogLevel)level,file,function,line);
|
||||||
|
va_list pArg;
|
||||||
|
va_start(pArg, fmt);
|
||||||
|
char buf[4096];
|
||||||
|
int n = vsprintf(buf, fmt, pArg);
|
||||||
|
buf[n] = '\0';
|
||||||
|
va_end(pArg);
|
||||||
|
info << buf;
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL log_setLevel(LogType level){
|
||||||
|
Logger::Instance().setLevel((LogLevel)level);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogoutChannel: public LogChannel {
|
||||||
|
public:
|
||||||
|
LogoutChannel(const string &name, onLogOut cb, LogLevel level = LDebug)
|
||||||
|
:LogChannel(name, level){
|
||||||
|
_cb = cb;
|
||||||
|
}
|
||||||
|
virtual ~LogoutChannel(){}
|
||||||
|
void write(const LogInfoPtr &logInfo){
|
||||||
|
if (level() > logInfo->_level) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stringstream strStream;
|
||||||
|
logInfo->format(strStream, false);
|
||||||
|
auto strTmp = strStream.str();
|
||||||
|
if (_cb) {
|
||||||
|
_cb(strTmp.data(), strTmp.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
onLogOut _cb = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL log_setOnLogOut(onLogOut cb){
|
||||||
|
std::shared_ptr<LogoutChannel> chn(new LogoutChannel("LogoutChannel",cb,LTrace));
|
||||||
|
Logger::Instance().add(chn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_COMMON_H_
|
||||||
|
#define SRC_COMMON_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#if defined(MediaKitWrapper_EXPORTS)
|
||||||
|
#define API_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define API_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define API_CALL __cdecl
|
||||||
|
#else
|
||||||
|
#define API_EXPORT
|
||||||
|
#define API_CALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////environment init////////////////////////////////
|
||||||
|
API_EXPORT void API_CALL onAppStart();
|
||||||
|
API_EXPORT void API_CALL onAppExit();
|
||||||
|
API_EXPORT void API_CALL setGlobalOptionString(const char *key,const char *val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:创建Http服务器
|
||||||
|
* 参数:port:htt监听端口,推荐80,传入0则随机分配
|
||||||
|
* 返回值:0:失败,非0:端口号
|
||||||
|
*/
|
||||||
|
API_EXPORT unsigned short API_CALL initHttpServer(unsigned short port);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:创建RTSP服务器
|
||||||
|
* 参数:port:rtsp监听端口,推荐554,传入0则随机分配
|
||||||
|
* 返回值:0:失败,非0:端口号
|
||||||
|
*/
|
||||||
|
API_EXPORT unsigned short API_CALL initRtspServer(unsigned short port);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:创建RTMP服务器
|
||||||
|
* 参数:port:rtmp监听端口,推荐1935,传入0则随机分配
|
||||||
|
* 返回值:0:失败,非0:端口号
|
||||||
|
*/
|
||||||
|
API_EXPORT unsigned short API_CALL initRtmpServer(unsigned short port);
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////日志////////////////////////////////
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
//日志级别
|
||||||
|
LogTrace = 0, LogDebug, LogInfo, LogWarn, LogError, LogFatal,
|
||||||
|
} LogType;
|
||||||
|
|
||||||
|
typedef void(API_CALL *onLogOut)(const char *strLog, int iLogLen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:设置Log输出回调
|
||||||
|
* 参数:onLogOut:回调函数
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL log_setOnLogOut(onLogOut);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:设在日志显示级别
|
||||||
|
* 参数:level:日志级别
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL log_setLevel(LogType level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:打印日志
|
||||||
|
* 参数:level:日志级别;file:文件名称,function:函数名称,line:所在行数,fmt:格式化字符串
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL log_printf(LogType level, const char* file, const char* function, int line, const char *fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#define log_trace(fmt,...) log_printf(LogTrace,__FILE__,__FUNCTION__,__LINE__,fmt,__VA_ARGS__)
|
||||||
|
#define log_debug(fmt,...) log_printf(LogDebug,__FILE__,__FUNCTION__,__LINE__,fmt,__VA_ARGS__)
|
||||||
|
#define log_info(fmt,...) log_printf(LogInfo,__FILE__,__FUNCTION__,__LINE__,fmt,__VA_ARGS__)
|
||||||
|
#define log_warn(fmt,...) log_printf(LogWarn,__FILE__,__FUNCTION__,__LINE__,fmt,__VA_ARGS__)
|
||||||
|
#define log_error(fmt,...) log_printf(LogError,__FILE__,__FUNCTION__,__LINE__,fmt,__VA_ARGS__)
|
||||||
|
#define log_fatal(fmt,...) log_printf(LogFatal,__FILE__,__FUNCTION__,__LINE__,fmt,__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SRC_COMMON_H_ */
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
//
|
||||||
|
// Created by xzl on 2018/8/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "flvrecorder.h"
|
||||||
|
#include "Rtmp/FlvMuxer.h"
|
||||||
|
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
API_EXPORT FlvRecorderContex API_CALL createFlvRecorder(){
|
||||||
|
DebugL;
|
||||||
|
FlvRecorder::Ptr *ret = new FlvRecorder::Ptr(new FlvRecorder);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL releaseFlvRecorder(FlvRecorderContex ctx){
|
||||||
|
DebugL;
|
||||||
|
FlvRecorder::Ptr *record = (FlvRecorder::Ptr *)(ctx);
|
||||||
|
delete record;
|
||||||
|
}
|
||||||
|
API_EXPORT int API_CALL flvRecorder_start(FlvRecorderContex ctx,const char *appName,const char *streamName, const char *file_path){
|
||||||
|
DebugL << appName << " " << streamName << " " << file_path;
|
||||||
|
FlvRecorder::Ptr *record = (FlvRecorder::Ptr *)(ctx);
|
||||||
|
try {
|
||||||
|
(*record)->startRecord(DEFAULT_VHOST,appName,streamName,file_path);
|
||||||
|
return 0;
|
||||||
|
}catch (std::exception &ex){
|
||||||
|
WarnL << ex.what();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEDIAKITWRAPPER_FLVMUXER_H
|
||||||
|
#define MEDIAKITWRAPPER_FLVMUXER_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef void* FlvRecorderContex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建flv录制器
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
API_EXPORT FlvRecorderContex API_CALL createFlvRecorder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放flv录制器
|
||||||
|
* @param ctx
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL releaseFlvRecorder(FlvRecorderContex ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始录制flv
|
||||||
|
* @param ctx flv录制器
|
||||||
|
* @param appName 绑定的RtmpMediaSource的 app名
|
||||||
|
* @param streamName 绑定的RtmpMediaSource的 stream名
|
||||||
|
* @param file_path 文件存放地址
|
||||||
|
* @return 0:开始超过,-1:失败,打开文件失败或该RtmpMediaSource不存在
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL flvRecorder_start(FlvRecorderContex ctx,const char *appName,const char *streamName, const char *file_path);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MEDIAKITWRAPPER_FLVMUXER_H */
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "httpdownloader.h"
|
||||||
|
|
||||||
|
#include "Util/logger.h"
|
||||||
|
#include "Util/TimeTicker.h"
|
||||||
|
#include "Util/onceToken.h"
|
||||||
|
#include "Http/HttpDownloader.h"
|
||||||
|
#include "cleaner.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
static recursive_mutex s_mtxMapDownloader;
|
||||||
|
static unordered_map<void *, HttpDownloader::Ptr> s_mapDownloader;
|
||||||
|
|
||||||
|
static onceToken s_token([](){
|
||||||
|
cleaner::Instance().push_front([](){
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapDownloader);
|
||||||
|
s_mapDownloader.clear();
|
||||||
|
DebugL << "clear httpdownloader" << endl;
|
||||||
|
});
|
||||||
|
},nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
API_EXPORT HttpDownloaderContex API_CALL createDownloader(){
|
||||||
|
HttpDownloader::Ptr ret(new HttpDownloader());
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapDownloader);
|
||||||
|
s_mapDownloader.emplace(ret.get(),ret);
|
||||||
|
return ret.get();
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL downloader_startDownload(HttpDownloaderContex ctx,const char *url,downloader_onResult cb,void *userData){
|
||||||
|
downloader_startDownload_l(ctx,url,"",cb,userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL downloader_startDownload_l(HttpDownloaderContex ctx,const char *url,const char *file,downloader_onResult cb,void *userData){
|
||||||
|
HttpDownloader *ptr = (HttpDownloader *)ctx;
|
||||||
|
string urlTmp(url);
|
||||||
|
ptr->setOnResult([cb,userData,urlTmp](int code,const char *errMsg,const char *filePath){
|
||||||
|
if(cb){
|
||||||
|
InfoL << code << " " << errMsg << " " << filePath << " " << urlTmp;
|
||||||
|
cb(userData,code,errMsg,filePath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ptr->startDownload(url,file,false);
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL releaseDownloader(HttpDownloaderContex ctx){
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapDownloader);
|
||||||
|
s_mapDownloader.erase(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_HTTPDOWNLOADER_H_
|
||||||
|
#define SRC_HTTPDOWNLOADER_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////Httpdownloader/////////////////////////////////////////////////
|
||||||
|
typedef void * HttpDownloaderContex;
|
||||||
|
typedef void(API_CALL *downloader_onResult)(void *userData,int code,const char *errMsg,const char *filePath);
|
||||||
|
|
||||||
|
API_EXPORT HttpDownloaderContex API_CALL createDownloader();
|
||||||
|
API_EXPORT void API_CALL downloader_startDownload(HttpDownloaderContex ctx,const char *url,downloader_onResult cb,void *userData);
|
||||||
|
API_EXPORT void API_CALL downloader_startDownload_l(HttpDownloaderContex ctx,const char *url,const char *file,downloader_onResult cb,void *userData);
|
||||||
|
API_EXPORT void API_CALL releaseDownloader(HttpDownloaderContex ctx);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SRC_HTTPDOWNLOADER_H_ */
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "media.h"
|
||||||
|
#include "Util/logger.h"
|
||||||
|
#include "Util/TimeTicker.h"
|
||||||
|
#include "Util/onceToken.h"
|
||||||
|
#include "Device/Device.h"
|
||||||
|
#include "cleaner.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
static recursive_mutex s_mtxMapMedia;
|
||||||
|
static unordered_map<void *, DevChannel::Ptr> s_mapMedia;
|
||||||
|
|
||||||
|
static onceToken s_token([](){
|
||||||
|
cleaner::Instance().push_front([](){
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapMedia);
|
||||||
|
s_mapMedia.clear();
|
||||||
|
DebugL << "clear media" << endl;
|
||||||
|
});
|
||||||
|
},nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////Rtsp media///////////////////////////
|
||||||
|
API_EXPORT MediaContext API_CALL createMedia(const char *appName,const char *mediaName , float fDuration,int bEanbleHls, int bEnableMp4) {
|
||||||
|
DevChannel::Ptr ret(new DevChannel(DEFAULT_VHOST,appName,mediaName,fDuration,bEanbleHls,bEnableMp4));
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapMedia);
|
||||||
|
s_mapMedia.emplace((void *) (ret.get()), ret);
|
||||||
|
return ret.get();
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL releaseMedia(MediaContext ctx) {
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapMedia);
|
||||||
|
s_mapMedia.erase(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL media_initVideo(MediaContext ctx, int width, int height, int frameRate) {
|
||||||
|
DevChannel *ptr = (DevChannel *) ctx;
|
||||||
|
VideoInfo info;
|
||||||
|
info.iFrameRate = frameRate;
|
||||||
|
info.iWidth = width;
|
||||||
|
info.iHeight = height;
|
||||||
|
ptr->initVideo(info);
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL media_initAudio(MediaContext ctx, int channel, int sampleBit, int sampleRate,int profile) {
|
||||||
|
DevChannel *ptr = (DevChannel *) ctx;
|
||||||
|
AudioInfo info;
|
||||||
|
info.iSampleRate = sampleRate;
|
||||||
|
info.iChannel = channel;
|
||||||
|
info.iSampleBit = sampleBit;
|
||||||
|
info.iProfile = profile;
|
||||||
|
ptr->initAudio(info);
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL media_inputH264(MediaContext ctx, void *data, int len, unsigned long stamp) {
|
||||||
|
//TimeTicker();
|
||||||
|
DevChannel *ptr = (DevChannel *) ctx;
|
||||||
|
ptr->inputH264((char *) data, len, stamp);
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL media_inputAAC(MediaContext ctx, void *data, int len,unsigned long stamp,int withAdtsHeader) {
|
||||||
|
//TimeTicker();
|
||||||
|
DevChannel *ptr = (DevChannel *) ctx;
|
||||||
|
ptr->inputAAC((char *) data, len, stamp,withAdtsHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL media_inputAAC1(MediaContext ctx, void *data, int len, unsigned long stamp,void *adts){
|
||||||
|
DevChannel *ptr = (DevChannel *) ctx;
|
||||||
|
ptr->inputAAC((char *) data, len, stamp,(char *)adts);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL media_inputAAC2(MediaContext ctx, void *data, int len, unsigned long stamp,void *aac_cfg){
|
||||||
|
DevChannel *ptr = (DevChannel *) ctx;
|
||||||
|
AdtsFrame frame;
|
||||||
|
makeAdtsHeader((char*)aac_cfg, frame);
|
||||||
|
char adts[8];
|
||||||
|
writeAdtsHeader(frame, (uint8_t*)adts);
|
||||||
|
ptr->inputAAC((char *) data, len, stamp,(char *)adts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_MEDIA_H_
|
||||||
|
#define SRC_MEDIA_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////Rtsp media////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef void* MediaContext;
|
||||||
|
/*
|
||||||
|
* 描述:创建一个媒体源
|
||||||
|
* 参数:mediaName:媒体名称,url地址的一部分,fDuration:文件长度(单位秒),直播输入0,bEanbleHls:是否启用hls,bEnableMp4:是否录制mp4
|
||||||
|
* 返回值:媒体源句柄
|
||||||
|
*/
|
||||||
|
API_EXPORT MediaContext API_CALL createMedia(const char *appName,const char *mediaName,float fDuration,int bEanbleHls, int bEnableMp4);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:销毁媒体源
|
||||||
|
* 参数:ctx:媒体源句柄
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL releaseMedia(MediaContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:初始化媒体源的视频信息
|
||||||
|
* 参数:ctx:媒体源句柄;width:视频宽度;height:视频高度;frameRate:视频fps
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL media_initVideo(MediaContext ctx, int width, int height, int frameRate);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:初始化媒体源的音频信息
|
||||||
|
* 参数:ctx:媒体源句柄;channel:声道数;sampleBit:音频采样位数,支持16bit;sampleRate:音频采样率;profile:aac编码profile,在不输入adts头时用于生产adts头
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL media_initAudio(MediaContext ctx, int channel, int sampleBit, int sampleRate , int profile);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:输入单帧H264视频,需要输入SPS和PPS帧,帧起始字节00 00 01,00 00 00 01均可
|
||||||
|
* 参数:ctx:媒体源句柄;data:单帧H264数据;len:单帧H264数据字节数;stamp:时间戳,毫秒
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL media_inputH264(MediaContext ctx, void *data, int len, unsigned long stamp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:输入单帧AAC音频(有adts头)
|
||||||
|
* 参数:ctx:媒体源句柄;data:单帧AAC数据;len:单帧AAC数据字节数;stamp:时间戳,毫秒 ,withAdtsHeader:是否有adts头
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL media_inputAAC(MediaContext ctx, void *data, int len, unsigned long stamp,int withAdtsHeader);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:输入单帧AAC音频(单独指定adts头)
|
||||||
|
* 参数:ctx:媒体源句柄;data:单帧AAC数据;len:单帧AAC数据字节数;stamp:时间戳,毫秒;adts:adts头指针
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL media_inputAAC1(MediaContext ctx, void *data, int len, unsigned long stamp,void *adts);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:输入单帧AAC音频(指定2个字节的aac配置)
|
||||||
|
* 参数:ctx:媒体源句柄;data:单帧AAC数据;len:单帧AAC数据字节数;stamp:时间戳,毫秒;adts:adts头指针;aac_cfg:aac配置
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL media_inputAAC2(MediaContext ctx, void *data, int len, unsigned long stamp,void *aac_cfg);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SRC_MEDIA_H_ */
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_RTSPAPI_H_
|
||||||
|
#define SRC_RTSPAPI_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "httpdownloader.h"
|
||||||
|
#include "media.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "proxyplayer.h"
|
||||||
|
#include "flvrecorder.h"
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SRC_RTSPAPI_H_ */
|
||||||
|
|
@ -0,0 +1,345 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "player.h"
|
||||||
|
#include "Util/logger.h"
|
||||||
|
#include "Util/TimeTicker.h"
|
||||||
|
#include "Util/onceToken.h"
|
||||||
|
#include "Thread/ThreadPool.h"
|
||||||
|
#include "Poller/EventPoller.h"
|
||||||
|
#include "Player/MediaPlayer.h"
|
||||||
|
#include "H264/H264Parser.h"
|
||||||
|
#include "cleaner.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
static recursive_mutex s_mtxMapPlayer;
|
||||||
|
static unordered_map<void *, MediaPlayer::Ptr> s_mapPlayer;
|
||||||
|
|
||||||
|
static onceToken s_token([](){
|
||||||
|
cleaner::Instance().push_front([](){
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapPlayer);
|
||||||
|
s_mapPlayer.clear();
|
||||||
|
DebugL << "clear player" << endl;
|
||||||
|
});
|
||||||
|
},nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////rtsp player/////////////////////////////////////////
|
||||||
|
#define getPlayer(ctx) \
|
||||||
|
MediaPlayer::Ptr player;\
|
||||||
|
{\
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapPlayer);\
|
||||||
|
auto it = s_mapPlayer.find(ctx);\
|
||||||
|
if(it != s_mapPlayer.end()){\
|
||||||
|
player = it->second;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
API_EXPORT PlayerContext API_CALL createPlayer() {
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapPlayer);
|
||||||
|
MediaPlayer::Ptr ret(new MediaPlayer());
|
||||||
|
s_mapPlayer.emplace(ret.get(), ret);
|
||||||
|
if(s_mapPlayer.size() > 16){
|
||||||
|
ErrorL << s_mapPlayer.size();
|
||||||
|
}
|
||||||
|
return ret.get();
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL releasePlayer(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player_setOnGetAudio(ctx, nullptr, nullptr);
|
||||||
|
player_setOnGetVideo(ctx, nullptr, nullptr);
|
||||||
|
player_setOnPlayResult(ctx, nullptr, nullptr);
|
||||||
|
player_setOnShutdown(ctx, nullptr, nullptr);
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapPlayer);
|
||||||
|
s_mapPlayer.erase(ctx);
|
||||||
|
|
||||||
|
ASYNC_TRACE([player]() {
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapPlayer);
|
||||||
|
player->teardown();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL player_setOptionInt(PlayerContext ctx,const char* key,int val){
|
||||||
|
string keyTmp(key);
|
||||||
|
ASYNC_TRACE([ctx,keyTmp,val](){
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(*player)[keyTmp] = val;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL player_setOptionString(PlayerContext ctx,const char* key,const char *val){
|
||||||
|
string keyTmp(key);
|
||||||
|
string valTmp(val);
|
||||||
|
ASYNC_TRACE([ctx,keyTmp,valTmp](){
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(*player)[keyTmp] = valTmp;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL player_play(PlayerContext ctx, const char* url) {
|
||||||
|
string urlTmp(url);
|
||||||
|
ASYNC_TRACE([ctx,urlTmp](){
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player->play(urlTmp.data());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL player_pause(PlayerContext ctx, int pause) {
|
||||||
|
ASYNC_TRACE([ctx,pause](){
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player->pause(pause);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL player_seekTo(PlayerContext ctx, float fProgress) {
|
||||||
|
ASYNC_TRACE([ctx,fProgress]() {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return player->seekTo(fProgress);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL player_setOnShutdown(PlayerContext ctx, player_onResult cb, void *userData) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(cb){
|
||||||
|
SYNC_TRACE([&](){
|
||||||
|
player->setOnShutdown([cb,userData](const SockException &ex) {
|
||||||
|
cb(userData,ex.getErrCode(),ex.what());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
SYNC_TRACE([&](){
|
||||||
|
player->setOnShutdown(nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL player_setOnPlayResult(PlayerContext ctx, player_onResult cb, void *userData) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cb) {
|
||||||
|
SYNC_TRACE([&](){
|
||||||
|
player->setOnPlayResult([cb,userData](const SockException &ex) {
|
||||||
|
cb(userData,ex.getErrCode(),ex.what());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SYNC_TRACE([&](){
|
||||||
|
player->setOnPlayResult(nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL player_setOnGetVideo(PlayerContext ctx, player_onGetH264 cb,
|
||||||
|
void *userData) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cb) {
|
||||||
|
std::shared_ptr<H264Parser> pParser(new H264Parser());
|
||||||
|
SYNC_TRACE([&](){
|
||||||
|
player->setOnVideoCB([cb,userData,pParser](const H264Frame &frame) {
|
||||||
|
pParser->inputH264(frame.data, frame.timeStamp);
|
||||||
|
cb(userData, (void *)frame.data.data(), frame.data.size(), frame.timeStamp,pParser->getPts());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SYNC_TRACE([&](){
|
||||||
|
player->setOnVideoCB(nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL player_setOnGetAudio(PlayerContext ctx, player_onGetAAC cb,
|
||||||
|
void *userData) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cb) {
|
||||||
|
SYNC_TRACE([&](){
|
||||||
|
player->setOnAudioCB([cb,userData](const AdtsFrame &frame) {
|
||||||
|
cb(userData, (void *)frame.data, frame.aac_frame_length, frame.timeStamp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SYNC_TRACE([&](){
|
||||||
|
player->setOnAudioCB(nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_getVideoWidth(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getVideoWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_getVideoHeight(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getVideoHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_getVideoFps(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getVideoFps();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_getAudioSampleRate(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getAudioSampleRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_getAudioSampleBit(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getAudioSampleBit();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_getAudioChannel(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getAudioChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_getH264PPS(PlayerContext ctx, char *buf, int bufsize) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bufsize < (int) player->getPps().size() || player->getPps().empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(buf, player->getPps().data(), player->getPps().size());
|
||||||
|
return player->getPps().size();
|
||||||
|
}
|
||||||
|
API_EXPORT int API_CALL player_getH264SPS(PlayerContext ctx, char *buf, int bufsize) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bufsize < (int) player->getSps().size() || player->getSps().empty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(buf, player->getSps().data(), player->getSps().size());
|
||||||
|
return player->getSps().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_getAacCfg(PlayerContext ctx, char *buf, int bufsize) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bufsize < (int) player->getAudioCfg().size()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(buf, player->getAudioCfg().data(), player->getAudioCfg().size());
|
||||||
|
return player->getAudioCfg().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_containAudio(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->containAudio();
|
||||||
|
|
||||||
|
}
|
||||||
|
API_EXPORT int API_CALL player_containVideo(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->containVideo();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL player_isInited(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->isInited();
|
||||||
|
}
|
||||||
|
API_EXPORT float API_CALL player_getDuration(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT float API_CALL player_getProgress(PlayerContext ctx) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT float API_CALL player_getLossRate(PlayerContext ctx, int trackId) {
|
||||||
|
getPlayer(ctx);
|
||||||
|
if (!player) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return player->getRtpLossRate(trackId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_PLAYER_H_
|
||||||
|
#define SRC_PLAYER_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////RTSP Player/////////////////////////////////////////////////
|
||||||
|
typedef void* PlayerContext;
|
||||||
|
typedef void(API_CALL *player_onResult)(void *userData,int errCode,const char *errMsg);
|
||||||
|
typedef void(API_CALL *player_onGetAAC)(void *userData,void *data,int len,unsigned long timeStamp);
|
||||||
|
typedef void(API_CALL *player_onGetH264)(void *userData,void *data,int len,unsigned long dts,unsigned long pts);
|
||||||
|
/*
|
||||||
|
* 描述:创建一个Rtsp播放器
|
||||||
|
* 参数:无
|
||||||
|
* 返回值:Rtsp播放器句柄
|
||||||
|
*/
|
||||||
|
API_EXPORT PlayerContext API_CALL createPlayer();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:销毁一个播放器
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL releasePlayer(PlayerContext ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:设置播放器配置选项
|
||||||
|
* 参数: ctx:播放器句柄
|
||||||
|
* key:配置项键,例如 rtp_type
|
||||||
|
* val:值,例如 //设置rtp传输类型,可选项有0(tcp,默认)、1(udp)、2(组播)
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL player_setOptionInt(PlayerContext ctx,const char* key,int val);
|
||||||
|
API_EXPORT void API_CALL player_setOptionString(PlayerContext ctx,const char* key,const char *val);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:播放rtsp链接(仅支持H264与AAC负载)
|
||||||
|
* 参数: ctx:播放器句柄
|
||||||
|
* url:rtsp链接
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL player_play(PlayerContext ctx,const char* url);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:暂停播放RTSP
|
||||||
|
* 参数:ctx:播放器句柄;pause:1:暂停播放,0:恢复播放
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL player_pause(PlayerContext ctx,int pause);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:设置播放器异常停止回调函数
|
||||||
|
* 参数:ctx:播放器句柄;cb:回调函数指针;userData:用户数据指针
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL player_setOnShutdown(PlayerContext ctx,player_onResult cb,void *userData);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:设置播放器播放结果回调函数
|
||||||
|
* 参数:ctx:播放器句柄,cb:回调函数指针;userData:用户数据指针
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL player_setOnPlayResult(PlayerContext ctx,player_onResult cb,void *userData);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:设置播放器收到视频帧回调,I帧前为SPS,PPS帧;每帧包含00 00 00 01的帧头
|
||||||
|
* 参数:ctx:播放器句柄,cb:回调函数指针;userData:用户数据指针
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL player_setOnGetVideo(PlayerContext ctx,player_onGetH264 cb,void *userData);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:设置播放器收到音频帧回调,每帧数据包含ADTS头
|
||||||
|
* 参数:ctx:播放器句柄,cb:回调函数指针;userData:用户数据指针
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL player_setOnGetAudio(PlayerContext ctx,player_onGetAAC cb,void *userData);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取视频宽度
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:视频宽度
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_getVideoWidth(PlayerContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取视频高度
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:视频高度
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL API_CALL player_getVideoHeight(PlayerContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取视频帧率
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:视频帧率
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_getVideoFps(PlayerContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取音频采样率
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:音频采样率
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_getAudioSampleRate(PlayerContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取音频采样位数(8bit或16bit)
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:音频采样位数
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_getAudioSampleBit(PlayerContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取音频通道数(单声道1,双声道2)
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:音频通道数
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_getAudioChannel(PlayerContext ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取H264的PPS帧
|
||||||
|
* 参数:ctx:播放器句柄,buf:存放PPS数据的缓存;bufsize:缓存大小
|
||||||
|
* 返回值:帧数据长度
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_getH264PPS(PlayerContext ctx,char *buf,int bufsize);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取H264的SPS帧
|
||||||
|
* 参数:ctx:播放器句柄,buf:存放SPS数据的缓存;bufsize:缓存大小
|
||||||
|
* 返回值:帧数据长度
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_getH264SPS(PlayerContext ctx,char *buf,int bufsize);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取AAC编码配置信息
|
||||||
|
* 参数:ctx:播放器句柄;buf:存放CFG数据的缓存;bufsize:缓存大小
|
||||||
|
* 返回值:CFG数据长度
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_getAacCfg(PlayerContext ctx,char *buf,int bufsize);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:是否包含音频数据
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:1:包含,0:不包含
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_containAudio(PlayerContext ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:是否包含视频数据
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:1:包含,0:不包含
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_containVideo(PlayerContext ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:是否已经初始化完成(获取完整的播放信息)
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:1:初始化完成,0:未完成
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL player_isInited(PlayerContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取点播的时间长度,单位为秒(小于等于0,说明是直播,否则为点播)
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:点播的时间长度,单位秒
|
||||||
|
*/
|
||||||
|
API_EXPORT float API_CALL player_getDuration(PlayerContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取点播播放进度
|
||||||
|
* 参数:ctx:播放器句柄
|
||||||
|
* 返回值:点播播放进度,取值范围未 0.0~1.0
|
||||||
|
*/
|
||||||
|
API_EXPORT float API_CALL player_getProgress(PlayerContext ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:设置点播播放进度
|
||||||
|
* 参数:ctx:播放器句柄;fProgress:播放进度,取值范围未 0.0~1.0
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL player_seekTo(PlayerContext ctx, float fProgress);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:获取丢包率
|
||||||
|
* 参数:ctx:播放器句柄;trackId:如果是-1,则返回总丢包率,否则返回视频或者音频的丢包率
|
||||||
|
* 返回值:丢包率
|
||||||
|
*/
|
||||||
|
API_EXPORT float API_CALL player_getLossRate(PlayerContext ctx,int trackId);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SRC_PLAYER_H_ */
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "cleaner.h"
|
||||||
|
#include "proxyplayer.h"
|
||||||
|
#include "Device/PlayerProxy.h"
|
||||||
|
#include "Util/onceToken.h"
|
||||||
|
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
static recursive_mutex s_mtxMapProxyPlayer;
|
||||||
|
static unordered_map<void *, PlayerProxy::Ptr> s_mapProxyPlayer;
|
||||||
|
|
||||||
|
static onceToken s_token([](){
|
||||||
|
cleaner::Instance().push_front([](){
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapProxyPlayer);
|
||||||
|
s_mapProxyPlayer.clear();
|
||||||
|
DebugL << "clear proxyplayer" << endl;
|
||||||
|
});
|
||||||
|
},nullptr);
|
||||||
|
|
||||||
|
API_EXPORT ProxyPlayerContext API_CALL createProxyPlayer(const char *app,const char *stream,int rtp_type){
|
||||||
|
PlayerProxy::Ptr ret(new PlayerProxy(DEFAULT_VHOST,app,stream));
|
||||||
|
(*ret)[RtspPlayer::kRtpType] = rtp_type;
|
||||||
|
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapProxyPlayer);
|
||||||
|
s_mapProxyPlayer.emplace(ret.get(),ret);
|
||||||
|
return ret.get();
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL releaseProxyPlayer(ProxyPlayerContext ctx){
|
||||||
|
lock_guard<recursive_mutex> lck(s_mtxMapProxyPlayer);
|
||||||
|
s_mapProxyPlayer.erase(ctx);
|
||||||
|
}
|
||||||
|
API_EXPORT void API_CALL proxyPlayer_play(ProxyPlayerContext ctx,const char *url){
|
||||||
|
PlayerProxy *ptr = (PlayerProxy *)ctx;
|
||||||
|
ptr->play(url);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRC_PROXYPLAYER_H_
|
||||||
|
#define SRC_PROXYPLAYER_H_
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void* ProxyPlayerContext;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:创建一个代理播放器
|
||||||
|
* 参数:app:应用名,生成url的一部分,rtsp://127.0.0.1/app/xxxx
|
||||||
|
* stream:媒体流名,生成url的一部分,rtsp://127.0.0.1/xxxx/stream
|
||||||
|
* rtp_type:如果播放的是rtsp连接则通过该参数配置设置rtp传输方式:RTP_TCP = 0, RTP_UDP = 1, RTP_MULTICAST = 2
|
||||||
|
* 返回值:代理播放器句柄
|
||||||
|
*/
|
||||||
|
API_EXPORT ProxyPlayerContext API_CALL createProxyPlayer(const char *app,const char *stream,int rtp_type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:销毁代理播放器
|
||||||
|
* 参数:ctx:代理播放器句柄
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL releaseProxyPlayer(ProxyPlayerContext ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 描述:开始播放
|
||||||
|
* 参数:url:rtsp/rtmp连接
|
||||||
|
* 返回值:无
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL proxyPlayer_play(ProxyPlayerContext ctx,const char *url);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SRC_PROXYPLAYER_H_ */
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
aux_source_directory(. TEST_SRC_LIST)
|
||||||
|
foreach(TEST_SRC ${TEST_SRC_LIST})
|
||||||
|
STRING(REGEX REPLACE "^\\./|\\.c[a-zA-Z0-9_]*$" "" TEST_EXE_NAME ${TEST_SRC})
|
||||||
|
message(STATUS "添加测试程序:${TEST_EXE_NAME}")
|
||||||
|
add_executable(${TEST_EXE_NAME} ${TEST_SRC})
|
||||||
|
|
||||||
|
if(ANDROID)
|
||||||
|
target_link_libraries(${TEST_EXE_NAME} ${CMAKE_PROJECT_NAME}_static ${LINK_LIB_LIST})
|
||||||
|
elseif(WIN32)
|
||||||
|
target_link_libraries(${TEST_EXE_NAME} ${CMAKE_PROJECT_NAME}_shared ${LINK_LIB_LIST})
|
||||||
|
else()
|
||||||
|
target_link_libraries(${TEST_EXE_NAME} ${CMAKE_PROJECT_NAME}_shared ${LINK_LIB_LIST} pthread)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endforeach(TEST_SRC ${TEST_SRC_LIST})
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "mediakit.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
|
||||||
|
void *media = nullptr;
|
||||||
|
|
||||||
|
int main(int argc,char *argv[]){
|
||||||
|
//设置退出信号处理函数
|
||||||
|
signal(SIGINT, [](int){});
|
||||||
|
////////init environment////////////////////////////////////////////////////////////////
|
||||||
|
onAppStart();
|
||||||
|
////////init service/////////////////////////////////////////////////////////////////////
|
||||||
|
initHttpServer(80);
|
||||||
|
initRtmpServer(1935);
|
||||||
|
initRtspServer(554);
|
||||||
|
////////ProxyPlayer////////////////////////////////////////////////////////////////////////
|
||||||
|
auto proxy = createProxyPlayer("app","proxy",0);
|
||||||
|
proxyPlayer_play(proxy,"rtmp://live.hkstv.hk.lxdns.com/live/hks");
|
||||||
|
log_warn("%s","请打开vlc播放:rtsp://127.0.0.1/app/proxy "
|
||||||
|
"rtmp://127.0.0.1/app/proxy "
|
||||||
|
"http://127.0.0.1/app/proxy/hls.m3u8");
|
||||||
|
////////http downloader////////////////////////////////////////////////////////////////////
|
||||||
|
auto downloader = createDownloader();
|
||||||
|
downloader_startDownload(downloader,
|
||||||
|
"http://pic4.nipic.com/20091121/3764872_215617048242_2.jpg",
|
||||||
|
[](void *userData,int code,const char *errMsg,const char *filePath){
|
||||||
|
log_info("下载结果:%d-%s:%s",code,errMsg,filePath);
|
||||||
|
}, downloader);
|
||||||
|
////////player//////////////////////////////////////////////////////////////////////////////
|
||||||
|
auto player = createPlayer();
|
||||||
|
|
||||||
|
player_setOnPlayResult(player,[](void *userData,int errCode,const char *errMsg){
|
||||||
|
log_info("播放结果:%d-%s",errCode,errMsg);
|
||||||
|
|
||||||
|
////////media/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if(errCode){
|
||||||
|
//play failed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto player = userData;
|
||||||
|
media = createMedia("app","media",0,0,0);
|
||||||
|
if(player_containAudio(player) == 1){
|
||||||
|
media_initAudio(media,
|
||||||
|
player_getAudioChannel(player),
|
||||||
|
player_getAudioSampleBit(player),
|
||||||
|
player_getAudioSampleRate(player),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(player_containVideo(player) == 1){
|
||||||
|
media_initVideo(media,
|
||||||
|
player_getVideoWidth(player),
|
||||||
|
player_getVideoHeight(player),
|
||||||
|
player_getVideoFps(player));
|
||||||
|
}
|
||||||
|
log_warn("%s","请打开vlc播放:rtsp://127.0.0.1/app/media "
|
||||||
|
"rtmp://127.0.0.1/app/media "
|
||||||
|
"http://127.0.0.1/app/media/hls.m3u8");
|
||||||
|
},player);
|
||||||
|
|
||||||
|
player_setOnShutdown(player,[](void *userData,int errCode,const char *errMsg){
|
||||||
|
log_info("播放器异常断开:%d-%s",errCode,errMsg);
|
||||||
|
|
||||||
|
if(media){
|
||||||
|
releaseMedia(media);
|
||||||
|
}
|
||||||
|
},player);
|
||||||
|
|
||||||
|
player_setOnGetAudio(player,[](void *userData,void *data,int len,unsigned long timeStamp){
|
||||||
|
//在此解码视频
|
||||||
|
//TO-DO
|
||||||
|
//log_trace("audio:%d-%d",len,timeStamp);
|
||||||
|
|
||||||
|
////////输入aac///////////
|
||||||
|
if(media){
|
||||||
|
media_inputAAC(media,data,len,timeStamp,1);
|
||||||
|
}
|
||||||
|
},player);
|
||||||
|
|
||||||
|
player_setOnGetVideo(player,[](void *userData,void *data,int len,unsigned long dts,unsigned long pts){
|
||||||
|
//在此解码音频
|
||||||
|
//TO-DO
|
||||||
|
//log_trace("video:%d-%d-%d",len,dts,pts);
|
||||||
|
|
||||||
|
////////输入264///////////
|
||||||
|
if(media){
|
||||||
|
media_inputH264(media,data,len,dts);
|
||||||
|
}
|
||||||
|
},player);
|
||||||
|
|
||||||
|
player_play(player,"rtmp://live.hkstv.hk.lxdns.com/live/hks");
|
||||||
|
|
||||||
|
|
||||||
|
//sleep forever
|
||||||
|
sleep(UINT32_MAX);
|
||||||
|
////////uninit environment////////////////////////////////////////////////////////////////////
|
||||||
|
onAppExit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
|
||||||
|
find_path(JEMALLOC_INCLUDE_DIR
|
||||||
|
NAMES jemalloc/jemalloc.h
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(JEMALLOC_LIBRARY
|
||||||
|
NAMES jemalloc
|
||||||
|
)
|
||||||
|
|
||||||
|
set(JEMALLOC_INCLUDE_DIRS ${JEMALLOC_INCLUDE_DIR})
|
||||||
|
set(JEMALLOC_LIBRARIES ${JEMALLOC_LIBRARY})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(JEMALLOC DEFAULT_MSG JEMALLOC_LIBRARY JEMALLOC_INCLUDE_DIR)
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
include(CheckCXXSourceCompiles)
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
find_path(MYSQL_INCLUDE_DIR mysql/mysql.h
|
find_path(MYSQL_INCLUDE_DIR mysql.h
|
||||||
PATHS
|
PATHS
|
||||||
$ENV{MYSQL_INCLUDE_DIR}
|
$ENV{MYSQL_INCLUDE_DIR}
|
||||||
$ENV{MYSQL_DIR}/include
|
$ENV{MYSQL_DIR}/include
|
||||||
|
|
@ -64,6 +64,7 @@ if(WIN32)
|
||||||
$ENV{MYSQL_DIR}/lib/opt
|
$ENV{MYSQL_DIR}/lib/opt
|
||||||
$ENV{MYSQL_DIR}/client/release
|
$ENV{MYSQL_DIR}/client/release
|
||||||
$ENV{ProgramFiles}/MySQL/*/lib/opt
|
$ENV{ProgramFiles}/MySQL/*/lib/opt
|
||||||
|
$ENV{ProgramFiles}/MySQL/*/lib/
|
||||||
$ENV{SystemDrive}/MySQL/*/lib/opt
|
$ENV{SystemDrive}/MySQL/*/lib/opt
|
||||||
$ENV{ProgramW6432}/MySQL/*/lib
|
$ENV{ProgramW6432}/MySQL/*/lib
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
find_path(SDL2_INCLUDE_DIR
|
||||||
|
NAMES SDL2/SDL.h
|
||||||
|
HINTS SDL2
|
||||||
|
PATHS $ENV{HOME}/sdl2/include)
|
||||||
|
|
||||||
|
find_library(SDL2_LIBRARY
|
||||||
|
NAMES SDL2
|
||||||
|
PATHS $ENV{HOME}/sdl2/lib/x86)
|
||||||
|
|
||||||
|
set(SDL2_LIBRARIES ${SDL2_LIBRARY})
|
||||||
|
set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
find_package_handle_standard_args(SDL2 DEFAULT_MSG SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||||
|
|
@ -1,8 +1,14 @@
|
||||||
find_path(ZLTOOLKIT_INCLUDE_DIR
|
find_path(ZLTOOLKIT_INCLUDE_DIR
|
||||||
NAMES ZLToolKit/Network/Socket.h)
|
NAMES Network/Socket.h
|
||||||
|
PATHS
|
||||||
|
${PROJECT_SOURCE_DIR}/../ZLToolKit/src
|
||||||
|
$ENV{HOME}/ZLToolKit/include)
|
||||||
|
|
||||||
find_library(ZLTOOLKIT_LIBRARY
|
find_library(ZLTOOLKIT_LIBRARY
|
||||||
NAMES ZLToolKit)
|
NAMES ZLToolKit
|
||||||
|
PATHS
|
||||||
|
${PROJECT_SOURCE_DIR}/../ZLToolKit/build/lib
|
||||||
|
$ENV{HOME}/ZLToolKit/lib)
|
||||||
|
|
||||||
set(ZLTOOLKIT_LIBRARIES ${ZLTOOLKIT_LIBRARY})
|
set(ZLTOOLKIT_LIBRARIES ${ZLTOOLKIT_LIBRARY})
|
||||||
set(ZLTOOLKIT_INCLUDE_DIRS ${ZLTOOLKIT_INCLUDE_DIR})
|
set(ZLTOOLKIT_INCLUDE_DIRS ${ZLTOOLKIT_INCLUDE_DIR})
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,9 +1,29 @@
|
||||||
/*
|
/*
|
||||||
* AACEncoder.cpp
|
* MIT License
|
||||||
*
|
*
|
||||||
* Created on: 2016年8月11日
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
* Author: xzl
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef ENABLE_FAAC
|
#ifdef ENABLE_FAAC
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
@ -18,27 +38,26 @@ extern "C" {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace ZL::Util;
|
using namespace toolkit;
|
||||||
|
|
||||||
namespace ZL {
|
namespace mediakit {
|
||||||
namespace Codec {
|
|
||||||
|
|
||||||
AACEncoder::AACEncoder() {
|
AACEncoder::AACEncoder() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AACEncoder::~AACEncoder() {
|
AACEncoder::~AACEncoder() {
|
||||||
if (m_hEncoder != nullptr) {
|
if (_hEncoder != nullptr) {
|
||||||
faacEncClose(m_hEncoder);
|
faacEncClose(_hEncoder);
|
||||||
m_hEncoder = nullptr;
|
_hEncoder = nullptr;
|
||||||
}
|
}
|
||||||
if (m_pucAacBuf != nullptr) {
|
if (_pucAacBuf != nullptr) {
|
||||||
delete[] m_pucAacBuf;
|
delete[] _pucAacBuf;
|
||||||
m_pucAacBuf = nullptr;
|
_pucAacBuf = nullptr;
|
||||||
}
|
}
|
||||||
if (m_pucPcmBuf != nullptr) {
|
if (_pucPcmBuf != nullptr) {
|
||||||
delete[] m_pucPcmBuf;
|
delete[] _pucPcmBuf;
|
||||||
m_pucPcmBuf = nullptr;
|
_pucPcmBuf = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,19 +66,19 @@ bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// (1) Open FAAC engine
|
// (1) Open FAAC engine
|
||||||
m_hEncoder = faacEncOpen(iSampleRate, iChannels, &m_ulInputSamples,
|
_hEncoder = faacEncOpen(iSampleRate, iChannels, &_ulInputSamples,
|
||||||
&m_ulMaxOutputBytes);
|
&_ulMaxOutputBytes);
|
||||||
if (m_hEncoder == NULL) {
|
if (_hEncoder == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_pucAacBuf = new unsigned char[m_ulMaxOutputBytes];
|
_pucAacBuf = new unsigned char[_ulMaxOutputBytes];
|
||||||
m_ulMaxInputBytes = m_ulInputSamples * iSampleBit / 8;
|
_ulMaxInputBytes = _ulInputSamples * iSampleBit / 8;
|
||||||
m_pucPcmBuf = new unsigned char[m_ulMaxInputBytes * 4];
|
_pucPcmBuf = new unsigned char[_ulMaxInputBytes * 4];
|
||||||
|
|
||||||
// (2.1) Get current encoding configuration
|
// (2.1) Get current encoding configuration
|
||||||
faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(m_hEncoder);
|
faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(_hEncoder);
|
||||||
if (pConfiguration == NULL) {
|
if (pConfiguration == NULL) {
|
||||||
faacEncClose(m_hEncoder);
|
faacEncClose(_hEncoder);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pConfiguration->aacObjectType =LOW;
|
pConfiguration->aacObjectType =LOW;
|
||||||
|
|
@ -75,30 +94,29 @@ bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
|
||||||
pConfiguration->inputFormat = FAAC_INPUT_16BIT;
|
pConfiguration->inputFormat = FAAC_INPUT_16BIT;
|
||||||
|
|
||||||
// (2.2) Set encoding configuration
|
// (2.2) Set encoding configuration
|
||||||
if(!faacEncSetConfiguration(m_hEncoder, pConfiguration)){
|
if(!faacEncSetConfiguration(_hEncoder, pConfiguration)){
|
||||||
ErrorL << "faacEncSetConfiguration failed";
|
ErrorL << "faacEncSetConfiguration failed";
|
||||||
faacEncClose(m_hEncoder);
|
faacEncClose(_hEncoder);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AACEncoder::inputData(char *pcPcmBufr, int iLen, unsigned char **ppucOutBuffer) {
|
int AACEncoder::inputData(char *pcPcmBufr, int iLen, unsigned char **ppucOutBuffer) {
|
||||||
memcpy(m_pucPcmBuf + m_uiPcmLen, pcPcmBufr, iLen);
|
memcpy(_pucPcmBuf + _uiPcmLen, pcPcmBufr, iLen);
|
||||||
m_uiPcmLen += iLen;
|
_uiPcmLen += iLen;
|
||||||
if (m_uiPcmLen < m_ulMaxInputBytes) {
|
if (_uiPcmLen < _ulMaxInputBytes) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nRet = faacEncEncode(m_hEncoder, (int32_t *) (m_pucPcmBuf), m_ulInputSamples, m_pucAacBuf, m_ulMaxOutputBytes);
|
int nRet = faacEncEncode(_hEncoder, (int32_t *) (_pucPcmBuf), _ulInputSamples, _pucAacBuf, _ulMaxOutputBytes);
|
||||||
m_uiPcmLen -= m_ulMaxInputBytes;
|
_uiPcmLen -= _ulMaxInputBytes;
|
||||||
memmove(m_pucPcmBuf, m_pucPcmBuf + m_ulMaxInputBytes, m_uiPcmLen);
|
memmove(_pucPcmBuf, _pucPcmBuf + _ulMaxInputBytes, _uiPcmLen);
|
||||||
*ppucOutBuffer = m_pucAacBuf;
|
*ppucOutBuffer = _pucAacBuf;
|
||||||
return nRet;
|
return nRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace Codec */
|
} /* namespace mediakit */
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif //ENABLE_FAAC
|
#endif //ENABLE_FAAC
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,34 @@
|
||||||
/*
|
/*
|
||||||
* AACEncoder.h
|
* MIT License
|
||||||
*
|
*
|
||||||
* Created on: 2016年8月11日
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
* Author: xzl
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef CODEC_AACENCODER_H_
|
#ifndef CODEC_AACENCODER_H_
|
||||||
#define CODEC_AACENCODER_H_
|
#define CODEC_AACENCODER_H_
|
||||||
|
|
||||||
namespace ZL {
|
namespace mediakit {
|
||||||
namespace Codec {
|
|
||||||
|
|
||||||
class AACEncoder {
|
class AACEncoder {
|
||||||
public:
|
public:
|
||||||
|
|
@ -19,19 +38,18 @@ public:
|
||||||
int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer);
|
int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned char *m_pucPcmBuf = nullptr;
|
unsigned char *_pucPcmBuf = nullptr;
|
||||||
unsigned int m_uiPcmLen = 0;
|
unsigned int _uiPcmLen = 0;
|
||||||
|
|
||||||
unsigned char *m_pucAacBuf = nullptr;
|
unsigned char *_pucAacBuf = nullptr;
|
||||||
void *m_hEncoder = nullptr;
|
void *_hEncoder = nullptr;
|
||||||
|
|
||||||
unsigned long m_ulInputSamples = 0;
|
unsigned long _ulInputSamples = 0;
|
||||||
unsigned long m_ulMaxInputBytes = 0;
|
unsigned long _ulMaxInputBytes = 0;
|
||||||
unsigned long m_ulMaxOutputBytes = 0;
|
unsigned long _ulMaxOutputBytes = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace Codec */
|
} /* namespace mediakit */
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* CODEC_AACENCODER_H_ */
|
#endif /* CODEC_AACENCODER_H_ */
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,37 @@
|
||||||
/*
|
/*
|
||||||
* H264Encoder.cpp
|
* MIT License
|
||||||
*
|
*
|
||||||
* Created on: 2016年8月11日
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
* Author: xzl
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef ENABLE_X264
|
#ifdef ENABLE_X264
|
||||||
#include "H264Encoder.h"
|
#include "H264Encoder.h"
|
||||||
|
|
||||||
#include "Util/TimeTicker.h"
|
#include "Util/TimeTicker.h"
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace ZL {
|
using namespace toolkit;
|
||||||
namespace Codec {
|
|
||||||
|
namespace mediakit {
|
||||||
|
|
||||||
H264Encoder::H264Encoder() {
|
H264Encoder::H264Encoder() {
|
||||||
|
|
||||||
|
|
@ -19,19 +39,19 @@ H264Encoder::H264Encoder() {
|
||||||
|
|
||||||
H264Encoder::~H264Encoder() {
|
H264Encoder::~H264Encoder() {
|
||||||
//* 清除图像区域
|
//* 清除图像区域
|
||||||
if (m_pPicIn) {
|
if (_pPicIn) {
|
||||||
delete m_pPicIn;
|
delete _pPicIn;
|
||||||
m_pPicIn = nullptr;
|
_pPicIn = nullptr;
|
||||||
}
|
}
|
||||||
if (m_pPicOut) {
|
if (_pPicOut) {
|
||||||
delete m_pPicOut;
|
delete _pPicOut;
|
||||||
m_pPicOut = nullptr;
|
_pPicOut = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//* 关闭编码器句柄
|
//* 关闭编码器句柄
|
||||||
if (m_pX264Handle) {
|
if (_pX264Handle) {
|
||||||
x264_encoder_close(m_pX264Handle);
|
x264_encoder_close(_pX264Handle);
|
||||||
m_pX264Handle = nullptr;
|
_pX264Handle = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,20 +77,20 @@ Vui参数集视频可用性信息视频标准化选项
|
||||||
int i_sar_height;
|
int i_sar_height;
|
||||||
int i_sar_width; 设置长宽比
|
int i_sar_width; 设置长宽比
|
||||||
|
|
||||||
int i_overscan; 0=undef, 1=no overscan, 2=overscan 过扫描线,默认"undef"(不设置),可选项:show(观看)/crop(去除)
|
int i_overscan; 0=undef, 1=no overscan, 2=overscan 过扫描线,默认"undef"(不设置),可选项:show(观看)/crop(去除)
|
||||||
|
|
||||||
见以下的值h264附件E
|
见以下的值h264附件E
|
||||||
Int i_vidformat; 视频格式,默认"undef",component/pal/ntsc/secam/mac/undef
|
Int i_vidformat; 视频格式,默认"undef",component/pal/ntsc/secam/mac/undef
|
||||||
int b_fullrange; Specify full range samples setting,默认"off",可选项:off/on
|
int b_fullrange; Specify full range samples setting,默认"off",可选项:off/on
|
||||||
int i_colorprim; 原始色度格式,默认"undef",可选项:undef/bt709/bt470m/bt470bg,smpte170m/smpte240m/film
|
int i_colorprim; 原始色度格式,默认"undef",可选项:undef/bt709/bt470m/bt470bg,smpte170m/smpte240m/film
|
||||||
int i_transfer; 转换方式,默认"undef",可选项:undef/bt709/bt470m/bt470bg/linear,log100/log316/smpte170m/smpte240m
|
int i_transfer; 转换方式,默认"undef",可选项:undef/bt709/bt470m/bt470bg/linear,log100/log316/smpte170m/smpte240m
|
||||||
int i_colmatrix; 色度矩阵设置,默认"undef",undef/bt709/fcc/bt470bg,smpte170m/smpte240m/GBR/YCgCo
|
int i_colmatrix; 色度矩阵设置,默认"undef",undef/bt709/fcc/bt470bg,smpte170m/smpte240m/GBR/YCgCo
|
||||||
int i_chroma_loc; both top & bottom色度样本指定,范围0~5,默认0
|
int i_chroma_loc; both top & bottom色度样本指定,范围0~5,默认0
|
||||||
} vui;
|
} vui;
|
||||||
|
|
||||||
int i_fps_num;
|
int i_fps_num;
|
||||||
int i_fps_den;
|
int i_fps_den;
|
||||||
这两个参数是由fps帧率确定的,赋值的过程见下:
|
这两个参数是由fps帧率确定的,赋值的过程见下:
|
||||||
{ float fps;
|
{ float fps;
|
||||||
if( sscanf( value, "%d/%d", &p->i_fps_num, &p->i_fps_den ) == 2 )
|
if( sscanf( value, "%d/%d", &p->i_fps_num, &p->i_fps_den ) == 2 )
|
||||||
;
|
;
|
||||||
|
|
@ -137,7 +157,7 @@ Value的值就是fps。
|
||||||
int i_subpel_refine; 亚像素运动估计质量
|
int i_subpel_refine; 亚像素运动估计质量
|
||||||
int b_chroma_me; 亚像素色度运动估计和P帧的模式选择
|
int b_chroma_me; 亚像素色度运动估计和P帧的模式选择
|
||||||
int b_mixed_references; 允许每个宏块的分区在P帧有它自己的参考号
|
int b_mixed_references; 允许每个宏块的分区在P帧有它自己的参考号
|
||||||
int i_trellis; Trellis量化,对每个8x8的块寻找合适的量化值,需要CABAC,默认0 0:关闭1:只在最后编码时使用2:一直使用
|
int i_trellis; Trellis量化,对每个8x8的块寻找合适的量化值,需要CABAC,默认0 0:关闭1:只在最后编码时使用2:一直使用
|
||||||
int b_fast_pskip; 快速P帧跳过检测
|
int b_fast_pskip; 快速P帧跳过检测
|
||||||
int b_dct_decimate; 在P-frames转换参数域
|
int b_dct_decimate; 在P-frames转换参数域
|
||||||
int i_noise_reduction; 自适应伪盲区
|
int i_noise_reduction; 自适应伪盲区
|
||||||
|
|
@ -209,7 +229,7 @@ Value的值就是fps。
|
||||||
} x264_param_t;*/
|
} x264_param_t;*/
|
||||||
|
|
||||||
bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
|
bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
|
||||||
if (m_pX264Handle) {
|
if (_pX264Handle) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
x264_param_t X264Param, *pX264Param = &X264Param;
|
x264_param_t X264Param, *pX264Param = &X264Param;
|
||||||
|
|
@ -249,13 +269,13 @@ bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
|
||||||
这个GOP就称为open-GOP。
|
这个GOP就称为open-GOP。
|
||||||
有些解码器不能完全支持open-GOP码流,
|
有些解码器不能完全支持open-GOP码流,
|
||||||
例如蓝光解码器,因此在x264里面open-GOP是默认关闭的。
|
例如蓝光解码器,因此在x264里面open-GOP是默认关闭的。
|
||||||
对于解码端,接收到的码流如果如下:I0 B0 B1 P0 B2 B3...这就是一个open-GOP码流(I帧后面紧跟B帧)。
|
对于解码端,接收到的码流如果如下:I0 B0 B1 P0 B2 B3...这就是一个open-GOP码流(I帧后面紧跟B帧)。
|
||||||
因此B0 B1的解码需要用到I0前面一个GOP的数据,B0 B1的dts是小于I0的。
|
因此B0 B1的解码需要用到I0前面一个GOP的数据,B0 B1的dts是小于I0的。
|
||||||
如果码流如下: I0 P0 B0 B1 P1 B2 B3...这就是一个close-GOP码流,
|
如果码流如下: I0 P0 B0 B1 P1 B2 B3...这就是一个close-GOP码流,
|
||||||
I0后面所有帧的解码不依赖于I0前面的帧,I0后面所有帧的dts都比I0的大。
|
I0后面所有帧的解码不依赖于I0前面的帧,I0后面所有帧的dts都比I0的大。
|
||||||
如果码流是IDR0 B0 B1 P0 B2 B3...那个这个GOP是close-GOP,B0,B1虽然dst比IDR0小,
|
如果码流是IDR0 B0 B1 P0 B2 B3...那个这个GOP是close-GOP,B0,B1虽然dst比IDR0小,
|
||||||
但编解码端都刷新了参考缓冲,B0,B1参考不到前向GOP帧。
|
但编解码端都刷新了参考缓冲,B0,B1参考不到前向GOP帧。
|
||||||
对于编码端,如果编码帧类型决定如下: ...P0 B1 B2 P3 B4 B5 I6这就会输出open-Gop码流 (P0 P3 B1 B2 I6 B4 B5...),
|
对于编码端,如果编码帧类型决定如下: ...P0 B1 B2 P3 B4 B5 I6这就会输出open-Gop码流 (P0 P3 B1 B2 I6 B4 B5...),
|
||||||
B4 B5的解码依赖P3。
|
B4 B5的解码依赖P3。
|
||||||
如果编码帧类型决定如下...P0 B1 B2 P3 B4 P5 I6这样就不会输出open-GOP码流(P0 P3 B1 B2 P5 B4 I6...)。
|
如果编码帧类型决定如下...P0 B1 B2 P3 B4 P5 I6这样就不会输出open-GOP码流(P0 P3 B1 B2 P5 B4 I6...)。
|
||||||
两者区别在于I6前面的第5帧是设置为B帧还是P帧,
|
两者区别在于I6前面的第5帧是设置为B帧还是P帧,
|
||||||
|
|
@ -287,48 +307,47 @@ bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
|
||||||
|
|
||||||
//* 打开编码器句柄,通过x264_encoder_parameters得到设置给X264
|
//* 打开编码器句柄,通过x264_encoder_parameters得到设置给X264
|
||||||
//* 的参数.通过x264_encoder_reconfig更新X264的参数
|
//* 的参数.通过x264_encoder_reconfig更新X264的参数
|
||||||
m_pX264Handle = x264_encoder_open(pX264Param);
|
_pX264Handle = x264_encoder_open(pX264Param);
|
||||||
if (!m_pX264Handle) {
|
if (!_pX264Handle) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_pPicIn = new x264_picture_t;
|
_pPicIn = new x264_picture_t;
|
||||||
m_pPicOut = new x264_picture_t;
|
_pPicOut = new x264_picture_t;
|
||||||
x264_picture_init(m_pPicIn);
|
x264_picture_init(_pPicIn);
|
||||||
x264_picture_init(m_pPicOut);
|
x264_picture_init(_pPicOut);
|
||||||
m_pPicIn->img.i_csp = X264_CSP_I420;
|
_pPicIn->img.i_csp = X264_CSP_I420;
|
||||||
m_pPicIn->img.i_plane = 3;
|
_pPicIn->img.i_plane = 3;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int H264Encoder::inputData(char* apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame** ppFrame) {
|
int H264Encoder::inputData(char* apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame** ppFrame) {
|
||||||
//TimeTicker1(5);
|
//TimeTicker1(5);
|
||||||
m_pPicIn->img.i_stride[0] = aiYuvLen[0];
|
_pPicIn->img.i_stride[0] = aiYuvLen[0];
|
||||||
m_pPicIn->img.i_stride[1] = aiYuvLen[1];
|
_pPicIn->img.i_stride[1] = aiYuvLen[1];
|
||||||
m_pPicIn->img.i_stride[2] = aiYuvLen[2];
|
_pPicIn->img.i_stride[2] = aiYuvLen[2];
|
||||||
m_pPicIn->img.plane[0] = (uint8_t *) apcYuv[0];
|
_pPicIn->img.plane[0] = (uint8_t *) apcYuv[0];
|
||||||
m_pPicIn->img.plane[1] = (uint8_t *) apcYuv[1];
|
_pPicIn->img.plane[1] = (uint8_t *) apcYuv[1];
|
||||||
m_pPicIn->img.plane[2] = (uint8_t *) apcYuv[2];
|
_pPicIn->img.plane[2] = (uint8_t *) apcYuv[2];
|
||||||
m_pPicIn->i_pts = i64Pts;
|
_pPicIn->i_pts = i64Pts;
|
||||||
int iNal;
|
int iNal;
|
||||||
x264_nal_t* pNals;
|
x264_nal_t* pNals;
|
||||||
|
|
||||||
int iResult = x264_encoder_encode(m_pX264Handle, &pNals, &iNal, m_pPicIn,
|
int iResult = x264_encoder_encode(_pX264Handle, &pNals, &iNal, _pPicIn,
|
||||||
m_pPicOut);
|
_pPicOut);
|
||||||
if (iResult <= 0) {
|
if (iResult <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < iNal; i++) {
|
for (int i = 0; i < iNal; i++) {
|
||||||
x264_nal_t pNal = pNals[i];
|
x264_nal_t pNal = pNals[i];
|
||||||
m_aFrames[i].iType = pNal.i_type;
|
_aFrames[i].iType = pNal.i_type;
|
||||||
m_aFrames[i].iLength = pNal.i_payload;
|
_aFrames[i].iLength = pNal.i_payload;
|
||||||
m_aFrames[i].pucData = pNal.p_payload;
|
_aFrames[i].pucData = pNal.p_payload;
|
||||||
}
|
}
|
||||||
*ppFrame = m_aFrames;
|
*ppFrame = _aFrames;
|
||||||
return iNal;
|
return iNal;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace Codec */
|
} /* namespace mediakit */
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif //ENABLE_X264
|
#endif //ENABLE_X264
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,30 @@
|
||||||
/*
|
/*
|
||||||
* H264Encoder.h
|
* MIT License
|
||||||
*
|
*
|
||||||
* Created on: 2016年8月11日
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
* Author: xzl
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef CODEC_H264ENCODER_H_
|
#ifndef CODEC_H264ENCODER_H_
|
||||||
#define CODEC_H264ENCODER_H_
|
#define CODEC_H264ENCODER_H_
|
||||||
|
|
||||||
|
|
@ -18,8 +38,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
#endif //__cplusplus
|
#endif //__cplusplus
|
||||||
|
|
||||||
namespace ZL {
|
namespace mediakit {
|
||||||
namespace Codec {
|
|
||||||
|
|
||||||
class H264Encoder {
|
class H264Encoder {
|
||||||
public:
|
public:
|
||||||
|
|
@ -34,13 +53,12 @@ public:
|
||||||
bool init(int iWidth, int iHeight, int iFps);
|
bool init(int iWidth, int iHeight, int iFps);
|
||||||
int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame);
|
int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame);
|
||||||
private:
|
private:
|
||||||
x264_t* m_pX264Handle = nullptr;
|
x264_t* _pX264Handle = nullptr;
|
||||||
x264_picture_t* m_pPicIn = nullptr;
|
x264_picture_t* _pPicIn = nullptr;
|
||||||
x264_picture_t* m_pPicOut = nullptr;
|
x264_picture_t* _pPicOut = nullptr;
|
||||||
H264Frame m_aFrames[10];
|
H264Frame _aFrames[10];
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace Codec */
|
} /* namespace mediakit */
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* CODEC_H264ENCODER_H_ */
|
#endif /* CODEC_H264ENCODER_H_ */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "Device.h"
|
||||||
|
#include "Util/logger.h"
|
||||||
|
#include "Util/util.h"
|
||||||
|
#include "Util/base64.h"
|
||||||
|
#include "Util/TimeTicker.h"
|
||||||
|
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
namespace mediakit {
|
||||||
|
|
||||||
|
DevChannel::DevChannel(const char *strVhost,
|
||||||
|
const char *strApp,
|
||||||
|
const char *strId,
|
||||||
|
float fDuration,
|
||||||
|
bool bEanbleHls,
|
||||||
|
bool bEnableMp4) :
|
||||||
|
MultiMediaSourceMuxer(strVhost, strApp, strId, fDuration, bEanbleHls, bEnableMp4) {}
|
||||||
|
|
||||||
|
DevChannel::~DevChannel() {}
|
||||||
|
|
||||||
|
#ifdef ENABLE_X264
|
||||||
|
void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) {
|
||||||
|
//TimeTicker1(50);
|
||||||
|
if (!_pH264Enc) {
|
||||||
|
_pH264Enc.reset(new H264Encoder());
|
||||||
|
if (!_pH264Enc->init(_video->iWidth, _video->iHeight, _video->iFrameRate)) {
|
||||||
|
_pH264Enc.reset();
|
||||||
|
WarnL << "H264Encoder init failed!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_pH264Enc) {
|
||||||
|
H264Encoder::H264Frame *pOut;
|
||||||
|
int iFrames = _pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut);
|
||||||
|
for (int i = 0; i < iFrames; i++) {
|
||||||
|
inputH264((char *) pOut[i].pucData, pOut[i].iLength, uiStamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //ENABLE_X264
|
||||||
|
|
||||||
|
#ifdef ENABLE_FAAC
|
||||||
|
void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) {
|
||||||
|
if (!_pAacEnc) {
|
||||||
|
_pAacEnc.reset(new AACEncoder());
|
||||||
|
if (!_pAacEnc->init(_audio->iSampleRate, _audio->iChannel, _audio->iSampleBit)) {
|
||||||
|
_pAacEnc.reset();
|
||||||
|
WarnL << "AACEncoder init failed!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_pAacEnc) {
|
||||||
|
unsigned char *pucOut;
|
||||||
|
int iRet = _pAacEnc->inputData(pcData, iDataLen, &pucOut);
|
||||||
|
if (iRet > 0) {
|
||||||
|
inputAAC((char *) pucOut, iRet, uiStamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //ENABLE_FAAC
|
||||||
|
|
||||||
|
void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t uiStamp) {
|
||||||
|
if(uiStamp == 0){
|
||||||
|
uiStamp = (uint32_t)_aTicker[0].elapsedTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
int prefixeSize;
|
||||||
|
|
||||||
|
if (memcmp("\x00\x00\x00\x01", pcData, 4) == 0) {
|
||||||
|
prefixeSize = 4;
|
||||||
|
} else if (memcmp("\x00\x00\x01", pcData, 3) == 0) {
|
||||||
|
prefixeSize = 3;
|
||||||
|
} else {
|
||||||
|
prefixeSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputFrame(std::make_shared<H264FrameNoCopyAble>((char *)pcData,iDataLen,uiStamp,prefixeSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevChannel::inputAAC(const char* pcData, int iDataLen, uint32_t uiStamp,bool withAdtsHeader) {
|
||||||
|
if(withAdtsHeader){
|
||||||
|
inputAAC(pcData+7,iDataLen-7,uiStamp,pcData);
|
||||||
|
} else if(_audio) {
|
||||||
|
inputAAC(pcData,iDataLen,uiStamp,(char *)_adtsHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader){
|
||||||
|
if(uiStamp == 0){
|
||||||
|
uiStamp = (uint32_t)_aTicker[1].elapsedTime();
|
||||||
|
}
|
||||||
|
if(pcAdtsHeader + 7 == pcDataWithoutAdts){
|
||||||
|
inputFrame(std::make_shared<AACFrameNoCopyAble>((char *)pcDataWithoutAdts - 7,iDataLen + 7,uiStamp,7));
|
||||||
|
} else {
|
||||||
|
char *dataWithAdts = new char[iDataLen + 7];
|
||||||
|
memcpy(dataWithAdts,pcAdtsHeader,7);
|
||||||
|
memcpy(dataWithAdts + 7 , pcDataWithoutAdts , iDataLen);
|
||||||
|
inputFrame(std::make_shared<AACFrameNoCopyAble>(dataWithAdts,iDataLen + 7,uiStamp,7));
|
||||||
|
delete [] dataWithAdts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DevChannel::initVideo(const VideoInfo& info) {
|
||||||
|
_video = std::make_shared<VideoInfo>(info);
|
||||||
|
addTrack(std::make_shared<H264Track>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevChannel::initAudio(const AudioInfo& info) {
|
||||||
|
_audio = std::make_shared<AudioInfo>(info);
|
||||||
|
addTrack(std::make_shared<AACTrack>());
|
||||||
|
|
||||||
|
AACFrame adtsHeader;
|
||||||
|
adtsHeader.syncword = 0x0FFF;
|
||||||
|
adtsHeader.id = 0;
|
||||||
|
adtsHeader.layer = 0;
|
||||||
|
adtsHeader.protection_absent = 1;
|
||||||
|
adtsHeader.profile = info.iProfile;//audioObjectType - 1;
|
||||||
|
int i = 0;
|
||||||
|
for(auto rate : samplingFrequencyTable){
|
||||||
|
if(rate == info.iSampleRate){
|
||||||
|
adtsHeader.sf_index = i;
|
||||||
|
};
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
adtsHeader.private_bit = 0;
|
||||||
|
adtsHeader.channel_configuration = info.iChannel;
|
||||||
|
adtsHeader.original = 0;
|
||||||
|
adtsHeader.home = 0;
|
||||||
|
adtsHeader.copyright_identification_bit = 0;
|
||||||
|
adtsHeader.copyright_identification_start = 0;
|
||||||
|
adtsHeader.aac_frame_length = 7;
|
||||||
|
adtsHeader.adts_buffer_fullness = 2047;
|
||||||
|
adtsHeader.no_raw_data_blocks_in_frame = 0;
|
||||||
|
writeAdtsHeader(adtsHeader,_adtsHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace mediakit */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEVICE_DEVICE_H_
|
||||||
|
#define DEVICE_DEVICE_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
#include "Util/util.h"
|
||||||
|
#include "Util/TimeTicker.h"
|
||||||
|
#include "Common/MultiMediaSourceMuxer.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ENABLE_FAAC
|
||||||
|
#include "Codec/AACEncoder.h"
|
||||||
|
#endif //ENABLE_FAAC
|
||||||
|
|
||||||
|
#ifdef ENABLE_X264
|
||||||
|
#include "Codec/H264Encoder.h"
|
||||||
|
#endif //ENABLE_X264
|
||||||
|
|
||||||
|
|
||||||
|
namespace mediakit {
|
||||||
|
|
||||||
|
class VideoInfo {
|
||||||
|
public:
|
||||||
|
int iWidth;
|
||||||
|
int iHeight;
|
||||||
|
float iFrameRate;
|
||||||
|
};
|
||||||
|
class AudioInfo {
|
||||||
|
public:
|
||||||
|
int iChannel;
|
||||||
|
int iSampleBit;
|
||||||
|
int iSampleRate;
|
||||||
|
int iProfile;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 该类已经废弃,保留只为兼容旧代码,请直接使用MultiMediaSourceMuxer类!
|
||||||
|
*/
|
||||||
|
class DevChannel : public MultiMediaSourceMuxer{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<DevChannel> Ptr;
|
||||||
|
//fDuration<=0为直播,否则为点播
|
||||||
|
DevChannel(const char *strVhost,
|
||||||
|
const char *strApp,
|
||||||
|
const char *strId,
|
||||||
|
float fDuration = 0,
|
||||||
|
bool bEanbleHls = true,
|
||||||
|
bool bEnableMp4 = false);
|
||||||
|
|
||||||
|
virtual ~DevChannel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化h264视频Track
|
||||||
|
* 相当于MultiMediaSourceMuxer::addTrack(H264Track::Ptr );
|
||||||
|
* @param info
|
||||||
|
*/
|
||||||
|
void initVideo(const VideoInfo &info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化aac音频Track
|
||||||
|
* 相当于MultiMediaSourceMuxer::addTrack(AACTrack::Ptr );
|
||||||
|
* @param info
|
||||||
|
*/
|
||||||
|
void initAudio(const AudioInfo &info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入264帧
|
||||||
|
* @param pcData 264单帧数据指针
|
||||||
|
* @param iDataLen 数据指针长度
|
||||||
|
* @param uiStamp 时间戳,单位毫秒;等于0时内部会自动生成时间戳
|
||||||
|
*/
|
||||||
|
void inputH264(const char *pcData, int iDataLen, uint32_t uiStamp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入可能带adts头的aac帧
|
||||||
|
* @param pcDataWithAdts 可能带adts头的aac帧
|
||||||
|
* @param iDataLen 帧数据长度
|
||||||
|
* @param uiStamp 时间戳,单位毫秒,等于0时内部会自动生成时间戳
|
||||||
|
* @param withAdtsHeader 是否带adts头
|
||||||
|
*/
|
||||||
|
void inputAAC(const char *pcDataWithAdts, int iDataLen, uint32_t uiStamp, bool withAdtsHeader = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入不带adts头的aac帧
|
||||||
|
* @param pcDataWithoutAdts 不带adts头的aac帧
|
||||||
|
* @param iDataLen 帧数据长度
|
||||||
|
* @param uiStamp 时间戳,单位毫秒
|
||||||
|
* @param pcAdtsHeader adts头
|
||||||
|
*/
|
||||||
|
void inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader);
|
||||||
|
|
||||||
|
#ifdef ENABLE_X264
|
||||||
|
/**
|
||||||
|
* 输入yuv420p视频帧,内部会完成编码并调用inputH264方法
|
||||||
|
* @param apcYuv
|
||||||
|
* @param aiYuvLen
|
||||||
|
* @param uiStamp
|
||||||
|
*/
|
||||||
|
void inputYUV(char *apcYuv[3], int aiYuvLen[3], uint32_t uiStamp);
|
||||||
|
#endif //ENABLE_X264
|
||||||
|
|
||||||
|
#ifdef ENABLE_FAAC
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入pcm数据,内部会完成编码并调用inputAAC方法
|
||||||
|
* @param pcData
|
||||||
|
* @param iDataLen
|
||||||
|
* @param uiStamp
|
||||||
|
*/
|
||||||
|
void inputPCM(char *pcData, int iDataLen, uint32_t uiStamp);
|
||||||
|
#endif //ENABLE_FAAC
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef ENABLE_X264
|
||||||
|
std::shared_ptr<H264Encoder> _pH264Enc;
|
||||||
|
#endif //ENABLE_X264
|
||||||
|
|
||||||
|
#ifdef ENABLE_FAAC
|
||||||
|
std::shared_ptr<AACEncoder> _pAacEnc;
|
||||||
|
#endif //ENABLE_FAAC
|
||||||
|
std::shared_ptr<VideoInfo> _video;
|
||||||
|
std::shared_ptr<AudioInfo> _audio;
|
||||||
|
|
||||||
|
SmoothTicker _aTicker[2];
|
||||||
|
uint8_t _adtsHeader[7];
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace mediakit */
|
||||||
|
|
||||||
|
#endif /* DEVICE_DEVICE_H_ */
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* MediaSender.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年9月1日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_MEDIASENDER_H_
|
|
||||||
#define SRC_MEDIASENDER_H_
|
|
||||||
|
|
||||||
#include "Thread/ThreadPool.h"
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
class MediaSender {
|
|
||||||
public:
|
|
||||||
static ThreadPool & sendThread() {
|
|
||||||
static ThreadPool pool(1);
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
MediaSender();
|
|
||||||
virtual ~MediaSender();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* SRC_MEDIASENDER_H_ */
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "MediaSink.h"
|
||||||
|
|
||||||
|
//最多等待未初始化的Track 10秒,超时之后会忽略未初始化的Track
|
||||||
|
#define MAX_WAIT_MS 10000
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
void MediaSink::addTrack(const Track::Ptr &track_in) {
|
||||||
|
lock_guard<recursive_mutex> lck(_mtx);
|
||||||
|
//克隆Track,只拷贝其数据,不拷贝其数据转发关系
|
||||||
|
auto track = track_in->clone();
|
||||||
|
|
||||||
|
weak_ptr<MediaSink> weakSelf = shared_from_this();
|
||||||
|
track->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([weakSelf](const Frame::Ptr &frame){
|
||||||
|
auto strongSelf = weakSelf.lock();
|
||||||
|
if(!strongSelf){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(strongSelf->_allTrackReady){
|
||||||
|
strongSelf->onTrackFrame(frame);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
auto codec_id = track->getCodecId();
|
||||||
|
_track_map[codec_id] = track;
|
||||||
|
auto lam = [this,track](){
|
||||||
|
onTrackReady(track);
|
||||||
|
};
|
||||||
|
if(track->ready()){
|
||||||
|
lam();
|
||||||
|
}else{
|
||||||
|
_allTrackReady = false;
|
||||||
|
_trackReadyCallback[codec_id] = lam;
|
||||||
|
_ticker.resetTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaSink::inputFrame(const Frame::Ptr &frame) {
|
||||||
|
lock_guard<recursive_mutex> lck(_mtx);
|
||||||
|
auto codec_id = frame->getCodecId();
|
||||||
|
auto it = _track_map.find(codec_id);
|
||||||
|
if (it == _track_map.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
it->second->inputFrame(frame);
|
||||||
|
|
||||||
|
if(!_allTrackReady && !_trackReadyCallback.empty() && it->second->ready()){
|
||||||
|
//Track由未就绪状态装换成就绪状态,我们就触发onTrackReady回调
|
||||||
|
auto it_callback = _trackReadyCallback.find(codec_id);
|
||||||
|
if(it_callback != _trackReadyCallback.end()){
|
||||||
|
it_callback->second();
|
||||||
|
_trackReadyCallback.erase(it_callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_allTrackReady && (_trackReadyCallback.empty() || _ticker.elapsedTime() > MAX_WAIT_MS)){
|
||||||
|
_allTrackReady = true;
|
||||||
|
|
||||||
|
if(!_trackReadyCallback.empty()){
|
||||||
|
//这是超时强制忽略未准备好的Track
|
||||||
|
_trackReadyCallback.clear();
|
||||||
|
//移除未准备好的Track
|
||||||
|
for(auto it = _track_map.begin() ; it != _track_map.end() ; ){
|
||||||
|
if(!it->second->ready()){
|
||||||
|
it = _track_map.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_track_map.empty()){
|
||||||
|
//最少有一个有效的Track
|
||||||
|
onAllTrackReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaSink::isAllTrackReady() const {
|
||||||
|
return _allTrackReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
Track::Ptr MediaSink::getTrack(TrackType type,bool trackReady) const {
|
||||||
|
lock_guard<recursive_mutex> lck(_mtx);
|
||||||
|
for (auto &pr : _track_map){
|
||||||
|
if(pr.second->getTrackType() == type){
|
||||||
|
if(!trackReady){
|
||||||
|
return pr.second;
|
||||||
|
}
|
||||||
|
return pr.second->ready() ? pr.second : nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_MEDIASINK_H
|
||||||
|
#define ZLMEDIAKIT_MEDIASINK_H
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
#include "Util/TimeTicker.h"
|
||||||
|
#include "Extension/Frame.h"
|
||||||
|
#include "Extension/Track.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 该类的作用是等待Track ready()返回true也就是就绪后再通知派生类进行下一步的操作
|
||||||
|
* 目的是输入Frame前由Track截取处理下,以便获取有效的信息(譬如sps pps aa_cfg)
|
||||||
|
*/
|
||||||
|
class MediaSink : public FrameWriterInterface , public std::enable_shared_from_this<MediaSink>{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<MediaSink> Ptr;
|
||||||
|
MediaSink(){}
|
||||||
|
virtual ~MediaSink(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入frame
|
||||||
|
* @param frame
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加track,内部会调用Track的clone方法
|
||||||
|
* 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系
|
||||||
|
* @param track
|
||||||
|
*/
|
||||||
|
virtual void addTrack(const Track::Ptr & track);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全部Track是否都准备好了
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool isAllTrackReady() const ;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取特定类型的Track
|
||||||
|
* @param type track类型
|
||||||
|
* @param trackReady 是否获取已经准备好的Track
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Track::Ptr getTrack(TrackType type,bool trackReady = true) const ;
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* 某track已经准备好,其ready()状态返回true,
|
||||||
|
* 此时代表可以获取其例如sps pps等相关信息了
|
||||||
|
* @param track
|
||||||
|
*/
|
||||||
|
virtual void onTrackReady(const Track::Ptr & track) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有Track已经准备好,
|
||||||
|
*/
|
||||||
|
virtual void onAllTrackReady() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 某Track输出frame,在onAllTrackReady触发后才会调用此方法
|
||||||
|
* @param frame
|
||||||
|
*/
|
||||||
|
virtual void onTrackFrame(const Frame::Ptr &frame) {};
|
||||||
|
private:
|
||||||
|
mutable recursive_mutex _mtx;
|
||||||
|
map<int,Track::Ptr> _track_map;
|
||||||
|
map<int,function<void()> > _trackReadyCallback;
|
||||||
|
bool _allTrackReady = false;
|
||||||
|
Ticker _ticker;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_MEDIASINK_H
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "MediaSource.h"
|
||||||
|
#include "MediaFile/MediaReader.h"
|
||||||
|
#include "Util/util.h"
|
||||||
|
#include "Rtsp/Rtsp.h"
|
||||||
|
#include "Network/sockutil.h"
|
||||||
|
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
namespace mediakit {
|
||||||
|
|
||||||
|
recursive_mutex MediaSource::g_mtxMediaSrc;
|
||||||
|
MediaSource::SchemaVhostAppStreamMap MediaSource::g_mapMediaSrc;
|
||||||
|
|
||||||
|
MediaSource::Ptr MediaSource::find(
|
||||||
|
const string &schema,
|
||||||
|
const string &vhost_tmp,
|
||||||
|
const string &app,
|
||||||
|
const string &id,
|
||||||
|
bool bMake) {
|
||||||
|
string vhost = vhost_tmp;
|
||||||
|
if(vhost.empty()){
|
||||||
|
vhost = DEFAULT_VHOST;
|
||||||
|
}
|
||||||
|
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
||||||
|
MediaSource::Ptr ret;
|
||||||
|
searchMedia(schema, vhost, app, id,
|
||||||
|
[&](SchemaVhostAppStreamMap::iterator &it0 ,
|
||||||
|
VhostAppStreamMap::iterator &it1,
|
||||||
|
AppStreamMap::iterator &it2,
|
||||||
|
StreamMap::iterator &it3){
|
||||||
|
ret = it3->second.lock();
|
||||||
|
if(!ret){
|
||||||
|
//该对象已经销毁
|
||||||
|
it2->second.erase(it3);
|
||||||
|
eraseIfEmpty(it0,it1,it2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if(!ret && bMake){
|
||||||
|
//查找某一媒体源,找到后返回
|
||||||
|
ret = MediaReader::onMakeMediaSource(schema, vhost,app,id);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool MediaSource::regist() {
|
||||||
|
//注册该源,注册后服务器才能找到该源
|
||||||
|
bool success;
|
||||||
|
{
|
||||||
|
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
||||||
|
auto pr = g_mapMediaSrc[_strSchema][_strVhost][_strApp].emplace(_strId, shared_from_this());
|
||||||
|
success = pr.second;
|
||||||
|
}
|
||||||
|
if(success){
|
||||||
|
InfoL << _strSchema << " " << _strVhost << " " << _strApp << " " << _strId;
|
||||||
|
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaChanged,
|
||||||
|
true,
|
||||||
|
_strSchema,
|
||||||
|
_strVhost,
|
||||||
|
_strApp,
|
||||||
|
_strId,
|
||||||
|
*this);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
bool MediaSource::unregist() {
|
||||||
|
//反注册该源
|
||||||
|
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
||||||
|
return searchMedia(_strSchema, _strVhost, _strApp, _strId, [&](SchemaVhostAppStreamMap::iterator &it0 ,
|
||||||
|
VhostAppStreamMap::iterator &it1,
|
||||||
|
AppStreamMap::iterator &it2,
|
||||||
|
StreamMap::iterator &it3){
|
||||||
|
auto strongMedia = it3->second.lock();
|
||||||
|
if(strongMedia && this != strongMedia.get()){
|
||||||
|
//不是自己,不允许反注册
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
it2->second.erase(it3);
|
||||||
|
eraseIfEmpty(it0,it1,it2);
|
||||||
|
unregisted();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void MediaSource::unregisted(){
|
||||||
|
InfoL << "" << _strSchema << " " << _strVhost << " " << _strApp << " " << _strId;
|
||||||
|
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaChanged,
|
||||||
|
false,
|
||||||
|
_strSchema,
|
||||||
|
_strVhost,
|
||||||
|
_strApp,
|
||||||
|
_strId,
|
||||||
|
*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaInfo::parse(const string &url){
|
||||||
|
//string url = "rtsp://127.0.0.1:8554/live/id?key=val&a=1&&b=2&vhost=vhost.com";
|
||||||
|
auto schema_pos = url.find("://");
|
||||||
|
if(schema_pos != string::npos){
|
||||||
|
_schema = url.substr(0,schema_pos);
|
||||||
|
}else{
|
||||||
|
schema_pos = -3;
|
||||||
|
}
|
||||||
|
auto split_vec = split(url.substr(schema_pos + 3),"/");
|
||||||
|
if(split_vec.size() > 0){
|
||||||
|
auto vhost = split_vec[0];
|
||||||
|
auto pos = vhost.find(":");
|
||||||
|
if(pos != string::npos){
|
||||||
|
_host = _vhost = vhost.substr(0,pos);
|
||||||
|
_port = vhost.substr(pos + 1);
|
||||||
|
} else{
|
||||||
|
_host = _vhost = vhost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(split_vec.size() > 1){
|
||||||
|
_app = split_vec[1];
|
||||||
|
}
|
||||||
|
if(split_vec.size() > 2){
|
||||||
|
string steamid;
|
||||||
|
for(int i = 2 ; i < split_vec.size() ; ++i){
|
||||||
|
steamid.append(split_vec[i] + "/");
|
||||||
|
}
|
||||||
|
if(steamid.back() == '/'){
|
||||||
|
steamid.pop_back();
|
||||||
|
}
|
||||||
|
auto pos = steamid.find("?");
|
||||||
|
if(pos != string::npos){
|
||||||
|
_streamid = steamid.substr(0,pos);
|
||||||
|
_param_strs = steamid.substr(pos + 1);
|
||||||
|
_params = Parser::parseArgs(_param_strs);
|
||||||
|
if(_params.find(VHOST_KEY) != _params.end()){
|
||||||
|
_vhost = _params[VHOST_KEY];
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
_streamid = steamid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_vhost.empty()){
|
||||||
|
//无效vhost
|
||||||
|
_vhost = DEFAULT_VHOST;
|
||||||
|
}else{
|
||||||
|
if(INADDR_NONE != inet_addr(_vhost.data())){
|
||||||
|
//这是ip,未指定vhost;使用默认vhost
|
||||||
|
_vhost = DEFAULT_VHOST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace mediakit */
|
||||||
|
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_MEDIASOURCE_H
|
||||||
|
#define ZLMEDIAKIT_MEDIASOURCE_H
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "Common/config.h"
|
||||||
|
#include "Util/logger.h"
|
||||||
|
#include "Util/TimeTicker.h"
|
||||||
|
#include "Util/NoticeCenter.h"
|
||||||
|
#include "Rtsp/Rtsp.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
namespace mediakit {
|
||||||
|
|
||||||
|
class MediaSourceEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MediaSourceEvent(){};
|
||||||
|
virtual ~MediaSourceEvent(){};
|
||||||
|
public:
|
||||||
|
virtual bool seekTo(uint32_t ui32Stamp){
|
||||||
|
//拖动进度条
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool close() {
|
||||||
|
//通知其停止推流
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class MediaInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MediaInfo(){}
|
||||||
|
MediaInfo(const string &url){
|
||||||
|
parse(url);
|
||||||
|
}
|
||||||
|
~MediaInfo(){}
|
||||||
|
|
||||||
|
void parse(const string &url);
|
||||||
|
|
||||||
|
string &operator[](const string &key){
|
||||||
|
return _params[key];
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
string _schema;
|
||||||
|
string _host;
|
||||||
|
string _port;
|
||||||
|
string _vhost;
|
||||||
|
string _app;
|
||||||
|
string _streamid;
|
||||||
|
StrCaseMap _params;
|
||||||
|
string _param_strs;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MediaSource: public enable_shared_from_this<MediaSource> {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<MediaSource> Ptr;
|
||||||
|
typedef unordered_map<string, weak_ptr<MediaSource> > StreamMap;
|
||||||
|
typedef unordered_map<string, StreamMap > AppStreamMap;
|
||||||
|
typedef unordered_map<string, AppStreamMap > VhostAppStreamMap;
|
||||||
|
typedef unordered_map<string, VhostAppStreamMap > SchemaVhostAppStreamMap;
|
||||||
|
|
||||||
|
MediaSource(const string &strSchema,
|
||||||
|
const string &strVhost,
|
||||||
|
const string &strApp,
|
||||||
|
const string &strId) :
|
||||||
|
_strSchema(strSchema),
|
||||||
|
_strApp(strApp),
|
||||||
|
_strId(strId) {
|
||||||
|
if(strVhost.empty()){
|
||||||
|
_strVhost = DEFAULT_VHOST;
|
||||||
|
}else{
|
||||||
|
_strVhost = strVhost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual ~MediaSource() {
|
||||||
|
unregist();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Ptr find(const string &schema,
|
||||||
|
const string &vhost,
|
||||||
|
const string &app,
|
||||||
|
const string &id,
|
||||||
|
bool bMake = true) ;
|
||||||
|
|
||||||
|
const string& getSchema() const {
|
||||||
|
return _strSchema;
|
||||||
|
}
|
||||||
|
const string& getVhost() const {
|
||||||
|
return _strVhost;
|
||||||
|
}
|
||||||
|
const string& getApp() const {
|
||||||
|
//获取该源的id
|
||||||
|
return _strApp;
|
||||||
|
}
|
||||||
|
const string& getId() const {
|
||||||
|
return _strId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool seekTo(uint32_t ui32Stamp) {
|
||||||
|
auto listener = _listener.lock();
|
||||||
|
if(!listener){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return listener->seekTo(ui32Stamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32_t getTimeStamp(TrackType trackType) = 0;
|
||||||
|
|
||||||
|
bool close() {
|
||||||
|
auto listener = _listener.lock();
|
||||||
|
if(!listener){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return listener->close();
|
||||||
|
}
|
||||||
|
void setListener(const std::weak_ptr<MediaSourceEvent> &listener){
|
||||||
|
_listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FUN>
|
||||||
|
static void for_each_media(FUN && fun){
|
||||||
|
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
||||||
|
for (auto &pr0 : g_mapMediaSrc){
|
||||||
|
for(auto &pr1 : pr0.second){
|
||||||
|
for(auto &pr2 : pr1.second){
|
||||||
|
for(auto &pr3 : pr2.second){
|
||||||
|
fun(pr0.first,pr1.first,pr2.first,pr3.first,pr3.second.lock());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool regist() ;
|
||||||
|
bool unregist() ;
|
||||||
|
private:
|
||||||
|
template <typename FUN>
|
||||||
|
static bool searchMedia(const string &schema,
|
||||||
|
const string &vhost,
|
||||||
|
const string &app,
|
||||||
|
const string &id,
|
||||||
|
FUN &&fun){
|
||||||
|
auto it0 = g_mapMediaSrc.find(schema);
|
||||||
|
if (it0 == g_mapMediaSrc.end()) {
|
||||||
|
//未找到协议
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it1 = it0->second.find(vhost);
|
||||||
|
if(it1 == it0->second.end()){
|
||||||
|
//未找到vhost
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it2 = it1->second.find(app);
|
||||||
|
if(it2 == it1->second.end()){
|
||||||
|
//未找到app
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it3 = it2->second.find(id);
|
||||||
|
if(it3 == it2->second.end()){
|
||||||
|
//未找到streamId
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return fun(it0,it1,it2,it3);
|
||||||
|
}
|
||||||
|
template <typename IT0,typename IT1,typename IT2>
|
||||||
|
static void eraseIfEmpty(IT0 it0,IT1 it1,IT2 it2){
|
||||||
|
if(it2->second.empty()){
|
||||||
|
it1->second.erase(it2);
|
||||||
|
if(it1->second.empty()){
|
||||||
|
it0->second.erase(it1);
|
||||||
|
if(it0->second.empty()){
|
||||||
|
g_mapMediaSrc.erase(it0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void unregisted();
|
||||||
|
protected:
|
||||||
|
std::weak_ptr<MediaSourceEvent> _listener;
|
||||||
|
private:
|
||||||
|
string _strSchema;//协议类型
|
||||||
|
string _strVhost; //vhost
|
||||||
|
string _strApp; //媒体app
|
||||||
|
string _strId; //媒体id
|
||||||
|
static SchemaVhostAppStreamMap g_mapMediaSrc; //静态的媒体源表
|
||||||
|
static recursive_mutex g_mtxMediaSrc; //访问静态的媒体源表的互斥锁
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace mediakit */
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_MEDIASOURCE_H
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_MULTIMEDIASOURCEMUXER_H
|
||||||
|
#define ZLMEDIAKIT_MULTIMEDIASOURCEMUXER_H
|
||||||
|
|
||||||
|
#include "RtspMuxer/RtspMediaSourceMuxer.h"
|
||||||
|
#include "RtmpMuxer/RtmpMediaSourceMuxer.h"
|
||||||
|
#include "MediaFile/MediaRecorder.h"
|
||||||
|
|
||||||
|
class MultiMediaSourceMuxer : public FrameWriterInterface{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<MultiMediaSourceMuxer> Ptr;
|
||||||
|
|
||||||
|
MultiMediaSourceMuxer(const string &vhost,
|
||||||
|
const string &strApp,
|
||||||
|
const string &strId,
|
||||||
|
float dur_sec = 0.0,
|
||||||
|
bool bEanbleHls = true,
|
||||||
|
bool bEnableMp4 = false){
|
||||||
|
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost,strApp,strId,std::make_shared<TitleMete>(dur_sec));
|
||||||
|
_rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost,strApp,strId,std::make_shared<TitleSdp>(dur_sec));
|
||||||
|
_record = std::make_shared<MediaRecorder>(vhost,strApp,strId,bEanbleHls,bEnableMp4);
|
||||||
|
|
||||||
|
}
|
||||||
|
virtual ~MultiMediaSourceMuxer(){}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加音视频媒体
|
||||||
|
* @param track 媒体描述
|
||||||
|
*/
|
||||||
|
void addTrack(const Track::Ptr & track) {
|
||||||
|
_rtmp->addTrack(track);
|
||||||
|
_rtsp->addTrack(track);
|
||||||
|
_record->addTrack(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入帧数据然后打包rtmp
|
||||||
|
* @param frame 帧数据
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override {
|
||||||
|
_rtmp->inputFrame(frame);
|
||||||
|
_rtsp->inputFrame(frame);
|
||||||
|
_record->inputFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置事件监听器
|
||||||
|
* @param listener
|
||||||
|
*/
|
||||||
|
void setListener(const std::weak_ptr<MediaSourceEvent> &listener){
|
||||||
|
_rtmp->setListener(listener);
|
||||||
|
_rtsp->setListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回总的消费者个数
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int readerCount() const{
|
||||||
|
return _rtsp->readerCount() + _rtmp->readerCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTimeStamp(uint32_t stamp){
|
||||||
|
_rtsp->setTimeStamp(stamp);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
RtmpMediaSourceMuxer::Ptr _rtmp;
|
||||||
|
RtspMediaSourceMuxer::Ptr _rtsp;
|
||||||
|
MediaRecorder::Ptr _record;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_MULTIMEDIASOURCEMUXER_H
|
||||||
|
|
@ -1,46 +1,75 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Util/NoticeCenter.h>
|
||||||
#include "Common/config.h"
|
#include "Common/config.h"
|
||||||
#include "Util/util.h"
|
#include "Util/util.h"
|
||||||
#include "Util/onceToken.h"
|
#include "Util/onceToken.h"
|
||||||
#include "Network/sockutil.h"
|
#include "Network/sockutil.h"
|
||||||
|
|
||||||
#ifndef UINT64_MAX
|
using namespace toolkit;
|
||||||
#define UINT64_MAX 0xFFFFFFFFFFFFFFFF
|
|
||||||
#endif//UINT64_MAX
|
|
||||||
|
|
||||||
using namespace ZL::Network;
|
namespace mediakit {
|
||||||
|
|
||||||
namespace Config {
|
bool loadIniConfig(const char *ini_path){
|
||||||
|
string ini;
|
||||||
void loaIniConfig(){
|
if(ini_path){
|
||||||
auto &ini = ZL::Util::mINI::Instance();
|
ini = ini_path;
|
||||||
|
}else{
|
||||||
|
ini = exePath() + ".ini";
|
||||||
|
}
|
||||||
try{
|
try{
|
||||||
ini.parseFile(exePath() + ".ini");
|
mINI::Instance().parseFile(ini);
|
||||||
|
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
|
||||||
|
return true;
|
||||||
}catch (std::exception &ex) {
|
}catch (std::exception &ex) {
|
||||||
ini.dumpFile(exePath() + ".ini");
|
mINI::Instance().dumpFile(ini);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
////////////广播名称///////////
|
////////////广播名称///////////
|
||||||
namespace Broadcast {
|
namespace Broadcast {
|
||||||
const char kBroadcastRtspSessionPlay[] = "kBroadcastRtspSessionPlay";
|
const char kBroadcastMediaChanged[] = "kBroadcastMediaChanged";
|
||||||
const char kBroadcastRtspSrcRegisted[] = "kBroadcastRtspSrcRegisted";
|
|
||||||
const char kBroadcastRtmpSrcRegisted[] = "kBroadcastRtmpSrcRegisted";
|
|
||||||
const char kBroadcastRecordMP4[] = "kBroadcastRecordMP4";
|
const char kBroadcastRecordMP4[] = "kBroadcastRecordMP4";
|
||||||
const char kBroadcastHttpRequest[] = "kBroadcastHttpRequest";
|
const char kBroadcastHttpRequest[] = "kBroadcastHttpRequest";
|
||||||
} //namespace Broadcast
|
const char kBroadcastOnGetRtspRealm[] = "kBroadcastOnGetRtspRealm";
|
||||||
|
const char kBroadcastOnRtspAuth[] = "kBroadcastOnRtspAuth";
|
||||||
|
const char kBroadcastMediaPlayed[] = "kBroadcastMediaPlayed";
|
||||||
|
const char kBroadcastMediaPublish[] = "kBroadcastMediaPublish";
|
||||||
|
const char kBroadcastFlowReport[] = "kBroadcastFlowReport";
|
||||||
|
const char kBroadcastReloadConfig[] = "kBroadcastReloadConfig";
|
||||||
|
const char kBroadcastShellLogin[] = "kBroadcastShellLogin";
|
||||||
|
const char kBroadcastNotFoundStream[] = "kBroadcastNotFoundStream";
|
||||||
|
|
||||||
//代理失败最大重试次数
|
const char kFlowThreshold[] = "broadcast.flowThreshold";
|
||||||
namespace Proxy {
|
|
||||||
#define PROXY_FIELD "proxy."
|
|
||||||
|
|
||||||
#define PROXY_REPLAY_CNT (UINT64_MAX)
|
|
||||||
const char kReplayCount[] = PROXY_FIELD"replayCount";
|
|
||||||
|
|
||||||
onceToken token([](){
|
onceToken token([](){
|
||||||
mINI::Instance()[kReplayCount] = PROXY_REPLAY_CNT;
|
mINI::Instance()[kFlowThreshold] = 1024;
|
||||||
},nullptr);
|
},nullptr);
|
||||||
|
} //namespace Broadcast
|
||||||
}//namespace Proxy
|
|
||||||
|
|
||||||
|
|
||||||
////////////HTTP配置///////////
|
////////////HTTP配置///////////
|
||||||
namespace Http {
|
namespace Http {
|
||||||
|
|
@ -61,7 +90,7 @@ const char kSendBufSize[] = HTTP_FIELD"sendBufSize";
|
||||||
const char kMaxReqSize[] = HTTP_FIELD"maxReqSize";
|
const char kMaxReqSize[] = HTTP_FIELD"maxReqSize";
|
||||||
|
|
||||||
//http keep-alive秒数
|
//http keep-alive秒数
|
||||||
#define HTTP_KEEP_ALIVE_SECOND 5
|
#define HTTP_KEEP_ALIVE_SECOND 10
|
||||||
const char kKeepAliveSecond[] = HTTP_FIELD"keepAliveSecond";
|
const char kKeepAliveSecond[] = HTTP_FIELD"keepAliveSecond";
|
||||||
|
|
||||||
//http keep-alive最大请求数
|
//http keep-alive最大请求数
|
||||||
|
|
@ -69,13 +98,13 @@ const char kKeepAliveSecond[] = HTTP_FIELD"keepAliveSecond";
|
||||||
const char kMaxReqCount[] = HTTP_FIELD"maxReqCount";
|
const char kMaxReqCount[] = HTTP_FIELD"maxReqCount";
|
||||||
|
|
||||||
//http 字符编码
|
//http 字符编码
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define HTTP_CHAR_SET "gb2312"
|
||||||
|
#else
|
||||||
#define HTTP_CHAR_SET "utf-8"
|
#define HTTP_CHAR_SET "utf-8"
|
||||||
|
#endif
|
||||||
const char kCharSet[] = HTTP_FIELD"charSet";
|
const char kCharSet[] = HTTP_FIELD"charSet";
|
||||||
|
|
||||||
//http 服务器名称
|
|
||||||
#define HTTP_SERVER_NAME "ZLServer"
|
|
||||||
const char kServerName[] = HTTP_FIELD"serverName";
|
|
||||||
|
|
||||||
//http 服务器根目录
|
//http 服务器根目录
|
||||||
#define HTTP_ROOT_PATH (exeDir() + "httpRoot")
|
#define HTTP_ROOT_PATH (exeDir() + "httpRoot")
|
||||||
const char kRootPath[] = HTTP_FIELD"rootPath";
|
const char kRootPath[] = HTTP_FIELD"rootPath";
|
||||||
|
|
@ -86,17 +115,12 @@ const char kRootPath[] = HTTP_FIELD"rootPath";
|
||||||
"<body bgcolor=\"white\">"\
|
"<body bgcolor=\"white\">"\
|
||||||
"<center><h1>您访问的资源不存在!</h1></center>"\
|
"<center><h1>您访问的资源不存在!</h1></center>"\
|
||||||
"<hr><center>"\
|
"<hr><center>"\
|
||||||
HTTP_SERVER_NAME\
|
SERVER_NAME\
|
||||||
"</center>"\
|
"</center>"\
|
||||||
"</body>"\
|
"</body>"\
|
||||||
"</html>"
|
"</html>"
|
||||||
const char kNotFound[] = HTTP_FIELD"notFound";
|
const char kNotFound[] = HTTP_FIELD"notFound";
|
||||||
|
|
||||||
//HTTP访问url前缀
|
|
||||||
#define HTTP_PREFIX (StrPrinter << "http://" \
|
|
||||||
<< SockUtil::get_local_ip() \
|
|
||||||
<< ":" << HTTP_PORT << endl)
|
|
||||||
const char kHttpPrefix[] = HTTP_FIELD"httpPrefix";
|
|
||||||
|
|
||||||
onceToken token([](){
|
onceToken token([](){
|
||||||
mINI::Instance()[kPort] = HTTP_PORT;
|
mINI::Instance()[kPort] = HTTP_PORT;
|
||||||
|
|
@ -106,10 +130,8 @@ onceToken token([](){
|
||||||
mINI::Instance()[kKeepAliveSecond] = HTTP_KEEP_ALIVE_SECOND;
|
mINI::Instance()[kKeepAliveSecond] = HTTP_KEEP_ALIVE_SECOND;
|
||||||
mINI::Instance()[kMaxReqCount] = HTTP_MAX_REQ_CNT;
|
mINI::Instance()[kMaxReqCount] = HTTP_MAX_REQ_CNT;
|
||||||
mINI::Instance()[kCharSet] = HTTP_CHAR_SET;
|
mINI::Instance()[kCharSet] = HTTP_CHAR_SET;
|
||||||
mINI::Instance()[kServerName] = HTTP_SERVER_NAME;
|
|
||||||
mINI::Instance()[kRootPath] = HTTP_ROOT_PATH;
|
mINI::Instance()[kRootPath] = HTTP_ROOT_PATH;
|
||||||
mINI::Instance()[kNotFound] = HTTP_NOT_FOUND;
|
mINI::Instance()[kNotFound] = HTTP_NOT_FOUND;
|
||||||
mINI::Instance()[kHttpPrefix] = HTTP_PREFIX;
|
|
||||||
},nullptr);
|
},nullptr);
|
||||||
|
|
||||||
}//namespace Http
|
}//namespace Http
|
||||||
|
|
@ -121,15 +143,11 @@ namespace Shell {
|
||||||
#define SHELL_PORT 9000
|
#define SHELL_PORT 9000
|
||||||
const char kPort[] = SHELL_FIELD"port";
|
const char kPort[] = SHELL_FIELD"port";
|
||||||
|
|
||||||
#define SHELL_SERVER_NAME "ZLServer"
|
|
||||||
const char kServerName[] = SHELL_FIELD"serverName";
|
|
||||||
|
|
||||||
#define SHELL_MAX_REQ_SIZE 1024
|
#define SHELL_MAX_REQ_SIZE 1024
|
||||||
const char kMaxReqSize[] = SHELL_FIELD"maxReqSize";
|
const char kMaxReqSize[] = SHELL_FIELD"maxReqSize";
|
||||||
|
|
||||||
onceToken token([](){
|
onceToken token([](){
|
||||||
mINI::Instance()[kPort] = SHELL_PORT;
|
mINI::Instance()[kPort] = SHELL_PORT;
|
||||||
mINI::Instance()[kServerName] = SHELL_SERVER_NAME;
|
|
||||||
mINI::Instance()[kMaxReqSize] = SHELL_MAX_REQ_SIZE;
|
mINI::Instance()[kMaxReqSize] = SHELL_MAX_REQ_SIZE;
|
||||||
},nullptr);
|
},nullptr);
|
||||||
} //namespace Shell
|
} //namespace Shell
|
||||||
|
|
@ -141,12 +159,12 @@ namespace Rtsp {
|
||||||
#define RTSP_PORT 554
|
#define RTSP_PORT 554
|
||||||
const char kPort[] = RTSP_FIELD"port";
|
const char kPort[] = RTSP_FIELD"port";
|
||||||
|
|
||||||
#define RTSP_SERVER_NAME "ZLServer"
|
const char kAuthBasic[] = RTSP_FIELD"authBasic";
|
||||||
const char kServerName[] = RTSP_FIELD"serverName";
|
|
||||||
|
|
||||||
onceToken token([](){
|
onceToken token([](){
|
||||||
mINI::Instance()[kPort] = RTSP_PORT;
|
mINI::Instance()[kPort] = RTSP_PORT;
|
||||||
mINI::Instance()[kServerName] = RTSP_SERVER_NAME;
|
//默认Md5方式认证
|
||||||
|
mINI::Instance()[kAuthBasic] = 0;
|
||||||
},nullptr);
|
},nullptr);
|
||||||
|
|
||||||
} //namespace Rtsp
|
} //namespace Rtsp
|
||||||
|
|
@ -157,9 +175,11 @@ namespace Rtmp {
|
||||||
|
|
||||||
#define RTMP_PORT 1935
|
#define RTMP_PORT 1935
|
||||||
const char kPort[] = RTMP_FIELD"port";
|
const char kPort[] = RTMP_FIELD"port";
|
||||||
|
const char kModifyStamp[] = RTMP_FIELD"modifyStamp";
|
||||||
|
|
||||||
onceToken token([](){
|
onceToken token([](){
|
||||||
mINI::Instance()[kPort] = RTMP_PORT;
|
mINI::Instance()[kPort] = RTMP_PORT;
|
||||||
|
mINI::Instance()[kModifyStamp] = true;
|
||||||
},nullptr);
|
},nullptr);
|
||||||
} //namespace RTMP
|
} //namespace RTMP
|
||||||
|
|
||||||
|
|
@ -175,10 +195,6 @@ const char kVideoMtuSize[] = RTP_FIELD"videoMtuSize";
|
||||||
#define RTP_Audio_MTU_SIZE 600
|
#define RTP_Audio_MTU_SIZE 600
|
||||||
const char kAudioMtuSize[] = RTP_FIELD"audioMtuSize";
|
const char kAudioMtuSize[] = RTP_FIELD"audioMtuSize";
|
||||||
|
|
||||||
//udp方式接受RTP包的最大缓存
|
|
||||||
#define RTP_UDP_BUFSIZE (128 * 1024)
|
|
||||||
const char kUdpBufSize[] = RTP_FIELD"udpBufSize";
|
|
||||||
|
|
||||||
//RTP排序缓存最大个数
|
//RTP排序缓存最大个数
|
||||||
#define RTP_MAX_RTP_COUNT 50
|
#define RTP_MAX_RTP_COUNT 50
|
||||||
const char kMaxRtpCount[] = RTP_FIELD"maxRtpCount";
|
const char kMaxRtpCount[] = RTP_FIELD"maxRtpCount";
|
||||||
|
|
@ -195,7 +211,6 @@ const char kCycleMS[] = RTP_FIELD"cycleMS";
|
||||||
onceToken token([](){
|
onceToken token([](){
|
||||||
mINI::Instance()[kVideoMtuSize] = RTP_VIDOE_MTU_SIZE;
|
mINI::Instance()[kVideoMtuSize] = RTP_VIDOE_MTU_SIZE;
|
||||||
mINI::Instance()[kAudioMtuSize] = RTP_Audio_MTU_SIZE;
|
mINI::Instance()[kAudioMtuSize] = RTP_Audio_MTU_SIZE;
|
||||||
mINI::Instance()[kUdpBufSize] = RTP_UDP_BUFSIZE;
|
|
||||||
mINI::Instance()[kMaxRtpCount] = RTP_MAX_RTP_COUNT;
|
mINI::Instance()[kMaxRtpCount] = RTP_MAX_RTP_COUNT;
|
||||||
mINI::Instance()[kClearCount] = RTP_CLEAR_COUNT;
|
mINI::Instance()[kClearCount] = RTP_CLEAR_COUNT;
|
||||||
mINI::Instance()[kCycleMS] = RTP_CYCLE_MS;
|
mINI::Instance()[kCycleMS] = RTP_CYCLE_MS;
|
||||||
|
|
@ -206,20 +221,16 @@ onceToken token([](){
|
||||||
namespace MultiCast {
|
namespace MultiCast {
|
||||||
#define MULTI_FIELD "multicast."
|
#define MULTI_FIELD "multicast."
|
||||||
//组播分配起始地址
|
//组播分配起始地址
|
||||||
#define MULTI_ADDR_MIN (0xE00000FF + 10)
|
|
||||||
const char kAddrMin[] = MULTI_FIELD"addrMin";
|
const char kAddrMin[] = MULTI_FIELD"addrMin";
|
||||||
|
|
||||||
//组播分配截止地址
|
//组播分配截止地址
|
||||||
#define MULTI_ADDR_MAX (0xEFFFFFFF)
|
|
||||||
const char kAddrMax[] = MULTI_FIELD"addrMax";
|
const char kAddrMax[] = MULTI_FIELD"addrMax";
|
||||||
|
|
||||||
//组播TTL
|
//组播TTL
|
||||||
#define MULTI_UDP_TTL 64
|
#define MULTI_UDP_TTL 64
|
||||||
const char kUdpTTL[] = MULTI_FIELD"udpTTL";
|
const char kUdpTTL[] = MULTI_FIELD"udpTTL";
|
||||||
|
|
||||||
onceToken token([](){
|
onceToken token([](){
|
||||||
mINI::Instance()[kAddrMin] = MULTI_ADDR_MIN;
|
mINI::Instance()[kAddrMin] = "239.0.0.0";
|
||||||
mINI::Instance()[kAddrMax] = MULTI_ADDR_MAX;
|
mINI::Instance()[kAddrMax] = "239.255.255.255";
|
||||||
mINI::Instance()[kUdpTTL] = MULTI_UDP_TTL;
|
mINI::Instance()[kUdpTTL] = MULTI_UDP_TTL;
|
||||||
},nullptr);
|
},nullptr);
|
||||||
|
|
||||||
|
|
@ -241,12 +252,6 @@ const char kSampleMS[] = RECORD_FIELD"sampleMS";
|
||||||
#define RECORD_FILE_SECOND (10*60)
|
#define RECORD_FILE_SECOND (10*60)
|
||||||
const char kFileSecond[] = RECORD_FIELD"fileSecond";
|
const char kFileSecond[] = RECORD_FIELD"fileSecond";
|
||||||
|
|
||||||
//Rtsp访问url前缀
|
|
||||||
#define RECORD_RTSP_PREFIX (StrPrinter << "rtsp://" \
|
|
||||||
<< SockUtil::get_local_ip() \
|
|
||||||
<< ":" << RTSP_PORT << endl)
|
|
||||||
const char kRtspPrefix[] = RECORD_FIELD"rtspPrefix";
|
|
||||||
|
|
||||||
//录制文件路径
|
//录制文件路径
|
||||||
#define RECORD_FILE_PATH HTTP_ROOT_PATH
|
#define RECORD_FILE_PATH HTTP_ROOT_PATH
|
||||||
const char kFilePath[] = RECORD_FIELD"filePath";
|
const char kFilePath[] = RECORD_FIELD"filePath";
|
||||||
|
|
@ -256,7 +261,6 @@ onceToken token([](){
|
||||||
mINI::Instance()[kSampleMS] = RECORD_SAMPLE_MS;
|
mINI::Instance()[kSampleMS] = RECORD_SAMPLE_MS;
|
||||||
mINI::Instance()[kFileSecond] = RECORD_FILE_SECOND;
|
mINI::Instance()[kFileSecond] = RECORD_FILE_SECOND;
|
||||||
mINI::Instance()[kFilePath] = RECORD_FILE_PATH;
|
mINI::Instance()[kFilePath] = RECORD_FILE_PATH;
|
||||||
mINI::Instance()[kRtspPrefix] = RECORD_RTSP_PREFIX;
|
|
||||||
},nullptr);
|
},nullptr);
|
||||||
|
|
||||||
} //namespace Record
|
} //namespace Record
|
||||||
|
|
@ -266,7 +270,7 @@ namespace Hls {
|
||||||
#define HLS_FIELD "hls."
|
#define HLS_FIELD "hls."
|
||||||
|
|
||||||
//HLS切片时长,单位秒
|
//HLS切片时长,单位秒
|
||||||
#define HLS_SEGMENT_DURATION 5
|
#define HLS_SEGMENT_DURATION 3
|
||||||
const char kSegmentDuration[] = HLS_FIELD"segDur";
|
const char kSegmentDuration[] = HLS_FIELD"segDur";
|
||||||
|
|
||||||
//HLS切片个数
|
//HLS切片个数
|
||||||
|
|
@ -290,6 +294,6 @@ onceToken token([](){
|
||||||
|
|
||||||
} //namespace Hls
|
} //namespace Hls
|
||||||
|
|
||||||
} // namespace Config
|
} // namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,49 @@
|
||||||
//
|
/*
|
||||||
// appConfig.h
|
* MIT License
|
||||||
// ZLMedia
|
*
|
||||||
//
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
// Created by lyl on 16/10/22.
|
*
|
||||||
// Copyright © 2016年 jizan. All rights reserved.
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
//
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef appConfig_h
|
|
||||||
#define appConfig_h
|
|
||||||
|
|
||||||
|
#ifndef COMMON_CONFIG_H
|
||||||
|
#define COMMON_CONFIG_H
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include "Util/mini.h"
|
#include "Util/mini.h"
|
||||||
using namespace ZL::Util;
|
#include "Util/onceToken.h"
|
||||||
|
#include "Util/NoticeCenter.h"
|
||||||
|
|
||||||
namespace Config {
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
void loaIniConfig();
|
namespace mediakit {
|
||||||
////////////TCP最大连接数///////////
|
|
||||||
#ifdef __x86_64__
|
|
||||||
#define MAX_TCP_SESSION 100000
|
|
||||||
#else
|
|
||||||
#define MAX_TCP_SESSION 128
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
//加载配置文件,如果配置文件不存在,那么会导出默认配置并生成配置文件
|
||||||
|
//加载配置文件成功后会触发kBroadcastUpdateConfig广播
|
||||||
|
//如果指定的文件名(ini_path)为空,那么会加载默认配置文件
|
||||||
|
//默认配置文件名为 /path/to/your/exe.ini
|
||||||
|
//加载配置文件成功后返回true,否则返回false
|
||||||
|
bool loadIniConfig(const char *ini_path = nullptr);
|
||||||
////////////其他宏定义///////////
|
////////////其他宏定义///////////
|
||||||
#ifndef MAX
|
#ifndef MAX
|
||||||
#define MAX(a,b) ((a) > (b) ? (a) : (b) )
|
#define MAX(a,b) ((a) > (b) ? (a) : (b) )
|
||||||
|
|
@ -35,32 +57,98 @@ void loaIniConfig();
|
||||||
#define CLEAR_ARR(arr) for(auto &item : arr){ item = 0;}
|
#define CLEAR_ARR(arr) for(auto &item : arr){ item = 0;}
|
||||||
#endif //CLEAR_ARR
|
#endif //CLEAR_ARR
|
||||||
|
|
||||||
|
#define SERVER_NAME "ZLMediaKit-3.0"
|
||||||
|
#define VHOST_KEY "vhost"
|
||||||
|
#define HTTP_SCHEMA "http"
|
||||||
|
#define RTSP_SCHEMA "rtsp"
|
||||||
|
#define RTMP_SCHEMA "rtmp"
|
||||||
|
#define DEFAULT_VHOST "__defaultVhost__"
|
||||||
|
|
||||||
////////////广播名称///////////
|
////////////广播名称///////////
|
||||||
namespace Broadcast {
|
namespace Broadcast {
|
||||||
extern const char kBroadcastRtspSessionPlay[];
|
|
||||||
#define BroadcastRtspSessionPlayArgs const char *app,const char *stream
|
|
||||||
|
|
||||||
extern const char kBroadcastRtspSrcRegisted[];
|
//注册或反注册MediaSource事件广播
|
||||||
#define BroadcastRtspSrcRegistedArgs const char *app,const char *stream
|
extern const char kBroadcastMediaChanged[];
|
||||||
|
#define BroadcastMediaChangedArgs const bool &bRegist, const string &schema,const string &vhost,const string &app,const string &stream,MediaSource &sender
|
||||||
extern const char kBroadcastRtmpSrcRegisted[];
|
|
||||||
#define BroadcastRtmpSrcRegistedArgs const char *app,const char *stream
|
|
||||||
|
|
||||||
|
//录制mp4文件成功后广播
|
||||||
extern const char kBroadcastRecordMP4[];
|
extern const char kBroadcastRecordMP4[];
|
||||||
#define BroadcastRecordMP4Args const Mp4Info &info
|
#define BroadcastRecordMP4Args const Mp4Info &info,Mp4Maker &sender
|
||||||
|
|
||||||
|
//收到http api请求广播
|
||||||
extern const char kBroadcastHttpRequest[];
|
extern const char kBroadcastHttpRequest[];
|
||||||
#define BroadcastHttpRequestArgs const Parser &parser,HttpSession::HttpResponseInvoker &invoker
|
#define BroadcastHttpRequestArgs const Parser &parser,const HttpSession::HttpResponseInvoker &invoker,bool &consumed,TcpSession &sender
|
||||||
|
|
||||||
|
//该流是否需要认证?是的话调用invoker并传入realm,否则传入空的realm.如果该事件不监听则不认证
|
||||||
|
extern const char kBroadcastOnGetRtspRealm[];
|
||||||
|
#define BroadcastOnGetRtspRealmArgs const MediaInfo &args,const RtspSession::onGetRealm &invoker,TcpSession &sender
|
||||||
|
|
||||||
|
//请求认证用户密码事件,user_name为用户名,must_no_encrypt如果为true,则必须提供明文密码(因为此时是base64认证方式),否则会导致认证失败
|
||||||
|
//获取到密码后请调用invoker并输入对应类型的密码和密码类型,invoker执行时会匹配密码
|
||||||
|
extern const char kBroadcastOnRtspAuth[];
|
||||||
|
#define BroadcastOnRtspAuthArgs const MediaInfo &args,const string &user_name,const bool &must_no_encrypt,const RtspSession::onAuth &invoker,TcpSession &sender
|
||||||
|
|
||||||
|
//鉴权结果回调对象
|
||||||
|
//如果errMessage为空则代表鉴权成功
|
||||||
|
typedef std::function<void(const string &errMessage)> AuthInvoker;
|
||||||
|
|
||||||
|
//收到rtsp/rtmp推流事件广播,通过该事件控制推流鉴权
|
||||||
|
extern const char kBroadcastMediaPublish[];
|
||||||
|
#define BroadcastMediaPublishArgs const MediaInfo &args,const Broadcast::AuthInvoker &invoker,TcpSession &sender
|
||||||
|
|
||||||
|
//兼容旧代码的宏
|
||||||
|
#define BroadcastRtmpPublishArgs BroadcastMediaPublishArgs
|
||||||
|
#define kBroadcastRtmpPublish kBroadcastMediaPublish
|
||||||
|
|
||||||
|
//播放rtsp/rtmp/http-flv事件广播,通过该事件控制播放鉴权
|
||||||
|
extern const char kBroadcastMediaPlayed[];
|
||||||
|
#define BroadcastMediaPlayedArgs const MediaInfo &args,const Broadcast::AuthInvoker &invoker,TcpSession &sender
|
||||||
|
|
||||||
|
//shell登录鉴权
|
||||||
|
extern const char kBroadcastShellLogin[];
|
||||||
|
#define BroadcastShellLoginArgs const string &user_name,const string &passwd,const Broadcast::AuthInvoker &invoker,TcpSession &sender
|
||||||
|
|
||||||
|
//停止rtsp/rtmp/http-flv会话后流量汇报事件广播
|
||||||
|
extern const char kBroadcastFlowReport[];
|
||||||
|
#define BroadcastFlowReportArgs const MediaInfo &args,const uint64_t &totalBytes,const uint64_t &totalDuration,TcpSession &sender
|
||||||
|
|
||||||
|
//未找到流后会广播该事件,请在监听该事件后去拉流或其他方式产生流,这样就能按需拉流了
|
||||||
|
extern const char kBroadcastNotFoundStream[];
|
||||||
|
#define BroadcastNotFoundStreamArgs const MediaInfo &args,TcpSession &sender
|
||||||
|
|
||||||
|
//流量汇报事件流量阈值,单位KB,默认1MB
|
||||||
|
extern const char kFlowThreshold[];
|
||||||
|
|
||||||
|
//更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播
|
||||||
|
extern const char kBroadcastReloadConfig[];
|
||||||
|
#define BroadcastReloadConfigArgs void
|
||||||
|
#define ReloadConfigTag ((void *)(0xFF))
|
||||||
|
|
||||||
|
#define RELOAD_KEY(arg,key) \
|
||||||
|
do{ \
|
||||||
|
decltype(arg) arg##tmp = mINI::Instance()[key]; \
|
||||||
|
if(arg != arg##tmp ) { \
|
||||||
|
arg = arg##tmp; \
|
||||||
|
InfoL << "reload config:" << key << "=" << arg; \
|
||||||
|
} \
|
||||||
|
}while(0);
|
||||||
|
|
||||||
|
//监听某个配置发送变更
|
||||||
|
#define RELOAD_KEY_REGISTER(arg,key) \
|
||||||
|
do{ \
|
||||||
|
static onceToken s_token([](){ \
|
||||||
|
NoticeCenter::Instance().addListener(ReloadConfigTag,Broadcast::kBroadcastReloadConfig,[](BroadcastReloadConfigArgs){ \
|
||||||
|
RELOAD_KEY(arg,key); \
|
||||||
|
}); \
|
||||||
|
}); \
|
||||||
|
}while(0);
|
||||||
|
|
||||||
|
#define GET_CONFIG_AND_REGISTER(type,arg,key) \
|
||||||
|
static type arg = mINI::Instance()[key]; \
|
||||||
|
RELOAD_KEY_REGISTER(arg,key);
|
||||||
|
|
||||||
} //namespace Broadcast
|
} //namespace Broadcast
|
||||||
|
|
||||||
//代理失败最大重试次数
|
|
||||||
namespace Proxy {
|
|
||||||
extern const char kReplayCount[];
|
|
||||||
}//namespace Proxy
|
|
||||||
|
|
||||||
|
|
||||||
////////////HTTP配置///////////
|
////////////HTTP配置///////////
|
||||||
namespace Http {
|
namespace Http {
|
||||||
extern const char kPort[];
|
extern const char kPort[];
|
||||||
|
|
@ -75,35 +163,32 @@ extern const char kKeepAliveSecond[];
|
||||||
extern const char kMaxReqCount[];
|
extern const char kMaxReqCount[];
|
||||||
//http 字符编码
|
//http 字符编码
|
||||||
extern const char kCharSet[];
|
extern const char kCharSet[];
|
||||||
//http 服务器名称
|
|
||||||
extern const char kServerName[];
|
|
||||||
//http 服务器根目录
|
//http 服务器根目录
|
||||||
extern const char kRootPath[];
|
extern const char kRootPath[];
|
||||||
//http 404错误提示内容
|
//http 404错误提示内容
|
||||||
extern const char kNotFound[];
|
extern const char kNotFound[];
|
||||||
//HTTP访问url前缀
|
|
||||||
extern const char kHttpPrefix[];
|
|
||||||
}//namespace Http
|
}//namespace Http
|
||||||
|
|
||||||
////////////SHELL配置///////////
|
////////////SHELL配置///////////
|
||||||
namespace Shell {
|
namespace Shell {
|
||||||
extern const char kServerName[];
|
|
||||||
extern const char kMaxReqSize[];
|
extern const char kMaxReqSize[];
|
||||||
extern const char kPort[];
|
extern const char kPort[];
|
||||||
} //namespace Shell
|
} //namespace Shell
|
||||||
|
|
||||||
////////////RTSP服务器配置///////////
|
////////////RTSP服务器配置///////////
|
||||||
namespace Rtsp {
|
namespace Rtsp {
|
||||||
#define RTSP_VERSION 1.30
|
|
||||||
#define RTSP_BUILDTIME __DATE__" CST"
|
|
||||||
|
|
||||||
extern const char kServerName[];
|
|
||||||
extern const char kPort[];
|
extern const char kPort[];
|
||||||
|
//是否优先base64方式认证?默认Md5方式认证
|
||||||
|
extern const char kAuthBasic[];
|
||||||
} //namespace Rtsp
|
} //namespace Rtsp
|
||||||
|
|
||||||
////////////RTMP服务器配置///////////
|
////////////RTMP服务器配置///////////
|
||||||
namespace Rtmp {
|
namespace Rtmp {
|
||||||
extern const char kPort[];
|
extern const char kPort[];
|
||||||
|
extern const char kModifyStamp[];
|
||||||
|
|
||||||
} //namespace RTMP
|
} //namespace RTMP
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -113,8 +198,6 @@ namespace Rtp {
|
||||||
extern const char kVideoMtuSize[];
|
extern const char kVideoMtuSize[];
|
||||||
//RTP打包最大MTU,公网情况下更小
|
//RTP打包最大MTU,公网情况下更小
|
||||||
extern const char kAudioMtuSize[];
|
extern const char kAudioMtuSize[];
|
||||||
//udp方式接受RTP包的最大缓存
|
|
||||||
extern const char kUdpBufSize[];
|
|
||||||
//RTP排序缓存最大个数
|
//RTP排序缓存最大个数
|
||||||
extern const char kMaxRtpCount[];
|
extern const char kMaxRtpCount[];
|
||||||
//如果RTP序列正确次数累计达到该数字就启动清空排序缓存
|
//如果RTP序列正确次数累计达到该数字就启动清空排序缓存
|
||||||
|
|
@ -141,8 +224,6 @@ extern const char kAppName[];
|
||||||
extern const char kSampleMS[];
|
extern const char kSampleMS[];
|
||||||
//MP4文件录制大小,不能太大,否则MP4Close函数执行事件太长
|
//MP4文件录制大小,不能太大,否则MP4Close函数执行事件太长
|
||||||
extern const char kFileSecond[];
|
extern const char kFileSecond[];
|
||||||
//Rtsp访问url前缀
|
|
||||||
extern const char kRtspPrefix[];
|
|
||||||
//录制文件路径
|
//录制文件路径
|
||||||
extern const char kFilePath[];
|
extern const char kFilePath[];
|
||||||
} //namespace Record
|
} //namespace Record
|
||||||
|
|
@ -159,6 +240,6 @@ extern const char kFileBufSize[];
|
||||||
extern const char kFilePath[];
|
extern const char kFilePath[];
|
||||||
} //namespace Hls
|
} //namespace Hls
|
||||||
|
|
||||||
} // namespace Config
|
} // namespace mediakit
|
||||||
|
|
||||||
#endif /* appConfig_h */
|
#endif /* COMMON_CONFIG_H */
|
||||||
|
|
|
||||||
|
|
@ -1,256 +0,0 @@
|
||||||
/*
|
|
||||||
* Device.cpp
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月10日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "base64.h"
|
|
||||||
#include "Device.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace DEV {
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
|
||||||
#ifdef ENABLE_RTSP2RTMP
|
|
||||||
DevChannel::DevChannel(const char *strApp, const char *strId,float fDuration,bool bLiveStream ) :
|
|
||||||
m_mediaSrc(new RtspToRtmpMediaSource(strApp,strId , bLiveStream)) {
|
|
||||||
#else
|
|
||||||
DevChannel::DevChannel(const char *strApp, const char *strId,float fDuration,bool bLiveStream ) :
|
|
||||||
m_mediaSrc(new RtspToRtmpMediaSource(strApp,strId )) {
|
|
||||||
#endif //ENABLE_RTSP2RTMP
|
|
||||||
m_strSDP = "v=0\r\n";
|
|
||||||
m_strSDP += "o=- 1383190487994921 1 IN IP4 0.0.0.0\r\n";
|
|
||||||
m_strSDP += "s=RTSP Session, streamed by the ZL\r\n";
|
|
||||||
m_strSDP += "i=ZL Live Stream\r\n";
|
|
||||||
m_strSDP += "c=IN IP4 0.0.0.0\r\n";
|
|
||||||
m_strSDP += "t=0 0\r\n";
|
|
||||||
//直播,时间长度永远
|
|
||||||
if(fDuration <= 0 || bLiveStream){
|
|
||||||
m_strSDP += "a=range:npt=0-\r\n";
|
|
||||||
}else{
|
|
||||||
m_strSDP += StrPrinter <<"a=range:npt=0-" << fDuration << "\r\n" << endl;
|
|
||||||
}
|
|
||||||
m_strSDP += "a=control:*\r\n";
|
|
||||||
}
|
|
||||||
DevChannel::~DevChannel() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) {
|
|
||||||
//TimeTicker1(50);
|
|
||||||
#ifdef ENABLE_X264
|
|
||||||
if (!m_pH264Enc) {
|
|
||||||
m_pH264Enc.reset(new H264Encoder());
|
|
||||||
if (!m_pH264Enc->init(m_video->iWidth, m_video->iHeight, m_video->iFrameRate)) {
|
|
||||||
m_pH264Enc.reset();
|
|
||||||
WarnL << "H264Encoder init failed!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_pH264Enc) {
|
|
||||||
H264Encoder::H264Frame *pOut;
|
|
||||||
int iFrames = m_pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut);
|
|
||||||
for (int i = 0; i < iFrames; i++) {
|
|
||||||
inputH264((char *) pOut[i].pucData, pOut[i].iLength, uiStamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ErrorL << "libx264 was not enabled!";
|
|
||||||
#endif //ENABLE_X264
|
|
||||||
}
|
|
||||||
|
|
||||||
void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) {
|
|
||||||
#ifdef ENABLE_FAAC
|
|
||||||
if (!m_pAacEnc) {
|
|
||||||
m_pAacEnc.reset(new AACEncoder());
|
|
||||||
if (!m_pAacEnc->init(m_audio->iSampleRate, m_audio->iChannel, m_audio->iSampleBit)) {
|
|
||||||
m_pAacEnc.reset();
|
|
||||||
WarnL << "AACEncoder init failed!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_pAacEnc) {
|
|
||||||
unsigned char *pucOut;
|
|
||||||
int iRet = m_pAacEnc->inputData(pcData, iDataLen, &pucOut);
|
|
||||||
if (iRet > 0) {
|
|
||||||
inputAAC((char *) pucOut, iRet, uiStamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ErrorL << "libfaac was not enabled!";
|
|
||||||
#endif //ENABLE_FAAC
|
|
||||||
}
|
|
||||||
|
|
||||||
void DevChannel::inputH264(char* pcData, int iDataLen, uint32_t uiStamp) {
|
|
||||||
if (!m_pRtpMaker_h264) {
|
|
||||||
uint32_t ui32Ssrc;
|
|
||||||
memcpy(&ui32Ssrc, makeRandStr(4, false).data(), 4);
|
|
||||||
auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
|
|
||||||
m_mediaSrc->onGetRTP(pkt,bKeyPos);
|
|
||||||
};
|
|
||||||
static uint32_t videoMtu = mINI::Instance()[Config::Rtp::kVideoMtuSize].as<uint32_t>();
|
|
||||||
m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ui32Ssrc,videoMtu));
|
|
||||||
}
|
|
||||||
if (!m_bSdp_gotH264 && m_video) {
|
|
||||||
makeSDP_264((unsigned char*) pcData, iDataLen);
|
|
||||||
}
|
|
||||||
int iOffset = 4;
|
|
||||||
if (memcmp("\x00\x00\x01", pcData, 3) == 0) {
|
|
||||||
iOffset = 3;
|
|
||||||
}
|
|
||||||
m_pRtpMaker_h264->makeRtp(pcData + iOffset, iDataLen - iOffset, uiStamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DevChannel::inputAAC(char* pcData, int iDataLen, uint32_t uiStamp) {
|
|
||||||
if (!m_pRtpMaker_aac) {
|
|
||||||
uint32_t ssrc;
|
|
||||||
memcpy(&ssrc, makeRandStr(8, false).data() + 4, 4);
|
|
||||||
auto lam = [this](const RtpPacket::Ptr &pkt, bool keyPos) {
|
|
||||||
m_mediaSrc->onGetRTP(pkt,keyPos);
|
|
||||||
};
|
|
||||||
static uint32_t audioMtu = mINI::Instance()[Config::Rtp::kAudioMtuSize].as<uint32_t>();
|
|
||||||
m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc, audioMtu,m_audio->iSampleRate));
|
|
||||||
}
|
|
||||||
if (!m_bSdp_gotAAC && m_audio) {
|
|
||||||
makeSDP_AAC((unsigned char*) pcData, iDataLen);
|
|
||||||
}
|
|
||||||
m_pRtpMaker_aac->makeRtp(pcData + 7, iDataLen - 7, uiStamp);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void DevChannel::makeSDP_264(unsigned char *pcData, int iDataLen) {
|
|
||||||
int offset = 4;
|
|
||||||
if (memcmp("\x00\x00\x01", pcData, 3) == 0) {
|
|
||||||
offset = 3;
|
|
||||||
}
|
|
||||||
switch (pcData[offset] & 0x1F) {
|
|
||||||
case 7:/*SPS frame*/
|
|
||||||
{
|
|
||||||
if (m_uiSPSLen != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(m_aucSPS, pcData + offset, iDataLen - offset);
|
|
||||||
m_uiSPSLen = iDataLen - offset;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 8:/*PPS frame*/
|
|
||||||
{
|
|
||||||
if (m_uiPPSLen != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(m_aucPPS, pcData + offset, iDataLen - offset);
|
|
||||||
m_uiPPSLen = iDataLen - offset;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!m_uiSPSLen || !m_uiPPSLen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char acTmp[256];
|
|
||||||
int profile_level_id = 0;
|
|
||||||
if (m_uiSPSLen >= 4) { // sanity check
|
|
||||||
profile_level_id = (m_aucSPS[1] << 16) | (m_aucSPS[2] << 8) | m_aucSPS[3]; // profile_idc|constraint_setN_flag|level_idc
|
|
||||||
}
|
|
||||||
|
|
||||||
//视频通道
|
|
||||||
m_strSDP += StrPrinter << "m=video 0 RTP/AVP "
|
|
||||||
<< m_pRtpMaker_h264->getPlayloadType() << "\r\n" << endl;
|
|
||||||
m_strSDP += "b=AS:5100\r\n";
|
|
||||||
m_strSDP += StrPrinter << "a=rtpmap:" << m_pRtpMaker_h264->getPlayloadType()
|
|
||||||
<< " H264/" << m_pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
|
|
||||||
m_strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_h264->getPlayloadType()
|
|
||||||
<< " packetization-mode=1;profile-level-id=" << endl;
|
|
||||||
|
|
||||||
memset(acTmp, 0, sizeof(acTmp));
|
|
||||||
sprintf(acTmp, "%06X", profile_level_id);
|
|
||||||
m_strSDP += acTmp;
|
|
||||||
m_strSDP += ";sprop-parameter-sets=";
|
|
||||||
memset(acTmp, 0, sizeof(acTmp));
|
|
||||||
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) m_aucSPS, m_uiSPSLen);
|
|
||||||
//WarnL<<"SPS base64:"<<strTemp;
|
|
||||||
//WarnL<<"SPS hexdump:"<<hexdump(SPS_BUF, SPS_LEN);
|
|
||||||
m_strSDP += acTmp;
|
|
||||||
m_strSDP += ",";
|
|
||||||
memset(acTmp, 0, sizeof(acTmp));
|
|
||||||
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) m_aucPPS, m_uiPPSLen);
|
|
||||||
m_strSDP += acTmp;
|
|
||||||
m_strSDP += "\r\n";
|
|
||||||
if (m_video->iFrameRate > 0 && m_video->iHeight > 0 && m_video->iWidth > 0) {
|
|
||||||
m_strSDP += "a=framerate:";
|
|
||||||
m_strSDP += StrPrinter << m_video->iFrameRate << endl;
|
|
||||||
m_strSDP += StrPrinter << "\r\na=framesize:"
|
|
||||||
<< m_pRtpMaker_h264->getPlayloadType() << " " << endl;
|
|
||||||
m_strSDP += StrPrinter << m_video->iWidth << endl;
|
|
||||||
m_strSDP += "-";
|
|
||||||
m_strSDP += StrPrinter << m_video->iHeight << endl;
|
|
||||||
m_strSDP += "\r\n";
|
|
||||||
}
|
|
||||||
m_strSDP += StrPrinter << "a=control:trackID="
|
|
||||||
<< m_pRtpMaker_h264->getInterleaved() / 2 << "\r\n" << endl;
|
|
||||||
m_bSdp_gotH264 = true;
|
|
||||||
if (m_audio) {
|
|
||||||
if (m_bSdp_gotAAC) {
|
|
||||||
makeSDP(m_strSDP);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
makeSDP(m_strSDP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void DevChannel::makeSDP_AAC(unsigned char *fixedHeader, int dataLen) {
|
|
||||||
auto audioSpecificConfig = makeAdtsConfig(fixedHeader);
|
|
||||||
if (audioSpecificConfig.size() != 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char fConfigStr[5] = { 0 };
|
|
||||||
sprintf(fConfigStr, "%02X%02x", (uint8_t)audioSpecificConfig[0],(uint8_t)audioSpecificConfig[1]);
|
|
||||||
|
|
||||||
m_strSDP += StrPrinter << "m=audio 0 RTP/AVP "
|
|
||||||
<< m_pRtpMaker_aac->getPlayloadType() << "\r\n" << endl;
|
|
||||||
m_strSDP += "b=AS:96\r\n";
|
|
||||||
m_strSDP += StrPrinter << "a=rtpmap:" << m_pRtpMaker_aac->getPlayloadType()
|
|
||||||
<< " MPEG4-GENERIC/" << m_pRtpMaker_aac->getSampleRate() << "\r\n"
|
|
||||||
<< endl;
|
|
||||||
m_strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_aac->getPlayloadType()
|
|
||||||
<< " streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config="
|
|
||||||
<< endl;
|
|
||||||
m_strSDP += fConfigStr;
|
|
||||||
m_strSDP += "\r\n";
|
|
||||||
m_strSDP += StrPrinter << "a=control:trackID="
|
|
||||||
<< m_pRtpMaker_aac->getInterleaved() / 2 << "\r\n" << endl;
|
|
||||||
|
|
||||||
m_bSdp_gotAAC = true;
|
|
||||||
if (m_video) {
|
|
||||||
if (m_bSdp_gotH264) {
|
|
||||||
makeSDP(m_strSDP);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
makeSDP(m_strSDP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DevChannel::makeSDP(const string& strSdp) {
|
|
||||||
m_mediaSrc->onGetSDP(strSdp);
|
|
||||||
m_mediaSrc->regist();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DevChannel::initVideo(const VideoInfo& info) {
|
|
||||||
m_video.reset(new VideoInfo(info));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DevChannel::initAudio(const AudioInfo& info) {
|
|
||||||
m_audio.reset(new AudioInfo(info));
|
|
||||||
}
|
|
||||||
} /* namespace DEV */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
/*
|
|
||||||
* Device.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年8月10日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DEVICE_DEVICE_H_
|
|
||||||
#define DEVICE_DEVICE_H_
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
#include "Util/util.h"
|
|
||||||
#include "RTP/RtpMakerAAC.h"
|
|
||||||
#include "RTP/RtpMakerH264.h"
|
|
||||||
#include "Rtsp/RtspToRtmpMediaSource.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Rtsp;
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
#ifdef ENABLE_FAAC
|
|
||||||
#include "Codec/AACEncoder.h"
|
|
||||||
using namespace ZL::Codec;
|
|
||||||
#endif //ENABLE_FAAC
|
|
||||||
|
|
||||||
#ifdef ENABLE_X264
|
|
||||||
#include "Codec/H264Encoder.h"
|
|
||||||
using namespace ZL::Codec;
|
|
||||||
#endif //ENABLE_X264
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace DEV {
|
|
||||||
|
|
||||||
class VideoInfo {
|
|
||||||
public:
|
|
||||||
int iWidth;
|
|
||||||
int iHeight;
|
|
||||||
float iFrameRate;
|
|
||||||
};
|
|
||||||
class AudioInfo {
|
|
||||||
public:
|
|
||||||
int iChannel;
|
|
||||||
int iSampleBit;
|
|
||||||
int iSampleRate;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DevChannel {
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<DevChannel> Ptr;
|
|
||||||
DevChannel(const char *strApp, const char *strId,float fDuration = 0,bool bLiveStream = true);
|
|
||||||
virtual ~DevChannel();
|
|
||||||
|
|
||||||
void initVideo(const VideoInfo &info);
|
|
||||||
void initAudio(const AudioInfo &info);
|
|
||||||
|
|
||||||
void inputYUV(char *apcYuv[3], int aiYuvLen[3], uint32_t uiStamp);
|
|
||||||
void inputPCM(char *pcData, int iDataLen, uint32_t uiStamp);
|
|
||||||
|
|
||||||
void inputH264(char *pcData, int iDataLen, uint32_t uiStamp);
|
|
||||||
void inputAAC(char *pcData, int iDataLen, uint32_t uiStamp);
|
|
||||||
#ifdef ENABLE_RTSP2RTMP
|
|
||||||
int readerCount() {
|
|
||||||
return m_mediaSrc ? m_mediaSrc->readerCount() : 0;
|
|
||||||
}
|
|
||||||
void updateTimeStamp(uint32_t uiStamp){
|
|
||||||
m_mediaSrc->updateTimeStamp(uiStamp);
|
|
||||||
}
|
|
||||||
#endif //ENABLE_RTSP2RTMP
|
|
||||||
void setOnSeek(const function<bool(uint32_t)> &onSeek){
|
|
||||||
m_mediaSrc->setOnSeek(onSeek);
|
|
||||||
}
|
|
||||||
void setOnStamp(const function<uint32_t()> &cb) {
|
|
||||||
m_mediaSrc->setOnStamp(cb);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
inline void makeSDP_264(unsigned char *pucData, int iDataLen);
|
|
||||||
inline void makeSDP_AAC(unsigned char *pucData, int iDataLen);
|
|
||||||
inline void makeSDP(const string& strSdp);
|
|
||||||
#ifdef ENABLE_X264
|
|
||||||
std::shared_ptr<H264Encoder> m_pH264Enc;
|
|
||||||
#endif //ENABLE_X264
|
|
||||||
|
|
||||||
#ifdef ENABLE_FAAC
|
|
||||||
std::shared_ptr<AACEncoder> m_pAacEnc;
|
|
||||||
#endif //ENABLE_FAAC
|
|
||||||
RtpMaker_AAC::Ptr m_pRtpMaker_aac;
|
|
||||||
RtpMaker_H264::Ptr m_pRtpMaker_h264;
|
|
||||||
RtspToRtmpMediaSource::Ptr m_mediaSrc;
|
|
||||||
string m_strSDP;
|
|
||||||
bool m_bSdp_gotH264 = false;
|
|
||||||
bool m_bSdp_gotAAC = false;
|
|
||||||
|
|
||||||
unsigned char m_aucSPS[256];
|
|
||||||
unsigned int m_uiSPSLen = 0;
|
|
||||||
unsigned char m_aucPPS[256];
|
|
||||||
unsigned int m_uiPPSLen = 0;
|
|
||||||
std::shared_ptr<VideoInfo> m_video;
|
|
||||||
std::shared_ptr<AudioInfo> m_audio;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} /* namespace DEV */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* DEVICE_DEVICE_H_ */
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
/*
|
|
||||||
* PlyerProxy.cpp
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月6日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Common/config.h"
|
|
||||||
#include "PlayerProxy.h"
|
|
||||||
#include "Util/mini.h"
|
|
||||||
#include "Util/MD5.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Thread/AsyncTaskThread.h"
|
|
||||||
|
|
||||||
using namespace ZL::Util;
|
|
||||||
using namespace ZL::Thread;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace DEV {
|
|
||||||
|
|
||||||
PlayerProxy::PlayerProxy(const char *strApp,const char *strSrc){
|
|
||||||
m_strApp = strApp;
|
|
||||||
m_strSrc = strSrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerProxy::play(const char* strUrl, const char *strUser,
|
|
||||||
const char *strPwd, PlayerBase::eRtpType eType, uint32_t iSecond) {
|
|
||||||
m_aliveSecond = iSecond;
|
|
||||||
string strUrlTmp(strUrl);
|
|
||||||
string strUserTmp(strUser);
|
|
||||||
string strPwdTmp(strPwd);
|
|
||||||
|
|
||||||
m_pPlayer.reset(new MediaPlayer());
|
|
||||||
weak_ptr<PlayerProxy> weakSelf = shared_from_this();
|
|
||||||
m_pPlayer->setOnVideoCB( [weakSelf,strUrlTmp](const H264Frame &data ) {
|
|
||||||
auto strongSelf = weakSelf.lock();
|
|
||||||
if(!strongSelf){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(strongSelf->m_pChn){
|
|
||||||
strongSelf->m_pChn->inputH264((char *)data.data.data(), data.data.size(), data.timeStamp);
|
|
||||||
}else{
|
|
||||||
strongSelf->initMedia();
|
|
||||||
}
|
|
||||||
strongSelf->checkExpired();
|
|
||||||
});
|
|
||||||
m_pPlayer->setOnAudioCB( [weakSelf,strUrlTmp](const AdtsFrame &data ) {
|
|
||||||
auto strongSelf = weakSelf.lock();
|
|
||||||
if(!strongSelf){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(strongSelf->m_pChn){
|
|
||||||
strongSelf->m_pChn->inputAAC((char *)data.data, data.aac_frame_length, data.timeStamp);
|
|
||||||
}else{
|
|
||||||
strongSelf->initMedia();
|
|
||||||
}
|
|
||||||
strongSelf->checkExpired();
|
|
||||||
});
|
|
||||||
|
|
||||||
std::shared_ptr<uint64_t> piFailedCnt(new uint64_t(0)); //连续播放失败次数
|
|
||||||
m_pPlayer->setOnPlayResult([weakSelf,strUrlTmp,strUserTmp,strPwdTmp,eType,piFailedCnt](const SockException &err) {
|
|
||||||
auto strongSelf = weakSelf.lock();
|
|
||||||
if(!strongSelf) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static uint64_t replayCnt = mINI::Instance()[Config::Proxy::kReplayCount].as<uint64_t>();
|
|
||||||
if(!err) {
|
|
||||||
// 播放成功
|
|
||||||
*piFailedCnt = 0;//连续播放失败次数清0
|
|
||||||
}else if(*piFailedCnt < replayCnt) {
|
|
||||||
// 播放失败,延时重试播放
|
|
||||||
strongSelf->rePlay(strUrlTmp, strUserTmp, strPwdTmp, eType,(*piFailedCnt)++);
|
|
||||||
}else{
|
|
||||||
strongSelf->expired();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
weak_ptr<MediaPlayer> weakPtr= m_pPlayer;
|
|
||||||
m_pPlayer->setOnShutdown([weakSelf,weakPtr,strUrlTmp,strUserTmp,strPwdTmp,eType,piFailedCnt](const SockException &err) {
|
|
||||||
auto strongSelf = weakSelf.lock();
|
|
||||||
if(!strongSelf) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(strongSelf->m_pChn) {
|
|
||||||
strongSelf->m_pChn.reset();
|
|
||||||
}
|
|
||||||
//播放异常中断,延时重试播放
|
|
||||||
static uint64_t replayCnt = mINI::Instance()[Config::Proxy::kReplayCount].as<uint64_t>();
|
|
||||||
if(*piFailedCnt < replayCnt) {
|
|
||||||
strongSelf->rePlay(strUrlTmp, strUserTmp, strPwdTmp, eType,(*piFailedCnt)++);
|
|
||||||
}else{
|
|
||||||
strongSelf->expired();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
m_pPlayer->play(strUrl, strUser, strPwd, eType);
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerProxy::~PlayerProxy() {
|
|
||||||
auto iTaskId = reinterpret_cast<uint64_t>(this);
|
|
||||||
AsyncTaskThread::Instance().CancelTask(iTaskId);
|
|
||||||
}
|
|
||||||
void PlayerProxy::rePlay(const string &strUrl, const string &strUser, const string &strPwd, PlayerBase::eRtpType eType, uint64_t iFailedCnt){
|
|
||||||
checkExpired();
|
|
||||||
auto iTaskId = reinterpret_cast<uint64_t>(this);
|
|
||||||
auto iDelay = MAX((uint64_t)2 * 1000, MIN(iFailedCnt * 3000,(uint64_t)60*1000));
|
|
||||||
weak_ptr<MediaPlayer> weakPtr = m_pPlayer;
|
|
||||||
AsyncTaskThread::Instance().CancelTask(iTaskId);
|
|
||||||
AsyncTaskThread::Instance().DoTaskDelay(iTaskId, iDelay, [weakPtr,strUrl,strUser,strPwd,eType,iFailedCnt]() {
|
|
||||||
//播放失败次数越多,则延时越长
|
|
||||||
auto strongPlayer = weakPtr.lock();
|
|
||||||
if(!strongPlayer) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
WarnL << "重试播放[" << iFailedCnt << "]:" << strUrl;
|
|
||||||
strongPlayer->play(strUrl.data(), strUser.data(), strPwd.data(), eType);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
void PlayerProxy::initMedia() {
|
|
||||||
if (!m_pPlayer->isInited()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_pChn.reset(new DevChannel(m_strApp.data(),m_strSrc.data(),m_pPlayer->getDuration()));
|
|
||||||
if (m_pPlayer->containVideo()) {
|
|
||||||
VideoInfo info;
|
|
||||||
info.iFrameRate = m_pPlayer->getVideoFps();
|
|
||||||
info.iWidth = m_pPlayer->getVideoWidth();
|
|
||||||
info.iHeight = m_pPlayer->getVideoHeight();
|
|
||||||
m_pChn->initVideo(info);
|
|
||||||
}
|
|
||||||
if (m_pPlayer->containAudio()) {
|
|
||||||
AudioInfo info;
|
|
||||||
info.iSampleRate = m_pPlayer->getAudioSampleRate();
|
|
||||||
info.iChannel = m_pPlayer->getAudioChannel();
|
|
||||||
info.iSampleBit = m_pPlayer->getAudioSampleBit();
|
|
||||||
m_pChn->initAudio(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerProxy::checkExpired() {
|
|
||||||
if(m_aliveSecond && m_aliveTicker.elapsedTime() > m_aliveSecond * 1000){
|
|
||||||
//到期
|
|
||||||
expired();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerProxy::expired() {
|
|
||||||
if(onExpired){
|
|
||||||
onExpired();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace Player */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* PlyerProxy.h
|
|
||||||
*
|
|
||||||
* Created on: 2016年12月6日
|
|
||||||
* Author: xzl
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SRC_DEVICE_PLAYERPROXY_H_
|
|
||||||
#define SRC_DEVICE_PLAYERPROXY_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include "Device.h"
|
|
||||||
#include "Player/MediaPlayer.h"
|
|
||||||
#include "Util/TimeTicker.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace ZL::Player;
|
|
||||||
|
|
||||||
namespace ZL {
|
|
||||||
namespace DEV {
|
|
||||||
|
|
||||||
class PlayerProxy : public std::enable_shared_from_this<PlayerProxy>{
|
|
||||||
public:
|
|
||||||
typedef std::shared_ptr<PlayerProxy> Ptr;
|
|
||||||
PlayerProxy(const char *strApp, const char *strSrc);
|
|
||||||
void play(const char* strUrl, const char *strUser = "", const char *strPwd = "",PlayerBase::eRtpType eType = PlayerBase::RTP_TCP,uint32_t iSecond = 0);
|
|
||||||
virtual ~PlayerProxy();
|
|
||||||
void setOnExpired(const function<void()> &cb){
|
|
||||||
onExpired = cb;
|
|
||||||
}
|
|
||||||
private :
|
|
||||||
MediaPlayer::Ptr m_pPlayer;
|
|
||||||
DevChannel::Ptr m_pChn;
|
|
||||||
Ticker m_aliveTicker;
|
|
||||||
uint32_t m_aliveSecond = 0;
|
|
||||||
function<void()> onExpired;
|
|
||||||
string m_strApp;
|
|
||||||
string m_strSrc;
|
|
||||||
void initMedia();
|
|
||||||
void rePlay(const string &strUrl, const string &strUser, const string &strPwd, PlayerBase::eRtpType eType,uint64_t iFailedCnt);
|
|
||||||
void checkExpired();
|
|
||||||
void expired();
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace Player */
|
|
||||||
} /* namespace ZL */
|
|
||||||
|
|
||||||
#endif /* SRC_DEVICE_PLAYERPROXY_H_ */
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
|
||||||
*
|
|
||||||
* This file is part of FFmpeg.
|
|
||||||
*
|
|
||||||
* FFmpeg is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* FFmpeg 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with FFmpeg; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Base64 encode/decode
|
|
||||||
* @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#include "common.h"
|
|
||||||
#include "stdio.h"
|
|
||||||
#include "base64.h"
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
/* ---------------- private code */
|
|
||||||
static const uint8_t map2[] =
|
|
||||||
{
|
|
||||||
0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
|
|
||||||
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
|
|
||||||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
|
||||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
|
|
||||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
|
|
||||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
|
||||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
|
||||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
|
|
||||||
};
|
|
||||||
|
|
||||||
int av_base64_decode(uint8_t *out, const char *in, int out_size)
|
|
||||||
{
|
|
||||||
int i, v;
|
|
||||||
uint8_t *dst = out;
|
|
||||||
|
|
||||||
v = 0;
|
|
||||||
for (i = 0; in[i] && in[i] != '='; i++) {
|
|
||||||
unsigned int index= in[i]-43;
|
|
||||||
if (index>=FF_ARRAY_ELEMS(map2) || map2[index] == 0xff)
|
|
||||||
return -1;
|
|
||||||
v = (v << 6) + map2[index];
|
|
||||||
if (i & 3) {
|
|
||||||
if (dst - out < out_size) {
|
|
||||||
*dst++ = v >> (6 - 2 * (i & 3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst - out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* b64_encode: Stolen from VLC's http.c.
|
|
||||||
* Simplified by Michael.
|
|
||||||
* Fixed edge cases and made it work from data (vs. strings) by Ryan.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
|
|
||||||
{
|
|
||||||
static const char b64[] =
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
||||||
char *ret, *dst;
|
|
||||||
unsigned i_bits = 0;
|
|
||||||
int i_shift = 0;
|
|
||||||
int bytes_remaining = in_size;
|
|
||||||
|
|
||||||
if (in_size >= UINT_MAX / 4 || out_size < AV_BASE64_SIZE(in_size))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ret = dst = out;
|
|
||||||
while (bytes_remaining) {
|
|
||||||
i_bits = (i_bits << 8) + *in++;
|
|
||||||
bytes_remaining--;
|
|
||||||
i_shift += 8;
|
|
||||||
|
|
||||||
do {
|
|
||||||
*dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
|
|
||||||
i_shift -= 6;
|
|
||||||
} while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
|
|
||||||
}
|
|
||||||
while ((dst - ret) & 3)
|
|
||||||
*dst++ = '=';
|
|
||||||
*dst = '\0';
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
|
|
||||||
#undef printf
|
|
||||||
|
|
||||||
#define MAX_DATA_SIZE 1024
|
|
||||||
#define MAX_ENCODED_SIZE 2048
|
|
||||||
|
|
||||||
static int test_encode_decode(const uint8_t *data, unsigned int data_size,
|
|
||||||
const char *encoded_ref)
|
|
||||||
{
|
|
||||||
char encoded[MAX_ENCODED_SIZE];
|
|
||||||
uint8_t data2[MAX_DATA_SIZE];
|
|
||||||
int data2_size, max_data2_size = MAX_DATA_SIZE;
|
|
||||||
|
|
||||||
if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) {
|
|
||||||
printf("Failed: cannot encode the input data\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (encoded_ref && strcmp(encoded, encoded_ref)) {
|
|
||||||
printf("Failed: encoded string differs from reference\n"
|
|
||||||
"Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) < 0) {
|
|
||||||
printf("Failed: cannot decode the encoded string\n"
|
|
||||||
"Encoded:\n%s\n", encoded);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (memcmp(data2, data, data_size)) {
|
|
||||||
printf("Failed: encoded/decoded data differs from original data\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Passed!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
int i, error_count = 0;
|
|
||||||
struct test {
|
|
||||||
const uint8_t *data;
|
|
||||||
const char *encoded_ref;
|
|
||||||
} tests[] = {
|
|
||||||
{ "", ""},
|
|
||||||
{ "1", "MQ=="},
|
|
||||||
{ "22", "MjI="},
|
|
||||||
{ "333", "MzMz"},
|
|
||||||
{ "4444", "NDQ0NA=="},
|
|
||||||
{ "55555", "NTU1NTU="},
|
|
||||||
{ "666666", "NjY2NjY2"},
|
|
||||||
{ "abc:def", "YWJjOmRlZg=="},
|
|
||||||
};
|
|
||||||
|
|
||||||
printf("Encoding/decoding tests\n");
|
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
|
|
||||||
error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref);
|
|
||||||
|
|
||||||
return error_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
|
||||||
*
|
|
||||||
* This file is part of FFmpeg.
|
|
||||||
*
|
|
||||||
* FFmpeg is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* FFmpeg 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with FFmpeg; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
|
|
||||||
#ifndef AVUTIL_BASE64_H
|
|
||||||
#define AVUTIL_BASE64_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode a base64-encoded string.
|
|
||||||
*
|
|
||||||
* @param out buffer for decoded data
|
|
||||||
* @param in null-terminated input string
|
|
||||||
* @param out_size size in bytes of the out buffer, must be at
|
|
||||||
* least 3/4 of the length of in
|
|
||||||
* @return number of bytes written, or a negative value in case of
|
|
||||||
* invalid input
|
|
||||||
*/
|
|
||||||
int av_base64_decode(uint8_t *out, const char *in, int out_size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode data to base64 and null-terminate.
|
|
||||||
*
|
|
||||||
* @param out buffer for encoded data
|
|
||||||
* @param out_size size in bytes of the output buffer, must be at
|
|
||||||
* least AV_BASE64_SIZE(in_size)
|
|
||||||
* @param in_size size in bytes of the 'in' buffer
|
|
||||||
* @return 'out' or NULL in case of error
|
|
||||||
*/
|
|
||||||
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate the output size needed to base64-encode x bytes.
|
|
||||||
*/
|
|
||||||
#define AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
|
|
||||||
|
|
||||||
#endif /* AVUTIL_BASE64_H */
|
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "AAC.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
void writeAdtsHeader(const AACFrame &hed, uint8_t *pcAdts) {
|
||||||
|
pcAdts[0] = (hed.syncword >> 4 & 0xFF); //8bit
|
||||||
|
pcAdts[1] = (hed.syncword << 4 & 0xF0); //4 bit
|
||||||
|
pcAdts[1] |= (hed.id << 3 & 0x08); //1 bit
|
||||||
|
pcAdts[1] |= (hed.layer << 1 & 0x06); //2bit
|
||||||
|
pcAdts[1] |= (hed.protection_absent & 0x01); //1 bit
|
||||||
|
|
||||||
|
pcAdts[2] = (hed.profile << 6 & 0xC0); // 2 bit
|
||||||
|
pcAdts[2] |= (hed.sf_index << 2 & 0x3C); //4bit
|
||||||
|
pcAdts[2] |= (hed.private_bit << 1 & 0x02); //1 bit
|
||||||
|
pcAdts[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit
|
||||||
|
|
||||||
|
pcAdts[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit
|
||||||
|
pcAdts[3] |= (hed.original << 5 & 0x20); //1 bit
|
||||||
|
pcAdts[3] |= (hed.home << 4 & 0x10); //1 bit
|
||||||
|
pcAdts[3] |= (hed.copyright_identification_bit << 3 & 0x08); //1 bit
|
||||||
|
pcAdts[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit
|
||||||
|
pcAdts[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit
|
||||||
|
|
||||||
|
pcAdts[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit
|
||||||
|
|
||||||
|
pcAdts[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit
|
||||||
|
pcAdts[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit
|
||||||
|
|
||||||
|
pcAdts[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit
|
||||||
|
pcAdts[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 bit
|
||||||
|
}
|
||||||
|
string makeAdtsConfig(const uint8_t *pcAdts){
|
||||||
|
if (!(pcAdts[0] == 0xFF && (pcAdts[1] & 0xF0) == 0xF0)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// Get and check the 'profile':
|
||||||
|
unsigned char profile = (pcAdts[2] & 0xC0) >> 6; // 2 bits
|
||||||
|
if (profile == 3) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and check the 'sampling_frequency_index':
|
||||||
|
unsigned char sampling_frequency_index = (pcAdts[2] & 0x3C) >> 2; // 4 bits
|
||||||
|
if (samplingFrequencyTable[sampling_frequency_index] == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and check the 'channel_configuration':
|
||||||
|
unsigned char channel_configuration = ((pcAdts[2] & 0x01) << 2)
|
||||||
|
| ((pcAdts[3] & 0xC0) >> 6); // 3 bits
|
||||||
|
|
||||||
|
unsigned char audioSpecificConfig[2];
|
||||||
|
unsigned char const audioObjectType = profile + 1;
|
||||||
|
audioSpecificConfig[0] = (audioObjectType << 3) | (sampling_frequency_index >> 1);
|
||||||
|
audioSpecificConfig[1] = (sampling_frequency_index << 7) | (channel_configuration << 3);
|
||||||
|
return string((char *)audioSpecificConfig,2);
|
||||||
|
}
|
||||||
|
void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts) {
|
||||||
|
uint8_t cfg1 = strAudioCfg[0];
|
||||||
|
uint8_t cfg2 = strAudioCfg[1];
|
||||||
|
|
||||||
|
int audioObjectType;
|
||||||
|
int sampling_frequency_index;
|
||||||
|
int channel_configuration;
|
||||||
|
|
||||||
|
audioObjectType = cfg1 >> 3;
|
||||||
|
sampling_frequency_index = ((cfg1 & 0x07) << 1) | (cfg2 >> 7);
|
||||||
|
channel_configuration = (cfg2 & 0x7F) >> 3;
|
||||||
|
|
||||||
|
adts.syncword = 0x0FFF;
|
||||||
|
adts.id = 0;
|
||||||
|
adts.layer = 0;
|
||||||
|
adts.protection_absent = 1;
|
||||||
|
adts.profile = audioObjectType - 1;
|
||||||
|
adts.sf_index = sampling_frequency_index;
|
||||||
|
adts.private_bit = 0;
|
||||||
|
adts.channel_configuration = channel_configuration;
|
||||||
|
adts.original = 0;
|
||||||
|
adts.home = 0;
|
||||||
|
adts.copyright_identification_bit = 0;
|
||||||
|
adts.copyright_identification_start = 0;
|
||||||
|
adts.aac_frame_length = 7;
|
||||||
|
adts.adts_buffer_fullness = 2047;
|
||||||
|
adts.no_raw_data_blocks_in_frame = 0;
|
||||||
|
}
|
||||||
|
void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel){
|
||||||
|
iSampleRate = samplingFrequencyTable[adts.sf_index];
|
||||||
|
iChannel = adts.channel_configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,310 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_AAC_H
|
||||||
|
#define ZLMEDIAKIT_AAC_H
|
||||||
|
|
||||||
|
#include "Frame.h"
|
||||||
|
#include "Track.h"
|
||||||
|
#include "RtspMuxer/RtspSdp.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
class AACFrame;
|
||||||
|
|
||||||
|
unsigned const samplingFrequencyTable[16] = { 96000, 88200,
|
||||||
|
64000, 48000,
|
||||||
|
44100, 32000,
|
||||||
|
24000, 22050,
|
||||||
|
16000, 12000,
|
||||||
|
11025, 8000,
|
||||||
|
7350, 0, 0, 0 };
|
||||||
|
|
||||||
|
void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts);
|
||||||
|
void writeAdtsHeader(const AACFrame &adts, uint8_t *pcAdts) ;
|
||||||
|
string makeAdtsConfig(const uint8_t *pcAdts);
|
||||||
|
void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac帧,包含adts头
|
||||||
|
*/
|
||||||
|
class AACFrame : public Frame {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<AACFrame> Ptr;
|
||||||
|
|
||||||
|
char *data() const override{
|
||||||
|
return (char *)buffer;
|
||||||
|
}
|
||||||
|
uint32_t size() const override {
|
||||||
|
return aac_frame_length;
|
||||||
|
}
|
||||||
|
uint32_t dts() const override {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
uint32_t prefixSize() const override{
|
||||||
|
return iPrefixSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackAudio;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return CodecAAC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
unsigned int syncword; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始
|
||||||
|
unsigned int id; //1 bslbf MPEG 标示符, 设置为1
|
||||||
|
unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’
|
||||||
|
unsigned int protection_absent; //1 bslbf 表示是否误码校验
|
||||||
|
unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC
|
||||||
|
unsigned int sf_index; //4 uimsbf 表示使用的采样率下标
|
||||||
|
unsigned int private_bit; //1 bslbf
|
||||||
|
unsigned int channel_configuration; //3 uimsbf 表示声道数
|
||||||
|
unsigned int original; //1 bslbf
|
||||||
|
unsigned int home; //1 bslbf
|
||||||
|
//下面的为改变的参数即每一帧都不同
|
||||||
|
unsigned int copyright_identification_bit; //1 bslbf
|
||||||
|
unsigned int copyright_identification_start; //1 bslbf
|
||||||
|
unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block
|
||||||
|
unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流
|
||||||
|
//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧.
|
||||||
|
//所以说number_of_raw_data_blocks_in_frame == 0
|
||||||
|
//表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
|
||||||
|
unsigned int no_raw_data_blocks_in_frame; //2 uimsfb
|
||||||
|
unsigned char buffer[2 * 1024 + 7];
|
||||||
|
uint16_t sequence;
|
||||||
|
uint32_t timeStamp;
|
||||||
|
uint32_t iPrefixSize = 7;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
class AACFrameNoCopyAble : public FrameNoCopyAble {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<AACFrameNoCopyAble> Ptr;
|
||||||
|
|
||||||
|
AACFrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 7){
|
||||||
|
buffer_ptr = ptr;
|
||||||
|
buffer_size = size;
|
||||||
|
timeStamp = stamp;
|
||||||
|
iPrefixSize = prefixeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackAudio;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return CodecAAC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac音频通道
|
||||||
|
*/
|
||||||
|
class AACTrack : public AudioTrack{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<AACTrack> Ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延后获取adts头信息
|
||||||
|
* 在随后的inputFrame中获取adts头信息
|
||||||
|
*/
|
||||||
|
AACTrack(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造aac类型的媒体
|
||||||
|
* @param aac_cfg aac两个字节的配置信息
|
||||||
|
*/
|
||||||
|
AACTrack(const string &aac_cfg){
|
||||||
|
if(aac_cfg.size() != 2){
|
||||||
|
throw std::invalid_argument("adts配置必须为2个字节");
|
||||||
|
}
|
||||||
|
_cfg = aac_cfg;
|
||||||
|
onReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造aac类型的媒体
|
||||||
|
* @param adts_header adts头,7个字节
|
||||||
|
* @param adts_header_len adts头长度,不少于7个字节
|
||||||
|
*/
|
||||||
|
AACTrack(const char *adts_header,int adts_header_len = 7){
|
||||||
|
if(adts_header_len < 7){
|
||||||
|
throw std::invalid_argument("adts头必须不少于7个字节");
|
||||||
|
}
|
||||||
|
_cfg = makeAdtsConfig((uint8_t*)adts_header);
|
||||||
|
onReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造aac类型的媒体
|
||||||
|
* @param aac_frame_with_adts 带adts头的aac帧
|
||||||
|
*/
|
||||||
|
AACTrack(const Frame::Ptr &aac_frame_with_adts){
|
||||||
|
if(aac_frame_with_adts->getCodecId() != CodecAAC || aac_frame_with_adts->prefixSize() < 7){
|
||||||
|
throw std::invalid_argument("必须输入带adts头的aac帧");
|
||||||
|
}
|
||||||
|
_cfg = makeAdtsConfig((uint8_t*)aac_frame_with_adts->data());
|
||||||
|
onReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取aac两个字节的配置
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
const string &getAacCfg() const{
|
||||||
|
return _cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回编码类型
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return CodecAAC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在获取aac_cfg前是无效的Track
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool ready() override {
|
||||||
|
return !_cfg.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回音频采样率
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getAudioSampleRate() const override{
|
||||||
|
return _sampleRate;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 返回音频采样位数,一般为16或8
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getAudioSampleBit() const override{
|
||||||
|
return _sampleBit;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 返回音频通道数
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getAudioChannel() const override{
|
||||||
|
return _channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入数据帧,并获取aac_cfg
|
||||||
|
* @param frame 数据帧
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override{
|
||||||
|
if(_cfg.empty() && frame->prefixSize() >= 7){
|
||||||
|
//7个字节的adts头
|
||||||
|
_cfg = makeAdtsConfig(reinterpret_cast<const uint8_t *>(frame->data()));
|
||||||
|
onReady();
|
||||||
|
}
|
||||||
|
AudioTrack::inputFrame(frame);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* 解析2个字节的aac配置
|
||||||
|
*/
|
||||||
|
void onReady(){
|
||||||
|
AACFrame aacFrame;
|
||||||
|
makeAdtsHeader(_cfg,aacFrame);
|
||||||
|
getAACInfo(aacFrame,_sampleRate,_channel);
|
||||||
|
}
|
||||||
|
Track::Ptr clone() override {
|
||||||
|
return std::make_shared<std::remove_reference<decltype(*this)>::type >(*this);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
string _cfg;
|
||||||
|
int _sampleRate = 0;
|
||||||
|
int _sampleBit = 16;
|
||||||
|
int _channel = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aac类型SDP
|
||||||
|
*/
|
||||||
|
class AACSdp : public Sdp {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param aac_cfg aac两个字节的配置描述
|
||||||
|
* @param sample_rate 音频采样率
|
||||||
|
* @param playload_type rtp playload type 默认98
|
||||||
|
* @param bitrate 比特率
|
||||||
|
*/
|
||||||
|
AACSdp(const string &aac_cfg,
|
||||||
|
int sample_rate,
|
||||||
|
int playload_type = 98,
|
||||||
|
int bitrate = 128) : Sdp(sample_rate,playload_type){
|
||||||
|
_printer << "m=audio 0 RTP/AVP " << playload_type << "\r\n";
|
||||||
|
_printer << "b=AS:" << bitrate << "\r\n";
|
||||||
|
_printer << "a=rtpmap:" << playload_type << " MPEG4-GENERIC/" << sample_rate << "\r\n";
|
||||||
|
|
||||||
|
char configStr[32] = {0};
|
||||||
|
snprintf(configStr, sizeof(configStr), "%02X%02X", (uint8_t)aac_cfg[0], (uint8_t)aac_cfg[1]);
|
||||||
|
_printer << "a=fmtp:" << playload_type << " streamtype=5;profile-level-id=1;mode=AAC-hbr;"
|
||||||
|
<< "sizelength=13;indexlength=3;indexdeltalength=3;config="
|
||||||
|
<< configStr << "\r\n";
|
||||||
|
_printer << "a=control:trackID=" << getTrackType() << "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
string getSdp() const override {
|
||||||
|
return _printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override {
|
||||||
|
return TrackAudio;
|
||||||
|
}
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return CodecAAC;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
_StrPrinter _printer;
|
||||||
|
};
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_AAC_H
|
||||||
|
|
@ -0,0 +1,270 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Factory.h"
|
||||||
|
#include "RtmpMuxer/H264RtmpCodec.h"
|
||||||
|
#include "RtmpMuxer/AACRtmpCodec.h"
|
||||||
|
#include "RtspMuxer/H264RtpCodec.h"
|
||||||
|
#include "RtspMuxer/AACRtpCodec.h"
|
||||||
|
#include "RtspMuxer/H265RtpCodec.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
Sdp::Ptr Factory::getSdpByTrack(const Track::Ptr &track) {
|
||||||
|
switch (track->getCodecId()){
|
||||||
|
case CodecH264:{
|
||||||
|
H264Track::Ptr h264Track = dynamic_pointer_cast<H264Track>(track);
|
||||||
|
if(!h264Track){
|
||||||
|
WarnL << "该Track不是H264Track类型";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if(!h264Track->ready()){
|
||||||
|
WarnL << "该Track未准备好";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::make_shared<H264Sdp>(h264Track->getSps(),h264Track->getPps());
|
||||||
|
}
|
||||||
|
|
||||||
|
case CodecH265:{
|
||||||
|
H265Track::Ptr h265Track = dynamic_pointer_cast<H265Track>(track);
|
||||||
|
if(!h265Track){
|
||||||
|
WarnL << "该Track不是H265Track类型";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if(!h265Track->ready()){
|
||||||
|
WarnL << "该Track未准备好";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::make_shared<H265Sdp>(h265Track->getVps(),h265Track->getSps(),h265Track->getPps());
|
||||||
|
}
|
||||||
|
|
||||||
|
case CodecAAC:{
|
||||||
|
AACTrack::Ptr aacTrack = dynamic_pointer_cast<AACTrack>(track);
|
||||||
|
if(!aacTrack){
|
||||||
|
WarnL << "该Track不是AACTrack类型";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if(!aacTrack->ready()){
|
||||||
|
WarnL << "该Track未准备好";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::make_shared<AACSdp>(aacTrack->getAacCfg(),aacTrack->getAudioSampleRate());
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
WarnL << "暂不支持的CodecId:" << track->getCodecId();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
|
||||||
|
if (strcasecmp(track->_codec.data(), "mpeg4-generic") == 0) {
|
||||||
|
string aac_cfg_str = FindField(track->_fmtp.c_str(), "config=", nullptr);
|
||||||
|
if (aac_cfg_str.size() != 4) {
|
||||||
|
aac_cfg_str = FindField(track->_fmtp.c_str(), "config=", ";");
|
||||||
|
}
|
||||||
|
if (aac_cfg_str.size() != 4) {
|
||||||
|
//延后获取adts头
|
||||||
|
return std::make_shared<AACTrack>();
|
||||||
|
}
|
||||||
|
string aac_cfg;
|
||||||
|
|
||||||
|
unsigned int cfg1;
|
||||||
|
sscanf(aac_cfg_str.substr(0, 2).c_str(), "%02X", &cfg1);
|
||||||
|
cfg1 &= 0x00FF;
|
||||||
|
aac_cfg.push_back(cfg1);
|
||||||
|
|
||||||
|
unsigned int cfg2;
|
||||||
|
sscanf(aac_cfg_str.substr(2, 2).c_str(), "%02X", &cfg2);
|
||||||
|
cfg2 &= 0x00FF;
|
||||||
|
aac_cfg.push_back(cfg2);
|
||||||
|
|
||||||
|
return std::make_shared<AACTrack>(aac_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(track->_codec.data(), "h264") == 0) {
|
||||||
|
string sps_pps = FindField(track->_fmtp.c_str(), "sprop-parameter-sets=", nullptr);
|
||||||
|
if(sps_pps.empty()){
|
||||||
|
return std::make_shared<H264Track>();
|
||||||
|
}
|
||||||
|
string base64_SPS = FindField(sps_pps.c_str(), NULL, ",");
|
||||||
|
string base64_PPS = FindField(sps_pps.c_str(), ",", NULL);
|
||||||
|
if(base64_PPS.back() == ';'){
|
||||||
|
base64_PPS.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sps = decodeBase64(base64_SPS);
|
||||||
|
auto pps = decodeBase64(base64_PPS);
|
||||||
|
return std::make_shared<H264Track>(sps,pps,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(track->_codec.data(), "h265") == 0) {
|
||||||
|
//a=fmtp:96 sprop-sps=QgEBAWAAAAMAsAAAAwAAAwBdoAKAgC0WNrkky/AIAAADAAgAAAMBlQg=; sprop-pps=RAHA8vA8kAA=
|
||||||
|
int pt;
|
||||||
|
char sprop_vps[128] = {0},sprop_sps[128] = {0},sprop_pps[128] = {0};
|
||||||
|
if (4 == sscanf(track->_fmtp.c_str(), "%d sprop-vps=%127[^;]; sprop-sps=%127[^;]; sprop-pps=%127[^;]", &pt, sprop_vps,sprop_sps, sprop_pps)) {
|
||||||
|
auto vps = decodeBase64(sprop_vps);
|
||||||
|
auto sps = decodeBase64(sprop_sps);
|
||||||
|
auto pps = decodeBase64(sprop_pps);
|
||||||
|
return std::make_shared<H265Track>(vps,sps,pps,0,0,0);
|
||||||
|
}
|
||||||
|
if (3 == sscanf(track->_fmtp.c_str(), "%d sprop-sps=%127[^;]; sprop-pps=%127[^;]", &pt,sprop_sps, sprop_pps)) {
|
||||||
|
auto sps = decodeBase64(sprop_sps);
|
||||||
|
auto pps = decodeBase64(sprop_pps);
|
||||||
|
return std::make_shared<H265Track>("",sps,pps,0,0,0);
|
||||||
|
}
|
||||||
|
return std::make_shared<H265Track>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WarnL << "暂不支持该sdp:" << track->_codec << " " << track->_fmtp;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Track::Ptr Factory::getTrackByCodecId(CodecId codecId) {
|
||||||
|
switch (codecId){
|
||||||
|
case CodecH264:{
|
||||||
|
return std::make_shared<H264Track>();
|
||||||
|
}
|
||||||
|
case CodecH265:{
|
||||||
|
return std::make_shared<H265Track>();
|
||||||
|
}
|
||||||
|
case CodecAAC:{
|
||||||
|
return std::make_shared<AACTrack>();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
WarnL << "暂不支持该CodecId:" << codecId;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RtpCodec::Ptr Factory::getRtpEncoderById(CodecId codecId,
|
||||||
|
uint32_t ui32Ssrc,
|
||||||
|
uint32_t ui32MtuSize,
|
||||||
|
uint32_t ui32SampleRate,
|
||||||
|
uint8_t ui8PlayloadType,
|
||||||
|
uint8_t ui8Interleaved) {
|
||||||
|
switch (codecId){
|
||||||
|
case CodecH264:
|
||||||
|
return std::make_shared<H264RtpEncoder>(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved);
|
||||||
|
case CodecH265:
|
||||||
|
return std::make_shared<H265RtpEncoder>(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved);
|
||||||
|
case CodecAAC:
|
||||||
|
return std::make_shared<AACRtpEncoder>(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved);
|
||||||
|
default:
|
||||||
|
WarnL << "暂不支持该CodecId:" << codecId;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RtpCodec::Ptr Factory::getRtpDecoderById(CodecId codecId) {
|
||||||
|
switch (codecId){
|
||||||
|
case CodecH264:
|
||||||
|
return std::make_shared<H264RtpDecoder>();
|
||||||
|
case CodecH265:
|
||||||
|
return std::make_shared<H265RtpDecoder>();
|
||||||
|
case CodecAAC:
|
||||||
|
return std::make_shared<AACRtpDecoder>();
|
||||||
|
default:
|
||||||
|
WarnL << "暂不支持该CodecId:" << codecId;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////rtmp相关///////////////////////////////////////////
|
||||||
|
|
||||||
|
Track::Ptr Factory::getTrackByAmf(const AMFValue &amf) {
|
||||||
|
CodecId codecId = getCodecIdByAmf(amf);
|
||||||
|
if(codecId == CodecInvalid){
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return getTrackByCodecId(codecId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CodecId Factory::getCodecIdByAmf(const AMFValue &val){
|
||||||
|
if (val.type() == AMF_STRING){
|
||||||
|
auto str = val.as_string();
|
||||||
|
if(str == "avc1"){
|
||||||
|
return CodecH264;
|
||||||
|
}
|
||||||
|
if(str == "mp4a"){
|
||||||
|
return CodecAAC;
|
||||||
|
}
|
||||||
|
WarnL << "暂不支持该Amf:" << str;
|
||||||
|
return CodecInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val.type() != AMF_NULL){
|
||||||
|
auto type_id = val.as_integer();
|
||||||
|
switch (type_id){
|
||||||
|
case 7:{
|
||||||
|
return CodecH264;
|
||||||
|
}
|
||||||
|
case 10:{
|
||||||
|
return CodecAAC;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
WarnL << "暂不支持该Amf:" << type_id;
|
||||||
|
return CodecInvalid;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
WarnL << "Metedata不存在相应的Track";
|
||||||
|
}
|
||||||
|
|
||||||
|
return CodecInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) {
|
||||||
|
switch (track->getCodecId()){
|
||||||
|
case CodecH264:
|
||||||
|
return std::make_shared<H264RtmpEncoder>(track);
|
||||||
|
case CodecAAC:
|
||||||
|
return std::make_shared<AACRtmpEncoder>(track);
|
||||||
|
default:
|
||||||
|
WarnL << "暂不支持该CodecId:" << track->getCodecId();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AMFValue Factory::getAmfByCodecId(CodecId codecId) {
|
||||||
|
switch (codecId){
|
||||||
|
case CodecAAC:{
|
||||||
|
return AMFValue("mp4a");
|
||||||
|
}
|
||||||
|
case CodecH264:{
|
||||||
|
return AMFValue("avc1");
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return AMFValue(AMF_NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_FACTORY_H
|
||||||
|
#define ZLMEDIAKIT_FACTORY_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "Rtmp/amf.h"
|
||||||
|
#include "Extension/Track.h"
|
||||||
|
#include "RtspMuxer/RtspSdp.h"
|
||||||
|
#include "RtspMuxer/RtpCodec.h"
|
||||||
|
#include "RtmpMuxer/RtmpCodec.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
class Factory {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据CodecId获取Track,该Track的ready()状态一般都为false
|
||||||
|
* @param codecId 编解码器id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static Track::Ptr getTrackByCodecId(CodecId codecId);
|
||||||
|
|
||||||
|
////////////////////////////////rtsp相关//////////////////////////////////
|
||||||
|
/**
|
||||||
|
* 根据sdp生成Track对象
|
||||||
|
*/
|
||||||
|
static Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据Track生成SDP对象
|
||||||
|
* @param track 媒体信息
|
||||||
|
* @return 返回sdp对象
|
||||||
|
*/
|
||||||
|
static Sdp::Ptr getSdpByTrack(const Track::Ptr &track);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据CodecId生成Rtp打包器
|
||||||
|
* @param codecId
|
||||||
|
* @param ui32Ssrc
|
||||||
|
* @param ui32MtuSize
|
||||||
|
* @param ui32SampleRate
|
||||||
|
* @param ui8PlayloadType
|
||||||
|
* @param ui8Interleaved
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static RtpCodec::Ptr getRtpEncoderById(CodecId codecId,
|
||||||
|
uint32_t ui32Ssrc,
|
||||||
|
uint32_t ui32MtuSize,
|
||||||
|
uint32_t ui32SampleRate,
|
||||||
|
uint8_t ui8PlayloadType,
|
||||||
|
uint8_t ui8Interleaved);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据CodecId生成Rtp解包器
|
||||||
|
* @param codecId
|
||||||
|
* @param ui32SampleRate
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static RtpCodec::Ptr getRtpDecoderById(CodecId codecId);
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////rtmp相关//////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据amf对象获取响应的Track
|
||||||
|
* @param amf rtmp metedata中的videocodecid或audiocodecid的值
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static Track::Ptr getTrackByAmf(const AMFValue &amf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据amf对象获取相应的CodecId
|
||||||
|
* @param val rtmp metedata中的videocodecid或audiocodecid的值
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static CodecId getCodecIdByAmf(const AMFValue &val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据Track获取Rtmp的编解码器
|
||||||
|
* @param track 媒体描述对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据codecId获取rtmp的codec描述
|
||||||
|
* @param codecId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static AMFValue getAmfByCodecId(CodecId codecId);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_FACTORY_H
|
||||||
|
|
@ -0,0 +1,312 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_FRAME_H
|
||||||
|
#define ZLMEDIAKIT_FRAME_H
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <functional>
|
||||||
|
#include "Util/RingBuffer.h"
|
||||||
|
#include "Network/Socket.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CodecInvalid = -1,
|
||||||
|
CodecH264 = 0,
|
||||||
|
CodecH265,
|
||||||
|
CodecAAC,
|
||||||
|
CodecMax = 0x7FFF
|
||||||
|
} CodecId;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TrackInvalid = -1,
|
||||||
|
TrackVideo = 0,
|
||||||
|
TrackAudio,
|
||||||
|
TrackTitle,
|
||||||
|
TrackMax = 0x7FFF
|
||||||
|
} TrackType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码信息的抽象接口
|
||||||
|
*/
|
||||||
|
class CodecInfo {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<CodecInfo> Ptr;
|
||||||
|
|
||||||
|
CodecInfo(){}
|
||||||
|
virtual ~CodecInfo(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取音视频类型
|
||||||
|
*/
|
||||||
|
virtual TrackType getTrackType() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取编解码器类型
|
||||||
|
*/
|
||||||
|
virtual CodecId getCodecId() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 帧类型的抽象接口
|
||||||
|
*/
|
||||||
|
class Frame : public Buffer, public CodecInfo{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<Frame> Ptr;
|
||||||
|
virtual ~Frame(){}
|
||||||
|
/**
|
||||||
|
* 时间戳,已经废弃,请使用dts() 、pts()接口
|
||||||
|
*/
|
||||||
|
inline uint32_t stamp() const {
|
||||||
|
return dts();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回解码时间戳,单位毫秒
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual uint32_t dts() const = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回显示时间戳,单位毫秒
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual uint32_t pts() const {
|
||||||
|
return dts();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前缀长度,譬如264前缀为0x00 00 00 01,那么前缀长度就是4
|
||||||
|
* aac前缀则为7个字节
|
||||||
|
*/
|
||||||
|
virtual uint32_t prefixSize() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回是否为关键帧
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual bool keyFrame() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 循环池辅助类
|
||||||
|
* @tparam T
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class ResourcePoolHelper{
|
||||||
|
public:
|
||||||
|
ResourcePoolHelper(int size = 8){
|
||||||
|
_pool.setSize(size);
|
||||||
|
}
|
||||||
|
virtual ~ResourcePoolHelper(){}
|
||||||
|
|
||||||
|
std::shared_ptr<T> obtainObj(){
|
||||||
|
return _pool.obtain();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ResourcePool<T> _pool;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写帧接口的抽闲接口
|
||||||
|
*/
|
||||||
|
class FrameWriterInterface {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<FrameWriterInterface> Ptr;
|
||||||
|
|
||||||
|
FrameWriterInterface(){}
|
||||||
|
virtual ~FrameWriterInterface(){}
|
||||||
|
/**
|
||||||
|
* 写入帧数据
|
||||||
|
* @param frame 帧
|
||||||
|
*/
|
||||||
|
virtual void inputFrame(const Frame::Ptr &frame) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写帧接口转function,辅助类
|
||||||
|
*/
|
||||||
|
class FrameWriterInterfaceHelper : public FrameWriterInterface {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<FrameWriterInterfaceHelper> Ptr;
|
||||||
|
typedef std::function<void(const Frame::Ptr &frame)> onWriteFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inputFrame后触发onWriteFrame回调
|
||||||
|
* @param cb
|
||||||
|
*/
|
||||||
|
FrameWriterInterfaceHelper(const onWriteFrame& cb){
|
||||||
|
_writeCallback = cb;
|
||||||
|
}
|
||||||
|
virtual ~FrameWriterInterfaceHelper(){}
|
||||||
|
/**
|
||||||
|
* 写入帧数据
|
||||||
|
* @param frame 帧
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override {
|
||||||
|
_writeCallback(frame);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
onWriteFrame _writeCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 帧环形缓存接口类
|
||||||
|
*/
|
||||||
|
class FrameRingInterface : public FrameWriterInterface{
|
||||||
|
public:
|
||||||
|
typedef RingBuffer<Frame::Ptr> RingType;
|
||||||
|
typedef std::shared_ptr<FrameRingInterface> Ptr;
|
||||||
|
|
||||||
|
FrameRingInterface(){}
|
||||||
|
virtual ~FrameRingInterface(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取帧环形缓存
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual RingType::Ptr getFrameRing() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置帧环形缓存
|
||||||
|
* @param ring
|
||||||
|
*/
|
||||||
|
virtual void setFrameRing(const RingType::Ptr &ring) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 帧环形缓存
|
||||||
|
*/
|
||||||
|
class FrameRing : public FrameRingInterface{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<FrameRing> Ptr;
|
||||||
|
|
||||||
|
FrameRing(){
|
||||||
|
}
|
||||||
|
virtual ~FrameRing(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取帧环形缓存
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
RingType::Ptr getFrameRing() const override {
|
||||||
|
return _frameRing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置帧环形缓存
|
||||||
|
* @param ring
|
||||||
|
*/
|
||||||
|
void setFrameRing(const RingType::Ptr &ring) override {
|
||||||
|
_frameRing = ring;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入数据帧
|
||||||
|
* @param frame
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override{
|
||||||
|
if(_frameRing){
|
||||||
|
_frameRing->write(frame,frame->keyFrame());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
RingType::Ptr _frameRing;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支持代理转发的帧环形缓存
|
||||||
|
*/
|
||||||
|
class FrameRingInterfaceDelegate : public FrameRing {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<FrameRingInterfaceDelegate> Ptr;
|
||||||
|
|
||||||
|
FrameRingInterfaceDelegate(){}
|
||||||
|
virtual ~FrameRingInterfaceDelegate(){}
|
||||||
|
|
||||||
|
void addDelegate(const FrameWriterInterface::Ptr &delegate){
|
||||||
|
lock_guard<mutex> lck(_mtx);
|
||||||
|
_delegateMap.emplace(delegate.get(),delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void delDelegate(void *ptr){
|
||||||
|
lock_guard<mutex> lck(_mtx);
|
||||||
|
_delegateMap.erase(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入帧数据
|
||||||
|
* @param frame 帧
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override{
|
||||||
|
FrameRing::inputFrame(frame);
|
||||||
|
lock_guard<mutex> lck(_mtx);
|
||||||
|
for(auto &pr : _delegateMap){
|
||||||
|
pr.second->inputFrame(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
mutex _mtx;
|
||||||
|
map<void *,FrameWriterInterface::Ptr> _delegateMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FrameNoCopyAble : public Frame{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<FrameNoCopyAble> Ptr;
|
||||||
|
char *data() const override{
|
||||||
|
return buffer_ptr;
|
||||||
|
}
|
||||||
|
uint32_t size() const override {
|
||||||
|
return buffer_size;
|
||||||
|
}
|
||||||
|
uint32_t dts() const override {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
uint32_t prefixSize() const override{
|
||||||
|
return iPrefixSize;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
char *buffer_ptr;
|
||||||
|
uint32_t buffer_size;
|
||||||
|
uint32_t timeStamp;
|
||||||
|
uint32_t iPrefixSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_FRAME_H
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "H264.h"
|
||||||
|
#include "H264/SPSParser.h"
|
||||||
|
#include "Util/logger.h"
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
bool getAVCInfo(const string& strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps) {
|
||||||
|
return getAVCInfo(strSps.data(),strSps.size(),iVideoWidth,iVideoHeight,iVideoFps);
|
||||||
|
}
|
||||||
|
bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps){
|
||||||
|
T_GetBitContext tGetBitBuf;
|
||||||
|
T_SPS tH264SpsInfo;
|
||||||
|
memset(&tGetBitBuf,0,sizeof(tGetBitBuf));
|
||||||
|
memset(&tH264SpsInfo,0,sizeof(tH264SpsInfo));
|
||||||
|
tGetBitBuf.pu8Buf = (uint8_t*)sps + 1;
|
||||||
|
tGetBitBuf.iBufSize = sps_len - 1;
|
||||||
|
if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight);
|
||||||
|
h264GeFramerate(&tH264SpsInfo, &iVideoFps);
|
||||||
|
//ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,360 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_H264_H
|
||||||
|
#define ZLMEDIAKIT_H264_H
|
||||||
|
|
||||||
|
#include "Frame.h"
|
||||||
|
#include "Track.h"
|
||||||
|
#include "RtspMuxer/RtspSdp.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define H264_TYPE(v) ((uint8_t)(v) & 0x1F)
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
|
||||||
|
bool getAVCInfo(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 264帧类
|
||||||
|
*/
|
||||||
|
class H264Frame : public Frame {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<H264Frame> Ptr;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NAL_SPS = 7,
|
||||||
|
NAL_PPS = 8,
|
||||||
|
NAL_IDR = 5,
|
||||||
|
NAL_B_P = 1
|
||||||
|
} NalType;
|
||||||
|
|
||||||
|
char *data() const override{
|
||||||
|
return (char *)buffer.data();
|
||||||
|
}
|
||||||
|
uint32_t size() const override {
|
||||||
|
return buffer.size();
|
||||||
|
}
|
||||||
|
uint32_t dts() const override {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pts() const override {
|
||||||
|
return ptsStamp ? ptsStamp : timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t prefixSize() const override{
|
||||||
|
return iPrefixSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return CodecH264;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return type == NAL_IDR;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
uint16_t sequence;
|
||||||
|
uint32_t timeStamp;
|
||||||
|
uint32_t ptsStamp = 0;
|
||||||
|
unsigned char type;
|
||||||
|
string buffer;
|
||||||
|
uint32_t iPrefixSize = 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class H264FrameNoCopyAble : public FrameNoCopyAble {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<H264FrameNoCopyAble> Ptr;
|
||||||
|
|
||||||
|
H264FrameNoCopyAble(char *ptr,uint32_t size,uint32_t stamp,int prefixeSize = 4){
|
||||||
|
buffer_ptr = ptr;
|
||||||
|
buffer_size = size;
|
||||||
|
timeStamp = stamp;
|
||||||
|
iPrefixSize = prefixeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override{
|
||||||
|
return TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override{
|
||||||
|
return CodecH264;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return H264_TYPE(buffer_ptr[iPrefixSize]) == H264Frame::NAL_IDR;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 264视频通道
|
||||||
|
*/
|
||||||
|
class H264Track : public VideoTrack{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<H264Track> Ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不指定sps pps构造h264类型的媒体
|
||||||
|
* 在随后的inputFrame中获取sps pps
|
||||||
|
*/
|
||||||
|
H264Track(){}
|
||||||
|
/**
|
||||||
|
* 构造h264类型的媒体
|
||||||
|
* @param sps sps帧数据
|
||||||
|
* @param pps pps帧数据
|
||||||
|
* @param sps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01
|
||||||
|
* @param pps_prefix_len 264头长度,可以为3个或4个字节,一般为0x00 00 00 01
|
||||||
|
*/
|
||||||
|
H264Track(const string &sps,const string &pps,int sps_prefix_len = 4,int pps_prefix_len = 4){
|
||||||
|
_sps = sps.substr(sps_prefix_len);
|
||||||
|
_pps = pps.substr(pps_prefix_len);
|
||||||
|
onReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造h264类型的媒体
|
||||||
|
* @param sps sps帧
|
||||||
|
* @param pps pps帧
|
||||||
|
*/
|
||||||
|
H264Track(const Frame::Ptr &sps,const Frame::Ptr &pps){
|
||||||
|
if(sps->getCodecId() != CodecH264 || pps->getCodecId() != CodecH264 ){
|
||||||
|
throw std::invalid_argument("必须输入H264类型的帧");
|
||||||
|
}
|
||||||
|
_sps = string(sps->data() + sps->prefixSize(),sps->size() - sps->prefixSize());
|
||||||
|
_pps = string(pps->data() + pps->prefixSize(),pps->size() - pps->prefixSize());
|
||||||
|
onReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回不带0x00 00 00 01头的sps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
const string &getSps() const{
|
||||||
|
return _sps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回不带0x00 00 00 01头的pps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
const string &getPps() const{
|
||||||
|
return _pps;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return CodecH264;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回视频高度
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getVideoHeight() const override{
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回视频宽度
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getVideoWidth() const override{
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回视频fps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
float getVideoFps() const override{
|
||||||
|
return _fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ready() override {
|
||||||
|
return !_sps.empty() && !_pps.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入数据帧,并获取sps pps
|
||||||
|
* @param frame 数据帧
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override{
|
||||||
|
int type = H264_TYPE(*((uint8_t *)frame->data() + frame->prefixSize()));
|
||||||
|
switch (type){
|
||||||
|
case H264Frame::NAL_SPS:{
|
||||||
|
//sps
|
||||||
|
_sps = string(frame->data() + frame->prefixSize(),frame->size() - frame->prefixSize());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case H264Frame::NAL_PPS:{
|
||||||
|
//pps
|
||||||
|
_pps = string(frame->data() + frame->prefixSize(),frame->size() - frame->prefixSize());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H264Frame::NAL_IDR:{
|
||||||
|
//I
|
||||||
|
if(!_sps.empty() && _last_frame_type != H264Frame::NAL_IDR){
|
||||||
|
if(!_spsFrame)
|
||||||
|
{
|
||||||
|
H264Frame::Ptr insertFrame = std::make_shared<H264Frame>();
|
||||||
|
insertFrame->type = H264Frame::NAL_SPS;
|
||||||
|
insertFrame->timeStamp = frame->stamp();
|
||||||
|
insertFrame->buffer.assign("\x0\x0\x0\x1",4);
|
||||||
|
insertFrame->buffer.append(_sps);
|
||||||
|
insertFrame->iPrefixSize = 4;
|
||||||
|
_spsFrame = insertFrame;
|
||||||
|
}
|
||||||
|
_spsFrame->timeStamp = frame->stamp();
|
||||||
|
VideoTrack::inputFrame(_spsFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_pps.empty() && _last_frame_type != H264Frame::NAL_IDR){
|
||||||
|
if(!_ppsFrame)
|
||||||
|
{
|
||||||
|
H264Frame::Ptr insertFrame = std::make_shared<H264Frame>();
|
||||||
|
insertFrame->type = H264Frame::NAL_PPS;
|
||||||
|
insertFrame->timeStamp = frame->stamp();
|
||||||
|
insertFrame->buffer.assign("\x0\x0\x0\x1",4);
|
||||||
|
insertFrame->buffer.append(_pps);
|
||||||
|
insertFrame->iPrefixSize = 4;
|
||||||
|
_ppsFrame = insertFrame;
|
||||||
|
}
|
||||||
|
_ppsFrame->timeStamp = frame->stamp();
|
||||||
|
VideoTrack::inputFrame(_ppsFrame);
|
||||||
|
}
|
||||||
|
VideoTrack::inputFrame(frame);
|
||||||
|
_last_frame_type = type;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H264Frame::NAL_B_P:{
|
||||||
|
//B or P
|
||||||
|
VideoTrack::inputFrame(frame);
|
||||||
|
_last_frame_type = type;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_width == 0 && ready()){
|
||||||
|
onReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* 解析sps获取宽高fps
|
||||||
|
*/
|
||||||
|
void onReady(){
|
||||||
|
getAVCInfo(_sps,_width,_height,_fps);
|
||||||
|
}
|
||||||
|
Track::Ptr clone() override {
|
||||||
|
return std::make_shared<std::remove_reference<decltype(*this)>::type >(*this);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
string _sps;
|
||||||
|
string _pps;
|
||||||
|
int _width = 0;
|
||||||
|
int _height = 0;
|
||||||
|
float _fps = 0;
|
||||||
|
int _last_frame_type = -1;
|
||||||
|
H264Frame::Ptr _spsFrame;
|
||||||
|
H264Frame::Ptr _ppsFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* h264类型sdp
|
||||||
|
*/
|
||||||
|
class H264Sdp : public Sdp {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param sps 264 sps,不带0x00000001头
|
||||||
|
* @param pps 264 pps,不带0x00000001头
|
||||||
|
* @param playload_type rtp playload type 默认96
|
||||||
|
* @param bitrate 比特率
|
||||||
|
*/
|
||||||
|
H264Sdp(const string &strSPS,
|
||||||
|
const string &strPPS,
|
||||||
|
int playload_type = 96,
|
||||||
|
int bitrate = 4000) : Sdp(90000,playload_type) {
|
||||||
|
//视频通道
|
||||||
|
_printer << "m=video 0 RTP/AVP " << playload_type << "\r\n";
|
||||||
|
_printer << "b=AS:" << bitrate << "\r\n";
|
||||||
|
_printer << "a=rtpmap:" << playload_type << " H264/" << 90000 << "\r\n";
|
||||||
|
_printer << "a=fmtp:" << playload_type << " packetization-mode=1;profile-level-id=";
|
||||||
|
|
||||||
|
char strTemp[100];
|
||||||
|
uint32_t profile_level_id = 0;
|
||||||
|
if (strSPS.length() >= 4) { // sanity check
|
||||||
|
profile_level_id = (uint8_t(strSPS[1]) << 16) |
|
||||||
|
(uint8_t(strSPS[2]) << 8) |
|
||||||
|
(uint8_t(strSPS[3])); // profile_idc|constraint_setN_flag|level_idc
|
||||||
|
}
|
||||||
|
memset(strTemp, 0, 100);
|
||||||
|
sprintf(strTemp, "%06X", profile_level_id);
|
||||||
|
_printer << strTemp;
|
||||||
|
_printer << ";sprop-parameter-sets=";
|
||||||
|
memset(strTemp, 0, 100);
|
||||||
|
av_base64_encode(strTemp, 100, (uint8_t *) strSPS.data(), strSPS.size());
|
||||||
|
_printer << strTemp << ",";
|
||||||
|
memset(strTemp, 0, 100);
|
||||||
|
av_base64_encode(strTemp, 100, (uint8_t *) strPPS.data(), strPPS.size());
|
||||||
|
_printer << strTemp << "\r\n";
|
||||||
|
_printer << "a=control:trackID=" << getTrackType() << "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
string getSdp() const override {
|
||||||
|
return _printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override {
|
||||||
|
return TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return CodecH264;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
_StrPrinter _printer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_H264_H
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "H265.h"
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_H265_H
|
||||||
|
#define ZLMEDIAKIT_H265_H
|
||||||
|
|
||||||
|
#include "Frame.h"
|
||||||
|
#include "Track.h"
|
||||||
|
#include "RtspMuxer/RtspSdp.h"
|
||||||
|
|
||||||
|
namespace mediakit {
|
||||||
|
|
||||||
|
#define H265_TYPE(v) (((uint8_t)(v) >> 1) & 0x3f)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 265帧类
|
||||||
|
*/
|
||||||
|
class H265Frame : public Frame {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<H265Frame> Ptr;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NAL_TRAIL_N = 0,
|
||||||
|
NAL_TRAIL_R = 1,
|
||||||
|
NAL_TSA_N = 2,
|
||||||
|
NAL_TSA_R = 3,
|
||||||
|
NAL_STSA_N = 4,
|
||||||
|
NAL_STSA_R = 5,
|
||||||
|
NAL_RADL_N = 6,
|
||||||
|
NAL_RADL_R = 7,
|
||||||
|
NAL_RASL_N = 8,
|
||||||
|
NAL_RASL_R = 9,
|
||||||
|
NAL_BLA_W_LP = 16,
|
||||||
|
NAL_BLA_W_RADL = 17,
|
||||||
|
NAL_BLA_N_LP = 18,
|
||||||
|
NAL_IDR_W_RADL = 19,
|
||||||
|
NAL_IDR_N_LP = 20,
|
||||||
|
NAL_CRA_NUT = 21,
|
||||||
|
NAL_VPS = 32,
|
||||||
|
NAL_SPS = 33,
|
||||||
|
NAL_PPS = 34,
|
||||||
|
NAL_AUD = 35,
|
||||||
|
NAL_EOS_NUT = 36,
|
||||||
|
NAL_EOB_NUT = 37,
|
||||||
|
NAL_FD_NUT = 38,
|
||||||
|
NAL_SEI_PREFIX = 39,
|
||||||
|
NAL_SEI_SUFFIX = 40,
|
||||||
|
} NaleType;
|
||||||
|
|
||||||
|
char *data() const override {
|
||||||
|
return (char *) buffer.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t size() const override {
|
||||||
|
return buffer.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t dts() const override {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t prefixSize() const override {
|
||||||
|
return iPrefixSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override {
|
||||||
|
return TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return CodecH265;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return isKeyFrame(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isKeyFrame(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case NAL_BLA_N_LP:
|
||||||
|
case NAL_BLA_W_LP:
|
||||||
|
case NAL_BLA_W_RADL:
|
||||||
|
case NAL_CRA_NUT:
|
||||||
|
case NAL_IDR_N_LP:
|
||||||
|
case NAL_IDR_W_RADL:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint16_t sequence;
|
||||||
|
uint32_t timeStamp;
|
||||||
|
unsigned char type;
|
||||||
|
string buffer;
|
||||||
|
uint32_t iPrefixSize = 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class H265FrameNoCopyAble : public FrameNoCopyAble {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<H265FrameNoCopyAble> Ptr;
|
||||||
|
|
||||||
|
H265FrameNoCopyAble(char *ptr, uint32_t size, uint32_t stamp, int prefixeSize = 4) {
|
||||||
|
buffer_ptr = ptr;
|
||||||
|
buffer_size = size;
|
||||||
|
timeStamp = stamp;
|
||||||
|
iPrefixSize = prefixeSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override {
|
||||||
|
return TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return CodecH265;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
int type = H265_TYPE(((uint8_t *) buffer_ptr)[iPrefixSize]);
|
||||||
|
return H265Frame::isKeyFrame(type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 265视频通道
|
||||||
|
*/
|
||||||
|
class H265Track : public VideoTrack {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<H265Track> Ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不指定sps pps构造h265类型的媒体
|
||||||
|
* 在随后的inputFrame中获取sps pps
|
||||||
|
*/
|
||||||
|
H265Track() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造h265类型的媒体
|
||||||
|
* @param vps vps帧数据
|
||||||
|
* @param sps sps帧数据
|
||||||
|
* @param pps pps帧数据
|
||||||
|
* @param vps_prefix_len 265头长度,可以为3个或4个字节,一般为0x00 00 00 01
|
||||||
|
* @param sps_prefix_len 265头长度,可以为3个或4个字节,一般为0x00 00 00 01
|
||||||
|
* @param pps_prefix_len 265头长度,可以为3个或4个字节,一般为0x00 00 00 01
|
||||||
|
*/
|
||||||
|
H265Track(const string &vps,const string &sps, const string &pps,int vps_prefix_len = 4, int sps_prefix_len = 4, int pps_prefix_len = 4) {
|
||||||
|
_vps = vps.substr(vps_prefix_len);
|
||||||
|
_sps = sps.substr(sps_prefix_len);
|
||||||
|
_pps = pps.substr(pps_prefix_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回不带0x00 00 00 01头的vps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
const string &getVps() const {
|
||||||
|
return _vps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回不带0x00 00 00 01头的sps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
const string &getSps() const {
|
||||||
|
return _sps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回不带0x00 00 00 01头的pps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
const string &getPps() const {
|
||||||
|
return _pps;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return CodecH265;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ready() override {
|
||||||
|
return !_vps.empty() && !_sps.empty() && !_pps.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入数据帧,并获取sps pps
|
||||||
|
* @param frame 数据帧
|
||||||
|
*/
|
||||||
|
void inputFrame(const Frame::Ptr &frame) override {
|
||||||
|
int type = H265_TYPE(((uint8_t *) frame->data() + frame->prefixSize())[0]);
|
||||||
|
if (H265Frame::isKeyFrame(type)) {
|
||||||
|
//关键帧之前插入vps sps pps
|
||||||
|
if(!_vps.empty()){
|
||||||
|
if (!_vpsFrame) {
|
||||||
|
H265Frame::Ptr insertFrame = std::make_shared<H265Frame>();
|
||||||
|
insertFrame->type = H265Frame::NAL_VPS;
|
||||||
|
insertFrame->timeStamp = frame->stamp();
|
||||||
|
insertFrame->buffer.assign("\x0\x0\x0\x1", 4);
|
||||||
|
insertFrame->buffer.append(_sps);
|
||||||
|
insertFrame->iPrefixSize = 4;
|
||||||
|
_vpsFrame = insertFrame;
|
||||||
|
}
|
||||||
|
_vpsFrame->timeStamp = frame->stamp();
|
||||||
|
VideoTrack::inputFrame(_vpsFrame);
|
||||||
|
}
|
||||||
|
if (!_sps.empty()) {
|
||||||
|
if (!_spsFrame) {
|
||||||
|
H265Frame::Ptr insertFrame = std::make_shared<H265Frame>();
|
||||||
|
insertFrame->type = H265Frame::NAL_SPS;
|
||||||
|
insertFrame->timeStamp = frame->stamp();
|
||||||
|
insertFrame->buffer.assign("\x0\x0\x0\x1", 4);
|
||||||
|
insertFrame->buffer.append(_sps);
|
||||||
|
insertFrame->iPrefixSize = 4;
|
||||||
|
_spsFrame = insertFrame;
|
||||||
|
}
|
||||||
|
_spsFrame->timeStamp = frame->stamp();
|
||||||
|
VideoTrack::inputFrame(_spsFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_pps.empty()) {
|
||||||
|
if (!_ppsFrame) {
|
||||||
|
H265Frame::Ptr insertFrame = std::make_shared<H265Frame>();
|
||||||
|
insertFrame->type = H265Frame::NAL_PPS;
|
||||||
|
insertFrame->timeStamp = frame->stamp();
|
||||||
|
insertFrame->buffer.assign("\x0\x0\x0\x1", 4);
|
||||||
|
insertFrame->buffer.append(_pps);
|
||||||
|
insertFrame->iPrefixSize = 4;
|
||||||
|
_ppsFrame = insertFrame;
|
||||||
|
}
|
||||||
|
_ppsFrame->timeStamp = frame->stamp();
|
||||||
|
VideoTrack::inputFrame(_ppsFrame);
|
||||||
|
}
|
||||||
|
VideoTrack::inputFrame(frame);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//非idr帧
|
||||||
|
switch (type) {
|
||||||
|
case H265Frame::NAL_VPS: {
|
||||||
|
//vps
|
||||||
|
_vps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case H265Frame::NAL_SPS: {
|
||||||
|
//sps
|
||||||
|
_sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case H265Frame::NAL_PPS: {
|
||||||
|
//pps
|
||||||
|
_pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
//other frames
|
||||||
|
VideoTrack::inputFrame(frame);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Track::Ptr clone() override {
|
||||||
|
return std::make_shared<std::remove_reference<decltype(*this)>::type>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string _vps;
|
||||||
|
string _sps;
|
||||||
|
string _pps;
|
||||||
|
|
||||||
|
H265Frame::Ptr _vpsFrame;
|
||||||
|
H265Frame::Ptr _spsFrame;
|
||||||
|
H265Frame::Ptr _ppsFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* h265类型sdp
|
||||||
|
*/
|
||||||
|
class H265Sdp : public Sdp {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param sps 265 sps,不带0x00000001头
|
||||||
|
* @param pps 265 pps,不带0x00000001头
|
||||||
|
* @param playload_type rtp playload type 默认96
|
||||||
|
* @param bitrate 比特率
|
||||||
|
*/
|
||||||
|
H265Sdp(const string &strVPS,
|
||||||
|
const string &strSPS,
|
||||||
|
const string &strPPS,
|
||||||
|
int playload_type = 96,
|
||||||
|
int bitrate = 4000) : Sdp(90000,playload_type) {
|
||||||
|
//视频通道
|
||||||
|
_printer << "m=video 0 RTP/AVP " << playload_type << "\r\n";
|
||||||
|
_printer << "b=AS:" << bitrate << "\r\n";
|
||||||
|
_printer << "a=rtpmap:" << playload_type << " H265/" << 90000 << "\r\n";
|
||||||
|
_printer << "a=fmtp:" << playload_type << " ";
|
||||||
|
_printer << "sprop-vps=";
|
||||||
|
_printer << encodeBase64(strVPS) << "; ";
|
||||||
|
_printer << "sprop-sps=";
|
||||||
|
_printer << encodeBase64(strSPS) << "; ";
|
||||||
|
_printer << "sprop-pps=";
|
||||||
|
_printer << encodeBase64(strPPS) << "\r\n";
|
||||||
|
_printer << "a=control:trackID=" << getTrackType() << "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
string getSdp() const override {
|
||||||
|
return _printer;
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackType getTrackType() const override {
|
||||||
|
return TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return CodecH265;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
_StrPrinter _printer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_H265_H
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_TRACK_H
|
||||||
|
#define ZLMEDIAKIT_TRACK_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include "Frame.h"
|
||||||
|
#include "Util/RingBuffer.h"
|
||||||
|
#include "Rtsp/Rtsp.h"
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
|
namespace mediakit{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 媒体通道描述类,也支持帧输入输出
|
||||||
|
*/
|
||||||
|
class Track : public FrameRingInterfaceDelegate , public CodecInfo{
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<Track> Ptr;
|
||||||
|
Track(){}
|
||||||
|
|
||||||
|
virtual ~Track(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否准备好,准备好才能获取譬如sps pps等信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual bool ready() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 克隆接口,用于复制本对象用
|
||||||
|
* 在调用该接口时只会复制派生类的信息
|
||||||
|
* 环形缓存和代理关系不能拷贝,否则会关系紊乱
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual Track::Ptr clone() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制拷贝,只能拷贝派生类的信息,
|
||||||
|
* 环形缓存和代理关系不能拷贝,否则会关系紊乱
|
||||||
|
* @param that
|
||||||
|
*/
|
||||||
|
Track(const Track &that){}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频通道描述Track类,支持获取宽高fps信息
|
||||||
|
*/
|
||||||
|
class VideoTrack : public Track {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<VideoTrack> Ptr;
|
||||||
|
|
||||||
|
TrackType getTrackType() const override { return TrackVideo;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回视频高度
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual int getVideoHeight() const {return 0;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回视频宽度
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual int getVideoWidth() const {return 0;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回视频fps
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual float getVideoFps() const {return 0;};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音频Track派生类,支持采样率通道数,采用位数信息
|
||||||
|
*/
|
||||||
|
class AudioTrack : public Track {
|
||||||
|
public:
|
||||||
|
typedef std::shared_ptr<AudioTrack> Ptr;
|
||||||
|
|
||||||
|
TrackType getTrackType() const override { return TrackAudio;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回音频采样率
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual int getAudioSampleRate() const {return 0;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回音频采样位数,一般为16或8
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual int getAudioSampleBit() const {return 0;};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回音频通道数
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual int getAudioChannel() const {return 0;};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}//namespace mediakit
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_TRACK_H
|
||||||
|
|
@ -1,15 +1,33 @@
|
||||||
//
|
/*
|
||||||
// H264Parser.cpp
|
* MIT License
|
||||||
// MediaPlayer
|
*
|
||||||
//
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
// Created by xzl on 2017/1/16.
|
*
|
||||||
// Copyright © 2017年 jizan. All rights reserved.
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
//
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "H264Parser.h"
|
#include "H264Parser.h"
|
||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
|
using namespace toolkit;
|
||||||
|
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
H264Parser::H264Parser(){
|
H264Parser::H264Parser(){
|
||||||
|
|
||||||
|
|
@ -19,19 +37,19 @@ H264Parser::~H264Parser(){
|
||||||
}
|
}
|
||||||
void H264Parser::inputH264(const string &h264,uint32_t dts){
|
void H264Parser::inputH264(const string &h264,uint32_t dts){
|
||||||
|
|
||||||
m_parser.SetStream((const uint8_t *)h264.data(), h264.size());
|
_parser.SetStream((const uint8_t *)h264.data(), h264.size());
|
||||||
while (true) {
|
while (true) {
|
||||||
if(media::H264Parser::kOk != m_parser.AdvanceToNextNALU(&m_nalu)){
|
if(media::H264Parser::kOk != _parser.AdvanceToNextNALU(&_nalu)){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_nalu.nal_unit_type) {
|
switch (_nalu.nal_unit_type) {
|
||||||
case media::H264NALU::kNonIDRSlice:
|
case media::H264NALU::kNonIDRSlice:
|
||||||
case media::H264NALU::kIDRSlice:{
|
case media::H264NALU::kIDRSlice:{
|
||||||
if(media::H264Parser::kOk == m_parser.ParseSliceHeader(m_nalu, &m_shdr)){
|
if(media::H264Parser::kOk == _parser.ParseSliceHeader(_nalu, &_shdr)){
|
||||||
const media::H264SPS *pPps = m_parser.GetSPS(m_shdr.pic_parameter_set_id);
|
const media::H264SPS *pPps = _parser.GetSPS(_shdr.pic_parameter_set_id);
|
||||||
if (pPps) {
|
if (pPps) {
|
||||||
m_poc.ComputePicOrderCnt(pPps, m_shdr, &m_iNowPOC);
|
_poc.ComputePicOrderCnt(pPps, _shdr, &_iNowPOC);
|
||||||
computePts(dts);
|
computePts(dts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -39,12 +57,12 @@ void H264Parser::inputH264(const string &h264,uint32_t dts){
|
||||||
break;
|
break;
|
||||||
case media::H264NALU::kSPS:{
|
case media::H264NALU::kSPS:{
|
||||||
int sps_id;
|
int sps_id;
|
||||||
m_parser.ParseSPS(&sps_id);
|
_parser.ParseSPS(&sps_id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case media::H264NALU::kPPS:{
|
case media::H264NALU::kPPS:{
|
||||||
int pps_id;
|
int pps_id;
|
||||||
m_parser.ParsePPS(&pps_id);
|
_parser.ParsePPS(&pps_id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -54,33 +72,33 @@ void H264Parser::inputH264(const string &h264,uint32_t dts){
|
||||||
}
|
}
|
||||||
|
|
||||||
void H264Parser::computePts(uint32_t iNowDTS) {
|
void H264Parser::computePts(uint32_t iNowDTS) {
|
||||||
auto iPOCInc = m_iNowPOC - m_iLastPOC;
|
auto iPOCInc = _iNowPOC - _iLastPOC;
|
||||||
if (m_shdr.slice_type % 5 == 1) {
|
if (_shdr.slice_type % 5 == 1) {
|
||||||
//这是B帧
|
//这是B帧
|
||||||
m_iNowPTS = m_iLastPTS + m_iMsPerPOC * (iPOCInc);
|
_iNowPTS = _iLastPTS + _iMsPerPOC * (iPOCInc);
|
||||||
} else {
|
} else {
|
||||||
//这是I帧或者P帧
|
//这是I帧或者P帧
|
||||||
m_iNowPTS = iNowDTS;
|
_iNowPTS = iNowDTS;
|
||||||
//计算每一POC的时间
|
//计算每一POC的时间
|
||||||
if(iPOCInc == 0){
|
if(iPOCInc == 0){
|
||||||
WarnL << "iPOCInc = 0," << m_iNowPOC << " " << m_iLastPOC;
|
WarnL << "iPOCInc = 0," << _iNowPOC << " " << _iLastPOC;
|
||||||
}else{
|
}else{
|
||||||
m_iMsPerPOC = (m_iNowPTS - m_iLastPTS) / iPOCInc;
|
_iMsPerPOC = (_iNowPTS - _iLastPTS) / iPOCInc;
|
||||||
}
|
}
|
||||||
m_iLastPTS = m_iNowPTS;
|
_iLastPTS = _iNowPTS;
|
||||||
m_iLastPOC = m_iNowPOC;
|
_iLastPOC = _iNowPOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// DebugL << m_shdr.slice_type
|
// DebugL << _shdr.slice_type
|
||||||
// <<"\r\nNOW:"
|
// <<"\r\nNOW:"
|
||||||
// << m_iNowPOC << " "
|
// << _iNowPOC << " "
|
||||||
// << m_iNowPTS << " "
|
// << _iNowPTS << " "
|
||||||
// << iNowDTS << " "
|
// << iNowDTS << " "
|
||||||
// << "\r\nLST:"
|
// << "\r\nLST:"
|
||||||
// << m_iLastPOC << " "
|
// << _iLastPOC << " "
|
||||||
// << m_iLastPTS << " "
|
// << _iLastPTS << " "
|
||||||
// << m_iMsPerPOC << endl;
|
// << _iMsPerPOC << endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,28 @@
|
||||||
//
|
/*
|
||||||
// H264Parser.h
|
* MIT License
|
||||||
// MediaPlayer
|
*
|
||||||
//
|
* Copyright (c) 2016 xiongziliang <771730766@qq.com>
|
||||||
// Created by xzl on 2017/1/16.
|
*
|
||||||
// Copyright © 2017年 jizan. All rights reserved.
|
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
|
||||||
//
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef H264Parser_h
|
#ifndef H264Parser_h
|
||||||
#define H264Parser_h
|
#define H264Parser_h
|
||||||
|
|
@ -26,29 +44,29 @@ public:
|
||||||
void inputH264(const string &h264,uint32_t dts);
|
void inputH264(const string &h264,uint32_t dts);
|
||||||
|
|
||||||
int32_t getPOC() const{
|
int32_t getPOC() const{
|
||||||
return m_iNowPOC;
|
return _iNowPOC;
|
||||||
}
|
}
|
||||||
int getSliceType() const{
|
int getSliceType() const{
|
||||||
return m_shdr.slice_type;
|
return _shdr.slice_type;
|
||||||
}
|
}
|
||||||
int getNaluType() const{
|
int getNaluType() const{
|
||||||
return m_nalu.nal_unit_type;
|
return _nalu.nal_unit_type;
|
||||||
}
|
}
|
||||||
uint32_t getPts() const{
|
uint32_t getPts() const{
|
||||||
return m_iNowPTS;
|
return _iNowPTS;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
media::H264Parser m_parser;
|
media::H264Parser _parser;
|
||||||
media::H264POC m_poc;
|
media::H264POC _poc;
|
||||||
media::H264NALU m_nalu;
|
media::H264NALU _nalu;
|
||||||
media::H264SliceHeader m_shdr;
|
media::H264SliceHeader _shdr;
|
||||||
|
|
||||||
int32_t m_iNowPOC = INT32_MAX;
|
int32_t _iNowPOC = INT32_MAX;
|
||||||
int32_t m_iLastPOC = INT32_MAX;
|
int32_t _iLastPOC = INT32_MAX;
|
||||||
|
|
||||||
uint32_t m_iNowPTS = INT32_MAX;
|
uint32_t _iNowPTS = INT32_MAX;
|
||||||
uint32_t m_iLastPTS = INT32_MAX;
|
uint32_t _iLastPTS = INT32_MAX;
|
||||||
int32_t m_iMsPerPOC = 30;
|
int32_t _iMsPerPOC = 30;
|
||||||
|
|
||||||
void computePts(uint32_t dts);
|
void computePts(uint32_t dts);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h> /* for uint32_t, etc */
|
#include <stdint.h> /* for uint32_t, etc */
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "SPSParser.h"
|
#include "SPSParser.h"
|
||||||
|
|
||||||
/********************************************
|
/********************************************
|
||||||
|
|
@ -21,8 +19,9 @@
|
||||||
#define MIN_LOG2_MAX_FRAME_NUM 4
|
#define MIN_LOG2_MAX_FRAME_NUM 4
|
||||||
#define H264_MAX_PICTURE_COUNT 36
|
#define H264_MAX_PICTURE_COUNT 36
|
||||||
#define CODEC_FLAG2_IGNORE_CROP 0x00010000 ///< Discard cropping information from SPS.
|
#define CODEC_FLAG2_IGNORE_CROP 0x00010000 ///< Discard cropping information from SPS.
|
||||||
|
#ifndef INT_MAX
|
||||||
#define INT_MAX 65535
|
#define INT_MAX 65535
|
||||||
|
#endif //INT_MAX
|
||||||
|
|
||||||
/* report level */
|
/* report level */
|
||||||
#define RPT_ERR (1) // error, system error
|
#define RPT_ERR (1) // error, system error
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
/***************************************************************************************
|
#ifndef _SPSPARSER_H_
|
||||||
***************************************************************************************/
|
#define _SPSPARSER_H_
|
||||||
#ifndef _JZAN_SPS_PPS_H_
|
|
||||||
#define _JZAN_SPS_PPS_H_
|
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -189,4 +187,4 @@ void h264GeFramerate(T_SPS *ptSps, float *pfFramerate);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif //_SPS_PPS_H_
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -7,8 +7,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
using namespace ZL::Util;
|
using namespace toolkit;
|
||||||
|
|
||||||
|
|
||||||
template <class ForwardIterator>
|
template <class ForwardIterator>
|
||||||
void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
|
void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
|
||||||
|
|
@ -173,7 +172,7 @@ return kInvalidStream; \
|
||||||
start += subsamples[i].clear_bytes;
|
start += subsamples[i].clear_bytes;
|
||||||
|
|
||||||
const uint8_t* end =
|
const uint8_t* end =
|
||||||
std::min(start + subsamples[i].cypher_bytes, stream_end);
|
min(start + subsamples[i].cypher_bytes, stream_end);
|
||||||
encrypted_ranges_.Add(start, end);
|
encrypted_ranges_.Add(start, end);
|
||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +310,7 @@ return kInvalidStream; \
|
||||||
// The start code is inside an encrypted section so we need to scan
|
// The start code is inside an encrypted section so we need to scan
|
||||||
// for another start code.
|
// for another start code.
|
||||||
*start_code_size = 0;
|
*start_code_size = 0;
|
||||||
start += std::min(*offset + 1, bytes_left);
|
start += min(*offset + 1, bytes_left);
|
||||||
}
|
}
|
||||||
} while (*start_code_size == 0);
|
} while (*start_code_size == 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -8,8 +8,7 @@
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "h264_parser.h"
|
#include "h264_parser.h"
|
||||||
#include "h264_poc.h"
|
#include "h264_poc.h"
|
||||||
|
using namespace toolkit;
|
||||||
using namespace ZL::Util;
|
|
||||||
|
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
|
|
@ -113,7 +112,7 @@ namespace media {
|
||||||
// (assuming no interlacing).
|
// (assuming no interlacing).
|
||||||
int32_t top_foc = pic_order_cnt_msb + slice_hdr.pic_order_cnt_lsb;
|
int32_t top_foc = pic_order_cnt_msb + slice_hdr.pic_order_cnt_lsb;
|
||||||
int32_t bottom_foc = top_foc + slice_hdr.delta_pic_order_cnt_bottom;
|
int32_t bottom_foc = top_foc + slice_hdr.delta_pic_order_cnt_bottom;
|
||||||
*pic_order_cnt = std::min(top_foc, bottom_foc);
|
*pic_order_cnt = min(top_foc, bottom_foc);
|
||||||
|
|
||||||
// Store state.
|
// Store state.
|
||||||
prev_frame_num_ = slice_hdr.frame_num;
|
prev_frame_num_ = slice_hdr.frame_num;
|
||||||
|
|
@ -182,7 +181,7 @@ namespace media {
|
||||||
int32_t top_foc = expected_pic_order_cnt + slice_hdr.delta_pic_order_cnt0;
|
int32_t top_foc = expected_pic_order_cnt + slice_hdr.delta_pic_order_cnt0;
|
||||||
int32_t bottom_foc = top_foc + sps->offset_for_top_to_bottom_field +
|
int32_t bottom_foc = top_foc + sps->offset_for_top_to_bottom_field +
|
||||||
slice_hdr.delta_pic_order_cnt1;
|
slice_hdr.delta_pic_order_cnt1;
|
||||||
*pic_order_cnt = std::min(top_foc, bottom_foc);
|
*pic_order_cnt = min(top_foc, bottom_foc);
|
||||||
|
|
||||||
// Store state.
|
// Store state.
|
||||||
prev_frame_num_ = slice_hdr.frame_num;
|
prev_frame_num_ = slice_hdr.frame_num;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ static type& name = *new type arguments
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
using namespace ZL::Util;
|
using namespace toolkit;
|
||||||
|
|
||||||
#define DCHECK(x) if(!(x)) { ErrorL << "DCHECK " << #x <<endl; }
|
#define DCHECK(x) if(!(x)) { ErrorL << "DCHECK " << #x <<endl; }
|
||||||
#define DCHECK_GT(x,y) if(!((x) > (y))) { ErrorL << "DCHECK_GT:" << #x << #y << endl; }
|
#define DCHECK_GT(x,y) if(!((x) > (y))) { ErrorL << "DCHECK_GT:" << #x << #y << endl; }
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
//
|
|
||||||
// ranges.cpp
|
|
||||||
// MediaPlayer
|
|
||||||
//
|
|
||||||
// Created by xzl on 2017/1/13.
|
|
||||||
// Copyright © 2017年 jizan. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "ranges.h"
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ namespace media {
|
||||||
// original loop went too far.
|
// original loop went too far.
|
||||||
while ((i + 1) < ranges_.size() &&
|
while ((i + 1) < ranges_.size() &&
|
||||||
ranges_[i + 1].first <= ranges_[i].second) {
|
ranges_[i + 1].first <= ranges_[i].second) {
|
||||||
ranges_[i].second = std::max(ranges_[i].second, ranges_[i + 1].second);
|
ranges_[i].second = max(ranges_[i].second, ranges_[i + 1].second);
|
||||||
ranges_.erase(ranges_.begin() + i + 1);
|
ranges_.erase(ranges_.begin() + i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,8 +133,8 @@ namespace media {
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
|
|
||||||
while (i < size() && j < other.size()) {
|
while (i < size() && j < other.size()) {
|
||||||
T max_start = std::max(start(i), other.start(j));
|
T max_start = max(start(i), other.start(j));
|
||||||
T min_end = std::min(end(i), other.end(j));
|
T min_end = min(end(i), other.end(j));
|
||||||
|
|
||||||
// Add an intersection range to the result if the ranges overlap.
|
// Add an intersection range to the result if the ranges overlap.
|
||||||
if (max_start < min_end)
|
if (max_start < min_end)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue