Commit 3f73024a by xzl

初始提交

parent aef0ecbc
File added
......@@ -27,3 +27,4 @@
*.exe
*.out
*.app
/X64/
<?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>
<?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="2101233173096" 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="-863197511674744034" 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="-1608958325086134348" 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>
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
-include ../makefile.init
RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
-include src/Shell/subdir.mk
-include src/Rtsp/subdir.mk
-include src/Rtmp/subdir.mk
-include src/RTP/subdir.mk
-include src/Player/subdir.mk
-include src/MedaiFile/CRC/subdir.mk
-include src/MedaiFile/subdir.mk
-include src/Http/subdir.mk
-include src/H264/subdir.mk
-include src/Device/subdir.mk
-include src/Codec/subdir.mk
-include src/subdir.mk
-include subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(CC_DEPS)),)
-include $(CC_DEPS)
endif
ifneq ($(strip $(C++_DEPS)),)
-include $(C++_DEPS)
endif
ifneq ($(strip $(C_UPPER_DEPS)),)
-include $(C_UPPER_DEPS)
endif
ifneq ($(strip $(CXX_DEPS)),)
-include $(CXX_DEPS)
endif
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
ifneq ($(strip $(CPP_DEPS)),)
-include $(CPP_DEPS)
endif
endif
-include ../makefile.defs
# Add inputs and outputs from these tool invocations to the build variables
# All Target
all: libZLMediaKit.a
# Tool invocations
libZLMediaKit.a: $(OBJS) $(USER_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: Cross GCC Archiver'
arm-linux-gnueabi-ar -r "libZLMediaKit.a" $(OBJS) $(USER_OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '
# Other Targets
clean:
-$(RM) $(CC_DEPS)$(C++_DEPS)$(OBJS)$(C_UPPER_DEPS)$(CXX_DEPS)$(ARCHIVES)$(C_DEPS)$(CPP_DEPS) libZLMediaKit.a
-@echo ' '
.PHONY: all clean dependents
.SECONDARY:
-include ../makefile.targets
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
USER_OBJS :=
LIBS :=
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
C_UPPER_SRCS :=
CXX_SRCS :=
C++_SRCS :=
OBJ_SRCS :=
CC_SRCS :=
ASM_SRCS :=
C_SRCS :=
CPP_SRCS :=
O_SRCS :=
S_UPPER_SRCS :=
CC_DEPS :=
C++_DEPS :=
OBJS :=
C_UPPER_DEPS :=
CXX_DEPS :=
ARCHIVES :=
C_DEPS :=
CPP_DEPS :=
# Every subdirectory with source files must be described here
SUBDIRS := \
src/Codec \
src/Device \
src/H264 \
src/Http \
src/MedaiFile/CRC \
src/MedaiFile \
src/Player \
src/RTP \
src/Rtmp \
src/Rtsp \
src/Shell \
src \
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Codec/AACEncoder.cpp \
../src/Codec/H264Encoder.cpp
OBJS += \
./src/Codec/AACEncoder.o \
./src/Codec/H264Encoder.o
CPP_DEPS += \
./src/Codec/AACEncoder.d \
./src/Codec/H264Encoder.d
# Each subdirectory must supply rules for building sources it contributes
src/Codec/%.o: ../src/Codec/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Device/Device.cpp \
../src/Device/PlayerProxy.cpp \
../src/Device/base64.cpp
OBJS += \
./src/Device/Device.o \
./src/Device/PlayerProxy.o \
./src/Device/base64.o
CPP_DEPS += \
./src/Device/Device.d \
./src/Device/PlayerProxy.d \
./src/Device/base64.d
# Each subdirectory must supply rules for building sources it contributes
src/Device/%.o: ../src/Device/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../src/H264/SPSParser.c
CPP_SRCS += \
../src/H264/H264Parser.cpp \
../src/H264/h264_bit_reader.cpp \
../src/H264/h264_parser.cpp \
../src/H264/h264_poc.cpp \
../src/H264/ranges.cpp
OBJS += \
./src/H264/H264Parser.o \
./src/H264/SPSParser.o \
./src/H264/h264_bit_reader.o \
./src/H264/h264_parser.o \
./src/H264/h264_poc.o \
./src/H264/ranges.o
C_DEPS += \
./src/H264/SPSParser.d
CPP_DEPS += \
./src/H264/H264Parser.d \
./src/H264/h264_bit_reader.d \
./src/H264/h264_parser.d \
./src/H264/h264_poc.d \
./src/H264/ranges.d
# Each subdirectory must supply rules for building sources it contributes
src/H264/%.o: ../src/H264/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
src/H264/%.o: ../src/H264/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
arm-linux-gnueabi-gcc -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Http/HttpSession.cpp \
../src/Http/strCoding.cpp
OBJS += \
./src/Http/HttpSession.o \
./src/Http/strCoding.o
CPP_DEPS += \
./src/Http/HttpSession.d \
./src/Http/strCoding.d
# Each subdirectory must supply rules for building sources it contributes
src/Http/%.o: ../src/Http/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/MedaiFile/CRC/crc32.cpp
OBJS += \
./src/MedaiFile/CRC/crc32.o
CPP_DEPS += \
./src/MedaiFile/CRC/crc32.d
# Each subdirectory must supply rules for building sources it contributes
src/MedaiFile/CRC/%.o: ../src/MedaiFile/CRC/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/MedaiFile/HLSMaker.cpp \
../src/MedaiFile/MediaReader.cpp \
../src/MedaiFile/MediaRecorder.cpp \
../src/MedaiFile/Mp4Maker.cpp \
../src/MedaiFile/TSMaker.cpp
OBJS += \
./src/MedaiFile/HLSMaker.o \
./src/MedaiFile/MediaReader.o \
./src/MedaiFile/MediaRecorder.o \
./src/MedaiFile/Mp4Maker.o \
./src/MedaiFile/TSMaker.o
CPP_DEPS += \
./src/MedaiFile/HLSMaker.d \
./src/MedaiFile/MediaReader.d \
./src/MedaiFile/MediaRecorder.d \
./src/MedaiFile/Mp4Maker.d \
./src/MedaiFile/TSMaker.d
# Each subdirectory must supply rules for building sources it contributes
src/MedaiFile/%.o: ../src/MedaiFile/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Player/MediaPlayer.cpp \
../src/Player/Player.cpp \
../src/Player/PlayerBase.cpp
OBJS += \
./src/Player/MediaPlayer.o \
./src/Player/Player.o \
./src/Player/PlayerBase.o
CPP_DEPS += \
./src/Player/MediaPlayer.d \
./src/Player/Player.d \
./src/Player/PlayerBase.d
# Each subdirectory must supply rules for building sources it contributes
src/Player/%.o: ../src/Player/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/RTP/RtpMakerAAC.cpp \
../src/RTP/RtpMakerH264.cpp
OBJS += \
./src/RTP/RtpMakerAAC.o \
./src/RTP/RtpMakerH264.o
CPP_DEPS += \
./src/RTP/RtpMakerAAC.d \
./src/RTP/RtpMakerH264.d
# Each subdirectory must supply rules for building sources it contributes
src/RTP/%.o: ../src/RTP/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Rtmp/RtmpMediaSource.cpp \
../src/Rtmp/RtmpParser.cpp \
../src/Rtmp/RtmpPlayer.cpp \
../src/Rtmp/RtmpPlayerImp.cpp \
../src/Rtmp/RtmpProtocol.cpp \
../src/Rtmp/RtmpPusher.cpp \
../src/Rtmp/RtmpSession.cpp \
../src/Rtmp/RtmpToRtspMediaSource.cpp \
../src/Rtmp/amf.cpp \
../src/Rtmp/utils.cpp
OBJS += \
./src/Rtmp/RtmpMediaSource.o \
./src/Rtmp/RtmpParser.o \
./src/Rtmp/RtmpPlayer.o \
./src/Rtmp/RtmpPlayerImp.o \
./src/Rtmp/RtmpProtocol.o \
./src/Rtmp/RtmpPusher.o \
./src/Rtmp/RtmpSession.o \
./src/Rtmp/RtmpToRtspMediaSource.o \
./src/Rtmp/amf.o \
./src/Rtmp/utils.o
CPP_DEPS += \
./src/Rtmp/RtmpMediaSource.d \
./src/Rtmp/RtmpParser.d \
./src/Rtmp/RtmpPlayer.d \
./src/Rtmp/RtmpPlayerImp.d \
./src/Rtmp/RtmpProtocol.d \
./src/Rtmp/RtmpPusher.d \
./src/Rtmp/RtmpSession.d \
./src/Rtmp/RtmpToRtspMediaSource.d \
./src/Rtmp/amf.d \
./src/Rtmp/utils.d
# Each subdirectory must supply rules for building sources it contributes
src/Rtmp/%.o: ../src/Rtmp/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Rtsp/RtpBroadCaster.cpp \
../src/Rtsp/RtpParser.cpp \
../src/Rtsp/Rtsp.cpp \
../src/Rtsp/RtspMediaSource.cpp \
../src/Rtsp/RtspPlayer.cpp \
../src/Rtsp/RtspPlayerImp.cpp \
../src/Rtsp/RtspSession.cpp \
../src/Rtsp/RtspToRtmpMediaSource.cpp \
../src/Rtsp/UDPServer.cpp
OBJS += \
./src/Rtsp/RtpBroadCaster.o \
./src/Rtsp/RtpParser.o \
./src/Rtsp/Rtsp.o \
./src/Rtsp/RtspMediaSource.o \
./src/Rtsp/RtspPlayer.o \
./src/Rtsp/RtspPlayerImp.o \
./src/Rtsp/RtspSession.o \
./src/Rtsp/RtspToRtmpMediaSource.o \
./src/Rtsp/UDPServer.o
CPP_DEPS += \
./src/Rtsp/RtpBroadCaster.d \
./src/Rtsp/RtpParser.d \
./src/Rtsp/Rtsp.d \
./src/Rtsp/RtspMediaSource.d \
./src/Rtsp/RtspPlayer.d \
./src/Rtsp/RtspPlayerImp.d \
./src/Rtsp/RtspSession.d \
./src/Rtsp/RtspToRtmpMediaSource.d \
./src/Rtsp/UDPServer.d
# Each subdirectory must supply rules for building sources it contributes
src/Rtsp/%.o: ../src/Rtsp/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Shell/CMD.cpp \
../src/Shell/ShellSession.cpp
OBJS += \
./src/Shell/CMD.o \
./src/Shell/ShellSession.o
CPP_DEPS += \
./src/Shell/CMD.d \
./src/Shell/ShellSession.d
# Each subdirectory must supply rules for building sources it contributes
src/Shell/%.o: ../src/Shell/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/config.cpp
OBJS += \
./src/config.o
CPP_DEPS += \
./src/config.d
# Each subdirectory must supply rules for building sources it contributes
src/%.o: ../src/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
arm-linux-gnueabi-g++ -std=c++1y -I/home/xzl/soft -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
-include ../makefile.init
RM := rm -rf
# All of the sources participating in the build are defined here
-include sources.mk
-include src/Shell/subdir.mk
-include src/Rtsp/subdir.mk
-include src/Rtmp/subdir.mk
-include src/RTP/subdir.mk
-include src/Player/subdir.mk
-include src/MedaiFile/CRC/subdir.mk
-include src/MedaiFile/subdir.mk
-include src/Http/subdir.mk
-include src/H264/subdir.mk
-include src/Device/subdir.mk
-include src/Codec/subdir.mk
-include src/subdir.mk
-include subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(CC_DEPS)),)
-include $(CC_DEPS)
endif
ifneq ($(strip $(C++_DEPS)),)
-include $(C++_DEPS)
endif
ifneq ($(strip $(C_UPPER_DEPS)),)
-include $(C_UPPER_DEPS)
endif
ifneq ($(strip $(CXX_DEPS)),)
-include $(CXX_DEPS)
endif
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
ifneq ($(strip $(CPP_DEPS)),)
-include $(CPP_DEPS)
endif
endif
-include ../makefile.defs
# Add inputs and outputs from these tool invocations to the build variables
# All Target
all: libZLMediaKit.so
# Tool invocations
libZLMediaKit.so: $(OBJS) $(USER_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: Cross G++ Linker'
g++ -shared -o "libZLMediaKit.so" $(OBJS) $(USER_OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '
# Other Targets
clean:
-$(RM) $(LIBRARIES)$(CC_DEPS)$(C++_DEPS)$(OBJS)$(C_UPPER_DEPS)$(CXX_DEPS)$(C_DEPS)$(CPP_DEPS) libZLMediaKit.so
-@echo ' '
.PHONY: all clean dependents
.SECONDARY:
-include ../makefile.targets
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
USER_OBJS :=
LIBS :=
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
C_UPPER_SRCS :=
CXX_SRCS :=
C++_SRCS :=
OBJ_SRCS :=
CC_SRCS :=
ASM_SRCS :=
C_SRCS :=
CPP_SRCS :=
O_SRCS :=
S_UPPER_SRCS :=
LIBRARIES :=
CC_DEPS :=
C++_DEPS :=
OBJS :=
C_UPPER_DEPS :=
CXX_DEPS :=
C_DEPS :=
CPP_DEPS :=
# Every subdirectory with source files must be described here
SUBDIRS := \
src/Codec \
src/Device \
src/H264 \
src/Http \
src/MedaiFile/CRC \
src/MedaiFile \
src/Player \
src/RTP \
src/Rtmp \
src/Rtsp \
src/Shell \
src \
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Codec/AACEncoder.cpp \
../src/Codec/H264Encoder.cpp
OBJS += \
./src/Codec/AACEncoder.o \
./src/Codec/H264Encoder.o
CPP_DEPS += \
./src/Codec/AACEncoder.d \
./src/Codec/H264Encoder.d
# Each subdirectory must supply rules for building sources it contributes
src/Codec/%.o: ../src/Codec/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Device/Device.cpp \
../src/Device/PlayerProxy.cpp \
../src/Device/base64.cpp
OBJS += \
./src/Device/Device.o \
./src/Device/PlayerProxy.o \
./src/Device/base64.o
CPP_DEPS += \
./src/Device/Device.d \
./src/Device/PlayerProxy.d \
./src/Device/base64.d
# Each subdirectory must supply rules for building sources it contributes
src/Device/%.o: ../src/Device/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../src/H264/SPSParser.c
CPP_SRCS += \
../src/H264/H264Parser.cpp \
../src/H264/h264_bit_reader.cpp \
../src/H264/h264_parser.cpp \
../src/H264/h264_poc.cpp \
../src/H264/ranges.cpp
OBJS += \
./src/H264/H264Parser.o \
./src/H264/SPSParser.o \
./src/H264/h264_bit_reader.o \
./src/H264/h264_parser.o \
./src/H264/h264_poc.o \
./src/H264/ranges.o
C_DEPS += \
./src/H264/SPSParser.d
CPP_DEPS += \
./src/H264/H264Parser.d \
./src/H264/h264_bit_reader.d \
./src/H264/h264_parser.d \
./src/H264/h264_poc.d \
./src/H264/ranges.d
# Each subdirectory must supply rules for building sources it contributes
src/H264/%.o: ../src/H264/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
src/H264/%.o: ../src/H264/%.c
@echo 'Building file: $<'
@echo 'Invoking: Cross GCC Compiler'
gcc -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Http/HttpSession.cpp \
../src/Http/strCoding.cpp
OBJS += \
./src/Http/HttpSession.o \
./src/Http/strCoding.o
CPP_DEPS += \
./src/Http/HttpSession.d \
./src/Http/strCoding.d
# Each subdirectory must supply rules for building sources it contributes
src/Http/%.o: ../src/Http/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/MedaiFile/CRC/crc32.cpp
OBJS += \
./src/MedaiFile/CRC/crc32.o
CPP_DEPS += \
./src/MedaiFile/CRC/crc32.d
# Each subdirectory must supply rules for building sources it contributes
src/MedaiFile/CRC/%.o: ../src/MedaiFile/CRC/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/MedaiFile/HLSMaker.cpp \
../src/MedaiFile/MediaReader.cpp \
../src/MedaiFile/MediaRecorder.cpp \
../src/MedaiFile/Mp4Maker.cpp \
../src/MedaiFile/TSMaker.cpp
OBJS += \
./src/MedaiFile/HLSMaker.o \
./src/MedaiFile/MediaReader.o \
./src/MedaiFile/MediaRecorder.o \
./src/MedaiFile/Mp4Maker.o \
./src/MedaiFile/TSMaker.o
CPP_DEPS += \
./src/MedaiFile/HLSMaker.d \
./src/MedaiFile/MediaReader.d \
./src/MedaiFile/MediaRecorder.d \
./src/MedaiFile/Mp4Maker.d \
./src/MedaiFile/TSMaker.d
# Each subdirectory must supply rules for building sources it contributes
src/MedaiFile/%.o: ../src/MedaiFile/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Player/MediaPlayer.cpp \
../src/Player/Player.cpp \
../src/Player/PlayerBase.cpp
OBJS += \
./src/Player/MediaPlayer.o \
./src/Player/Player.o \
./src/Player/PlayerBase.o
CPP_DEPS += \
./src/Player/MediaPlayer.d \
./src/Player/Player.d \
./src/Player/PlayerBase.d
# Each subdirectory must supply rules for building sources it contributes
src/Player/%.o: ../src/Player/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/RTP/RtpMakerAAC.cpp \
../src/RTP/RtpMakerH264.cpp
OBJS += \
./src/RTP/RtpMakerAAC.o \
./src/RTP/RtpMakerH264.o
CPP_DEPS += \
./src/RTP/RtpMakerAAC.d \
./src/RTP/RtpMakerH264.d
# Each subdirectory must supply rules for building sources it contributes
src/RTP/%.o: ../src/RTP/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Rtmp/RtmpMediaSource.cpp \
../src/Rtmp/RtmpParser.cpp \
../src/Rtmp/RtmpPlayer.cpp \
../src/Rtmp/RtmpPlayerImp.cpp \
../src/Rtmp/RtmpProtocol.cpp \
../src/Rtmp/RtmpPusher.cpp \
../src/Rtmp/RtmpSession.cpp \
../src/Rtmp/RtmpToRtspMediaSource.cpp \
../src/Rtmp/amf.cpp \
../src/Rtmp/utils.cpp
OBJS += \
./src/Rtmp/RtmpMediaSource.o \
./src/Rtmp/RtmpParser.o \
./src/Rtmp/RtmpPlayer.o \
./src/Rtmp/RtmpPlayerImp.o \
./src/Rtmp/RtmpProtocol.o \
./src/Rtmp/RtmpPusher.o \
./src/Rtmp/RtmpSession.o \
./src/Rtmp/RtmpToRtspMediaSource.o \
./src/Rtmp/amf.o \
./src/Rtmp/utils.o
CPP_DEPS += \
./src/Rtmp/RtmpMediaSource.d \
./src/Rtmp/RtmpParser.d \
./src/Rtmp/RtmpPlayer.d \
./src/Rtmp/RtmpPlayerImp.d \
./src/Rtmp/RtmpProtocol.d \
./src/Rtmp/RtmpPusher.d \
./src/Rtmp/RtmpSession.d \
./src/Rtmp/RtmpToRtspMediaSource.d \
./src/Rtmp/amf.d \
./src/Rtmp/utils.d
# Each subdirectory must supply rules for building sources it contributes
src/Rtmp/%.o: ../src/Rtmp/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Rtsp/RtpBroadCaster.cpp \
../src/Rtsp/RtpParser.cpp \
../src/Rtsp/Rtsp.cpp \
../src/Rtsp/RtspMediaSource.cpp \
../src/Rtsp/RtspPlayer.cpp \
../src/Rtsp/RtspPlayerImp.cpp \
../src/Rtsp/RtspSession.cpp \
../src/Rtsp/RtspToRtmpMediaSource.cpp \
../src/Rtsp/UDPServer.cpp
OBJS += \
./src/Rtsp/RtpBroadCaster.o \
./src/Rtsp/RtpParser.o \
./src/Rtsp/Rtsp.o \
./src/Rtsp/RtspMediaSource.o \
./src/Rtsp/RtspPlayer.o \
./src/Rtsp/RtspPlayerImp.o \
./src/Rtsp/RtspSession.o \
./src/Rtsp/RtspToRtmpMediaSource.o \
./src/Rtsp/UDPServer.o
CPP_DEPS += \
./src/Rtsp/RtpBroadCaster.d \
./src/Rtsp/RtpParser.d \
./src/Rtsp/Rtsp.d \
./src/Rtsp/RtspMediaSource.d \
./src/Rtsp/RtspPlayer.d \
./src/Rtsp/RtspPlayerImp.d \
./src/Rtsp/RtspSession.d \
./src/Rtsp/RtspToRtmpMediaSource.d \
./src/Rtsp/UDPServer.d
# Each subdirectory must supply rules for building sources it contributes
src/Rtsp/%.o: ../src/Rtsp/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/Shell/CMD.cpp \
../src/Shell/ShellSession.cpp
OBJS += \
./src/Shell/CMD.o \
./src/Shell/ShellSession.o
CPP_DEPS += \
./src/Shell/CMD.d \
./src/Shell/ShellSession.d
# Each subdirectory must supply rules for building sources it contributes
src/Shell/%.o: ../src/Shell/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
################################################################################
# Automatically-generated file. Do not edit!
################################################################################
# Add inputs and outputs from these tool invocations to the build variables
CPP_SRCS += \
../src/config.cpp
OBJS += \
./src/config.o
CPP_DEPS += \
./src/config.d
# Each subdirectory must supply rules for building sources it contributes
src/%.o: ../src/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: Cross G++ Compiler'
g++ -std=c++1y -DENABLE_FAAC -DENABLE_RTSP2RTMP -DENABLE_RTMP2RTSP -DENABLE_MEDIAFILE -DENABLE_X264 -I"/Users/xzl/git/ZLMediaKit/src" -I../../ZLToolKit/src -O3 -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '
/*
* AACEncoder.cpp
*
* Created on: 2016年8月11日
* Author: xzl
*/
#ifdef ENABLE_FAAC
#include "AACEncoder.h"
#include "Util/logger.h"
#include <cstdlib>
#ifdef __cplusplus
extern "C" {
#endif
#include <faac.h>
#ifdef __cplusplus
}
#endif
using namespace ZL::Util;
namespace ZL {
namespace Codec {
AACEncoder::AACEncoder() {
}
AACEncoder::~AACEncoder() {
if (m_hEncoder != nullptr) {
faacEncClose(m_hEncoder);
m_hEncoder = nullptr;
}
if (m_pucAacBuf != nullptr) {
delete[] m_pucAacBuf;
m_pucAacBuf = nullptr;
}
if (m_pucPcmBuf != nullptr) {
delete[] m_pucPcmBuf;
m_pucPcmBuf = nullptr;
}
}
bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
if (iSampleBit != 16) {
return false;
}
// (1) Open FAAC engine
m_hEncoder = faacEncOpen(iSampleRate, iChannels, &m_ulInputSamples,
&m_ulMaxOutputBytes);
if (m_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];
// (2.1) Get current encoding configuration
faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(m_hEncoder);
if (pConfiguration == NULL) {
faacEncClose(m_hEncoder);
return false;
}
pConfiguration->aacObjectType =LOW;
pConfiguration->mpegVersion = 4;
pConfiguration->useTns = 1;
pConfiguration->shortctl = SHORTCTL_NORMAL;
pConfiguration->useLfe = 1;
pConfiguration->allowMidside = 1;
pConfiguration->bitRate = 0;
pConfiguration->bandWidth = 0;
pConfiguration->quantqual = 50;
pConfiguration->outputFormat = 1;
pConfiguration->inputFormat = FAAC_INPUT_16BIT;
// (2.2) Set encoding configuration
if(!faacEncSetConfiguration(m_hEncoder, pConfiguration)){
ErrorL << "faacEncSetConfiguration failed";
faacEncClose(m_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) {
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;
return nRet;
}
} /* namespace Codec */
} /* namespace ZL */
#endif //ENABLE_FAAC
/*
* AACEncoder.h
*
* Created on: 2016年8月11日
* Author: xzl
*/
#ifndef CODEC_AACENCODER_H_
#define CODEC_AACENCODER_H_
namespace ZL {
namespace Codec {
class AACEncoder {
public:
AACEncoder(void);
virtual ~AACEncoder(void);
bool init(int iSampleRate, int iAudioChannel, int iAudioSampleBit);
int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer);
private:
unsigned char *m_pucPcmBuf = nullptr;
unsigned int m_uiPcmLen = 0;
unsigned char *m_pucAacBuf = nullptr;
void *m_hEncoder = nullptr;
unsigned long m_ulInputSamples = 0;
unsigned long m_ulMaxInputBytes = 0;
unsigned long m_ulMaxOutputBytes = 0;
};
} /* namespace Codec */
} /* namespace ZL */
#endif /* CODEC_AACENCODER_H_ */
/*
* H264Encoder.h
*
* Created on: 2016年8月11日
* Author: xzl
*/
#ifndef CODEC_H264ENCODER_H_
#define CODEC_H264ENCODER_H_
#include <cstdint>
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
#include <x264.h>
#ifdef __cplusplus
}
#endif //__cplusplus
namespace ZL {
namespace Codec {
class H264Encoder {
public:
typedef struct {
int iType;
int iLength;
uint8_t *pucData;
} H264Frame;
H264Encoder(void);
virtual ~H264Encoder(void);
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];
};
} /* namespace Codec */
} /* namespace ZL */
#endif /* CODEC_H264ENCODER_H_ */
/*
* Device.cpp
*
* Created on: 2016年8月10日
* Author: xzl
*/
#include "Device.h"
#include "Util/logger.h"
#include <stdio.h>
#include "Util/util.h"
#include <cstdio>
#include "base64.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 */
/*
* Device.h
*
* Created on: 2016年8月10日
* Author: xzl
*/
#ifndef DEVICE_DEVICE_H_
#define DEVICE_DEVICE_H_
#include <sys/time.h>
#include <string>
#include <functional>
#include <memory>
#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
using namespace ZL::Rtsp;
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_ */
/*
* PlyerProxy.cpp
*
* Created on: 2016年12月6日
* Author: xzl
*/
#include "PlayerProxy.h"
#include "Thread/AsyncTaskThread.h"
#include "Util/MD5.h"
#include "Util/logger.h"
#include "config.h"
#include "Util/mini.hpp"
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());
m_pPlayer->play(strUrl, strUser, strPwd, eType);
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();
}
});
}
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 */
/*
* PlyerProxy.h
*
* Created on: 2016年12月6日
* Author: xzl
*/
#ifndef SRC_DEVICE_PLAYERPROXY_H_
#define SRC_DEVICE_PLAYERPROXY_H_
#include "Device.h"
#include <memory>
#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_ */
/*
* 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
/*
* 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 */
//
// H264Parser.cpp
// MediaPlayer
//
// Created by xzl on 2017/1/16.
// Copyright © 2017年 jizan. All rights reserved.
//
#include "H264Parser.h"
#include "Util/logger.h"
using namespace ZL::Util;
H264Parser::H264Parser(){
}
H264Parser::~H264Parser(){
}
void H264Parser::inputH264(const string &h264,uint32_t dts){
m_parser.SetStream((const uint8_t *)h264.data(), h264.size());
while (true) {
if(media::H264Parser::kOk != m_parser.AdvanceToNextNALU(&m_nalu)){
break;
}
switch (m_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 (pPps) {
m_poc.ComputePicOrderCnt(pPps, m_shdr, &m_iNowPOC);
computePts(dts);
}
}
}
break;
case media::H264NALU::kSPS:{
int sps_id;
m_parser.ParseSPS(&sps_id);
}
break;
case media::H264NALU::kPPS:{
int pps_id;
m_parser.ParsePPS(&pps_id);
}
break;
default:
break;
}
}
}
void H264Parser::computePts(uint32_t iNowDTS) {
auto iPOCInc = m_iNowPOC - m_iLastPOC;
if (m_shdr.slice_type % 5 == 1) {
//这是B帧
m_iNowPTS = m_iLastPTS + m_iMsPerPOC * (iPOCInc);
} else {
//这是I帧或者P帧
m_iNowPTS = iNowDTS;
//计算每一POC的时间
if(iPOCInc == 0){
WarnL << "iPOCInc = 0," << m_iNowPOC << " " << m_iLastPOC;
}else{
m_iMsPerPOC = (m_iNowPTS - m_iLastPTS) / iPOCInc;
}
m_iLastPTS = m_iNowPTS;
m_iLastPOC = m_iNowPOC;
}
// DebugL << m_shdr.slice_type
// <<"\r\nNOW:"
// << m_iNowPOC << " "
// << m_iNowPTS << " "
// << iNowDTS << " "
// << "\r\nLST:"
// << m_iLastPOC << " "
// << m_iLastPTS << " "
// << m_iMsPerPOC << endl;
}
//
// H264Parser.hpp
// MediaPlayer
//
// Created by xzl on 2017/1/16.
// Copyright © 2017年 jizan. All rights reserved.
//
#ifndef H264Parser_h
#define H264Parser_h
#include <stdio.h>
#include <string>
#include "h264_parser.h"
#include "h264_poc.h"
using namespace std;
class H264Parser{
public:
H264Parser();
virtual ~H264Parser();
void inputH264(const string &h264,uint32_t dts);
int32_t getPOC() const{
return m_iNowPOC;
}
int getSliceType() const{
return m_shdr.slice_type;
}
int getNaluType() const{
return m_nalu.nal_unit_type;
}
uint32_t getPts() const{
return m_iNowPTS;
}
private:
media::H264Parser m_parser;
media::H264POC m_poc;
media::H264NALU m_nalu;
media::H264SliceHeader m_shdr;
int32_t m_iNowPOC = INT32_MAX;
int32_t m_iLastPOC = INT32_MAX;
uint32_t m_iNowPTS = INT32_MAX;
uint32_t m_iLastPTS = INT32_MAX;
int32_t m_iMsPerPOC = 30;
void computePts(uint32_t dts);
};
#endif /* H264Parser_hpp */
/***************************************************************************************
***************************************************************************************/
#ifndef _JZAN_SPS_PPS_H_
#define _JZAN_SPS_PPS_H_
#if defined (__cplusplus)
extern "C" {
#endif
#define QP_MAX_NUM (51 + 6*6) // The maximum supported qp
/**
* Chromaticity coordinates of the source primaries.
*/
enum T_AVColorPrimaries {
AVCOL_PRI_RESERVED0 = 0,
AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B
AVCOL_PRI_UNSPECIFIED = 2,
AVCOL_PRI_RESERVED = 3,
AVCOL_PRI_BT470M = 4, ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above
AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C
AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020
AVCOL_PRI_NB, ///< Not part of ABI
};
/**
* Color Transfer Characteristic.
*/
enum T_AVColorTransferCharacteristic {
AVCOL_TRC_RESERVED0 = 0,
AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361
AVCOL_TRC_UNSPECIFIED = 2,
AVCOL_TRC_RESERVED = 3,
AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG
AVCOL_TRC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC
AVCOL_TRC_SMPTE240M = 7,
AVCOL_TRC_LINEAR = 8, ///< "Linear transfer characteristics"
AVCOL_TRC_LOG = 9, ///< "Logarithmic transfer characteristic (100:1 range)"
AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)"
AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4
AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour Gamut
AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)
AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10 bit system
AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12 bit system
AVCOL_TRC_NB, ///< Not part of ABI
};
/**
* YUV tColorspace type.
*/
enum T_AVColorSpace {
AVCOL_SPC_RGB = 0, ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)
AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
AVCOL_SPC_UNSPECIFIED = 2,
AVCOL_SPC_RESERVED = 3,
AVCOL_SPC_FCC = 4, ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
AVCOL_SPC_SMPTE240M = 7,
AVCOL_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
AVCOL_SPC_BT2020_NCL = 9, ///< ITU-R BT2020 non-constant luminance system
AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system
AVCOL_SPC_NB, ///< Not part of ABI
};
/**
* rational number numerator/denominator
*/
typedef struct T_AVRational{
int num; ///< numerator
int den; ///< denominator
} T_AVRational;
/***
* Sequence parameter set
* ¿É²Î¿¼H264±ê×¼µÚ7½ÚºÍ¸½Â¼D E
*/
#define Extended_SAR 255
/**
* Sequence parameter set
*/
typedef struct T_SPS {
unsigned int uiSpsId;
int iProfileIdc;
int iLevelIdc;
int iChromaFormatIdc;
int iTransformBypass; ///< qpprime_y_zero_transform_bypass_flag
int iLog2MaxFrameNum; ///< log2_max_frame_num_minus4 + 4
int iPocType; ///< pic_order_cnt_type
int iLog2MaxPocLsb; ///< log2_max_pic_order_cnt_lsb_minus4
int iDeltaPicOrderAlwaysZeroFlag;
int iOffsetForNonRefPic;
int iOffsetForTopToBottomField;
int iPocCycleLength; ///< num_ref_frames_in_pic_order_cnt_cycle
int iRefFrameCount; ///< num_ref_frames
int iGapsInFrameNumAllowedFlag;
int iMbWidth; ///< pic_width_in_mbs_minus1 + 1
int iMbHeight; ///< pic_height_in_map_units_minus1 + 1
int iFrameMbsOnlyFlag;
int iMbAff; ///< mb_adaptive_frame_field_flag
int iDirect8x8InferenceFlag;
int iCrop; ///< frame_cropping_flag
/* those 4 are already in luma samples */
unsigned int uiCropLeft; ///< frame_cropping_rect_left_offset
unsigned int uiCropRight; ///< frame_cropping_rect_right_offset
unsigned int uiCropTop; ///< frame_cropping_rect_top_offset
unsigned int uiCropBottom; ///< frame_cropping_rect_bottom_offset
int iVuiParametersPresentFlag;
T_AVRational tSar;
int iVideoSignalTypePresentFlag;
int iFullRange;
int iColourDescriptionPresentFlag;
enum T_AVColorPrimaries tColorPrimaries;
enum T_AVColorTransferCharacteristic tColorTrc;
enum T_AVColorSpace tColorspace;
int iTimingInfoPresentFlag;
uint32_t u32NumUnitsInTick;
uint32_t u32TimeScale;
int iFixedFrameRateFlag;
short asOffsetForRefFrame[256]; // FIXME dyn aloc?
int iBitstreamRestrictionFlag;
int iNumReorderFrames;
int iScalingMatrixPresent;
uint8_t aau8ScalingMatrix4[6][16];
uint8_t aau8ScalingMatrix8[6][64];
int iNalHrdParametersPresentFlag;
int iVclHrdParametersPresentFlag;
int iPicStructPresentFlag;
int iTimeOffsetLength;
int iCpbCnt; ///< See H.264 E.1.2
int iInitialCpbRemovalDelayLength; ///< initial_cpb_removal_delay_length_minus1 + 1
int iCpbRemovalDelayLength; ///< cpb_removal_delay_length_minus1 + 1
int iDpbOutputDelayLength; ///< dpb_output_delay_length_minus1 + 1
int iBitDepthLuma; ///< bit_depth_luma_minus8 + 8
int iBitDepthChroma; ///< bit_depth_chroma_minus8 + 8
int iResidualColorTransformFlag; ///< residual_colour_transform_flag
int iConstraintSetFlags; ///< constraint_set[0-3]_flag
int iNew; ///< flag to keep track if the decoder context needs re-init due to changed SPS
} T_SPS;
/**
* Picture parameter set
*/
typedef struct T_PPS {
unsigned int uiSpsId;
int iCabac; ///< entropy_coding_mode_flag
int iPicOrderPresent; ///< pic_order_present_flag
int iSliceGroupCount; ///< num_slice_groups_minus1 + 1
int iMbSliceGroupMapType;
unsigned int auiRefCount[2]; ///< num_ref_idx_l0/1_active_minus1 + 1
int iWeightedPred; ///< weighted_pred_flag
int iWeightedBipredIdc;
int iInitQp; ///< pic_init_qp_minus26 + 26
int iInitQs; ///< pic_init_qs_minus26 + 26
int aiChromaQpIndexOffset[2];
int iDeblockingFilterParametersPresent; ///< deblocking_filter_parameters_present_flag
int iConstrainedIntraPred; ///< constrained_intra_pred_flag
int iRedundantPicCntPresent; ///< redundant_pic_cnt_present_flag
int iTransform8x8Mode; ///< transform_8x8_mode_flag
uint8_t aau8ScalingMatrix4[6][16];
uint8_t aau8ScalingMatrix8[6][64];
uint8_t u8ChromaQpTable[2][QP_MAX_NUM+1]; ///< pre-scaled (with aiChromaQpIndexOffset) version of qp_table
int iChromaQpDiff;
} T_PPS;
typedef struct T_GetBitContext{
uint8_t *pu8Buf; /*Ö¸ÏòSPS start*/
int iBufSize; /*SPS ³¤¶È*/
int iBitPos; /*bitÒѶÁȡλÖÃ*/
int iTotalBit; /*bit×ܳ¤¶È*/
int iCurBitPos; /*µ±Ç°¶ÁȡλÖÃ*/
}T_GetBitContext;
int h264DecSeqParameterSet(void *pvBuf, T_SPS *ptSps);
void h264GetWidthHeight(T_SPS *ptSps, int *piWidth, int *piHeight);
void h264GeFramerate(T_SPS *ptSps, float *pfFramerate);
#if defined (__cplusplus)
}
#endif
#endif
// 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.
#include "h264_bit_reader.h"
#include "macros.h"
namespace media {
H264BitReader::H264BitReader()
: data_(NULL),
bytes_left_(0),
curr_byte_(0),
num_remaining_bits_in_curr_byte_(0),
prev_two_bytes_(0),
emulation_prevention_bytes_(0) {}
H264BitReader::~H264BitReader() {}
bool H264BitReader::Initialize(const uint8_t* data, off_t size) {
DCHECK(data);
if (size < 1)
return false;
data_ = data;
bytes_left_ = size;
num_remaining_bits_in_curr_byte_ = 0;
// Initially set to 0xffff to accept all initial two-byte sequences.
prev_two_bytes_ = 0xffff;
emulation_prevention_bytes_ = 0;
return true;
}
bool H264BitReader::UpdateCurrByte() {
if (bytes_left_ < 1)
return false;
// Emulation prevention three-byte detection.
// If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03).
if (*data_ == 0x03 && (prev_two_bytes_ & 0xffff) == 0) {
// Detected 0x000003, skip last byte.
++data_;
--bytes_left_;
++emulation_prevention_bytes_;
// Need another full three bytes before we can detect the sequence again.
prev_two_bytes_ = 0xffff;
if (bytes_left_ < 1)
return false;
}
// Load a new byte and advance pointers.
curr_byte_ = *data_++ & 0xff;
--bytes_left_;
num_remaining_bits_in_curr_byte_ = 8;
prev_two_bytes_ = ((prev_two_bytes_ & 0xff) << 8) | curr_byte_;
return true;
}
// Read |num_bits| (1 to 31 inclusive) from the stream and return them
// in |out|, with first bit in the stream as MSB in |out| at position
// (|num_bits| - 1).
bool H264BitReader::ReadBits(int num_bits, int* out) {
int bits_left = num_bits;
*out = 0;
DCHECK(num_bits <= 31);
while (num_remaining_bits_in_curr_byte_ < bits_left) {
// Take all that's left in current byte, shift to make space for the rest.
*out |= (curr_byte_ << (bits_left - num_remaining_bits_in_curr_byte_));
bits_left -= num_remaining_bits_in_curr_byte_;
if (!UpdateCurrByte())
return false;
}
*out |= (curr_byte_ >> (num_remaining_bits_in_curr_byte_ - bits_left));
*out &= ((1u << num_bits) - 1u);
num_remaining_bits_in_curr_byte_ -= bits_left;
return true;
}
off_t H264BitReader::NumBitsLeft() {
return (num_remaining_bits_in_curr_byte_ + bytes_left_ * 8);
}
bool H264BitReader::HasMoreRBSPData() {
// Make sure we have more bits, if we are at 0 bits in current byte and
// updating current byte fails, we don't have more data anyway.
if (num_remaining_bits_in_curr_byte_ == 0 && !UpdateCurrByte())
return false;
// If there is no more RBSP data, then |curr_byte_| contains the stop bit and
// zero padding. Check to see if there is other data instead.
// (We don't actually check for the stop bit itself, instead treating the
// invalid case of all trailing zeros identically).
if ((curr_byte_ & ((1 << (num_remaining_bits_in_curr_byte_ - 1)) - 1)) != 0)
return true;
// While the spec disallows it (7.4.1: "The last byte of the NAL unit shall
// not be equal to 0x00"), some streams have trailing null bytes anyway. We
// don't handle emulation prevention sequences because HasMoreRBSPData() is
// not used when parsing slices (where cabac_zero_word elements are legal).
for (off_t i = 0; i < bytes_left_; i++) {
if (data_[i] != 0)
return true;
}
bytes_left_ = 0;
return false;
}
size_t H264BitReader::NumEmulationPreventionBytesRead() {
return emulation_prevention_bytes_;
}
} // namespace media
// 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.
//
// This file contains an implementation of an H264 Annex-B video stream parser.
#ifndef MEDIA_FILTERS_H264_BIT_READER_H_
#define MEDIA_FILTERS_H264_BIT_READER_H_
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include "macros.h"
using namespace std;
namespace media {
// A class to provide bit-granularity reading of H.264 streams.
// This is not a generic bit reader class, as it takes into account
// H.264 stream-specific constraints, such as skipping emulation-prevention
// bytes and stop bits. See spec for more details.
class MEDIA_EXPORT H264BitReader {
public:
H264BitReader();
~H264BitReader();
// Initialize the reader to start reading at |data|, |size| being size
// of |data| in bytes.
// Return false on insufficient size of stream..
// TODO(posciak,fischman): consider replacing Initialize() with
// heap-allocating and creating bit readers on demand instead.
bool Initialize(const uint8_t* data, off_t size);
// Read |num_bits| next bits from stream and return in |*out|, first bit
// from the stream starting at |num_bits| position in |*out|.
// |num_bits| may be 1-32, inclusive.
// Return false if the given number of bits cannot be read (not enough
// bits in the stream), true otherwise.
bool ReadBits(int num_bits, int* out);
// Return the number of bits left in the stream.
off_t NumBitsLeft();
// See the definition of more_rbsp_data() in spec.
bool HasMoreRBSPData();
// Return the number of emulation prevention bytes already read.
size_t NumEmulationPreventionBytesRead();
private:
// Advance to the next byte, loading it into curr_byte_.
// Return false on end of stream.
bool UpdateCurrByte();
// Pointer to the next unread (not in curr_byte_) byte in the stream.
const uint8_t* data_;
// Bytes left in the stream (without the curr_byte_).
off_t bytes_left_;
// Contents of the current byte; first unread bit starting at position
// 8 - num_remaining_bits_in_curr_byte_ from MSB.
int curr_byte_;
// Number of bits remaining in curr_byte_
int num_remaining_bits_in_curr_byte_;
// Used in emulation prevention three byte detection (see spec).
// Initially set to 0xffff to accept all initial two-byte sequences.
int prev_two_bytes_;
// Number of emulation preventation bytes (0x000003) we met.
size_t emulation_prevention_bytes_;
DISALLOW_COPY_AND_ASSIGN(H264BitReader);
};
} // namespace media
#endif // MEDIA_FILTERS_H264_BIT_READER_H_
// 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.
#ifndef MEDIA_VIDEO_H264_POC_H_
#define MEDIA_VIDEO_H264_POC_H_
#include <stdint.h>
#include "macros.h"
using namespace std;
namespace media {
struct H264SPS;
struct H264SliceHeader;
class MEDIA_EXPORT H264POC {
public:
H264POC();
~H264POC();
// Compute the picture order count for a slice, storing the result into
// |*pic_order_cnt|.
bool ComputePicOrderCnt(
const H264SPS* sps,
const H264SliceHeader& slice_hdr,
int32_t* pic_order_cnt);
// Reset computation state. It's best (although not strictly required) to call
// this after a seek.
void Reset();
private:
int32_t ref_pic_order_cnt_msb_;
int32_t ref_pic_order_cnt_lsb_;
int32_t prev_frame_num_;
int32_t prev_frame_num_offset_;
DISALLOW_COPY_AND_ASSIGN(H264POC);
};
} // namespace media
#endif // MEDIA_VIDEO_H264_POC_H_
// 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.
// This file contains macros and macro-like constructs (e.g., templates) that
// are commonly used throughout Chromium source. (It may also contain things
// that are closely related to things that are commonly used that belong in this
// file.)
#ifndef BASE_MACROS_H_
#define BASE_MACROS_H_
#include <stddef.h> // For size_t.
// Put this in the declarations for a class to be uncopyable.
#define DISALLOW_COPY(TypeName) \
TypeName(const TypeName&) = delete
// Put this in the declarations for a class to be unassignable.
#define DISALLOW_ASSIGN(TypeName) \
void operator=(const TypeName&) = delete
// A macro to disallow the copy constructor and operator= functions.
// This should be used in the private: declarations for a class.
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName() = delete; \
DISALLOW_COPY_AND_ASSIGN(TypeName)
// The arraysize(arr) macro returns the # of elements in an array arr. The
// expression is a compile-time constant, and therefore can be used in defining
// new arrays, for example. If you use arraysize on a pointer by mistake, you
// will get a compile-time error. For the technical details, refer to
// http://blogs.msdn.com/b/the1/archive/2004/05/07/128242.aspx.
// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
// Used to explicitly mark the return value of a function as unused. If you are
// really sure you don't want to do anything with the return value of a function
// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example:
//
// std::unique_ptr<MyType> my_var = ...;
// if (TakeOwnership(my_var.get()) == SUCCESS)
// ignore_result(my_var.release());
//
template<typename T>
inline void ignore_result(const T&) {
}
// The following enum should be used only as a constructor argument to indicate
// that the variable has static storage class, and that the constructor should
// do nothing to its state. It indicates to the reader that it is legal to
// declare a static instance of the class, provided the constructor is given
// the base::LINKER_INITIALIZED argument. Normally, it is unsafe to declare a
// static variable that has a constructor or a destructor because invocation
// order is undefined. However, IF the type can be initialized by filling with
// zeroes (which the loader does for static variables), AND the destructor also
// does nothing to the storage, AND there are no virtual methods, then a
// constructor declared as
// explicit MyClass(base::LinkerInitialized x) {}
// and invoked as
// static MyClass my_variable_name(base::LINKER_INITIALIZED);
namespace base {
enum LinkerInitialized { LINKER_INITIALIZED };
// Use these to declare and define a static local variable (static T;) so that
// it is leaked so that its destructors are not called at exit. If you need
// thread-safe initialization, use base/lazy_instance.h instead.
#define CR_DEFINE_STATIC_LOCAL(type, name, arguments) \
static type& name = *new type arguments
} // base
#define MEDIA_EXPORT
#include <assert.h>
#include "Util/logger.h"
using namespace ZL::Util;
#define DCHECK(x) if(!(x)) { ErrorL << "DCHECK " << #x <<endl; }
#define DCHECK_GT(x,y) if(!((x) > (y))) { ErrorL << "DCHECK_GT:" << #x << #y << endl; }
#define DCHECK_GE(x,y) if(!((x) >= (y))) { ErrorL << "DCHECK_GE:" << #x << #y << endl; }
#define DCHECK_LT(x,y) if(!((x) < (y))) { ErrorL << "DCHECK_LT:" << #x << #y << endl; }
#define NOTREACHED() ErrorL << "NOTREACHED" << endl;
#endif // BASE_MACROS_H_
//
// ranges.cpp
// MediaPlayer
//
// Created by xzl on 2017/1/13.
// Copyright © 2017年 jizan. All rights reserved.
//
#include "ranges.h"
// 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.
#ifndef MEDIA_BASE_RANGES_H_
#define MEDIA_BASE_RANGES_H_
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <ostream>
#include <vector>
using namespace std;
namespace media {
// Ranges allows holding an ordered list of ranges of [start,end) intervals.
// The canonical example use-case is holding the list of ranges of buffered
// bytes or times in a <video> tag.
template <typename T> // Endpoint type; typically a base::TimeDelta or an int64_t.
class Ranges {
public:
// Allow copy & assign.
// Add (start,end) to this object, coallescing overlaps as appropriate.
// Returns the number of stored ranges, post coallescing.
size_t Add(T start, T end);
// Return the number of disjoint ranges.
size_t size() const;
// Return the "i"'th range's start & end (0-based).
T start(size_t i) const;
T end(size_t i) const;
// Clear all ranges.
void clear();
// Computes the intersection between this range and |other|.
Ranges<T> IntersectionWith(const Ranges<T>& other) const;
private:
// Wrapper around DCHECK_LT allowing comparisons of operator<<'able T's.
void DCheckLT(const T& lhs, const T& rhs) const;
// Disjoint, in increasing order of start.
std::vector<std::pair<T, T> > ranges_;
};
//////////////////////////////////////////////////////////////////////
// EVERYTHING BELOW HERE IS IMPLEMENTATION DETAIL!!
//////////////////////////////////////////////////////////////////////
template<class T>
size_t Ranges<T>::Add(T start, T end) {
if (start == end) // Nothing to be done with empty ranges.
return ranges_.size();
//DCheckLT(start, end);
size_t i;
// Walk along the array of ranges until |start| is no longer larger than the
// current interval's end.
for (i = 0; i < ranges_.size() && ranges_[i].second < start; ++i) {
// Empty body
}
// Now we know |start| belongs in the i'th slot.
// If i is the end of the range, append new range and done.
if (i == ranges_.size()) {
ranges_.push_back(std::make_pair(start, end));
return ranges_.size();
}
// If |end| is less than i->first, then [start,end) is a new (non-overlapping)
// i'th entry pushing everyone else back, and done.
if (end < ranges_[i].first) {
ranges_.insert(ranges_.begin() + i, std::make_pair(start, end));
return ranges_.size();
}
// Easy cases done. Getting here means there is overlap between [start,end)
// and the existing ranges.
// Now: start <= i->second && i->first <= end
if (start < ranges_[i].first)
ranges_[i].first = start;
if (ranges_[i].second < end)
ranges_[i].second = end;
// Now: [start,end) is contained in the i'th range, and we'd be done, except
// for the fact that the newly-extended i'th range might now overlap
// subsequent ranges. Merge until discontinuities appear. Note that there's
// no need to test/merge previous ranges, since needing that would mean the
// 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_.erase(ranges_.begin() + i + 1);
}
return ranges_.size();
}
template<class T>
size_t Ranges<T>::size() const {
return ranges_.size();
}
template<class T>
T Ranges<T>::start(size_t i) const {
return ranges_[i].first;
}
template<class T>
T Ranges<T>::end(size_t i) const {
return ranges_[i].second;
}
template<class T>
void Ranges<T>::clear() {
ranges_.clear();
}
template<class T>
Ranges<T> Ranges<T>::IntersectionWith(const Ranges<T>& other) const {
Ranges<T> result;
size_t i = 0;
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));
// Add an intersection range to the result if the ranges overlap.
if (max_start < min_end)
result.Add(max_start, min_end);
if (end(i) < other.end(j))
++i;
else
++j;
}
return result;
}
} // namespace media
#endif // MEDIA_BASE_RANGES_H_
/*
* HttpSession.h
*
* Created on: 2016年9月22日
* Author: xzl
*/
#ifndef SRC_HTTP_HTTPSESSION_H_
#define SRC_HTTP_HTTPSESSION_H_
#include "config.h"
#include "Rtsp/Rtsp.h"
#include "Network/TcpLimitedSession.h"
using namespace std;
using namespace ZL::Network;
namespace ZL {
namespace Http {
class HttpSession: public TcpLimitedSession<MAX_TCP_SESSION> {
public:
typedef map<string,string> KeyValue;
HttpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock);
virtual ~HttpSession();
void onRecv(const Socket::Buffer::Ptr &) override;
void onError(const SockException &err) override;
void onManager() override;
private:
typedef int (HttpSession::*HttpCMDHandle)();
static unordered_map<string, HttpCMDHandle> g_mapCmdIndex;
Parser m_parser;
string m_strPath;
string m_strRcvBuf;
Ticker m_ticker;
uint32_t m_iReqCnt = 0;
inline int parserHttpReq(const string &);
inline int Handle_Req_GET();
inline int Handle_Req_POST();
inline bool makeMeun(const string &strFullPath, string &strRet);
inline void sendNotFound(bool bClose);
inline void sendResponse(const char *pcStatus,const KeyValue &header,const string &strContent);
inline KeyValue makeHttpHeader(bool bClose=false,int64_t iContentSize=-1,const char *pcContentType="text/html");
};
} /* namespace Http */
} /* namespace ZL */
#endif /* SRC_HTTP_HTTPSESSION_H_ */
/*
* strCoding.cpp
*
* Created on: 2016年9月22日
* Author: xzl
*/
#include "strCoding.h"
#include <string.h>
namespace ZL {
namespace Http {
inline char strCoding::CharToInt(char ch) {
if (ch >= '0' && ch <= '9')
return (char) (ch - '0');
if (ch >= 'a' && ch <= 'f')
return (char) (ch - 'a' + 10);
if (ch >= 'A' && ch <= 'F')
return (char) (ch - 'A' + 10);
return -1;
}
inline char strCoding::StrToBin(const char *str) {
char tempWord[2];
char chn;
tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011
tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000
chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000
return chn;
}
string strCoding::UrlUTF8Encode(const char * str) {
string dd;
size_t len = strlen(str);
for (size_t i = 0; i < len; i++) {
if (isalnum((uint8_t) str[i])) {
char tempbuff[2];
sprintf(tempbuff, "%c", str[i]);
dd.append(tempbuff);
} else if (isspace((uint8_t) str[i])) {
dd.append("+");
} else {
char tempbuff[4];
sprintf(tempbuff, "%%%X%X", ((uint8_t*) str)[i] >> 4,
((uint8_t*) str)[i] % 16);
dd.append(tempbuff);
}
}
return dd;
}
string strCoding::UrlUTF8Decode(const string &str) {
string output = "";
char tmp[2];
int i = 0, len = str.length();
while (i < len) {
if (str[i] == '%') {
tmp[0] = str[i + 1];
tmp[1] = str[i + 2];
output += StrToBin(tmp);
i = i + 3;
} else if (str[i] == '+') {
output += ' ';
i++;
} else {
output += str[i];
i++;
}
}
return output;
}
} /* namespace Http */
} /* namespace ZL */
/*
* strCoding.h
*
* Created on: 2016年9月22日
* Author: xzl
*/
#ifndef SRC_HTTP_STRCODING_H_
#define SRC_HTTP_STRCODING_H_
#include <iostream>
#include <string>
#ifdef _WINDOWS
#include <windows.h>
#endif
using namespace std;
namespace ZL {
namespace Http {
class strCoding {
public:
static string UrlUTF8Encode(const char * str); //urlutf8 编码
static string UrlUTF8Decode(const string &str); //urlutf8解码
private:
strCoding(void);
virtual ~strCoding(void);
static inline char CharToInt(char ch);
static inline char StrToBin(const char *str);
};
} /* namespace Http */
} /* namespace ZL */
#endif /* SRC_HTTP_STRCODING_H_ */
/*
* crc32.cpp
*
* Created on: 2013-9-11
* Author: root
*/
/*
* crc32.h
*
* Created on: 2013-6-21
* Author: root
*/
#include "crc32.h"
#define BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff))
#define BSWAP32C(x) (BSWAP16C(x) << 16 | BSWAP16C((x) >> 16))
#define BSWAP64C(x) (BSWAP32C(x) << 32 | BSWAP32C((x) >> 32))
static const unsigned int crc_tab[256] = {
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};
unsigned int calc_crc32 (unsigned char *data, unsigned int datalen)
{
unsigned int i;
unsigned int crc = 0xffffffff;
for (i=0; i<datalen; i++)
{
crc = (crc << 8) ^ crc_tab[((crc >> 24) ^ *data++) & 0xff];
}
return crc;
}
unsigned int Zwg_ntohl(unsigned int s)
{
union
{
int i;
char buf;
}a;
a.i = 0x01;
if(a.buf)
{
// 小端
s = BSWAP32C(s);
}
return s;
}
/*
* crc32.h
*
* Created on: 2013-6-21
* Author: root
*/
#ifndef CRC32_H_
#define CRC32_H_
unsigned int calc_crc32 (unsigned char *data, unsigned int datalen);
unsigned int Zwg_ntohl(unsigned int s);
#endif /* CRC32_H_ */
/*
* HLSMaker.cpp
*
* Created on: 2013-6-24
* Author: root
*/
#include "HLSMaker.h"
#include <sys/time.h>
namespace ZL {
namespace MediaFile {
HLSMaker::HLSMaker(const string& strM3u8File, const string& strHttpUrl,
uint32_t ui32BufSize, uint32_t ui32Duration, uint32_t ui32Num) {
if (ui32BufSize < 16 * 1024) {
ui32BufSize = 16 * 1024;
}
m_ui32BufSize = ui32BufSize;
if (ui32Duration < 5) {
ui32Duration = 5;
}
if (ui32Num < 2) {
ui32Num = 2;
}
m_ui64TsCnt = 0;
m_strM3u8File = strM3u8File;
m_strHttpUrl = strHttpUrl.substr(0, strHttpUrl.find_last_of('/') + 1);
m_ui32NumSegments = ui32Num;
m_ui32SegmentDuration = ui32Duration;
m_strOutputPrefix = strM3u8File.substr(0, strM3u8File.find_last_of('.'));
m_strFileName = m_strOutputPrefix.substr(m_strOutputPrefix.find_last_of('/') + 1);
m_strTmpFileName = m_strOutputPrefix + "-0.ts";
m_ts.init(m_strTmpFileName, m_ui32BufSize);
}
HLSMaker::~HLSMaker() {
m_ts.clear();
string strDir = m_strOutputPrefix.substr(0,m_strOutputPrefix.find_last_of('/'));
File::delete_file(strDir.data());
}
int HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment,
int iEnd) {
FILE *pIndexFp;
char *pcWriteBuf;
const char *pcTmpM3u8File = (m_strM3u8File).c_str();
pIndexFp = File::createfile_file(pcTmpM3u8File, "w");
if (pIndexFp == NULL) {
return -1;
}
if (iFirstSegment < 0) {
iFirstSegment = 0;
}
if (!pIndexFp) {
WarnL << "Could not open temporary m3u8 index file (" << pcTmpM3u8File
<< "), no index file will be created";
return -1;
}
pcWriteBuf = (char *) malloc(sizeof(char) * 1024);
if (!pcWriteBuf) {
WarnL << "Could not allocate write buffer for index file, index file will be invalid";
fclose(pIndexFp);
return -1;
}
if (m_ui32NumSegments) {
snprintf(pcWriteBuf, 1024,
"#EXTM3U\n#EXT-X-TARGETDURATION:%u\n#EXT-X-MEDIA-SEQUENCE:%u\n",
m_ui32SegmentDuration, iFirstSegment);
} else {
snprintf(pcWriteBuf, 1024, "#EXTM3U\n#EXT-X-TARGETDURATION:%u\n",
m_ui32SegmentDuration);
}
if (fwrite(pcWriteBuf, strlen(pcWriteBuf), 1, pIndexFp) != 1) {
WarnL << "Could not write to m3u8 index file, will not continue writing to index file";
free(pcWriteBuf);
fclose(pIndexFp);
return -1;
}
for (unsigned int i = iFirstSegment; i < uiLastSegment; i++) {
snprintf(pcWriteBuf, 1024, "#EXTINF:%u,\n%s%s-%u.ts\n",
m_ui32SegmentDuration, m_strHttpUrl.c_str(),
m_strFileName.c_str(), i);
//printf(options.output_prefix);
if (fwrite(pcWriteBuf, strlen(pcWriteBuf), 1, pIndexFp) != 1) {
WarnL << "Could not write to m3u8 index file, will not continue writing to index file";
free(pcWriteBuf);
fclose(pIndexFp);
return -1;
}
}
if (iEnd) {
snprintf(pcWriteBuf, 1024, "#EXT-X-ENDLIST\n");
if (fwrite(pcWriteBuf, strlen(pcWriteBuf), 1, pIndexFp) != 1) {
WarnL << "Could not write last file and endlist tag to m3u8 index file";
free(pcWriteBuf);
fclose(pIndexFp);
return -1;
}
}
free(pcWriteBuf);
fclose(pIndexFp);
return 1;
}
void HLSMaker::inputH264(void *data, uint32_t length, uint32_t timeStamp,
int type) {
switch (type) {
case 7: //SPS
if (m_Timer.elapsedTime() >= m_ui32SegmentDuration * 1000) {
m_ts.clear();
m_strTmpFileName = StrPrinter << m_strOutputPrefix << '-' << (++m_ui64TsCnt) << ".ts" << endl;
if (!m_ts.init(m_strTmpFileName, m_ui32BufSize)) {
//创建文件失败
return;
}
m_Timer.resetTime();
removets();
if (write_index_file(m_ui64TsCnt - m_ui32NumSegments, m_ui64TsCnt, 0) == -1) {
WarnL << "write_index_file error :" << strerror(errno);
}
}
case 1: //P
//insert aud frame before p and SPS frame
m_ts.inputH264("\x0\x0\x0\x1\x9\xf0", 6, timeStamp);
case 5: //IDR
case 8: //PPS
m_ts.inputH264((char *) data, length, timeStamp);
break;
default:
break;
}
}
void HLSMaker::inputAAC(void *data, uint32_t length, uint32_t timeStamp) {
m_ts.inputAAC((char *) data, length, timeStamp);
}
void HLSMaker::removets() {
if (m_ui64TsCnt <= m_ui32NumSegments) {
return;
}
File::delete_file( (StrPrinter << m_strOutputPrefix << "-"
<< m_ui64TsCnt - m_ui32NumSegments - 1
<< ".ts" << endl).data());
}
} /* namespace MediaFile */
} /* namespace ZL */
/*
* HLSMaker.h
*
* Created on: 2013-6-24
* Author: root
*/
#ifndef HLSMAKER_H_
#define HLSMAKER_H_
#include "TSMaker.h"
#include "Util/TimeTicker.h"
#include "Util/File.h"
#include "Util/util.h"
#include "Util/logger.h"
#include "config.h"
using namespace ZL::Util;
namespace ZL {
namespace MediaFile {
class HLSMaker {
public:
HLSMaker(const string &strM3u8File,
const string &strHttpUrl,
uint32_t ui32BufSize = 64 * 1024,
uint32_t ui32Duration = 5,
uint32_t ui32Num = 3);
virtual ~HLSMaker();
//时间戳:参考频率90000
void inputH264( void *pData,
uint32_t ui32Length,
uint32_t ui32TimeStamp,
int iType);
//时间戳:参考频率90000
void inputAAC( void *pData,
uint32_t ui32Length,
uint32_t ui32TimeStamp);
private:
TSMaker m_ts;
string m_strM3u8File;
string m_strHttpUrl;
string m_strFileName;
string m_strOutputPrefix;
string m_strTmpFileName;
uint32_t m_ui32SegmentDuration;
uint32_t m_ui32NumSegments;
uint64_t m_ui64TsCnt;
uint32_t m_ui32BufSize;
Ticker m_Timer;
int write_index_file(int iFirstSegment, unsigned int uiLastSegment, int iEnd);
void removets();
};
} /* namespace MediaFile */
} /* namespace ZL */
#endif /* HLSMAKER_H_ */
/*
* MediaReader.h
*
* Created on: 2016年12月14日
* Author: xzl
*/
#ifndef SRC_MEDAIFILE_MEDIAREADER_H_
#define SRC_MEDAIFILE_MEDIAREADER_H_
#include "Rtsp/RtspMediaSource.h"
#include "Rtmp/RtmpMediaSource.h"
#include "Device/Device.h"
#ifdef ENABLE_MEDIAFILE
#include <mp4v2/mp4v2.h>
#endif //ENABLE_MEDIAFILE
using namespace ZL::DEV;
using namespace ZL::Rtsp;
using namespace ZL::Rtmp;
namespace ZL {
namespace MediaFile {
class MediaReader : public std::enable_shared_from_this<MediaReader>{
public:
typedef std::shared_ptr<MediaReader> Ptr;
MediaReader(const string &strApp, const string &strId);
virtual ~MediaReader();
static RtspMediaSource::Ptr onMakeRtsp(const string &strApp, const string &strId);
static RtmpMediaSource::Ptr onMakeRtmp(const string &strApp, const string &strId);
private:
#ifdef ENABLE_MEDIAFILE
MP4FileHandle m_hMP4File = MP4_INVALID_FILE_HANDLE;
MP4TrackId m_video_trId = MP4_INVALID_TRACK_ID;
uint32_t m_video_ms = 0;
uint32_t m_video_num_samples = 0;
uint32_t m_video_sample_max_size = 0;
uint32_t m_video_width = 0;
uint32_t m_video_height = 0;
uint32_t m_video_framerate = 0;
string m_strPps;
string m_strSps;
bool m_bSyncSample = false;
MP4TrackId m_audio_trId = MP4_INVALID_TRACK_ID;
uint32_t m_audio_ms = 0;
uint32_t m_audio_num_samples = 0;
uint32_t m_audio_sample_max_size = 0;
uint32_t m_audio_sample_rate = 0;
uint32_t m_audio_num_channels = 0;
string m_strAacCfg;
AdtsFrame m_adts;
int m_iDuration = 0;
DevChannel::Ptr m_pChn;
MP4SampleId m_video_current = 0;
MP4SampleId m_audio_current = 0;
std::shared_ptr<uint8_t> m_pcVideoSample;
int m_iSeekTime = 0 ;
Ticker m_ticker;
Ticker m_alive;
recursive_mutex m_mtx;
void seek(int iSeekTime,bool bReStart = true);
inline void setSeekTime(int iSeekTime);
inline uint32_t getVideoCurrentTime();
void startReadMP4();
inline MP4SampleId getVideoSampleId(int iTimeInc = 0);
inline MP4SampleId getAudioSampleId(int iTimeInc = 0);
bool readSample(int iTimeInc = 0);
inline bool readVideoSample(int iTimeInc = 0);
inline bool readAudioSample(int iTimeInc = 0);
inline void writeH264(uint8_t *pucData,int iLen,uint32_t uiStamp);
inline void writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp);
#endif
};
} /* namespace MediaFile */
} /* namespace ZL */
#endif /* SRC_MEDAIFILE_MEDIAREADER_H_ */
/*
* MediaRecorder.cpp
*
* Created on: 2016年12月8日
* Author: xzl
*/
#include "config.h"
#include "Network/sockutil.h"
#include "MediaRecorder.h"
#include "Util/util.h"
#include "Http/HttpSession.h"
#include "config.h"
#include "Util/mini.hpp"
using namespace ZL::Util;
using namespace ZL::Network;
namespace ZL {
namespace MediaFile {
MediaRecorder::MediaRecorder(const string &strApp,const string &strId,const std::shared_ptr<PlayerBase> &pPlayer) {
#ifdef ENABLE_MEDIAFILE
static string hlsPrefix = mINI::Instance()[Config::Hls::kHttpPrefix];
static string hlsPath = mINI::Instance()[Config::Hls::kFilePath];
static uint32_t hlsBufSize = mINI::Instance()[Config::Hls::kFileBufSize].as<uint32_t>();
static uint32_t hlsDuration = mINI::Instance()[Config::Hls::kSegmentDuration].as<uint32_t>();
static uint32_t hlsNum = mINI::Instance()[Config::Hls::kSegmentNum].as<uint32_t>();
static string recordPath = mINI::Instance()[Config::Record::kFilePath];
static string recordAppName = mINI::Instance()[Config::Record::kAppName];
m_hlsMaker.reset(new HLSMaker(hlsPath + "/" + strApp + "/" + strId + "/hls.m3u8",
hlsPrefix + "/" + strApp + "/" + strId + "/",
hlsBufSize,hlsDuration,hlsNum));
m_mp4Maker.reset(new Mp4Maker(recordPath + "/" + recordAppName + "/" + strApp + "/" + strId + "/",
strApp,strId,pPlayer));
#endif //ENABLE_MEDIAFILE
}
MediaRecorder::~MediaRecorder() {
}
void MediaRecorder::inputH264(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType) {
#ifdef ENABLE_MEDIAFILE
m_hlsMaker->inputH264(pData, ui32Length, ui32TimeStamp * 90, iType);
m_mp4Maker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
#endif //ENABLE_MEDIAFILE
}
void MediaRecorder::inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp) {
#ifdef ENABLE_MEDIAFILE
m_hlsMaker->inputAAC(pData, ui32Length, ui32TimeStamp * 90);
m_mp4Maker->inputAAC(pData, ui32Length, ui32TimeStamp);
#endif //ENABLE_MEDIAFILE
}
} /* namespace MediaFile */
} /* namespace ZL */
/*
* MediaRecorder.h
*
* Created on: 2016年12月8日
* Author: xzl
*/
#ifndef SRC_MEDAIFILE_MEDIARECORDER_H_
#define SRC_MEDAIFILE_MEDIARECORDER_H_
#include "Player/PlayerBase.h"
#include <memory>
#ifdef ENABLE_MEDIAFILE
#include "Mp4Maker.h"
#include "HLSMaker.h"
#endif //ENABLE_MEDIAFILE
using namespace std;
using namespace ZL::Player;
namespace ZL {
namespace MediaFile {
class MediaRecorder {
public:
typedef std::shared_ptr<MediaRecorder> Ptr;
MediaRecorder(const string &strApp,const string &strId,const std::shared_ptr<PlayerBase> &pPlayer);
virtual ~MediaRecorder();
void inputH264( void *pData,
uint32_t ui32Length,
uint32_t ui32TimeStamp,
int iType);
void inputAAC( void *pData,
uint32_t ui32Length,
uint32_t ui32TimeStamp);
private:
#ifdef ENABLE_MEDIAFILE
std::shared_ptr<HLSMaker> m_hlsMaker;
std::shared_ptr<Mp4Maker> m_mp4Maker;
#endif //ENABLE_MEDIAFILE
};
} /* namespace MediaFile */
} /* namespace ZL */
#endif /* SRC_MEDAIFILE_MEDIARECORDER_H_ */
#ifdef ENABLE_MEDIAFILE
#include "MediaRecorder.h"
#include <netinet/in.h>
#include <sys/stat.h>
#include "Util/File.h"
#include "Mp4Maker.h"
#include "Util/NoticeCenter.h"
#include "config.h"
#include "Util/mini.hpp"
using namespace ZL::Util;
namespace ZL {
namespace MediaFile {
string timeStr(const char *fmt) {
std::tm tm_snapshot;
auto time = ::time(NULL);
#if defined(WIN32)
localtime_s(&tm_snapshot, &time); // thread-safe?
std::ostringstream oss;
oss << std::put_time(const_cast<std::tm*>(&tm_snapshot), fmt);
return oss.str();
#else
localtime_r(&time, &tm_snapshot); // POSIX
const size_t size = 1024;
char buffer[size];
auto success = std::strftime(buffer, size, fmt, &tm_snapshot);
if (0 == success)
return string(fmt);
return buffer;
#endif
}
Mp4Maker::Mp4Maker(const string& strPath,const string &strApp,const string &strStreamId, const PlayerBase::Ptr &pPlayer) {
DebugL << strPath;
m_pPlayer = pPlayer;
m_strPath = strPath;
/////record 业务逻辑//////
m_info.strAppName = strApp;
m_info.strStreamId = strStreamId;
m_info.strFolder = strPath;
//----record 业务逻辑----//
}
Mp4Maker::~Mp4Maker() {
closeFile();
}
void Mp4Maker::inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType){
switch (iType) {
case 1: //P
case 5: { //IDR
if (m_strLastVideo.size()) {
_inputH264((char *) m_strLastVideo.data(), m_strLastVideo.size(), ui32TimeStamp - m_ui32LastVideoTime, m_iLastVideoType);
}
//m_strLastVideo.assign(("\x0\x0\x0\x2\x9\xf0"), 6);
uint32_t *p = (uint32_t *) pData;
*p = htonl(ui32Length - 4);
m_strLastVideo.assign((char *) pData, ui32Length);
memcpy(pData, "\x00\x00\x00\x01", 4);
m_ui32LastVideoTime = ui32TimeStamp;
m_iLastVideoType = iType;
}
break;
default:
break;
}
}
void Mp4Maker::inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp){
if (m_strLastAudio.size()) {
_inputAAC((char *)m_strLastAudio.data(), m_strLastAudio.size(), ui32TimeStamp - m_ui32LastAudioTime);
}
m_strLastAudio.assign((char *)pData, ui32Length);
m_ui32LastAudioTime = ui32TimeStamp;
}
void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duration, int iType) {
static uint32_t recordMS = 1000 * mINI::Instance()[Config::Record::kFileSecond].as<uint32_t>();
if(iType == 5 && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordMS)){
//在I帧率处新建MP4文件
//如果文件未创建或者文件超过10分钟则创建新文件
createFile();
}
if (m_hVideo != MP4_INVALID_TRACK_ID) {
MP4WriteSample(m_hMp4, m_hVideo, (uint8_t *) pData, ui32Length,ui32Duration * 90,0,iType == 5);
}
}
void Mp4Maker::_inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32Duration) {
static uint32_t recordMS = 1000 * mINI::Instance()[Config::Record::kFileSecond].as<uint32_t>();
if (!m_pPlayer->containVideo() && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordMS)) {
//在I帧率处新建MP4文件
//如果文件未创建或者文件超过10分钟则创建新文件
createFile();
}
if (m_hAudio != MP4_INVALID_TRACK_ID) {
auto duration = ui32Duration * m_pPlayer->getAudioSampleRate() /1000.0;
MP4WriteSample(m_hMp4, m_hAudio, (uint8_t*)pData + 7, ui32Length - 7,duration,0,false);
}
}
void Mp4Maker::createFile() {
if(!m_pPlayer->isInited()){
return;
}
closeFile();
auto strDate = timeStr("%Y-%m-%d");
auto strTime = timeStr("%H-%M-%S");
auto strFileTmp = m_strPath + strDate + "/." + strTime + ".mp4";
auto strFile = m_strPath + strDate + "/" + strTime + ".mp4";
/////record 业务逻辑//////
m_info.ui64StartedTime = ::time(NULL);
m_info.strFileName = strTime + ".mp4";
m_info.strFilePath = strFile;
static string appName = mINI::Instance()[Config::Record::kAppName];
m_info.strUrl = appName + "/"
+ m_info.strAppName + "/"
+ m_info.strStreamId + "/"
+ strDate + "/"
+ strTime + ".mp4";
//----record 业务逻辑----//
File::createfile_path(strFileTmp.data(), S_IRWXO | S_IRWXG | S_IRWXU);
m_hMp4 = MP4Create(strFileTmp.data());
if (m_hMp4 == MP4_INVALID_FILE_HANDLE) {
WarnL << "创建MP4文件失败:" << strFileTmp;
return;
}
//MP4SetTimeScale(m_hMp4, 90000);
m_strFileTmp = strFileTmp;
m_strFile = strFile;
m_ticker.resetTime();
if(m_pPlayer->containVideo()){
auto &sps = m_pPlayer->getSps();
auto &pps = m_pPlayer->getPps();
m_hVideo = MP4AddH264VideoTrack(m_hMp4, 90000, MP4_INVALID_DURATION,
m_pPlayer->getVideoWidth(), m_pPlayer->getVideoHeight(),
sps[5], sps[6], sps[7], 3);
if(m_hVideo !=MP4_INVALID_TRACK_ID){
MP4AddH264SequenceParameterSet(m_hMp4, m_hVideo, (uint8_t *)sps.data() + 4, sps.size() - 4);
MP4AddH264PictureParameterSet(m_hMp4, m_hVideo, (uint8_t *)pps.data() + 4, pps.size() - 4);
}else{
WarnL << "添加视频通道失败:" << strFileTmp;
}
}
if(m_pPlayer->containAudio()){
m_hAudio = MP4AddAudioTrack(m_hMp4, m_pPlayer->getAudioSampleRate(), MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
if (m_hAudio != MP4_INVALID_TRACK_ID) {
auto &cfg = m_pPlayer->getAudioCfg();
MP4SetTrackESConfiguration(m_hMp4, m_hAudio,(uint8_t *)cfg.data(), cfg.size());
}else{
WarnL << "添加音频通道失败:" << strFileTmp;
}
}
}
void Mp4Maker::closeFile() {
if (m_hMp4 != MP4_INVALID_FILE_HANDLE) {
{
TimeTicker();
MP4Close(m_hMp4,MP4_CLOSE_DO_NOT_COMPUTE_BITRATE);
}
rename(m_strFileTmp.data(),m_strFile.data());
m_hMp4 = MP4_INVALID_FILE_HANDLE;
m_hVideo = MP4_INVALID_TRACK_ID;
m_hAudio = MP4_INVALID_TRACK_ID;
/////record 业务逻辑//////
m_info.ui64TimeLen = ::time(NULL) - m_info.ui64StartedTime;
//获取文件大小
struct stat fileData;
stat(m_strFile.data(), &fileData);
m_info.ui64FileSize = fileData.st_size;
//----record 业务逻辑----//
NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastRecordMP4,(const Mp4Info &)m_info);
}
}
} /* namespace MediaFile */
} /* namespace ZL */
#endif //ENABLE_MEDIAFILE
/*
* Mp4Maker.h
*
* Created on: 2013-9-18
* Author: root
*/
#ifndef MP4MAKER_H_
#define MP4MAKER_H_
#ifdef ENABLE_MEDIAFILE
#include <mutex>
#include "Player/PlayerBase.h"
#include <memory>
#include "Util/logger.h"
#include "Util/util.h"
#include "Util/TimeTicker.h"
#include <mp4v2/mp4v2.h>
#include "Util/TimeTicker.h"
using namespace std;
using namespace ZL::Player;
using namespace ZL::Util;
namespace ZL {
namespace MediaFile {
class Mp4Info
{
public:
time_t ui64StartedTime; //GMT标准时间,单位秒
time_t ui64TimeLen;//录像长度,单位秒
__off_t ui64FileSize;//文件大小,单位BYTE
string strFilePath;//文件路径
string strFileName;//文件名称
string strFolder;//文件夹路径
string strUrl;//播放路径
string strAppName;//应用名称
string strStreamId;//流ID
};
class Mp4Maker {
public:
typedef std::shared_ptr<Mp4Maker> Ptr;
Mp4Maker(const string &strPath,const string &strApp,const string &strStreamId, const PlayerBase::Ptr &pPlayer);
virtual ~Mp4Maker();
//时间戳:参考频率1000
void inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType);
//时间戳:参考频率1000
void inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp);
private:
MP4FileHandle m_hMp4 = MP4_INVALID_FILE_HANDLE;
MP4TrackId m_hVideo = MP4_INVALID_TRACK_ID;
MP4TrackId m_hAudio = MP4_INVALID_TRACK_ID;
PlayerBase::Ptr m_pPlayer;
string m_strPath;
string m_strFile;
string m_strFileTmp;
Ticker m_ticker;
SmoothTicker m_mediaTicker[2];
void createFile();
void closeFile();
void _inputH264(void *pData, uint32_t ui32Length, uint32_t ui64Duration, int iType);
void _inputAAC(void *pData, uint32_t ui32Length, uint32_t ui64Duration);
string m_strLastVideo;
string m_strLastAudio;
uint32_t m_ui32LastVideoTime = 0;
uint32_t m_ui32LastAudioTime = 0;
int m_iLastVideoType = 0;
Mp4Info m_info;
};
} /* namespace MediaFile */
} /* namespace ZL */
#endif ///ENABLE_MEDIAFILE
#endif /* MP4MAKER_H_ */
/*
* MediaSender.h
*
* Created on: 2016年9月1日
* Author: xzl
*/
#ifndef SRC_MEDIASENDER_H_
#define SRC_MEDIASENDER_H_
#include "Thread/ThreadPool.hpp"
using namespace ZL::Thread;
class MediaSender {
public:
static ThreadPool & sendThread() {
static ThreadPool pool(1, ThreadPool::PRIORITY_HIGHEST);
return pool;
}
private:
MediaSender();
virtual ~MediaSender();
};
#endif /* SRC_MEDIASENDER_H_ */
/*
* MediaPlayer.cpp
*
* Created on: 2016年12月5日
* Author: xzl
*/
#include "Rtmp/RtmpPlayerImp.h"
#include "Rtsp/RtspPlayerImp.h"
#include "MediaPlayer.h"
#include <algorithm>
using namespace ZL::Rtmp;
using namespace ZL::Rtsp;
namespace ZL {
namespace Player {
MediaPlayer::MediaPlayer() {
}
MediaPlayer::~MediaPlayer() {
if(!EventPoller::Instance().isMainThread()){
FatalL << "未在主线程释放";
}
teardown();
}
void MediaPlayer::play(const char* strUrl, const char* strUser, const char* strPwd, eRtpType eType) {
string strPrefix = FindField(strUrl, NULL, "://");
if ((strcasecmp(m_strPrefix.data(),strPrefix.data()) != 0) || strPrefix.empty()) {
//协议切换
m_strPrefix = strPrefix;
m_parser = PlayerBase::createPlayer(strUrl);
m_parser->setOnShutdown(m_shutdownCB);
m_parser->setOnVideoCB(m_onGetVideoCB);
m_parser->setOnAudioCB(m_onGetAudioCB);
}
m_parser->setOnPlayResult(m_playResultCB);
m_parser->play(strUrl, strUser, strPwd, eType);
}
void MediaPlayer::pause(bool bPause) {
if (m_parser) {
m_parser->pause(bPause);
}
}
void MediaPlayer::teardown() {
if (m_parser) {
m_parser->teardown();
}
}
} /* namespace Player */
} /* namespace ZL */
/*
* MediaPlayer.h
*
* Created on: 2016年12月5日
* Author: xzl
*/
#ifndef SRC_PLAYER_MEDIAPLAYER_H_
#define SRC_PLAYER_MEDIAPLAYER_H_
#include "Player.h"
#include "PlayerBase.h"
#include <string>
#include <memory>
using namespace std;
namespace ZL {
namespace Player {
class MediaPlayer : public PlayerImp<PlayerBase,PlayerBase> {
public:
typedef std::shared_ptr<MediaPlayer> Ptr;
MediaPlayer();
virtual ~MediaPlayer();
void play(const char* strUrl, const char *strUser = "", const char *strPwd = "", eRtpType eType = RTP_TCP) override;
void pause(bool bPause) override;
void teardown() override;
private:
string m_strPrefix;
};
} /* namespace Player */
} /* namespace ZL */
#endif /* SRC_PLAYER_MEDIAPLAYER_H_ */
/*
* Player.cpp
*
* Created on: 2016年12月2日
* Author: xzl
*/
#include "Player.h"
#include "H264/SPSParser.h"
#include <cstring>
#include "Util/logger.h"
using namespace ZL::Util;
static unsigned const samplingFrequencyTable[16] = { 96000, 88200,
64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025,
8000, 7350, 0, 0, 0 };
void writeAdtsHeader(const AdtsFrame &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,AdtsFrame &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 AdtsFrame &adts,int &iSampleRate,int &iChannel){
iSampleRate = samplingFrequencyTable[adts.sf_index];
iChannel = adts.channel_configuration;
}
bool getAVCInfo(const string& strSps,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 *)strSps.data() + 1;
tGetBitBuf.iBufSize = strSps.size() - 1;
if(0 != h264DecSeqParameterSet((void *) &tGetBitBuf, &tH264SpsInfo)){
return false;
}
h264GetWidthHeight(&tH264SpsInfo, &iVideoWidth, &iVideoHeight);
h264GeFramerate(&tH264SpsInfo, &iVideoFps);
//FatalL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
return true;
}
/*
* Player.h
*
* Created on: 2016年12月2日
* Author: xzl
*/
#ifndef SRC_PLAYER_PLAYER_H_
#define SRC_PLAYER_PLAYER_H_
#include <string>
using namespace std;
typedef struct {
uint16_t sequence;
uint32_t timeStamp;
unsigned char type;
string data;
} H264Frame;
//ADTS 头中相对有用的信息 采样率、声道数、帧长度
typedef struct {
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 data[2 * 1024 + 7];
uint16_t sequence;
uint32_t timeStamp;
} AdtsFrame;
void makeAdtsHeader(const string &strAudioCfg,AdtsFrame &adts);
void writeAdtsHeader(const AdtsFrame &adts, uint8_t *pcAdts) ;
string makeAdtsConfig(const uint8_t *pcAdts);
void getAACInfo(const AdtsFrame &adts,int &iSampleRate,int &iChannel);
bool getAVCInfo(const string &strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps);
#endif /* SRC_PLAYER_PLAYER_H_ */
/*
* PlayerBase.cpp
*
* Created on: 2016年12月1日
* Author: xzl
*/
#include "PlayerBase.h"
#include "Rtmp/RtmpPlayerImp.h"
#include "Rtsp/RtspPlayerImp.h"
#include "Rtsp/Rtsp.h"
#include <algorithm>
using namespace std;
using namespace ZL::Rtmp;
using namespace ZL::Rtsp;
namespace ZL {
namespace Player {
PlayerBase::Ptr PlayerBase::createPlayer(const char* strUrl) {
string prefix = FindField(strUrl, NULL, "://");
if (strcasecmp("rtsp",prefix.data()) == 0) {
return PlayerBase::Ptr(new RtspPlayerImp());
}
if (strcasecmp("rtmp",prefix.data()) == 0) {
return PlayerBase::Ptr(new RtmpPlayerImp());
}
return PlayerBase::Ptr(new RtspPlayerImp());
}
} /* namespace Player */
} /* namespace ZL */
/*
* PlayerBase.h
*
* Created on: 2016年12月1日
* Author: xzl
*/
#ifndef SRC_PLAYER_PLAYERBASE_H_
#define SRC_PLAYER_PLAYERBASE_H_
#include "Player.h"
#include "Network/Socket.hpp"
#include <functional>
#include <memory>
#include <string>
using namespace std;
using namespace ZL::Network;
namespace ZL {
namespace Player {
class PlayerBase{
public:
typedef std::shared_ptr<PlayerBase> Ptr;
typedef enum {
RTP_TCP = 0,
RTP_UDP = 1,
RTP_MULTICAST = 2,
} eRtpType;
static Ptr createPlayer(const char* strUrl);
PlayerBase(){};
virtual ~PlayerBase(){};
virtual void play(const char* strUrl, const char *strUser = "", const char *strPwd = "", eRtpType eType = RTP_TCP) {};
virtual void pause(bool bPause) {};
virtual void teardown() {};
virtual void setOnShutdown( const function<void(const SockException &)> &cb) {};
virtual void setOnPlayResult( const function<void(const SockException &ex)> &cb) {};
virtual void setOnVideoCB( const function<void(const H264Frame &frame)> &cb) {};
virtual void setOnAudioCB( const function<void(const AdtsFrame &frame)> &cb) {};
virtual int getVideoHeight() const { return 0; };
virtual int getVideoWidth() const { return 0; };
virtual float getVideoFps() const { return 0; };
virtual int getAudioSampleRate() const { return 0; };
virtual int getAudioSampleBit() const { return 0; };
virtual int getAudioChannel() const { return 0; };
virtual float getRtpLossRate(int iTrackId) const {return 0; };
virtual const string& getPps() const { static string null;return null; };
virtual const string& getSps() const { static string null;return null; };
virtual const string& getAudioCfg() const { static string null;return null; };
virtual bool containAudio() const { return false; };
virtual bool containVideo() const { return false; };
virtual bool isInited() const { return true; };
virtual float getDuration() const { return 0;};
virtual float getProgresss() const { return 0;};
virtual void seekTo(float fProgress) {};
protected:
virtual void onShutdown(const SockException &ex) {};
virtual void onPlayResult(const SockException &ex) {};
};
template<typename Parent,typename Parser>
class PlayerImp : public Parent
{
public:
typedef std::shared_ptr<PlayerImp> Ptr;
PlayerImp(){};
virtual ~PlayerImp(){};
void setOnShutdown(const function<void(const SockException &)> &cb) override {
if (m_parser) {
m_parser->setOnShutdown(cb);
}
m_shutdownCB = cb;
}
void setOnPlayResult(const function<void(const SockException &ex)> &cb) override {
if (m_parser) {
m_parser->setOnPlayResult(cb);
}
m_playResultCB = cb;
}
void setOnVideoCB(const function<void(const H264Frame &frame)> &cb) override{
if (m_parser) {
m_parser->setOnVideoCB(cb);
}
m_onGetVideoCB = cb;
}
void setOnAudioCB(const function<void(const AdtsFrame &frame)> &cb) override{
if (m_parser) {
m_parser->setOnAudioCB(cb);
}
m_onGetAudioCB = cb;
}
int getVideoHeight() const override{
if (m_parser) {
return m_parser->getVideoHeight();
}
return PlayerBase::getVideoHeight();
}
int getVideoWidth() const override{
if (m_parser) {
return m_parser->getVideoWidth();
}
return PlayerBase::getVideoWidth();
}
float getVideoFps() const override{
if (m_parser) {
return m_parser->getVideoFps();
}
return PlayerBase::getVideoFps();
}
int getAudioSampleRate() const override{
if (m_parser) {
return m_parser->getAudioSampleRate();
}
return PlayerBase::getAudioSampleRate();
}
int getAudioSampleBit() const override{
if (m_parser) {
return m_parser->getAudioSampleBit();
}
return PlayerBase::getAudioSampleBit();
}
int getAudioChannel() const override{
if (m_parser) {
return m_parser->getAudioChannel();
}
return PlayerBase::getAudioChannel();
}
const string& getPps() const override{
if (m_parser) {
return m_parser->getPps();
}
return PlayerBase::getPps();
}
const string& getSps() const override{
if (m_parser) {
return m_parser->getSps();
}
return PlayerBase::getSps();
}
const string& getAudioCfg() const override{
if (m_parser) {
return m_parser->getAudioCfg();
}
return PlayerBase::getAudioCfg();
}
bool containAudio() const override{
if (m_parser) {
return m_parser->containAudio();
}
return PlayerBase::containAudio();
}
bool containVideo() const override{
if (m_parser) {
return m_parser->containVideo();
}
return PlayerBase::containVideo();
}
bool isInited() const override{
if (m_parser) {
return m_parser->isInited();
}
return PlayerBase::isInited();
}
float getDuration() const override {
if (m_parser) {
return m_parser->getDuration();
}
return PlayerBase::getDuration();
}
float getProgresss() const override{
if (m_parser) {
return m_parser->getProgresss();
}
return PlayerBase::getProgresss();
};
void seekTo(float fProgress) override{
if (m_parser) {
return m_parser->seekTo(fProgress);
}
return PlayerBase::seekTo(fProgress);
};
protected:
void onShutdown(const SockException &ex) override {
if (m_shutdownCB) {
m_shutdownCB(ex);
}
}
void onPlayResult(const SockException &ex) override {
if (m_playResultCB) {
m_playResultCB(ex);
m_playResultCB = nullptr;
}
}
function<void(const SockException &ex)> m_shutdownCB;
function<void(const SockException &ex)> m_playResultCB;
std::shared_ptr<Parser> m_parser;
function<void(const H264Frame &frame)> m_onGetVideoCB;
function<void(const AdtsFrame &frame)> m_onGetAudioCB;
};
} /* namespace Player */
} /* namespace ZL */
#endif /* SRC_PLAYER_PLAYERBASE_H_ */
/*
* RtpMaker.h
*
* Created on: 2016年8月12日
* Author: xzl
*/
#ifndef RTP_RTPMAKER_H_
#define RTP_RTPMAKER_H_
#include "Rtsp/RtspMediaSource.h"
#include "Util/ResourcePool.h"
#include "Util/logger.h"
#include "Util/RingBuffer.hpp"
#include "Util/TimeTicker.h"
#include "Thread/ThreadPool.hpp"
using namespace ZL::Util;
using namespace ZL::Thread;
namespace ZL {
namespace Rtsp {
class RtpMaker {
public:
typedef function<void(const RtpPacket::Ptr &pPkt, bool bKeyPos)> onGetRTP;
RtpMaker(const onGetRTP &cb, uint32_t ui32Ssrc, int iMtuSize,int iSampleRate,
uint8_t ui8PlayloadType, uint8_t ui8Interleaved) {
callBack = cb;
m_ui32Ssrc = ui32Ssrc;
m_ui32SampleRate = iSampleRate;
m_iMtuSize = iMtuSize;
m_ui8PlayloadType = ui8PlayloadType;
m_ui8Interleaved = ui8Interleaved;
}
virtual ~RtpMaker() {
}
virtual void makeRtp(const char *pcData, int iDataLen, uint32_t uiStamp)=0;
int getInterleaved() const {
return m_ui8Interleaved;
}
int getPlayloadType() const {
return m_ui8PlayloadType;
}
int getSampleRate() const {
return m_ui32SampleRate;
}
uint32_t getSsrc() const {
return m_ui32Ssrc;
}
uint16_t getSeqence() const {
return m_ui16Sequence;
}
uint32_t getTimestamp() const {
return m_ui32TimeStamp;
}
protected:
uint32_t m_ui32Ssrc;
uint32_t m_ui32SampleRate;
int m_iMtuSize;
uint8_t m_ui8PlayloadType;
uint8_t m_ui8Interleaved;
uint16_t m_ui16Sequence = 0;
uint32_t m_ui32TimeStamp = 0;
virtual void onMakeRtp(const RtpPacket::Ptr &pkt, bool bKeyPos = true) {
callBack(pkt, bKeyPos);
}
inline RtpPacket::Ptr obtainPkt() {
return m_pktPool.obtain();
}
private:
RtspMediaSource::PoolType m_pktPool;
onGetRTP callBack;
};
} /* namespace RTP */
} /* namespace ZL */
#endif /* RTP_RTPMAKER_H_ */
/*
* RtpMakerAAC.cpp
*
* Created on: 2016年8月12日
* Author: xzl
*/
#include <netinet/in.h>
#include "RtpMakerAAC.h"
#include "config.h"
#include "Util/mini.hpp"
using namespace ZL::Util;
namespace ZL {
namespace Rtsp {
void RtpMaker_AAC::makeRtp(const char *pcData, int iLen, uint32_t uiStamp) {
static uint32_t cycleMS = mINI::Instance()[Config::Rtp::kCycleMS].as<uint32_t>();
uiStamp %= cycleMS;
char *ptr = (char *) pcData;
int iSize = iLen;
while (iSize > 0 ) {
if (iSize <= m_iMtuSize - 20) {
m_aucSectionBuf[0] = 0;
m_aucSectionBuf[1] = 16;
m_aucSectionBuf[2] = iLen >> 5;
m_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(m_aucSectionBuf + 4, ptr, iSize);
makeAACRtp(m_aucSectionBuf, iSize + 4, true, uiStamp);
break;
}
m_aucSectionBuf[0] = 0;
m_aucSectionBuf[1] = 16;
m_aucSectionBuf[2] = (iLen) >> 5;
m_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(m_aucSectionBuf + 4, ptr, m_iMtuSize - 20);
makeAACRtp(m_aucSectionBuf, m_iMtuSize - 16, false, uiStamp);
ptr += (m_iMtuSize - 20);
iSize -= (m_iMtuSize - 20);
}
}
inline void RtpMaker_AAC::makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp) {
uint16_t u16RtpLen = uiLen + 12;
m_ui32TimeStamp = (m_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(m_ui32TimeStamp);
uint16_t sq = htons(m_ui16Sequence);
uint32_t sc = htonl(m_ui32Ssrc);
auto pRtppkt = obtainPkt();
auto &rtppkt = *(pRtppkt.get());
unsigned char *pucRtp = rtppkt.payload;
pucRtp[0] = '$';
pucRtp[1] = m_ui8Interleaved;
pucRtp[2] = u16RtpLen >> 8;
pucRtp[3] = u16RtpLen & 0x00FF;
pucRtp[4] = 0x80;
pucRtp[5] = (bMark << 7) | m_ui8PlayloadType;
memcpy(&pucRtp[6], &sq, 2);
memcpy(&pucRtp[8], &ts, 4);
//ssrc
memcpy(&pucRtp[12], &sc, 4);
memcpy(&pucRtp[16], pData, uiLen);
rtppkt.PT = m_ui8PlayloadType;
rtppkt.interleaved = m_ui8Interleaved;
rtppkt.mark = bMark;
rtppkt.length = uiLen + 16;
rtppkt.sequence = m_ui16Sequence;
rtppkt.timeStamp = m_ui32TimeStamp;
rtppkt.ssrc = m_ui32Ssrc;
rtppkt.type = TrackAudio;
memcpy(rtppkt.payload + 16, pData, uiLen);
onMakeRtp(pRtppkt, false);
m_ui16Sequence++;
}
} /* namespace RTP */
} /* namespace ZL */
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论