Merge pull request #1 from xiongziliang/master

Able to merge
This commit is contained in:
haopeng 2018-12-17 14:47:03 +08:00 committed by GitHub
commit 925d397ea4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
241 changed files with 22429 additions and 8471 deletions

BIN
.DS_Store vendored

Binary file not shown.

437
.cproject
View File

@ -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="&quot;${workspace_loc:/${ProjName}/src}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/extra/x264/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/extra/faac-1.28/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;E:\ServiceCenter\ZLToolKit\src&quot;"/>
</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="&quot;E:\ServiceCenter\ZLToolKit\WIN32&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/extra/x264/lib}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/extra/faac-1.28/lib}&quot;"/>
</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>

13
.gitignore vendored
View File

@ -10,8 +10,8 @@
*.pch
# Compiled Dynamic libraries
*.dylib
*.dll
#*.dylib
#*.dll
# Fortran module files
*.mod
@ -23,7 +23,14 @@
*.lib
# Executables
*.exe
#*.exe
*.out
*.app
/X64/
*.DS_Store
/cmake-build-debug/
/.idea/
/c_wrapper/.idea/

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "ZLToolKit"]
path = ZLToolKit
url = https://github.com/xiongziliang/ZLToolKit.git

View File

@ -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>

View File

@ -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 &quot;${INPUTS}&quot;" 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 &quot;${INPUTS}&quot;" 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 &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>

View File

@ -2,7 +2,7 @@ language: cpp
sudo: required
dist: trusty
compiler:
- gcc
- clang
os:
- linux
script:

View File

@ -1,5 +1,7 @@
project(ZLMediaKit)
cmake_minimum_required(VERSION 2.8)
project(ZLMediaKit)
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")
@ -7,114 +9,91 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
#
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})
#
aux_source_directory(src/${SUB_DIR} SRC_LIST)
#
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(ToolKit_Root ${CMAKE_SOURCE_DIR}/ZLToolKit/src)
set(MediaKit_Root ${CMAKE_SOURCE_DIR}/src)
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.hWinsock.h
add_definitions(-DWIN32_LEAN_AND_MEAN -DMP4V2_NO_STDINT_DEFS)
endif ()
#
set(LINK_LIB_LIST zlmediakit zltoolkit)
#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(OPENSSL_FOUND)
if (OPENSSL_FOUND)
message(STATUS "found openssl library\"${OPENSSL_INCLUDE_DIR}\",ENABLE_OPENSSL enabled")
include_directories(${OPENSSL_INCLUDE_DIR})
add_definitions(-DENABLE_OPENSSL)
list(APPEND LINK_LIB_LIST ${OPENSSL_LIBRARIES})
endif (OPENSSL_FOUND)
#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(MYSQL_FOUND)
if (MYSQL_FOUND)
message(STATUS "found mysqlclient library\"${MYSQL_INCLUDE_DIR}\",ENABLE_MYSQL enabled")
include_directories(${MYSQL_INCLUDE_DIR})
add_definitions(-DENABLE_MYSQL)
list(APPEND LINK_LIB_LIST ${MYSQL_LIBRARIES})
endif (MYSQL_FOUND)
#mp4v2
#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(MP4V2_FOUND)
if (MP4V2_FOUND)
include_directories(${MP4V2_INCLUDE_DIR})
list(APPEND LINK_LIB_LIST ${MP4V2_LIBRARY})
add_definitions(-DENABLE_MP4V2)
message(STATUS "found MP4V2:${MP4V2_INCLUDE_DIR},${MP4V2_LIBRARY}")
endif (MP4V2_FOUND)
#x264
find_package(X264 QUIET)
if(X264_FOUND)
message(STATUS "找到x264库:\"${X264_INCLUDE_DIR}\",ENABLE_X264宏已打开")
include_directories(${X264_INCLUDE_DIRS})
add_definitions(-DENABLE_X264)
list(APPEND LINK_LIB_LIST ${X264_LIBRARIES})
endif(X264_FOUND)
if (X264_FOUND)
message(STATUS "found x264 library\"${X264_INCLUDE_DIRS}\",ENABLE_X264 enabled")
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(FAAC_FOUND)
if (FAAC_FOUND)
message(STATUS "found faac library\"${FAAC_INCLUDE_DIR}\",ENABLE_FAAC enabled")
include_directories(${FAAC_INCLUDE_DIR})
add_definitions(-DENABLE_FAAC)
list(APPEND LINK_LIB_LIST ${FAAC_LIBRARIES})
endif ()
#ZLToolKit
find_package(ZLTOOLKIT QUIET)
if(ZLTOOLKIT_FOUND)
message(STATUS "找到ZLToolKit库:\"${ZLTOOLKIT_INCLUDE_DIR}\"")
include_directories(${ZLTOOLKIT_INCLUDE_DIR}/ZLToolKit)
list(APPEND LINK_LIB_LIST ${ZLTOOLKIT_LIBRARIES})
endif(ZLTOOLKIT_FOUND)
#使GOP
add_definitions(-DENABLE_RING_USEBUF)
#
add_library(zltoolkit STATIC ${ToolKit_src_list})
add_library(zlmediakit STATIC ${MediaKit_src_list})
#
message(STATUS "将链接依赖库:${LINK_LIB_LIST}")
#RTSP/RTMP,HLS
add_definitions(-DENABLE_RTMP2RTSP -DENABLE_RTSP2RTMP -DENABLE_HLS)
if (WIN32)
list(APPEND LINK_LIB_LIST WS2_32 Iphlpapi shlwapi)
elseif(NOT ANDROID OR IOS)
list(APPEND LINK_LIB_LIST pthread)
endif ()
#
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)
message(STATUS "linked libraries:${LINK_LIB_LIST}")
#
if(NOT IOS)
add_subdirectory(tests)
else(NOT IOS)
include_directories(${PROJECT_SOURCE_DIR}/../ZLToolKit/src)
endif(NOT IOS)

View File

@ -1,6 +1,6 @@
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
of this software and associated documentation files (the "Software"), to deal

190
README.md
View File

@ -1,47 +1,70 @@
# 一个基于C++11简单易用的轻量级流媒体库
平台|编译状态
----|-------
Linux | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit)
macOS | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_mac.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_mac)
iOS | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit-build_for_ios.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit-build_for_ios)
Android | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_android.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit_build_for_android)
# 一个基于C++11的高性能运营级流媒体服务框架
[![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit)
## 项目特点
- 基于C++11开发避免使用裸指针代码稳定可靠同时跨平台移植简单方便代码清晰简洁。
- 打包多种流媒体协议(RTSP/RTMP/HLS支持协议间的互相转换提供一站式的服务。
- 使用epoll+线程池+异步网络IO模式开发并发性能优越。
- 只实现主流的的H264+AAC流媒体方案代码精简,脉络清晰,适合学习。
- 已实现主流的的H264+AAC流媒体方案代码精简,脉络清晰,适合学习。
- 编码格式与框架代码解耦,方便自由简洁的添加支持其他编码格式
- 代码经过大量的稳定性、性能测试,可满足商用服务器项目。
- 支持linux、macos、ios、android、windows平台
## 项目定位
- 移动嵌入式跨平台流媒体解决方案。
- 商用级流媒体服务器。
- 网络编程二次开发SDK。
## 功能清单
- RTSP
- RTSP 服务器支持RTMP/MP4转RTSP。
- RTSP 播放器支持RTSP代理。
- RTSP 播放器支持RTSP代理,支持生成静音音频
- 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播` 四种RTP传输方式 。
- 服务器/客户端完整支持Basic/Digest方式的登录鉴权全异步可配置化的鉴权接口。
- 支持H265编码
- RTMP
- RTMP 播放服务器支持RTSP/MP4转RTMP。
- RTMP 发布服务器,支持录制发布流。
- RTMP 播放器支持RTMP代理
- RTMP 播放器支持RTMP代理,支持生成静音音频
- RTMP 推流客户端。
- 支持http-flv直播。
- 支持https-flv直播。
- HLS
- 支持HLS文件生成自带HTTP文件服务器。
- HTTP[S]
- 服务器支持`目录索引生成`,`文件下载`,`表单提交请求`。
- 客户端提供`文件下载器(支持断点续传)`,`接口请求器`。
- 客户端提供`文件下载器(支持断点续传)`,`接口请求器`,`文件上传器`。
- 完整HTTP API服务器可以作为web后台开发框架。
- 支持跨域访问。
- 客户端支持cookie
- 支持WebSocket服务器
- 其他
- 支持输入YUV+PCM自动生成RTSP/RTMP/HLS/MP4.
- 支持简单的telnet调试。
- 支持H264的解析支持B帧的POC计算排序。
- 支持配置文件热加载
- 支持流量统计、推流播放鉴权等事件
- 支持rtsp/rtmp/http虚拟主机
- 支持flv、mp4文件录制
- 支持rtps/rtmp点播支持seek
## 后续任务
- 提供更多的示例代码
- 完善支持H265
- 添加rtsp推流功能
## 编译要求
- 编译器支持C++11GCC4.8/Clang3.3/VC2015或以上
- cmake3.2或以上
## 编译(Linux)
- 我的编译环境
- Ubuntu16.04 64 bit + gcc5.4(最低gcc4.7)
- Ubuntu16.04 64 bit + gcc5.4
- cmake 3.5.1
- 编译
@ -93,39 +116,63 @@ Android | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit_build_f
export ANDROID_NDK_ROOT=/path/to/ndk
./build_for_android.sh
```
## 编译(Windows)
- 我的编译环境
- 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<RtmpSession>::Ptr rtmpSrv(new TcpServer<RtmpSession>());
TcpServer<HttpSession>::Ptr httpSrv(new TcpServer<HttpSession>());
TcpServer<HttpsSession>::Ptr httpsSrv(new TcpServer<HttpsSession>());
TcpServer::Ptr rtspSrv(new TcpServer());
TcpServer::Ptr rtmpSrv(new TcpServer());
TcpServer::Ptr httpSrv(new TcpServer());
TcpServer::Ptr httpsSrv(new TcpServer());
rtspSrv->start(mINI::Instance()[Config::Rtsp::kPort]);
rtmpSrv->start(mINI::Instance()[Config::Rtmp::kPort]);
httpSrv->start(mINI::Instance()[Config::Http::kPort]);
httpsSrv->start(mINI::Instance()[Config::Http::kSSLPort]);
rtspSrv->start<RtspSession>(mINI::Instance()[Config::Rtsp::kPort]);
rtmpSrv->start<RtmpSession>(mINI::Instance()[Config::Rtmp::kPort]);
httpSrv->start<HttpSession>(mINI::Instance()[Config::Http::kPort]);
httpsSrv->start<HttpsSession>(mINI::Instance()[Config::Http::kSSLPort]);
EventPoller::Instance().runLoop();
```
- 作为播放器:
```
MediaPlayer::Ptr player(new MediaPlayer());
player->setOnPlayResult([](const SockException &ex) {
InfoL << "OnPlayResult:" << ex.what();
});
player->setOnShutdown([](const SockException &ex) {
ErrorL << "OnShutdown:" << ex.what();
});
player->setOnVideoCB([&](const H264Frame &frame){
//在这里解码H264并显示
});
player->setOnAudioCB([&](const AdtsFrame &frame){
//在这里解码AAC并播放
});
//支持rtmp、rtsp
player->play("rtsp://192.168.0.122/","admin","123456",PlayerBase::RTP_TCP);
EventPoller::Instance().runLoop();
MediaPlayer::Ptr player(new MediaPlayer());
weak_ptr<MediaPlayer> weakPlayer = player;
player->setOnPlayResult([weakPlayer](const SockException &ex) {
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) {
ErrorL << "OnShutdown:" << ex.what();
});
//支持rtmp、rtsp
(*player)[RtspPlayer::kRtpType] = PlayerBase::RTP_TCP;
player->play("rtsp://admin:jzan123456@192.168.0.122/");
```
- 作为代理服务器:
```
@ -173,41 +220,11 @@ Android | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit_build_f
EventPoller::Instance().runLoop();
```
## 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宏具体操作如下
```
#编译ZLToolKit
cd ZLToolKit
mkdir -p build
cd build -DENABLE_ASNC_TCP_CLIENT
cmake ..
make -j4
sudo make install
```
ZLMediaKit提供了测试性能的示例代码在tests/test_benchmark.cpp。
这里是测试报告:[benchmark.md](https://github.com/xiongziliang/ZLMediaKit/blob/master/benchmark.md)
- github下载太慢了有其他下载方式吗
@ -218,7 +235,34 @@ Android | [![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit_build_f
[ZLMediaKit](http://git.oschina.net/xiahcu/ZLMediaKit)
## 联系方式
- 邮箱:<771730766@qq.com>
- QQ群542509000
- 在windows下编译很多错误
由于本项目主体代码在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)

1
ZLToolKit Submodule

@ -0,0 +1 @@
Subproject commit 666eb9ba01939f739bf145abc5f02539ca2b9c97

1
_config.yml Normal file
View File

@ -0,0 +1 @@
theme: jekyll-theme-cayman

37
benchmark.md Normal file
View File

@ -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 | 无 |

View File

@ -1,14 +1,13 @@
#!/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 ..
git clone --depth=50 https://github.com/xiongziliang/ZLMediaKit.git
git clone --depth=1 https://github.com/xiongziliang/ZLMediaKit.git
cd ZLMediaKit
git submodule init
git submodule update
mkdir -p android_build
rm -rf ./build
ln -s ./android_build 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
make -j4
sudo make install

View File

@ -1,14 +1,13 @@
#!/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 ..
git clone --depth=50 https://github.com/xiongziliang/ZLMediaKit.git
git clone --depth=1 https://github.com/xiongziliang/ZLMediaKit.git
cd ZLMediaKit
git submodule init
git submodule update
mkdir -p ios_build
rm -rf ./build
ln -s ./ios_build build
cd ios_build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/iOS.cmake -DIOS_PLATFORM=OS
make -j4
sudo make install

View File

@ -1,20 +1,24 @@
#!/bin/bash
path=`pwd`
wget https://raw.githubusercontent.com/xiongziliang/ZLToolKit/master/build_for_linux.sh -O ./toolkit_build.sh
sudo chmod +x ./toolkit_build.sh
./toolkit_build.sh
cd ..
git clone --depth=1 https://github.com/xiongziliang/ZLMediaKit.git
cd ZLMediaKit
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 libfaac-dev
sudo apt-get install libmp4v2-dev
#sudo apt-get install libsdl-dev
#sudo apt-get install libavcodec-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
rm -rf ./build
ln -s ./linux_build build
cd linux_build
cmake ..
make -j4
sudo make install

View File

@ -1,19 +1,22 @@
#!/bin/bash
path=`pwd`
wget https://raw.githubusercontent.com/xiongziliang/ZLToolKit/master/build_for_mac.sh -O toolkit_build.sh
sudo chmod +x ./toolkit_build.sh
./toolkit_build.sh
cd ..
git clone --depth=1 https://github.com/xiongziliang/ZLMediaKit.git
cd ZLMediaKit
git submodule init
git submodule update
brew install cmake
brew install mysql
brew install openssl
brew install x264
brew install faac
brew install mp4v2
brew install sdl
brew install ffmpeg
cd $path
cd ..
git clone --depth=50 https://github.com/xiongziliang/ZLMediaKit.git
cd ZLMediaKit
mkdir -p mac_build
rm -rf ./build
ln -s ./mac_build build
cd mac_build
cmake .. -DOPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2j/
make -j4
sudo make install

1
c_wrapper/.idea/.name Normal file
View File

@ -0,0 +1 @@
MediaKitWrapper

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

4
c_wrapper/.idea/misc.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

View File

@ -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>

View File

@ -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>

124
c_wrapper/CMakeLists.txt Executable file
View File

@ -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.hWinsock.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)

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

130
c_wrapper/cmake/FindMYSQL.cmake Executable file
View File

@ -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)

15
c_wrapper/cmake/FindSDL2.cmake Executable file
View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

209
c_wrapper/cmake/iOS.cmake Executable file
View File

@ -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)

70
c_wrapper/src/cleaner.h Executable file
View File

@ -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_ */

154
c_wrapper/src/common.cpp Executable file
View File

@ -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);
}

123
c_wrapper/src/common.h Executable file
View File

@ -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监听端口800
* :0:,0:
*/
API_EXPORT unsigned short API_CALL initHttpServer(unsigned short port);
/*
* :RTSP服务器
* :port:rtsp监听端口5540
* :0:,0:
*/
API_EXPORT unsigned short API_CALL initRtspServer(unsigned short port);
/*
* :RTMP服务器
* :port:rtmp监听端口19350
* :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:,functionlinefmt
* :
*/
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_ */

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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);
}

50
c_wrapper/src/httpdownloader.h Executable file
View File

@ -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_ */

105
c_wrapper/src/media.cpp Executable file
View File

@ -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);
}

103
c_wrapper/src/media.h Executable file
View File

@ -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:hlsbEnableMp4: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编码profileadts头时用于生产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音频(2aac配置)
* :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_ */

38
c_wrapper/src/mediakit.h Executable file
View File

@ -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_ */

345
c_wrapper/src/player.cpp Executable file
View File

@ -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);
}

235
c_wrapper/src/player.h Executable file
View File

@ -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帧前为SPSPPS帧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);
/*
* :12
* :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:
* :10
*/
API_EXPORT int API_CALL player_containAudio(PlayerContext ctx);
/*
* :
* :ctx:
* :10
*/
API_EXPORT int API_CALL player_containVideo(PlayerContext ctx);
/*
* :
* :ctx:
* :10
*/
API_EXPORT int API_CALL player_isInited(PlayerContext ctx);
/*
* :0
* :ctx:
* :
*/
API_EXPORT float API_CALL player_getDuration(PlayerContext ctx);
/*
* :
* :ctx:
* : 0.01.0
*/
API_EXPORT float API_CALL player_getProgress(PlayerContext ctx);
/*
* :
* :ctx:fProgress 0.01.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_ */

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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})

View File

@ -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;
}

16
cmake/FindJEMALLOC.cmake Normal file
View File

@ -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)

View File

@ -17,7 +17,7 @@
include(CheckCXXSourceCompiles)
if(WIN32)
find_path(MYSQL_INCLUDE_DIR mysql/mysql.h
find_path(MYSQL_INCLUDE_DIR mysql.h
PATHS
$ENV{MYSQL_INCLUDE_DIR}
$ENV{MYSQL_DIR}/include
@ -64,6 +64,7 @@ if(WIN32)
$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
)

15
cmake/FindSDL2.cmake Normal file
View File

@ -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)

View File

@ -1,8 +1,14 @@
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
NAMES ZLToolKit)
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})

BIN
src/.DS_Store vendored

Binary file not shown.

View File

@ -1,9 +1,29 @@
/*
* AACEncoder.cpp
/*
* MIT License
*
* Created on: 2016811
* Author: xzl
* 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.
*/
#ifdef ENABLE_FAAC
#include <cstdlib>
@ -18,27 +38,26 @@ extern "C" {
}
#endif
using namespace ZL::Util;
using namespace toolkit;
namespace ZL {
namespace Codec {
namespace mediakit {
AACEncoder::AACEncoder() {
}
AACEncoder::~AACEncoder() {
if (m_hEncoder != nullptr) {
faacEncClose(m_hEncoder);
m_hEncoder = nullptr;
if (_hEncoder != nullptr) {
faacEncClose(_hEncoder);
_hEncoder = nullptr;
}
if (m_pucAacBuf != nullptr) {
delete[] m_pucAacBuf;
m_pucAacBuf = nullptr;
if (_pucAacBuf != nullptr) {
delete[] _pucAacBuf;
_pucAacBuf = nullptr;
}
if (m_pucPcmBuf != nullptr) {
delete[] m_pucPcmBuf;
m_pucPcmBuf = nullptr;
if (_pucPcmBuf != nullptr) {
delete[] _pucPcmBuf;
_pucPcmBuf = nullptr;
}
}
@ -47,19 +66,19 @@ bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
return false;
}
// (1) Open FAAC engine
m_hEncoder = faacEncOpen(iSampleRate, iChannels, &m_ulInputSamples,
&m_ulMaxOutputBytes);
if (m_hEncoder == NULL) {
_hEncoder = faacEncOpen(iSampleRate, iChannels, &_ulInputSamples,
&_ulMaxOutputBytes);
if (_hEncoder == NULL) {
return false;
}
m_pucAacBuf = new unsigned char[m_ulMaxOutputBytes];
m_ulMaxInputBytes = m_ulInputSamples * iSampleBit / 8;
m_pucPcmBuf = new unsigned char[m_ulMaxInputBytes * 4];
_pucAacBuf = new unsigned char[_ulMaxOutputBytes];
_ulMaxInputBytes = _ulInputSamples * iSampleBit / 8;
_pucPcmBuf = new unsigned char[_ulMaxInputBytes * 4];
// (2.1) Get current encoding configuration
faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(m_hEncoder);
faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(_hEncoder);
if (pConfiguration == NULL) {
faacEncClose(m_hEncoder);
faacEncClose(_hEncoder);
return false;
}
pConfiguration->aacObjectType =LOW;
@ -75,30 +94,29 @@ bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
pConfiguration->inputFormat = FAAC_INPUT_16BIT;
// (2.2) Set encoding configuration
if(!faacEncSetConfiguration(m_hEncoder, pConfiguration)){
if(!faacEncSetConfiguration(_hEncoder, pConfiguration)){
ErrorL << "faacEncSetConfiguration failed";
faacEncClose(m_hEncoder);
faacEncClose(_hEncoder);
return false;
}
return true;
}
int AACEncoder::inputData(char *pcPcmBufr, int iLen, unsigned char **ppucOutBuffer) {
memcpy(m_pucPcmBuf + m_uiPcmLen, pcPcmBufr, iLen);
m_uiPcmLen += iLen;
if (m_uiPcmLen < m_ulMaxInputBytes) {
memcpy(_pucPcmBuf + _uiPcmLen, pcPcmBufr, iLen);
_uiPcmLen += iLen;
if (_uiPcmLen < _ulMaxInputBytes) {
return 0;
}
int nRet = faacEncEncode(m_hEncoder, (int32_t *) (m_pucPcmBuf), m_ulInputSamples, m_pucAacBuf, m_ulMaxOutputBytes);
m_uiPcmLen -= m_ulMaxInputBytes;
memmove(m_pucPcmBuf, m_pucPcmBuf + m_ulMaxInputBytes, m_uiPcmLen);
*ppucOutBuffer = m_pucAacBuf;
int nRet = faacEncEncode(_hEncoder, (int32_t *) (_pucPcmBuf), _ulInputSamples, _pucAacBuf, _ulMaxOutputBytes);
_uiPcmLen -= _ulMaxInputBytes;
memmove(_pucPcmBuf, _pucPcmBuf + _ulMaxInputBytes, _uiPcmLen);
*ppucOutBuffer = _pucAacBuf;
return nRet;
}
} /* namespace Codec */
} /* namespace ZL */
} /* namespace mediakit */
#endif //ENABLE_FAAC

View File

@ -1,15 +1,34 @@
/*
* AACEncoder.h
/*
* MIT License
*
* Created on: 2016811
* Author: xzl
* 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 CODEC_AACENCODER_H_
#define CODEC_AACENCODER_H_
namespace ZL {
namespace Codec {
namespace mediakit {
class AACEncoder {
public:
@ -19,19 +38,18 @@ public:
int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer);
private:
unsigned char *m_pucPcmBuf = nullptr;
unsigned int m_uiPcmLen = 0;
unsigned char *_pucPcmBuf = nullptr;
unsigned int _uiPcmLen = 0;
unsigned char *m_pucAacBuf = nullptr;
void *m_hEncoder = nullptr;
unsigned char *_pucAacBuf = nullptr;
void *_hEncoder = nullptr;
unsigned long m_ulInputSamples = 0;
unsigned long m_ulMaxInputBytes = 0;
unsigned long m_ulMaxOutputBytes = 0;
unsigned long _ulInputSamples = 0;
unsigned long _ulMaxInputBytes = 0;
unsigned long _ulMaxOutputBytes = 0;
};
} /* namespace Codec */
} /* namespace ZL */
} /* namespace mediakit */
#endif /* CODEC_AACENCODER_H_ */

View File

@ -1,17 +1,37 @@
/*
* H264Encoder.cpp
/*
* MIT License
*
* Created on: 2016811
* Author: xzl
* 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.
*/
#ifdef ENABLE_X264
#include "H264Encoder.h"
#include "Util/TimeTicker.h"
using namespace ZL::Util;
namespace ZL {
namespace Codec {
using namespace toolkit;
namespace mediakit {
H264Encoder::H264Encoder() {
@ -19,19 +39,19 @@ H264Encoder::H264Encoder() {
H264Encoder::~H264Encoder() {
//* 清除图像区域
if (m_pPicIn) {
delete m_pPicIn;
m_pPicIn = nullptr;
if (_pPicIn) {
delete _pPicIn;
_pPicIn = nullptr;
}
if (m_pPicOut) {
delete m_pPicOut;
m_pPicOut = nullptr;
if (_pPicOut) {
delete _pPicOut;
_pPicOut = nullptr;
}
//* 关闭编码器句柄
if (m_pX264Handle) {
x264_encoder_close(m_pX264Handle);
m_pX264Handle = nullptr;
if (_pX264Handle) {
x264_encoder_close(_pX264Handle);
_pX264Handle = nullptr;
}
}
@ -57,20 +77,20 @@ Vui参数集视频可用性信息视频标准化选项
int i_sar_height;
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
Int i_vidformat; "undef"component/pal/ntsc/secam/mac/undef
int b_fullrange; Specify full range samples setting"off"off/on
int i_colorprim; "undef"undef/bt709/bt470m/bt470bgsmpte170m/smpte240m/film
int i_transfer; "undef"undef/bt709/bt470m/bt470bg/linear,log100/log316/smpte170m/smpte240m
int b_fullrange; Specify full range samples setting"off":off/on
int i_colorprim; "undef":undef/bt709/bt470m/bt470bgsmpte170m/smpte240m/film
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_chroma_loc; both top & bottom色度样本指定0~50
} vui;
int i_fps_num;
int i_fps_den;
fps帧率确定的
fps帧率确定的:
{ float fps;
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 b_chroma_me; P帧的模式选择
int b_mixed_references; P帧有它自己的参考号
int i_trellis; Trellis量化8x8的块寻找合适的量化值CABAC0 01使2使
int i_trellis; Trellis量化8x8的块寻找合适的量化值CABAC0 0:1:使2:使
int b_fast_pskip; P帧跳过检测
int b_dct_decimate; P-frames转换参数域
int i_noise_reduction;
@ -209,7 +229,7 @@ Value的值就是fps。
} x264_param_t;*/
bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
if (m_pX264Handle) {
if (_pX264Handle) {
return true;
}
x264_param_t X264Param, *pX264Param = &X264Param;
@ -249,13 +269,13 @@ bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
GOP就称为open-GOP
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的
I0 P0 B0 B1 P1 B2 B3...close-GOP码流
: I0 P0 B0 B1 P1 B2 B3...close-GOP码流
I0后面所有帧的解码不依赖于I0前面的帧I0后面所有帧的dts都比I0的大
IDR0 B0 B1 P0 B2 B3...GOP是close-GOPB0,B1虽然dst比IDR0小
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
...P0 B1 B2 P3 B4 P5 I6这样就不会输出open-GOP码流P0 P3 B1 B2 P5 B4 I6...
I6前面的第5帧是设置为B帧还是P帧
@ -287,48 +307,47 @@ bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
//* 打开编码器句柄,通过x264_encoder_parameters得到设置给X264
//* 的参数.通过x264_encoder_reconfig更新X264的参数
m_pX264Handle = x264_encoder_open(pX264Param);
if (!m_pX264Handle) {
_pX264Handle = x264_encoder_open(pX264Param);
if (!_pX264Handle) {
return false;
}
m_pPicIn = new x264_picture_t;
m_pPicOut = new x264_picture_t;
x264_picture_init(m_pPicIn);
x264_picture_init(m_pPicOut);
m_pPicIn->img.i_csp = X264_CSP_I420;
m_pPicIn->img.i_plane = 3;
_pPicIn = new x264_picture_t;
_pPicOut = new x264_picture_t;
x264_picture_init(_pPicIn);
x264_picture_init(_pPicOut);
_pPicIn->img.i_csp = X264_CSP_I420;
_pPicIn->img.i_plane = 3;
return true;
}
int H264Encoder::inputData(char* apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame** ppFrame) {
//TimeTicker1(5);
m_pPicIn->img.i_stride[0] = aiYuvLen[0];
m_pPicIn->img.i_stride[1] = aiYuvLen[1];
m_pPicIn->img.i_stride[2] = aiYuvLen[2];
m_pPicIn->img.plane[0] = (uint8_t *) apcYuv[0];
m_pPicIn->img.plane[1] = (uint8_t *) apcYuv[1];
m_pPicIn->img.plane[2] = (uint8_t *) apcYuv[2];
m_pPicIn->i_pts = i64Pts;
_pPicIn->img.i_stride[0] = aiYuvLen[0];
_pPicIn->img.i_stride[1] = aiYuvLen[1];
_pPicIn->img.i_stride[2] = aiYuvLen[2];
_pPicIn->img.plane[0] = (uint8_t *) apcYuv[0];
_pPicIn->img.plane[1] = (uint8_t *) apcYuv[1];
_pPicIn->img.plane[2] = (uint8_t *) apcYuv[2];
_pPicIn->i_pts = i64Pts;
int iNal;
x264_nal_t* pNals;
int iResult = x264_encoder_encode(m_pX264Handle, &pNals, &iNal, m_pPicIn,
m_pPicOut);
int iResult = x264_encoder_encode(_pX264Handle, &pNals, &iNal, _pPicIn,
_pPicOut);
if (iResult <= 0) {
return 0;
}
for (int i = 0; i < iNal; i++) {
x264_nal_t pNal = pNals[i];
m_aFrames[i].iType = pNal.i_type;
m_aFrames[i].iLength = pNal.i_payload;
m_aFrames[i].pucData = pNal.p_payload;
_aFrames[i].iType = pNal.i_type;
_aFrames[i].iLength = pNal.i_payload;
_aFrames[i].pucData = pNal.p_payload;
}
*ppFrame = m_aFrames;
*ppFrame = _aFrames;
return iNal;
}
} /* namespace Codec */
} /* namespace ZL */
} /* namespace mediakit */
#endif //ENABLE_X264

View File

@ -1,10 +1,30 @@
/*
* H264Encoder.h
/*
* MIT License
*
* Created on: 2016811
* Author: xzl
* 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 CODEC_H264ENCODER_H_
#define CODEC_H264ENCODER_H_
@ -18,8 +38,7 @@ extern "C" {
}
#endif //__cplusplus
namespace ZL {
namespace Codec {
namespace mediakit {
class H264Encoder {
public:
@ -34,13 +53,12 @@ public:
bool init(int iWidth, int iHeight, int iFps);
int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame);
private:
x264_t* m_pX264Handle = nullptr;
x264_picture_t* m_pPicIn = nullptr;
x264_picture_t* m_pPicOut = nullptr;
H264Frame m_aFrames[10];
x264_t* _pX264Handle = nullptr;
x264_picture_t* _pPicIn = nullptr;
x264_picture_t* _pPicOut = nullptr;
H264Frame _aFrames[10];
};
} /* namespace Codec */
} /* namespace ZL */
} /* namespace mediakit */
#endif /* CODEC_H264ENCODER_H_ */

164
src/Common/Device.cpp Normal file
View File

@ -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 */

160
src/Common/Device.h Normal file
View File

@ -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_ */

View File

@ -1,25 +0,0 @@
/*
* MediaSender.h
*
* Created on: 201691
* 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_ */

121
src/Common/MediaSink.cpp Normal file
View File

@ -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

122
src/Common/MediaSink.h Normal file
View File

@ -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 ;
/**
* trackTrack的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输出frameonAllTrackReady触发后才会调用此方法
* @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

177
src/Common/MediaSource.cpp Normal file
View File

@ -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 */

229
src/Common/MediaSource.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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 "Util/util.h"
#include "Util/onceToken.h"
#include "Network/sockutil.h"
#ifndef UINT64_MAX
#define UINT64_MAX 0xFFFFFFFFFFFFFFFF
#endif//UINT64_MAX
using namespace toolkit;
using namespace ZL::Network;
namespace mediakit {
namespace Config {
void loaIniConfig(){
auto &ini = ZL::Util::mINI::Instance();
bool loadIniConfig(const char *ini_path){
string ini;
if(ini_path){
ini = ini_path;
}else{
ini = exePath() + ".ini";
}
try{
ini.parseFile(exePath() + ".ini");
mINI::Instance().parseFile(ini);
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
return true;
}catch (std::exception &ex) {
ini.dumpFile(exePath() + ".ini");
mINI::Instance().dumpFile(ini);
return false;
}
}
////////////广播名称///////////
namespace Broadcast {
const char kBroadcastRtspSessionPlay[] = "kBroadcastRtspSessionPlay";
const char kBroadcastRtspSrcRegisted[] = "kBroadcastRtspSrcRegisted";
const char kBroadcastRtmpSrcRegisted[] = "kBroadcastRtmpSrcRegisted";
const char kBroadcastMediaChanged[] = "kBroadcastMediaChanged";
const char kBroadcastRecordMP4[] = "kBroadcastRecordMP4";
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";
//代理失败最大重试次数
namespace Proxy {
#define PROXY_FIELD "proxy."
#define PROXY_REPLAY_CNT (UINT64_MAX)
const char kReplayCount[] = PROXY_FIELD"replayCount";
const char kFlowThreshold[] = "broadcast.flowThreshold";
onceToken token([](){
mINI::Instance()[kReplayCount] = PROXY_REPLAY_CNT;
mINI::Instance()[kFlowThreshold] = 1024;
},nullptr);
}//namespace Proxy
} //namespace Broadcast
////////////HTTP配置///////////
namespace Http {
@ -61,7 +90,7 @@ const char kSendBufSize[] = HTTP_FIELD"sendBufSize";
const char kMaxReqSize[] = HTTP_FIELD"maxReqSize";
//http keep-alive秒数
#define HTTP_KEEP_ALIVE_SECOND 5
#define HTTP_KEEP_ALIVE_SECOND 10
const char kKeepAliveSecond[] = HTTP_FIELD"keepAliveSecond";
//http keep-alive最大请求数
@ -69,13 +98,13 @@ const char kKeepAliveSecond[] = HTTP_FIELD"keepAliveSecond";
const char kMaxReqCount[] = HTTP_FIELD"maxReqCount";
//http 字符编码
#if defined(_WIN32)
#define HTTP_CHAR_SET "gb2312"
#else
#define HTTP_CHAR_SET "utf-8"
#endif
const char kCharSet[] = HTTP_FIELD"charSet";
//http 服务器名称
#define HTTP_SERVER_NAME "ZLServer"
const char kServerName[] = HTTP_FIELD"serverName";
//http 服务器根目录
#define HTTP_ROOT_PATH (exeDir() + "httpRoot")
const char kRootPath[] = HTTP_FIELD"rootPath";
@ -86,17 +115,12 @@ const char kRootPath[] = HTTP_FIELD"rootPath";
"<body bgcolor=\"white\">"\
"<center><h1>您访问的资源不存在!</h1></center>"\
"<hr><center>"\
HTTP_SERVER_NAME\
SERVER_NAME\
"</center>"\
"</body>"\
"</html>"
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([](){
mINI::Instance()[kPort] = HTTP_PORT;
@ -106,10 +130,8 @@ onceToken token([](){
mINI::Instance()[kKeepAliveSecond] = HTTP_KEEP_ALIVE_SECOND;
mINI::Instance()[kMaxReqCount] = HTTP_MAX_REQ_CNT;
mINI::Instance()[kCharSet] = HTTP_CHAR_SET;
mINI::Instance()[kServerName] = HTTP_SERVER_NAME;
mINI::Instance()[kRootPath] = HTTP_ROOT_PATH;
mINI::Instance()[kNotFound] = HTTP_NOT_FOUND;
mINI::Instance()[kHttpPrefix] = HTTP_PREFIX;
},nullptr);
}//namespace Http
@ -121,15 +143,11 @@ namespace Shell {
#define SHELL_PORT 9000
const char kPort[] = SHELL_FIELD"port";
#define SHELL_SERVER_NAME "ZLServer"
const char kServerName[] = SHELL_FIELD"serverName";
#define SHELL_MAX_REQ_SIZE 1024
const char kMaxReqSize[] = SHELL_FIELD"maxReqSize";
onceToken token([](){
mINI::Instance()[kPort] = SHELL_PORT;
mINI::Instance()[kServerName] = SHELL_SERVER_NAME;
mINI::Instance()[kMaxReqSize] = SHELL_MAX_REQ_SIZE;
},nullptr);
} //namespace Shell
@ -141,12 +159,12 @@ namespace Rtsp {
#define RTSP_PORT 554
const char kPort[] = RTSP_FIELD"port";
#define RTSP_SERVER_NAME "ZLServer"
const char kServerName[] = RTSP_FIELD"serverName";
const char kAuthBasic[] = RTSP_FIELD"authBasic";
onceToken token([](){
mINI::Instance()[kPort] = RTSP_PORT;
mINI::Instance()[kServerName] = RTSP_SERVER_NAME;
//默认Md5方式认证
mINI::Instance()[kAuthBasic] = 0;
},nullptr);
} //namespace Rtsp
@ -157,9 +175,11 @@ namespace Rtmp {
#define RTMP_PORT 1935
const char kPort[] = RTMP_FIELD"port";
const char kModifyStamp[] = RTMP_FIELD"modifyStamp";
onceToken token([](){
mINI::Instance()[kPort] = RTMP_PORT;
mINI::Instance()[kModifyStamp] = true;
},nullptr);
} //namespace RTMP
@ -175,10 +195,6 @@ const char kVideoMtuSize[] = RTP_FIELD"videoMtuSize";
#define RTP_Audio_MTU_SIZE 600
const char kAudioMtuSize[] = RTP_FIELD"audioMtuSize";
//udp方式接受RTP包的最大缓存
#define RTP_UDP_BUFSIZE (128 * 1024)
const char kUdpBufSize[] = RTP_FIELD"udpBufSize";
//RTP排序缓存最大个数
#define RTP_MAX_RTP_COUNT 50
const char kMaxRtpCount[] = RTP_FIELD"maxRtpCount";
@ -195,7 +211,6 @@ const char kCycleMS[] = RTP_FIELD"cycleMS";
onceToken token([](){
mINI::Instance()[kVideoMtuSize] = RTP_VIDOE_MTU_SIZE;
mINI::Instance()[kAudioMtuSize] = RTP_Audio_MTU_SIZE;
mINI::Instance()[kUdpBufSize] = RTP_UDP_BUFSIZE;
mINI::Instance()[kMaxRtpCount] = RTP_MAX_RTP_COUNT;
mINI::Instance()[kClearCount] = RTP_CLEAR_COUNT;
mINI::Instance()[kCycleMS] = RTP_CYCLE_MS;
@ -206,20 +221,16 @@ onceToken token([](){
namespace MultiCast {
#define MULTI_FIELD "multicast."
//组播分配起始地址
#define MULTI_ADDR_MIN (0xE00000FF + 10)
const char kAddrMin[] = MULTI_FIELD"addrMin";
//组播分配截止地址
#define MULTI_ADDR_MAX (0xEFFFFFFF)
const char kAddrMax[] = MULTI_FIELD"addrMax";
//组播TTL
#define MULTI_UDP_TTL 64
const char kUdpTTL[] = MULTI_FIELD"udpTTL";
onceToken token([](){
mINI::Instance()[kAddrMin] = MULTI_ADDR_MIN;
mINI::Instance()[kAddrMax] = MULTI_ADDR_MAX;
mINI::Instance()[kAddrMin] = "239.0.0.0";
mINI::Instance()[kAddrMax] = "239.255.255.255";
mINI::Instance()[kUdpTTL] = MULTI_UDP_TTL;
},nullptr);
@ -241,12 +252,6 @@ const char kSampleMS[] = RECORD_FIELD"sampleMS";
#define RECORD_FILE_SECOND (10*60)
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
const char kFilePath[] = RECORD_FIELD"filePath";
@ -256,7 +261,6 @@ onceToken token([](){
mINI::Instance()[kSampleMS] = RECORD_SAMPLE_MS;
mINI::Instance()[kFileSecond] = RECORD_FILE_SECOND;
mINI::Instance()[kFilePath] = RECORD_FILE_PATH;
mINI::Instance()[kRtspPrefix] = RECORD_RTSP_PREFIX;
},nullptr);
} //namespace Record
@ -266,7 +270,7 @@ namespace Hls {
#define HLS_FIELD "hls."
//HLS切片时长,单位秒
#define HLS_SEGMENT_DURATION 5
#define HLS_SEGMENT_DURATION 3
const char kSegmentDuration[] = HLS_FIELD"segDur";
//HLS切片个数
@ -290,6 +294,6 @@ onceToken token([](){
} //namespace Hls
} // namespace Config
} // namespace mediakit

View File

@ -1,27 +1,49 @@
//
// appConfig.h
// ZLMedia
//
// Created by lyl on 16/10/22.
// Copyright © 2016年 jizan. All rights reserved.
//
/*
* 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 appConfig_h
#define appConfig_h
#ifndef COMMON_CONFIG_H
#define COMMON_CONFIG_H
#include <functional>
#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();
////////////TCP最大连接数///////////
#ifdef __x86_64__
#define MAX_TCP_SESSION 100000
#else
#define MAX_TCP_SESSION 128
#endif
namespace mediakit {
//加载配置文件,如果配置文件不存在,那么会导出默认配置并生成配置文件
//加载配置文件成功后会触发kBroadcastUpdateConfig广播
//如果指定的文件名(ini_path)为空,那么会加载默认配置文件
//默认配置文件名为 /path/to/your/exe.ini
//加载配置文件成功后返回true否则返回false
bool loadIniConfig(const char *ini_path = nullptr);
////////////其他宏定义///////////
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b) )
@ -35,32 +57,98 @@ void loaIniConfig();
#define CLEAR_ARR(arr) for(auto &item : arr){ item = 0;}
#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 {
extern const char kBroadcastRtspSessionPlay[];
#define BroadcastRtspSessionPlayArgs const char *app,const char *stream
extern const char kBroadcastRtspSrcRegisted[];
#define BroadcastRtspSrcRegistedArgs const char *app,const char *stream
extern const char kBroadcastRtmpSrcRegisted[];
#define BroadcastRtmpSrcRegistedArgs const char *app,const char *stream
//注册或反注册MediaSource事件广播
extern const char kBroadcastMediaChanged[];
#define BroadcastMediaChangedArgs const bool &bRegist, const string &schema,const string &vhost,const string &app,const string &stream,MediaSource &sender
//录制mp4文件成功后广播
extern const char kBroadcastRecordMP4[];
#define BroadcastRecordMP4Args const Mp4Info &info
#define BroadcastRecordMP4Args const Mp4Info &info,Mp4Maker &sender
//收到http api请求广播
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 Proxy {
extern const char kReplayCount[];
}//namespace Proxy
////////////HTTP配置///////////
namespace Http {
extern const char kPort[];
@ -75,35 +163,32 @@ extern const char kKeepAliveSecond[];
extern const char kMaxReqCount[];
//http 字符编码
extern const char kCharSet[];
//http 服务器名称
extern const char kServerName[];
//http 服务器根目录
extern const char kRootPath[];
//http 404错误提示内容
extern const char kNotFound[];
//HTTP访问url前缀
extern const char kHttpPrefix[];
}//namespace Http
////////////SHELL配置///////////
namespace Shell {
extern const char kServerName[];
extern const char kMaxReqSize[];
extern const char kPort[];
} //namespace Shell
////////////RTSP服务器配置///////////
namespace Rtsp {
#define RTSP_VERSION 1.30
#define RTSP_BUILDTIME __DATE__" CST"
extern const char kServerName[];
extern const char kPort[];
//是否优先base64方式认证默认Md5方式认证
extern const char kAuthBasic[];
} //namespace Rtsp
////////////RTMP服务器配置///////////
namespace Rtmp {
extern const char kPort[];
extern const char kModifyStamp[];
} //namespace RTMP
@ -113,8 +198,6 @@ namespace Rtp {
extern const char kVideoMtuSize[];
//RTP打包最大MTU,公网情况下更小
extern const char kAudioMtuSize[];
//udp方式接受RTP包的最大缓存
extern const char kUdpBufSize[];
//RTP排序缓存最大个数
extern const char kMaxRtpCount[];
//如果RTP序列正确次数累计达到该数字就启动清空排序缓存
@ -141,8 +224,6 @@ extern const char kAppName[];
extern const char kSampleMS[];
//MP4文件录制大小,不能太大,否则MP4Close函数执行事件太长
extern const char kFileSecond[];
//Rtsp访问url前缀
extern const char kRtspPrefix[];
//录制文件路径
extern const char kFilePath[];
} //namespace Record
@ -159,6 +240,6 @@ extern const char kFileBufSize[];
extern const char kFilePath[];
} //namespace Hls
} // namespace Config
} // namespace mediakit
#endif /* appConfig_h */
#endif /* COMMON_CONFIG_H */

View File

@ -1,256 +0,0 @@
/*
* Device.cpp
*
* Created on: 2016810
* 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 */

View File

@ -1,108 +0,0 @@
/*
* Device.h
*
* Created on: 2016810
* 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_ */

View File

@ -1,153 +0,0 @@
/*
* PlyerProxy.cpp
*
* Created on: 2016126
* 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 */

View File

@ -1,48 +0,0 @@
/*
* PlyerProxy.h
*
* Created on: 2016126
* 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_ */

View File

@ -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

View File

@ -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 */

120
src/Extension/AAC.cpp Normal file
View File

@ -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

310
src/Extension/AAC.h Normal file
View File

@ -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;
}
/**
* 168
* @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:
/**
* 2aac配置
*/
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

270
src/Extension/Factory.cpp Normal file
View File

@ -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

144
src/Extension/Factory.h Normal file
View File

@ -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获取TrackTrack的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

312
src/Extension/Frame.h Normal file
View File

@ -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();
}
/**
* 2640x00 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

56
src/Extension/H264.cpp Normal file
View File

@ -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

360
src/Extension/H264.h Normal file
View File

@ -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 264340x00 00 00 01
* @param pps_prefix_len 264340x00 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 01sps
* @return
*/
const string &getSps() const{
return _sps;
}
/**
* 0x00 00 00 01pps
* @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

33
src/Extension/H265.cpp Normal file
View File

@ -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

357
src/Extension/H265.h Normal file
View File

@ -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 265340x00 00 00 01
* @param sps_prefix_len 265340x00 00 00 01
* @param pps_prefix_len 265340x00 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 01vps
* @return
*/
const string &getVps() const {
return _vps;
}
/**
* 0x00 00 00 01sps
* @return
*/
const string &getSps() const {
return _sps;
}
/**
* 0x00 00 00 01pps
* @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

130
src/Extension/Track.h Normal file
View File

@ -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;};
/**
* 168
* @return
*/
virtual int getAudioSampleBit() const {return 0;};
/**
*
* @return
*/
virtual int getAudioChannel() const {return 0;};
};
}//namespace mediakit
#endif //ZLMEDIAKIT_TRACK_H

View File

@ -1,15 +1,33 @@
//
// H264Parser.cpp
// MediaPlayer
//
// Created by xzl on 2017/1/16.
// Copyright © 2017年 jizan. All rights reserved.
//
/*
* 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 "H264Parser.h"
#include "Util/logger.h"
using namespace toolkit;
using namespace ZL::Util;
H264Parser::H264Parser(){
@ -19,19 +37,19 @@ H264Parser::~H264Parser(){
}
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) {
if(media::H264Parser::kOk != m_parser.AdvanceToNextNALU(&m_nalu)){
if(media::H264Parser::kOk != _parser.AdvanceToNextNALU(&_nalu)){
break;
}
switch (m_nalu.nal_unit_type) {
switch (_nalu.nal_unit_type) {
case media::H264NALU::kNonIDRSlice:
case media::H264NALU::kIDRSlice:{
if(media::H264Parser::kOk == m_parser.ParseSliceHeader(m_nalu, &m_shdr)){
const media::H264SPS *pPps = m_parser.GetSPS(m_shdr.pic_parameter_set_id);
if(media::H264Parser::kOk == _parser.ParseSliceHeader(_nalu, &_shdr)){
const media::H264SPS *pPps = _parser.GetSPS(_shdr.pic_parameter_set_id);
if (pPps) {
m_poc.ComputePicOrderCnt(pPps, m_shdr, &m_iNowPOC);
_poc.ComputePicOrderCnt(pPps, _shdr, &_iNowPOC);
computePts(dts);
}
}
@ -39,12 +57,12 @@ void H264Parser::inputH264(const string &h264,uint32_t dts){
break;
case media::H264NALU::kSPS:{
int sps_id;
m_parser.ParseSPS(&sps_id);
_parser.ParseSPS(&sps_id);
}
break;
case media::H264NALU::kPPS:{
int pps_id;
m_parser.ParsePPS(&pps_id);
_parser.ParsePPS(&pps_id);
}
break;
default:
@ -54,33 +72,33 @@ void H264Parser::inputH264(const string &h264,uint32_t dts){
}
void H264Parser::computePts(uint32_t iNowDTS) {
auto iPOCInc = m_iNowPOC - m_iLastPOC;
if (m_shdr.slice_type % 5 == 1) {
auto iPOCInc = _iNowPOC - _iLastPOC;
if (_shdr.slice_type % 5 == 1) {
//这是B帧
m_iNowPTS = m_iLastPTS + m_iMsPerPOC * (iPOCInc);
_iNowPTS = _iLastPTS + _iMsPerPOC * (iPOCInc);
} else {
//这是I帧或者P帧
m_iNowPTS = iNowDTS;
_iNowPTS = iNowDTS;
//计算每一POC的时间
if(iPOCInc == 0){
WarnL << "iPOCInc = 0," << m_iNowPOC << " " << m_iLastPOC;
WarnL << "iPOCInc = 0," << _iNowPOC << " " << _iLastPOC;
}else{
m_iMsPerPOC = (m_iNowPTS - m_iLastPTS) / iPOCInc;
_iMsPerPOC = (_iNowPTS - _iLastPTS) / iPOCInc;
}
m_iLastPTS = m_iNowPTS;
m_iLastPOC = m_iNowPOC;
_iLastPTS = _iNowPTS;
_iLastPOC = _iNowPOC;
}
// DebugL << m_shdr.slice_type
// DebugL << _shdr.slice_type
// <<"\r\nNOW:"
// << m_iNowPOC << " "
// << m_iNowPTS << " "
// << _iNowPOC << " "
// << _iNowPTS << " "
// << iNowDTS << " "
// << "\r\nLST:"
// << m_iLastPOC << " "
// << m_iLastPTS << " "
// << m_iMsPerPOC << endl;
// << _iLastPOC << " "
// << _iLastPTS << " "
// << _iMsPerPOC << endl;
}

View File

@ -1,10 +1,28 @@
//
// H264Parser.h
// MediaPlayer
//
// Created by xzl on 2017/1/16.
// Copyright © 2017年 jizan. All rights reserved.
//
/*
* 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 H264Parser_h
#define H264Parser_h
@ -26,29 +44,29 @@ public:
void inputH264(const string &h264,uint32_t dts);
int32_t getPOC() const{
return m_iNowPOC;
return _iNowPOC;
}
int getSliceType() const{
return m_shdr.slice_type;
return _shdr.slice_type;
}
int getNaluType() const{
return m_nalu.nal_unit_type;
return _nalu.nal_unit_type;
}
uint32_t getPts() const{
return m_iNowPTS;
return _iNowPTS;
}
private:
media::H264Parser m_parser;
media::H264POC m_poc;
media::H264NALU m_nalu;
media::H264SliceHeader m_shdr;
media::H264Parser _parser;
media::H264POC _poc;
media::H264NALU _nalu;
media::H264SliceHeader _shdr;
int32_t m_iNowPOC = INT32_MAX;
int32_t m_iLastPOC = INT32_MAX;
int32_t _iNowPOC = INT32_MAX;
int32_t _iLastPOC = INT32_MAX;
uint32_t m_iNowPTS = INT32_MAX;
uint32_t m_iLastPTS = INT32_MAX;
int32_t m_iMsPerPOC = 30;
uint32_t _iNowPTS = INT32_MAX;
uint32_t _iLastPTS = INT32_MAX;
int32_t _iMsPerPOC = 30;
void computePts(uint32_t dts);

View File

@ -1,9 +1,7 @@
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h> /* for uint32_t, etc */
#include <pthread.h>
#include "SPSParser.h"
/********************************************
@ -21,8 +19,9 @@
#define MIN_LOG2_MAX_FRAME_NUM 4
#define H264_MAX_PICTURE_COUNT 36
#define CODEC_FLAG2_IGNORE_CROP 0x00010000 ///< Discard cropping information from SPS.
#ifndef INT_MAX
#define INT_MAX 65535
#endif //INT_MAX
/* report level */
#define RPT_ERR (1) // error, system error

View File

@ -1,7 +1,5 @@
/***************************************************************************************
***************************************************************************************/
#ifndef _JZAN_SPS_PPS_H_
#define _JZAN_SPS_PPS_H_
#ifndef _SPSPARSER_H_
#define _SPSPARSER_H_
#if defined (__cplusplus)
extern "C" {
@ -189,4 +187,4 @@ void h264GeFramerate(T_SPS *ptSps, float *pfFramerate);
}
#endif
#endif
#endif //_SPS_PPS_H_

View 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
// found in the LICENSE file.

View 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
// found in the LICENSE file.
//

View 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
// found in the LICENSE file.
@ -7,8 +7,7 @@
#include <memory>
#include "macros.h"
#include "Util/logger.h"
using namespace ZL::Util;
using namespace toolkit;
template <class ForwardIterator>
void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
@ -173,7 +172,7 @@ return kInvalidStream; \
start += subsamples[i].clear_bytes;
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);
start = end;
}
@ -311,7 +310,7 @@ return kInvalidStream; \
// The start code is inside an encrypted section so we need to scan
// for another start code.
*start_code_size = 0;
start += std::min(*offset + 1, bytes_left);
start += min(*offset + 1, bytes_left);
}
} while (*start_code_size == 0);

View 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
// found in the LICENSE file.
//

View 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
// found in the LICENSE file.
@ -8,8 +8,7 @@
#include "macros.h"
#include "h264_parser.h"
#include "h264_poc.h"
using namespace ZL::Util;
using namespace toolkit;
namespace media {
@ -113,7 +112,7 @@ namespace media {
// (assuming no interlacing).
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;
*pic_order_cnt = std::min(top_foc, bottom_foc);
*pic_order_cnt = min(top_foc, bottom_foc);
// Store state.
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 bottom_foc = top_foc + sps->offset_for_top_to_bottom_field +
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.
prev_frame_num_ = slice_hdr.frame_num;

View 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
// found in the LICENSE file.

View 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
// found in the LICENSE file.
@ -88,7 +88,7 @@ static type& name = *new type arguments
#include <assert.h>
#include "Util/logger.h"
using namespace ZL::Util;
using namespace toolkit;
#define DCHECK(x) if(!(x)) { ErrorL << "DCHECK " << #x <<endl; }
#define DCHECK_GT(x,y) if(!((x) > (y))) { ErrorL << "DCHECK_GT:" << #x << #y << endl; }

View File

@ -1,9 +0,0 @@
//
// ranges.cpp
// MediaPlayer
//
// Created by xzl on 2017/1/13.
// Copyright © 2017年 jizan. All rights reserved.
//
#include "ranges.h"

View File

@ -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
// found in the LICENSE file.
@ -96,7 +96,7 @@ namespace media {
// original loop went too far.
while ((i + 1) < ranges_.size() &&
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);
}
@ -133,8 +133,8 @@ namespace media {
size_t j = 0;
while (i < size() && j < other.size()) {
T max_start = std::max(start(i), other.start(j));
T min_end = std::min(end(i), other.end(j));
T max_start = max(start(i), other.start(j));
T min_end = min(end(i), other.end(j));
// Add an intersection range to the result if the ranges overlap.
if (max_start < min_end)

Some files were not shown because too many files have changed in this diff Show More